diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb
new file mode 100644
index 000000000..2e91d68ee
--- /dev/null
+++ b/app/controllers/api/v2/search_controller.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class Api::V2::SearchController < Api::V1::SearchController
+ def index
+ @search = Search.new(search)
+ render json: @search, serializer: REST::V2::SearchSerializer
+ end
+end
diff --git a/app/javascript/mastodon/actions/search.js b/app/javascript/mastodon/actions/search.js
index 882c1709e..b670d25c3 100644
--- a/app/javascript/mastodon/actions/search.js
+++ b/app/javascript/mastodon/actions/search.js
@@ -33,7 +33,7 @@ export function submitSearch() {
dispatch(fetchSearchRequest());
- api(getState).get('/api/v1/search', {
+ api(getState).get('/api/v2/search', {
params: {
q: value,
resolve: true,
diff --git a/app/javascript/mastodon/features/compose/components/search_results.js b/app/javascript/mastodon/features/compose/components/search_results.js
index f2655c14d..445bf27bb 100644
--- a/app/javascript/mastodon/features/compose/components/search_results.js
+++ b/app/javascript/mastodon/features/compose/components/search_results.js
@@ -16,6 +16,28 @@ const shortNumberFormat = number => {
}
};
+const renderHashtag = hashtag => (
+
+
+
+ #{hashtag.get('name')}
+
+
+ {shortNumberFormat(hashtag.getIn(['history', 0, 'accounts']))} }} />
+
+
+
+ {shortNumberFormat(hashtag.getIn(['history', 0, 'uses']))}
+
+
+
+ day.get('uses')).toArray()}>
+
+
+
+
+);
+
export default class SearchResults extends ImmutablePureComponent {
static propTypes = {
@@ -44,27 +66,7 @@ export default class SearchResults extends ImmutablePureComponent {
- {trends && trends.map(hashtag => (
-
-
-
- #{hashtag.get('name')}
-
-
- {shortNumberFormat(hashtag.getIn(['history', 0, 'accounts']))} }} />
-
-
-
- {shortNumberFormat(hashtag.getIn(['history', 0, 'uses']))}
-
-
-
- day.get('uses')).toArray()}>
-
-
-
-
- ))}
+ {trends && trends.map(hashtag => renderHashtag(hashtag))}
);
@@ -74,7 +76,7 @@ export default class SearchResults extends ImmutablePureComponent {
count += results.get('accounts').size;
accounts = (
-
+
{results.get('accounts').map(accountId =>
)}
@@ -85,7 +87,7 @@ export default class SearchResults extends ImmutablePureComponent {
count += results.get('statuses').size;
statuses = (
-
+
{results.get('statuses').map(statusId => )}
@@ -96,13 +98,9 @@ export default class SearchResults extends ImmutablePureComponent {
count += results.get('hashtags').size;
hashtags = (
-
+
- {results.get('hashtags').map(hashtag => (
-
- {hashtag}
-
- ))}
+ {results.get('hashtags').map(hashtag => renderHashtag(hashtag))}
);
}
diff --git a/app/javascript/mastodon/reducers/search.js b/app/javascript/mastodon/reducers/search.js
index 56fd7226b..4758defb1 100644
--- a/app/javascript/mastodon/reducers/search.js
+++ b/app/javascript/mastodon/reducers/search.js
@@ -9,7 +9,7 @@ import {
COMPOSE_REPLY,
COMPOSE_DIRECT,
} from '../actions/compose';
-import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
+import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
const initialState = ImmutableMap({
value: '',
@@ -39,7 +39,7 @@ export default function search(state = initialState, action) {
return state.set('results', ImmutableMap({
accounts: ImmutableList(action.results.accounts.map(item => item.id)),
statuses: ImmutableList(action.results.statuses.map(item => item.id)),
- hashtags: ImmutableList(action.results.hashtags),
+ hashtags: fromJS(action.results.hashtags),
})).set('submitted', true);
default:
return state;
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index a2a18b5a0..c93d8e86a 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -3284,6 +3284,15 @@ a.status-card {
}
.search__icon {
+ &::-moz-focus-inner {
+ border: 0;
+ }
+
+ &::-moz-focus-inner,
+ &:focus {
+ outline: 0 !important;
+ }
+
.fa {
position: absolute;
top: 10px;
@@ -3333,7 +3342,6 @@ a.status-card {
.search-results__header {
color: $dark-text-color;
background: lighten($ui-base-color, 2%);
- border-bottom: 1px solid darken($ui-base-color, 4%);
padding: 15px;
font-weight: 500;
font-size: 16px;
@@ -3346,33 +3354,21 @@ a.status-card {
}
.search-results__section {
- margin-bottom: 20px;
+ margin-bottom: 5px;
h5 {
- position: relative;
+ background: darken($ui-base-color, 4%);
+ border-bottom: 1px solid lighten($ui-base-color, 8%);
+ cursor: default;
+ display: flex;
+ padding: 15px;
+ font-weight: 500;
+ font-size: 16px;
+ color: $dark-text-color;
- &::before {
- content: "";
- display: block;
- position: absolute;
- left: 0;
- right: 0;
- top: 50%;
- width: 100%;
- height: 0;
- border-top: 1px solid lighten($ui-base-color, 8%);
- }
-
- span {
+ .fa {
display: inline-block;
- background: $ui-base-color;
- color: $darker-text-color;
- font-size: 14px;
- font-weight: 500;
- padding: 10px;
- position: relative;
- z-index: 1;
- cursor: default;
+ margin-right: 5px;
}
}
diff --git a/app/serializers/rest/v2/search_serializer.rb b/app/serializers/rest/v2/search_serializer.rb
new file mode 100644
index 000000000..cdb6b3a53
--- /dev/null
+++ b/app/serializers/rest/v2/search_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class REST::V2::SearchSerializer < ActiveModel::Serializer
+ has_many :accounts, serializer: REST::AccountSerializer
+ has_many :statuses, serializer: REST::StatusSerializer
+ has_many :hashtags, serializer: REST::TagSerializer
+end
diff --git a/config/routes.rb b/config/routes.rb
index 2fcb885ed..31e90e2ff 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -315,6 +315,10 @@ Rails.application.routes.draw do
end
end
+ namespace :v2 do
+ get '/search', to: 'search#index', as: :search
+ end
+
namespace :web do
resource :settings, only: [:update]
resource :embed, only: [:create]