import { type mastodon } from "masto"; import { Accessor, createResource, createSignal } from "solid-js"; type TimelineFetchTips = { direction?: "new" | "old"; }; type Timeline = { list(params: { maxId?: string; minId?: string; }): mastodon.Paginator; }; export function useTimeline( timeline: Accessor, ) { let minId: string | undefined; let maxId: string | undefined; let otl: Timeline | undefined; const idSet = new Set(); return createResource< mastodon.v1.Status[], [Timeline], TimelineFetchTips | undefined >( () => [timeline()] as const, async ([tl], info) => { if (otl !== tl) { minId = undefined; maxId = undefined; idSet.clear(); info.value = []; otl = tl; } const direction = typeof info.refetching !== "boolean" ? info.refetching?.direction : "old"; const pager = await tl.list( direction === "old" ? { maxId: minId, } : { minId: maxId, }, ); const old = info.value || []; const diff = pager.filter((x) => !idSet.has(x.id)); for (const v of diff.map((x) => x.id)) { idSet.add(v); } if (direction === "old") { minId = pager[pager.length - 1]?.id; if (!maxId && pager.length > 0) { maxId = pager[0].id; } return [...old, ...diff]; } else { maxId = pager.length > 0 ? pager[0].id : undefined; if (!minId && pager.length > 0) { minId = pager[pager.length - 1]?.id; } return [...diff, ...old]; } }, { initialValue: [], storage(init) { return createSignal(init, { equals: false }); }, }, ); }