player.time);
const seekableStart = usePlayerSelector((player) => player.seekableStart);
const duration = usePlayerSelector((player) => player.duration);
+ const live = usePlayerSelector((player) => player.live);
return (
-
- {hms(seekableStart)}
+
+ {hms(time)}
- {hms(duration)}
+ {live ? `${hms(seekableStart)} - ${hms(duration)}` : `${hms(duration)}`}
);
}
@@ -159,49 +162,37 @@ function Time() {
function Tracks() {
const audioTracks = usePlayerSelector((player) => player.audioTracks);
const setAudioTrack = usePlayerSelector((player) => player.setAudioTrack);
- const audioKey = audioTracks.find((track) => track.active)?.id.toString();
const subtitleTracks = usePlayerSelector((player) => player.subtitleTracks);
const setSubtitleTrack = usePlayerSelector(
(player) => player.setSubtitleTrack,
);
- const subtitleKey = subtitleTracks
- .find((track) => track.active)
- ?.id.toString();
return (
-
-
-
+ getKey={(item) => item.id}
+ getLabel={(item) => item.label}
+ onChange={(item) => setSubtitleTrack(item.id)}
+ />
);
}
diff --git a/packages/app/src/components/Selection.tsx b/packages/app/src/components/Selection.tsx
new file mode 100644
index 0000000..e206753
--- /dev/null
+++ b/packages/app/src/components/Selection.tsx
@@ -0,0 +1,50 @@
+import { Select, SelectItem } from "@nextui-org/react";
+
+interface SelectionProps
{
+ items: T[];
+ label: string;
+ getKey(item: T): number | string | null;
+ getLabel(item: T): string;
+ getActive(item: T): boolean;
+ onChange(item: T): void;
+}
+
+export function Selection({
+ items,
+ label,
+ getKey,
+ getLabel,
+ getActive,
+ onChange,
+}: SelectionProps) {
+ const selectedKeys: string[] = [];
+ for (const item of items) {
+ if (getActive(item)) {
+ const key = getKey(item);
+ selectedKeys.push(String(key));
+ }
+ }
+
+ return (
+
+ );
+}
diff --git a/packages/app/src/context/PlayerContext.tsx b/packages/app/src/context/PlayerContext.tsx
index f6ab41a..4168536 100644
--- a/packages/app/src/context/PlayerContext.tsx
+++ b/packages/app/src/context/PlayerContext.tsx
@@ -25,6 +25,14 @@ export function PlayerProvider({ children }: PlayerProviderProps) {
);
}
+export function WithPlayer({ children }: { children: ReactNode }) {
+ const { player } = usePlayer();
+ if (!player) {
+ return null;
+ }
+ return children;
+}
+
export function usePlayer() {
const context = useContext(PlayerContext);
if (!context) {
diff --git a/packages/app/src/routes/(dashboard)/_layout/player.tsx b/packages/app/src/routes/(dashboard)/_layout/player.tsx
index 736c51b..63e6f2e 100644
--- a/packages/app/src/routes/(dashboard)/_layout/player.tsx
+++ b/packages/app/src/routes/(dashboard)/_layout/player.tsx
@@ -14,14 +14,9 @@ import { Player } from "../../../components/Player";
import { PlayerControls } from "../../../components/PlayerControls";
import { PlayerStats } from "../../../components/PlayerStats";
import { ScrollCard } from "../../../components/ScrollCard";
-import {
- PlayerProvider,
- usePlayer,
- usePlayerSelector,
-} from "../../../context/PlayerContext";
+import { PlayerProvider, WithPlayer } from "../../../context/PlayerContext";
import { useSwaggerSchema } from "../../../hooks/useSwaggerSchema";
import type { FormRef } from "../../../components/Form";
-import type { RefObject } from "react";
export const Route = createFileRoute("/(dashboard)/_layout/player")({
component: RouteComponent,
@@ -69,7 +64,42 @@ function RouteComponent() {