diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb
index 6dd4fb18b0..28dace0f98 100644
--- a/app/chewy/statuses_index.rb
+++ b/app/chewy/statuses_index.rb
@@ -30,7 +30,20 @@ class StatusesIndex < Chewy::Index
english_stemmer
),
},
+ sudachi_analyzer: {
+ filter: [],
+ type: 'custom',
+ tokenizer: 'sudachi_tokenizer',
+ },
},
+ tokenizer: {
+ sudachi_tokenizer: {
+ resources_path: '/etc/elasticsearch/sudachi',
+ split_mode: 'C',
+ type: 'sudachi_tokenizer',
+ discard_punctuation: 'true',
+ }
+ }
}
# We do not use delete_if option here because it would call a method that we
@@ -47,6 +60,11 @@ class StatusesIndex < Chewy::Index
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
end
+ crutch :emoji_reactions do |collection|
+ data = ::EmojiReaction.where(status_id: collection.map(&:id)).where(account: Account.local).pluck(:status_id, :account_id)
+ data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
+ end
+
crutch :reblogs do |collection|
data = ::Status.where(reblog_of_id: collection.map(&:id)).where(account: Account.local).pluck(:reblog_of_id, :account_id)
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb
index 4d20aeb10f..6098fc6abd 100644
--- a/app/controllers/api/v2/search_controller.rb
+++ b/app/controllers/api/v2/search_controller.rb
@@ -3,7 +3,7 @@
class Api::V2::SearchController < Api::BaseController
include Authorization
- RESULTS_LIMIT = 20
+ RESULTS_LIMIT = 40
before_action -> { authorize_if_got_token! :read, :'read:search' }
before_action :validate_search_params!
diff --git a/app/javascript/mastodon/actions/search.js b/app/javascript/mastodon/actions/search.js
index 56608f28ba..95192e078d 100644
--- a/app/javascript/mastodon/actions/search.js
+++ b/app/javascript/mastodon/actions/search.js
@@ -46,7 +46,7 @@ export function submitSearch(type) {
params: {
q: value,
resolve: signedIn,
- limit: 5,
+ limit: 10,
type,
},
}).then(response => {
diff --git a/app/javascript/mastodon/features/compose/components/search_results.jsx b/app/javascript/mastodon/features/compose/components/search_results.jsx
index 1dccd950cb..faa5bbe61d 100644
--- a/app/javascript/mastodon/features/compose/components/search_results.jsx
+++ b/app/javascript/mastodon/features/compose/components/search_results.jsx
@@ -24,6 +24,7 @@ class SearchResults extends ImmutablePureComponent {
dismissSuggestion: PropTypes.func.isRequired,
searchTerm: PropTypes.string,
intl: PropTypes.object.isRequired,
+ noMoreResults: ImmutablePropTypes.map,
};
componentDidMount () {
@@ -44,6 +45,8 @@ class SearchResults extends ImmutablePureComponent {
handleLoadMoreHashtags = () => this.props.expandSearch('hashtags');
+ showMoreResults = (searchType) => this.props.noMoreResults ? !this.props.noMoreResults.get(searchType) : true;
+
render () {
const { intl, results, suggestions, dismissSuggestion, searchTerm } = this.props;
@@ -75,26 +78,28 @@ class SearchResults extends ImmutablePureComponent {
if (results.get('accounts') && results.get('accounts').size > 0) {
count += results.get('accounts').size;
+ const showMore = this.showMoreResults('accounts');
accounts = (
{results.get('accounts').map(accountId =>
)}
- {results.get('accounts').size >= 5 &&
}
+ {showMore &&
}
);
}
if (results.get('statuses') && results.get('statuses').size > 0) {
count += results.get('statuses').size;
+ const showMore = this.showMoreResults('statuses');
statuses = (
{results.get('statuses').map(statusId => )}
- {results.get('statuses').size >= 5 && }
+ {showMore && }
);
} else if(results.get('statuses') && results.get('statuses').size === 0 && !searchEnabled && !(searchTerm.startsWith('@') || searchTerm.startsWith('#') || searchTerm.includes(' '))) {
@@ -111,13 +116,14 @@ class SearchResults extends ImmutablePureComponent {
if (results.get('hashtags') && results.get('hashtags').size > 0) {
count += results.get('hashtags').size;
+ const showMore = this.showMoreResults('hashtags');
hashtags = (
{results.get('hashtags').map(hashtag => )}
- {results.get('hashtags').size >= 5 && }
+ {showMore && }
);
}
diff --git a/app/javascript/mastodon/reducers/search.js b/app/javascript/mastodon/reducers/search.js
index e545f430cc..f56d85542f 100644
--- a/app/javascript/mastodon/reducers/search.js
+++ b/app/javascript/mastodon/reducers/search.js
@@ -21,6 +21,7 @@ const initialState = ImmutableMap({
submitted: false,
hidden: false,
results: ImmutableMap(),
+ noMoreResults: ImmutableMap(),
isLoading: false,
searchTerm: '',
recent: ImmutableOrderedSet(),
@@ -34,6 +35,7 @@ export default function search(state = initialState, action) {
return state.withMutations(map => {
map.set('value', '');
map.set('results', ImmutableMap());
+ map.set('noMoreResults', ImmutableMap());
map.set('submitted', false);
map.set('hidden', false);
});
@@ -57,13 +59,18 @@ export default function search(state = initialState, action) {
statuses: ImmutableList(action.results.statuses.map(item => item.id)),
hashtags: fromJS(action.results.hashtags),
}));
+ map.set('noMoreResults', ImmutableMap({
+ accounts: action.results.accounts.length <= 0,
+ statuses: action.results.statuses.length <= 0,
+ hashtags: false,
+ }));
map.set('searchTerm', action.searchTerm);
map.set('isLoading', false);
});
case SEARCH_EXPAND_SUCCESS:
const results = action.searchType === 'hashtags' ? fromJS(action.results.hashtags) : action.results[action.searchType].map(item => item.id);
- return state.updateIn(['results', action.searchType], list => list.concat(results));
+ return state.updateIn(['results', action.searchType], list => list.concat(results)).setIn(['noMoreResults', action.searchType], results.size <= 0);
case SEARCH_RESULT_CLICK:
return state.update('recent', set => set.add(fromJS(action.result)));
case SEARCH_RESULT_FORGET:
diff --git a/app/lib/status_filter.rb b/app/lib/status_filter.rb
index c0e6f33313..05b818f73a 100644
--- a/app/lib/status_filter.rb
+++ b/app/lib/status_filter.rb
@@ -15,6 +15,12 @@ class StatusFilter
blocked_by_policy? || (account_present? && filtered_status?) || silenced_account?
end
+ def search_filtered?
+ return false if !account.nil? && account.id == status.account_id
+
+ blocked_by_policy_search? || (account_present? && filtered_status?) || silenced_account?
+ end
+
private
def account_present?
@@ -53,7 +59,15 @@ class StatusFilter
!policy_allows_show?
end
+ def blocked_by_policy_search?
+ !policy_allows_search?
+ end
+
def policy_allows_show?
StatusPolicy.new(account, status, @preloaded_relations).show?
end
+
+ def policy_allows_search?
+ StatusPolicy.new(account, status, @preloaded_relations).search?
+ end
end
diff --git a/app/models/status.rb b/app/models/status.rb
index fcb3deb949..ebd4cac382 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -157,12 +157,14 @@ class Status < ApplicationRecord
if preloaded.nil?
ids += mentions.joins(:account).merge(Account.local).active.pluck(:account_id)
ids += favourites.joins(:account).merge(Account.local).pluck(:account_id)
+ ids += emoji_reactions.joins(:account).merge(Account.local).pluck(:account_id)
ids += reblogs.joins(:account).merge(Account.local).pluck(:account_id)
ids += bookmarks.joins(:account).merge(Account.local).pluck(:account_id)
ids += poll.votes.joins(:account).merge(Account.local).pluck(:account_id) if poll.present?
else
ids += preloaded.mentions[id] || []
ids += preloaded.favourites[id] || []
+ ids += preloaded.emoji_reactions[id] || []
ids += preloaded.reblogs[id] || []
ids += preloaded.bookmarks[id] || []
ids += preloaded.votes[id] || []
diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb
index 694997788d..74709647a8 100644
--- a/app/policies/status_policy.rb
+++ b/app/policies/status_policy.rb
@@ -19,6 +19,18 @@ class StatusPolicy < ApplicationPolicy
end
end
+ def search?
+ return false if author.suspended?
+
+ if requires_mention?
+ owned? || mention_exists?
+ elsif !public?
+ owned? || following_author? || mention_exists?
+ else
+ current_account.nil? || (!author_blocking? && !author_blocking_domain?)
+ end
+ end
+
def reblog?
!requires_mention? && (!private? || owned?) && show? && !blocking_author?
end
@@ -55,6 +67,10 @@ class StatusPolicy < ApplicationPolicy
record.private_visibility?
end
+ def public?
+ record.public_visibility? || record.public_unlisted_visibility?
+ end
+
def mention_exists?
return false if current_account.nil?
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index b1ce5453fb..da9faf7384 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -35,7 +35,8 @@ class SearchService < BaseService
end
def perform_statuses_search!
- definition = parsed_query.apply(StatusesIndex.filter(term: { searchable_by: @account.id }))
+ # definition = parsed_query.apply(StatusesIndex.filter(term: { searchable_by: @account.id })).order(id: :desc)
+ definition = parsed_query.apply(StatusesIndex).order(id: :desc)
definition = definition.filter(term: { account_id: @options[:account_id] }) if @options[:account_id].present?
@@ -51,7 +52,7 @@ class SearchService < BaseService
account_domains = results.map(&:account_domain)
preloaded_relations = @account.relations_map(account_ids, account_domains)
- results.reject { |status| StatusFilter.new(status, @account, preloaded_relations).filtered? }
+ results.reject { |status| StatusFilter.new(status, @account, preloaded_relations).search_filtered? }
rescue Faraday::ConnectionFailed, Parslet::ParseFailed
[]
end