@@ -47,10 +47,10 @@ type Video = {
4747 smallThumbnailUrl ?: string | null ;
4848 triggerAccessToken ?: string ;
4949 videoLengthSeconds ?: number | null ;
50- isProcessing : boolean ;
50+ status : "uploading" | "processing" | "ready" | "deleting" ;
5151 isPrivate : boolean ;
5252 createdAt : string ;
53- deletionDate ?: string | null ;
53+ pendingDeletionDate ?: string | null ;
5454} ;
5555
5656export function VideosBoard ( { videos } : { videos : Video [ ] } ) {
@@ -85,24 +85,17 @@ function UploadedVideo({ video }: { video: Video }) {
8585 className = "dark relative bg-card rounded-lg overflow-hidden shadow-md transition-shadow duration-300 ease-in-out hover:shadow-lg group aspect-video border-border/50 hover:border-border flex flex-col justify-between"
8686 >
8787 < div className = "absolute inset-0" >
88- { video . smallThumbnailUrl ? (
89- < img
90- src = { video . smallThumbnailUrl }
91- alt = { `${ video . title } thumbnail` }
92- className = "transition-transform duration-200 ease-in-out group-hover:scale-105 w-full"
93- />
94- ) : (
95- < TriggerAuthContext . Provider
96- value = { { accessToken : video . triggerAccessToken } }
97- >
98- < ThumbnailPlaceholder videoId = { video . id } />
99- </ TriggerAuthContext . Provider >
100- ) }
101- < div className = "absolute inset-0 bg-black bg-opacity-60 transition-opacity duration-300 ease-in-out group-hover:bg-opacity-40" />
88+ < VideoThumbnail
89+ smallThumbnailUrl = { video . smallThumbnailUrl }
90+ title = { video . title }
91+ videoId = { video . id }
92+ triggerAccessToken = { video . triggerAccessToken }
93+ />
94+ < div className = "absolute inset-0 bg-black bg-opacity-40 transition-opacity duration-300 ease-in-out group-hover:bg-opacity-20" />
10295 </ div >
10396 < div className = "absolute right-0 text-xs flex gap-1 m-1" >
104- { ! ! video . deletionDate && (
105- < PendingDeletionChip deletionDate = { video . deletionDate } />
97+ { ! ! video . pendingDeletionDate && (
98+ < PendingDeletionChip deletionDate = { video . pendingDeletionDate } />
10699 ) }
107100 { ! Number . isNaN ( Number . parseFloat ( `${ video . videoLengthSeconds } ` ) ) && (
108101 < span className = "p-1 bg-black/50 rounded-md backdrop-blur-md" >
@@ -199,11 +192,49 @@ function UploadedVideo({ video }: { video: Video }) {
199192 ) ;
200193}
201194
195+ type VideoThumbnailProps = {
196+ smallThumbnailUrl ?: string | null ;
197+ title : string ;
198+ videoId : string ;
199+ triggerAccessToken ?: string ;
200+ } ;
201+
202+ function VideoThumbnail ( {
203+ smallThumbnailUrl,
204+ title,
205+ triggerAccessToken,
206+ videoId,
207+ } : VideoThumbnailProps ) {
208+ if ( smallThumbnailUrl ) {
209+ return (
210+ < img
211+ src = { smallThumbnailUrl }
212+ alt = { `Thumbnail for ${ title } ` }
213+ className = "transition-transform duration-200 ease-in-out group-hover:scale-105 w-full"
214+ loading = "lazy"
215+ decoding = "async"
216+ draggable = "false"
217+ />
218+ ) ;
219+ }
220+
221+ if ( triggerAccessToken ) {
222+ return (
223+ < TriggerAuthContext . Provider value = { { accessToken : triggerAccessToken } } >
224+ < ThumbnailPlaceholder videoId = { videoId } />
225+ </ TriggerAuthContext . Provider >
226+ ) ;
227+ }
228+
229+ return null ;
230+ }
231+
202232type ThumbnailPlaceholderProps = {
203233 videoId : string ;
204234} ;
235+
205236function ThumbnailPlaceholder ( props : ThumbnailPlaceholderProps ) {
206- const { runs } = useRealtimeRunsWithTag ( `video-processing- ${ props . videoId } ` ) ;
237+ const { runs } = useRealtimeRunsWithTag ( `videoProcessing_ ${ props . videoId } ` ) ;
207238
208239 useEffect ( ( ) => {
209240 for ( const run of runs ) {
0 commit comments