Working epub viewer
This commit is contained in:
parent
7d667b2114
commit
2fa91a2448
12 changed files with 882 additions and 303 deletions
773
package-lock.json
generated
773
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -24,6 +24,7 @@
|
|||
"react-dropzone": "^14.3.5",
|
||||
"react-hot-toast": "^2.5.1",
|
||||
"react-pdf": "^9.2.1",
|
||||
"react-reader": "^2.0.12",
|
||||
"string-similarity": "^4.0.4",
|
||||
"uuid": "^11.0.5"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,9 +2,54 @@
|
|||
|
||||
import { useParams } from "next/navigation";
|
||||
import Link from 'next/link';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useEPUB } from '@/contexts/EPUBContext';
|
||||
import { DocumentSkeleton } from '@/components/DocumentSkeleton';
|
||||
import { EPUBViewer } from '@/components/EPUBViewer';
|
||||
|
||||
export default function EPUBPage() {
|
||||
const { id } = useParams();
|
||||
const { setCurrentDocument, currDocName, clearCurrDoc } = useEPUB();
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const loadDocument = useCallback(async () => {
|
||||
if (!isLoading) return;
|
||||
try {
|
||||
if (!id) {
|
||||
setError('Document not found');
|
||||
return;
|
||||
}
|
||||
await setCurrentDocument(id as string);
|
||||
} catch (err) {
|
||||
console.error('Error loading document:', err);
|
||||
setError('Failed to load document');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [isLoading, id, setCurrentDocument]);
|
||||
|
||||
useEffect(() => {
|
||||
loadDocument();
|
||||
}, [loadDocument]);
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen">
|
||||
<p className="text-red-500 mb-4">{error}</p>
|
||||
<Link
|
||||
href="/"
|
||||
onClick={() => clearCurrDoc()}
|
||||
className="inline-flex items-center px-3 py-1 bg-base text-foreground rounded-lg hover:bg-offbase transition-colors"
|
||||
>
|
||||
<svg className="w-4 h-4 mr-2 text-muted" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||
</svg>
|
||||
Back to Documents
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -13,7 +58,7 @@ export default function EPUBPage() {
|
|||
<div className="flex items-center gap-2">
|
||||
<Link
|
||||
href="/"
|
||||
onClick={() => { }}
|
||||
onClick={() => clearCurrDoc()}
|
||||
className="inline-flex items-center px-3 py-1 bg-base text-foreground rounded-lg hover:bg-offbase transform transition-transform duration-200 ease-in-out hover:scale-[1.02]"
|
||||
>
|
||||
<svg className="w-4 h-4 mr-2" fill="currentColor" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
|
@ -23,11 +68,17 @@ export default function EPUBPage() {
|
|||
</Link>
|
||||
</div>
|
||||
<h1 className="ml-2 mr-2 text-md font-semibold text-foreground truncate">
|
||||
{id}
|
||||
{isLoading ? 'Loading...' : currDocName}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isLoading ? (
|
||||
<div className="p-4">
|
||||
<DocumentSkeleton />
|
||||
</div>
|
||||
) : (
|
||||
<EPUBViewer className="p-4" />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,27 @@
|
|||
'use client';
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { DocumentProvider } from '@/contexts/DocumentContext';
|
||||
import { PDFProvider } from '@/contexts/PDFContext';
|
||||
import { EPUBProvider } from '@/contexts/EPUBContext';
|
||||
import { TTSProvider } from '@/contexts/TTSContext';
|
||||
import { ThemeProvider } from '@/contexts/ThemeContext';
|
||||
import { ConfigProvider } from '@/contexts/ConfigContext';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export function Providers({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<ConfigProvider>
|
||||
<TTSProvider>
|
||||
<PDFProvider>
|
||||
{children}
|
||||
</PDFProvider>
|
||||
</TTSProvider>
|
||||
<DocumentProvider>
|
||||
<TTSProvider>
|
||||
<PDFProvider>
|
||||
<EPUBProvider>
|
||||
{children}
|
||||
</EPUBProvider>
|
||||
</PDFProvider>
|
||||
</TTSProvider>
|
||||
</DocumentProvider>
|
||||
</ConfigProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { usePDF } from '@/contexts/PDFContext';
|
||||
import { useEpubDocuments } from '@/hooks/epub/useEpubDocuments';
|
||||
import Link from 'next/link';
|
||||
import { Button, Dialog } from '@headlessui/react';
|
||||
import { Transition, TransitionChild, DialogPanel, DialogTitle } from '@headlessui/react';
|
||||
import { Fragment, useState } from 'react';
|
||||
import { useDocuments } from '@/contexts/DocumentContext';
|
||||
|
||||
type DocumentToDelete = {
|
||||
id: string;
|
||||
|
|
@ -12,8 +11,15 @@ type DocumentToDelete = {
|
|||
};
|
||||
|
||||
export function DocumentList() {
|
||||
const { documents: pdfDocs, removeDocument: removePDF, isDocsLoading: isPDFLoading } = usePDF();
|
||||
const { documents: epubDocs, removeDocument: removeEPUB, isLoading: isEPUBLoading } = useEpubDocuments();
|
||||
const {
|
||||
pdfDocs,
|
||||
removePDFDocument: removePDF,
|
||||
isPDFLoading,
|
||||
epubDocs,
|
||||
removeEPUBDocument: removeEPUB,
|
||||
isEPUBLoading,
|
||||
} = useDocuments();
|
||||
|
||||
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
|
||||
const [documentToDelete, setDocumentToDelete] = useState<DocumentToDelete | null>(null);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,17 +2,15 @@
|
|||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { usePDF } from '@/contexts/PDFContext';
|
||||
import { UploadIcon } from '@/components/icons/Icons';
|
||||
import { useEpubDocuments } from '@/hooks/epub/useEpubDocuments';
|
||||
import { useDocuments } from '@/contexts/DocumentContext';
|
||||
|
||||
interface DocumentUploaderProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function DocumentUploader({ className = '' }: DocumentUploaderProps) {
|
||||
const { addDocument: addPDF } = usePDF();
|
||||
const { addDocument: addEPUB } = useEpubDocuments();
|
||||
const { addPDFDocument: addPDF, addEPUBDocument: addEPUB } = useDocuments();
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
|
|
|
|||
36
src/components/EPUBViewer.tsx
Normal file
36
src/components/EPUBViewer.tsx
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useEPUB } from '@/contexts/EPUBContext';
|
||||
import { DocumentSkeleton } from '@/components/DocumentSkeleton';
|
||||
|
||||
const ReactReader = dynamic(() => import('react-reader').then(mod => mod.ReactReader), {
|
||||
ssr: false,
|
||||
loading: () => <DocumentSkeleton />
|
||||
});
|
||||
|
||||
interface EPUBViewerProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function EPUBViewer({ className = '' }: EPUBViewerProps) {
|
||||
const { currDocData, currDocName } = useEPUB(); // Changed from currDocURL
|
||||
const [location, setLocation] = useState<string | number>(0);
|
||||
|
||||
if (!currDocData) {
|
||||
return <DocumentSkeleton />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ height: '100vh' }} className={className}>
|
||||
<ReactReader
|
||||
location={location}
|
||||
locationChanged={setLocation}
|
||||
url={currDocData} // ReactReader can accept ArrayBuffer directly
|
||||
title={currDocName}
|
||||
showToc={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
61
src/contexts/DocumentContext.tsx
Normal file
61
src/contexts/DocumentContext.tsx
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
'use client';
|
||||
|
||||
import { createContext, useContext, ReactNode } from 'react';
|
||||
import { usePDFDocuments } from '@/hooks/pdf/usePDFDocuments';
|
||||
import { useEPUBDocuments } from '@/hooks/epub/useEPUBDocuments';
|
||||
import { PDFDocument, EPUBDocument } from '@/utils/indexedDB';
|
||||
|
||||
interface DocumentContextType {
|
||||
// PDF Documents
|
||||
pdfDocs: PDFDocument[];
|
||||
addPDFDocument: (file: File) => Promise<string>;
|
||||
removePDFDocument: (id: string) => Promise<void>;
|
||||
isPDFLoading: boolean;
|
||||
|
||||
// EPUB Documents
|
||||
epubDocs: EPUBDocument[];
|
||||
addEPUBDocument: (file: File) => Promise<string>;
|
||||
removeEPUBDocument: (id: string) => Promise<void>;
|
||||
isEPUBLoading: boolean;
|
||||
}
|
||||
|
||||
const DocumentContext = createContext<DocumentContextType | undefined>(undefined);
|
||||
|
||||
export function DocumentProvider({ children }: { children: ReactNode }) {
|
||||
const {
|
||||
documents: pdfDocs,
|
||||
addDocument: addPDFDocument,
|
||||
removeDocument: removePDFDocument,
|
||||
isLoading: isPDFLoading
|
||||
} = usePDFDocuments();
|
||||
|
||||
const {
|
||||
documents: epubDocs,
|
||||
addDocument: addEPUBDocument,
|
||||
removeDocument: removeEPUBDocument,
|
||||
isLoading: isEPUBLoading
|
||||
} = useEPUBDocuments();
|
||||
|
||||
return (
|
||||
<DocumentContext.Provider value={{
|
||||
pdfDocs,
|
||||
addPDFDocument,
|
||||
removePDFDocument,
|
||||
isPDFLoading,
|
||||
epubDocs,
|
||||
addEPUBDocument,
|
||||
removeEPUBDocument,
|
||||
isEPUBLoading
|
||||
}}>
|
||||
{children}
|
||||
</DocumentContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useDocuments() {
|
||||
const context = useContext(DocumentContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useDocuments must be used within a DocumentProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
132
src/contexts/EPUBContext.tsx
Normal file
132
src/contexts/EPUBContext.tsx
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
'use client';
|
||||
|
||||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { indexedDBService } from '@/utils/indexedDB';
|
||||
import { useTTS } from '@/contexts/TTSContext';
|
||||
|
||||
interface EPUBContextType {
|
||||
// Current document state
|
||||
currDocData: ArrayBuffer | undefined; // Changed back to currDocData
|
||||
currDocName: string | undefined;
|
||||
currDocPages: number | undefined;
|
||||
currDocPage: number;
|
||||
currDocText: string | undefined;
|
||||
setCurrentDocument: (id: string) => Promise<void>;
|
||||
clearCurrDoc: () => void;
|
||||
|
||||
// EPUB functionality
|
||||
onDocumentLoadSuccess: ({ numPages }: { numPages: number }) => void;
|
||||
}
|
||||
|
||||
// Create the context
|
||||
const EPUBContext = createContext<EPUBContextType | undefined>(undefined);
|
||||
|
||||
/**
|
||||
* EPUBProvider Component
|
||||
*
|
||||
* Main provider component that manages EPUB state and functionality.
|
||||
* Handles document loading, text processing, and integration with TTS.
|
||||
*/
|
||||
export function EPUBProvider({ children }: { children: ReactNode }) {
|
||||
const { setText: setTTSText, currDocPage, currDocPages, setCurrDocPages } = useTTS();
|
||||
|
||||
// Current document state
|
||||
const [currDocData, setCurrDocData] = useState<ArrayBuffer>(); // Changed back to currDocData
|
||||
const [currDocName, setCurrDocName] = useState<string>();
|
||||
const [currDocText, setCurrDocText] = useState<string>();
|
||||
|
||||
/**
|
||||
* Handles successful document load
|
||||
*/
|
||||
const onDocumentLoadSuccess = useCallback(({ numPages }: { numPages: number }) => {
|
||||
console.log('EPUB loaded:', numPages);
|
||||
setCurrDocPages(numPages);
|
||||
}, [setCurrDocPages]);
|
||||
|
||||
/**
|
||||
* Clears the current document state
|
||||
*/
|
||||
const clearCurrDoc = useCallback(() => {
|
||||
setCurrDocData(undefined);
|
||||
setCurrDocName(undefined);
|
||||
setCurrDocText(undefined);
|
||||
setCurrDocPages(undefined);
|
||||
setTTSText('');
|
||||
}, [setCurrDocPages, setTTSText]);
|
||||
|
||||
/**
|
||||
* Sets the current document based on its ID
|
||||
*/
|
||||
const setCurrentDocument = useCallback(async (id: string): Promise<void> => {
|
||||
try {
|
||||
const doc = await indexedDBService.getEPUBDocument(id);
|
||||
if (doc) {
|
||||
console.log('Retrieved document size:', doc.size);
|
||||
console.log('Retrieved ArrayBuffer size:', doc.data.byteLength);
|
||||
|
||||
if (doc.data.byteLength === 0) {
|
||||
console.error('Retrieved ArrayBuffer is empty');
|
||||
throw new Error('Empty document data');
|
||||
}
|
||||
|
||||
setCurrDocName(doc.name);
|
||||
setCurrDocData(doc.data); // Store ArrayBuffer directly
|
||||
} else {
|
||||
console.error('Document not found in IndexedDB');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to get EPUB document:', error);
|
||||
clearCurrDoc(); // Clean up on error
|
||||
}
|
||||
}, [clearCurrDoc]);
|
||||
|
||||
|
||||
// Context value memoization
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
onDocumentLoadSuccess,
|
||||
setCurrentDocument,
|
||||
currDocData, // Changed back to currDocData
|
||||
currDocName,
|
||||
currDocPages,
|
||||
currDocPage,
|
||||
currDocText,
|
||||
clearCurrDoc,
|
||||
}),
|
||||
[
|
||||
onDocumentLoadSuccess,
|
||||
setCurrentDocument,
|
||||
currDocData, // Changed back to currDocData
|
||||
currDocName,
|
||||
currDocPages,
|
||||
currDocPage,
|
||||
currDocText,
|
||||
clearCurrDoc,
|
||||
]
|
||||
);
|
||||
|
||||
return (
|
||||
<EPUBContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</EPUBContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom hook to consume the EPUB context
|
||||
* Ensures the context is used within a provider
|
||||
*/
|
||||
export function useEPUB() {
|
||||
const context = useContext(EPUBContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useEPUB must be used within an EPUBProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ import {
|
|||
useMemo,
|
||||
} from 'react';
|
||||
|
||||
import { indexedDBService, type PDFDocument } from '@/utils/indexedDB';
|
||||
import { indexedDBService } from '@/utils/indexedDB';
|
||||
import { useTTS } from '@/contexts/TTSContext';
|
||||
import {
|
||||
extractTextFromPDF,
|
||||
|
|
@ -32,18 +32,11 @@ import {
|
|||
clearHighlights,
|
||||
handleTextClick,
|
||||
} from '@/utils/pdf';
|
||||
import { usePDFDocuments } from '@/hooks/pdf/usePDFDocuments';
|
||||
|
||||
/**
|
||||
* Interface defining all available methods and properties in the PDF context
|
||||
*/
|
||||
interface PDFContextType {
|
||||
// PDF document store management
|
||||
addDocument: (file: File) => Promise<string>;
|
||||
documents: PDFDocument[];
|
||||
removeDocument: (id: string) => Promise<void>;
|
||||
isDocsLoading: boolean;
|
||||
|
||||
// Current document state
|
||||
currDocURL: string | undefined;
|
||||
currDocName: string | undefined;
|
||||
|
|
@ -76,15 +69,7 @@ const PDFContext = createContext<PDFContextType | undefined>(undefined);
|
|||
* Handles document loading, text processing, and integration with TTS.
|
||||
*/
|
||||
export function PDFProvider({ children }: { children: ReactNode }) {
|
||||
const {
|
||||
setText: setTTSText,
|
||||
currDocPage,
|
||||
currDocPages,
|
||||
setCurrDocPages,
|
||||
} = useTTS();
|
||||
|
||||
// PDF Documents hook
|
||||
const { addDocument, documents, removeDocument, isLoading: isDocsLoading } = usePDFDocuments();
|
||||
const { setText: setTTSText, currDocPage, currDocPages, setCurrDocPages } = useTTS();
|
||||
|
||||
// Current document state
|
||||
const [currDocURL, setCurrDocURL] = useState<string>();
|
||||
|
|
@ -157,10 +142,6 @@ export function PDFProvider({ children }: { children: ReactNode }) {
|
|||
// Context value memoization
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
addDocument,
|
||||
documents,
|
||||
removeDocument,
|
||||
isDocsLoading,
|
||||
onDocumentLoadSuccess,
|
||||
setCurrentDocument,
|
||||
currDocURL,
|
||||
|
|
@ -174,10 +155,6 @@ export function PDFProvider({ children }: { children: ReactNode }) {
|
|||
handleTextClick,
|
||||
}),
|
||||
[
|
||||
addDocument,
|
||||
documents,
|
||||
removeDocument,
|
||||
isDocsLoading,
|
||||
onDocumentLoadSuccess,
|
||||
setCurrentDocument,
|
||||
currDocURL,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|||
import { indexedDBService, type EPUBDocument } from '@/utils/indexedDB';
|
||||
import { useConfig } from '@/contexts/ConfigContext';
|
||||
|
||||
export function useEpubDocuments() {
|
||||
export function useEPUBDocuments() {
|
||||
const { isDBReady } = useConfig();
|
||||
const [documents, setDocuments] = useState<EPUBDocument[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
|
@ -13,7 +13,7 @@ export function useEpubDocuments() {
|
|||
const loadDocuments = useCallback(async () => {
|
||||
if (isDBReady) {
|
||||
try {
|
||||
const docs = await indexedDBService.getAllEpubDocuments();
|
||||
const docs = await indexedDBService.getAllEPUBDocuments();
|
||||
setDocuments(docs);
|
||||
} catch (error) {
|
||||
console.error('Failed to load EPUB documents:', error);
|
||||
|
|
@ -29,16 +29,21 @@ export function useEpubDocuments() {
|
|||
|
||||
const addDocument = useCallback(async (file: File): Promise<string> => {
|
||||
const id = uuidv4();
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
|
||||
console.log('Original file size:', file.size);
|
||||
console.log('ArrayBuffer size:', arrayBuffer.byteLength);
|
||||
|
||||
const newDoc: EPUBDocument = {
|
||||
id,
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
lastModified: file.lastModified,
|
||||
data: new Blob([file], { type: file.type }),
|
||||
data: arrayBuffer,
|
||||
};
|
||||
|
||||
try {
|
||||
await indexedDBService.addEpubDocument(newDoc);
|
||||
await indexedDBService.addEPUBDocument(newDoc);
|
||||
setDocuments((prev) => [...prev, newDoc]);
|
||||
return id;
|
||||
} catch (error) {
|
||||
|
|
@ -49,7 +54,7 @@ export function useEpubDocuments() {
|
|||
|
||||
const removeDocument = useCallback(async (id: string): Promise<void> => {
|
||||
try {
|
||||
await indexedDBService.removeEpubDocument(id);
|
||||
await indexedDBService.removeEPUBDocument(id);
|
||||
setDocuments((prev) => prev.filter((doc) => doc.id !== id));
|
||||
} catch (error) {
|
||||
console.error('Failed to remove EPUB document:', error);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export interface EPUBDocument {
|
|||
name: string;
|
||||
size: number;
|
||||
lastModified: number;
|
||||
data: Blob;
|
||||
data: ArrayBuffer; // Changed from Blob to ArrayBuffer
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
|
|
@ -196,31 +196,49 @@ class IndexedDBService {
|
|||
}
|
||||
|
||||
// Add EPUB Document Methods
|
||||
async addEpubDocument(document: EPUBDocument): Promise<void> {
|
||||
async addEPUBDocument(document: EPUBDocument): Promise<void> {
|
||||
if (!this.db) {
|
||||
await this.init();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (document.data.byteLength === 0) {
|
||||
throw new Error('Cannot store empty ArrayBuffer');
|
||||
}
|
||||
|
||||
console.log('Storing document:', {
|
||||
name: document.name,
|
||||
size: document.size,
|
||||
actualSize: document.data.byteLength
|
||||
});
|
||||
|
||||
const transaction = this.db!.transaction([EPUB_STORE_NAME], 'readwrite');
|
||||
const store = transaction.objectStore(EPUB_STORE_NAME);
|
||||
const request = store.put(document);
|
||||
|
||||
// Create a structured clone of the document to ensure proper storage
|
||||
const request = store.put({
|
||||
...document,
|
||||
data: document.data.slice(0) // Create a copy of the ArrayBuffer
|
||||
});
|
||||
|
||||
request.onerror = (event) => {
|
||||
console.error('Error storing document:', (event.target as IDBRequest).error);
|
||||
reject((event.target as IDBRequest).error);
|
||||
};
|
||||
|
||||
transaction.oncomplete = () => {
|
||||
console.log('Document stored successfully');
|
||||
resolve();
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error in addEPUBDocument:', error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async getEpubDocument(id: string): Promise<EPUBDocument | undefined> {
|
||||
async getEPUBDocument(id: string): Promise<EPUBDocument | undefined> {
|
||||
if (!this.db) {
|
||||
await this.init();
|
||||
}
|
||||
|
|
@ -232,19 +250,29 @@ class IndexedDBService {
|
|||
const request = store.get(id);
|
||||
|
||||
request.onerror = (event) => {
|
||||
console.error('Error fetching document:', (event.target as IDBRequest).error);
|
||||
reject((event.target as IDBRequest).error);
|
||||
};
|
||||
|
||||
request.onsuccess = () => {
|
||||
resolve(request.result);
|
||||
const doc = request.result;
|
||||
if (doc) {
|
||||
console.log('Retrieved document from DB:', {
|
||||
name: doc.name,
|
||||
size: doc.size,
|
||||
actualSize: doc.data.byteLength
|
||||
});
|
||||
}
|
||||
resolve(doc);
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error in getEPUBDocument:', error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async getAllEpubDocuments(): Promise<EPUBDocument[]> {
|
||||
async getAllEPUBDocuments(): Promise<EPUBDocument[]> {
|
||||
if (!this.db) {
|
||||
await this.init();
|
||||
}
|
||||
|
|
@ -268,7 +296,7 @@ class IndexedDBService {
|
|||
});
|
||||
}
|
||||
|
||||
async removeEpubDocument(id: string): Promise<void> {
|
||||
async removeEPUBDocument(id: string): Promise<void> {
|
||||
if (!this.db) {
|
||||
await this.init();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue