feat(frontend): reading stats store (TDD) + session heartbeat hook (B0)
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { createLocalStats, type StatsStore } from "./readingStats";
|
||||
|
||||
const TICK = 30; // 秒:可见期间心跳粒度
|
||||
|
||||
/** Reader 页挂一次:可见期间每 30s 落一笔,隐藏/卸载即 flush。 */
|
||||
export function useReadingSession(store: StatsStore = createLocalStats()) {
|
||||
const acc = useRef(0);
|
||||
const last = useRef(0);
|
||||
useEffect(() => {
|
||||
last.current = Date.now(); // 渲染期不取时钟,effect 内初始化起算点
|
||||
const flush = () => {
|
||||
const now = Date.now();
|
||||
if (document.visibilityState === "visible") acc.current += (now - last.current) / 1000;
|
||||
last.current = now;
|
||||
if (acc.current >= 1) {
|
||||
store.record(acc.current);
|
||||
acc.current = 0;
|
||||
}
|
||||
};
|
||||
const t = setInterval(flush, TICK * 1000);
|
||||
const onVis = () => flush();
|
||||
document.addEventListener("visibilitychange", onVis);
|
||||
globalThis.addEventListener?.("pagehide", onVis);
|
||||
return () => {
|
||||
clearInterval(t);
|
||||
document.removeEventListener("visibilitychange", onVis);
|
||||
globalThis.removeEventListener?.("pagehide", onVis);
|
||||
flush();
|
||||
};
|
||||
}, [store]);
|
||||
}
|
||||
Reference in New Issue
Block a user