* Remove: #955 フィルターのアクション`half_warn` * Add: 「フィルター対象投稿の投稿者名やアイコンを表示する」設定 * Fix test
This commit is contained in:
parent
22bf14e9f0
commit
67064de265
19 changed files with 49 additions and 45 deletions
|
@ -55,7 +55,7 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
|
||||||
if (['mention', 'status'].includes(notification.type) && notification.status.filtered) {
|
if (['mention', 'status'].includes(notification.type) && notification.status.filtered) {
|
||||||
const filters = notification.status.filtered.filter(result => result.filter.context.includes('notifications'));
|
const filters = notification.status.filtered.filter(result => result.filter.context.includes('notifications'));
|
||||||
|
|
||||||
if (filters.some(result => result.filter.filter_action_ex === 'hide')) {
|
if (filters.some(result => result.filter.filter_action === 'hide')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -592,24 +592,26 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
<div className={classNames('status', `status-${status.get('visibility_ex')}`, { 'status-reply': !!status.get('in_reply_to_id'), 'status--in-thread': !!rootId, 'status--first-in-thread': previousId && (!connectUp || connectToRoot), muted: this.props.muted })} data-id={status.get('id')}>
|
<div className={classNames('status', `status-${status.get('visibility_ex')}`, { 'status-reply': !!status.get('in_reply_to_id'), 'status--in-thread': !!rootId, 'status--first-in-thread': previousId && (!connectUp || connectToRoot), muted: this.props.muted })} data-id={status.get('id')}>
|
||||||
|
|
||||||
<div onMouseUp={this.handleMouseUp} className='status__info'>
|
{(!matchedFilters || expanded || isShowItem('avatar_on_filter')) && (
|
||||||
<Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} className='status__relative-time'>
|
<div onMouseUp={this.handleMouseUp} className='status__info'>
|
||||||
{withQuote}
|
<Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} className='status__relative-time'>
|
||||||
{withReference}
|
{withQuote}
|
||||||
{withExpiration}
|
{withReference}
|
||||||
{withLimited}
|
{withExpiration}
|
||||||
<span className='status__visibility-icon'><VisibilityIcon visibility={status.get('visibility_ex')} /></span>
|
{withLimited}
|
||||||
<RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
|
<span className='status__visibility-icon'><VisibilityIcon visibility={status.get('visibility_ex')} /></span>
|
||||||
</Link>
|
<RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
|
||||||
|
</Link>
|
||||||
|
|
||||||
<Link to={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} data-hover-card-account={status.getIn(['account', 'id'])} className='status__display-name'>
|
<Link to={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} data-hover-card-account={status.getIn(['account', 'id'])} className='status__display-name'>
|
||||||
<div className='status__avatar'>
|
<div className='status__avatar'>
|
||||||
{statusAvatar}
|
{statusAvatar}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DisplayName account={status.get('account')} />
|
<DisplayName account={status.get('account')} />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{matchedFilters && <FilterWarning title={matchedFilters.join(', ')} expanded={this.state.showDespiteFilter} onClick={this.handleFilterToggle} />}
|
{matchedFilters && <FilterWarning title={matchedFilters.join(', ')} expanded={this.state.showDespiteFilter} onClick={this.handleFilterToggle} />}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
* | 'recent_emojis'
|
* | 'recent_emojis'
|
||||||
* | 'relationships'
|
* | 'relationships'
|
||||||
* | 'status_reference_unavailable_server'
|
* | 'status_reference_unavailable_server'
|
||||||
|
* | 'avatar_on_filter'
|
||||||
* } HideItemsDefinition
|
* } HideItemsDefinition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ const normalizeFilter = (state, filter) => {
|
||||||
title: filter.title,
|
title: filter.title,
|
||||||
context: filter.context,
|
context: filter.context,
|
||||||
filter_action: filter.filter_action,
|
filter_action: filter.filter_action,
|
||||||
filter_action_ex: filter.filter_action_ex,
|
|
||||||
keywords: filter.keywords,
|
keywords: filter.keywords,
|
||||||
expires_at: filter.expires_at ? Date.parse(filter.expires_at) : null,
|
expires_at: filter.expires_at ? Date.parse(filter.expires_at) : null,
|
||||||
with_quote: filter.with_quote,
|
with_quote: filter.with_quote,
|
||||||
|
|
|
@ -36,7 +36,6 @@ export const makeGetStatus = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let filtered = false;
|
let filtered = false;
|
||||||
let filterAction = 'warn';
|
|
||||||
if ((accountReblog || accountBase).get('id') !== me && filters) {
|
if ((accountReblog || accountBase).get('id') !== me && filters) {
|
||||||
let filterResults = statusReblog?.get('filtered') || statusBase.get('filtered') || ImmutableList();
|
let filterResults = statusReblog?.get('filtered') || statusBase.get('filtered') || ImmutableList();
|
||||||
const quoteFilterResults = statusQuote?.get('filtered');
|
const quoteFilterResults = statusQuote?.get('filtered');
|
||||||
|
@ -47,13 +46,12 @@ export const makeGetStatus = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action_ex']) === 'hide')) {
|
if (filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action']) === 'hide')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
filterResults = filterResults.filter(result => filters.has(result.get('filter')));
|
filterResults = filterResults.filter(result => filters.has(result.get('filter')));
|
||||||
if (!filterResults.isEmpty()) {
|
if (!filterResults.isEmpty()) {
|
||||||
filtered = filterResults.map(result => filters.getIn([result.get('filter'), 'title']));
|
filtered = filterResults.map(result => filters.getIn([result.get('filter'), 'title']));
|
||||||
filterAction = filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action_ex']) === 'warn') ? 'warn' : 'half_warn';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +60,6 @@ export const makeGetStatus = () => {
|
||||||
map.set('quote', statusQuote);
|
map.set('quote', statusQuote);
|
||||||
map.set('account', accountBase);
|
map.set('account', accountBase);
|
||||||
map.set('matched_filters', filtered);
|
map.set('matched_filters', filtered);
|
||||||
map.set('filter_action', filterAction);
|
|
||||||
map.set('filter_action_ex', filterAction);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -123,6 +123,10 @@ module User::HasSettings
|
||||||
settings['web.show_relationships']
|
settings['web.show_relationships']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def setting_show_avatar_on_filter
|
||||||
|
settings['web.show_avatar_on_filter']
|
||||||
|
end
|
||||||
|
|
||||||
def setting_allow_quote
|
def setting_allow_quote
|
||||||
settings['allow_quote']
|
settings['allow_quote']
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,7 +38,7 @@ class CustomFilter < ApplicationRecord
|
||||||
include Expireable
|
include Expireable
|
||||||
include Redisable
|
include Redisable
|
||||||
|
|
||||||
enum :action, { warn: 0, hide: 1, half_warn: 2 }, suffix: :action
|
enum :action, { warn: 0, hide: 1 }, suffix: :action
|
||||||
|
|
||||||
belongs_to :account
|
belongs_to :account
|
||||||
has_many :keywords, class_name: 'CustomFilterKeyword', inverse_of: :custom_filter, dependent: :destroy
|
has_many :keywords, class_name: 'CustomFilterKeyword', inverse_of: :custom_filter, dependent: :destroy
|
||||||
|
|
|
@ -83,6 +83,7 @@ class UserSettings
|
||||||
setting :hide_status_reference_unavailable_server, default: false
|
setting :hide_status_reference_unavailable_server, default: false
|
||||||
setting :hide_favourite_menu, default: false
|
setting :hide_favourite_menu, default: false
|
||||||
setting :hide_emoji_reaction_count, default: false
|
setting :hide_emoji_reaction_count, default: false
|
||||||
|
setting :show_avatar_on_filter, default: true
|
||||||
|
|
||||||
setting_inverse_alias :'web.show_blocking_quote', :'web.hide_blocking_quote'
|
setting_inverse_alias :'web.show_blocking_quote', :'web.hide_blocking_quote'
|
||||||
setting_inverse_alias :'web.show_emoji_reaction_count', :'web.hide_emoji_reaction_count'
|
setting_inverse_alias :'web.show_emoji_reaction_count', :'web.hide_emoji_reaction_count'
|
||||||
|
|
|
@ -48,6 +48,7 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||||
object_account_user.setting_show_quote_in_home ? nil : 'quote_in_home',
|
object_account_user.setting_show_quote_in_home ? nil : 'quote_in_home',
|
||||||
object_account_user.setting_show_quote_in_public ? nil : 'quote_in_public',
|
object_account_user.setting_show_quote_in_public ? nil : 'quote_in_public',
|
||||||
object_account_user.setting_show_relationships ? nil : 'relationships',
|
object_account_user.setting_show_relationships ? nil : 'relationships',
|
||||||
|
object_account_user.setting_show_avatar_on_filter ? nil : 'avatar_on_filter',
|
||||||
].compact
|
].compact
|
||||||
store[:enabled_visibilities] = enabled_visibilities
|
store[:enabled_visibilities] = enabled_visibilities
|
||||||
store[:featured_tags] = object.current_account.featured_tags.pluck(:name)
|
store[:featured_tags] = object.current_account.featured_tags.pluck(:name)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class REST::FilterSerializer < ActiveModel::Serializer
|
class REST::FilterSerializer < ActiveModel::Serializer
|
||||||
attributes :id, :title, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :context, :expires_at, :filter_action, :filter_action_ex
|
attributes :id, :title, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :context, :expires_at, :filter_action
|
||||||
has_many :keywords, serializer: REST::FilterKeywordSerializer, if: :rules_requested?
|
has_many :keywords, serializer: REST::FilterKeywordSerializer, if: :rules_requested?
|
||||||
has_many :statuses, serializer: REST::FilterStatusSerializer, if: :rules_requested?
|
has_many :statuses, serializer: REST::FilterStatusSerializer, if: :rules_requested?
|
||||||
|
|
||||||
|
@ -12,14 +12,4 @@ class REST::FilterSerializer < ActiveModel::Serializer
|
||||||
def rules_requested?
|
def rules_requested?
|
||||||
instance_options[:rules_requested]
|
instance_options[:rules_requested]
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_action
|
|
||||||
return :warn if object.half_warn_action?
|
|
||||||
|
|
||||||
object.filter_action
|
|
||||||
end
|
|
||||||
|
|
||||||
def filter_action_ex
|
|
||||||
object.filter_action
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :filter_action,
|
= f.input :filter_action,
|
||||||
as: :radio_buttons,
|
as: :radio_buttons,
|
||||||
collection: %i(half_warn warn hide),
|
collection: %i(warn hide),
|
||||||
hint: t('simple_form.hints.filters.action'),
|
hint: t('simple_form.hints.filters.action'),
|
||||||
include_blank: false,
|
include_blank: false,
|
||||||
label_method: ->(action) { filter_action_label(action) },
|
label_method: ->(action) { filter_action_label(action) },
|
||||||
|
|
|
@ -141,6 +141,7 @@
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= ff.input :'web.expand_content_warnings', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_expand_spoilers')
|
= ff.input :'web.expand_content_warnings', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_expand_spoilers')
|
||||||
|
= ff.input :'web.show_avatar_on_filter', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_show_avatar_on_filter')
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
= f.button :button, t('generic.save_changes'), type: :submit
|
= f.button :button, t('generic.save_changes'), type: :submit
|
||||||
|
|
|
@ -99,7 +99,6 @@ en:
|
||||||
filters:
|
filters:
|
||||||
action: Chose which action to perform when a post matches the filter
|
action: Chose which action to perform when a post matches the filter
|
||||||
actions:
|
actions:
|
||||||
half_warn: Hide the filtered content (exclude account info) behind a warning mentioning the filter's title
|
|
||||||
hide: Completely hide the filtered content, behaving as if it did not exist
|
hide: Completely hide the filtered content, behaving as if it did not exist
|
||||||
warn: Hide the filtered content behind a warning mentioning the filter's title
|
warn: Hide the filtered content behind a warning mentioning the filter's title
|
||||||
form_admin_settings:
|
form_admin_settings:
|
||||||
|
@ -320,6 +319,7 @@ en:
|
||||||
setting_reject_unlisted_subscription: Reject sending unlisted visibility/non-public searchability posts to Misskey, Calckey
|
setting_reject_unlisted_subscription: Reject sending unlisted visibility/non-public searchability posts to Misskey, Calckey
|
||||||
setting_reverse_search_quote: Perform word-by-word search when search keywords are not enclosed in double quotes
|
setting_reverse_search_quote: Perform word-by-word search when search keywords are not enclosed in double quotes
|
||||||
setting_show_application: Disclose application used to send posts
|
setting_show_application: Disclose application used to send posts
|
||||||
|
setting_show_avatar_on_filter: Show filtered posts with avatar and user profile
|
||||||
setting_show_blocking_quote: Show posts which have a quote written by the user you are blocking
|
setting_show_blocking_quote: Show posts which have a quote written by the user you are blocking
|
||||||
setting_show_emoji_reaction_count: Show emoji reaction number
|
setting_show_emoji_reaction_count: Show emoji reaction number
|
||||||
setting_show_emoji_reaction_on_timeline: Show all emoji reactions on timeline
|
setting_show_emoji_reaction_on_timeline: Show all emoji reactions on timeline
|
||||||
|
@ -372,7 +372,6 @@ en:
|
||||||
name: Hashtag
|
name: Hashtag
|
||||||
filters:
|
filters:
|
||||||
actions:
|
actions:
|
||||||
half_warn: Half hide with a warning
|
|
||||||
hide: Hide completely
|
hide: Hide completely
|
||||||
warn: Hide with a warning
|
warn: Hide with a warning
|
||||||
options:
|
options:
|
||||||
|
|
|
@ -98,7 +98,6 @@ ja:
|
||||||
filters:
|
filters:
|
||||||
action: 投稿がフィルタに一致したときに実行するアクションを選択
|
action: 投稿がフィルタに一致したときに実行するアクションを選択
|
||||||
actions:
|
actions:
|
||||||
half_warn: フィルターに一致した投稿の本文のみを非表示にし、フィルターのタイトルを含む警告を表示します
|
|
||||||
hide: フィルタに一致した投稿を完全に非表示にします
|
hide: フィルタに一致した投稿を完全に非表示にします
|
||||||
warn: フィルタに一致した投稿を非表示にし、フィルタのタイトルを含む警告を表示します
|
warn: フィルタに一致した投稿を非表示にし、フィルタのタイトルを含む警告を表示します
|
||||||
form_admin_settings:
|
form_admin_settings:
|
||||||
|
@ -318,6 +317,7 @@ ja:
|
||||||
setting_reject_unlisted_subscription: Misskey系サーバーに「非収載」かつ検索許可「誰でも以外」の投稿を「フォロワーのみ」に変換して配送する
|
setting_reject_unlisted_subscription: Misskey系サーバーに「非収載」かつ検索許可「誰でも以外」の投稿を「フォロワーのみ」に変換して配送する
|
||||||
setting_reverse_search_quote: ダブルクオートで囲まず検索した時、単語単位で検索する
|
setting_reverse_search_quote: ダブルクオートで囲まず検索した時、単語単位で検索する
|
||||||
setting_show_application: 送信したアプリを開示する
|
setting_show_application: 送信したアプリを開示する
|
||||||
|
setting_show_avatar_on_filter: フィルター対象投稿の投稿者名やアイコンを表示する
|
||||||
setting_show_blocking_quote: ブロックしたユーザーの投稿を引用した投稿を表示する
|
setting_show_blocking_quote: ブロックしたユーザーの投稿を引用した投稿を表示する
|
||||||
setting_show_emoji_reaction_count: 投稿につけられた各絵文字の数を表示する
|
setting_show_emoji_reaction_count: 投稿につけられた各絵文字の数を表示する
|
||||||
setting_show_emoji_reaction_on_timeline: タイムライン上の投稿に他の人のつけた絵文字を表示する
|
setting_show_emoji_reaction_on_timeline: タイムライン上の投稿に他の人のつけた絵文字を表示する
|
||||||
|
@ -370,7 +370,6 @@ ja:
|
||||||
name: ハッシュタグ
|
name: ハッシュタグ
|
||||||
filters:
|
filters:
|
||||||
actions:
|
actions:
|
||||||
half_warn: アカウント名だけを出し、本文は警告で隠す
|
|
||||||
hide: 完全に隠す
|
hide: 完全に隠す
|
||||||
warn: 警告付きで隠す
|
warn: 警告付きで隠す
|
||||||
options:
|
options:
|
||||||
|
|
11
db/migrate/20250123091137_remove_half_warn_filter_option.rb
Normal file
11
db/migrate/20250123091137_remove_half_warn_filter_option.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class RemoveHalfWarnFilterOption < ActiveRecord::Migration[8.0]
|
||||||
|
class CustomFilter < ApplicationRecord; end
|
||||||
|
|
||||||
|
def up
|
||||||
|
CustomFilter.where(action: 2).in_batches.update_all(action: 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2025_01_08_111200) do
|
ActiveRecord::Schema[8.0].define(version: 2025_01_23_091137) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "pg_catalog.plpgsql"
|
enable_extension "pg_catalog.plpgsql"
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module Mastodon
|
module Mastodon
|
||||||
module Version
|
module Version
|
||||||
KMYBLUE_API_VERSION = 1
|
KMYBLUE_API_VERSION = 2
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace :dangerous do
|
||||||
end
|
end
|
||||||
|
|
||||||
target_migrations = %w(
|
target_migrations = %w(
|
||||||
|
20250123091137
|
||||||
20241208232829
|
20241208232829
|
||||||
20240828123604
|
20240828123604
|
||||||
20240709063700
|
20240709063700
|
||||||
|
|
|
@ -784,9 +784,8 @@ const startServer = async () => {
|
||||||
// custom_filters.action database column, it is an integer
|
// custom_filters.action database column, it is an integer
|
||||||
// representing a value in an enum defined by Ruby on Rails:
|
// representing a value in an enum defined by Ruby on Rails:
|
||||||
//
|
//
|
||||||
// enum { warn: 0, hide: 1, half_warn: 2 }
|
// enum { warn: 0, hide: 1 }
|
||||||
filter_action: filter.filter_action === 2 ? 'warn' : ['warn', 'hide', 'half_warn'][filter.filter_action],
|
filter_action: ['warn', 'hide'][filter.filter_action],
|
||||||
filter_action_ex: ['warn', 'hide', 'half_warn'][filter.filter_action],
|
|
||||||
with_quote: filter.with_quote,
|
with_quote: filter.with_quote,
|
||||||
withAccountName: filter.with_profile,
|
withAccountName: filter.with_profile,
|
||||||
excludeFollows: filter.exclude_follows,
|
excludeFollows: filter.exclude_follows,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue