2024-07-14 12:28:44 +00:00
|
|
|
import { type mastodon } from "masto";
|
2024-08-06 12:27:30 +00:00
|
|
|
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>();
|
2024-08-06 12:27:30 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-08-06 12:27:30 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-08-06 12:27:30 +00:00
|
|
|
return { direction: "new" as const, records: diff };
|
2024-07-14 12:28:44 +00:00
|
|
|
}
|
|
|
|
},
|
2024-08-06 12:27:30 +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
|
|
|
{
|
2024-08-06 12:27:30 +00:00
|
|
|
refetch,
|
|
|
|
mutate: setStore,
|
2024-07-14 12:28:44 +00:00
|
|
|
},
|
2024-08-06 12:27:30 +00:00
|
|
|
] as const;
|
2024-07-14 12:28:44 +00:00
|
|
|
}
|