"use client" import { useInfiniteQuery } from "@tanstack/react-query" import { createSupabaseBrowserClient } from "@/lib/supabase/client" import { queryKeys } from "./query-keys" import type { TimelineEntry } from "@/lib/types/timeline" const TIMELINE_PAGE_SIZE = 50 interface TimelineRow { entry_id: string feed_id: string feed_title: string custom_title: string | null entry_title: string entry_url: string author: string | null summary: string | null image_url: string | null published_at: string is_read: boolean is_saved: boolean enclosure_url: string | null enclosure_type: string | null } function mapRowToTimelineEntry(row: TimelineRow): TimelineEntry { return { entryIdentifier: row.entry_id, feedIdentifier: row.feed_id, feedTitle: row.feed_title, customTitle: row.custom_title, entryTitle: row.entry_title, entryUrl: row.entry_url, author: row.author, summary: row.summary, imageUrl: row.image_url, publishedAt: row.published_at, isRead: row.is_read, isSaved: row.is_saved, enclosureUrl: row.enclosure_url, enclosureType: row.enclosure_type, } } interface TimelineCursor { publishedAt: string isRead: boolean } export function useTimeline( folderIdentifier?: string | null, feedIdentifier?: string | null, unreadOnly?: boolean, prioritiseUnread?: boolean ) { const supabaseClient = createSupabaseBrowserClient() return useInfiniteQuery({ queryKey: queryKeys.timeline.list(folderIdentifier, feedIdentifier, unreadOnly, prioritiseUnread), queryFn: async ({ pageParam, }: { 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?.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 TimelineCursor | undefined, getNextPageParam: (lastPage: TimelineEntry[]) => { if (lastPage.length < TIMELINE_PAGE_SIZE) return undefined const lastEntry = lastPage[lastPage.length - 1] return { publishedAt: lastEntry.publishedAt, isRead: lastEntry.isRead, } }, }) }