// Track reading speed and update database // Feature Registration Pattern implementation import type { ReaderContext } from "./core/reader-context"; export function init(context: ReaderContext): void { let state: ReadingSpeedTrackerState | null = null; context.events.on("reader:loaded", (detail: { mediaItemId: string }) => { state = createReadingSpeedTracker(detail.mediaItemId); }); context.events.on("reading-session:start", () => { if (state) { startReadingSession(state); } }); context.events.on("page-changed", () => { if (state) { recordPageTurn(state); } }); context.events.on("words-read", (detail: { wordCount: number }) => { if (state) { recordWordsRead(state, detail.wordCount); } }); context.events.on("reading-session:end", async () => { if (state) { await syncReadingSpeed(state); } }); context.events.on("reader:unload", async () => { if (state) { await syncReadingSpeed(state); state = null; } }); } interface ReadingSpeedTrackerState { startTime: number | null; pagesRead: number; wordsRead: number; lastSync: number; mediaItemId: string; } function createReadingSpeedTracker( mediaItemId: string, ): ReadingSpeedTrackerState { return { startTime: null, pagesRead: 0, wordsRead: 0, lastSync: Date.now(), mediaItemId, }; } function startReadingSession( state: ReadingSpeedTrackerState, ): ReadingSpeedTrackerState { state.startTime = Date.now(); state.pagesRead = 0; state.wordsRead = 0; return state; } function recordPageTurn( state: ReadingSpeedTrackerState, ): ReadingSpeedTrackerState { if (!state.startTime) return state; state.pagesRead += 1; const now = Date.now(); if (state.pagesRead % 5 === 0 || now - state.lastSync > 5 * 60 * 1000) { syncReadingSpeed(state); state.lastSync = now; } return state; } function recordWordsRead( state: ReadingSpeedTrackerState, wordCount: number, ): ReadingSpeedTrackerState { state.wordsRead += wordCount; return state; } async function syncReadingSpeed( state: ReadingSpeedTrackerState, ): Promise { if (!state.startTime) return; const minutesElapsed = (Date.now() - state.startTime) / (1000 * 60); const pagesPerMinute = state.pagesRead / minutesElapsed; const wordsPerMinute = state.wordsRead / minutesElapsed; try { const token = localStorage.getItem("token"); await fetch(`/readers/${state.mediaItemId}/reading-speed`, { method: "PUT", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ pages_per_minute: pagesPerMinute, words_per_minute: wordsPerMinute, pages_read: state.pagesRead, total_reading_minutes: minutesElapsed, }), }); } catch (error) { console.error("Failed to sync reading speed:", error); } }