useTimeline: use masto's Paginator

This commit is contained in:
thislight 2024-08-12 22:29:55 +08:00
parent e8fcc40bde
commit 88a81e4904

View file

@ -14,55 +14,49 @@ type Timeline = {
}; };
export function useTimeline(timeline: Accessor<Timeline>) { export function useTimeline(timeline: Accessor<Timeline>) {
let minId: string | undefined;
let maxId: string | undefined;
let otl: Timeline | undefined; let otl: Timeline | undefined;
const idSet = new Set<string>(); let npager: mastodon.Paginator<mastodon.v1.Status[], unknown> | undefined;
let opager: mastodon.Paginator<mastodon.v1.Status[], unknown> | undefined;
const [snapshot, { refetch }] = createResource< const [snapshot, { refetch }] = createResource<
{ records: mastodon.v1.Status[]; direction: "old" | "new" }, {
records: mastodon.v1.Status[];
direction: "new" | "old";
tlChanged: boolean;
},
[Timeline], [Timeline],
TimelineFetchTips | undefined TimelineFetchTips | undefined
>( >(
() => [timeline()] as const, () => [timeline()] as const,
async ([tl], info) => { async ([tl], info) => {
let tlChanged = false;
if (otl !== tl) { if (otl !== tl) {
minId = undefined; console.debug("timeline reset");
maxId = undefined; npager = opager = undefined;
idSet.clear();
otl = tl; otl = tl;
tlChanged = true;
} }
const direction = const direction =
typeof info.refetching !== "boolean" typeof info.refetching !== "boolean"
? info.refetching?.direction ? (info.refetching?.direction ?? "old")
: "old"; : "old";
const pager = await tl.list(
direction === "old"
? {
maxId: minId,
}
: {
minId: maxId,
},
);
const diff = pager.filter((x) => !idSet.has(x.id));
for (const v of diff.map((x) => x.id)) {
idSet.add(v);
}
if (direction === "old") { if (direction === "old") {
minId = pager[pager.length - 1]?.id; if (!opager) {
if (!maxId && pager.length > 0) { opager = tl.list({}).setDirection("next");
maxId = pager[0].id;
} }
const next = await opager.next();
return { return {
direction: "old" as const, direction,
records: diff, records: next.value ?? [],
end: next.done,
tlChanged,
}; };
} else { } else {
maxId = pager.length > 0 ? pager[0].id : undefined; if (!npager) {
if (!minId && pager.length > 0) { npager = tl.list({}).setDirection("prev");
minId = pager[pager.length - 1]?.id;
} }
return { direction: "new" as const, records: diff }; const next = await npager.next();
const page = next.value ?? [];
return { direction, records: page, end: next.done, tlChanged };
} }
}, },
); );
@ -72,7 +66,10 @@ export function useTimeline(timeline: Accessor<Timeline>) {
createEffect(() => { createEffect(() => {
const shot = snapshot(); const shot = snapshot();
if (!shot) return; if (!shot) return;
const { direction, records } = shot; const { direction, records, tlChanged } = shot;
if (tlChanged) {
setStore(() => []);
}
if (direction == "new") { if (direction == "new") {
setStore((x) => [...records, ...x]); setStore((x) => [...records, ...x]);
} else if (direction == "old") { } else if (direction == "old") {