jbilcke-hf HF staff commited on
Commit
9cea1bb
1 Parent(s): df83860

improve huggingface support

Browse files
src/app/interface/left-menu/index.tsx CHANGED
@@ -16,6 +16,7 @@ export function LeftMenu() {
16
  const setView = useStore(s => s.setView)
17
  const menuMode = useStore(s => s.menuMode)
18
  const setMenuMode = useStore(s => s.setMenuMode)
 
19
 
20
  return (
21
  <div className={cn(
@@ -27,11 +28,15 @@ export function LeftMenu() {
27
  <div className={cn(
28
  `flex flex-col w-full`,
29
  )}>
30
- <Link href="/">
 
 
 
31
  <MenuItem
32
  icon={<RiHome8Line className="h-6 w-6" />}
33
  selected={view === "home"}
34
  // </Link>onClick={() => setView("home")}
 
35
  >
36
  Discover
37
  </MenuItem>
 
16
  const setView = useStore(s => s.setView)
17
  const menuMode = useStore(s => s.menuMode)
18
  const setMenuMode = useStore(s => s.setMenuMode)
19
+ const setCurrentVideo = useStore(s => s.setCurrentVideo)
20
 
21
  return (
22
  <div className={cn(
 
28
  <div className={cn(
29
  `flex flex-col w-full`,
30
  )}>
31
+ <Link href={{
32
+ pathname: '/',
33
+ query: { v: undefined },
34
+ }}>
35
  <MenuItem
36
  icon={<RiHome8Line className="h-6 w-6" />}
37
  selected={view === "home"}
38
  // </Link>onClick={() => setView("home")}
39
+ // onClick={() => setCurrentVideo(undefiend)}
40
  >
41
  Discover
42
  </MenuItem>
src/app/main.tsx CHANGED
@@ -11,7 +11,7 @@ import { UserAccountView } from "./views/user-account-view"
11
  import { NotFoundView } from "./views/not-found-view"
12
  import { VideoInfo } from "@/types"
13
  import { useEffect } from "react"
14
- import { usePathname } from "next/navigation"
15
  import { TubeLayout } from "./interface/tube-layout"
16
 
17
  // this is where we transition from the server-side space
@@ -29,16 +29,29 @@ export function Main({
29
  video?: VideoInfo
30
  }) {
31
  const pathname = usePathname()
 
32
 
33
  const setCurrentVideo = useStore(s => s.setCurrentVideo)
34
  const setView = useStore(s => s.setView)
35
  const setPathname = useStore(s => s.setPathname)
36
 
 
 
 
37
  useEffect(() => {
38
- if (video?.id) {
39
- setCurrentVideo(video)
 
 
 
 
 
 
 
 
 
40
  }
41
- }, [video?.id])
42
 
43
 
44
  useEffect(() => {
 
11
  import { NotFoundView } from "./views/not-found-view"
12
  import { VideoInfo } from "@/types"
13
  import { useEffect } from "react"
14
+ import { usePathname, useRouter } from "next/navigation"
15
  import { TubeLayout } from "./interface/tube-layout"
16
 
17
  // this is where we transition from the server-side space
 
29
  video?: VideoInfo
30
  }) {
31
  const pathname = usePathname()
32
+ const router = useRouter()
33
 
34
  const setCurrentVideo = useStore(s => s.setCurrentVideo)
35
  const setView = useStore(s => s.setView)
36
  const setPathname = useStore(s => s.setPathname)
37
 
38
+ const videoId = `${video?.id || ""}`
39
+ // console.log("Main video= "+ videoId)
40
+
41
  useEffect(() => {
42
+ // note: it is important to ALWAYS set the current video to videoId
43
+ // even if it's undefined
44
+ setCurrentVideo(video)
45
+
46
+ if (videoId) {
47
+ // this is a hack for hugging face:
48
+ // we allow the ?v=<id> param on the root of the domain
49
+ if (pathname !== "/watch") {
50
+ // console.log("we are on huggingface apparently!")
51
+ router.replace(`/watch?v=${videoId}`)
52
+ }
53
  }
54
+ }, [videoId])
55
 
56
 
57
  useEffect(() => {
src/app/page.tsx CHANGED
@@ -1,8 +1,15 @@
1
 
 
 
2
  import { Main } from "./main"
 
3
 
4
- export default function Page() {
 
 
 
 
5
  return (
6
- <Main />
7
  )
8
  }
 
1
 
2
+ import { AppQueryProps } from "@/types"
3
+
4
  import { Main } from "./main"
5
+ import { getVideo } from "./server/actions/ai-tube-hf/getVideo"
6
 
7
+ // we have routes but on Hugging Face we don't see them
8
+ // so.. let's use the work around
9
+ export default async function Page({ searchParams: { v: videoId } }: AppQueryProps) {
10
+ const video = await getVideo({ videoId, neverThrow: true })
11
+ // console.log("Root page: videoId ----> ", video?.id)
12
  return (
13
+ <Main video={video} />
14
  )
15
  }
src/app/server/actions/ai-tube-hf/getVideo.ts CHANGED
@@ -4,19 +4,32 @@ import { VideoInfo } from "@/types"
4
 
5
  import { getIndex } from "./getIndex"
6
 
7
- export async function getVideo(videoId?: string | string[] | null): Promise<VideoInfo> {
8
- const id = `${videoId || ""}`
 
 
 
 
 
 
 
9
 
10
- if (!id) {
11
- throw new Error(`cannot get the video, invalid id: "${id}"`)
12
- }
13
- const published = await getIndex({ status: "published" })
14
 
15
- const video = published[id] || undefined
16
 
17
- if (!video) {
18
- throw new Error(`cannot get the video, nothing found for id "${id}"`)
19
- }
20
 
21
- return video
 
 
 
 
 
 
22
  }
 
4
 
5
  import { getIndex } from "./getIndex"
6
 
7
+ export async function getVideo({
8
+ videoId,
9
+ neverThrow,
10
+ }: {
11
+ videoId?: string | string[] | null,
12
+ neverThrow?: boolean
13
+ }): Promise<VideoInfo | undefined> {
14
+ try {
15
+ const id = `${videoId || ""}`
16
 
17
+ if (!id) {
18
+ throw new Error(`cannot get the video, invalid id: "${id}"`)
19
+ }
20
+ const published = await getIndex({ status: "published" })
21
 
22
+ const video = published[id] || undefined
23
 
24
+ if (!video) {
25
+ throw new Error(`cannot get the video, nothing found for id "${id}"`)
26
+ }
27
 
28
+ return video
29
+ } catch (err) {
30
+ if (neverThrow) {
31
+ return undefined
32
+ }
33
+ throw err
34
+ }
35
  }
src/app/state/useStore.ts CHANGED
@@ -31,6 +31,12 @@ export const useStore = create<{
31
  currentTags: string[]
32
  setCurrentTags: (currentTags?: string[]) => void
33
 
 
 
 
 
 
 
34
  currentVideos: VideoInfo[]
35
  setCurrentVideos: (currentVideos: VideoInfo[]) => void
36
 
@@ -93,6 +99,16 @@ export const useStore = create<{
93
  set({ currentTags })
94
  },
95
 
 
 
 
 
 
 
 
 
 
 
96
  currentVideos: [],
97
  setCurrentVideos: (currentVideos: VideoInfo[] = []) => {
98
  set({
 
31
  currentTags: string[]
32
  setCurrentTags: (currentTags?: string[]) => void
33
 
34
+ currentModels: string[]
35
+ setCurrentModels: (currentModels?: string[]) => void
36
+
37
+ currentModel?: string
38
+ setCurrentModel: (currentModel?: string) => void
39
+
40
  currentVideos: VideoInfo[]
41
  setCurrentVideos: (currentVideos: VideoInfo[]) => void
42
 
 
99
  set({ currentTags })
100
  },
101
 
102
+ currentModels: [],
103
+ setCurrentModels: (currentModels?: string[]) => {
104
+ set({ currentModels })
105
+ },
106
+
107
+ currentModel: undefined,
108
+ setCurrentModel: (currentModel?: string) => {
109
+ set({ currentModel })
110
+ },
111
+
112
  currentVideos: [],
113
  setCurrentVideos: (currentVideos: VideoInfo[] = []) => {
114
  set({
src/app/views/public-video-view/index.tsx CHANGED
@@ -12,8 +12,28 @@ import { VideoInfo } from "@/types"
12
  export function PublicVideoView() {
13
  const video = useStore(s => s.currentVideo)
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!video) { return null }
16
-
17
  return (
18
  <div className={cn(
19
  `w-full`,
 
12
  export function PublicVideoView() {
13
  const video = useStore(s => s.currentVideo)
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(() => {
20
+ const queryString = new URL(location.href).search
21
+ const searchParams = new URLSearchParams(queryString)
22
+ if (videoId) {
23
+ if (searchParams.get("v") !== videoId) {
24
+ console.log(`current videoId "${videoId}" isn't set in the URL query params.. TODO we should set it`)
25
+
26
+ // searchParams.set("v", videoId)
27
+ // location.search = searchParams.toString()
28
+ }
29
+ } else {
30
+ // searchParams.delete("v")
31
+ // location.search = searchParams.toString()
32
+ }
33
+ }, [videoId])
34
+
35
  if (!video) { return null }
36
+
37
  return (
38
  <div className={cn(
39
  `w-full`,
src/app/watch/page.tsx CHANGED
@@ -3,22 +3,15 @@ import Head from "next/head"
3
  import Script from "next/script"
4
  import { Metadata, ResolvingMetadata } from "next"
5
 
 
6
 
7
  import { Main } from "../main"
8
-
9
  import { getVideo } from "../server/actions/ai-tube-hf/getVideo"
10
 
11
- type Props = {
12
- params: { id: string }
13
- searchParams: {
14
- v?: string | string[],
15
- [key: string]: string | string[] | undefined
16
- }
17
- }
18
 
19
  // https://nextjs.org/docs/pages/building-your-application/optimizing/fonts
20
  export async function generateMetadata(
21
- { params, searchParams: { v: videoId } }: Props,
22
  parent: ResolvingMetadata
23
  ): Promise<Metadata> {
24
  // read route params
@@ -26,7 +19,7 @@ export async function generateMetadata(
26
  const metadataBase = new URL('https://huggingface.co/spaces/jbilcke-hf/ai-tube')
27
 
28
  try {
29
- const video = await getVideo(videoId)
30
 
31
  if (!video) {
32
  throw new Error("Video not found")
@@ -69,15 +62,9 @@ export async function generateMetadata(
69
  }
70
 
71
 
72
- export default async function WatchPage({ searchParams: { v: videoId } }: Props) {
73
- // const [_pending, startTransition] = useTransition()
74
- // const setView = useStore(s => s.setView)
75
- // const setCurrentVideo = useStore(s => s.setCurrentVideo)
76
- const id = `${videoId || ""}`
77
-
78
- const video = await getVideo(videoId)
79
-
80
- // console.log("got video:", video.id)
81
  return (
82
  <Main video={video} />
83
  )
 
3
  import Script from "next/script"
4
  import { Metadata, ResolvingMetadata } from "next"
5
 
6
+ import { AppQueryProps } from "@/types"
7
 
8
  import { Main } from "../main"
 
9
  import { getVideo } from "../server/actions/ai-tube-hf/getVideo"
10
 
 
 
 
 
 
 
 
11
 
12
  // https://nextjs.org/docs/pages/building-your-application/optimizing/fonts
13
  export async function generateMetadata(
14
+ { params, searchParams: { v: videoId } }: AppQueryProps,
15
  parent: ResolvingMetadata
16
  ): Promise<Metadata> {
17
  // read route params
 
19
  const metadataBase = new URL('https://huggingface.co/spaces/jbilcke-hf/ai-tube')
20
 
21
  try {
22
+ const video = await getVideo({ videoId, neverThrow: true })
23
 
24
  if (!video) {
25
  throw new Error("Video not found")
 
62
  }
63
 
64
 
65
+ export default async function WatchPage({ searchParams: { v: videoId } }: AppQueryProps) {
66
+ const video = await getVideo({ videoId, neverThrow: true })
67
+ // console.log("WatchPage: --> " + video?.id)
 
 
 
 
 
 
68
  return (
69
  <Main video={video} />
70
  )
src/types.ts CHANGED
@@ -410,4 +410,13 @@ export type UpdateQueueRequest = {
410
  export type UpdateQueueResponse = {
411
  error?: string
412
  nbUpdated: number
 
 
 
 
 
 
 
 
 
413
  }
 
410
  export type UpdateQueueResponse = {
411
  error?: string
412
  nbUpdated: number
413
+ }
414
+
415
+
416
+ export type AppQueryProps = {
417
+ params: { id: string }
418
+ searchParams: {
419
+ v?: string | string[],
420
+ [key: string]: string | string[] | undefined
421
+ }
422
  }