feat(bookmarks): client plumbing — saver capture + bookmark api

This commit is contained in:
2026-09-08 01:04:44 +08:00
parent 0fe3bc3057
commit b2c5c4a445
5 changed files with 31 additions and 4 deletions
+4
View File
@@ -7,12 +7,14 @@ export type ProgressSend = (
export interface ProgressSaver {
report: (locator: Record<string, unknown>, percent: number) => void;
flush: () => void;
at: () => { loc: Record<string, unknown>; pct: number } | null;
}
// spec §8:PUT 节流 5s(leading-edge + 尾部合并);关页兜底走 keepalive fetch
//(spec 原文 sendBeacon,但 beacon 无法带 Authorization,后端 Bearer-only,语义等价替换)
export function createProgressSaver(send: ProgressSend, intervalMs = 5000): ProgressSaver {
let lastKey = "";
let cur: { loc: Record<string, unknown>; pct: number } | null = null;
let pending: { loc: Record<string, unknown>; pct: number } | null = null;
let timer: ReturnType<typeof setTimeout> | null = null;
let lastAt = 0;
@@ -31,6 +33,7 @@ export function createProgressSaver(send: ProgressSend, intervalMs = 5000): Prog
return {
report(locator, percent) {
cur = { loc: locator, pct: percent };
pending = { loc: locator, pct: percent };
if (timer) return; // 已有尾部定时器:只更新挂起值
const t = Date.now();
@@ -53,5 +56,6 @@ export function createProgressSaver(send: ProgressSend, intervalMs = 5000): Prog
lastAt = Date.now();
doSend(true);
},
at: () => cur,
};
}
+10 -2
View File
@@ -13,10 +13,14 @@ export interface Chrome {
export interface ReaderProps {
book: Book;
initialLocator?: Record<string, unknown>;
initialPercent?: number;
chrome: Chrome;
}
export function useProgressSaver(bookId: number): ProgressSaver {
export function useProgressSaver(
bookId: number,
seed?: { locator?: Record<string, unknown>; percent?: number },
): ProgressSaver & { capture: () => { locator: Record<string, unknown>; percent: number } } {
const qc = useQueryClient();
const saver = useMemo(
() =>
@@ -26,6 +30,10 @@ export function useProgressSaver(bookId: number): ProgressSaver {
}),
[bookId, qc],
);
const capture = () => {
const cur = saver.at();
return cur ? { locator: cur.loc, percent: cur.pct } : { locator: seed?.locator ?? {}, percent: seed?.percent ?? 0 };
};
useEffect(() => {
const onPageHide = () => saver.flush();
@@ -41,5 +49,5 @@ export function useProgressSaver(bookId: number): ProgressSaver {
};
}, [saver]);
return saver;
return Object.assign(saver, { capture });
}