diff --git a/app/soapbox/actions/timelines.ts b/app/soapbox/actions/timelines.ts index 902b99f70..b555a3b38 100644 --- a/app/soapbox/actions/timelines.ts +++ b/app/soapbox/actions/timelines.ts @@ -221,29 +221,29 @@ const expandHomeTimeline = ({ url, accountId, maxId }: ExpandHomeTimelineOpts = return expandTimeline('home', endpoint, params, done); }; -const expandPublicTimeline = ({ maxId, onlyMedia }: Record = {}, done = noOp) => - expandTimeline(`public${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { max_id: maxId, only_media: !!onlyMedia }, done); +const expandPublicTimeline = ({ url, maxId, onlyMedia }: Record = {}, done = noOp) => + expandTimeline(`public${onlyMedia ? ':media' : ''}`, url || '/api/v1/timelines/public', url ? {} : { max_id: maxId, only_media: !!onlyMedia }, done); -const expandRemoteTimeline = (instance: string, { maxId, onlyMedia }: Record = {}, done = noOp) => - expandTimeline(`remote${onlyMedia ? ':media' : ''}:${instance}`, '/api/v1/timelines/public', { local: false, instance: instance, max_id: maxId, only_media: !!onlyMedia }, done); +const expandRemoteTimeline = (instance: string, { url, maxId, onlyMedia }: Record = {}, done = noOp) => + expandTimeline(`remote${onlyMedia ? ':media' : ''}:${instance}`, url || '/api/v1/timelines/public', url ? {} : { local: false, instance: instance, max_id: maxId, only_media: !!onlyMedia }, done); -const expandCommunityTimeline = ({ maxId, onlyMedia }: Record = {}, done = noOp) => - expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done); +const expandCommunityTimeline = ({ url, maxId, onlyMedia }: Record = {}, done = noOp) => + expandTimeline(`community${onlyMedia ? ':media' : ''}`, url || '/api/v1/timelines/public', url ? {} : { local: true, max_id: maxId, only_media: !!onlyMedia }, done); -const expandDirectTimeline = ({ maxId }: Record = {}, done = noOp) => - expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done); +const expandDirectTimeline = ({ url, maxId }: Record = {}, done = noOp) => + expandTimeline('direct', url || '/api/v1/timelines/direct', url ? {} : { max_id: maxId }, done); -const expandAccountTimeline = (accountId: string, { maxId, withReplies }: Record = {}) => - expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId, with_muted: true }); +const expandAccountTimeline = (accountId: string, { url, maxId, withReplies }: Record = {}) => + expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, url || `/api/v1/accounts/${accountId}/statuses`, url ? {} : { exclude_replies: !withReplies, max_id: maxId, with_muted: true }); const expandAccountFeaturedTimeline = (accountId: string) => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, with_muted: true }); -const expandAccountMediaTimeline = (accountId: string | number, { maxId }: Record = {}) => - expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40, with_muted: true }); +const expandAccountMediaTimeline = (accountId: string | number, { url, maxId }: Record = {}) => + expandTimeline(`account:${accountId}:media`, url || `/api/v1/accounts/${accountId}/statuses`, url ? {} : { max_id: maxId, only_media: true, limit: 40, with_muted: true }); -const expandListTimeline = (id: string, { maxId }: Record = {}, done = noOp) => - expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done); +const expandListTimeline = (id: string, { url, maxId }: Record = {}, done = noOp) => + expandTimeline(`list:${id}`, url || `/api/v1/timelines/list/${id}`, url ? {} : { max_id: maxId }, done); const expandGroupTimeline = (id: string, { maxId }: Record = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { max_id: maxId }, done); @@ -254,8 +254,8 @@ const expandGroupTimelineFromTag = (id: string, tagName: string, { maxId }: Reco const expandGroupMediaTimeline = (id: string | number, { maxId }: Record = {}) => expandTimeline(`group:${id}:media`, `/api/v1/timelines/group/${id}`, { max_id: maxId, only_media: true, limit: 40, with_muted: true }); -const expandHashtagTimeline = (hashtag: string, { maxId, tags }: Record = {}, done = noOp) => { - return expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, { +const expandHashtagTimeline = (hashtag: string, { url, maxId, tags }: Record = {}, done = noOp) => { + return expandTimeline(`hashtag:${hashtag}`, url || `/api/v1/timelines/tag/${hashtag}`, url ? {} : { max_id: maxId, any: parseTags(tags, 'any'), all: parseTags(tags, 'all'), diff --git a/app/soapbox/features/account-gallery/index.tsx b/app/soapbox/features/account-gallery/index.tsx index 7cee5c569..86a832a36 100644 --- a/app/soapbox/features/account-gallery/index.tsx +++ b/app/soapbox/features/account-gallery/index.tsx @@ -64,6 +64,7 @@ const AccountGallery = () => { const attachments: ImmutableList = useAppSelector((state) => getAccountGallery(state, accountId as string)); const isLoading = useAppSelector((state) => state.timelines.get(`account:${accountId}:media`)?.isLoading); const hasMore = useAppSelector((state) => state.timelines.get(`account:${accountId}:media`)?.hasMore); + const next = useAppSelector(state => state.timelines.get(`account:${accountId}:media`)?.next); const node = useRef(null); @@ -75,7 +76,7 @@ const AccountGallery = () => { const handleLoadMore = (maxId: string | null) => { if (accountId && accountId !== -1) { - dispatch(expandAccountMediaTimeline(accountId, { maxId })); + dispatch(expandAccountMediaTimeline(accountId, { url: next, maxId })); } }; diff --git a/app/soapbox/features/account-timeline/index.tsx b/app/soapbox/features/account-timeline/index.tsx index 4f8ccc211..e3f5ca3e7 100644 --- a/app/soapbox/features/account-timeline/index.tsx +++ b/app/soapbox/features/account-timeline/index.tsx @@ -40,6 +40,7 @@ const AccountTimeline: React.FC = ({ params, withReplies = fal const patronEnabled = soapboxConfig.getIn(['extensions', 'patron', 'enabled']) === true; const isLoading = useAppSelector(state => state.getIn(['timelines', `account:${path}`, 'isLoading']) === true); const hasMore = useAppSelector(state => state.getIn(['timelines', `account:${path}`, 'hasMore']) === true); + const next = useAppSelector(state => state.timelines.get(`account:${path}`)?.next); const accountUsername = account?.username || params.username; @@ -69,7 +70,7 @@ const AccountTimeline: React.FC = ({ params, withReplies = fal const handleLoadMore = (maxId: string) => { if (account) { - dispatch(expandAccountTimeline(account.id, { maxId, withReplies })); + dispatch(expandAccountTimeline(account.id, { url: next, maxId, withReplies })); } }; diff --git a/app/soapbox/features/community-timeline/index.tsx b/app/soapbox/features/community-timeline/index.tsx index 3fca53cc5..387297a80 100644 --- a/app/soapbox/features/community-timeline/index.tsx +++ b/app/soapbox/features/community-timeline/index.tsx @@ -5,7 +5,7 @@ import { connectCommunityStream } from 'soapbox/actions/streaming'; import { expandCommunityTimeline } from 'soapbox/actions/timelines'; import PullToRefresh from 'soapbox/components/pull-to-refresh'; import { Column } from 'soapbox/components/ui'; -import { useAppDispatch, useSettings } from 'soapbox/hooks'; +import { useAppSelector, useAppDispatch, useSettings } from 'soapbox/hooks'; import Timeline from '../ui/components/timeline'; @@ -19,11 +19,12 @@ const CommunityTimeline = () => { const settings = useSettings(); const onlyMedia = settings.getIn(['community', 'other', 'onlyMedia']); + const next = useAppSelector(state => state.timelines.get('community')?.next); const timelineId = 'community'; const handleLoadMore = (maxId: string) => { - dispatch(expandCommunityTimeline({ maxId, onlyMedia })); + dispatch(expandCommunityTimeline({ url: next, maxId, onlyMedia })); }; const handleRefresh = () => { diff --git a/app/soapbox/features/direct-timeline/index.tsx b/app/soapbox/features/direct-timeline/index.tsx index aef932516..eee31a829 100644 --- a/app/soapbox/features/direct-timeline/index.tsx +++ b/app/soapbox/features/direct-timeline/index.tsx @@ -6,7 +6,7 @@ import { connectDirectStream } from 'soapbox/actions/streaming'; import { expandDirectTimeline } from 'soapbox/actions/timelines'; import AccountSearch from 'soapbox/components/account-search'; import { Column } from 'soapbox/components/ui'; -import { useAppDispatch } from 'soapbox/hooks'; +import { useAppSelector, useAppDispatch } from 'soapbox/hooks'; import Timeline from '../ui/components/timeline'; @@ -18,6 +18,7 @@ const messages = defineMessages({ const DirectTimeline = () => { const intl = useIntl(); const dispatch = useAppDispatch(); + const next = useAppSelector(state => state.timelines.get('direct')?.next); useEffect(() => { dispatch(expandDirectTimeline()); @@ -33,7 +34,7 @@ const DirectTimeline = () => { }; const handleLoadMore = (maxId: string) => { - dispatch(expandDirectTimeline({ maxId })); + dispatch(expandDirectTimeline({ url: next, maxId })); }; return ( diff --git a/app/soapbox/features/hashtag-timeline/index.tsx b/app/soapbox/features/hashtag-timeline/index.tsx index e448bef8a..bf906ce01 100644 --- a/app/soapbox/features/hashtag-timeline/index.tsx +++ b/app/soapbox/features/hashtag-timeline/index.tsx @@ -39,6 +39,7 @@ export const HashtagTimeline: React.FC = ({ params }) => { const dispatch = useAppDispatch(); const disconnects = useRef<(() => void)[]>([]); const tag = useAppSelector((state) => state.tags.get(id)); + const next = useAppSelector(state => state.timelines.get(`hashtag:${id}`)?.next); // Mastodon supports displaying results from multiple hashtags. // https://github.com/mastodon/mastodon/issues/6359 @@ -89,7 +90,7 @@ export const HashtagTimeline: React.FC = ({ params }) => { }; const handleLoadMore = (maxId: string) => { - dispatch(expandHashtagTimeline(id, { maxId, tags })); + dispatch(expandHashtagTimeline(id, { url: next, maxId, tags })); }; const handleFollow = () => { diff --git a/app/soapbox/features/list-timeline/index.tsx b/app/soapbox/features/list-timeline/index.tsx index 9751f2440..f16acf18b 100644 --- a/app/soapbox/features/list-timeline/index.tsx +++ b/app/soapbox/features/list-timeline/index.tsx @@ -17,6 +17,7 @@ const ListTimeline: React.FC = () => { const { id } = useParams<{ id: string }>(); const list = useAppSelector((state) => state.lists.get(id)); + const next = useAppSelector(state => state.timelines.get(`list:${id}`)?.next); useEffect(() => { dispatch(fetchList(id)); @@ -30,7 +31,7 @@ const ListTimeline: React.FC = () => { }, [id]); const handleLoadMore = (maxId: string) => { - dispatch(expandListTimeline(id, { maxId })); + dispatch(expandListTimeline(id, { url: next, maxId })); }; const handleEditClick = () => { diff --git a/app/soapbox/features/public-timeline/index.tsx b/app/soapbox/features/public-timeline/index.tsx index 8f96e432d..cad8cd7f6 100644 --- a/app/soapbox/features/public-timeline/index.tsx +++ b/app/soapbox/features/public-timeline/index.tsx @@ -7,7 +7,7 @@ import { connectPublicStream } from 'soapbox/actions/streaming'; import { expandPublicTimeline } from 'soapbox/actions/timelines'; import PullToRefresh from 'soapbox/components/pull-to-refresh'; import { Accordion, Column } from 'soapbox/components/ui'; -import { useAppDispatch, useInstance, useSettings } from 'soapbox/hooks'; +import { useAppSelector, useAppDispatch, useInstance, useSettings } from 'soapbox/hooks'; import PinnedHostsPicker from '../remote-timeline/components/pinned-hosts-picker'; import Timeline from '../ui/components/timeline'; @@ -24,6 +24,7 @@ const CommunityTimeline = () => { const instance = useInstance(); const settings = useSettings(); const onlyMedia = settings.getIn(['public', 'other', 'onlyMedia']); + const next = useAppSelector(state => state.timelines.get('public')?.next); const timelineId = 'public'; @@ -39,7 +40,7 @@ const CommunityTimeline = () => { }; const handleLoadMore = (maxId: string) => { - dispatch(expandPublicTimeline({ maxId, onlyMedia })); + dispatch(expandPublicTimeline({ url: next, maxId, onlyMedia })); }; const handleRefresh = () => { diff --git a/app/soapbox/features/remote-timeline/index.tsx b/app/soapbox/features/remote-timeline/index.tsx index 3283078af..b0afd38a8 100644 --- a/app/soapbox/features/remote-timeline/index.tsx +++ b/app/soapbox/features/remote-timeline/index.tsx @@ -6,7 +6,7 @@ import { connectRemoteStream } from 'soapbox/actions/streaming'; import { expandRemoteTimeline } from 'soapbox/actions/timelines'; import IconButton from 'soapbox/components/icon-button'; import { Column, HStack, Text } from 'soapbox/components/ui'; -import { useAppDispatch, useSettings } from 'soapbox/hooks'; +import { useAppSelector, useAppDispatch, useSettings } from 'soapbox/hooks'; import Timeline from '../ui/components/timeline'; @@ -30,6 +30,7 @@ const RemoteTimeline: React.FC = ({ params }) => { const timelineId = 'remote'; const onlyMedia = !!settings.getIn(['remote', 'other', 'onlyMedia']); + const next = useAppSelector(state => state.timelines.get('remote')?.next); const pinned: boolean = (settings.getIn(['remote_timeline', 'pinnedHosts']) as any).includes(instance); @@ -44,7 +45,7 @@ const RemoteTimeline: React.FC = ({ params }) => { }; const handleLoadMore = (maxId: string) => { - dispatch(expandRemoteTimeline(instance, { maxId, onlyMedia })); + dispatch(expandRemoteTimeline(instance, { url: next, maxId, onlyMedia })); }; useEffect(() => {