Spaces:
Sleeping
Sleeping
| "use client" | |
| import { useEffect } from "react" | |
| import { usePathname, useRouter } from "next/navigation" | |
| import { ConsentBanner, ConsentProvider } from 'react-hook-consent' | |
| import 'react-hook-consent/dist/styles/style.css' | |
| import { ChannelInfo, MediaInfo } from "@/types/general" | |
| import { getCollectionKey } from "@/lib/business/getCollectionKey" | |
| import { useStore } from "./state/useStore" | |
| import { HomeView } from "./views/home-view" | |
| import { PublicChannelsView } from "./views/public-channels-view" | |
| import { PublicChannelView } from "./views/public-channel-view" | |
| import { UserChannelView } from "./views/user-channel-view" | |
| import { UserAccountView } from "./views/user-account-view" | |
| import { NotFoundView } from "./views/not-found-view" | |
| import { TubeLayout } from "../components/interface/tube-layout" | |
| import { PublicMusicVideosView } from "./views/public-music-videos-view" | |
| import { PublicMediaEmbedView } from "./views/public-media-embed-view" | |
| import { PublicMediaView } from "./views/public-media-view" | |
| import { PublicLatentMediaEmbedView } from "./views/public-latent-media-embed-view" | |
| import { PublicLatentMediaView } from "./views/public-latent-media-view" | |
| import { PublicLatentSearchView } from "./views/public-latent-search-view" | |
| // this is where we transition from the server-side space | |
| // and the client-side space | |
| // basically, all the views are generated in client-side space | |
| // so the role of Main is to map server-side provided params | |
| // to the Zustand store (client-side) | |
| // | |
| // one benefit of doing this is that we will able to add some animations/transitions | |
| // more easily | |
| export function Main({ | |
| jwtToken, | |
| // view, | |
| publicMedia, | |
| publicMedias, | |
| latentMedia, | |
| latentMedias, | |
| publicChannelVideos, | |
| publicTracks, | |
| publicTrack, | |
| channel, | |
| }: { | |
| // token used to secure communications between the Next frontend and the Next API | |
| // this doesn't necessarily mean the user has to be logged it: | |
| // we can use this for anonymous visitors too. | |
| jwtToken?: string | |
| // server side params | |
| // view?: InterfaceView | |
| publicMedia?: MediaInfo | |
| publicMedias?: MediaInfo[] | |
| latentMedia?: MediaInfo | |
| latentMedias?: MediaInfo[] | |
| publicChannelVideos?: MediaInfo[] | |
| publicTracks?: MediaInfo[] | |
| publicTrack?: MediaInfo | |
| channel?: ChannelInfo | |
| }) { | |
| // this could be also a parameter of main, where we pass this manually | |
| const pathname = usePathname() | |
| const router = useRouter() | |
| const setJwtToken = useStore(s => s.setJwtToken) | |
| const setPublicMedia = useStore(s => s.setPublicMedia) | |
| const setView = useStore(s => s.setView) | |
| const setPathname = useStore(s => s.setPathname) | |
| const setPublicChannel = useStore(s => s.setPublicChannel) | |
| const setPublicMedias = useStore(s => s.setPublicMedias) | |
| const setPublicLatentMedia = useStore(s => s.setPublicLatentMedia) | |
| const setPublicLatentMedias = useStore(s => s.setPublicLatentMedias) | |
| const setPublicChannelVideos = useStore(s => s.setPublicChannelVideos) | |
| const setPublicTracks = useStore(s => s.setPublicTracks) | |
| const setPublicTrack = useStore(s => s.setPublicTrack) | |
| // console.log("[main.tsx] latentMedia = ", latentMedia) | |
| useEffect(() => { | |
| if (typeof jwtToken !== "string" && !jwtToken) { return } | |
| setJwtToken(jwtToken) | |
| }, [jwtToken]) | |
| useEffect(() => { | |
| if (!publicMedias?.length) { return } | |
| // note: it is important to ALWAYS set the current video to videoId | |
| // even if it's undefined | |
| setPublicMedias(publicMedias) | |
| }, [getCollectionKey(publicMedias)]) | |
| useEffect(() => { | |
| if (!publicChannelVideos?.length) { return } | |
| // note: it is important to ALWAYS set the current video to videoId | |
| // even if it's undefined | |
| setPublicChannelVideos(publicChannelVideos) | |
| }, [getCollectionKey(publicChannelVideos)]) | |
| useEffect(() => { | |
| if (!publicTracks?.length) { return } | |
| // note: it is important to ALWAYS set the current video to videoId | |
| // even if it's undefined | |
| setPublicTracks(publicTracks) | |
| }, [getCollectionKey(publicTracks)]) | |
| useEffect(() => { | |
| // note: it is important to ALWAYS set the current video to videoId | |
| // even if it's undefined | |
| setPublicTrack(publicTrack) | |
| if (!publicTrack || !publicTrack?.id) { return } | |
| // this is a hack for hugging face: | |
| // we allow the ?v=<id> param on the root of the domain | |
| if (pathname !== "/music") { | |
| // console.log("we are on huggingface apparently!") | |
| router.replace(`/music?m=${publicTrack.id}`) | |
| } | |
| }, [publicTrack?.id]) | |
| useEffect(() => { | |
| // note: it is important to ALWAYS set the current video to videoId | |
| // even if it's undefined | |
| setPublicMedia(publicMedia) | |
| if (!publicMedia || !publicMedia?.id) { return } | |
| if (pathname === "/embed") { return } | |
| // this is a hack for hugging face: | |
| // we allow the ?v=<id> param on the root of the domain | |
| if (pathname !== "/watch") { | |
| // console.log("we are on huggingface apparently!") | |
| router.replace(`/watch?v=${publicMedia.id}`) | |
| } | |
| }, [publicMedia?.id]) | |
| useEffect(() => { | |
| if (!latentMedias?.length) { return } | |
| setPublicLatentMedias(latentMedias) | |
| }, [getCollectionKey(latentMedias)]) | |
| useEffect(() => { | |
| console.log("latentMedia:", { | |
| "id": latentMedia?.id | |
| }) | |
| console.log(latentMedia) | |
| setPublicLatentMedia(latentMedia) | |
| if (!latentMedia || !latentMedia?.id) { return } | |
| if (pathname === "/latent/embed") { return } | |
| if (pathname !== "/latent/watch") { | |
| // console.log("we are on huggingface apparently!") | |
| // router.replace(`/watch?v=${publicMedia.id}`) | |
| // TODO: add params in the URL to represent the latent result | |
| router.replace(`/latent/watch`) | |
| } | |
| }, [latentMedia?.id]) | |
| useEffect(() => { | |
| // note: it is important to ALWAYS set the current video to videoId | |
| // even if it's undefined | |
| setPublicChannel(channel) | |
| if (!channel || !channel?.id) { return } | |
| // this is a hack for hugging face: | |
| // we allow the ?v=<id> param on the root of the domain | |
| if (pathname !== "/channel") { | |
| // console.log("we are on huggingface apparently!") | |
| router.replace(`/channel?v=${channel.id}`) | |
| } | |
| }, [channel?.id]) | |
| // this is critical: it sync the current route (coming from server-side) | |
| // with the zustand state manager | |
| useEffect(() => { | |
| setPathname(pathname) | |
| }, [pathname]) | |
| const view = useStore(s => s.view) | |
| return ( | |
| <ConsentProvider | |
| options={{ | |
| services: [ | |
| { | |
| id: 'gtm', | |
| name: 'Google Tag Manager (for Google analytics)', | |
| scripts: [ | |
| { id: 'inline-code', code: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': | |
| new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], | |
| j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= | |
| 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); | |
| })(window,document,'script','dataLayer','GTM-5ZGS5FDG');` }, | |
| ], | |
| // cookies: [ { pattern: 'cookie-name' }, { pattern: /regex/ } | |
| // ], | |
| // localStorage: ['local-storage-key'], | |
| // sessionStorage: ['session-storage-key'], | |
| mandatory: true, | |
| }, | |
| ], | |
| // customHash: 'my-custom-hash', // optional, e.g. when changing the options based on language | |
| theme: 'dark', | |
| }} | |
| > | |
| <TubeLayout> | |
| {view === "home" && <HomeView />} | |
| {view === "public_media_embed" && <PublicMediaEmbedView />} | |
| {view === "public_media" && <PublicMediaView />} | |
| {/* latent content is the content that "doesn't exist" (is generated by the AI) */} | |
| {view === "public_latent_search" && <PublicLatentSearchView />} | |
| {view === "public_latent_media_embed" && <PublicLatentMediaEmbedView />} | |
| {view === "public_latent_media" && <PublicLatentMediaView />} | |
| {view === "public_music_videos" && <PublicMusicVideosView />} | |
| {view === "public_channels" && <PublicChannelsView />} | |
| {view === "public_channel" && <PublicChannelView />} | |
| {/*view === "user_medias" && <UserMediasView />*/} | |
| {view === "user_channel" && <UserChannelView />} | |
| {view === "user_account" && <UserAccountView />} | |
| {view === "not_found" && <NotFoundView />} | |
| </TubeLayout> | |
| <ConsentBanner | |
| settings={{ hidden: false, label: 'More', modal: { title: 'AiTube Analytics' } }} | |
| decline={{ hidden: false, label: 'No' }} | |
| approve={{ label: 'Yes' }} | |
| > | |
| <> | |
| Do you allow AiTube to use cookies and external services? This is used to improve the user experience, by analyzing which features and content are liked the most. | |
| </> | |
| </ConsentBanner> | |
| </ConsentProvider> | |
| ) | |
| } |