jbilcke-hf HF staff commited on
Commit
80ea539
1 Parent(s): a2c7711

separate user account classes

Browse files
src/app/certification.ts ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // for the moment only Hugging Face employees can be certified,
2
+ // but it might be given to a select few high-profile partners
3
+ // normal users don't need to be certified to enjoy the platform
4
+ export const certifiedUsers = new Set([
5
+ "jbilcke-hf",
6
+ "merve",
7
+ "xenova"
8
+ ])
9
+
10
+ export function isCertifiedUser(username: string): boolean {
11
+ return certifiedUsers.has(username.trim().toLowerCase())
12
+ }
src/app/interface/channel-card/index.tsx CHANGED
@@ -1,10 +1,15 @@
1
  import { useState } from "react"
 
2
 
3
  import { cn } from "@/lib/utils"
4
  import { ChannelInfo } from "@/types"
 
 
5
 
6
- const defaultChannelThumbnail = "/huggingface-avatar.jpeg"
7
-
 
 
8
  export function ChannelCard({
9
  channel,
10
  onClick,
@@ -18,8 +23,8 @@ export function ChannelCard({
18
 
19
  const handleBadChannelThumbnail = () => {
20
  try {
21
- if (channelThumbnail !== defaultChannelThumbnail) {
22
- setChannelThumbnail(defaultChannelThumbnail)
23
  }
24
  } catch (err) {
25
 
@@ -52,10 +57,18 @@ export function ChannelCard({
52
  `w-26 h-26`
53
  )}
54
  >
55
- <img
56
- src={channelThumbnail}
57
- onError={handleBadChannelThumbnail}
58
- />
 
 
 
 
 
 
 
 
59
  </div>
60
 
61
  <div className={cn(
@@ -70,8 +83,9 @@ export function ChannelCard({
70
  } target="_blank">@{channel.datasetUser}</a>
71
  </div>
72
  */}
73
- <div className="text-center text-xs font-medium">
74
- @{channel.datasetUser}
 
75
  </div>
76
  <div className="flex flex-row items-center justify-center text-neutral-400">
77
  <div className="text-center text-xs">{0} videos</div>
 
1
  import { useState } from "react"
2
+ import dynamic from "next/dynamic"
3
 
4
  import { cn } from "@/lib/utils"
5
  import { ChannelInfo } from "@/types"
6
+ import { isCertifiedUser } from "@/app/certification"
7
+ import { RiCheckboxCircleFill } from "react-icons/ri"
8
 
9
+ const DefaultAvatar = dynamic(() => import("../default-avatar"), {
10
+ loading: () => null,
11
+ })
12
+
13
  export function ChannelCard({
14
  channel,
15
  onClick,
 
23
 
24
  const handleBadChannelThumbnail = () => {
25
  try {
26
+ if (channelThumbnail) {
27
+ setChannelThumbnail("")
28
  }
29
  } catch (err) {
30
 
 
57
  `w-26 h-26`
58
  )}
59
  >
60
+ {channelThumbnail ?
61
+ <img
62
+ src={channelThumbnail}
63
+ onError={handleBadChannelThumbnail}
64
+ />
65
+ : <DefaultAvatar
66
+ username={channel.datasetUser}
67
+ bgColor="#fde047"
68
+ textColor="#1c1917"
69
+ width={104}
70
+ roundShape
71
+ />}
72
  </div>
73
 
74
  <div className={cn(
 
83
  } target="_blank">@{channel.datasetUser}</a>
84
  </div>
85
  */}
86
+ <div className="flex flex-row items-center space-x-0.5">
87
+ <div className="flex flex-row items-center text-center text-xs font-medium">@{channel.datasetUser}</div>
88
+ {isCertifiedUser(channel.datasetUser) ? <div className="text-xs text-neutral-400"><RiCheckboxCircleFill className="" /></div> : null}
89
  </div>
90
  <div className="flex flex-row items-center justify-center text-neutral-400">
91
  <div className="text-center text-xs">{0} videos</div>
src/app/interface/video-card/index.tsx CHANGED
@@ -9,6 +9,7 @@ import { cn } from "@/lib/utils"
9
  import { VideoInfo } from "@/types"
10
  import { formatDuration } from "@/lib/formatDuration"
11
  import { formatTimeAgo } from "@/lib/formatTimeAgo"
 
12
 
13
  const DefaultAvatar = dynamic(() => import("../default-avatar"), {
14
  loading: () => null,
@@ -150,7 +151,7 @@ export function VideoCard({
150
  isCompact ? `text-xs` : `text-sm`
151
  )}>
152
  <div>{video.channel.label}</div>
153
- <div><RiCheckboxCircleFill className="" /></div>
154
  </div>
155
 
156
  <div className={cn(
 
9
  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,
 
151
  isCompact ? `text-xs` : `text-sm`
152
  )}>
153
  <div>{video.channel.label}</div>
154
+ {isCertifiedUser(video.channel.datasetUser) ? <div><RiCheckboxCircleFill className="" /></div> : null}
155
  </div>
156
 
157
  <div className={cn(
src/app/views/public-video-view/index.tsx CHANGED
@@ -1,6 +1,7 @@
1
  "use client"
2
 
3
  import { useEffect, useState } from "react"
 
4
  import { RiCheckboxCircleFill } from "react-icons/ri"
5
  import { PiShareFatLight } from "react-icons/pi"
6
  import CopyToClipboard from "react-copy-to-clipboard"
@@ -14,7 +15,12 @@ import { VideoPlayer } from "@/app/interface/video-player"
14
  import { VideoInfo } from "@/types"
15
  import { ActionButton } from "@/app/interface/action-button"
16
  import { RecommendedVideos } from "@/app/interface/recommended-videos"
 
17
 
 
 
 
 
18
 
19
  export function PublicVideoView() {
20
  const video = useStore(s => s.publicVideo)
@@ -23,6 +29,8 @@ export function PublicVideoView() {
23
 
24
  const [copied, setCopied] = useState<boolean>(false)
25
 
 
 
26
  // we inject the current videoId in the URL, if it's not already present
27
  // this is a hack for Hugging Face iframes
28
  useEffect(() => {
@@ -48,6 +56,18 @@ export function PublicVideoView() {
48
  }, 2000)
49
  }
50
  }, [copied])
 
 
 
 
 
 
 
 
 
 
 
 
51
  if (!video) { return null }
52
 
53
  return (
@@ -104,9 +124,22 @@ export function PublicVideoView() {
104
  `mr-3`
105
  )}>
106
  <div className="flex w-10 rounded-full overflow-hidden">
107
- <img
108
- src="huggingface-avatar.jpeg"
109
- />
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  </div>
111
  </div>
112
 
@@ -119,7 +152,7 @@ export function PublicVideoView() {
119
  `text-zinc-100 text-base font-medium space-x-1`,
120
  )}>
121
  <div>{video.channel.label}</div>
122
- <div className="text-sm text-neutral-400"><RiCheckboxCircleFill className="" /></div>
123
  </div>
124
  <div className={cn(
125
  `flex flex-row items-center`,
 
1
  "use client"
2
 
3
  import { useEffect, useState } from "react"
4
+ import dynamic from "next/dynamic"
5
  import { RiCheckboxCircleFill } from "react-icons/ri"
6
  import { PiShareFatLight } from "react-icons/pi"
7
  import CopyToClipboard from "react-copy-to-clipboard"
 
15
  import { VideoInfo } from "@/types"
16
  import { ActionButton } from "@/app/interface/action-button"
17
  import { RecommendedVideos } from "@/app/interface/recommended-videos"
18
+ import { isCertifiedUser } from "@/app/certification"
19
 
20
+ const DefaultAvatar = dynamic(() => import("../../interface/default-avatar"), {
21
+ loading: () => null,
22
+ })
23
+
24
 
25
  export function PublicVideoView() {
26
  const video = useStore(s => s.publicVideo)
 
29
 
30
  const [copied, setCopied] = useState<boolean>(false)
31
 
32
+ const [channelThumbnail, setChannelThumbnail] = useState(`${video?.channel.thumbnail || ""}`)
33
+
34
  // we inject the current videoId in the URL, if it's not already present
35
  // this is a hack for Hugging Face iframes
36
  useEffect(() => {
 
56
  }, 2000)
57
  }
58
  }, [copied])
59
+
60
+
61
+ const handleBadChannelThumbnail = () => {
62
+ try {
63
+ if (channelThumbnail) {
64
+ setChannelThumbnail("")
65
+ }
66
+ } catch (err) {
67
+
68
+ }
69
+ }
70
+
71
  if (!video) { return null }
72
 
73
  return (
 
124
  `mr-3`
125
  )}>
126
  <div className="flex w-10 rounded-full overflow-hidden">
127
+ {
128
+ channelThumbnail ? <div className="flex flex-col">
129
+ <div className="flex w-9 rounded-full overflow-hidden">
130
+ <img
131
+ src={channelThumbnail}
132
+ onError={handleBadChannelThumbnail}
133
+ />
134
+ </div>
135
+ </div>
136
+ : <DefaultAvatar
137
+ username={video.channel.datasetUser}
138
+ bgColor="#fde047"
139
+ textColor="#1c1917"
140
+ width={36}
141
+ roundShape
142
+ />}
143
  </div>
144
  </div>
145
 
 
152
  `text-zinc-100 text-base font-medium space-x-1`,
153
  )}>
154
  <div>{video.channel.label}</div>
155
+ {isCertifiedUser(video.channel.datasetUser) ? <div className="text-sm text-neutral-400"><RiCheckboxCircleFill className="" /></div> : null}
156
  </div>
157
  <div className={cn(
158
  `flex flex-row items-center`,