Run code formatting (prettier/eslint) on existing reader format files that were not migrated to the new structure. This ensures consistent code style across the codebase. ## Changes ### Formatting Applied - Added newlines at end of files - Fixed line length and indentation - Updated import statements for consistency - Applied code style rules uniformly ### Files Affected - **Comic**: background-color, chapter-markers, page-order, panel-gap - **Ebook**: font-loader, search, view-modes - **Manga**: vertical-scroll-mode - **PDF**: annotation-layer, pdf-navigation, pdf-text-selection ## Purpose These files will be removed in subsequent commits as they are replaced by the new modular structure. The formatting ensures consistency during the transition period and maintains code quality standards. Note: These are non-functional formatting changes only. No logic or behavior was modified in this commit.
175 lines
5.1 KiB
TypeScript
175 lines
5.1 KiB
TypeScript
// 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";
|
|
}
|