diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9c64713..8aab32e 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,6 @@ import "./globals.css"; -import { Providers } from "./providers"; +import { ReactNode } from "react"; +import { Providers } from "@/app/providers"; import { Metadata } from "next"; import Script from "next/script"; import { Footer } from "@/components/Footer"; @@ -48,12 +49,7 @@ export const metadata: Metadata = { const isDev = process.env.NEXT_PUBLIC_NODE_ENV !== 'production' || process.env.NODE_ENV == null; //const isDev = false; -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - +export default function RootLayout({ children }: { children: ReactNode }) { return ( diff --git a/src/app/page.tsx b/src/app/page.tsx index e303b30..58789cb 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,32 +1,17 @@ -'use client'; - -import { useState } from 'react'; import { DocumentUploader } from '@/components/DocumentUploader'; import { DocumentList } from '@/components/DocumentList'; import { SettingsModal } from '@/components/SettingsModal'; -import { SettingsIcon } from '@/components/icons/Icons'; -import { Button } from '@headlessui/react'; export default function Home() { - const [isSettingsOpen, setIsSettingsOpen] = useState(false); - return (
- +

OpenReader WebUI

A bring your own text-to-speech api web interface for reading documents with high quality voices

-
); } diff --git a/src/components/ConfirmDialog.tsx b/src/components/ConfirmDialog.tsx index e8bca7e..cd828d5 100644 --- a/src/components/ConfirmDialog.tsx +++ b/src/components/ConfirmDialog.tsx @@ -1,6 +1,4 @@ -'use client'; - -import { Fragment, useEffect } from 'react'; +import { Fragment, KeyboardEvent } from 'react'; import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react'; interface ConfirmDialogProps { @@ -24,23 +22,21 @@ export function ConfirmDialog({ cancelText = 'Cancel', isDangerous = false, }: ConfirmDialogProps) { - useEffect(() => { - if (!isOpen) return; - - const handleKeyDown = (e: KeyboardEvent) => { - if (e.key === 'Enter') { - e.preventDefault(); - onConfirm(); - } - }; - - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); - }, [isOpen, onConfirm]); + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + onConfirm(); + } + }; return ( - + void; -} - const themes = THEMES.map(id => ({ id, name: id.charAt(0).toUpperCase() + id.slice(1) })); -export function SettingsModal({ isOpen, setIsOpen }: SettingsModalProps) { +export function SettingsModal() { + const [isOpen, setIsOpen] = useState(false); + const { theme, setTheme } = useTheme(); const { apiKey, baseUrl, updateConfig } = useConfig(); const { refreshPDFs, refreshEPUBs, clearPDFs, clearEPUBs } = useDocuments(); @@ -95,7 +92,14 @@ export function SettingsModal({ isOpen, setIsOpen }: SettingsModalProps) { }; return ( - <> + ); } diff --git a/src/contexts/ConfigContext.tsx b/src/contexts/ConfigContext.tsx index 8b41265..5ff6744 100644 --- a/src/contexts/ConfigContext.tsx +++ b/src/contexts/ConfigContext.tsx @@ -1,6 +1,6 @@ 'use client'; -import { createContext, useContext, useEffect, useState } from 'react'; +import { createContext, useContext, useEffect, useState, ReactNode } from 'react'; import { getItem, indexedDBService, setItem } from '@/utils/indexedDB'; export type ViewType = 'single' | 'dual' | 'scroll'; @@ -29,7 +29,7 @@ type ConfigValues = { const ConfigContext = createContext(undefined); -export function ConfigProvider({ children }: { children: React.ReactNode }) { +export function ConfigProvider({ children }: { children: ReactNode }) { // Config state const [apiKey, setApiKey] = useState(''); const [baseUrl, setBaseUrl] = useState(''); diff --git a/src/contexts/PDFContext.tsx b/src/contexts/PDFContext.tsx index 9429cfc..e4d129f 100644 --- a/src/contexts/PDFContext.tsx +++ b/src/contexts/PDFContext.tsx @@ -21,6 +21,7 @@ import { useEffect, useCallback, useMemo, + RefObject, } from 'react'; import { indexedDBService } from '@/utils/indexedDB'; @@ -51,12 +52,12 @@ interface PDFContextType { // PDF functionality onDocumentLoadSuccess: (pdf: PDFDocumentProxy) => void; - highlightPattern: (text: string, pattern: string, containerRef: React.RefObject) => void; + highlightPattern: (text: string, pattern: string, containerRef: RefObject) => void; clearHighlights: () => void; handleTextClick: ( event: MouseEvent, pdfText: string, - containerRef: React.RefObject, + containerRef: RefObject, stopAndPlayFromIndex: (index: number) => void, isProcessing: boolean ) => void; diff --git a/src/contexts/TTSContext.tsx b/src/contexts/TTSContext.tsx index 05d1881..2bd5615 100644 --- a/src/contexts/TTSContext.tsx +++ b/src/contexts/TTSContext.tsx @@ -14,7 +14,7 @@ 'use client'; -import React, { +import { createContext, useContext, useState, @@ -22,6 +22,7 @@ import React, { useEffect, useRef, useMemo, + ReactNode, } from 'react'; import OpenAI from 'openai'; import { Howl } from 'howler'; @@ -84,7 +85,7 @@ const TTSContext = createContext(undefined); * Main provider component that manages the TTS state and functionality. * Handles initialization of OpenAI client, audio context, and media session. */ -export function TTSProvider({ children }: { children: React.ReactNode }) { +export function TTSProvider({ children }: { children: ReactNode }) { // Configuration context consumption const { apiKey: openApiKey, diff --git a/src/contexts/ThemeContext.tsx b/src/contexts/ThemeContext.tsx index 2562594..d8310dd 100644 --- a/src/contexts/ThemeContext.tsx +++ b/src/contexts/ThemeContext.tsx @@ -1,6 +1,6 @@ 'use client'; -import { createContext, useContext, useEffect, useState } from 'react'; +import { createContext, useContext, useEffect, useState, ReactNode } from 'react'; const THEMES = ['system', 'light', 'dark', 'aqua', 'forest', 'vibrant'] as const; type Theme = (typeof THEMES)[number]; @@ -24,7 +24,7 @@ const getEffectiveTheme = (theme: Theme): Theme => { return theme; }; -export function ThemeProvider({ children }: { children: React.ReactNode }) { +export function ThemeProvider({ children }: { children: ReactNode }) { const [theme, setTheme] = useState(() => { if (typeof window === 'undefined') return 'system'; return (localStorage.getItem('theme') as Theme) || 'system';