Merge branch 'zapped-by-pagination' into 'main'

zapped_by endpoint - Add pagination support

See merge request soapbox-pub/soapbox!3071
environments/review-fix-nos2x-2n6448/deployments/4716
Alex Gleason 1 month ago
commit 194aa4e5d5

@ -88,6 +88,9 @@ const ZAPS_FETCH_REQUEST = 'ZAPS_FETCH_REQUEST';
const ZAPS_FETCH_SUCCESS = 'ZAPS_FETCH_SUCCESS';
const ZAPS_FETCH_FAIL = 'ZAPS_FETCH_FAIL';
const ZAPS_EXPAND_SUCCESS = 'ZAPS_EXPAND_SUCCESS';
const ZAPS_EXPAND_FAIL = 'ZAPS_EXPAND_FAIL';
const messages = defineMessages({
bookmarkAdded: { id: 'status.bookmarked', defaultMessage: 'Bookmark added.' },
bookmarkRemoved: { id: 'status.unbookmarked', defaultMessage: 'Bookmark removed.' },
@ -634,8 +637,9 @@ const fetchZaps = (id: string) =>
dispatch(fetchZapsRequest(id));
api(getState).get(`/api/v1/ditto/statuses/${id}/zapped_by`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts((response.data as APIEntity[]).map(({ account }) => account).flat()));
dispatch(fetchZapsSuccess(id, response.data));
dispatch(fetchZapsSuccess(id, response.data, next ? next.uri : null));
}).catch(error => {
dispatch(fetchZapsFail(id, error));
});
@ -646,10 +650,11 @@ const fetchZapsRequest = (id: string) => ({
id,
});
const fetchZapsSuccess = (id: string, zaps: APIEntity[]) => ({
const fetchZapsSuccess = (id: string, zaps: APIEntity[], next: string | null) => ({
type: ZAPS_FETCH_SUCCESS,
id,
zaps,
next,
});
const fetchZapsFail = (id: string, error: unknown) => ({
@ -658,6 +663,31 @@ const fetchZapsFail = (id: string, error: unknown) => ({
error,
});
const expandZaps = (id: string, path: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
api(getState).get(path).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.map((item: APIEntity) => item.account)));
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.account.id)));
dispatch(expandZapsSuccess(id, response.data, next ? next.uri : null));
}).catch(error => {
dispatch(expandZapsFail(id, error));
});
};
const expandZapsSuccess = (id: string, zaps: APIEntity[], next: string | null) => ({
type: ZAPS_EXPAND_SUCCESS,
id,
zaps,
next,
});
const expandZapsFail = (id: string, error: unknown) => ({
type: ZAPS_EXPAND_FAIL,
id,
error,
});
const pin = (status: StatusEntity) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
@ -838,6 +868,8 @@ export {
ZAPS_FETCH_REQUEST,
ZAPS_FETCH_SUCCESS,
ZAPS_FETCH_FAIL,
ZAPS_EXPAND_SUCCESS,
ZAPS_EXPAND_FAIL,
reblog,
unreblog,
toggleReblog,
@ -909,4 +941,5 @@ export {
remoteInteractionFail,
zap,
fetchZaps,
expandZaps,
};

@ -2,7 +2,7 @@ import { List as ImmutableList } from 'immutable';
import React, { useEffect, useMemo } from 'react';
import { FormattedMessage } from 'react-intl';
import { fetchZaps } from 'soapbox/actions/interactions';
import { fetchZaps, expandZaps } from 'soapbox/actions/interactions';
import ScrollableList from 'soapbox/components/scrollable-list';
import { Modal, Spinner, Text } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account-container';
@ -23,7 +23,7 @@ interface IZapsModal {
const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
const dispatch = useAppDispatch();
const zaps = useAppSelector((state) => state.user_lists.zapped_by.get(statusId)?.items);
const next = useAppSelector((state) => state.user_lists.zapped_by.get(statusId)?.next);
const accounts = useMemo((): ImmutableList<IAccountWithZaps> | undefined => {
if (!zaps) return;
@ -43,6 +43,13 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
onClose('ZAPS');
};
const handleLoadMore = () => {
if (next) {
console.log('next, zaps modal: ', next);
dispatch(expandZaps(statusId, next!));
}
};
let body;
if (!zaps || !accounts) {
@ -58,14 +65,16 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
itemClassName='pb-3'
style={{ height: '80vh' }}
useWindowScroll={false}
onLoadMore={handleLoadMore}
hasMore={!!next}
>
{accounts.map((account) => {
{accounts.map((account, index) => {
return (
<div>
<div key={index}>
<Text weight='bold'>
{shortNumberFormat(account.amount / 1000)}
</Text>
<AccountContainer key={account.id} id={account.id} note={account.comment} emoji='⚡' />
<AccountContainer id={account.id} note={account.comment} emoji='⚡' />
</div>
);
},

@ -2,6 +2,7 @@ import {
Map as ImmutableMap,
OrderedSet as ImmutableOrderedSet,
Record as ImmutableRecord,
List as ImmutableList,
} from 'immutable';
import { AnyAction } from 'redux';
@ -65,6 +66,7 @@ import {
DISLIKES_FETCH_SUCCESS,
REACTIONS_FETCH_SUCCESS,
ZAPS_FETCH_SUCCESS,
ZAPS_EXPAND_SUCCESS,
} from 'soapbox/actions/interactions';
import {
NOTIFICATIONS_UPDATE,
@ -98,7 +100,8 @@ export const ZapRecord = ImmutableRecord({
});
const ZapListRecord = ImmutableRecord({
items: ImmutableOrderedSet<Zap>(),
next: null as string | null,
items: ImmutableList<Zap>(),
isLoading: false,
});
@ -203,11 +206,22 @@ export default function userLists(state = ReducerRecord(), action: AnyAction) {
}));
case ZAPS_FETCH_SUCCESS:
return state.setIn(['zapped_by', action.id], ZapListRecord({
items: ImmutableOrderedSet<Zap>(action.zaps.map(({ account, ...zap }: APIEntity) => ZapRecord({
items: ImmutableList(action.zaps.map(({ account, ...zap }: APIEntity) => ZapRecord({
...zap,
account: account.id,
}))),
}))), next: action.next,
}));
case ZAPS_EXPAND_SUCCESS:
return state.updateIn(['zapped_by', action.id], map => {
return (map as List)
.set('next', action.next)
.set('isLoading', false)
.update('items', list => (list as Items).concat(ImmutableList(action.zaps.map(({ account, ...zap }: APIEntity) => ZapRecord({
...zap,
account: account.id,
})))));
});
case NOTIFICATIONS_UPDATE:
return action.notification.type === 'follow_request' ? normalizeFollowRequest(state, action.notification) : state;
case FOLLOW_REQUESTS_FETCH_SUCCESS:

Loading…
Cancel
Save