From 0cc9ca4e667db2e3275e3eb31413b3a3d6df8615 Mon Sep 17 00:00:00 2001 From: "dev.daminik00" Date: Wed, 29 Oct 2025 23:37:06 +0100 Subject: [PATCH] add new video player --- package-lock.json | 36 +++ package.json | 3 + .../VideoGuideView/VideoGuideView.tsx | 35 +-- .../VideoPlayer/VideoPlayer.module.scss | 98 +++++++ .../video-guides/VideoPlayer/VideoPlayer.tsx | 253 ++++++++++++++++++ .../domains/video-guides/VideoPlayer/index.ts | 1 + 6 files changed, 400 insertions(+), 26 deletions(-) create mode 100644 src/components/domains/video-guides/VideoPlayer/VideoPlayer.module.scss create mode 100644 src/components/domains/video-guides/VideoPlayer/VideoPlayer.tsx create mode 100644 src/components/domains/video-guides/VideoPlayer/index.ts diff --git a/package-lock.json b/package-lock.json index ed08e02..9096f0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,9 @@ "@tanstack/react-virtual": "^3.13.12", "client-only": "^0.0.1", "clsx": "^2.1.1", + "hls.js": "^1.6.13", "idb": "^8.0.3", + "media-chrome": "^4.15.0", "next": "15.3.3", "next-intl": "^4.1.0", "react": "^19.0.0", @@ -20,6 +22,7 @@ "react-dom": "^19.0.0", "sass": "^1.89.2", "server-only": "^0.0.1", + "shaka-player": "^4.16.7", "socket.io-client": "^4.8.1", "zod": "^3.25.64", "zustand": "^5.0.5" @@ -4565,6 +4568,15 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ce-la-react": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ce-la-react/-/ce-la-react-0.3.1.tgz", + "integrity": "sha512-g0YwpZDPIwTwFumGTzNHcgJA6VhFfFCJkSNdUdC04br2UfU+56JDrJrJva3FZ7MToB4NDHAFBiPE/PZdNl1mQA==", + "license": "BSD-3-Clause", + "peerDependencies": { + "react": ">=17.0.0" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6227,6 +6239,12 @@ "node": ">= 0.4" } }, + "node_modules/hls.js": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.13.tgz", + "integrity": "sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA==", + "license": "Apache-2.0" + }, "node_modules/idb": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.3.tgz", @@ -6964,6 +6982,15 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/media-chrome": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/media-chrome/-/media-chrome-4.15.0.tgz", + "integrity": "sha512-OgC6m3Ss4cCUEVhvmRdUbnExqVKf8CDRDmbVTjIuRGAXdmz/vc34fL3onSsOm2uDZbhDB4Lb4KArGA48wG8Puw==", + "license": "MIT", + "dependencies": { + "ce-la-react": "^0.3.0" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7949,6 +7976,15 @@ "node": ">= 0.4" } }, + "node_modules/shaka-player": { + "version": "4.16.7", + "resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-4.16.7.tgz", + "integrity": "sha512-JWIVIxXRDkmogT+3t7UtYDbqY0dHyrfpqYPkKsyTXqBimwEgKFJIayhxwYF7Cn/qTkhp2nocHIdzaVZkaZLK4A==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/sharp": { "version": "0.34.2", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", diff --git a/package.json b/package.json index 9e94def..124b430 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "@tanstack/react-virtual": "^3.13.12", "client-only": "^0.0.1", "clsx": "^2.1.1", + "hls.js": "^1.6.13", "idb": "^8.0.3", + "media-chrome": "^4.15.0", "next": "15.3.3", "next-intl": "^4.1.0", "react": "^19.0.0", @@ -25,6 +27,7 @@ "react-dom": "^19.0.0", "sass": "^1.89.2", "server-only": "^0.0.1", + "shaka-player": "^4.16.7", "socket.io-client": "^4.8.1", "zod": "^3.25.64", "zustand": "^5.0.5" diff --git a/src/components/domains/video-guides/VideoGuideView/VideoGuideView.tsx b/src/components/domains/video-guides/VideoGuideView/VideoGuideView.tsx index 57319a8..ffcd876 100644 --- a/src/components/domains/video-guides/VideoGuideView/VideoGuideView.tsx +++ b/src/components/domains/video-guides/VideoGuideView/VideoGuideView.tsx @@ -1,11 +1,14 @@ "use client"; +import dynamic from "next/dynamic"; import { useRouter } from "next/navigation"; import { Icon, IconName, Typography } from "@/components/ui"; import styles from "./VideoGuideView.module.scss"; +const VideoPlayer = dynamic(() => import("../VideoPlayer"), { ssr: false }); + interface VideoGuideViewProps { id: string; name: string; @@ -20,24 +23,12 @@ export default function VideoGuideView({ }: VideoGuideViewProps) { const router = useRouter(); - // Extract video ID from various YouTube URL formats - const getYouTubeVideoId = (url: string): string | null => { - const patterns = [ - /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/, - /^([a-zA-Z0-9_-]{11})$/, // Direct video ID - ]; + // TODO: Remove hardcoded URLs when backend is ready + // Temporary hardcoded DASH/HLS URLs - using for ALL videos until backend updated + const dashUrl = "https://video.witlab.us/videos/TALK_FEELINGS/cmaf/source.mpd"; + const hlsUrl = "https://video.witlab.us/videos/TALK_FEELINGS/cmaf/source.m3u8"; - for (const pattern of patterns) { - const match = url.match(pattern); - if (match) return match[1]; - } - return null; - }; - - const videoId = getYouTubeVideoId(videoLink); - const embedUrl = videoId - ? `https://www.youtube.com/embed/${videoId}?rel=0&modestbranding=1` - : videoLink; + const _originalVideoLink = videoLink; // Keep for reference when backend is ready return (
@@ -60,15 +51,7 @@ export default function VideoGuideView({
{/* Video Player */}
-
-