Merge branch 'pagination-trends' into 'main'
Pagination trends Closes ditto#236 See merge request soapbox-pub/soapbox!3163
This commit is contained in:
commit
85fd43a095
|
@ -1,6 +1,7 @@
|
|||
import { APIEntity } from 'soapbox/types/entities';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
import api from '../api';
|
||||
import api, { getLinks } from '../api';
|
||||
|
||||
import { importFetchedStatuses } from './importer';
|
||||
|
||||
|
@ -9,6 +10,8 @@ import type { AppDispatch, RootState } from 'soapbox/store';
|
|||
const TRENDING_STATUSES_FETCH_REQUEST = 'TRENDING_STATUSES_FETCH_REQUEST';
|
||||
const TRENDING_STATUSES_FETCH_SUCCESS = 'TRENDING_STATUSES_FETCH_SUCCESS';
|
||||
const TRENDING_STATUSES_FETCH_FAIL = 'TRENDING_STATUSES_FETCH_FAIL';
|
||||
const TRENDING_STATUSES_EXPAND_FAIL = 'TRENDING_STATUSES_EXPAND_FAIL';
|
||||
const TRENDING_STATUSES_EXPAND_SUCCESS = 'TRENDING_STATUSES_EXPAND_SUCCESS';
|
||||
|
||||
const fetchTrendingStatuses = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
|
@ -20,18 +23,62 @@ const fetchTrendingStatuses = () =>
|
|||
if (!features.trendingStatuses) return;
|
||||
|
||||
dispatch({ type: TRENDING_STATUSES_FETCH_REQUEST });
|
||||
return api(getState).get('/api/v1/trends/statuses').then(({ data: statuses }) => {
|
||||
return api(getState).get('/api/v1/trends/statuses').then((response) => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
const statuses = response.data;
|
||||
|
||||
dispatch(importFetchedStatuses(statuses));
|
||||
dispatch({ type: TRENDING_STATUSES_FETCH_SUCCESS, statuses });
|
||||
dispatch(fetchTrendingStatusesSuccess(statuses, next ? next.uri : null));
|
||||
return statuses;
|
||||
}).catch(error => {
|
||||
dispatch({ type: TRENDING_STATUSES_FETCH_FAIL, error });
|
||||
dispatch(fetchTrendingStatusesFail(error));
|
||||
});
|
||||
};
|
||||
|
||||
const fetchTrendingStatusesSuccess = (statuses: APIEntity[], next: string | null) => ({
|
||||
type: TRENDING_STATUSES_FETCH_SUCCESS,
|
||||
statuses,
|
||||
next,
|
||||
});
|
||||
|
||||
|
||||
const fetchTrendingStatusesFail = (error: unknown) => ({
|
||||
type: TRENDING_STATUSES_FETCH_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
const expandTrendingStatuses = (path: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
api(getState).get(path).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
const statuses = response.data;
|
||||
|
||||
dispatch(importFetchedStatuses(statuses));
|
||||
dispatch(expandTrendingStatusesSuccess(statuses, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(expandTrendingStatusesFail(error));
|
||||
});
|
||||
};
|
||||
|
||||
const expandTrendingStatusesSuccess = (statuses: APIEntity[], next: string | null) => ({
|
||||
type: TRENDING_STATUSES_EXPAND_SUCCESS,
|
||||
statuses,
|
||||
next,
|
||||
});
|
||||
|
||||
const expandTrendingStatusesFail = (error: unknown) => ({
|
||||
type: TRENDING_STATUSES_EXPAND_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
export {
|
||||
TRENDING_STATUSES_FETCH_REQUEST,
|
||||
TRENDING_STATUSES_FETCH_SUCCESS,
|
||||
TRENDING_STATUSES_FETCH_FAIL,
|
||||
TRENDING_STATUSES_EXPAND_SUCCESS,
|
||||
TRENDING_STATUSES_EXPAND_FAIL,
|
||||
fetchTrendingStatuses,
|
||||
expandTrendingStatuses,
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, { useEffect, useRef } from 'react';
|
|||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { expandSearch, setFilter, setSearchAccount } from 'soapbox/actions/search';
|
||||
import { fetchTrendingStatuses } from 'soapbox/actions/trending-statuses';
|
||||
import { expandTrendingStatuses, fetchTrendingStatuses } from 'soapbox/actions/trending-statuses';
|
||||
import { useAccount } from 'soapbox/api/hooks';
|
||||
import Hashtag from 'soapbox/components/hashtag';
|
||||
import IconButton from 'soapbox/components/icon-button';
|
||||
|
@ -36,13 +36,20 @@ const SearchResults = () => {
|
|||
const results = useAppSelector((state) => state.search.results);
|
||||
const suggestions = useAppSelector((state) => state.suggestions.items);
|
||||
const trendingStatuses = useAppSelector((state) => state.trending_statuses.items);
|
||||
const nextTrendingStatuses = useAppSelector((state) => state.trending_statuses.next);
|
||||
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 || undefined);
|
||||
const { account } = useAccount(filterByAccount);
|
||||
|
||||
const handleLoadMore = () => dispatch(expandSearch(selectedFilter));
|
||||
const handleLoadMore = () => {
|
||||
if (results.accounts.size || results.statuses.size || results.hashtags.size) {
|
||||
dispatch(expandSearch(selectedFilter));
|
||||
} else if (nextTrendingStatuses) {
|
||||
dispatch(expandTrendingStatuses(nextTrendingStatuses));
|
||||
}
|
||||
};
|
||||
|
||||
const handleUnsetAccount = () => dispatch(setSearchAccount(null));
|
||||
|
||||
|
@ -224,7 +231,7 @@ const SearchResults = () => {
|
|||
scrollKey={`${selectedFilter}:${value}`}
|
||||
isLoading={submitted && !loaded}
|
||||
showLoading={submitted && !loaded && searchResults?.isEmpty()}
|
||||
hasMore={hasMore}
|
||||
hasMore={(!!nextTrendingStatuses) || hasMore}
|
||||
onLoadMore={handleLoadMore}
|
||||
placeholderComponent={placeholderComponent}
|
||||
placeholderCount={20}
|
||||
|
|
|
@ -47,7 +47,7 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
|
|||
|
||||
const handleLoadMore = () => {
|
||||
if (next) {
|
||||
dispatch(expandZaps(statusId, next!));
|
||||
dispatch(expandZaps(statusId, next));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import { OrderedSet as ImmutableOrderedSet, Record as ImmutableRecord } from 'im
|
|||
import {
|
||||
TRENDING_STATUSES_FETCH_REQUEST,
|
||||
TRENDING_STATUSES_FETCH_SUCCESS,
|
||||
TRENDING_STATUSES_EXPAND_SUCCESS,
|
||||
} from 'soapbox/actions/trending-statuses';
|
||||
|
||||
import type { AnyAction } from 'redux';
|
||||
|
@ -11,6 +12,7 @@ import type { APIEntity } from 'soapbox/types/entities';
|
|||
const ReducerRecord = ImmutableRecord({
|
||||
items: ImmutableOrderedSet<string>(),
|
||||
isLoading: false,
|
||||
next: null as string | null,
|
||||
});
|
||||
|
||||
type State = ReturnType<typeof ReducerRecord>;
|
||||
|
@ -18,10 +20,11 @@ type APIEntities = Array<APIEntity>;
|
|||
|
||||
const toIds = (items: APIEntities) => ImmutableOrderedSet(items.map(item => item.id));
|
||||
|
||||
const importStatuses = (state: State, statuses: APIEntities) => {
|
||||
const importStatuses = (state: State, statuses: APIEntities, next: string|null) => {
|
||||
return state.withMutations(state => {
|
||||
state.set('items', toIds(statuses));
|
||||
state.update('items', list => list.concat(toIds(statuses)));
|
||||
state.set('isLoading', false);
|
||||
state.set('next', next ? next : null);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -29,8 +32,9 @@ export default function trending_statuses(state: State = ReducerRecord(), action
|
|||
switch (action.type) {
|
||||
case TRENDING_STATUSES_FETCH_REQUEST:
|
||||
return state.set('isLoading', true);
|
||||
case TRENDING_STATUSES_EXPAND_SUCCESS:
|
||||
case TRENDING_STATUSES_FETCH_SUCCESS:
|
||||
return importStatuses(state, action.statuses);
|
||||
return importStatuses(state, action.statuses, action.next);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue