diff --git a/packages/nicolium/src/columns/timeline.tsx b/packages/nicolium/src/columns/timeline.tsx index b225e16c5..2ff447a69 100644 --- a/packages/nicolium/src/columns/timeline.tsx +++ b/packages/nicolium/src/columns/timeline.tsx @@ -3,7 +3,6 @@ import clsx from 'clsx'; import React, { useRef } from 'react'; import { defineMessages, FormattedList, FormattedMessage } from 'react-intl'; -import LoadMore from '@/components/load-more'; import ScrollTopButton from '@/components/scroll-top-button'; import ScrollableList from '@/components/scrollable-list'; import Status, { StatusFollowedTagInfo } from '@/components/statuses/status'; @@ -177,7 +176,6 @@ const TimelineStatus: React.FC = (props): React.JSX.Element =>
@@ -206,8 +204,16 @@ interface ITimeline { const Timeline: React.FC = ({ query, contextType = 'public' }) => { const node = useRef(null); - const { timelineId, entries, queuedCount, fetchNextPage, dequeueEntries, isFetching, isPending } = - query; + const { + timelineId, + entries, + queuedCount, + fetchNextPage, + dequeueEntries, + isFetching, + isPending, + hasNextPage, + } = query; const handleMoveUp = (index: number) => selectChild(index - 1, node, document.getElementById('status-list') ?? undefined); @@ -239,13 +245,6 @@ const Timeline: React.FC = ({ query, contextType = 'public' }) => { /> ); } - if ((entry.type === 'page-end' || entry.type === 'page-start') && !isFetching) { - return ( -
- -
- ); - } }; return ( @@ -266,7 +265,8 @@ const Timeline: React.FC = ({ query, contextType = 'public' }) => { placeholderComponent={() => } placeholderCount={20} ref={node} - hasMore + hasMore={hasNextPage} + onLoadMore={fetchNextPage} > {(entries || []).map(renderEntry)} diff --git a/packages/nicolium/src/queries/timelines/use-timeline.ts b/packages/nicolium/src/queries/timelines/use-timeline.ts index 5add2d601..1fb836c1b 100644 --- a/packages/nicolium/src/queries/timelines/use-timeline.ts +++ b/packages/nicolium/src/queries/timelines/use-timeline.ts @@ -38,11 +38,9 @@ const useTimeline = (timelineId: string, fetcher: TimelineFetcher, streamConfig? const fetchNextPage = useCallback(async () => { timelineActions.setLoading(timelineId, true); - const lastEntry = timeline.entries.at(-1); - if (!lastEntry || lastEntry.type !== 'page-end') return; try { - const response = await fetcher({ max_id: lastEntry.minId }); + const response = await fetcher({ max_id: timeline.oldestStatusId }); importEntities({ statuses: response.items }); @@ -50,7 +48,7 @@ const useTimeline = (timelineId: string, fetcher: TimelineFetcher, streamConfig? } catch (error) { // } - }, [timelineId, timeline.entries]); + }, [timelineId, timeline.oldestStatusId]); const dequeueEntries = useCallback(() => { timelineActions.dequeueEntries(timelineId); diff --git a/packages/nicolium/src/stores/timelines.ts b/packages/nicolium/src/stores/timelines.ts index 4ef9db422..11125161d 100644 --- a/packages/nicolium/src/stores/timelines.ts +++ b/packages/nicolium/src/stores/timelines.ts @@ -19,14 +19,6 @@ type TimelineEntry = type: 'gap'; sinceId: string; maxId: string; - } - | { - type: 'page-start'; - maxId?: string; - } - | { - type: 'page-end'; - minId?: string; }; interface TimelineData { @@ -35,6 +27,8 @@ interface TimelineData { queuedCount: number; isFetching: boolean; isPending: boolean; + hasNextPage: boolean; + oldestStatusId?: string; } interface State { @@ -43,8 +37,8 @@ interface State { expandTimeline: ( timelineId: string, statuses: Array, - hasMore: boolean, - initialFetch: boolean, + hasMore?: boolean, + initialFetch?: boolean, ) => void; receiveStreamingStatus: (timelineId: string, status: Status) => void; deleteStatus: (statusId: string) => void; @@ -53,7 +47,7 @@ interface State { }; } -const processPage = (statuses: Array, hasMore: boolean): Array => { +const processPage = (statuses: Array): Array => { const timelinePage: Array = []; const processStatus = (status: Status): boolean => { @@ -111,12 +105,6 @@ const processPage = (statuses: Array, hasMore: boolean): Array()( mutative((set) => ({ timelines: {} as Record, actions: { - expandTimeline: (timelineId, statuses, hasMore, initialFetch) => + expandTimeline: (timelineId, statuses, hasMore, initialFetch = false) => set((state) => { const timeline = state.timelines[timelineId] ?? createEmptyTimeline(); - const entries = processPage(statuses, hasMore); + const entries = processPage(statuses); - if (initialFetch) timeline.entries = []; - else if (timeline.entries.at(-1)?.type === 'page-end') timeline.entries.pop(); - timeline.entries.push(...entries); + if (initialFetch) timeline.entries = entries; + else timeline.entries.push(...entries); timeline.isPending = false; timeline.isFetching = false; + if (typeof hasMore === 'boolean') { + timeline.hasNextPage = hasMore; + const oldestStatus = statuses.at(-1); + if (oldestStatus) timeline.oldestStatusId = oldestStatus.id; + } state.timelines[timelineId] = timeline; }), receiveStreamingStatus: (timelineId, status) => { @@ -169,10 +161,11 @@ const useTimelinesStore = create()( }, setLoading: (timelineId, isFetching) => set((state) => { - const timeline = (state.timelines[timelineId] ??= createEmptyTimeline()); + const timeline = state.timelines[timelineId] ?? createEmptyTimeline(); timeline.isFetching = isFetching; if (!isFetching) timeline.isPending = false; + state.timelines[timelineId] = timeline; }), dequeueEntries: (timelineId) => set((state) => { @@ -180,7 +173,7 @@ const useTimelinesStore = create()( if (!timeline || timeline.queuedEntries.length === 0) return; - const processedEntries = processPage(timeline.queuedEntries, false); + const processedEntries = processPage(timeline.queuedEntries); timeline.entries.unshift(...processedEntries); timeline.queuedEntries = []; @@ -196,6 +189,8 @@ const createEmptyTimeline = (): TimelineData => ({ queuedCount: 0, isFetching: false, isPending: true, + hasNextPage: true, + oldestStatusId: undefined, }); const emptyTimeline = createEmptyTimeline(); diff --git a/packages/nicolium/src/styles/new/statuses.scss b/packages/nicolium/src/styles/new/statuses.scss index d2f11406f..cfbd99038 100644 --- a/packages/nicolium/src/styles/new/statuses.scss +++ b/packages/nicolium/src/styles/new/statuses.scss @@ -307,6 +307,16 @@ } } -.⁂-timeline-status--connected-bottom .status__content-wrapper { - padding-left: 54px; +.⁂-timeline-status { + &--connected-bottom .status__content-wrapper { + padding-left: 54px; + } + + &:not(.⁂-timeline-status--connected-bottom) { + @apply border-b border-solid border-gray-200 dark:border-gray-800; + } +} + +div:last-child > .⁂-timeline-status { + @apply border-b-0; }