@@ -35,6 +35,7 @@ import { useVoiceManagement } from '@/hooks/audio/useVoiceManagement';
3535import { useMediaSession } from '@/hooks/audio/useMediaSession' ;
3636import { useAudioContext } from '@/hooks/audio/useAudioContext' ;
3737import { getLastDocumentLocation } from '@/utils/indexedDB' ;
38+ import { useBackgroundState } from '@/hooks/audio/useBackgroundState' ;
3839
3940// Media globals
4041declare global {
@@ -51,6 +52,7 @@ interface TTSContextType {
5152 isPlaying : boolean ;
5253 isProcessing : boolean ;
5354 currentSentence : string ;
55+ isBackgrounded : boolean ; // Add this new property
5456
5557 // Navigation
5658 currDocPage : string | number ; // Change this to allow both types
@@ -142,8 +144,6 @@ export function TTSProvider({ children }: { children: ReactNode }) {
142144 // Track active abort controllers for TTS requests
143145 const activeAbortControllers = useRef < Set < AbortController > > ( new Set ( ) ) ;
144146
145- //console.log('page:', currDocPage, 'pages:', currDocPages);
146-
147147 /**
148148 * Processes text through the NLP API to split it into sentences
149149 *
@@ -535,7 +535,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
535535 format : [ 'mp3' ] ,
536536 html5 : true ,
537537 preload : true ,
538- pool : 5 , // Reduced pool size for iOS compatibility
538+ pool : 5 ,
539539 onplay : ( ) => {
540540 setIsProcessing ( false ) ;
541541 if ( 'mediaSession' in navigator ) {
@@ -549,7 +549,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
549549 } ,
550550 onend : ( ) => {
551551 URL . revokeObjectURL ( audioUrl ) ;
552- howl . unload ( ) ; // Explicitly unload when done
552+ howl . unload ( ) ;
553553 setActiveHowl ( null ) ;
554554 if ( isPlaying ) {
555555 advance ( ) ;
@@ -560,19 +560,18 @@ export function TTSProvider({ children }: { children: ReactNode }) {
560560 setIsProcessing ( false ) ;
561561 setActiveHowl ( null ) ;
562562 URL . revokeObjectURL ( audioUrl ) ;
563- howl . unload ( ) ; // Ensure cleanup on error
564- // Don't auto-advance on load error
563+ howl . unload ( ) ;
565564 setIsPlaying ( false ) ;
566565 } ,
567566 onstop : ( ) => {
568567 setIsProcessing ( false ) ;
569568 URL . revokeObjectURL ( audioUrl ) ;
570- howl . unload ( ) ; // Ensure cleanup on stop
569+ howl . unload ( ) ;
571570 }
572571 } ) ;
573572
574573 setActiveHowl ( howl ) ;
575- howl . play ( ) ;
574+ return howl ;
576575
577576 } catch ( error ) {
578577 console . error ( 'Error playing TTS:' , error ) ;
@@ -588,10 +587,25 @@ export function TTSProvider({ children }: { children: ReactNode }) {
588587 duration : 3000 ,
589588 } ) ;
590589
591- advance ( ) ; // Skip problematic sentence
590+ advance ( ) ;
591+ return null ;
592592 }
593593 } , [ isPlaying , processSentence , advance , activeHowl ] ) ;
594594
595+ const playAudio = useCallback ( async ( ) => {
596+ const howl = await playSentenceWithHowl ( sentences [ currentIndex ] ) ;
597+ if ( howl ) {
598+ howl . play ( ) ;
599+ }
600+ } , [ sentences , currentIndex , playSentenceWithHowl ] ) ;
601+
602+ // Place useBackgroundState after playAudio is defined
603+ const isBackgrounded = useBackgroundState ( {
604+ activeHowl,
605+ isPlaying,
606+ playAudio,
607+ } ) ;
608+
595609 /**
596610 * Preloads the next sentence's audio
597611 */
@@ -609,13 +623,6 @@ export function TTSProvider({ children }: { children: ReactNode }) {
609623 }
610624 } , [ currentIndex , sentences , audioCache , processSentence ] ) ;
611625
612- /**
613- * Plays the current sentence's audio
614- */
615- const playAudio = useCallback ( async ( ) => {
616- await playSentenceWithHowl ( sentences [ currentIndex ] ) ;
617- } , [ sentences , currentIndex , playSentenceWithHowl ] ) ;
618-
619626 /**
620627 * Main Playback Driver
621628 * Controls the flow of audio playback and sentence processing
@@ -625,6 +632,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
625632 if ( isProcessing ) return ; // Don't proceed if processing audio
626633 if ( ! sentences [ currentIndex ] ) return ; // Don't proceed if no sentence to play
627634 if ( activeHowl ) return ; // Don't proceed if audio is already playing
635+ if ( isBackgrounded ) return ; // Don't proceed if backgrounded
628636
629637 // Start playing current sentence
630638 playAudio ( ) ;
@@ -644,6 +652,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
644652 currentIndex ,
645653 sentences ,
646654 activeHowl ,
655+ isBackgrounded ,
647656 playAudio ,
648657 preloadNextAudio ,
649658 abortAudio
@@ -743,6 +752,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
743752 const value = useMemo ( ( ) => ( {
744753 isPlaying,
745754 isProcessing,
755+ isBackgrounded,
746756 currentSentence : sentences [ currentIndex ] || '' ,
747757 currDocPage,
748758 currDocPageNumber,
@@ -764,6 +774,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
764774 } ) , [
765775 isPlaying ,
766776 isProcessing ,
777+ isBackgrounded ,
767778 sentences ,
768779 currentIndex ,
769780 currDocPage ,
0 commit comments