(currDocPage);
- const [reloadKey, setReloadKey] = useState(0);
const [initialPrevLocLoad, setInitialPrevLocLoad] = useState(false);
+ const { updateTheme } = useEPUBTheme(epubTheme, rendition.current);
const handleLocationChanged = useCallback((location: string | number, initial = false) => {
- if (!bookRef.current?.isOpen) return;
+ if (!bookRef.current?.isOpen || !rendition.current) return;
// Handle special 'next' and 'prev' cases, which
if (location === 'next' && rendition.current) {
rendition.current.next();
@@ -111,32 +45,32 @@ export function EPUBViewer({ className = '' }: EPUBViewerProps) {
return;
}
- if (bookRef.current && rendition.current) {
- const { displayed, href } = rendition.current.location.start;
- const chapter = toc.current.find((item) => item.href === href);
-
- console.log('Displayed:', displayed, 'Chapter:', chapter);
- if (locationRef.current !== 1) {
- // Save the location to IndexedDB
- if (id) {
- console.log('Saving location:', location);
- setLastDocumentLocation(id as string, location.toString());
- }
- }
-
- setEPUBPageInChapter(displayed.page, displayed.total, chapter?.label || '');
-
- // Add a small delay for initial load to ensure rendition is ready
- if (initial) {
- rendition.current.display(location.toString()).then(() => {
- setInitialPrevLocLoad(true);
- });
- } else {
- locationRef.current = location;
- extractPageText(bookRef.current, rendition.current);
+ const { displayed, href } = rendition.current.location.start;
+ const chapter = toc.current.find((item) => item.href === href);
+
+ console.log('Displayed:', displayed, 'Chapter:', chapter);
+
+ if (locationRef.current !== 1) {
+ // Save the location to IndexedDB
+ if (id) {
+ console.log('Saving location:', location);
+ setLastDocumentLocation(id as string, location.toString());
}
}
+
+ setEPUBPageInChapter(displayed.page, displayed.total, chapter?.label || '');
+
+ // Add a small delay for initial load to ensure rendition is ready
+ if (initial) {
+ rendition.current.display(location.toString()).then(() => {
+ setInitialPrevLocLoad(true);
+ });
+ } else {
+ locationRef.current = location;
+ extractPageText(bookRef.current, rendition.current);
+ }
+
}, [id, setEPUBPageInChapter, extractPageText]);
// Replace the debounced text extraction with a proper implementation using useMemo
@@ -174,46 +108,6 @@ export function EPUBViewer({ className = '' }: EPUBViewerProps) {
}
}, [extractPageText, debouncedExtractText, initialPrevLocLoad]);
- const updateTheme = useCallback((rendition: Rendition) => {
- if (!epubTheme) return; // Only apply theme if enabled
-
- const colors = {
- foreground: getComputedStyle(document.documentElement).getPropertyValue('--foreground'),
- base: getComputedStyle(document.documentElement).getPropertyValue('--base'),
- };
-
- rendition.themes.override('color', colors.foreground);
- rendition.themes.override('background', colors.base);
- }, [epubTheme]);
-
- // Watch for theme changes
- useEffect(() => {
- if (!epubTheme || !bookRef.current?.isOpen || !rendition.current) return;
-
- const observer = new MutationObserver((mutations) => {
- mutations.forEach((mutation) => {
- if (mutation.attributeName === 'class') {
- if (epubTheme) {
- setReloadKey(prev => prev + 1);
- }
- }
- });
- });
-
- observer.observe(document.documentElement, {
- attributes: true,
- attributeFilter: ['class']
- });
-
- return () => observer.disconnect();
- }, [epubTheme]);
-
- // Watch for epubTheme changes
- useEffect(() => {
- if (!epubTheme || !bookRef.current?.isOpen || !rendition.current) return;
- setReloadKey(prev => prev + 1);
- }, [epubTheme]);
-
// Register the location change handler
useEffect(() => {
registerLocationChangeHandler(handleLocationChanged);
@@ -230,7 +124,7 @@ export function EPUBViewer({ className = '' }: EPUBViewerProps) {
{
- updateTheme(_rendition);
-
bookRef.current = _rendition.book;
rendition.current = _rendition;
+ updateTheme();
}}
/>
diff --git a/src/contexts/EPUBContext.tsx b/src/contexts/EPUBContext.tsx
index e874d30..5703183 100644
--- a/src/contexts/EPUBContext.tsx
+++ b/src/contexts/EPUBContext.tsx
@@ -21,7 +21,6 @@ interface EPUBContextType {
currDocText: string | undefined;
setCurrentDocument: (id: string) => Promise;
clearCurrDoc: () => void;
- onDocumentLoadSuccess: ({ numPages }: { numPages: number }) => void;
extractPageText: (book: Book, rendition: Rendition) => Promise;
}
@@ -35,14 +34,6 @@ export function EPUBProvider({ children }: { children: ReactNode }) {
const [currDocName, setCurrDocName] = useState();
const [currDocText, setCurrDocText] = useState();
- /**
- * Handles successful document load
- */
- const onDocumentLoadSuccess = useCallback(({ numPages }: { numPages: number }) => {
- console.log('EPUB loaded:', numPages);
- setCurrDocPages(numPages);
- }, [setCurrDocPages]);
-
/**
* Clears the current document state
*/
@@ -106,7 +97,6 @@ export function EPUBProvider({ children }: { children: ReactNode }) {
// Context value memoization
const contextValue = useMemo(
() => ({
- onDocumentLoadSuccess,
setCurrentDocument,
currDocData,
currDocName,
@@ -117,7 +107,6 @@ export function EPUBProvider({ children }: { children: ReactNode }) {
extractPageText,
}),
[
- onDocumentLoadSuccess,
setCurrentDocument,
currDocData,
currDocName,
diff --git a/src/hooks/useEPUBTheme.ts b/src/hooks/useEPUBTheme.ts
new file mode 100644
index 0000000..712e58c
--- /dev/null
+++ b/src/hooks/useEPUBTheme.ts
@@ -0,0 +1,119 @@
+import { useCallback, useEffect } from 'react';
+import { Rendition } from 'epubjs';
+import { ReactReaderStyle, IReactReaderStyle } from 'react-reader';
+
+export const getThemeStyles = (): IReactReaderStyle => {
+ const baseStyle = {
+ ...ReactReaderStyle,
+ readerArea: {
+ ...ReactReaderStyle.readerArea,
+ transition: undefined,
+ }
+ };
+
+ const colors = {
+ background: getComputedStyle(document.documentElement).getPropertyValue('--background'),
+ foreground: getComputedStyle(document.documentElement).getPropertyValue('--foreground'),
+ base: getComputedStyle(document.documentElement).getPropertyValue('--base'),
+ offbase: getComputedStyle(document.documentElement).getPropertyValue('--offbase'),
+ muted: getComputedStyle(document.documentElement).getPropertyValue('--muted'),
+ };
+
+ return {
+ ...baseStyle,
+ arrow: {
+ ...baseStyle.arrow,
+ color: colors.foreground,
+ },
+ arrowHover: {
+ ...baseStyle.arrowHover,
+ color: colors.muted,
+ },
+ readerArea: {
+ ...baseStyle.readerArea,
+ backgroundColor: colors.base,
+ },
+ titleArea: {
+ ...baseStyle.titleArea,
+ color: colors.foreground,
+ display: 'none',
+ },
+ tocArea: {
+ ...baseStyle.tocArea,
+ background: colors.base,
+ },
+ tocButtonExpanded: {
+ ...baseStyle.tocButtonExpanded,
+ background: colors.offbase,
+ },
+ tocButtonBar: {
+ ...baseStyle.tocButtonBar,
+ background: colors.muted,
+ },
+ tocButton: {
+ ...baseStyle.tocButton,
+ color: colors.muted,
+ },
+ tocAreaButton: {
+ ...baseStyle.tocAreaButton,
+ color: colors.muted,
+ backgroundColor: colors.offbase,
+ padding: '0.25rem',
+ paddingLeft: '0.5rem',
+ paddingRight: '0.5rem',
+ marginBottom: '0.25rem',
+ borderRadius: '0.25rem',
+ borderColor: 'transparent',
+ },
+ };
+};
+
+export const useEPUBTheme = (epubTheme: boolean, rendition: Rendition | undefined) => {
+ const updateTheme = useCallback(() => {
+ if (!epubTheme || !rendition) return;
+
+ const colors = {
+ foreground: getComputedStyle(document.documentElement).getPropertyValue('--foreground'),
+ base: getComputedStyle(document.documentElement).getPropertyValue('--base'),
+ };
+
+ // Register theme rules instead of using override
+ rendition.themes.registerRules('theme-light', {
+ 'body': {
+ 'color': colors.foreground,
+ 'background-color': colors.base
+ }
+ });
+
+ // Select the theme to apply it
+ rendition.themes.select('theme-light');
+ }, [epubTheme, rendition]);
+
+ // Watch for theme changes
+ useEffect(() => {
+ if (!epubTheme || !rendition) return;
+
+ const observer = new MutationObserver((mutations) => {
+ mutations.forEach((mutation) => {
+ if (mutation.attributeName === 'class') {
+ updateTheme();
+ }
+ });
+ });
+
+ observer.observe(document.documentElement, {
+ attributes: true,
+ attributeFilter: ['class']
+ });
+
+ return () => observer.disconnect();
+ }, [epubTheme, rendition, updateTheme]);
+
+ // Watch for epubTheme changes
+ useEffect(() => {
+ if (!epubTheme || !rendition) return;
+ updateTheme();
+ }, [epubTheme, rendition, updateTheme]);
+
+ return { updateTheme };
+};
\ No newline at end of file