import { type mastodon } from "masto"; import { Accessor, createEffect, createResource, createSignal } from "solid-js"; import { createStore } from "solid-js/store"; type TimelineFetchTips = { direction?: "new" | "old"; }; type Timeline = { list(params: { maxId?: string; minId?: string; }): mastodon.Paginator; }; export function useTimeline(timeline: Accessor) { let otl: Timeline | undefined; let npager: mastodon.Paginator | undefined; let opager: mastodon.Paginator | undefined; const [snapshot, { refetch }] = createResource< { records: mastodon.v1.Status[]; direction: "new" | "old"; tlChanged: boolean; }, [Timeline], TimelineFetchTips | undefined >( () => [timeline()] as const, async ([tl], info) => { let tlChanged = false; if (otl !== tl) { console.debug("timeline reset"); npager = opager = undefined; otl = tl; tlChanged = true; } const direction = typeof info.refetching !== "boolean" ? (info.refetching?.direction ?? "old") : "old"; if (direction === "old") { if (!opager) { opager = tl.list({}).setDirection("next"); } const next = await opager.next(); return { direction, records: next.value ?? [], end: next.done, tlChanged, }; } else { if (!npager) { npager = tl.list({}).setDirection("prev"); } const next = await npager.next(); const page = next.value ?? []; return { direction, records: page, end: next.done, tlChanged }; } }, ); const [store, setStore] = createStore([] as mastodon.v1.Status[]); createEffect(() => { const shot = snapshot(); if (!shot) return; const { direction, records, tlChanged } = shot; if (tlChanged) { setStore(() => []); } if (direction == "new") { setStore((x) => [...records, ...x]); } else if (direction == "old") { setStore((x) => [...x, ...records]); } }); return [ store, snapshot, { refetch, mutate: setStore, }, ] as const; }