Add mutual-followers-only visibility
This commit is contained in:
parent
807da5d3d6
commit
c3114f9a5e
14 changed files with 35 additions and 5 deletions
|
@ -84,7 +84,16 @@ class Api::V1::StatusesController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_circle
|
def set_circle
|
||||||
@circle = status_params[:circle_id].blank? ? nil : current_account.owned_circles.find(status_params[:circle_id])
|
@circle = begin
|
||||||
|
if status_params[:visibility] == 'mutual'
|
||||||
|
status_params[:visibility] = 'limited'
|
||||||
|
current_account
|
||||||
|
elsif status_params[:circle_id].blank?
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
current_account.owned_circles.find(status_params[:circle_id])
|
||||||
|
end
|
||||||
|
end
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render json: { error: I18n.t('statuses.errors.circle_not_found') }, status: 404
|
render json: { error: I18n.t('statuses.errors.circle_not_found') }, status: 404
|
||||||
end
|
end
|
||||||
|
|
|
@ -178,7 +178,7 @@ module ApplicationHelper
|
||||||
text: [params[:title], params[:text], params[:url]].compact.join(' '),
|
text: [params[:title], params[:text], params[:url]].compact.join(' '),
|
||||||
}
|
}
|
||||||
|
|
||||||
permit_visibilities = %w(public unlisted private direct)
|
permit_visibilities = %w(public unlisted private mutual direct)
|
||||||
default_privacy = current_account&.user&.setting_default_privacy
|
default_privacy = current_account&.user&.setting_default_privacy
|
||||||
permit_visibilities.shift(permit_visibilities.index(default_privacy) + 1) if default_privacy.present?
|
permit_visibilities.shift(permit_visibilities.index(default_privacy) + 1) if default_privacy.present?
|
||||||
state_params[:visibility] = params[:visibility] if permit_visibilities.include? params[:visibility]
|
state_params[:visibility] = params[:visibility] if permit_visibilities.include? params[:visibility]
|
||||||
|
|
|
@ -82,6 +82,7 @@ const messages = defineMessages({
|
||||||
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
|
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
|
||||||
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
|
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
|
||||||
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
|
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
|
||||||
|
mutual_short: { id: 'privacy.mutual.short', defaultMessage: 'Mutual-followers-only' },
|
||||||
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Circle' },
|
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Circle' },
|
||||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
||||||
});
|
});
|
||||||
|
@ -540,6 +541,7 @@ class Status extends ImmutablePureComponent {
|
||||||
'public': { icon: 'globe', text: intl.formatMessage(messages.public_short) },
|
'public': { icon: 'globe', text: intl.formatMessage(messages.public_short) },
|
||||||
'unlisted': { icon: 'unlock', text: intl.formatMessage(messages.unlisted_short) },
|
'unlisted': { icon: 'unlock', text: intl.formatMessage(messages.unlisted_short) },
|
||||||
'private': { icon: 'lock', text: intl.formatMessage(messages.private_short) },
|
'private': { icon: 'lock', text: intl.formatMessage(messages.private_short) },
|
||||||
|
'mutual': { icon: 'exchange', text: intl.formatMessage(messages.mutual_short) },
|
||||||
'limited': { icon: 'user-circle', text: intl.formatMessage(messages.limited_short) },
|
'limited': { icon: 'user-circle', text: intl.formatMessage(messages.limited_short) },
|
||||||
'direct': { icon: 'envelope', text: intl.formatMessage(messages.direct_short) },
|
'direct': { icon: 'envelope', text: intl.formatMessage(messages.direct_short) },
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,8 @@ const messages = defineMessages({
|
||||||
unlisted_long: { id: 'privacy.unlisted.long', defaultMessage: 'Visible for all, but not in public timelines' },
|
unlisted_long: { id: 'privacy.unlisted.long', defaultMessage: 'Visible for all, but not in public timelines' },
|
||||||
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
|
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
|
||||||
private_long: { id: 'privacy.private.long', defaultMessage: 'Visible for followers only' },
|
private_long: { id: 'privacy.private.long', defaultMessage: 'Visible for followers only' },
|
||||||
|
mutual_short: { id: 'privacy.mutual.short', defaultMessage: 'Mutuals-followers-only' },
|
||||||
|
mutual_long: { id: 'privacy.mutual.long', defaultMessage: 'Visible for mutual followers only (Supported servers only)' },
|
||||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
||||||
direct_long: { id: 'privacy.direct.long', defaultMessage: 'Visible for mentioned users only' },
|
direct_long: { id: 'privacy.direct.long', defaultMessage: 'Visible for mentioned users only' },
|
||||||
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Circle' },
|
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Circle' },
|
||||||
|
@ -239,6 +241,7 @@ class PrivacyDropdown extends React.PureComponent {
|
||||||
{ icon: 'globe', value: 'public', text: formatMessage(messages.public_short), meta: formatMessage(messages.public_long) },
|
{ icon: 'globe', value: 'public', text: formatMessage(messages.public_short), meta: formatMessage(messages.public_long) },
|
||||||
{ icon: 'unlock', value: 'unlisted', text: formatMessage(messages.unlisted_short), meta: formatMessage(messages.unlisted_long) },
|
{ icon: 'unlock', value: 'unlisted', text: formatMessage(messages.unlisted_short), meta: formatMessage(messages.unlisted_long) },
|
||||||
{ icon: 'lock', value: 'private', text: formatMessage(messages.private_short), meta: formatMessage(messages.private_long) },
|
{ icon: 'lock', value: 'private', text: formatMessage(messages.private_short), meta: formatMessage(messages.private_long) },
|
||||||
|
{ icon: 'exchange', value: 'mutual', text: formatMessage(messages.mutual_short), meta: formatMessage(messages.mutual_long) },
|
||||||
{ icon: 'user-circle', value: 'limited', text: formatMessage(messages.limited_short), meta: formatMessage(messages.limited_long) },
|
{ icon: 'user-circle', value: 'limited', text: formatMessage(messages.limited_short), meta: formatMessage(messages.limited_long) },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ const messages = defineMessages({
|
||||||
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
|
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
|
||||||
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
|
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
|
||||||
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
|
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
|
||||||
|
mutual_short: { id: 'privacy.mutual.short', defaultMessage: 'Mutual-followers-only' },
|
||||||
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Circle' },
|
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Circle' },
|
||||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
||||||
});
|
});
|
||||||
|
@ -338,6 +339,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
'public': { icon: 'globe', text: intl.formatMessage(messages.public_short) },
|
'public': { icon: 'globe', text: intl.formatMessage(messages.public_short) },
|
||||||
'unlisted': { icon: 'unlock', text: intl.formatMessage(messages.unlisted_short) },
|
'unlisted': { icon: 'unlock', text: intl.formatMessage(messages.unlisted_short) },
|
||||||
'private': { icon: 'lock', text: intl.formatMessage(messages.private_short) },
|
'private': { icon: 'lock', text: intl.formatMessage(messages.private_short) },
|
||||||
|
'mutual': { icon: 'exchange', text: intl.formatMessage(messages.mutual_short) },
|
||||||
'limited': { icon: 'user-circle', text: intl.formatMessage(messages.limited_short) },
|
'limited': { icon: 'user-circle', text: intl.formatMessage(messages.limited_short) },
|
||||||
'direct': { icon: 'envelope', text: intl.formatMessage(messages.direct_short) },
|
'direct': { icon: 'envelope', text: intl.formatMessage(messages.direct_short) },
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@ const messages = defineMessages({
|
||||||
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
|
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
|
||||||
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
|
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
|
||||||
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
|
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
|
||||||
|
mutual_short: { id: 'privacy.mutual.short', defaultMessage: 'Mutual-followers-only' },
|
||||||
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Circle' },
|
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Circle' },
|
||||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' },
|
||||||
});
|
});
|
||||||
|
@ -94,6 +95,7 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
'public': { icon: 'globe', text: intl.formatMessage(messages.public_short) },
|
'public': { icon: 'globe', text: intl.formatMessage(messages.public_short) },
|
||||||
'unlisted': { icon: 'unlock', text: intl.formatMessage(messages.unlisted_short) },
|
'unlisted': { icon: 'unlock', text: intl.formatMessage(messages.unlisted_short) },
|
||||||
'private': { icon: 'lock', text: intl.formatMessage(messages.private_short) },
|
'private': { icon: 'lock', text: intl.formatMessage(messages.private_short) },
|
||||||
|
'mutual': { icon: 'exchange', text: intl.formatMessage(messages.mutual_short) },
|
||||||
'limited': { icon: 'user-circle', text: intl.formatMessage(messages.limited_short) },
|
'limited': { icon: 'user-circle', text: intl.formatMessage(messages.limited_short) },
|
||||||
'direct': { icon: 'envelope', text: intl.formatMessage(messages.direct_short) },
|
'direct': { icon: 'envelope', text: intl.formatMessage(messages.direct_short) },
|
||||||
};
|
};
|
||||||
|
|
|
@ -388,6 +388,8 @@
|
||||||
"privacy.direct.short": "Direct",
|
"privacy.direct.short": "Direct",
|
||||||
"privacy.limited.long": "Visible for circle users only",
|
"privacy.limited.long": "Visible for circle users only",
|
||||||
"privacy.limited.short": "Circle",
|
"privacy.limited.short": "Circle",
|
||||||
|
"privacy.mutual.long": "Visible for mutual followers only (Supported servers only)",
|
||||||
|
"privacy.mutual.short": "Mutual-followers-only",
|
||||||
"privacy.private.long": "Visible for followers only",
|
"privacy.private.long": "Visible for followers only",
|
||||||
"privacy.private.short": "Followers-only",
|
"privacy.private.short": "Followers-only",
|
||||||
"privacy.public.long": "Visible for all, shown in public timelines",
|
"privacy.public.long": "Visible for all, shown in public timelines",
|
||||||
|
|
|
@ -388,6 +388,8 @@
|
||||||
"privacy.direct.short": "ダイレクト",
|
"privacy.direct.short": "ダイレクト",
|
||||||
"privacy.limited.long": "サークルで指定したユーザーのみ閲覧可",
|
"privacy.limited.long": "サークルで指定したユーザーのみ閲覧可",
|
||||||
"privacy.limited.short": "サークル",
|
"privacy.limited.short": "サークル",
|
||||||
|
"privacy.mutual.long": "相互フォローのみ閲覧可(対応サーバのみ)",
|
||||||
|
"privacy.mutual.short": "相互フォロー限定",
|
||||||
"privacy.private.long": "フォロワーのみ閲覧可",
|
"privacy.private.long": "フォロワーのみ閲覧可",
|
||||||
"privacy.private.short": "フォロワー限定",
|
"privacy.private.short": "フォロワー限定",
|
||||||
"privacy.public.long": "誰でも閲覧可、公開TLに表示",
|
"privacy.public.long": "誰でも閲覧可、公開TLに表示",
|
||||||
|
|
|
@ -219,7 +219,7 @@ const insertEmoji = (state, position, emojiData, needsSpace) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const privacyPreference = (a, b) => {
|
const privacyPreference = (a, b) => {
|
||||||
const order = ['public', 'unlisted', 'private', 'limited', 'direct'];
|
const order = ['public', 'unlisted', 'private', 'mutual', 'limited', 'direct'];
|
||||||
return order[Math.max(order.indexOf(a), order.indexOf(b), 0)];
|
return order[Math.max(order.indexOf(a), order.indexOf(b), 0)];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -341,6 +341,10 @@ module AccountInteractions
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mutuals
|
||||||
|
followers.merge(Account.where(id: following))
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def remove_potential_friendship(other_account, mutual = false)
|
def remove_potential_friendship(other_account, mutual = false)
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Status < ApplicationRecord
|
||||||
|
|
||||||
update_index('statuses#status', :proper)
|
update_index('statuses#status', :proper)
|
||||||
|
|
||||||
enum visibility: [:public, :unlisted, :private, :mutual, :direct, :limited], _suffix: :visibility
|
enum visibility: [:public, :unlisted, :private, :direct, :limited, :mutual], _suffix: :visibility
|
||||||
enum expires_action: [:delete, :hint], _prefix: :expires
|
enum expires_action: [:delete, :hint], _prefix: :expires
|
||||||
|
|
||||||
belongs_to :application, class_name: 'Doorkeeper::Application', optional: true
|
belongs_to :application, class_name: 'Doorkeeper::Application', optional: true
|
||||||
|
|
|
@ -44,7 +44,7 @@ class ProcessMentionsService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
if circle.present?
|
if circle.present?
|
||||||
circle.accounts.find_each do |target_account|
|
(circle.class.name == 'Account' ? circle.mutuals : circle.accounts).find_each do |target_account|
|
||||||
status.mentions.create(silent: true, account: target_account)
|
status.mentions.create(silent: true, account: target_account)
|
||||||
end
|
end
|
||||||
elsif status.limited_visibility? && status.thread&.limited_visibility?
|
elsif status.limited_visibility? && status.thread&.limited_visibility?
|
||||||
|
|
|
@ -1388,6 +1388,8 @@ en:
|
||||||
direct_long: Only show to mentioned users
|
direct_long: Only show to mentioned users
|
||||||
limited: Circle
|
limited: Circle
|
||||||
limited_long: Only show to circle users
|
limited_long: Only show to circle users
|
||||||
|
mutual: Mutual
|
||||||
|
mutual_long: Only show to mutual followers
|
||||||
private: Followers-only
|
private: Followers-only
|
||||||
private_long: Only show to followers
|
private_long: Only show to followers
|
||||||
public: Public
|
public: Public
|
||||||
|
|
|
@ -1325,6 +1325,8 @@ ja:
|
||||||
direct_long: 送信した相手のみ閲覧可
|
direct_long: 送信した相手のみ閲覧可
|
||||||
limited: サークル
|
limited: サークル
|
||||||
limited_long: サークルで指定したユーザーのみ閲覧可
|
limited_long: サークルで指定したユーザーのみ閲覧可
|
||||||
|
mutual: 相互フォロー限定
|
||||||
|
mutual_long: 相互フォロー相手にのみ表示されます
|
||||||
private: フォロワー限定
|
private: フォロワー限定
|
||||||
private_long: フォロワーにのみ表示されます
|
private_long: フォロワーにのみ表示されます
|
||||||
public: 公開
|
public: 公開
|
||||||
|
|
Loading…
Reference in a new issue