@@ -144,6 +144,7 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
144144 const [ redactedImageUrl , setRedactedImageUrl ] = useState < string | null > ( null ) ;
145145 const [ redactedVideoUrl , setRedactedVideoUrl ] = useState < string | null > ( null ) ;
146146 const [ redactedAudioUrl , setRedactedAudioUrl ] = useState < string | null > ( null ) ;
147+ const [ isMediaLoaded , setIsMediaLoaded ] = useState ( false ) ;
147148 // Visualization image is available but not currently displayed in the UI
148149 // const [visualizationImageUrl, setVisualizationImageUrl] = useState<string | null>(null);
149150 const [ isDownloading , setIsDownloading ] = useState ( false ) ;
@@ -153,6 +154,10 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
153154 const isVideo = file . type === "video" ;
154155 const isAudio = file . type === "audio" ;
155156
157+ useEffect ( ( ) => {
158+ setIsMediaLoaded ( false ) ;
159+ } , [ file . url ] ) ;
160+
156161 const handleRedactionSubmit = useCallback ( async ( ) => {
157162 if ( ! redactionPrompt . trim ( ) ) return ;
158163
@@ -510,11 +515,13 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
510515 src = { file . url }
511516 className = "w-full h-full"
512517 title = { `Original: ${ file . name } ` }
518+ onLoad = { ( ) => setIsMediaLoaded ( true ) }
513519 />
514520 ) : isVideo ? (
515521 < div className = "w-full h-full flex items-center justify-center bg-warm-gray/5 dark:bg-stone/5 p-4 overflow-hidden" >
516522 < video
517523 src = { file . url }
524+ onLoadedData = { ( ) => setIsMediaLoaded ( true ) }
518525 controls
519526 className = "max-w-full max-h-full object-contain"
520527 title = { `Original: ${ file . name } ` }
@@ -530,6 +537,7 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
530537 </ p >
531538 < audio
532539 src = { file . url }
540+ onLoadedData = { ( ) => setIsMediaLoaded ( true ) }
533541 controls
534542 className = "w-full max-w-md"
535543 title = { `Original: ${ file . name } ` }
@@ -543,6 +551,7 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
543551 fill
544552 className = "object-contain"
545553 unoptimized
554+ onLoad = { ( ) => setIsMediaLoaded ( true ) }
546555 />
547556 </ div >
548557 ) }
@@ -556,10 +565,10 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
556565 { /* Right Half - Redaction Controls or Preview */ }
557566 < div className = "flex-1 overflow-hidden flex flex-col min-h-0" >
558567 { status === "success" &&
559- ( redactedPdfUrl ||
560- redactedImageUrl ||
561- redactedVideoUrl ||
562- redactedAudioUrl ) ? (
568+ ( redactedPdfUrl ||
569+ redactedImageUrl ||
570+ redactedVideoUrl ||
571+ redactedAudioUrl ) ? (
563572 /* Redacted Preview */
564573 < div className = "flex-1 relative min-h-0 overflow-hidden" >
565574 { isPdf && redactedPdfUrl ? (
@@ -680,7 +689,8 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
680689 < div className = "flex-1 flex items-center justify-center" >
681690 < button
682691 onClick = { ( ) => setShowRedactionInput ( true ) }
683- className = "flex items-center space-x-3 px-6 py-4 rounded-xl bg-purple-500/10 hover:bg-purple-500/20 border-2 border-purple-500/30 hover:border-purple-500/50 transition-all"
692+ disabled = { ! isMediaLoaded }
693+ className = "flex items-center space-x-3 px-6 py-4 rounded-xl bg-purple-500/10 hover:bg-purple-500/20 border-2 border-purple-500/30 hover:border-purple-500/50 transition-all disabled:opacity-50 disabled:blur-sm disabled:cursor-not-allowed"
684694 >
685695 < Sparkles className = "w-6 h-6 text-purple-600 dark:text-purple-400" />
686696 < span className = "text-lg font-medium text-purple-700 dark:text-purple-300" >
@@ -731,22 +741,20 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
731741 < button
732742 type = "button"
733743 onClick = { ( ) => setRedactionMethod ( "blur" ) }
734- className = { `flex-1 px-4 py-2 rounded-lg border transition-colors ${
735- redactionMethod === "blur"
736- ? "border-purple-500 bg-purple-500/10 text-purple-700 dark:text-purple-300"
737- : "border-warm-gray/15 dark:border-stone/15 text-muted-foreground hover:bg-warm-gray/10 dark:hover:bg-stone/10"
738- } `}
744+ className = { `flex-1 px-4 py-2 rounded-lg border transition-colors ${ redactionMethod === "blur"
745+ ? "border-purple-500 bg-purple-500/10 text-purple-700 dark:text-purple-300"
746+ : "border-warm-gray/15 dark:border-stone/15 text-muted-foreground hover:bg-warm-gray/10 dark:hover:bg-stone/10"
747+ } `}
739748 >
740749 Blur
741750 </ button >
742751 < button
743752 type = "button"
744753 onClick = { ( ) => setRedactionMethod ( "pixelate" ) }
745- className = { `flex-1 px-4 py-2 rounded-lg border transition-colors ${
746- redactionMethod === "pixelate"
747- ? "border-purple-500 bg-purple-500/10 text-purple-700 dark:text-purple-300"
748- : "border-warm-gray/15 dark:border-stone/15 text-muted-foreground hover:bg-warm-gray/10 dark:hover:bg-stone/10"
749- } `}
754+ className = { `flex-1 px-4 py-2 rounded-lg border transition-colors ${ redactionMethod === "pixelate"
755+ ? "border-purple-500 bg-purple-500/10 text-purple-700 dark:text-purple-300"
756+ : "border-warm-gray/15 dark:border-stone/15 text-muted-foreground hover:bg-warm-gray/10 dark:hover:bg-stone/10"
757+ } `}
750758 >
751759 Pixelate
752760 </ button >
@@ -756,11 +764,10 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
756764 onClick = { ( ) =>
757765 setRedactionMethod ( "blackbox" )
758766 }
759- className = { `flex-1 px-4 py-2 rounded-lg border transition-colors ${
760- redactionMethod === "blackbox"
761- ? "border-purple-500 bg-purple-500/10 text-purple-700 dark:text-purple-300"
762- : "border-warm-gray/15 dark:border-stone/15 text-muted-foreground hover:bg-warm-gray/10 dark:hover:bg-stone/10"
763- } `}
767+ className = { `flex-1 px-4 py-2 rounded-lg border transition-colors ${ redactionMethod === "blackbox"
768+ ? "border-purple-500 bg-purple-500/10 text-purple-700 dark:text-purple-300"
769+ : "border-warm-gray/15 dark:border-stone/15 text-muted-foreground hover:bg-warm-gray/10 dark:hover:bg-stone/10"
770+ } `}
764771 >
765772 Blackbox
766773 </ button >
@@ -856,13 +863,13 @@ export function RedactModal({ isOpen, onClose, file }: RedactModalProps) {
856863 </ span >
857864 { imageRedactionResult . categories_selected . length >
858865 0 && (
859- < span className = "text-muted-foreground ml-2" >
860- •{ " " }
861- { imageRedactionResult . categories_selected . join (
862- ", " ,
863- ) }
864- </ span >
865- ) }
866+ < span className = "text-muted-foreground ml-2" >
867+ •{ " " }
868+ { imageRedactionResult . categories_selected . join (
869+ ", " ,
870+ ) }
871+ </ span >
872+ ) }
866873 </ >
867874 ) : isVideo && videoRedactionResult ? (
868875 < >
0 commit comments