From 1c8084b4f5fe03498b7ba07d5f060204d4e4f093 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 15:10:23 +0000 Subject: [PATCH 01/18] feat: Viewer token From 8eafc0643f9247de1615a8ac71879f2dad764720 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 15:20:38 +0000 Subject: [PATCH 02/18] check of user is streaming or not --- app/(dashboard)/u/[username]/(home)/page.tsx | 2 +- lib/user-service.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/(dashboard)/u/[username]/(home)/page.tsx b/app/(dashboard)/u/[username]/(home)/page.tsx index ec2f080..b5657b6 100644 --- a/app/(dashboard)/u/[username]/(home)/page.tsx +++ b/app/(dashboard)/u/[username]/(home)/page.tsx @@ -11,7 +11,7 @@ const CreatorPage = async ({ params }: CreatorPageProps) => { const externalUser = await currentUser(); const user = await getUserByUsername(params.username); - if (!user || user.externalUserId !== externalUser?.id) { + if (!user || user.externalUserId !== externalUser?.id || !user.stream) { throw new Error("Unauthorized"); } diff --git a/lib/user-service.ts b/lib/user-service.ts index fa49465..2d301f6 100644 --- a/lib/user-service.ts +++ b/lib/user-service.ts @@ -5,6 +5,9 @@ export const getUserByUsername = async (username: string) => { where: { username, }, + include: { + stream: true, + }, }); return user; From 4a1ea6df7bbcf35f95e7c03cb7e6e981b101ea4c Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 15:29:16 +0000 Subject: [PATCH 03/18] create StreamPLayer component --- app/(dashboard)/u/[username]/(home)/page.tsx | 7 ++++++- components/stream-player/index.tsx | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 components/stream-player/index.tsx diff --git a/app/(dashboard)/u/[username]/(home)/page.tsx b/app/(dashboard)/u/[username]/(home)/page.tsx index b5657b6..13bb946 100644 --- a/app/(dashboard)/u/[username]/(home)/page.tsx +++ b/app/(dashboard)/u/[username]/(home)/page.tsx @@ -1,3 +1,4 @@ +import { StreamPlayer } from "@/components/stream-player"; import { getUserByUsername } from "@/lib/user-service"; import { currentUser } from "@clerk/nextjs"; @@ -15,7 +16,11 @@ const CreatorPage = async ({ params }: CreatorPageProps) => { throw new Error("Unauthorized"); } - return
CreatorPage
; + return ( +
+ +
+ ); }; export default CreatorPage; diff --git a/components/stream-player/index.tsx b/components/stream-player/index.tsx new file mode 100644 index 0000000..767986c --- /dev/null +++ b/components/stream-player/index.tsx @@ -0,0 +1,17 @@ +"use client"; + +import { Stream, User } from "@prisma/client"; + +interface StreamPlayerProps { + user: User & { stream: Stream | null }; + stream: Stream; + isFollowing: boolean; +} + +export const StreamPlayer = ({ + user, + stream, + isFollowing, +}: StreamPlayerProps) => { + return
StreamPlayer
; +}; From d5e21ef7489f1ff226a7d4ecdd3d968fa3ab85a2 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 15:37:25 +0000 Subject: [PATCH 04/18] create useViewerToken hook --- hooks/use-viewer-token.ts | 20 ++++++++++++++++++++ package-lock.json | 9 +++++++++ package.json | 1 + 3 files changed, 30 insertions(+) create mode 100644 hooks/use-viewer-token.ts diff --git a/hooks/use-viewer-token.ts b/hooks/use-viewer-token.ts new file mode 100644 index 0000000..e7c9938 --- /dev/null +++ b/hooks/use-viewer-token.ts @@ -0,0 +1,20 @@ +import { useEffect, useState } from "react"; +import { toast } from "sonner"; + +export const useViewerToken = (hostIdentify: string) => { + const [token, setToken] = useState(""); + const [name, setName] = useState(""); + const [identify, setIdentify] = useState(""); + + useEffect(() => { + const createToken = async () => { + try { + const viewerToken = await createViewerToken(); + } catch (error) { + toast.error("Something went wrong"); + } + }; + }, []); + + return { token, name, identify }; +}; diff --git a/package-lock.json b/package-lock.json index f1ed4cd..239aac8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@radix-ui/react-tooltip": "^1.0.7", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", + "jwt-decode": "^4.0.0", "livekit-client": "^1.15.4", "livekit-server-sdk": "^1.2.7", "lucide-react": "^0.294.0", @@ -4135,6 +4136,14 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/package.json b/package.json index 5ec76fb..be6b4f9 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@radix-ui/react-tooltip": "^1.0.7", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", + "jwt-decode": "^4.0.0", "livekit-client": "^1.15.4", "livekit-server-sdk": "^1.2.7", "lucide-react": "^0.294.0", From b61fbee6f1051115d2a8d054013cb481c8dfeaf1 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 15:39:51 +0000 Subject: [PATCH 05/18] create token server action --- actions/token.ts | 3 +++ package-lock.json | 20 ++++++++++++++++++++ package.json | 2 ++ 3 files changed, 25 insertions(+) create mode 100644 actions/token.ts diff --git a/actions/token.ts b/actions/token.ts new file mode 100644 index 0000000..29d3339 --- /dev/null +++ b/actions/token.ts @@ -0,0 +1,3 @@ +"use server"; + +import { v4 } from "uuid"; diff --git a/package-lock.json b/package-lock.json index 239aac8..be5cd2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,12 +34,14 @@ "tailwind-merge": "^2.1.0", "tailwindcss-animate": "^1.0.7", "usehooks-ts": "^2.9.1", + "uuid": "^9.0.1", "zustand": "^4.4.7" }, "devDependencies": { "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@types/uuid": "^9.0.7", "autoprefixer": "^10.0.1", "eslint": "^8", "eslint-config-next": "14.0.4", @@ -1601,6 +1603,12 @@ "@types/node": "*" } }, + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, "node_modules/@typescript-eslint/parser": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.14.0.tgz", @@ -6280,6 +6288,18 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/package.json b/package.json index be6b4f9..d74c2db 100644 --- a/package.json +++ b/package.json @@ -35,12 +35,14 @@ "tailwind-merge": "^2.1.0", "tailwindcss-animate": "^1.0.7", "usehooks-ts": "^2.9.1", + "uuid": "^9.0.1", "zustand": "^4.4.7" }, "devDependencies": { "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@types/uuid": "^9.0.7", "autoprefixer": "^10.0.1", "eslint": "^8", "eslint-config-next": "14.0.4", From e4c89e3444a4f364d4f0bbf73be26540bd6cb3e5 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 15:42:20 +0000 Subject: [PATCH 06/18] create getUserById in user service --- lib/user-service.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/user-service.ts b/lib/user-service.ts index 2d301f6..2af32d5 100644 --- a/lib/user-service.ts +++ b/lib/user-service.ts @@ -12,3 +12,16 @@ export const getUserByUsername = async (username: string) => { return user; }; + +export const getUserById = async (id: string) => { + const user = await db.user.findUnique({ + where: { + id, + }, + include: { + stream: true, + }, + }); + + return user; +}; From 895ed0205b9e90c489007e8f77ef9e7d9200f66b Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 15:52:52 +0000 Subject: [PATCH 07/18] update the token server action --- actions/token.ts | 48 +++++++++++++++++++++++++++++++++++++++ hooks/use-viewer-token.ts | 3 ++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/actions/token.ts b/actions/token.ts index 29d3339..c102a11 100644 --- a/actions/token.ts +++ b/actions/token.ts @@ -1,3 +1,51 @@ "use server"; +import { getSelf } from "@/lib/auth-service"; +import { isBlockedByUser } from "@/lib/block-service"; +import { getUserById } from "@/lib/user-service"; +import { AccessToken } from "livekit-server-sdk"; import { v4 } from "uuid"; + +export const createViewerToken = async (hostIdentity: string) => { + let self; + + try { + self = await getSelf(); + } catch { + const id = v4(); + const username = `guest#${Math.floor(Math.random() * 1000)}`; + self = { id, username }; + } + + const host = await getUserById(hostIdentity); + + if (!host) { + throw new Error("User not Found"); + } + + const isBlocked = await isBlockedByUser(host.id); + + if (isBlocked) { + throw new Error("User is blocked"); + } + + const isHost = self.id === host.id; + + const token = new AccessToken( + process.env.LIVEKIT_API_KEY!, + process.env.LIVEKIT_API_SECRET!, + { + identity: isHost ? `host-${self.id}` : self.id, + name: self.username, + } + ); + + token.addGrant({ + room: host.id, + roomJoin: true, + canPublish: false, + canPublishData: true, + }); + + return await Promise.resolve(token.toJwt()); +}; diff --git a/hooks/use-viewer-token.ts b/hooks/use-viewer-token.ts index e7c9938..a2bec4e 100644 --- a/hooks/use-viewer-token.ts +++ b/hooks/use-viewer-token.ts @@ -1,7 +1,8 @@ +import { createViewerToken } from "@/actions/token"; import { useEffect, useState } from "react"; import { toast } from "sonner"; -export const useViewerToken = (hostIdentify: string) => { +export const useViewerToken = (hostIdentity: string) => { const [token, setToken] = useState(""); const [name, setName] = useState(""); const [identify, setIdentify] = useState(""); From c9b25d5cf45b19ef86b29edaafb586ea0e924952 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 15:57:33 +0000 Subject: [PATCH 08/18] complete the hook --- hooks/use-viewer-token.ts | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/hooks/use-viewer-token.ts b/hooks/use-viewer-token.ts index a2bec4e..0f48b45 100644 --- a/hooks/use-viewer-token.ts +++ b/hooks/use-viewer-token.ts @@ -1,21 +1,39 @@ import { createViewerToken } from "@/actions/token"; +import { JwtPayload, jwtDecode } from "jwt-decode"; import { useEffect, useState } from "react"; import { toast } from "sonner"; export const useViewerToken = (hostIdentity: string) => { const [token, setToken] = useState(""); const [name, setName] = useState(""); - const [identify, setIdentify] = useState(""); + const [identity, setIdentity] = useState(""); useEffect(() => { const createToken = async () => { try { - const viewerToken = await createViewerToken(); + const viewerToken = await createViewerToken(hostIdentity); + setToken(viewerToken); + + const decodedToken = jwtDecode(viewerToken) as JwtPayload & { + name?: string; + }; + const name = decodedToken?.name; + const identity = decodedToken.jti; + + if (identity) { + setIdentity(identity); + } + + if (name) { + setName(name); + } } catch (error) { toast.error("Something went wrong"); } }; - }, []); - return { token, name, identify }; + createToken(); + }, [hostIdentity]); + + return { token, name, identity }; }; From d8a997097bff25b1eb6c5430194948c1a3ce6ebd Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 16:09:18 +0000 Subject: [PATCH 09/18] testing --- components/stream-player/index.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/components/stream-player/index.tsx b/components/stream-player/index.tsx index 767986c..fd71bf1 100644 --- a/components/stream-player/index.tsx +++ b/components/stream-player/index.tsx @@ -1,6 +1,8 @@ "use client"; +import { useViewerToken } from "@/hooks/use-viewer-token"; import { Stream, User } from "@prisma/client"; +import { LiveKitRoom } from "@livekit/components-react"; interface StreamPlayerProps { user: User & { stream: Stream | null }; @@ -13,5 +15,20 @@ export const StreamPlayer = ({ stream, isFollowing, }: StreamPlayerProps) => { - return
StreamPlayer
; + const { token, name, identity } = useViewerToken(user.id); + + if (!token || !name || !identity) { + return
Cannot watch the stream
; + } + + return ( + <> + + Strean + + + ); }; From d5d76e6ef018679505938ab1cbd50ebd5b58acc0 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 16:10:48 +0000 Subject: [PATCH 10/18] update next config --- next.config.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/next.config.js b/next.config.js index 767719f..fb96d41 100644 --- a/next.config.js +++ b/next.config.js @@ -1,4 +1,17 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {} +const nextConfig = { + images: { + domains: ["utfs.io"], + }, + webpack: (config) => { + config.module.rules.push({ + test: /\.mjs$/, + include: /node_modules/, + type: "javascript/auto", + }); -module.exports = nextConfig + return config; + }, +}; + +module.exports = nextConfig; From 8b6ba3a13f82a68cfd1b70b04f17309e81bf2c9a Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 16:19:05 +0000 Subject: [PATCH 11/18] create Video component --- components/stream-player/index.tsx | 7 ++++++- components/stream-player/video.tsx | 12 ++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 components/stream-player/video.tsx diff --git a/components/stream-player/index.tsx b/components/stream-player/index.tsx index fd71bf1..61d6d5a 100644 --- a/components/stream-player/index.tsx +++ b/components/stream-player/index.tsx @@ -3,6 +3,8 @@ import { useViewerToken } from "@/hooks/use-viewer-token"; import { Stream, User } from "@prisma/client"; import { LiveKitRoom } from "@livekit/components-react"; +import { cn } from "@/lib/utils"; +import { Video } from "./video"; interface StreamPlayerProps { user: User & { stream: Stream | null }; @@ -26,8 +28,11 @@ export const StreamPlayer = ({ - Strean +
+
); diff --git a/components/stream-player/video.tsx b/components/stream-player/video.tsx new file mode 100644 index 0000000..09d7b5d --- /dev/null +++ b/components/stream-player/video.tsx @@ -0,0 +1,12 @@ +"use client"; + +import React from "react"; + +interface VideoProps { + hostName: string + hostIdentity: string +} + +export const Video = ({ hostName, hostIdentity }: VideoProps) => { + return
Video
; +}; From 5baf8122bbb61a4f47db213e2444b65991efc148 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 17:39:32 +0000 Subject: [PATCH 12/18] update Video component --- components/stream-player/video.tsx | 32 +++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/components/stream-player/video.tsx b/components/stream-player/video.tsx index 09d7b5d..02b7ff9 100644 --- a/components/stream-player/video.tsx +++ b/components/stream-player/video.tsx @@ -1,12 +1,34 @@ "use client"; -import React from "react"; +import { ConnectionState, Track } from "livekit-client"; +import { + useConnectionState, + useRemoteParticipant, + useTracks, +} from "@livekit/components-react"; interface VideoProps { - hostName: string - hostIdentity: string + hostName: string; + hostIdentity: string; } -export const Video = ({ hostName, hostIdentity }: VideoProps) => { - return
Video
; +export const Video = ({ hostName, hostIdentity }: VideoProps) => { + const connectionState = useConnectionState(); + const participant = useRemoteParticipant(hostIdentity); + const tracks = useTracks([ + Track.Source.Camera, + Track.Source.Microphone, + ]).filter((track) => track.participant.identity === hostIdentity); + + let content; + + if (!participant && connectionState === ConnectionState.Connected) { + content =
Offline
; + } else if (!participant || tracks.length === 0) { + content =
Loading
; + } else { + content =
Live
; + } + + return
{content}
; }; From 0dc8a3af01a96cae9ca7e989a1a46e1589f6f599 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 17:42:48 +0000 Subject: [PATCH 13/18] add components for Video --- components/stream-player/live-video.tsx | 5 +++++ components/stream-player/loading-video.tsx | 5 +++++ components/stream-player/offline-video.tsx | 5 +++++ components/stream-player/video.tsx | 9 ++++++--- 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 components/stream-player/live-video.tsx create mode 100644 components/stream-player/loading-video.tsx create mode 100644 components/stream-player/offline-video.tsx diff --git a/components/stream-player/live-video.tsx b/components/stream-player/live-video.tsx new file mode 100644 index 0000000..6179f44 --- /dev/null +++ b/components/stream-player/live-video.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export const LiveVideo = () => { + return
LiveVideo
; +}; diff --git a/components/stream-player/loading-video.tsx b/components/stream-player/loading-video.tsx new file mode 100644 index 0000000..387de8e --- /dev/null +++ b/components/stream-player/loading-video.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export const LoadingVideo = () => { + return
LoadingVideo
; +}; diff --git a/components/stream-player/offline-video.tsx b/components/stream-player/offline-video.tsx new file mode 100644 index 0000000..8e15ee9 --- /dev/null +++ b/components/stream-player/offline-video.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export const OfflineVideo = () => { + return
OfflineVideo
; +}; diff --git a/components/stream-player/video.tsx b/components/stream-player/video.tsx index 02b7ff9..a0d3e4d 100644 --- a/components/stream-player/video.tsx +++ b/components/stream-player/video.tsx @@ -6,6 +6,9 @@ import { useRemoteParticipant, useTracks, } from "@livekit/components-react"; +import { OfflineVideo } from "./offline-video"; +import { LoadingVideo } from "./loading-video"; +import { LiveVideo } from "./live-video"; interface VideoProps { hostName: string; @@ -23,11 +26,11 @@ export const Video = ({ hostName, hostIdentity }: VideoProps) => { let content; if (!participant && connectionState === ConnectionState.Connected) { - content =
Offline
; + content = ; } else if (!participant || tracks.length === 0) { - content =
Loading
; + content = ; } else { - content =
Live
; + content = ; } return
{content}
; From 096bde8088364b787972851fcf6bdb5ca7e36425 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 17:45:04 +0000 Subject: [PATCH 14/18] update OfflineVideo --- components/stream-player/offline-video.tsx | 15 ++++++++++++--- components/stream-player/video.tsx | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/components/stream-player/offline-video.tsx b/components/stream-player/offline-video.tsx index 8e15ee9..4ace612 100644 --- a/components/stream-player/offline-video.tsx +++ b/components/stream-player/offline-video.tsx @@ -1,5 +1,14 @@ -import React from "react"; +import { WifiOff } from "lucide-react"; -export const OfflineVideo = () => { - return
OfflineVideo
; +interface OfflineVideoProps { + username: string; +} + +export const OfflineVideo = ({ username }: OfflineVideoProps) => { + return ( +
+ +

{username} is offline

+
+ ); }; diff --git a/components/stream-player/video.tsx b/components/stream-player/video.tsx index a0d3e4d..d879c3d 100644 --- a/components/stream-player/video.tsx +++ b/components/stream-player/video.tsx @@ -26,7 +26,7 @@ export const Video = ({ hostName, hostIdentity }: VideoProps) => { let content; if (!participant && connectionState === ConnectionState.Connected) { - content = ; + content = ; } else if (!participant || tracks.length === 0) { content = ; } else { From 94a459838700e789f72fc2ee835b936ac9d87cc5 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 17:49:14 +0000 Subject: [PATCH 15/18] update LoadingVideo --- components/stream-player/loading-video.tsx | 14 ++++++++++++-- components/stream-player/video.tsx | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/components/stream-player/loading-video.tsx b/components/stream-player/loading-video.tsx index 387de8e..10d6508 100644 --- a/components/stream-player/loading-video.tsx +++ b/components/stream-player/loading-video.tsx @@ -1,5 +1,15 @@ +import { Loader } from "lucide-react"; import React from "react"; -export const LoadingVideo = () => { - return
LoadingVideo
; +interface LoadingVideoProps { + label: string; +} + +export const LoadingVideo = ({ label }: LoadingVideoProps) => { + return ( +
+ +

{label}

+
+ ); }; diff --git a/components/stream-player/video.tsx b/components/stream-player/video.tsx index d879c3d..99fd0b3 100644 --- a/components/stream-player/video.tsx +++ b/components/stream-player/video.tsx @@ -28,7 +28,7 @@ export const Video = ({ hostName, hostIdentity }: VideoProps) => { if (!participant && connectionState === ConnectionState.Connected) { content = ; } else if (!participant || tracks.length === 0) { - content = ; + content = ; } else { content = ; } From 9dbe231739d9c40ddd89964996000bfcbef4f888 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 17:51:43 +0000 Subject: [PATCH 16/18] update LiveVideo --- components/stream-player/live-video.tsx | 7 ++++++- components/stream-player/video.tsx | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/components/stream-player/live-video.tsx b/components/stream-player/live-video.tsx index 6179f44..33350d8 100644 --- a/components/stream-player/live-video.tsx +++ b/components/stream-player/live-video.tsx @@ -1,5 +1,10 @@ +import { Participant } from "livekit-client"; import React from "react"; -export const LiveVideo = () => { +interface LiveVideoProps { + participant: Participant; +} + +export const LiveVideo = ({ participant }: LiveVideoProps) => { return
LiveVideo
; }; diff --git a/components/stream-player/video.tsx b/components/stream-player/video.tsx index 99fd0b3..86610e7 100644 --- a/components/stream-player/video.tsx +++ b/components/stream-player/video.tsx @@ -30,7 +30,7 @@ export const Video = ({ hostName, hostIdentity }: VideoProps) => { } else if (!participant || tracks.length === 0) { content = ; } else { - content = ; + content = ; } return
{content}
; From e6781c30339ec2edc02f064acc9148bccdf0dc51 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Sun, 24 Dec 2023 19:47:54 +0000 Subject: [PATCH 17/18] add Skeleton Loading for Video --- components/stream-player/index.tsx | 16 ++++++++++++++-- components/stream-player/video.tsx | 9 +++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/components/stream-player/index.tsx b/components/stream-player/index.tsx index 61d6d5a..6ba0b6a 100644 --- a/components/stream-player/index.tsx +++ b/components/stream-player/index.tsx @@ -4,7 +4,7 @@ import { useViewerToken } from "@/hooks/use-viewer-token"; import { Stream, User } from "@prisma/client"; import { LiveKitRoom } from "@livekit/components-react"; import { cn } from "@/lib/utils"; -import { Video } from "./video"; +import { Video, VideoSkeleton } from "./video"; interface StreamPlayerProps { user: User & { stream: Stream | null }; @@ -20,7 +20,7 @@ export const StreamPlayer = ({ const { token, name, identity } = useViewerToken(user.id); if (!token || !name || !identity) { - return
Cannot watch the stream
; + return ; } return ( @@ -37,3 +37,15 @@ export const StreamPlayer = ({ ); }; + +export const StreamPlayerSkeleton = () => { + return ( +
+
+ + {/**/} +
+
{/**/}
+
+ ); +}; diff --git a/components/stream-player/video.tsx b/components/stream-player/video.tsx index 86610e7..e419865 100644 --- a/components/stream-player/video.tsx +++ b/components/stream-player/video.tsx @@ -9,6 +9,7 @@ import { import { OfflineVideo } from "./offline-video"; import { LoadingVideo } from "./loading-video"; import { LiveVideo } from "./live-video"; +import { Skeleton } from "../ui/skeleton"; interface VideoProps { hostName: string; @@ -35,3 +36,11 @@ export const Video = ({ hostName, hostIdentity }: VideoProps) => { return
{content}
; }; + +export const VideoSkeleton = () => { + return ( +
+ +
+ ); +}; From 397d90e145e307b3a41e4b51917d8c0f1b330a27 Mon Sep 17 00:00:00 2001 From: DevMirza Date: Mon, 25 Dec 2023 08:20:59 +0000 Subject: [PATCH 18/18] show live video --- components/stream-player/live-video.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/components/stream-player/live-video.tsx b/components/stream-player/live-video.tsx index 33350d8..fcb149f 100644 --- a/components/stream-player/live-video.tsx +++ b/components/stream-player/live-video.tsx @@ -1,10 +1,17 @@ import { Participant } from "livekit-client"; -import React from "react"; +import React, { useRef } from "react"; interface LiveVideoProps { participant: Participant; } export const LiveVideo = ({ participant }: LiveVideoProps) => { - return
LiveVideo
; + const videoRef = useRef(null); + const wrapperRef = useRef(null); + + return ( +
+
+ ); };