Merge branch 'search-from-account' into 'develop'

Allow to search for posts from given account

See merge request soapbox-pub/soapbox-fe!1710
This commit is contained in:
marcin mikołajczak 2022-08-08 14:41:34 +00:00
commit a2f9c7d97b
8 changed files with 53 additions and 9 deletions

View file

@ -22,6 +22,8 @@ const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST';
const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS';
const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL';
const SEARCH_ACCOUNT_SET = 'SEARCH_ACCOUNT_SET';
const changeSearch = (value: string) =>
(dispatch: AppDispatch) => {
// If backspaced all the way, clear the search
@ -43,6 +45,7 @@ const submitSearch = (filter?: SearchFilter) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const value = getState().search.value;
const type = filter || getState().search.filter || 'accounts';
const accountId = getState().search.accountId;
// An empty search doesn't return any results
if (value.length === 0) {
@ -51,13 +54,17 @@ const submitSearch = (filter?: SearchFilter) =>
dispatch(fetchSearchRequest(value));
api(getState).get('/api/v2/search', {
params: {
const params: Record<string, any> = {
q: value,
resolve: true,
limit: 20,
type,
},
};
if (accountId) params.account_id = accountId;
api(getState).get('/api/v2/search', {
params,
}).then(response => {
if (response.data.accounts) {
dispatch(importFetchedAccounts(response.data.accounts));
@ -151,6 +158,11 @@ const showSearch = () => ({
type: SEARCH_SHOW,
});
const setSearchAccount = (accountId: string) => ({
type: SEARCH_ACCOUNT_SET,
accountId,
});
export {
SEARCH_CHANGE,
SEARCH_CLEAR,
@ -162,6 +174,7 @@ export {
SEARCH_EXPAND_REQUEST,
SEARCH_EXPAND_SUCCESS,
SEARCH_EXPAND_FAIL,
SEARCH_ACCOUNT_SET,
changeSearch,
clearSearch,
submitSearch,
@ -174,4 +187,5 @@ export {
expandSearchSuccess,
expandSearchFail,
showSearch,
setSearchAccount,
};

View file

@ -2,11 +2,12 @@ import classNames from 'classnames';
import React, { useEffect, useRef } from 'react';
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { expandSearch, setFilter } from 'soapbox/actions/search';
import { clearSearch, expandSearch, setFilter } from 'soapbox/actions/search';
import { fetchTrendingStatuses } from 'soapbox/actions/trending_statuses';
import Hashtag from 'soapbox/components/hashtag';
import IconButton from 'soapbox/components/icon_button';
import ScrollableList from 'soapbox/components/scrollable_list';
import { Tabs } from 'soapbox/components/ui';
import { HStack, Tabs, Text } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account_container';
import StatusContainer from 'soapbox/containers/status_container';
import PlaceholderAccount from 'soapbox/features/placeholder/components/placeholder_account';
@ -37,9 +38,13 @@ const SearchResults = () => {
const trends = useAppSelector((state) => state.trends.items);
const submitted = useAppSelector((state) => state.search.submitted);
const selectedFilter = useAppSelector((state) => state.search.filter);
const filterByAccount = useAppSelector((state) => state.search.accountId);
const account = useAppSelector((state) => state.accounts.get(filterByAccount)?.acct);
const handleLoadMore = () => dispatch(expandSearch(selectedFilter));
const handleClearSearch = () => dispatch(clearSearch());
const selectFilter = (newActiveFilter: SearchFilter) => dispatch(setFilter(newActiveFilter));
const renderFilterBar = () => {
@ -189,7 +194,18 @@ const SearchResults = () => {
return (
<>
{renderFilterBar()}
{filterByAccount ? (
<HStack className='mb-4 pb-4 px-2 border-solid border-b border-gray-200 dark:border-gray-800' space={2}>
<IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/x.svg')} onClick={handleClearSearch} />
<Text>
<FormattedMessage
id='search_results.filter_message'
defaultMessage='You are searching for posts from @{acct}.'
values={{ acct: account }}
/>
</Text>
</HStack>
) : renderFilterBar()}
{noResultsMessage || (
<ScrollableList

View file

@ -17,6 +17,7 @@ import {
SEARCH_FILTER_SET,
SEARCH_EXPAND_REQUEST,
SEARCH_EXPAND_SUCCESS,
SEARCH_ACCOUNT_SET,
} from '../actions/search';
import type { AnyAction } from 'redux';
@ -41,6 +42,7 @@ const ReducerRecord = ImmutableRecord({
hidden: false,
results: ResultsRecord(),
filter: 'accounts' as SearchFilter,
accountId: null as string | null,
});
type State = ReturnType<typeof ReducerRecord>;
@ -120,6 +122,8 @@ export default function search(state = ReducerRecord(), action: AnyAction) {
return state.setIn(['results', `${action.searchType}Loaded`], false);
case SEARCH_EXPAND_SUCCESS:
return paginateResults(state, action.searchType, action.results, action.searchTerm);
case SEARCH_ACCOUNT_SET:
return ReducerRecord({ accountId: action.accountId, filter: 'statuses' });
default:
return state;
}

View file

@ -536,6 +536,16 @@ const getInstanceFeatures = (instance: Instance) => {
*/
scopes: v.software === PLEROMA ? 'read write follow push admin' : 'read write follow push',
/**
* Ability to search statuses from the given account.
* @see {@link https://docs.joinmastodon.org/methods/search/}
* @see POST /api/v2/search
*/
searchFromAccount: any([
v.software === MASTODON && gte(v.version, '2.8.0'),
v.software === PLEROMA && gte(v.version, '1.0.0'),
]),
/**
* Ability to manage account security settings.
* @see POST /api/pleroma/change_password