@@ -9,7 +9,14 @@ import { DownloadIcon, CheckCircleIcon, XCircleIcon, ClockIcon, ChevronUpDownIco
99import { ConfirmDialog } from '@/components/ConfirmDialog' ;
1010import { LoadingSpinner } from '@/components/Spinner' ;
1111import { useConfig } from '@/contexts/ConfigContext' ;
12- import type { TTSAudiobookChapter } from '@/types/tts' ;
12+ import type { TTSAudiobookChapter , TTSAudiobookFormat } from '@/types/tts' ;
13+ import {
14+ getAudiobookStatus ,
15+ deleteAudiobookChapter ,
16+ deleteAudiobook ,
17+ downloadAudiobookChapter ,
18+ downloadAudiobook
19+ } from '@/lib/client' ;
1320interface AudiobookExportModalProps {
1421 isOpen : boolean ;
1522 setIsOpen : ( isOpen : boolean ) => void ;
@@ -19,12 +26,12 @@ interface AudiobookExportModalProps {
1926 onProgress : ( progress : number ) => void ,
2027 signal : AbortSignal ,
2128 onChapterComplete : ( chapter : TTSAudiobookChapter ) => void ,
22- format : 'mp3' | 'm4b'
29+ format : TTSAudiobookFormat
2330 ) => Promise < string > ; // Returns bookId
2431 onRegenerateChapter ?: (
2532 chapterIndex : number ,
2633 bookId : string ,
27- format : 'mp3' | 'm4b' ,
34+ format : TTSAudiobookFormat ,
2835 signal : AbortSignal
2936 ) => Promise < TTSAudiobookChapter > ;
3037}
@@ -46,7 +53,7 @@ export function AudiobookExportModal({
4653 const [ isLoadingExisting , setIsLoadingExisting ] = useState ( false ) ;
4754 const [ isRefreshingChapters , setIsRefreshingChapters ] = useState ( false ) ;
4855 const [ currentChapter , setCurrentChapter ] = useState < string > ( '' ) ;
49- const [ format , setFormat ] = useState < 'mp3' | 'm4b' > ( 'm4b' ) ;
56+ const [ format , setFormat ] = useState < TTSAudiobookFormat > ( 'm4b' ) ;
5057 const [ regeneratingChapter , setRegeneratingChapter ] = useState < number | null > ( null ) ;
5158 const abortControllerRef = useRef < AbortController | null > ( null ) ;
5259 const [ pendingDeleteChapter , setPendingDeleteChapter ] = useState < TTSAudiobookChapter | null > ( null ) ;
@@ -61,26 +68,23 @@ export function AudiobookExportModal({
6168 setIsLoadingExisting ( true ) ;
6269 }
6370 try {
64- const response = await fetch ( `/api/audiobook/status?bookId=${ documentId } ` ) ;
65- if ( response . ok ) {
66- const data = await response . json ( ) ;
67- if ( data . exists && data . chapters . length > 0 ) {
68- setChapters ( data . chapters ) ;
69- setBookId ( data . bookId ) ;
70- // Set format from existing chapters - this ensures the format matches what was actually generated
71- if ( data . chapters [ 0 ] ?. format ) {
72- const detectedFormat = data . chapters [ 0 ] . format as 'mp3' | 'm4b' ;
73- setFormat ( detectedFormat ) ;
74- }
75- // If we have a complete audiobook, we're done
76- if ( data . hasComplete ) {
77- setProgress ( 100 ) ;
78- }
79- } else {
80- // If nothing exists, clear chapters/bookId to reflect current state
81- setChapters ( [ ] ) ;
82- setBookId ( null ) ;
71+ const data = await getAudiobookStatus ( documentId ) ;
72+ if ( data . exists && data . chapters . length > 0 ) {
73+ setChapters ( data . chapters ) ;
74+ setBookId ( data . bookId ) ;
75+ // Set format from existing chapters - this ensures the format matches what was actually generated
76+ if ( data . chapters [ 0 ] ?. format ) {
77+ const detectedFormat = data . chapters [ 0 ] . format as TTSAudiobookFormat ;
78+ setFormat ( detectedFormat ) ;
8379 }
80+ // If we have a complete audiobook, we're done
81+ if ( data . hasComplete ) {
82+ setProgress ( 100 ) ;
83+ }
84+ } else {
85+ // If nothing exists, clear chapters/bookId to reflect current state
86+ setChapters ( [ ] ) ;
87+ setBookId ( null ) ;
8488 }
8589 } catch ( error ) {
8690 console . error ( 'Error fetching existing chapters:' , error ) ;
@@ -241,12 +245,7 @@ export function AudiobookExportModal({
241245 const performDeleteChapter = useCallback ( async ( ) => {
242246 if ( ! bookId || ! pendingDeleteChapter ) return ;
243247 try {
244- const response = await fetch ( `/api/audiobook/chapter?bookId=${ bookId } &chapterIndex=${ pendingDeleteChapter . index } ` , {
245- method : 'DELETE'
246- } ) ;
247- if ( ! response . ok ) {
248- throw new Error ( 'Delete failed' ) ;
249- }
248+ await deleteAudiobookChapter ( bookId , pendingDeleteChapter . index ) ;
250249 setChapters ( prev => prev . filter ( c => c . index !== pendingDeleteChapter . index ) ) ;
251250 await fetchExistingChapters ( true ) ;
252251 } catch ( error ) {
@@ -261,10 +260,7 @@ export function AudiobookExportModal({
261260 const targetBookId = bookId || documentId ;
262261 if ( ! targetBookId ) return ;
263262 try {
264- const resp = await fetch ( `/api/audiobook?bookId=${ targetBookId } ` , { method : 'DELETE' } ) ;
265- if ( ! resp . ok ) {
266- throw new Error ( 'Reset failed' ) ;
267- }
263+ await deleteAudiobook ( targetBookId ) ;
268264 setChapters ( [ ] ) ;
269265 setBookId ( null ) ;
270266 setProgress ( 0 ) ;
@@ -281,10 +277,7 @@ export function AudiobookExportModal({
281277 if ( ! chapter . bookId ) return ;
282278
283279 try {
284- const response = await fetch ( `/api/audiobook/chapter?bookId=${ chapter . bookId } &chapterIndex=${ chapter . index } ` ) ;
285- if ( ! response . ok ) throw new Error ( 'Download failed' ) ;
286-
287- const blob = await response . blob ( ) ;
280+ const blob = await downloadAudiobookChapter ( chapter . bookId , chapter . index ) ;
288281 const url = URL . createObjectURL ( blob ) ;
289282 const a = document . createElement ( 'a' ) ;
290283 a . href = url ;
@@ -306,8 +299,7 @@ export function AudiobookExportModal({
306299
307300 setIsCombining ( true ) ;
308301 try {
309- const response = await fetch ( `/api/audiobook?bookId=${ bookId } &format=${ format } ` ) ;
310- if ( ! response . ok ) throw new Error ( 'Download failed' ) ;
302+ const response = await downloadAudiobook ( bookId , format ) ;
311303
312304 const reader = response . body ?. getReader ( ) ;
313305 if ( ! reader ) throw new Error ( 'No response body' ) ;
0 commit comments