@@ -26,6 +26,7 @@ import React, {
2626import OpenAI from 'openai' ;
2727import { Howl } from 'howler' ;
2828import toast from 'react-hot-toast' ;
29+ import { useParams } from 'next/navigation' ;
2930
3031import { useConfig } from '@/contexts/ConfigContext' ;
3132import { splitIntoSentences , preprocessSentenceForAudio } from '@/utils/nlp' ;
@@ -34,6 +35,7 @@ import { useAudioCache } from '@/hooks/audio/useAudioCache';
3435import { useVoiceManagement } from '@/hooks/audio/useVoiceManagement' ;
3536import { useMediaSession } from '@/hooks/audio/useMediaSession' ;
3637import { useAudioContext } from '@/hooks/audio/useAudioContext' ;
38+ import { getLastDocumentLocation } from '@/utils/indexedDB' ;
3739
3840// Media globals
3941declare global {
@@ -52,7 +54,8 @@ interface TTSContextType {
5254 currentSentence : string ;
5355
5456 // Navigation
55- currDocPage : number ;
57+ currDocPage : string | number ; // Change this to allow both types
58+ currDocPageNumber : number ; // For PDF
5659 currDocPages : number | undefined ;
5760
5861 // Voice settings
@@ -110,6 +113,9 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
110113 locationChangeHandlerRef . current = handler ;
111114 } , [ ] ) ;
112115
116+ // Get document ID from URL params
117+ const { id } = useParams ( ) ;
118+
113119 /**
114120 * State Management
115121 */
@@ -120,13 +126,15 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
120126 const [ isProcessing , setIsProcessing ] = useState ( false ) ;
121127 const [ speed , setSpeed ] = useState ( voiceSpeed ) ;
122128 const [ voice , setVoice ] = useState ( configVoice ) ;
123- const [ currDocPage , setCurrDocPage ] = useState < number > ( 1 ) ;
129+ const [ currDocPage , setCurrDocPage ] = useState < string | number > ( 1 ) ;
124130 const [ currDocPages , setCurrDocPages ] = useState < number > ( ) ;
125131 const [ nextPageLoading , setNextPageLoading ] = useState ( false ) ;
126132
127133 // Add this state to track if we're in EPUB mode
128134 const [ isEPUB , setIsEPUB ] = useState ( false ) ;
129135
136+ const currDocPageNumber = ( ! isEPUB ? parseInt ( currDocPage . toString ( ) ) : 1 ) ;
137+
130138 console . log ( 'page:' , currDocPage , 'pages:' , currDocPages ) ;
131139
132140 /**
@@ -137,8 +145,8 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
137145 */
138146 const incrementPage = useCallback ( ( num = 1 ) => {
139147 setNextPageLoading ( true ) ;
140- setCurrDocPage ( currDocPage + num ) ;
141- } , [ currDocPage ] ) ;
148+ setCurrDocPage ( currDocPageNumber + num ) ;
149+ } , [ currDocPageNumber ] ) ;
142150
143151 /**
144152 * Sets the current text and splits it into sentences
@@ -167,12 +175,12 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
167175 position : 'top-center' ,
168176 } ) ;
169177 return ;
170- } else if ( currDocPage < currDocPages ! ) {
178+ } else if ( currDocPageNumber < currDocPages ! ) {
171179 // For PDF, increment the page
172180 incrementPage ( ) ;
173181
174- toast . success ( `Skipping blank page ${ currDocPage } ` , {
175- id : `page-${ currDocPage } ` ,
182+ toast . success ( `Skipping blank page ${ currDocPageNumber } ` , {
183+ id : `page-${ currDocPageNumber } ` ,
176184 iconTheme : {
177185 primary : 'var(--accent)' ,
178186 secondary : 'var(--background)' ,
@@ -190,7 +198,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
190198
191199 setSentences ( newSentences ) ;
192200 setNextPageLoading ( false ) ;
193- } , [ isPlaying , skipBlank , currDocPage , currDocPages , incrementPage , isEPUB ] ) ;
201+ } , [ isPlaying , skipBlank , currDocPageNumber , currDocPages , incrementPage , isEPUB ] ) ;
194202
195203 /**
196204 * Stops the current audio playback and clears the active Howl instance
@@ -299,8 +307,8 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
299307 // For PDFs and other documents, check page bounds
300308 if ( ! isEPUB ) {
301309 // Handle next/previous page transitions
302- if ( ( nextIndex >= sentences . length && currDocPage < currDocPages ! ) ||
303- ( nextIndex < 0 && currDocPage > 1 ) ) {
310+ if ( ( nextIndex >= sentences . length && currDocPageNumber < currDocPages ! ) ||
311+ ( nextIndex < 0 && currDocPageNumber > 1 ) ) {
304312 console . log ( 'PDF: Advancing to next/prev page' ) ;
305313 setCurrentIndex ( 0 ) ;
306314 setSentences ( [ ] ) ;
@@ -309,12 +317,12 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
309317 }
310318
311319 // Handle end of document (PDF only)
312- if ( nextIndex >= sentences . length && currDocPage >= currDocPages ! ) {
320+ if ( nextIndex >= sentences . length && currDocPageNumber >= currDocPages ! ) {
313321 console . log ( 'PDF: Reached end of document' ) ;
314322 setIsPlaying ( false ) ;
315323 }
316324 }
317- } , [ currentIndex , incrementPage , sentences , currDocPage , currDocPages , isEPUB ] ) ;
325+ } , [ currentIndex , incrementPage , sentences , currDocPageNumber , currDocPages , isEPUB ] ) ;
318326
319327 /**
320328 * Moves forward one sentence in the text
@@ -637,6 +645,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
637645 isProcessing,
638646 currentSentence : sentences [ currentIndex ] || '' ,
639647 currDocPage,
648+ currDocPageNumber,
640649 currDocPages,
641650 availableVoices,
642651 togglePlay,
@@ -657,6 +666,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
657666 sentences ,
658667 currentIndex ,
659668 currDocPage ,
669+ currDocPageNumber ,
660670 currDocPages ,
661671 availableVoices ,
662672 togglePlay ,
@@ -680,6 +690,20 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
680690 skipBackward,
681691 } ) ;
682692
693+ // Load last location on mount for EPUB only
694+ useEffect ( ( ) => {
695+ if ( id && isEPUB ) {
696+ getLastDocumentLocation ( id as string ) . then ( lastLocation => {
697+ if ( lastLocation ) {
698+ setCurrDocPage ( lastLocation ) ;
699+ if ( locationChangeHandlerRef . current ) {
700+ locationChangeHandlerRef . current ( lastLocation ) ;
701+ }
702+ }
703+ } ) ;
704+ }
705+ } , [ id , isEPUB ] ) ;
706+
683707 /**
684708 * Renders the TTS context provider with its children
685709 *
0 commit comments