tutu/src/masto/timelines.ts

92 lines
2.3 KiB
TypeScript
Raw Normal View History

2024-07-14 12:28:44 +00:00
import { type mastodon } from "masto";
import { Accessor, createEffect, createResource, createSignal } from "solid-js";
import { createStore } from "solid-js/store";
2024-07-14 12:28:44 +00:00
type TimelineFetchTips = {
direction?: "new" | "old";
};
type Timeline = {
list(params: {
maxId?: string;
minId?: string;
}): mastodon.Paginator<mastodon.v1.Status[], unknown>;
};
2024-08-05 07:33:00 +00:00
export function useTimeline(timeline: Accessor<Timeline>) {
2024-07-14 12:28:44 +00:00
let minId: string | undefined;
let maxId: string | undefined;
let otl: Timeline | undefined;
const idSet = new Set<string>();
const [snapshot, { refetch }] = createResource<
{ records: mastodon.v1.Status[]; direction: "old" | "new" },
2024-07-14 12:28:44 +00:00
[Timeline],
TimelineFetchTips | undefined
>(
() => [timeline()] as const,
async ([tl], info) => {
if (otl !== tl) {
minId = undefined;
maxId = undefined;
idSet.clear();
otl = tl;
}
const direction =
typeof info.refetching !== "boolean"
? info.refetching?.direction
: "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") {
minId = pager[pager.length - 1]?.id;
if (!maxId && pager.length > 0) {
maxId = pager[0].id;
}
return {
direction: "old" as const,
records: diff,
};
2024-07-14 12:28:44 +00:00
} else {
maxId = pager.length > 0 ? pager[0].id : undefined;
if (!minId && pager.length > 0) {
minId = pager[pager.length - 1]?.id;
}
return { direction: "new" as const, records: diff };
2024-07-14 12:28:44 +00:00
}
},
);
const [store, setStore] = createStore([] as mastodon.v1.Status[]);
createEffect(() => {
const shot = snapshot();
if (!shot) return;
const { direction, records } = shot;
if (direction == "new") {
setStore((x) => [...records, ...x]);
} else if (direction == "old") {
setStore((x) => [...x, ...records]);
}
});
return [
store,
snapshot,
2024-07-14 12:28:44 +00:00
{
refetch,
mutate: setStore,
2024-07-14 12:28:44 +00:00
},
] as const;
2024-07-14 12:28:44 +00:00
}