Merge commit 'd4602118fb
' into kb_migration
This commit is contained in:
commit
4e6b51a016
14 changed files with 102 additions and 2 deletions
|
@ -147,6 +147,7 @@ class Api::V1::StatusesController < Api::BaseController
|
||||||
:language,
|
:language,
|
||||||
:markdown,
|
:markdown,
|
||||||
:scheduled_at,
|
:scheduled_at,
|
||||||
|
:status_reference_ids,
|
||||||
allowed_mentions: [],
|
allowed_mentions: [],
|
||||||
media_ids: [],
|
media_ids: [],
|
||||||
media_attributes: [
|
media_attributes: [
|
||||||
|
|
|
@ -394,9 +394,15 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.hide)} icon='eye' onClick={this.handleHideClick} />
|
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.hide)} icon='eye' onClick={this.handleHideClick} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const following = !account.getIn(['other_settings', 'emoji_reaction_must_follower']) || (relationship && relationship.get('following'));
|
||||||
|
const followed = !account.getIn(['other_settings', 'emoji_reaction_must_following']) || (relationship && relationship.get('followed_by'));
|
||||||
|
const denyFromAll = !account.getIn(['other_settings', 'emoji_reaction_deny_from_all']);
|
||||||
const emojiPickerButton = (
|
const emojiPickerButton = (
|
||||||
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.emojiReaction)} icon='smile-o' onClick={this.handleEmojiPickInnerButton} />
|
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.emojiReaction)} icon='smile-o' onClick={this.handleEmojiPickInnerButton} />
|
||||||
);
|
);
|
||||||
|
const emojiPickerDropdown = (writtenByMe || ((denyFromAll) && (following) && (followed))) && (
|
||||||
|
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} button={emojiPickerButton} />
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='status__action-bar'>
|
<div className='status__action-bar'>
|
||||||
|
@ -404,7 +410,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} />
|
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} />
|
||||||
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
|
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
|
||||||
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} />
|
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} />
|
||||||
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} button={emojiPickerButton} />
|
{emojiPickerDropdown}
|
||||||
|
|
||||||
{filterButton}
|
{filterButton}
|
||||||
|
|
||||||
|
|
|
@ -335,6 +335,27 @@ class Account < ApplicationRecord
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def emoji_reactions_must_following?
|
||||||
|
return user&.settings&.[]('emoji_reactions.must_be_following') || false if user.present?
|
||||||
|
return settings['emoji_reactions_must_be_following'] || false if settings.present?
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def emoji_reactions_must_follower?
|
||||||
|
return user&.settings&.[]('emoji_reactions.must_be_follower') || false if user.present?
|
||||||
|
return settings['emoji_reaction_must_be_follower'] || false if settings.present?
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def emoji_reactions_deny_from_all?
|
||||||
|
return user&.settings&.[]('emoji_reactions.deny_from_all') || false if user.present?
|
||||||
|
return settings['emoji_reaction_deny_from_all'] || false if settings.present?
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
def public_settings
|
def public_settings
|
||||||
config = {
|
config = {
|
||||||
'noindex' => noindex?,
|
'noindex' => noindex?,
|
||||||
|
@ -343,6 +364,9 @@ class Account < ApplicationRecord
|
||||||
'hide_statuses_count' => hide_statuses_count?,
|
'hide_statuses_count' => hide_statuses_count?,
|
||||||
'hide_following_count' => hide_following_count?,
|
'hide_following_count' => hide_following_count?,
|
||||||
'hide_followers_count' => hide_followers_count?,
|
'hide_followers_count' => hide_followers_count?,
|
||||||
|
'emoji_reaction_must_following' => emoji_reactions_must_following?,
|
||||||
|
'emoji_reaction_must_follower' => emoji_reactions_must_follower?,
|
||||||
|
'emoji_reaction_deny_from_all' => emoji_reactions_deny_from_all?,
|
||||||
}
|
}
|
||||||
config = config.merge(settings) if settings.present?
|
config = config.merge(settings) if settings.present?
|
||||||
config
|
config
|
||||||
|
|
|
@ -69,6 +69,12 @@ class UserSettings
|
||||||
setting :must_be_following_dm, default: false
|
setting :must_be_following_dm, default: false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
namespace :emoji_reactions do
|
||||||
|
setting :must_be_follower, default: false
|
||||||
|
setting :must_be_following, default: false
|
||||||
|
setting :deny_from_all, default: false
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(original_hash)
|
def initialize(original_hash)
|
||||||
@original_hash = original_hash || {}
|
@original_hash = original_hash || {}
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,9 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
|
||||||
:in_reply_to, :published, :url,
|
:in_reply_to, :published, :url,
|
||||||
:attributed_to, :to, :cc, :sensitive,
|
:attributed_to, :to, :cc, :sensitive,
|
||||||
:atom_uri, :in_reply_to_atom_uri,
|
:atom_uri, :in_reply_to_atom_uri,
|
||||||
:conversation, :searchable_by, :references
|
:conversation, :searchable_by
|
||||||
|
|
||||||
|
attribute :references, if: :not_private_post?
|
||||||
|
|
||||||
attribute :content
|
attribute :content
|
||||||
attribute :content_map, if: :language?
|
attribute :content_map, if: :language?
|
||||||
|
@ -150,6 +152,10 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
|
||||||
object.account.local?
|
object.account.local?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def not_private_post?
|
||||||
|
!object.private_visibility?
|
||||||
|
end
|
||||||
|
|
||||||
def poll_options
|
def poll_options
|
||||||
object.preloadable_poll.loaded_options
|
object.preloadable_poll.loaded_options
|
||||||
end
|
end
|
||||||
|
|
|
@ -51,6 +51,18 @@ class NotifyService < BaseService
|
||||||
@recipient.user.settings['interactions.must_be_following'] && !following_sender?
|
@recipient.user.settings['interactions.must_be_following'] && !following_sender?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def optional_non_follower_emoji_reaction?
|
||||||
|
emoji_reaction? && @recipient.user.settings['emoji_reactions.must_be_follower'] && !@notification.from_account.following?(@recipient)
|
||||||
|
end
|
||||||
|
|
||||||
|
def optional_non_following_emoji_reaction?
|
||||||
|
emoji_reaction? && @recipient.user.settings['emoji_reactions.must_be_following'] && !following_sender?
|
||||||
|
end
|
||||||
|
|
||||||
|
def emoji_reaction?
|
||||||
|
@notification.type == :emoji_reaction
|
||||||
|
end
|
||||||
|
|
||||||
def message?
|
def message?
|
||||||
@notification.type == :mention
|
@notification.type == :mention
|
||||||
end
|
end
|
||||||
|
@ -120,6 +132,8 @@ class NotifyService < BaseService
|
||||||
blocked ||= optional_non_follower?
|
blocked ||= optional_non_follower?
|
||||||
blocked ||= optional_non_following?
|
blocked ||= optional_non_following?
|
||||||
blocked ||= optional_non_following_and_direct?
|
blocked ||= optional_non_following_and_direct?
|
||||||
|
blocked ||= optional_non_follower_emoji_reaction?
|
||||||
|
blocked ||= optional_non_following_emoji_reaction?
|
||||||
blocked ||= conversation_muted?
|
blocked ||= conversation_muted?
|
||||||
blocked ||= blocked_mention? if @notification.type == :mention
|
blocked ||= blocked_mention? if @notification.type == :mention
|
||||||
blocked
|
blocked
|
||||||
|
|
|
@ -11,6 +11,7 @@ class SearchService < BaseService
|
||||||
@offset = options[:type].blank? ? 0 : options[:offset].to_i
|
@offset = options[:type].blank? ? 0 : options[:offset].to_i
|
||||||
@resolve = options[:resolve] || false
|
@resolve = options[:resolve] || false
|
||||||
@following = options[:following] || false
|
@following = options[:following] || false
|
||||||
|
@searchability = options[:searchability] || 'public'
|
||||||
|
|
||||||
default_results.tap do |results|
|
default_results.tap do |results|
|
||||||
next if @query.blank? || @limit.zero?
|
next if @query.blank? || @limit.zero?
|
||||||
|
|
|
@ -17,6 +17,7 @@ class UpdateStatusService < BaseService
|
||||||
# @option options [Boolean] :sensitive
|
# @option options [Boolean] :sensitive
|
||||||
# @option options [Boolean] :markdown
|
# @option options [Boolean] :markdown
|
||||||
# @option options [String] :language
|
# @option options [String] :language
|
||||||
|
# @option [Enumerable] :status_reference_ids Optional array
|
||||||
def call(status, account_id, options = {})
|
def call(status, account_id, options = {})
|
||||||
@status = status
|
@status = status
|
||||||
@options = options
|
@options = options
|
||||||
|
@ -36,6 +37,7 @@ class UpdateStatusService < BaseService
|
||||||
|
|
||||||
queue_poll_notifications!
|
queue_poll_notifications!
|
||||||
reset_preview_card!
|
reset_preview_card!
|
||||||
|
update_references!
|
||||||
update_metadata!
|
update_metadata!
|
||||||
broadcast_updates!
|
broadcast_updates!
|
||||||
|
|
||||||
|
@ -139,6 +141,11 @@ class UpdateStatusService < BaseService
|
||||||
LinkCrawlWorker.perform_async(@status.id)
|
LinkCrawlWorker.perform_async(@status.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_references!
|
||||||
|
reference_ids = (@options[:status_reference_ids] || []).map(&:to_i).filter(&:positive?)
|
||||||
|
ProcessReferencesWorker.perform_async(@status.id, reference_ids, [])
|
||||||
|
end
|
||||||
|
|
||||||
def update_metadata!
|
def update_metadata!
|
||||||
ProcessHashtagsService.new.call(@status)
|
ProcessHashtagsService.new.call(@status)
|
||||||
ProcessMentionsService.new.call(@status)
|
ProcessMentionsService.new.call(@status)
|
||||||
|
|
|
@ -8,6 +8,7 @@ class EmojiReactionValidator < ActiveModel::Validator
|
||||||
|
|
||||||
emoji_reaction.errors.add(:name, I18n.t('reactions.errors.unrecognized_emoji')) if emoji_reaction.custom_emoji_id.blank? && !unicode_emoji?(emoji_reaction.name)
|
emoji_reaction.errors.add(:name, I18n.t('reactions.errors.unrecognized_emoji')) if emoji_reaction.custom_emoji_id.blank? && !unicode_emoji?(emoji_reaction.name)
|
||||||
emoji_reaction.errors.add(:name, I18n.t('reactions.errors.unrecognized_emoji')) if emoji_reaction.custom_emoji_id.present? && disabled_custom_emoji?(emoji_reaction.custom_emoji)
|
emoji_reaction.errors.add(:name, I18n.t('reactions.errors.unrecognized_emoji')) if emoji_reaction.custom_emoji_id.present? && disabled_custom_emoji?(emoji_reaction.custom_emoji)
|
||||||
|
emoji_reaction.errors.add(:name, I18n.t('reactions.errors.banned')) if deny_from_all?(emoji_reaction) || non_follower?(emoji_reaction) || non_following?(emoji_reaction)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -19,4 +20,25 @@ class EmojiReactionValidator < ActiveModel::Validator
|
||||||
def disabled_custom_emoji?(custom_emoji)
|
def disabled_custom_emoji?(custom_emoji)
|
||||||
custom_emoji.nil? ? false : custom_emoji.disabled
|
custom_emoji.nil? ? false : custom_emoji.disabled
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def deny_from_all?(emoji_reaction)
|
||||||
|
return false if emoji_reaction.status.account.user.nil?
|
||||||
|
return false if emoji_reaction.status.account_id == emoji_reaction.account_id
|
||||||
|
|
||||||
|
emoji_reaction.status.account.user.settings['emoji_reactions.deny_from_all']
|
||||||
|
end
|
||||||
|
|
||||||
|
def non_following?(emoji_reaction)
|
||||||
|
return false if emoji_reaction.status.account.user.nil?
|
||||||
|
return false if emoji_reaction.status.account_id == emoji_reaction.account_id
|
||||||
|
|
||||||
|
emoji_reaction.status.account.user.settings['emoji_reactions.must_be_following'] && !emoji_reaction.status.account.following?(emoji_reaction.account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def non_follower?(emoji_reaction)
|
||||||
|
return false if emoji_reaction.status.account.user.nil?
|
||||||
|
return false if emoji_reaction.status.account_id == emoji_reaction.account_id
|
||||||
|
|
||||||
|
emoji_reaction.status.account.user.settings['emoji_reactions.must_be_follower'] && !emoji_reaction.account.following?(emoji_reaction.status.account)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
= ff.input :'interactions.must_be_follower', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_follower')
|
= ff.input :'interactions.must_be_follower', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_follower')
|
||||||
= ff.input :'interactions.must_be_following', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_following')
|
= ff.input :'interactions.must_be_following', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_following')
|
||||||
= ff.input :'interactions.must_be_following_dm', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_following_dm')
|
= ff.input :'interactions.must_be_following_dm', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_following_dm')
|
||||||
|
= ff.input :'emoji_reactions.must_be_follower', kmyblue: true, wrapper: :with_label, label: I18n.t('simple_form.labels.emoji_reactions.must_be_follower')
|
||||||
|
= ff.input :'emoji_reactions.must_be_following', kmyblue: true, wrapper: :with_label, label: I18n.t('simple_form.labels.emoji_reactions.must_be_following')
|
||||||
|
= ff.input :'emoji_reactions.deny_from_all', kmyblue: true, wrapper: :with_label, label: I18n.t('simple_form.labels.emoji_reactions.deny_from_all')
|
||||||
|
|
||||||
= f.simple_fields_for :settings, current_user.settings do |ff|
|
= f.simple_fields_for :settings, current_user.settings do |ff|
|
||||||
.fields-group
|
.fields-group
|
||||||
|
|
|
@ -1590,6 +1590,7 @@ en:
|
||||||
title: Privacy Policy
|
title: Privacy Policy
|
||||||
reactions:
|
reactions:
|
||||||
errors:
|
errors:
|
||||||
|
banned: Banned reaction from the user
|
||||||
duplication: Cannot react same things
|
duplication: Cannot react same things
|
||||||
limit_reached: Limit of different reactions reached
|
limit_reached: Limit of different reactions reached
|
||||||
unrecognized_emoji: is not a recognized emoji
|
unrecognized_emoji: is not a recognized emoji
|
||||||
|
|
|
@ -1577,6 +1577,7 @@ ja:
|
||||||
title: プライバシーポリシー
|
title: プライバシーポリシー
|
||||||
reactions:
|
reactions:
|
||||||
errors:
|
errors:
|
||||||
|
banned: 指定ユーザーからのリアクションは禁止されています
|
||||||
duplication: 同じリアクションを複数行おうとしました
|
duplication: 同じリアクションを複数行おうとしました
|
||||||
limit_reached: リアクションの種類が上限に達しました
|
limit_reached: リアクションの種類が上限に達しました
|
||||||
unrecognized_emoji: は絵文字として認識されていません
|
unrecognized_emoji: は絵文字として認識されていません
|
||||||
|
|
|
@ -257,6 +257,10 @@ en:
|
||||||
whole_word: Whole word
|
whole_word: Whole word
|
||||||
email_domain_block:
|
email_domain_block:
|
||||||
with_dns_records: Include MX records and IPs of the domain
|
with_dns_records: Include MX records and IPs of the domain
|
||||||
|
emoji_reactions:
|
||||||
|
deny_from_all: Block all stamps
|
||||||
|
must_be_follower: Block stamps from non-followers
|
||||||
|
must_be_following: Block stamps from people you don't follow
|
||||||
featured_tag:
|
featured_tag:
|
||||||
name: Hashtag
|
name: Hashtag
|
||||||
filters:
|
filters:
|
||||||
|
|
|
@ -265,6 +265,10 @@ ja:
|
||||||
whole_word: 単語全体にマッチ
|
whole_word: 単語全体にマッチ
|
||||||
email_domain_block:
|
email_domain_block:
|
||||||
with_dns_records: ドメインのMXレコードとIPアドレスを含む
|
with_dns_records: ドメインのMXレコードとIPアドレスを含む
|
||||||
|
emoji_reactions:
|
||||||
|
deny_from_all: 自分以外すべてのスタンプをブロック
|
||||||
|
must_be_follower: フォロワー以外からのスタンプをブロック
|
||||||
|
must_be_following: フォローしていないユーザーからのスタンプをブロック
|
||||||
featured_tag:
|
featured_tag:
|
||||||
name: ハッシュタグ
|
name: ハッシュタグ
|
||||||
filters:
|
filters:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue