jbilcke-hf HF staff commited on
Commit
54fce02
1 Parent(s): 6967c22

add thumbnail hover system

Browse files
src/app/interface/video-card/index.tsx CHANGED
@@ -10,6 +10,7 @@ import { VideoInfo } from "@/types"
10
  import { formatDuration } from "@/lib/formatDuration"
11
  import { formatTimeAgo } from "@/lib/formatTimeAgo"
12
  import { isCertifiedUser } from "@/app/certification"
 
13
 
14
  const DefaultAvatar = dynamic(() => import("../default-avatar"), {
15
  loading: () => null,
@@ -31,6 +32,10 @@ export function VideoCard({
31
  const [duration, setDuration] = useState(0)
32
 
33
  const [channelThumbnail, setChannelThumbnail] = useState(video.channel.thumbnail)
 
 
 
 
34
 
35
  const isCompact = layout === "compact"
36
 
@@ -84,15 +89,36 @@ export function VideoCard({
84
  isCompact ? `w-42 h-[94px]` : `aspect-video`
85
  )}
86
  >
87
- <video
88
- ref={ref}
89
- src={video.assetUrl}
90
- className={cn(
91
- `w-full`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  )}
93
- onLoadedMetadata={handleLoad}
94
- muted
95
- />
 
 
 
 
 
 
96
 
97
  <div className={cn(
98
  ``,
 
10
  import { formatDuration } from "@/lib/formatDuration"
11
  import { formatTimeAgo } from "@/lib/formatTimeAgo"
12
  import { isCertifiedUser } from "@/app/certification"
13
+ import { transparentImage } from "@/lib/transparentImage"
14
 
15
  const DefaultAvatar = dynamic(() => import("../default-avatar"), {
16
  loading: () => null,
 
32
  const [duration, setDuration] = useState(0)
33
 
34
  const [channelThumbnail, setChannelThumbnail] = useState(video.channel.thumbnail)
35
+ const [videoThumbnail, setVideoThumbnail] = useState(
36
+ `https://huggingface.co/datasets/jbilcke-hf/ai-tube-index/resolve/main/videos/${video.id}.webp`
37
+ )
38
+ const [videoThumbnailReady, setVideoThumbnailReady] = useState(false)
39
 
40
  const isCompact = layout === "compact"
41
 
 
89
  isCompact ? `w-42 h-[94px]` : `aspect-video`
90
  )}
91
  >
92
+ <div className="relative w-full">
93
+ <video
94
+ ref={ref}
95
+ src={video.assetUrl}
96
+ className={cn(
97
+ `w-full h-full`,
98
+ duration > 0 ? `opacity-100`: 'opacity-0',
99
+ `transition-all duration-500`,
100
+ )}
101
+ onLoadedMetadata={handleLoad}
102
+ muted
103
+ />
104
+ <img
105
+ src={videoThumbnail}
106
+ className={cn(
107
+ `absolute`,
108
+ videoThumbnailReady ? `opacity-100`: 'opacity-0',
109
+ `hover:opacity-0 w-full h-full top-0 z-30`,
110
+ //`pointer-events-none`,
111
+ `transition-all duration-500 hover:delay-200 ease-in-out`,
112
  )}
113
+ onLoad={() => {
114
+ setVideoThumbnailReady(true)
115
+ }}
116
+ onError={() => {
117
+ setVideoThumbnail(transparentImage)
118
+ setVideoThumbnailReady(false)
119
+ }}
120
+ />
121
+ </div>
122
 
123
  <div className={cn(
124
  ``,
src/lib/transparentImage.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ export const transparentImage = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=`