diff options
| author | Fuwn <[email protected]> | 2026-02-12 03:45:49 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-12 03:45:49 -0800 |
| commit | 369e7ef2d19f5656391a894e7b0e55e6d849776e (patch) | |
| tree | 825fff793bf5fa952a1d814656f04f9af1b4f88b /apps/web | |
| parent | fix: use singular "entry" in mark-as-read toast when count is 1 (diff) | |
| download | asa.news-369e7ef2d19f5656391a894e7b0e55e6d849776e.tar.xz asa.news-369e7ef2d19f5656391a894e7b0e55e6d849776e.zip | |
fix: prioritise unread entries server-side so they appear in all-entries view
Diffstat (limited to 'apps/web')
| -rw-r--r-- | apps/web/app/reader/_components/entry-list.tsx | 27 | ||||
| -rw-r--r-- | apps/web/lib/queries/query-keys.ts | 4 | ||||
| -rw-r--r-- | apps/web/lib/queries/use-timeline.ts | 24 |
3 files changed, 31 insertions, 24 deletions
diff --git a/apps/web/app/reader/_components/entry-list.tsx b/apps/web/app/reader/_components/entry-list.tsx index 7786e55..ee2dad2 100644 --- a/apps/web/app/reader/_components/entry-list.tsx +++ b/apps/web/app/reader/_components/entry-list.tsx @@ -20,12 +20,14 @@ function useEntryData( feedFilter: "all" | "saved", folderIdentifier?: string | null, feedIdentifier?: string | null, - customFeedIdentifier?: string | null + customFeedIdentifier?: string | null, + prioritiseUnread?: boolean ) { const timelineQuery = useTimeline( feedFilter === "all" && !customFeedIdentifier ? folderIdentifier : undefined, feedFilter === "all" && !customFeedIdentifier ? feedIdentifier : undefined, - false + false, + prioritiseUnread ) const savedQuery = useSavedEntries() const customFeedQuery = useCustomFeedTimeline( @@ -49,8 +51,12 @@ export function EntryList({ feedIdentifier, customFeedIdentifier, }: EntryListProperties) { + const prioritiseUnreadEntries = useUserInterfaceStore( + (state) => state.prioritiseUnreadEntries + ) + const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = - useEntryData(feedFilter, folderIdentifier, feedIdentifier, customFeedIdentifier) + useEntryData(feedFilter, folderIdentifier, feedIdentifier, customFeedIdentifier, prioritiseUnreadEntries) const entryListViewMode = useUserInterfaceStore( (state) => state.entryListViewMode @@ -72,20 +78,9 @@ export function EntryList({ (state) => state.setNavigableEntryIdentifiers ) - const prioritiseUnreadEntries = useUserInterfaceStore( - (state) => state.prioritiseUnreadEntries - ) - const allEntries = useMemo(() => { - const flatEntries = data?.pages.flatMap((page) => page) ?? [] - - if (!prioritiseUnreadEntries) return flatEntries - - const unreadEntries = flatEntries.filter((entry) => !entry.isRead) - const readEntries = flatEntries.filter((entry) => entry.isRead) - - return [...unreadEntries, ...readEntries] - }, [data, prioritiseUnreadEntries]) + return data?.pages.flatMap((page) => page) ?? [] + }, [data]) const scrollContainerReference = useRef<HTMLDivElement>(null) const firstEntryIdentifier = allEntries[0]?.entryIdentifier diff --git a/apps/web/lib/queries/query-keys.ts b/apps/web/lib/queries/query-keys.ts index 8c1098e..d893165 100644 --- a/apps/web/lib/queries/query-keys.ts +++ b/apps/web/lib/queries/query-keys.ts @@ -1,8 +1,8 @@ export const queryKeys = { timeline: { all: ["timeline"] as const, - list: (folderIdentifier?: string | null, feedIdentifier?: string | null, unreadOnly?: boolean) => - ["timeline", { folderIdentifier, feedIdentifier, unreadOnly }] as const, + list: (folderIdentifier?: string | null, feedIdentifier?: string | null, unreadOnly?: boolean, prioritiseUnread?: boolean) => + ["timeline", { folderIdentifier, feedIdentifier, unreadOnly, prioritiseUnread }] as const, }, savedEntries: { all: ["saved-entries"] as const, diff --git a/apps/web/lib/queries/use-timeline.ts b/apps/web/lib/queries/use-timeline.ts index 5a38aba..cb1f099 100644 --- a/apps/web/lib/queries/use-timeline.ts +++ b/apps/web/lib/queries/use-timeline.ts @@ -43,36 +43,48 @@ function mapRowToTimelineEntry(row: TimelineRow): TimelineEntry { } } +interface TimelineCursor { + publishedAt: string + isRead: boolean +} + export function useTimeline( folderIdentifier?: string | null, feedIdentifier?: string | null, - unreadOnly?: boolean + unreadOnly?: boolean, + prioritiseUnread?: boolean ) { const supabaseClient = createSupabaseBrowserClient() return useInfiniteQuery({ - queryKey: queryKeys.timeline.list(folderIdentifier, feedIdentifier, unreadOnly), + queryKey: queryKeys.timeline.list(folderIdentifier, feedIdentifier, unreadOnly, prioritiseUnread), queryFn: async ({ pageParam, }: { - pageParam: string | undefined + pageParam: TimelineCursor | undefined }) => { const { data, error } = await supabaseClient.rpc("get_timeline", { target_folder_id: folderIdentifier ?? undefined, target_feed_id: feedIdentifier ?? undefined, result_limit: TIMELINE_PAGE_SIZE, - pagination_cursor: pageParam ?? undefined, + pagination_cursor: pageParam?.publishedAt ?? undefined, unread_only: unreadOnly ?? false, + prioritise_unread: prioritiseUnread ?? false, + cursor_is_read: pageParam?.isRead ?? undefined, }) if (error) throw error return ((data as TimelineRow[]) ?? []).map(mapRowToTimelineEntry) }, - initialPageParam: undefined as string | undefined, + initialPageParam: undefined as TimelineCursor | undefined, getNextPageParam: (lastPage: TimelineEntry[]) => { if (lastPage.length < TIMELINE_PAGE_SIZE) return undefined - return lastPage[lastPage.length - 1].publishedAt + const lastEntry = lastPage[lastPage.length - 1] + return { + publishedAt: lastEntry.publishedAt, + isRead: lastEntry.isRead, + } }, }) } |