// Different viewing modes for ebooks // Feature Registration Pattern implementation import { ReaderContext } from "../core/reader-context"; export function init(context: ReaderContext): void { let state: ViewModeState | null = null; context.events.on("reader:loaded", (detail: { container: HTMLElement }) => { state = { currentMode: "paginated", currentPage: 1 }; setViewMode(detail.container, "paginated"); }); context.events.on("view-mode:set", (detail: { mode: ViewMode }) => { if (state && context.elements.readerContent) { state.currentMode = detail.mode; setViewMode(context.elements.readerContent, detail.mode); context.events.emit("view-mode:changed", { mode: detail.mode }); } }); context.events.on("view-mode:get", () => { if (state) { context.events.emit("view-mode:current", state); } }); context.events.on("pagination:go-to-page", (detail: { page: number }) => { if (state && context.elements.readerContent) { state.currentPage = detail.page; goToPage(context.elements.readerContent, detail.page); context.events.emit("pagination:page-changed", { page: detail.page }); } }); } type ViewMode = "paginated" | "scrolled" | "single-column" | "double-column"; interface ViewModeState { currentMode: ViewMode; currentPage: number; } function setViewMode(container: HTMLElement, mode: ViewMode): void { const content = container.querySelector(".ebook-content"); if (!content) return; const element = content as HTMLElement; element.classList.remove( "paginated", "scrolled", "single-column", "double-column", ); switch (mode) { case "paginated": applyPaginatedMode(element); break; case "scrolled": applyScrolledMode(element); break; case "single-column": applySingleColumn(element); break; case "double-column": applyDoubleColumn(element); break; } } function applyPaginatedMode(element: HTMLElement): void { element.classList.add("paginated"); // Set up for CSS columns element.style.height = "calc(100vh - 120px)"; element.style.overflowY = "auto"; element.style.overflowX = "hidden"; element.style.columnCount = "1"; element.style.columnFill = "auto"; element.style.columnGap = "0"; element.style.position = "relative"; // Inject CSS for CSS column pagination injectPaginatedStyles(); } function injectPaginatedStyles(): void { // Remove existing injected styles if any const existing = document.getElementById("paginated-styles"); existing?.remove(); const style = document.createElement("style"); style.id = "paginated-styles"; style.textContent = ` .paginated { height: calc(100vh - 120px) !important; overflow-y: auto !important; overflow-x: hidden !important; column-fill: auto !important; column-count: 1 !important; column-gap: 0 !important; position: relative !important; } .paginated > * { max-width: 100%; column-fill: auto; } .paginated .ebook-content { height: auto !important; min-height: 100%; } `; document.head.appendChild(style); } function applyScrolledMode(element: HTMLElement): void { element.classList.add("scrolled"); element.style.height = "auto"; element.style.overflowY = "auto"; element.style.columnCount = "1"; } function applySingleColumn(element: HTMLElement): void { element.classList.add("single-column"); element.style.columnCount = "1"; element.style.columnGap = "0"; element.style.maxWidth = "800px"; element.style.margin = "0 auto"; } function applyDoubleColumn(element: HTMLElement): void { element.classList.add("double-column"); element.style.columnCount = "2"; element.style.columnGap = "60px"; element.style.columnRule = "1px solid var(--text-secondary)"; element.style.maxWidth = "1400px"; element.style.margin = "0 auto"; } function goToPage(container: HTMLElement, pageNumber: number): void { const content = container.querySelector(".ebook-content") as HTMLElement; if (!content) return; const totalPages = getTotalPageCount(container); const targetPage = Math.min(Math.max(1, pageNumber), totalPages); const viewportHeight = window.innerHeight - 120; const scrollTop = (targetPage - 1) * viewportHeight; content.scrollTo({ top: scrollTop, behavior: "smooth", }); } function getTotalPageCount(container: HTMLElement): number { const content = container.querySelector(".ebook-content") as HTMLElement; if (!content) return 1; const viewportHeight = window.innerHeight - 120; const contentHeight = content.scrollHeight; return Math.max(1, Math.ceil(contentHeight / viewportHeight)); } export function getCurrentViewMode(container: HTMLElement): ViewMode { const content = container.querySelector(".ebook-content") as HTMLElement; if (!content) return "paginated"; if (content.classList.contains("paginated")) return "paginated"; if (content.classList.contains("scrolled")) return "scrolled"; if (content.classList.contains("single-column")) return "single-column"; if (content.classList.contains("double-column")) return "double-column"; return "paginated"; }