Merge branch 'modal-scrollable-list' into 'develop'
Fix scrollable list in modals and add pagination See merge request soapbox-pub/soapbox!2570
This commit is contained in:
@ -3,7 +3,7 @@ import { defineMessages } from 'react-intl';
|
||||
import toast from 'soapbox/toast';
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
|
||||
import api from '../api';
|
||||
import api, { getLinks } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||
@ -73,6 +73,12 @@ const REMOTE_INTERACTION_REQUEST = 'REMOTE_INTERACTION_REQUEST';
|
||||
const REMOTE_INTERACTION_SUCCESS = 'REMOTE_INTERACTION_SUCCESS';
|
||||
const REMOTE_INTERACTION_FAIL = 'REMOTE_INTERACTION_FAIL';
|
||||
|
||||
const FAVOURITES_EXPAND_SUCCESS = 'FAVOURITES_EXPAND_SUCCESS';
|
||||
const FAVOURITES_EXPAND_FAIL = 'FAVOURITES_EXPAND_FAIL';
|
||||
|
||||
const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS';
|
||||
const REBLOGS_EXPAND_FAIL = 'REBLOGS_EXPAND_FAIL';
|
||||
|
||||
const messages = defineMessages({
|
||||
bookmarkAdded: { id: 'status.bookmarked', defaultMessage: 'Bookmark added.' },
|
||||
bookmarkRemoved: { id: 'status.unbookmarked', defaultMessage: 'Bookmark removed.' },
|
||||
@ -380,9 +386,10 @@ const fetchReblogs = (id: string) =>
|
||||
dispatch(fetchReblogsRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
|
||||
dispatch(fetchReblogsSuccess(id, response.data));
|
||||
dispatch(fetchReblogsSuccess(id, response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(fetchReblogsFail(id, error));
|
||||
});
|
||||
@ -393,10 +400,11 @@ const fetchReblogsRequest = (id: string) => ({
|
||||
id,
|
||||
});
|
||||
|
||||
const fetchReblogsSuccess = (id: string, accounts: APIEntity[]) => ({
|
||||
const fetchReblogsSuccess = (id: string, accounts: APIEntity[], next: string | null) => ({
|
||||
type: REBLOGS_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
});
|
||||
|
||||
const fetchReblogsFail = (id: string, error: AxiosError) => ({
|
||||
@ -405,6 +413,31 @@ const fetchReblogsFail = (id: string, error: AxiosError) => ({
|
||||
error,
|
||||
});
|
||||
|
||||
const expandReblogs = (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));
|
||||
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
|
||||
dispatch(expandReblogsSuccess(id, response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(expandReblogsFail(id, error));
|
||||
});
|
||||
};
|
||||
|
||||
const expandReblogsSuccess = (id: string, accounts: APIEntity[], next: string | null) => ({
|
||||
type: REBLOGS_EXPAND_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
});
|
||||
|
||||
const expandReblogsFail = (id: string, error: AxiosError) => ({
|
||||
type: REBLOGS_EXPAND_FAIL,
|
||||
id,
|
||||
error,
|
||||
});
|
||||
|
||||
const fetchFavourites = (id: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
@ -412,9 +445,10 @@ const fetchFavourites = (id: string) =>
|
||||
dispatch(fetchFavouritesRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
|
||||
dispatch(fetchFavouritesSuccess(id, response.data));
|
||||
dispatch(fetchFavouritesSuccess(id, response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(fetchFavouritesFail(id, error));
|
||||
});
|
||||
@ -425,10 +459,11 @@ const fetchFavouritesRequest = (id: string) => ({
|
||||
id,
|
||||
});
|
||||
|
||||
const fetchFavouritesSuccess = (id: string, accounts: APIEntity[]) => ({
|
||||
const fetchFavouritesSuccess = (id: string, accounts: APIEntity[], next: string | null) => ({
|
||||
type: FAVOURITES_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
});
|
||||
|
||||
const fetchFavouritesFail = (id: string, error: AxiosError) => ({
|
||||
@ -437,6 +472,31 @@ const fetchFavouritesFail = (id: string, error: AxiosError) => ({
|
||||
error,
|
||||
});
|
||||
|
||||
const expandFavourites = (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));
|
||||
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
|
||||
dispatch(expandFavouritesSuccess(id, response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(expandFavouritesFail(id, error));
|
||||
});
|
||||
};
|
||||
|
||||
const expandFavouritesSuccess = (id: string, accounts: APIEntity[], next: string | null) => ({
|
||||
type: FAVOURITES_EXPAND_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
});
|
||||
|
||||
const expandFavouritesFail = (id: string, error: AxiosError) => ({
|
||||
type: FAVOURITES_EXPAND_FAIL,
|
||||
id,
|
||||
error,
|
||||
});
|
||||
|
||||
const fetchDislikes = (id: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
@ -669,6 +729,10 @@ export {
|
||||
REMOTE_INTERACTION_REQUEST,
|
||||
REMOTE_INTERACTION_SUCCESS,
|
||||
REMOTE_INTERACTION_FAIL,
|
||||
FAVOURITES_EXPAND_SUCCESS,
|
||||
FAVOURITES_EXPAND_FAIL,
|
||||
REBLOGS_EXPAND_SUCCESS,
|
||||
REBLOGS_EXPAND_FAIL,
|
||||
reblog,
|
||||
unreblog,
|
||||
toggleReblog,
|
||||
@ -709,10 +773,12 @@ export {
|
||||
fetchReblogsRequest,
|
||||
fetchReblogsSuccess,
|
||||
fetchReblogsFail,
|
||||
expandReblogs,
|
||||
fetchFavourites,
|
||||
fetchFavouritesRequest,
|
||||
fetchFavouritesSuccess,
|
||||
fetchFavouritesFail,
|
||||
expandFavourites,
|
||||
fetchDislikes,
|
||||
fetchDislikesRequest,
|
||||
fetchDislikesSuccess,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchFavourites } from 'soapbox/actions/interactions';
|
||||
import { fetchFavourites, expandFavourites } from 'soapbox/actions/interactions';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Modal, Spinner } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
@ -16,6 +16,7 @@ const FavouritesModal: React.FC<IFavouritesModal> = ({ onClose, statusId }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const accountIds = useAppSelector((state) => state.user_lists.favourited_by.get(statusId)?.items);
|
||||
const next = useAppSelector((state) => state.user_lists.favourited_by.get(statusId)?.next);
|
||||
|
||||
const fetchData = () => {
|
||||
dispatch(fetchFavourites(statusId));
|
||||
@ -29,6 +30,12 @@ const FavouritesModal: React.FC<IFavouritesModal> = ({ onClose, statusId }) => {
|
||||
onClose('FAVOURITES');
|
||||
};
|
||||
|
||||
const handleLoadMore = () => {
|
||||
if (next) {
|
||||
dispatch(expandFavourites(statusId, next!));
|
||||
}
|
||||
};
|
||||
|
||||
let body;
|
||||
|
||||
if (!accountIds) {
|
||||
@ -42,6 +49,10 @@ const FavouritesModal: React.FC<IFavouritesModal> = ({ onClose, statusId }) => {
|
||||
emptyMessage={emptyMessage}
|
||||
className='max-w-full'
|
||||
itemClassName='pb-3'
|
||||
style={{ height: '80vh' }}
|
||||
useWindowScroll={false}
|
||||
onLoadMore={handleLoadMore}
|
||||
hasMore={!!next}
|
||||
>
|
||||
{accountIds.map(id =>
|
||||
<AccountContainer key={id} id={id} />,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchReblogs } from 'soapbox/actions/interactions';
|
||||
import { fetchReblogs, expandReblogs } from 'soapbox/actions/interactions';
|
||||
import { fetchStatus } from 'soapbox/actions/statuses';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Modal, Spinner } from 'soapbox/components/ui';
|
||||
@ -16,6 +16,7 @@ interface IReblogsModal {
|
||||
const ReblogsModal: React.FC<IReblogsModal> = ({ onClose, statusId }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const accountIds = useAppSelector((state) => state.user_lists.reblogged_by.get(statusId)?.items);
|
||||
const next = useAppSelector((state) => state.user_lists.reblogged_by.get(statusId)?.next);
|
||||
|
||||
const fetchData = () => {
|
||||
dispatch(fetchReblogs(statusId));
|
||||
@ -30,6 +31,12 @@ const ReblogsModal: React.FC<IReblogsModal> = ({ onClose, statusId }) => {
|
||||
onClose('REBLOGS');
|
||||
};
|
||||
|
||||
const handleLoadMore = () => {
|
||||
if (next) {
|
||||
dispatch(expandReblogs(statusId, next!));
|
||||
}
|
||||
};
|
||||
|
||||
let body;
|
||||
|
||||
if (!accountIds) {
|
||||
@ -43,6 +50,10 @@ const ReblogsModal: React.FC<IReblogsModal> = ({ onClose, statusId }) => {
|
||||
emptyMessage={emptyMessage}
|
||||
className='max-w-full'
|
||||
itemClassName='pb-3'
|
||||
style={{ height: '80vh' }}
|
||||
useWindowScroll={false}
|
||||
onLoadMore={handleLoadMore}
|
||||
hasMore={!!next}
|
||||
>
|
||||
{accountIds.map((id) =>
|
||||
<AccountContainer key={id} id={id} />,
|
||||
|
||||
@ -59,7 +59,9 @@ import {
|
||||
} from 'soapbox/actions/groups';
|
||||
import {
|
||||
REBLOGS_FETCH_SUCCESS,
|
||||
REBLOGS_EXPAND_SUCCESS,
|
||||
FAVOURITES_FETCH_SUCCESS,
|
||||
FAVOURITES_EXPAND_SUCCESS,
|
||||
DISLIKES_FETCH_SUCCESS,
|
||||
REACTIONS_FETCH_SUCCESS,
|
||||
} from 'soapbox/actions/interactions';
|
||||
@ -172,9 +174,13 @@ export default function userLists(state = ReducerRecord(), action: AnyAction) {
|
||||
case FOLLOWING_EXPAND_SUCCESS:
|
||||
return appendToList(state, ['following', action.id], action.accounts, action.next);
|
||||
case REBLOGS_FETCH_SUCCESS:
|
||||
return normalizeList(state, ['reblogged_by', action.id], action.accounts);
|
||||
return normalizeList(state, ['reblogged_by', action.id], action.accounts, action.next);
|
||||
case REBLOGS_EXPAND_SUCCESS:
|
||||
return appendToList(state, ['reblogged_by', action.id], action.accounts, action.next);
|
||||
case FAVOURITES_FETCH_SUCCESS:
|
||||
return normalizeList(state, ['favourited_by', action.id], action.accounts);
|
||||
return normalizeList(state, ['favourited_by', action.id], action.accounts, action.next);
|
||||
case FAVOURITES_EXPAND_SUCCESS:
|
||||
return appendToList(state, ['favourited_by', action.id], action.accounts, action.next);
|
||||
case DISLIKES_FETCH_SUCCESS:
|
||||
return normalizeList(state, ['disliked_by', action.id], action.accounts);
|
||||
case REACTIONS_FETCH_SUCCESS:
|
||||
|
||||
Reference in New Issue
Block a user