@@ -32,7 +32,10 @@ import { useDashboardContext } from "@/app/(org)/dashboard/Contexts";
3232import ProgressCircle , {
3333 useUploadProgress ,
3434} from "@/app/s/[videoId]/_components/ProgressCircle" ;
35- import { VideoThumbnail } from "@/components/VideoThumbnail" ;
35+ import {
36+ ImageLoadingStatus ,
37+ VideoThumbnail ,
38+ } from "@/components/VideoThumbnail" ;
3639import { useEffectMutation } from "@/lib/EffectRuntime" ;
3740import { withRpc } from "@/lib/Rpcs" ;
3841import { PasswordDialog } from "../PasswordDialog" ;
@@ -172,6 +175,7 @@ export const CapCard = ({
172175 cap . id ,
173176 cap . hasActiveUpload || false ,
174177 ) ;
178+ const [ imageStatus , setImageStatus ] = useState < ImageLoadingStatus > ( "loading" ) ;
175179
176180 // Helper function to create a drag preview element
177181 const createDragPreview = ( text : string ) : HTMLElement => {
@@ -496,87 +500,72 @@ export const CapCard = ({
496500 </ div >
497501 </ div >
498502 ) }
503+
499504 < div className = "relative" >
500505 < Link
501506 className = { clsx (
502- "block group" ,
507+ "relative" ,
508+ // "block group",
503509 anyCapSelected && "cursor-pointer pointer-events-none" ,
504510 ) }
505511 onClick = { ( e ) => {
506512 if ( isDeleting ) e . preventDefault ( ) ;
507513 } }
508514 href = { `/s/${ cap . id } ` }
509515 >
510- { uploadProgress ? (
511- < div className = "overflow-hidden relative mx-auto w-full h-full rounded-t-xl border-b border-gray-3 aspect-video bg-black z-5" >
512- < div className = "flex absolute inset-0 justify-center items-center rounded-t-xl" >
513- { uploadProgress . status === "failed" ? (
514- < div className = "flex flex-col items-center" >
515- < div className = "flex justify-center items-center mb-2 w-8 h-8 bg-red-500 rounded-full" >
516- < FontAwesomeIcon
517- icon = { faVideo }
518- className = "text-white size-3"
516+ { imageStatus !== "success" && uploadProgress ? (
517+ < div className = "absolute inset-0 w-full h-full z-20" >
518+ < div className = "overflow-hidden relative mx-auto w-full h-full rounded-t-xl border-b border-gray-3 aspect-video bg-black z-5" >
519+ < div className = "flex absolute inset-0 justify-center items-center rounded-t-xl" >
520+ { uploadProgress . status === "failed" ? (
521+ < div className = "flex flex-col items-center" >
522+ < div className = "flex justify-center items-center mb-2 w-8 h-8 bg-red-500 rounded-full" >
523+ < FontAwesomeIcon
524+ icon = { faVideo }
525+ className = "text-white size-3"
526+ />
527+ </ div >
528+ < p className = "text-[13px] text-center text-white" >
529+ Upload failed
530+ </ p >
531+ </ div >
532+ ) : (
533+ < div className = "relative size-20 md:size-16" >
534+ < ProgressCircle
535+ progressTextClassName = "md:!text-[11px]"
536+ subTextClassName = "!mt-0 md:!text-[7px] !text-[10px] mb-1"
537+ className = "md:scale-[1.5] scale-[1.2]"
538+ progress = { uploadProgress . progress }
519539 />
520540 </ div >
521- < p className = "text-[13px] text-center text-white" >
522- Upload failed
523- </ p >
524- </ div >
525- ) : (
526- < div className = "relative size-20 md:size-16" >
527- < ProgressCircle
528- progressTextClassName = "md:!text-[11px]"
529- subTextClassName = "!mt-0 md:!text-[7px] !text-[10px] mb-1"
530- className = "md:scale-[1.5] scale-[1.2]"
531- progress = { uploadProgress . progress }
532- />
533- </ div >
534- ) }
535- </ div >
536- </ div >
537- ) : (
538- < VideoThumbnail
539- videoDuration = { cap . duration }
540- imageClass = { clsx (
541- anyCapSelected
542- ? "opacity-50"
543- : isDropdownOpen
544- ? "opacity-30"
545- : "group-hover:opacity-30" ,
546- "transition-opacity duration-200" ,
547- // uploadProgress && "opacity-30",
548- ) }
549- videoId = { cap . id }
550- alt = { `${ cap . name } Thumbnail` }
551- />
552- ) }
553- </ Link >
554- { uploadProgress && (
555- < div className = "flex absolute inset-0 z-50 justify-center items-center bg-black rounded-t-xl" >
556- { uploadProgress . status === "failed" ? (
557- < div className = "flex flex-col items-center" >
558- < div className = "flex justify-center items-center mb-2 w-8 h-8 bg-red-500 rounded-full" >
559- < FontAwesomeIcon
560- icon = { faVideo }
561- className = "text-white size-3"
562- />
541+ ) }
563542 </ div >
564- < p className = "text-[13px] text-center text-white" >
565- Upload failed
566- </ p >
567- </ div >
568- ) : (
569- < div className = "relative size-20 md:size-16" >
570- < ProgressCircle
571- progressTextClassName = "md:!text-[11px]"
572- subTextClassName = "!mt-0 md:!text-[7px] !text-[10px] mb-1"
573- className = "md:scale-[1.5] scale-[1.2]"
574- progress = { uploadProgress . progress }
575- />
576543 </ div >
544+ </ div >
545+ ) : null }
546+
547+ < VideoThumbnail
548+ videoDuration = { cap . duration }
549+ imageClass = { clsx (
550+ anyCapSelected
551+ ? "opacity-50"
552+ : isDropdownOpen
553+ ? "opacity-30"
554+ : "group-hover:opacity-30" ,
555+ "transition-opacity duration-200" ,
577556 ) }
578- </ div >
579- ) }
557+ containerClass = { clsx (
558+ imageStatus !== "success" && uploadProgress
559+ ? "display-none"
560+ : "" ,
561+ "absolute inset-0" ,
562+ ) }
563+ videoId = { cap . id }
564+ alt = { `${ cap . name } Thumbnail` }
565+ imageStatus = { imageStatus }
566+ setImageStatus = { setImageStatus }
567+ />
568+ </ Link >
580569 </ div >
581570 < div
582571 className = { clsx (
0 commit comments