Add: 検索許可「ローカルとフォロワー」 (#60)
This commit is contained in:
parent
deb8642e95
commit
235bef36d0
24 changed files with 210 additions and 25 deletions
|
@ -15,6 +15,8 @@ import { IconButton } from '../../../components/icon_button';
|
|||
const messages = defineMessages({
|
||||
public_short: { id: 'searchability.public.short', defaultMessage: 'Public' },
|
||||
public_long: { id: 'searchability.public.long', defaultMessage: 'Anyone can find' },
|
||||
public_unlisted_short: { id: 'searchability.public_unlisted.short', defaultMessage: 'Public unlisted' },
|
||||
public_unlisted_long: { id: 'searchability.public_unlisted.long', defaultMessage: 'Local users and followers can find' },
|
||||
private_short: { id: 'searchability.unlisted.short', defaultMessage: 'Followers' },
|
||||
private_long: { id: 'searchability.unlisted.long', defaultMessage: 'Your followers can find' },
|
||||
direct_short: { id: 'searchability.private.short', defaultMessage: 'Reactionners' },
|
||||
|
@ -223,6 +225,7 @@ class SearchabilityDropdown extends PureComponent {
|
|||
|
||||
this.options = [
|
||||
{ icon: 'globe', value: 'public', text: formatMessage(messages.public_short), meta: formatMessage(messages.public_long) },
|
||||
{ icon: 'cloud', value: 'public_unlisted', text: formatMessage(messages.public_unlisted_short), meta: formatMessage(messages.public_unlisted_long) },
|
||||
{ icon: 'unlock', value: 'private', text: formatMessage(messages.private_short), meta: formatMessage(messages.private_long) },
|
||||
{ icon: 'lock', value: 'direct', text: formatMessage(messages.direct_short), meta: formatMessage(messages.direct_long) },
|
||||
{ icon: 'at', value: 'limited', text: formatMessage(messages.limited_short), meta: formatMessage(messages.limited_long) },
|
||||
|
|
|
@ -38,6 +38,7 @@ const messages = defineMessages({
|
|||
personal_short: { id: 'privacy.personal.short', defaultMessage: 'Yourself only' },
|
||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Mentioned people only' },
|
||||
searchability_public_short: { id: 'searchability.public.short', defaultMessage: 'Public' },
|
||||
searchability_public_unlisted_short: { id: 'searchability.public_unlisted.short', defaultMessage: 'Public unlisted' },
|
||||
searchability_private_short: { id: 'searchability.unlisted.short', defaultMessage: 'Followers' },
|
||||
searchability_direct_short: { id: 'searchability.private.short', defaultMessage: 'Reactionners' },
|
||||
searchability_limited_short: { id: 'searchability.direct.short', defaultMessage: 'Self only' },
|
||||
|
@ -270,6 +271,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
|
||||
const searchabilityIconInfo = {
|
||||
'public': { icon: 'globe', text: intl.formatMessage(messages.searchability_public_short) },
|
||||
'public_unlisted': { icon: 'cloud', text: intl.formatMessage(messages.searchability_public_unlisted_short) },
|
||||
'private': { icon: 'unlock', text: intl.formatMessage(messages.searchability_private_short) },
|
||||
'direct': { icon: 'lock', text: intl.formatMessage(messages.searchability_direct_short) },
|
||||
'limited': { icon: 'at', text: intl.formatMessage(messages.searchability_limited_short) },
|
||||
|
|
|
@ -629,6 +629,8 @@
|
|||
"searchability.private.short": "Reactionners",
|
||||
"searchability.public.long": "Anyone can find",
|
||||
"searchability.public.short": "Everyone",
|
||||
"searchability.public_unlisted.long": "Local users and followers can find",
|
||||
"searchability.public_unlisted.short": "Local and followers",
|
||||
"searchability.unlisted.long": "Your followers and reactionners can find",
|
||||
"searchability.unlisted.short": "Followers and reactionners",
|
||||
"search_popout.domain": "domain",
|
||||
|
|
|
@ -714,6 +714,8 @@
|
|||
"searchability.private.short": "反応者のみ",
|
||||
"searchability.public.long": "この投稿は誰でも検索できます",
|
||||
"searchability.public.short": "誰でも",
|
||||
"searchability.public_unlisted.long": "ローカルユーザーとフォロワーが検索できます",
|
||||
"searchability.public_unlisted.short": "ローカルとフォロワー",
|
||||
"searchability.unlisted.long": "この投稿はあなたのフォロワーと反応者だけが検索できます",
|
||||
"searchability.unlisted.short": "フォロワーと反応者",
|
||||
"search_popout.domain": "ドメイン",
|
||||
|
|
|
@ -26,7 +26,7 @@ class AccountStatusesFilter
|
|||
scope.merge!(no_reblogs_scope) if exclude_reblogs?
|
||||
scope.merge!(hashtag_scope) if tagged?
|
||||
|
||||
available_searchabilities = [:public, :unlisted, :private, :direct, :limited, nil]
|
||||
available_searchabilities = [:public, :public_unlisted, :unlisted, :private, :direct, :limited, nil]
|
||||
available_visibilities = [:public, :public_unlisted, :login, :unlisted, :private, :direct, :limited]
|
||||
|
||||
available_searchabilities = [:public] if domain_block&.reject_send_not_public_searchability
|
||||
|
|
|
@ -23,7 +23,7 @@ class Importer::StatusesIndexImporter < Importer::BaseImporter
|
|||
to_index.map do |object|
|
||||
# This is unlikely to happen, but the post may have been
|
||||
# un-interacted with since it was queued for indexing
|
||||
if object.searchable_by.empty? && %w(public private).exclude?(object.searchability)
|
||||
if object.searchable_by.empty? && %w(public public_unlisted private).exclude?(object.searchability)
|
||||
deleted += 1
|
||||
{ delete: { _id: object.id } }
|
||||
else
|
||||
|
|
|
@ -89,10 +89,10 @@ class SearchQueryTransformer < Parslet::Transform
|
|||
public_index,
|
||||
searchability_limited,
|
||||
]
|
||||
definition_should << searchability_public if %i(public).include?(@searchability)
|
||||
definition_should << searchability_private if %i(public unlisted private).include?(@searchability)
|
||||
definition_should << searchable_by_me if %i(public unlisted private direct).include?(@searchability)
|
||||
definition_should << self_posts if %i(public unlisted private direct).exclude?(@searchability)
|
||||
definition_should << searchability_public if %i(public public_unlisted).include?(@searchability)
|
||||
definition_should << searchability_private if %i(public public_unlisted unlisted private).include?(@searchability)
|
||||
definition_should << searchable_by_me if %i(public public_unlisted unlisted private direct).include?(@searchability)
|
||||
definition_should << self_posts if %i(public public_unlisted unlisted private direct).exclude?(@searchability)
|
||||
|
||||
{
|
||||
bool: {
|
||||
|
@ -199,8 +199,8 @@ class SearchQueryTransformer < Parslet::Transform
|
|||
def following_account_ids
|
||||
return @following_account_ids if defined?(@following_account_ids)
|
||||
|
||||
account_exists_sql = Account.where('accounts.id = follows.target_account_id').where(searchability: %w(public private)).reorder(nil).select(1).to_sql
|
||||
status_exists_sql = Status.where('statuses.account_id = follows.target_account_id').where(reblog_of_id: nil).where(searchability: %w(public private)).reorder(nil).select(1).to_sql
|
||||
account_exists_sql = Account.where('accounts.id = follows.target_account_id').where(searchability: %w(public public_unlisted private)).reorder(nil).select(1).to_sql
|
||||
status_exists_sql = Status.where('statuses.account_id = follows.target_account_id').where(reblog_of_id: nil).where(searchability: %w(public public_unlisted private)).reorder(nil).select(1).to_sql
|
||||
following_accounts = Follow.where(account_id: @options[:current_account].id).merge(Account.where("EXISTS (#{account_exists_sql})").or(Account.where("EXISTS (#{status_exists_sql})")))
|
||||
@following_account_ids = following_accounts.pluck(:target_account_id)
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ module StatusSearchConcern
|
|||
|
||||
included do
|
||||
scope :indexable, -> { without_reblogs.where(visibility: [:public, :login], searchability: nil).joins(:account).where(account: { indexable: true }) }
|
||||
scope :remote_dynamic_searchability, -> { remote.where(searchability: [:public, :private]) }
|
||||
scope :remote_dynamic_searchability, -> { remote.where(searchability: [:public, :public_unlisted, :private]) }
|
||||
end
|
||||
|
||||
def searchable_by
|
||||
|
|
|
@ -129,7 +129,7 @@ class Status < ApplicationRecord
|
|||
scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') }
|
||||
scope :without_reblogs, -> { where(statuses: { reblog_of_id: nil }) }
|
||||
scope :with_public_visibility, -> { where(visibility: [:public, :public_unlisted, :login]) }
|
||||
scope :with_public_search_visibility, -> { merge(where(visibility: [:public, :public_unlisted, :login]).or(Status.where(searchability: :public))) }
|
||||
scope :with_public_search_visibility, -> { merge(where(visibility: [:public, :public_unlisted, :login]).or(Status.where(searchability: [:public, :public_unlisted]))) }
|
||||
scope :with_global_timeline_visibility, -> { where(visibility: [:public, :login]) }
|
||||
scope :tagged_with, ->(tag_ids) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag_ids }) }
|
||||
scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced_at: nil }) }
|
||||
|
@ -442,19 +442,26 @@ class Status < ApplicationRecord
|
|||
|
||||
def compute_searchability
|
||||
local = account.local?
|
||||
check_searchability = public_unlisted_searchability? ? 'public' : searchability
|
||||
|
||||
return 'private' if public_searchability? && account.silenced?
|
||||
return 'private' if %w(public public_unlisted).include?(check_searchability) && account.silenced?
|
||||
return 'direct' if unsupported_searchability?
|
||||
return searchability if local && !searchability.nil?
|
||||
return 'direct' if local || [:public, :private, :direct, :limited].exclude?(account.searchability.to_sym)
|
||||
return check_searchability if local && !check_searchability.nil?
|
||||
return 'direct' if local || %i(public private direct limited).exclude?(account.searchability.to_sym)
|
||||
|
||||
account_searchability = Status.searchabilities[account.searchability]
|
||||
status_searchability = Status.searchabilities[searchability.nil? ? 'direct' : searchability]
|
||||
status_searchability = Status.searchabilities[check_searchability.nil? ? 'direct' : check_searchability]
|
||||
Status.searchabilities.invert.fetch([account_searchability, status_searchability].max) || 'direct'
|
||||
end
|
||||
|
||||
def compute_searchability_activitypub
|
||||
return 'private' if public_unlisted_visibility? && public_searchability?
|
||||
return 'private' if public_unlisted_searchability?
|
||||
|
||||
compute_searchability
|
||||
end
|
||||
|
||||
def compute_searchability_local
|
||||
return 'public_unlisted' if public_unlisted_searchability?
|
||||
|
||||
compute_searchability
|
||||
end
|
||||
|
@ -477,6 +484,10 @@ class Status < ApplicationRecord
|
|||
end
|
||||
|
||||
def selectable_searchabilities
|
||||
searchabilities.keys - %w(unsupported)
|
||||
end
|
||||
|
||||
def selectable_searchabilities_for_search
|
||||
searchabilities.keys - %w(public_unlisted unsupported)
|
||||
end
|
||||
|
||||
|
@ -620,7 +631,7 @@ class Status < ApplicationRecord
|
|||
elsif visibility == 'limited'
|
||||
:limited
|
||||
elsif visibility == 'private'
|
||||
searchability == 'public' ? :private : searchability
|
||||
searchability == 'public' || searchability == 'public_unlisted' ? :private : searchability
|
||||
elsif visibility == 'direct'
|
||||
searchability == 'limited' ? :limited : :direct
|
||||
else
|
||||
|
|
|
@ -106,7 +106,8 @@ class Trends::Statuses < Trends::Base
|
|||
private
|
||||
|
||||
def eligible?(status)
|
||||
(status.searchability.nil? || status.public_searchability?) && (status.public_visibility? || status.public_unlisted_visibility?) &&
|
||||
(status.searchability.nil? || status.compute_searchability == 'public') &&
|
||||
(status.public_visibility? || status.public_unlisted_visibility?) &&
|
||||
status.account.discoverable? && !status.account.silenced? && status.spoiler_text.blank? && (!status.sensitive? || status.media_attachments.none?) &&
|
||||
!status.reply? && valid_locale?(status.language)
|
||||
end
|
||||
|
|
|
@ -93,7 +93,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
|||
end
|
||||
|
||||
def searchability
|
||||
object.compute_searchability
|
||||
object.compute_searchability_local
|
||||
end
|
||||
|
||||
def sensitive
|
||||
|
|
|
@ -64,8 +64,10 @@ class DeliveryAntennaService
|
|||
next if antenna.exclude_accounts&.include?(@status.account_id)
|
||||
next if antenna.exclude_domains&.include?(domain)
|
||||
next if antenna.exclude_tags&.any? { |tag_id| tag_ids.include?(tag_id) }
|
||||
next if @status.unlisted_visibility? && !@status.public_searchability? && follower_ids.exclude?(antenna.account_id)
|
||||
next if @status.unlisted_visibility? && @status.public_searchability? && follower_ids.exclude?(antenna.account_id) && antenna.any_keywords && antenna.any_tags
|
||||
|
||||
searchability = @status.compute_searchability
|
||||
next if @status.unlisted_visibility? && searchability != 'public' && follower_ids.exclude?(antenna.account_id)
|
||||
next if @status.unlisted_visibility? && searchability == 'public' && follower_ids.exclude?(antenna.account_id) && antenna.any_keywords && antenna.any_tags
|
||||
|
||||
collection.push(antenna)
|
||||
end
|
||||
|
@ -121,7 +123,7 @@ class DeliveryAntennaService
|
|||
when :public, :public_unlisted, :login, :limited
|
||||
false
|
||||
when :unlisted
|
||||
!@status.public_searchability?
|
||||
@status.compute_searchability != 'public'
|
||||
else
|
||||
true
|
||||
end
|
||||
|
|
|
@ -218,6 +218,6 @@ class FanOutOnWriteService < BaseService
|
|||
end
|
||||
|
||||
def broadcastable_unlisted2?
|
||||
@status.unlisted_visibility? && @status.public_searchability? && !@status.reblog? && !@account.silenced?
|
||||
@status.unlisted_visibility? && @status.compute_searchability == 'public' && !@status.reblog? && !@account.silenced?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,7 +81,7 @@ class PostStatusService < BaseService
|
|||
@visibility = :public_unlisted if @visibility&.to_sym == :public && !@options[:force_visibility] && !@options[:application]&.superapp && @account.user&.setting_public_post_to_unlisted && Setting.enable_public_unlisted_visibility
|
||||
@limited_scope = @options[:visibility]&.to_sym if @visibility == :limited
|
||||
@searchability = searchability
|
||||
@searchability = :private if @account.silenced? && @searchability&.to_sym == :public
|
||||
@searchability = :private if @account.silenced? && %i(public public_unlisted).include?(@searchability&.to_sym)
|
||||
@markdown = @options[:markdown] || false
|
||||
@scheduled_at = @options[:scheduled_at]&.to_datetime
|
||||
@scheduled_at = nil if scheduled_in_the_past?
|
||||
|
@ -129,6 +129,8 @@ class PostStatusService < BaseService
|
|||
case @options[:searchability]&.to_sym
|
||||
when :public
|
||||
case @visibility&.to_sym when :public, :public_unlisted, :login, :unlisted then :public when :private then :private else :direct end
|
||||
when :public_unlisted
|
||||
case @visibility&.to_sym when :public, :public_unlisted, :login, :unlisted then :public_unlisted when :private then :private else :direct end
|
||||
when :private
|
||||
case @visibility&.to_sym when :public, :public_unlisted, :login, :unlisted, :private then :private else :direct end
|
||||
when :direct
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
.fields-row
|
||||
.fields-group.fields-row__column.fields-row__column-12
|
||||
= ff.input :default_searchability_of_search, collection: Status.selectable_searchabilities, wrapper: :with_label, kmyblue: true, include_blank: false, label_method: lambda { |searchability| safe_join([I18n.t("statuses.searchabilities.#{searchability}"), I18n.t("statuses.searchabilities.#{searchability}_search_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_searchability_of_search')
|
||||
= ff.input :default_searchability_of_search, collection: Status.selectable_searchabilities_for_search, wrapper: :with_label, kmyblue: true, include_blank: false, label_method: lambda { |searchability| safe_join([I18n.t("statuses.searchabilities.#{searchability}"), I18n.t("statuses.searchabilities.#{searchability}_search_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_searchability_of_search')
|
||||
|
||||
.fields-group
|
||||
= ff.input :use_public_index, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_use_public_index')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue