@@ -41,9 +41,11 @@ export default function Artifacts({ projectId, papers }: ArtifactsProps) {
41
41
const [ audioInstructions , setAudioInstructions ] = useState ( "" ) ;
42
42
const [ selectedAudioLength , setSelectedAudioLength ] = useState ( "medium" ) ;
43
43
const [ isCreatingAudio , setIsCreatingAudio ] = useState ( false ) ;
44
+ const [ isCreateAudioDialogOpen , setCreateAudioDialogOpen ] = useState ( false ) ;
44
45
const [ audioOverviews , setAudioOverviews ] = useState < AudioOverview [ ] > ( [ ] ) ;
45
46
const [ audioJobs , setAudioJobs ] = useState < AudioOverviewJob [ ] > ( [ ] ) ;
46
47
const [ playingAudioId , setPlayingAudioId ] = useState < string | null > ( null ) ;
48
+ const [ activatedAudioIds , setActivatedAudioIds ] = useState < string [ ] > ( [ ] ) ;
47
49
const [ loadingAudioId , setLoadingAudioId ] = useState < string | null > ( null ) ;
48
50
const [ pollingInterval , setPollingInterval ] = useState < NodeJS . Timeout | null > ( null ) ;
49
51
const [ audioProgress , setAudioProgress ] = useState < { [ key : string ] : { currentTime : number ; duration : number } } > ( { } ) ;
@@ -117,6 +119,7 @@ export default function Artifacts({ projectId, papers }: ArtifactsProps) {
117
119
} , [ projectId , getProjectAudioOverviews , getProjectAudioJobs , startPolling , stopPolling ] ) ;
118
120
119
121
const handleCreateAudioOverview = async ( ) => {
122
+ setCreateAudioDialogOpen ( false ) ;
120
123
setIsCreatingAudio ( true ) ;
121
124
try {
122
125
const requestData = {
@@ -209,6 +212,9 @@ export default function Artifacts({ projectId, papers }: ArtifactsProps) {
209
212
} ;
210
213
}
211
214
215
+ if ( ! activatedAudioIds . includes ( audioOverviewId ) ) {
216
+ setActivatedAudioIds ( prev => [ ...prev , audioOverviewId ] ) ;
217
+ }
212
218
audio . play ( ) ;
213
219
}
214
220
} catch ( err ) {
@@ -268,7 +274,7 @@ export default function Artifacts({ projectId, papers }: ArtifactsProps) {
268
274
</ div >
269
275
270
276
< div className = "flex flex-wrap gap-3" >
271
- < Dialog >
277
+ < Dialog open = { isCreateAudioDialogOpen } onOpenChange = { setCreateAudioDialogOpen } >
272
278
< DialogTrigger asChild >
273
279
< button
274
280
disabled = { papers . length === 0 }
@@ -388,7 +394,6 @@ export default function Artifacts({ projectId, papers }: ArtifactsProps) {
388
394
< RichAudioOverview
389
395
audioOverview = { overview }
390
396
papers = { papers || [ ] }
391
- onClose = { ( ) => { } }
392
397
/>
393
398
</ div >
394
399
</ DialogContent >
@@ -397,82 +402,86 @@ export default function Artifacts({ projectId, papers }: ArtifactsProps) {
397
402
</ div >
398
403
</ div >
399
404
400
- { /* Progress Bar */ }
401
- < div className = "mb-3" >
402
- < div className = "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1" >
403
- < span > { progress ? formatTime ( progress . currentTime ) : '0:00' } </ span >
404
- < span > { progress ? formatTime ( progress . duration ) : '0:00' } </ span >
405
- </ div >
406
- < div className = "relative" >
407
- < div className = "w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden" >
408
- < div
409
- className = "h-full bg-blue-500 transition-all duration-100"
410
- style = { { width : `${ progressPercentage } %` } }
411
- />
405
+ { activatedAudioIds . includes ( overview . id ) && (
406
+ < >
407
+ { /* Progress Bar */ }
408
+ < div className = "mb-3" >
409
+ < div className = "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1" >
410
+ < span > { progress ? formatTime ( progress . currentTime ) : '0:00' } </ span >
411
+ < span > { progress ? formatTime ( progress . duration ) : '0:00' } </ span >
412
+ </ div >
413
+ < div className = "relative" >
414
+ < div className = "w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden" >
415
+ < div
416
+ className = "h-full bg-blue-500 transition-all duration-100"
417
+ style = { { width : `${ progressPercentage } %` } }
418
+ />
419
+ </ div >
420
+ < input
421
+ type = "range"
422
+ min = "0"
423
+ max = "100"
424
+ value = { progressPercentage }
425
+ onChange = { ( e ) => handleSeek ( overview . id , Number ( e . target . value ) ) }
426
+ className = "absolute inset-0 w-full h-full opacity-0 cursor-pointer"
427
+ />
428
+ </ div >
412
429
</ div >
413
- < input
414
- type = "range"
415
- min = "0"
416
- max = "100"
417
- value = { progressPercentage }
418
- onChange = { ( e ) => handleSeek ( overview . id , Number ( e . target . value ) ) }
419
- className = "absolute inset-0 w-full h-full opacity-0 cursor-pointer"
420
- />
421
- </ div >
422
- </ div >
423
430
424
- { /* Controls */ }
425
- < div className = "flex items-center justify-between" >
426
- < div className = "flex items-center space-x-2" >
427
- < button
428
- onClick = { ( ) => skipBackward ( overview . id ) }
429
- className = "p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
430
- title = "Skip back 10s"
431
- >
432
- < RotateCcw className = "w-4 h-4" />
433
- </ button >
434
- < button
435
- onClick = { ( ) => skipForward ( overview . id ) }
436
- className = "p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
437
- title = "Skip forward 10s"
438
- >
439
- < RotateCcw className = "w-4 h-4 scale-x-[-1]" />
440
- </ button >
441
- </ div >
442
-
443
- < div className = "flex items-center space-x-3" >
444
- { /* Volume Control */ }
445
- < div className = "flex items-center space-x-1" >
446
- < Volume2 className = "w-3 h-3 text-gray-500 dark:text-gray-400" />
447
- < input
448
- type = "range"
449
- min = "0"
450
- max = "1"
451
- step = "0.01"
452
- value = { volume }
453
- onChange = { ( e ) => handleVolumeChange ( overview . id , Number ( e . target . value ) ) }
454
- className = "w-16 h-1 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
455
- />
456
- </ div >
457
-
458
- { /* Speed Control */ }
459
- < div className = "flex space-x-1" >
460
- { [ 0.75 , 1 , 1.25 , 1.5 , 2 ] . map ( ( speedOption ) => (
431
+ { /* Controls */ }
432
+ < div className = "flex items-center justify-between" >
433
+ < div className = "flex items-center space-x-2" >
434
+ < button
435
+ onClick = { ( ) => skipBackward ( overview . id ) }
436
+ className = "p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
437
+ title = "Skip back 10s"
438
+ >
439
+ < RotateCcw className = "w-4 h-4" />
440
+ </ button >
461
441
< button
462
- key = { speedOption }
463
- onClick = { ( ) => handleSpeedChange ( overview . id , speedOption ) }
464
- className = { `px-2 py-1 text-xs rounded ${
465
- speed === speedOption
466
- ? 'bg-blue-600 text-white'
467
- : 'bg-gray-200 text-gray-700 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600'
468
- } transition-colors`}
442
+ onClick = { ( ) => skipForward ( overview . id ) }
443
+ className = "p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
444
+ title = "Skip forward 10s"
469
445
>
470
- { speedOption } x
446
+ < RotateCcw className = "w-4 h-4 scale-x-[-1]" />
471
447
</ button >
472
- ) ) }
448
+ </ div >
449
+
450
+ < div className = "flex items-center space-x-3" >
451
+ { /* Volume Control */ }
452
+ < div className = "flex items-center space-x-1" >
453
+ < Volume2 className = "w-3 h-3 text-gray-500 dark:text-gray-400" />
454
+ < input
455
+ type = "range"
456
+ min = "0"
457
+ max = "1"
458
+ step = "0.01"
459
+ value = { volume }
460
+ onChange = { ( e ) => handleVolumeChange ( overview . id , Number ( e . target . value ) ) }
461
+ className = "w-16 h-1 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
462
+ />
463
+ </ div >
464
+
465
+ { /* Speed Control */ }
466
+ < div className = "flex space-x-1" >
467
+ { [ 0.75 , 1 , 1.25 , 1.5 , 2 ] . map ( ( speedOption ) => (
468
+ < button
469
+ key = { speedOption }
470
+ onClick = { ( ) => handleSpeedChange ( overview . id , speedOption ) }
471
+ className = { `px-2 py-1 text-xs rounded ${
472
+ speed === speedOption
473
+ ? 'bg-blue-600 text-white'
474
+ : 'bg-gray-200 text-gray-700 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600'
475
+ } transition-colors`}
476
+ >
477
+ { speedOption } x
478
+ </ button >
479
+ ) ) }
480
+ </ div >
481
+ </ div >
473
482
</ div >
474
- </ div >
475
- </ div >
483
+ </ >
484
+ ) }
476
485
</ div >
477
486
) ;
478
487
} ) }
0 commit comments