reader: implement Feature Registration Pattern infrastructure
- Add Feature Registry system in reader-shell.ts to track features - Update format detection to use format_group with switch statement - Add manga detection via library_type_name or manga_type fields - Import and register features via init() functions on load - Fix parser imports in parser-manager.ts (add missing function imports) - Simplify epub-parsers and fb2-parser by removing unused imports
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
import { Alpine } from "../alpine";
|
||||
import { getReaderMetadata, updateReadingProgress } from "../api";
|
||||
import { getReaderMetadata } from "../api";
|
||||
import "./comic/panel-editor";
|
||||
import { createReaderContext, type ReaderContext } from "./core/reader-context";
|
||||
import { getState, setState } from "./core/reader-state";
|
||||
import { createNavigationAPI } from "./core/reader-navigation";
|
||||
import { readerEvents } from "./core/reader-events";
|
||||
|
||||
type ReaderType = "ebook" | "pdf" | "comic" | "manga";
|
||||
|
||||
interface UniversalReader {
|
||||
type: "ebook";
|
||||
cif: any;
|
||||
@@ -35,7 +34,7 @@ interface MangaReader {
|
||||
type CurrentReader = UniversalReader | PDFReader | ComicReader | MangaReader;
|
||||
|
||||
let currentReader: CurrentReader | null = null;
|
||||
let readerMetadata: import("../types/reader").ReaderMetadata | null = null;
|
||||
let readerMetadata: ReaderMetadata | null = null;
|
||||
|
||||
// ============================================================
|
||||
// Feature Registry
|
||||
@@ -90,41 +89,62 @@ async function initializeFeatures(context: ReaderContext): Promise<void> {
|
||||
|
||||
async function initializeReader(): Promise<void> {
|
||||
const mediaItemId = document.body.dataset.mediaItemId;
|
||||
if (!mediaItemId) return;
|
||||
|
||||
readerMetadata = await getReaderMetadata(mediaItemId);
|
||||
|
||||
switch (readerMetadata.library_type) {
|
||||
case "ebook":
|
||||
currentReader = await initializeEbookReader(readerMetadata);
|
||||
break;
|
||||
case "pdf":
|
||||
currentReader = await initializePDFReader(readerMetadata);
|
||||
break;
|
||||
case "comic":
|
||||
currentReader = await initializeComicReader(readerMetadata);
|
||||
break;
|
||||
case "manga":
|
||||
currentReader = await initializeMangaReader(readerMetadata);
|
||||
break;
|
||||
console.log("Initializing reader for:", mediaItemId);
|
||||
if (!mediaItemId) {
|
||||
console.error("No mediaItemId on body");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentReader) return;
|
||||
try {
|
||||
readerMetadata = await getReaderMetadata(mediaItemId);
|
||||
console.log("Got metadata:", readerMetadata);
|
||||
console.log("Library type:", readerMetadata.library_type_name);
|
||||
console.log("Mime type:", readerMetadata.mime_type);
|
||||
switch (readerMetadata.format_group) {
|
||||
case "reflowable":
|
||||
if (
|
||||
readerMetadata.mime_type === "application/epub+zip" ||
|
||||
readerMetadata.file_path.endsWith(".epub")
|
||||
) {
|
||||
currentReader = await initializeEbookReader(readerMetadata);
|
||||
}
|
||||
break;
|
||||
case "fixed_layout":
|
||||
currentReader = await initializePDFReader(readerMetadata);
|
||||
break;
|
||||
case "comic_archive":
|
||||
// Check manga_type or library_type_name
|
||||
if (
|
||||
readerMetadata.manga_type === "yes" ||
|
||||
readerMetadata.manga_type === "yes_and_right_to_left" ||
|
||||
readerMetadata.library_type_name === "manga"
|
||||
) {
|
||||
currentReader = await initializeMangaReader(readerMetadata);
|
||||
} else {
|
||||
currentReader = await initializeComicReader(readerMetadata);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
setState({ currentReader, readerMetadata });
|
||||
if (!currentReader) return;
|
||||
|
||||
const context = createReaderContext(
|
||||
getState,
|
||||
setState,
|
||||
createNavigationAPI(),
|
||||
() =>
|
||||
(context.render = () => {
|
||||
// Delegates to navigation module
|
||||
}),
|
||||
);
|
||||
setState({ currentReader, readerMetadata });
|
||||
|
||||
await initializeFeatures(context);
|
||||
readerEvents.emit("readerReady", currentReader);
|
||||
const context = createReaderContext(
|
||||
getState,
|
||||
setState,
|
||||
createNavigationAPI(),
|
||||
() =>
|
||||
(context.render = () => {
|
||||
// Delegates to navigation module
|
||||
}),
|
||||
);
|
||||
|
||||
await initializeFeatures(context);
|
||||
readerEvents.emit("readerReady", currentReader);
|
||||
} catch (error) {
|
||||
console.error("Render initialization failed:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function initializeEbookReader(metadata: any): Promise<UniversalReader> {
|
||||
@@ -196,7 +216,7 @@ function getFileExtension(filepath: string): string {
|
||||
// ============================================================
|
||||
|
||||
Alpine.data("readerShell", () => ({
|
||||
init() {
|
||||
initReader() {
|
||||
initializeReader();
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user