Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Commit
•
a40111f
1
Parent(s):
a3f1817
add link sharing capabilities
Browse files- package-lock.json +36 -0
- package.json +2 -0
- src/app/views/public-video-view/index.tsx +88 -23
package-lock.json
CHANGED
@@ -48,6 +48,7 @@
|
|
48 |
"qs": "^6.11.2",
|
49 |
"react": "18.2.0",
|
50 |
"react-circular-progressbar": "^2.1.0",
|
|
|
51 |
"react-dom": "18.2.0",
|
52 |
"react-icons": "^4.12.0",
|
53 |
"react-smooth-scroll-hook": "^1.3.4",
|
@@ -72,6 +73,7 @@
|
|
72 |
"devDependencies": {
|
73 |
"@types/proper-lockfile": "^4.1.2",
|
74 |
"@types/qs": "^6.9.7",
|
|
|
75 |
"@types/react-virtualized": "^9.21.22",
|
76 |
"@types/sbd": "^1.0.3",
|
77 |
"daisyui": "^3.7.4"
|
@@ -1768,6 +1770,15 @@
|
|
1768 |
"csstype": "^3.0.2"
|
1769 |
}
|
1770 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1771 |
"node_modules/@types/react-dom": {
|
1772 |
"version": "18.2.7",
|
1773 |
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
|
@@ -2825,6 +2836,14 @@
|
|
2825 |
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.65.tgz",
|
2826 |
"integrity": "sha512-5E9WgTy95B7i90oISjui9U5Zu7iExUPfU4ygtv4yXEy6zJFE3oQYHCnh5H1jZRPkjphJt2Ml3oQW6M0qtK534A=="
|
2827 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2828 |
"node_modules/create-require": {
|
2829 |
"version": "1.1.1",
|
2830 |
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
@@ -5552,6 +5571,18 @@
|
|
5552 |
"react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
5553 |
}
|
5554 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5555 |
"node_modules/react-dom": {
|
5556 |
"version": "18.2.0",
|
5557 |
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
@@ -6486,6 +6517,11 @@
|
|
6486 |
"node": ">=8.0"
|
6487 |
}
|
6488 |
},
|
|
|
|
|
|
|
|
|
|
|
6489 |
"node_modules/ts-interface-checker": {
|
6490 |
"version": "0.1.13",
|
6491 |
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
|
|
48 |
"qs": "^6.11.2",
|
49 |
"react": "18.2.0",
|
50 |
"react-circular-progressbar": "^2.1.0",
|
51 |
+
"react-copy-to-clipboard": "^5.1.0",
|
52 |
"react-dom": "18.2.0",
|
53 |
"react-icons": "^4.12.0",
|
54 |
"react-smooth-scroll-hook": "^1.3.4",
|
|
|
73 |
"devDependencies": {
|
74 |
"@types/proper-lockfile": "^4.1.2",
|
75 |
"@types/qs": "^6.9.7",
|
76 |
+
"@types/react-copy-to-clipboard": "^5.0.7",
|
77 |
"@types/react-virtualized": "^9.21.22",
|
78 |
"@types/sbd": "^1.0.3",
|
79 |
"daisyui": "^3.7.4"
|
|
|
1770 |
"csstype": "^3.0.2"
|
1771 |
}
|
1772 |
},
|
1773 |
+
"node_modules/@types/react-copy-to-clipboard": {
|
1774 |
+
"version": "5.0.7",
|
1775 |
+
"resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz",
|
1776 |
+
"integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==",
|
1777 |
+
"dev": true,
|
1778 |
+
"dependencies": {
|
1779 |
+
"@types/react": "*"
|
1780 |
+
}
|
1781 |
+
},
|
1782 |
"node_modules/@types/react-dom": {
|
1783 |
"version": "18.2.7",
|
1784 |
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
|
|
|
2836 |
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.65.tgz",
|
2837 |
"integrity": "sha512-5E9WgTy95B7i90oISjui9U5Zu7iExUPfU4ygtv4yXEy6zJFE3oQYHCnh5H1jZRPkjphJt2Ml3oQW6M0qtK534A=="
|
2838 |
},
|
2839 |
+
"node_modules/copy-to-clipboard": {
|
2840 |
+
"version": "3.3.3",
|
2841 |
+
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
|
2842 |
+
"integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
|
2843 |
+
"dependencies": {
|
2844 |
+
"toggle-selection": "^1.0.6"
|
2845 |
+
}
|
2846 |
+
},
|
2847 |
"node_modules/create-require": {
|
2848 |
"version": "1.1.1",
|
2849 |
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
|
|
5571 |
"react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
5572 |
}
|
5573 |
},
|
5574 |
+
"node_modules/react-copy-to-clipboard": {
|
5575 |
+
"version": "5.1.0",
|
5576 |
+
"resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz",
|
5577 |
+
"integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==",
|
5578 |
+
"dependencies": {
|
5579 |
+
"copy-to-clipboard": "^3.3.1",
|
5580 |
+
"prop-types": "^15.8.1"
|
5581 |
+
},
|
5582 |
+
"peerDependencies": {
|
5583 |
+
"react": "^15.3.0 || 16 || 17 || 18"
|
5584 |
+
}
|
5585 |
+
},
|
5586 |
"node_modules/react-dom": {
|
5587 |
"version": "18.2.0",
|
5588 |
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
|
|
6517 |
"node": ">=8.0"
|
6518 |
}
|
6519 |
},
|
6520 |
+
"node_modules/toggle-selection": {
|
6521 |
+
"version": "1.0.6",
|
6522 |
+
"resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
|
6523 |
+
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
|
6524 |
+
},
|
6525 |
"node_modules/ts-interface-checker": {
|
6526 |
"version": "0.1.13",
|
6527 |
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
package.json
CHANGED
@@ -49,6 +49,7 @@
|
|
49 |
"qs": "^6.11.2",
|
50 |
"react": "18.2.0",
|
51 |
"react-circular-progressbar": "^2.1.0",
|
|
|
52 |
"react-dom": "18.2.0",
|
53 |
"react-icons": "^4.12.0",
|
54 |
"react-smooth-scroll-hook": "^1.3.4",
|
@@ -73,6 +74,7 @@
|
|
73 |
"devDependencies": {
|
74 |
"@types/proper-lockfile": "^4.1.2",
|
75 |
"@types/qs": "^6.9.7",
|
|
|
76 |
"@types/react-virtualized": "^9.21.22",
|
77 |
"@types/sbd": "^1.0.3",
|
78 |
"daisyui": "^3.7.4"
|
|
|
49 |
"qs": "^6.11.2",
|
50 |
"react": "18.2.0",
|
51 |
"react-circular-progressbar": "^2.1.0",
|
52 |
+
"react-copy-to-clipboard": "^5.1.0",
|
53 |
"react-dom": "18.2.0",
|
54 |
"react-icons": "^4.12.0",
|
55 |
"react-smooth-scroll-hook": "^1.3.4",
|
|
|
74 |
"devDependencies": {
|
75 |
"@types/proper-lockfile": "^4.1.2",
|
76 |
"@types/qs": "^6.9.7",
|
77 |
+
"@types/react-copy-to-clipboard": "^5.0.7",
|
78 |
"@types/react-virtualized": "^9.21.22",
|
79 |
"@types/sbd": "^1.0.3",
|
80 |
"daisyui": "^3.7.4"
|
src/app/views/public-video-view/index.tsx
CHANGED
@@ -1,7 +1,10 @@
|
|
1 |
"use client"
|
2 |
|
3 |
-
import { useEffect } from "react"
|
4 |
import { RiCheckboxCircleFill } from "react-icons/ri"
|
|
|
|
|
|
|
5 |
|
6 |
import { useStore } from "@/app/state/useStore"
|
7 |
import { cn } from "@/lib/utils"
|
@@ -14,6 +17,8 @@ export function PublicVideoView() {
|
|
14 |
|
15 |
const videoId = `${video?.id || ""}`
|
16 |
|
|
|
|
|
17 |
// we inject the current videoId in the URL, if it's not already present
|
18 |
// this is a hack for Hugging Face iframes
|
19 |
useEffect(() => {
|
@@ -32,6 +37,13 @@ export function PublicVideoView() {
|
|
32 |
}
|
33 |
}, [videoId])
|
34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
if (!video) { return null }
|
36 |
|
37 |
return (
|
@@ -60,42 +72,95 @@ export function PublicVideoView() {
|
|
60 |
{/** VIDEO TOOLBAR - HORIZONTAL */}
|
61 |
<div className={cn(
|
62 |
`flex flex-row`,
|
63 |
-
`items-center
|
|
|
|
|
64 |
)}>
|
65 |
-
{/**
|
66 |
<div className={cn(
|
67 |
-
`flex flex-
|
68 |
-
`
|
69 |
)}>
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
</div>
|
75 |
-
</div>
|
76 |
|
77 |
-
|
78 |
-
<div className={cn(
|
79 |
-
`flex flex-col`
|
80 |
-
)}>
|
81 |
<div className={cn(
|
82 |
-
`flex flex-
|
83 |
-
`text-zinc-100 text-base font-medium space-x-1`,
|
84 |
)}>
|
85 |
-
<div
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
<div className={cn(
|
89 |
-
`flex flex-row
|
90 |
-
`
|
91 |
-
|
92 |
-
<
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
</div>
|
95 |
</div>
|
96 |
|
97 |
</div>
|
98 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
</div>
|
100 |
<div className={cn(
|
101 |
`sm:w-56 md:w-96`,
|
|
|
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"
|
7 |
+
import { LuCopyCheck } from "react-icons/lu"
|
8 |
|
9 |
import { useStore } from "@/app/state/useStore"
|
10 |
import { cn } from "@/lib/utils"
|
|
|
17 |
|
18 |
const videoId = `${video?.id || ""}`
|
19 |
|
20 |
+
const [copied, setCopied] = useState<boolean>(false)
|
21 |
+
|
22 |
// we inject the current videoId in the URL, if it's not already present
|
23 |
// this is a hack for Hugging Face iframes
|
24 |
useEffect(() => {
|
|
|
37 |
}
|
38 |
}, [videoId])
|
39 |
|
40 |
+
useEffect(() => {
|
41 |
+
if (copied) {
|
42 |
+
setTimeout(() => {
|
43 |
+
setCopied(false)
|
44 |
+
}, 2000)
|
45 |
+
}
|
46 |
+
}, [copied])
|
47 |
if (!video) { return null }
|
48 |
|
49 |
return (
|
|
|
72 |
{/** VIDEO TOOLBAR - HORIZONTAL */}
|
73 |
<div className={cn(
|
74 |
`flex flex-row`,
|
75 |
+
`items-center`,
|
76 |
+
`justify-between`,
|
77 |
+
`mb-4`
|
78 |
)}>
|
79 |
+
{/** LEFT PART FO THE TOOLBARR */}
|
80 |
<div className={cn(
|
81 |
+
`flex flex-row`,
|
82 |
+
`items-center`
|
83 |
)}>
|
84 |
+
{/** CHANNEL LOGO - VERTICAL */}
|
85 |
+
<div className={cn(
|
86 |
+
`flex flex-col`,
|
87 |
+
`mr-3`
|
88 |
+
)}>
|
89 |
+
<div className="flex w-10 rounded-full overflow-hidden">
|
90 |
+
<img
|
91 |
+
src="huggingface-avatar.jpeg"
|
92 |
+
/>
|
93 |
+
</div>
|
94 |
</div>
|
|
|
95 |
|
96 |
+
{/** CHANNEL INFO - VERTICAL */}
|
|
|
|
|
|
|
97 |
<div className={cn(
|
98 |
+
`flex flex-col`
|
|
|
99 |
)}>
|
100 |
+
<div className={cn(
|
101 |
+
`flex flex-row items-center`,
|
102 |
+
`text-zinc-100 text-base font-medium space-x-1`,
|
103 |
+
)}>
|
104 |
+
<div>{video.channel.label}</div>
|
105 |
+
<div className="text-sm text-neutral-400"><RiCheckboxCircleFill className="" /></div>
|
106 |
+
</div>
|
107 |
+
<div className={cn(
|
108 |
+
`flex flex-row items-center`,
|
109 |
+
`text-neutral-400 text-xs font-normal space-x-1`,
|
110 |
+
)}>
|
111 |
+
<div>0 followers</div>
|
112 |
+
<div></div>
|
113 |
+
</div>
|
114 |
</div>
|
115 |
+
</div>
|
116 |
+
|
117 |
+
{/** RIGHT PART FO THE TOOLBAR */}
|
118 |
+
<div className={cn(
|
119 |
+
`flex flex-row`,
|
120 |
+
`items-center`,
|
121 |
+
`space-x-2`
|
122 |
+
)}>
|
123 |
+
{/* SHARE */}
|
124 |
<div className={cn(
|
125 |
+
`flex flex-row`,
|
126 |
+
`items-center`
|
127 |
+
)}>
|
128 |
+
<CopyToClipboard
|
129 |
+
text={`https://huggingface.co/spaces/jbilcke-hf/ai-tube?v=${video.id}`}
|
130 |
+
onCopy={() => setCopied(true)}>
|
131 |
+
<div className={cn(
|
132 |
+
`flex flex-row space-x-2 pl-3 pr-4 h-9`,
|
133 |
+
`items-center justify-center text-center`,
|
134 |
+
`rounded-2xl`,
|
135 |
+
`cursor-pointer`,
|
136 |
+
`bg-neutral-700/50 hover:bg-neutral-700/90 text-zinc-100`
|
137 |
+
)}>
|
138 |
+
<div className="flex items-center justify-center pt-0.5">
|
139 |
+
{
|
140 |
+
copied ? <LuCopyCheck className="w-4 h-4" />
|
141 |
+
: <PiShareFatLight className="w-5 h-5" />
|
142 |
+
}
|
143 |
+
</div>
|
144 |
+
<div className="text-sm font-medium">
|
145 |
+
{
|
146 |
+
copied ? "Link copied!" : "Share video"
|
147 |
+
}</div>
|
148 |
+
</div>
|
149 |
+
</CopyToClipboard>
|
150 |
</div>
|
151 |
</div>
|
152 |
|
153 |
</div>
|
154 |
|
155 |
+
{/** VIDEO DESCRIPTION - VERTICAL */}
|
156 |
+
<div className={cn(
|
157 |
+
`flex flex-col p-3`,
|
158 |
+
`rounded-xl`,
|
159 |
+
`bg-neutral-700/50`,
|
160 |
+
`text-sm`
|
161 |
+
)}>
|
162 |
+
<p>{video.description}</p>
|
163 |
+
</div>
|
164 |
</div>
|
165 |
<div className={cn(
|
166 |
`sm:w-56 md:w-96`,
|