ADD VideoPlayer component and implement video fetching functionality
This commit is contained in:
@@ -6,6 +6,7 @@ import ClipEdit from './pages/ClipEdit';
|
||||
import Home from './pages/Home';
|
||||
import {useEffect} from "react";
|
||||
import MyClips from './pages/MyClips';
|
||||
import VideoPlayer from "./pages/VideoPlayer.tsx";
|
||||
|
||||
|
||||
function App() {
|
||||
@@ -21,6 +22,7 @@ function App() {
|
||||
<Route path="/create" element={<ClipUpload />} />
|
||||
<Route path="/create/:id" element={<ClipEdit />} />
|
||||
<Route path="/my-clips" element={<MyClips />} />
|
||||
<Route path="/video/:id" element={<VideoPlayer />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Router>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Link } from "react-router-dom";
|
||||
import { useState } from "react";
|
||||
|
||||
type VideoCardProps = {
|
||||
id: number,
|
||||
title: string,
|
||||
duration: number,
|
||||
thumbnailPath: string | null,
|
||||
@@ -15,19 +16,24 @@ type VideoCardProps = {
|
||||
const fallbackThumbnail = "../../../public/default_thumbnail.png";
|
||||
|
||||
const VideoCard = ({
|
||||
id,
|
||||
title,
|
||||
duration,
|
||||
thumbnailPath,
|
||||
videoPath,
|
||||
createdAt,
|
||||
className
|
||||
}: VideoCardProps) => {
|
||||
|
||||
const initialSrc = thumbnailPath && thumbnailPath.trim() !== "" ? thumbnailPath : fallbackThumbnail;
|
||||
const [imgSrc, setImgSrc] = useState(initialSrc);
|
||||
const [timeAgo, setTimeAgo] = useState(dateToTimeAgo(stringToDate(createdAt)));
|
||||
|
||||
setTimeout(() => {
|
||||
setTimeAgo(dateToTimeAgo(stringToDate(createdAt)))
|
||||
}, 1000);
|
||||
|
||||
return (
|
||||
<Link to={videoPath}>
|
||||
<Link to={"/video/" + id}>
|
||||
<div className={clsx("flex flex-col", className)}>
|
||||
<div className={"relative inline-block"}>
|
||||
<img
|
||||
@@ -55,15 +61,16 @@ const VideoCard = ({
|
||||
">
|
||||
{formatTime(duration)}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{dateToTimeAgo(stringToDate(createdAt))}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div className={"flex flex-row justify-between items-center p-2"}>
|
||||
<div className={"flex flex-col justify-between p-2"}>
|
||||
<p>{title == "" ? "(No Title)" : title}</p>
|
||||
<p
|
||||
className={"text-gray-600 text-sm"}
|
||||
>
|
||||
{timeAgo}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -15,6 +15,7 @@ const MyClips = () => {
|
||||
<div className={"flex flex-row"}>
|
||||
{clips.map((clip) => (
|
||||
<VideoCard
|
||||
id={clip.id}
|
||||
key={clip.videoPath}
|
||||
title={clip.title}
|
||||
duration={clip.duration}
|
||||
|
||||
48
frontend/src/pages/VideoPlayer.tsx
Normal file
48
frontend/src/pages/VideoPlayer.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {useParams} from "react-router-dom";
|
||||
|
||||
const VideoPlayer = () => {
|
||||
const { id } = useParams();
|
||||
const [videoUrl, setVideoUrl] = useState<string>("");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch the video URL from the server
|
||||
fetch(`/api/v1/download/clip/${id}`)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to load video");
|
||||
}
|
||||
return response.blob();
|
||||
})
|
||||
.then(blob => {
|
||||
const url = URL.createObjectURL(blob);
|
||||
setVideoUrl(url);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Error fetching video:", err);
|
||||
setError("Failed to load video. Please try again later.");
|
||||
});
|
||||
}, [id]);
|
||||
|
||||
return (
|
||||
<div className="video-player">
|
||||
<video
|
||||
className="w-full h-full"
|
||||
controls
|
||||
autoPlay
|
||||
src={videoUrl}
|
||||
onError={(e) => {
|
||||
setError(e.currentTarget.error?.message || "An error occurred while playing the video.");
|
||||
}}
|
||||
>
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
|
||||
{error && <div className="text-red-500 mt-2">{error}</div>}
|
||||
{!videoUrl && !error && <div className="text-gray-500 mt-2">Loading video...</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default VideoPlayer;
|
||||
@@ -22,6 +22,7 @@ type User = {
|
||||
}
|
||||
|
||||
type Clip = {
|
||||
id: number,
|
||||
title: string,
|
||||
description: string,
|
||||
duration: number,
|
||||
|
||||
Reference in New Issue
Block a user