parent
77a1cabb97
commit
45cc8fff7a
15 changed files with 107 additions and 8 deletions
|
@ -26,7 +26,7 @@ import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
|||
|
||||
import DropdownMenuContainer from '../containers/dropdown_menu_container';
|
||||
import EmojiPickerDropdown from '../features/compose/containers/emoji_picker_dropdown_container';
|
||||
import { enableEmojiReaction , bookmarkCategoryNeeded, simpleTimelineMenu, me } from '../initial_state';
|
||||
import { enableEmojiReaction , bookmarkCategoryNeeded, simpleTimelineMenu, me, hideEmojiReactionUnavailableServer } from '../initial_state';
|
||||
|
||||
import { IconButton } from './icon_button';
|
||||
|
||||
|
@ -453,6 +453,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.hide)} icon='eye' iconComponent={VisibilityIcon} onClick={this.handleHideClick} />
|
||||
);
|
||||
|
||||
const emojiReactionAvailableServer = !hideEmojiReactionUnavailableServer || status.get('emoji_reaction_available_server');
|
||||
const emojiReactionPolicy = account.getIn(['other_settings', 'emoji_reaction_policy']) || 'allow';
|
||||
const following = emojiReactionPolicy !== 'following_only' || (relationship && relationship.get('following'));
|
||||
const followed = emojiReactionPolicy !== 'followers_only' || (relationship && relationship.get('followed_by'));
|
||||
|
@ -462,7 +463,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
const emojiPickerButton = (
|
||||
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.emojiReaction)} icon='smile-o' iconComponent={EmojiReactionIcon} onClick={this.handleEmojiPickInnerButton} />
|
||||
);
|
||||
const emojiPickerDropdown = enableEmojiReaction && denyFromAll && (writtenByMe || (following && followed && mutual && outside)) && (
|
||||
const emojiPickerDropdown = enableEmojiReaction && emojiReactionAvailableServer && denyFromAll && (writtenByMe || (following && followed && mutual && outside)) && (
|
||||
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} button={emojiPickerButton} />
|
||||
);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
|||
|
||||
import { IconButton } from '../../../components/icon_button';
|
||||
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
|
||||
import { enableEmojiReaction , bookmarkCategoryNeeded, me } from '../../../initial_state';
|
||||
import { enableEmojiReaction , bookmarkCategoryNeeded, me, hideEmojiReactionUnavailableServer } from '../../../initial_state';
|
||||
import EmojiPickerDropdown from '../../compose/containers/emoji_picker_dropdown_container';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -358,6 +358,7 @@ class ActionBar extends PureComponent {
|
|||
reblogTitle = intl.formatMessage(messages.cannot_reblog);
|
||||
}
|
||||
|
||||
const emojiReactionAvailableServer = !hideEmojiReactionUnavailableServer || status.get('emoji_reaction_available_server');
|
||||
const emojiReactionPolicy = account.getIn(['other_settings', 'emoji_reaction_policy']) || 'allow';
|
||||
const following = emojiReactionPolicy !== 'following_only' || (relationship && relationship.get('following'));
|
||||
const followed = emojiReactionPolicy !== 'followers_only' || (relationship && relationship.get('followed_by'));
|
||||
|
@ -367,7 +368,7 @@ class ActionBar extends PureComponent {
|
|||
const emojiPickerButton = (
|
||||
<IconButton icon='smile-o' iconComponent={EmojiReactionIcon} onClick={this.handleEmojiPickInnerButton} title={intl.formatMessage(messages.pickEmoji)} />
|
||||
);
|
||||
const emojiPickerDropdown = enableEmojiReaction && denyFromAll && (writtenByMe || (following && followed && mutual && outside)) && (
|
||||
const emojiPickerDropdown = enableEmojiReaction && emojiReactionAvailableServer && denyFromAll && (writtenByMe || (following && followed && mutual && outside)) && (
|
||||
<div className='detailed-status__button'><EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} button={emojiPickerButton} /></div>
|
||||
);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import { Icon } from 'mastodon/components/icon';
|
|||
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
|
||||
import { SearchabilityIcon } from 'mastodon/components/searchability_icon';
|
||||
import { VisibilityIcon } from 'mastodon/components/visibility_icon';
|
||||
import { enableEmojiReaction } from 'mastodon/initial_state';
|
||||
import { enableEmojiReaction, hideEmojiReactionUnavailableServer } from 'mastodon/initial_state';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
|
||||
import { Avatar } from '../../../components/avatar';
|
||||
|
@ -233,7 +233,8 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
if (status.get('emoji_reactions')) {
|
||||
const emojiReactions = status.get('emoji_reactions');
|
||||
const emojiReactionPolicy = status.getIn(['account', 'other_settings', 'emoji_reaction_policy']) || 'allow';
|
||||
if (emojiReactions.size > 0 && enableEmojiReaction && emojiReactionPolicy !== 'block') {
|
||||
const emojiReactionAvailableServer = !hideEmojiReactionUnavailableServer || status.get('emoji_reaction_available_server');
|
||||
if (emojiReactions.size > 0 && enableEmojiReaction && emojiReactionAvailableServer && emojiReactionPolicy !== 'block') {
|
||||
emojiReactionsBar = <StatusEmojiReactionsBar emojiReactions={emojiReactions} status={status} onEmojiReact={this.props.onEmojiReact} onUnEmojiReact={this.props.onUnEmojiReact} />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
* @property {boolean} enable_dtl_menu
|
||||
* @property {boolean=} expand_spoilers
|
||||
* @property {boolean} hide_blocking_quote
|
||||
* @property {boolean} hide_emoji_reaction_unavailable_server
|
||||
* @property {boolean} hide_recent_emojis
|
||||
* @property {boolean} limited_federation_mode
|
||||
* @property {string} locale
|
||||
|
@ -143,6 +144,7 @@ export const enableDtlMenu = getMeta('enable_dtl_menu');
|
|||
export const expandSpoilers = getMeta('expand_spoilers');
|
||||
export const forceSingleColumn = !getMeta('advanced_layout');
|
||||
export const hideBlockingQuote = getMeta('hide_blocking_quote');
|
||||
export const hideEmojiReactionUnavailableServer = getMeta('hide_emoji_reaction_unavailable_server');
|
||||
export const hideRecentEmojis = getMeta('hide_recent_emojis');
|
||||
export const limitedFederationMode = getMeta('limited_federation_mode');
|
||||
export const mascot = getMeta('mascot');
|
||||
|
|
|
@ -259,6 +259,10 @@ module HasUserSettings
|
|||
settings['lock_follow_from_bot']
|
||||
end
|
||||
|
||||
def setting_hide_emoji_reaction_unavailable_server
|
||||
settings['web.hide_emoji_reaction_unavailable_server']
|
||||
end
|
||||
|
||||
def allows_report_emails?
|
||||
settings['notification_emails.report']
|
||||
end
|
||||
|
|
|
@ -14,4 +14,36 @@
|
|||
#
|
||||
|
||||
class InstanceInfo < ApplicationRecord
|
||||
EMOJI_REACTION_AVAILABLE_SOFTWARES = %w(
|
||||
misskey
|
||||
calckey
|
||||
cherrypick
|
||||
meisskey
|
||||
firefish
|
||||
renedon
|
||||
fedibird
|
||||
kmyblue
|
||||
pleroma
|
||||
akkoma
|
||||
).freeze
|
||||
|
||||
def self.emoji_reaction_available?(domain)
|
||||
return Setting.enable_emoji_reaction if domain.nil?
|
||||
|
||||
Rails.cache.fetch("emoji_reaction_available_domain:#{domain}") { fetch_emoji_reaction_available(domain) }
|
||||
end
|
||||
|
||||
def self.fetch_emoji_reaction_available(domain)
|
||||
return Setting.enable_emoji_reaction if domain.nil?
|
||||
|
||||
info = InstanceInfo.find_by(domain: domain)
|
||||
return false if info.nil?
|
||||
|
||||
return true if EMOJI_REACTION_AVAILABLE_SOFTWARES.include?(info['software'])
|
||||
|
||||
features = info.data.dig('metadata', 'features')
|
||||
return false if features.nil? || !features.is_a?(Array)
|
||||
|
||||
features.include?('emoji_reaction')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -525,6 +525,10 @@ class Status < ApplicationRecord
|
|||
Status.where(id: status_ids).pluck(:account_id).uniq.index_with { |a| Account.find_by(id: a).show_emoji_reaction?(my_account) }
|
||||
end
|
||||
|
||||
def emoji_reaction_availables_map(domains)
|
||||
domains.index_with { |d| InstanceInfo.emoji_reaction_available?(d) }
|
||||
end
|
||||
|
||||
def reload_stale_associations!(cached_items)
|
||||
account_ids = []
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ class UserSettings
|
|||
setting :show_quote_in_home, default: true
|
||||
setting :show_quote_in_public, default: false
|
||||
setting :hide_blocking_quote, default: true
|
||||
setting :hide_emoji_reaction_unavailable_server, default: false
|
||||
end
|
||||
|
||||
namespace :notification_emails do
|
||||
|
|
|
@ -4,7 +4,7 @@ class StatusRelationshipsPresenter
|
|||
PINNABLE_VISIBILITIES = %w(public public_unlisted unlisted login private).freeze
|
||||
|
||||
attr_reader :reblogs_map, :favourites_map, :mutes_map, :pins_map, :blocks_map, :domain_blocks_map,
|
||||
:bookmarks_map, :filters_map, :attributes_map, :emoji_reaction_allows_map
|
||||
:bookmarks_map, :filters_map, :attributes_map, :emoji_reaction_allows_map, :emoji_reaction_availables_map
|
||||
|
||||
def initialize(statuses, current_account_id = nil, **options)
|
||||
@current_account_id = current_account_id
|
||||
|
@ -19,6 +19,7 @@ class StatusRelationshipsPresenter
|
|||
@pins_map = {}
|
||||
@filters_map = {}
|
||||
@emoji_reaction_allows_map = nil
|
||||
@emoji_reaction_availables_map = {}
|
||||
else
|
||||
statuses = statuses.compact
|
||||
statuses += statuses.filter_map(&:quote)
|
||||
|
@ -35,6 +36,7 @@ class StatusRelationshipsPresenter
|
|||
@domain_blocks_map = Status.domain_blocks_map(statuses.filter_map { |status| status.account.domain }.uniq, current_account_id).merge(options[:domain_blocks_map] || {})
|
||||
@pins_map = Status.pins_map(pinnable_status_ids, current_account_id).merge(options[:pins_map] || {})
|
||||
@emoji_reaction_allows_map = Status.emoji_reaction_allows_map(status_ids, current_account_id).merge(options[:emoji_reaction_allows_map] || {})
|
||||
@emoji_reaction_availables_map = Status.emoji_reaction_availables_map(statuses.filter_map { |status| status.account.domain }.uniq).merge(options[:emoji_reaction_availables_map] || {})
|
||||
@attributes_map = options[:attributes_map] || {}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -66,6 +66,7 @@ class InitialStateSerializer < ActiveModel::Serializer
|
|||
store[:show_quote_in_home] = object.current_account.user.setting_show_quote_in_home
|
||||
store[:show_quote_in_public] = object.current_account.user.setting_show_quote_in_public
|
||||
store[:hide_blocking_quote] = object.current_account.user.setting_hide_blocking_quote
|
||||
store[:hide_emoji_reaction_unavailable_server] = object.current_account.user.setting_hide_emoji_reaction_unavailable_server
|
||||
else
|
||||
store[:auto_play_gif] = Setting.auto_play_gif
|
||||
store[:display_media] = Setting.display_media
|
||||
|
|
|
@ -6,7 +6,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
|||
attributes :id, :created_at, :in_reply_to_id, :in_reply_to_account_id,
|
||||
:sensitive, :spoiler_text, :visibility, :visibility_ex, :limited_scope, :language,
|
||||
:uri, :url, :replies_count, :reblogs_count, :searchability, :markdown,
|
||||
:status_reference_ids, :status_references_count, :status_referred_by_count,
|
||||
:status_reference_ids, :status_references_count, :status_referred_by_count, :emoji_reaction_available_server,
|
||||
:favourites_count, :emoji_reactions, :emoji_reactions_count, :reactions, :edited_at
|
||||
|
||||
attribute :favourited, if: :current_user?
|
||||
|
@ -166,6 +166,14 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
|||
end
|
||||
end
|
||||
|
||||
def emoji_reaction_available_server
|
||||
if relationships
|
||||
relationships.emoji_reaction_availables_map[object.account.domain] || false
|
||||
else
|
||||
InstanceInfo.emoji_reaction_available?(object.account.domain)
|
||||
end
|
||||
end
|
||||
|
||||
def reactions
|
||||
emoji_reactions.tap do |rs|
|
||||
rs.each do |emoji_reaction|
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
- if Setting.enable_emoji_reaction
|
||||
= ff.input :'web.enable_emoji_reaction', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_enable_emoji_reaction'), hint: I18n.t('simple_form.hints.defaults.setting_enable_emoji_reaction')
|
||||
= ff.input :'web.show_emoji_reaction_on_timeline', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_show_emoji_reaction_on_timeline')
|
||||
= ff.input :'web.hide_emoji_reaction_unavailable_server', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_hide_emoji_reaction_unavailable_server')
|
||||
|
||||
.fields-group
|
||||
= ff.input :'web.bookmark_category_needed', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_bookmark_category_needed'), hint: I18n.t('simple_form.hints.defaults.setting_bookmark_category_needed')
|
||||
|
|
|
@ -265,6 +265,7 @@ en:
|
|||
outside_only: Followings or followers only
|
||||
setting_expand_spoilers: Always expand posts marked with content warnings
|
||||
setting_hide_blocking_quote: Hide posts which have a quote written by the user you are blocking
|
||||
setting_hide_emoji_reaction_unavailable_server: Hide stamp button from unavailable server
|
||||
setting_hide_followers_count: Hide followers count
|
||||
setting_hide_following_count: Hide following count
|
||||
setting_hide_network: Hide your social graph
|
||||
|
|
|
@ -280,6 +280,7 @@ ja:
|
|||
setting_enable_emoji_reaction: スタンプ機能を使用する
|
||||
setting_expand_spoilers: 閲覧注意としてマークされた投稿を常に展開する
|
||||
setting_hide_blocking_quote: ブロックしたユーザーの投稿を引用した投稿を隠す
|
||||
setting_hide_emoji_reaction_unavailable_server: スタンプに対応していないと思われるサーバーの投稿からスタンプボタンを隠す
|
||||
setting_hide_followers_count: フォロワー数を隠す
|
||||
setting_hide_following_count: フォロー数を隠す
|
||||
setting_hide_network: 繋がりを隠す
|
||||
|
|
|
@ -460,6 +460,45 @@ RSpec.describe Status do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.emoji_reaction_availables_map' do
|
||||
subject { described_class.emoji_reaction_availables_map(domains) }
|
||||
|
||||
let(:domains) { %w(features_available.com features_unavailable.com features_invalid.com features_nil.com no_info.com mastodon.com misskey.com) }
|
||||
|
||||
before do
|
||||
Fabricate(:instance_info, domain: 'features_available.com', software: 'mastodon', data: { metadata: { features: ['emoji_reaction'] } })
|
||||
Fabricate(:instance_info, domain: 'features_unavailable.com', software: 'mastodon', data: { metadata: { features: ['ohagi'] } })
|
||||
Fabricate(:instance_info, domain: 'features_invalid.com', software: 'mastodon', data: { metadata: { features: 'good_for_ohagi' } })
|
||||
Fabricate(:instance_info, domain: 'features_nil.com', software: 'mastodon', data: { metadata: { features: nil } })
|
||||
Fabricate(:instance_info, domain: 'mastodon.com', software: 'mastodon')
|
||||
Fabricate(:instance_info, domain: 'misskey.com', software: 'misskey')
|
||||
end
|
||||
|
||||
it 'availables if features contains emoji_reaction' do
|
||||
expect(subject['features_available.com']).to be true
|
||||
end
|
||||
|
||||
it 'unavailables if features does not contain emoji_reaction' do
|
||||
expect(subject['features_unavailable.com']).to be false
|
||||
end
|
||||
|
||||
it 'unavailables if features is not valid' do
|
||||
expect(subject['features_invalid.com']).to be false
|
||||
end
|
||||
|
||||
it 'unavailables if features is nil' do
|
||||
expect(subject['features_nil.com']).to be false
|
||||
end
|
||||
|
||||
it 'unavailables if mastodon server' do
|
||||
expect(subject['mastodon.com']).to be false
|
||||
end
|
||||
|
||||
it 'availables if misskey server' do
|
||||
expect(subject['misskey.com']).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe '.tagged_with' do
|
||||
let(:tag_cats) { Fabricate(:tag, name: 'cats') }
|
||||
let(:tag_dogs) { Fabricate(:tag, name: 'dogs') }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue