This commit is contained in:
Richard Roberson 2025-01-25 22:08:15 -07:00
parent 96f9dae3ea
commit f7704da4d3
4 changed files with 49 additions and 57 deletions

View file

@ -4,7 +4,7 @@ import dynamic from 'next/dynamic';
import { usePDF } from '@/contexts/PDFContext';
import { useParams } from 'next/navigation';
import Link from 'next/link';
import { useEffect, useState } from 'react';
import { use, useCallback, useEffect, useState } from 'react';
import { PDFSkeleton } from '@/components/PDFSkeleton';
import { useTTS } from '@/contexts/TTSContext';
@ -25,24 +25,26 @@ export default function PDFViewerPage() {
const [isLoading, setIsLoading] = useState(true);
const [zoomLevel, setZoomLevel] = useState<number>(100);
useEffect(() => {
async function loadDocument() {
try {
if (!id) {
setError('Document not found');
return;
}
setCurrentDocument(id as string);
} catch (err) {
console.error('Error loading document:', err);
setError('Failed to load document');
} finally {
setIsLoading(false);
const loadDocument = useCallback(async () => {
if (!isLoading) return; // Prevent calls when not loading new doc
console.log('Loading new document (from page.tsx)');
try {
if (!id) {
setError('Document not found');
return;
}
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();
}, [id, setCurrentDocument]);
}, [loadDocument]);
const handleZoomIn = () => setZoomLevel(prev => Math.min(prev + 10, 200));
const handleZoomOut = () => setZoomLevel(prev => Math.max(prev - 10, 50));

View file

@ -8,8 +8,6 @@ import { useState, useEffect, useRef } from 'react';
import { PDFSkeleton } from './PDFSkeleton';
import { useTTS } from '@/contexts/TTSContext';
import { usePDF } from '@/contexts/PDFContext';
import { pdfjs } from 'react-pdf';
import type { TextItem } from 'pdfjs-dist/types/src/display/api';
import TTSPlayer from '@/components/player/TTSPlayer';
interface PDFViewerProps {

View file

@ -51,7 +51,6 @@ interface PDFContextType {
isProcessing: boolean
) => void;
onDocumentLoadSuccess: ({ numPages }: { numPages: number }) => void;
convertPDFDataToURL: (pdfData: Blob) => Promise<string>;
setCurrentDocument: (id: string) => Promise<void>;
currDocURL: string | undefined;
currDocName: string | undefined;
@ -267,7 +266,7 @@ export function PDFProvider({ children }: { children: ReactNode }) {
console.error('Failed to get document URL:', error);
setError('Failed to retrieve the document. Please try again.');
}
}, [getDocument, convertPDFDataToURL, loadCurrDocText]);
}, [getDocument, loadCurrDocText]);
// Clear all highlights in the PDF viewer
const clearHighlights = useCallback(() => {
@ -458,7 +457,6 @@ export function PDFProvider({ children }: { children: ReactNode }) {
clearHighlights,
handleTextClick,
onDocumentLoadSuccess,
convertPDFDataToURL,
setCurrentDocument,
currDocURL,
currDocName,
@ -478,7 +476,6 @@ export function PDFProvider({ children }: { children: ReactNode }) {
clearHighlights,
handleTextClick,
onDocumentLoadSuccess,
convertPDFDataToURL,
setCurrentDocument,
currDocURL,
currDocName,

View file

@ -89,11 +89,9 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
console.log('Setting page text:', text);
const newSentences = splitIntoSentences(text);
setSentences(newSentences);
//setCurrentIndex(0);
//setIsPlaying(false);
// Clear audio cache
audioCacheRef.current.clear();
//audioCacheRef.current.clear();
setNextPageLoading(false);
}, []);
@ -115,6 +113,31 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
}
});
}, [abortAudio]);
const advance = useCallback(async (backwards = false) => {
setCurrentIndex((prev) => {
const nextIndex = prev + (backwards ? -1 : 1);
if (nextIndex < sentences.length && nextIndex >= 0) {
console.log('Advancing to next sentence:', sentences[nextIndex]);
return nextIndex;
} else if (nextIndex >= sentences.length && currDocPage < currDocPages!) {
console.log('Advancing to next page:', currDocPage + 1);
setNextPageLoading(true);
setCurrDocPage(currDocPage + 1);
return 0;
} else if (nextIndex < 0 && currDocPage > 1) {
console.log('Advancing to previous page:', currDocPage - 1);
setNextPageLoading(true);
setCurrDocPage(currDocPage - 1);
return 0;
}
return prev;
});
}, [sentences, currDocPage, currDocPages]);
const skipForward = useCallback(() => {
@ -122,29 +145,20 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
abortAudio();
setCurrentIndex((prev) => {
const nextIndex = Math.min(prev + 1, sentences.length - 1);
console.log('Skipping forward to:', sentences[nextIndex]);
return nextIndex;
});
advance();
setIsProcessing(false);
}, [sentences, abortAudio]);
}, [abortAudio, advance]);
const skipBackward = useCallback(() => {
setIsProcessing(true);
abortAudio();
setCurrentIndex((prev) => {
const nextIndex = Math.max(prev - 1, 0);
console.log('Skipping backward to:', sentences[nextIndex]);
return nextIndex;
});
advance(true); // Pass true to go backwards
setIsProcessing(false);
}, [sentences, abortAudio]);
}, [abortAudio, advance]);
// Initialize OpenAI instance when config loads
useEffect(() => {
@ -229,30 +243,12 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
}
}, [togglePlay, skipForward, skipBackward]);
const advance = useCallback(async () => {
setCurrentIndex((prev) => {
const nextIndex = prev + 1;
if (nextIndex < sentences.length) {
console.log('Auto-advancing to next sentence:', sentences[nextIndex]);
return nextIndex;
} else if (currDocPage < currDocPages!) {
console.log('Auto-advancing to next page:', currDocPage + 1);
setNextPageLoading(true);
setCurrDocPage(currDocPage + 1);
return 0;
}
return prev;
});
}, [sentences, currDocPage, currDocPages]);
//new function to return audio buffer with caching
const getAudio = useCallback(async (sentence: string): Promise<AudioBuffer | undefined> => {
// Check if the audio is already cached
const cachedAudio = audioCacheRef.current.get(sentence);
if (cachedAudio) {
console.log('Using cached audio for sentence:', sentence);
console.log('Using cached audio for sentence:', sentence.substring(0, 20));
return cachedAudio;
}
@ -350,7 +346,6 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
const preloadNextAudio = useCallback(() => {
try {
if (sentences[currentIndex + 1] && !audioCacheRef.current.has(sentences[currentIndex + 1])) {
//await new Promise((resolve) => setTimeout(resolve, 200)); // Add small delay
processSentence(sentences[currentIndex + 1], true); // True indicates preloading
}
} catch (error) {