diff --git a/src/components/preview/Media.tsx b/src/components/preview/Media.tsx index a9a1213..a967a00 100644 --- a/src/components/preview/Media.tsx +++ b/src/components/preview/Media.tsx @@ -21,6 +21,7 @@ import "@vidstack/react/player/styles/default/layouts/audio.css"; import "@vidstack/react/player/styles/default/layouts/video.css"; import "@vidstack/react/player/styles/default/theme.css"; import { ChevronLeft, ChevronRight } from "lucide-react"; +import Link from "next/link"; import { useCallback, useRef, useState } from "react"; import { type z } from "zod"; @@ -28,7 +29,8 @@ import { PageLoader } from "~/components/layout"; import Icon from "~/components/ui/icon"; import useLoading from "~/hooks/useLoading"; -import { MediaPlayerIcons } from "~/lib/previewHelper"; +import { MediaPlayerIcons, getPreviewIcon } from "~/lib/previewHelper"; +import { cn, formatDate } from "~/lib/utils"; import { type Schema_File } from "~/types/schema"; @@ -37,8 +39,9 @@ import "~/styles/vidstack.css"; type Props = { file: z.infer; type: "video" | "audio"; + playlist: z.infer[]; }; -export default function PreviewMedia({ file, type }: Props) { +export default function PreviewMedia({ file, type, playlist }: Props) { const player = useRef(null); const [canPlay, setCanPlay] = useState(false); @@ -85,7 +88,7 @@ export default function PreviewMedia({ file, type }: Props) { seekBackwardButton: null, seekForwardButton: null, playButton: ( -
+
{canPlay ? ( @@ -144,6 +147,12 @@ export default function PreviewMedia({ file, type }: Props) {
+ + ), + beforeSettingsMenu: ( + + ), settingsMenu: ( - - - - - - {/* Loop */} - - - - - Loop - {isLoop ? "On" : "Off"} - - - - - setIsLoop(true)} + <> + + + + + + {/* Loop */} + + + + + Loop + {isLoop ? "On" : "Off"} + + + + - - On - - setIsLoop(false)} - > - - Off - - - - + setIsLoop(true)} + > + + On + + setIsLoop(false)} + > + + Off + + + + - {/* Playback Speed */} - + {/* Playback Speed */} + - {/* Audio Gain */} - - - + {/* Audio Gain */} + + + + ), }} /> @@ -392,3 +409,87 @@ function AudioGain() { ); } +function PlaylistMenu({ + playlist, + file, + placement = "top end", +}: { + playlist: z.infer[]; + file: z.infer; + placement?: Menu.ItemsProps["placement"]; +}) { + return ( + + + + + + {playlist.map((item) => { + const isCurrent = `${item.name}#${item.size}` === `${file.name}#${file.size}`; + + const Wrapper = ({ children, className }: React.PropsWithChildren<{ className?: string }>) => + isCurrent ? ( +
+ {children} +
+ ) : ( + + {children} + + ); + + return ( + + {/* Thumbnail */} +
+ {item.mimeType.includes("video") ? ( + {`Thumbnail + ) : ( +
+ +
+ )} +
+ +
+

{item.name}

+ {formatDate(item.modifiedTime)} +
+
+ ); + })} +
+
+ ); +}