diff --git a/app/javascript/mastodon/actions/search.ts b/app/javascript/mastodon/actions/search.ts
index 4f21a53b4d..4b97682a74 100644
--- a/app/javascript/mastodon/actions/search.ts
+++ b/app/javascript/mastodon/actions/search.ts
@@ -12,6 +12,11 @@ import {
createAppAsyncThunk,
} from 'mastodon/store/typed_functions';
+import {
+ importAccountsForPreviewCard,
+ importFetchedCollections,
+} from '../reducers/slices/collections';
+
import { fetchRelationships } from './accounts';
import { importFetchedAccounts, importFetchedStatuses } from './importer';
@@ -29,7 +34,7 @@ export const submitSearch = createDataLoadingThunk(
limit: 11,
});
},
- (data, { dispatch }) => {
+ async (data, { dispatch }) => {
if (data.accounts.length > 0) {
dispatch(importFetchedAccounts(data.accounts));
dispatch(fetchRelationships(data.accounts.map((account) => account.id)));
@@ -39,6 +44,11 @@ export const submitSearch = createDataLoadingThunk(
dispatch(importFetchedStatuses(data.statuses));
}
+ if (data.collections.length > 0) {
+ dispatch(importFetchedCollections(data.collections));
+ await importAccountsForPreviewCard(data.collections, dispatch);
+ }
+
return data;
},
{
@@ -60,7 +70,7 @@ export const expandSearch = createDataLoadingThunk(
offset,
});
},
- (data, { dispatch }) => {
+ async (data, { dispatch }) => {
if (data.accounts.length > 0) {
dispatch(importFetchedAccounts(data.accounts));
dispatch(fetchRelationships(data.accounts.map((account) => account.id)));
@@ -70,6 +80,11 @@ export const expandSearch = createDataLoadingThunk(
dispatch(importFetchedStatuses(data.statuses));
}
+ if (data.collections.length > 0) {
+ dispatch(importFetchedCollections(data.collections));
+ await importAccountsForPreviewCard(data.collections, dispatch);
+ }
+
return data;
},
{
diff --git a/app/javascript/mastodon/features/search/index.tsx b/app/javascript/mastodon/features/search/index.tsx
index 724d9c16d6..8ff5c9016a 100644
--- a/app/javascript/mastodon/features/search/index.tsx
+++ b/app/javascript/mastodon/features/search/index.tsx
@@ -4,6 +4,7 @@ import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
import { Helmet } from '@unhead/react/helmet';
+import CollectionsIcon from '@/material-icons/400-24px/category.svg?react';
import FindInPageIcon from '@/material-icons/400-24px/find_in_page.svg?react';
import PeopleIcon from '@/material-icons/400-24px/group.svg?react';
import SearchIcon from '@/material-icons/400-24px/search.svg?react';
@@ -23,6 +24,8 @@ import { useSearchParam } from 'mastodon/hooks/useSearchParam';
import type { Hashtag as HashtagType } from 'mastodon/models/tags';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
+import { CollectionListItem } from '../collections/components/collection_list_item';
+
import { SearchSection } from './components/search_section';
const messages = defineMessages({
@@ -131,7 +134,8 @@ export const SearchResults: React.FC<{ multiColumn: boolean }> = ({
filteredResults =
results.accounts.length +
results.hashtags.length +
- results.statuses.length >
+ results.statuses.length +
+ results.collections.length >
0 ? (
<>
{results.accounts.length > 0 && (
@@ -154,6 +158,32 @@ export const SearchResults: React.FC<{ multiColumn: boolean }> = ({
)}
+ {results.collections.length > 0 && (
+
+
+
+ >
+ }
+ >
+ {results.collections
+ .slice(0, INITIAL_DISPLAY)
+ .map((collection, index, array) => (
+
+ ))}
+
+ )}
+
{results.hashtags.length > 0 && (
({
accounts: serverJSON.accounts.map((account) => account.id),
statuses: serverJSON.statuses.map((status) => status.id),
hashtags: serverJSON.hashtags,
+ collections: serverJSON.collections,
});
diff --git a/app/javascript/mastodon/reducers/search.ts b/app/javascript/mastodon/reducers/search.ts
index c822990244..7b9e1f6fcf 100644
--- a/app/javascript/mastodon/reducers/search.ts
+++ b/app/javascript/mastodon/reducers/search.ts
@@ -49,6 +49,9 @@ export const searchReducer = createReducer(initialState, (builder) => {
hashtags: state.results
? [...state.results.hashtags, ...results.hashtags]
: results.hashtags,
+ collections: state.results
+ ? [...state.results.collections, ...results.collections]
+ : results.collections,
};
state.loading = false;
});
diff --git a/app/javascript/mastodon/reducers/slices/collections.ts b/app/javascript/mastodon/reducers/slices/collections.ts
index 56cf907f78..41bda5aa95 100644
--- a/app/javascript/mastodon/reducers/slices/collections.ts
+++ b/app/javascript/mastodon/reducers/slices/collections.ts
@@ -121,6 +121,15 @@ const collectionSlice = createSlice({
const { field, value } = action.payload;
state.editor[field] = value;
},
+ importFetchedCollections(
+ state,
+ action: PayloadAction,
+ ) {
+ const collections = action.payload;
+ collections.forEach((collection) => {
+ state.collections[collection.id] = collection;
+ });
+ },
},
extraReducers(builder) {
/**
@@ -328,7 +337,7 @@ const collectionSlice = createSlice({
/**
* Prefetch accounts whose avatars will be displayed in the collection list
*/
-async function importAccountsForPreviewCard(
+export async function importAccountsForPreviewCard(
collections: ApiCollectionJSON[],
dispatch: AppDispatch,
) {
@@ -419,6 +428,8 @@ export const collections = collectionSlice.reducer;
export const collectionEditorActions = collectionSlice.actions;
export const updateCollectionEditorField =
collectionSlice.actions.updateEditorField;
+export const importFetchedCollections =
+ collectionSlice.actions.importFetchedCollections;
/**
* Selectors