More work on youtube view

This commit is contained in:
Nick Mowen 2023-12-30 13:45:42 -07:00
parent c3ca8ebf2c
commit 82ad64143f
2 changed files with 70 additions and 28 deletions

View File

@ -4,21 +4,51 @@ import Logo from "../Logo";
import { formatUnixTimestampToDateTime } from "@/utils/dateUtil"; import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
import useSWR from "swr"; import useSWR from "swr";
import { FrigateConfig } from "@/types/frigateConfig"; import { FrigateConfig } from "@/types/frigateConfig";
import VideoPlayer from "../player/VideoPlayer";
import { Card } from "../ui/card";
type TimelineItemCardProps = { type TimelineItemCardProps = {
timeline: Timeline; timeline: Timeline;
relevantPreview: Preview | undefined; relevantPreview: Preview | undefined;
onSelect: () => void;
}; };
export default function TimelineItemCard({ export default function TimelineItemCard({
timeline, timeline,
relevantPreview, relevantPreview,
onSelect,
}: TimelineItemCardProps) { }: TimelineItemCardProps) {
const { data: config } = useSWR<FrigateConfig>("config"); const { data: config } = useSWR<FrigateConfig>("config");
return ( return (
<div className="relative m-2 flex h-24"> <Card className="relative m-2 flex h-32 cursor-pointer" onClick={onSelect}>
<div className="w-1/2 bg-black"></div> <div className="w-1/2 p-2">
<div className="px-1 w-1/2"> {relevantPreview && (
<VideoPlayer
options={{
preload: "auto",
height: "114",
width: "202",
autoplay: true,
controls: false,
fluid: false,
muted: true,
loadingSpinner: false,
sources: [
{
src: `${relevantPreview.src}`,
type: "video/mp4",
},
],
}}
seekOptions={{}}
onReady={(player) => {
player.pause(); // autoplay + pause is required for iOS
player.currentTime(timeline.timestamp - relevantPreview.start);
}}
/>
)}
</div>
<div className="px-2 py-1 w-1/2">
<div className="capitalize font-semibold text-sm"> <div className="capitalize font-semibold text-sm">
{getTimelineItemDescription(timeline)} {getTimelineItemDescription(timeline)}
</div> </div>
@ -31,7 +61,7 @@ export default function TimelineItemCard({
})} })}
</div> </div>
<Button <Button
className="absolute bottom-0 right-0" className="absolute bottom-1 right-1"
size="sm" size="sm"
variant="secondary" variant="secondary"
> >
@ -41,6 +71,6 @@ export default function TimelineItemCard({
+ +
</Button> </Button>
</div> </div>
</div> </Card>
); );
} }

View File

@ -106,14 +106,10 @@ export default function HistoryTimelineView({
}, [playbackTimes]); }, [playbackTimes]);
const onSelectItem = useCallback( const onSelectItem = useCallback(
(data: { items: number[] }) => { (timeline: Timeline | undefined) => {
if (data.items.length > 0) { if (timeline) {
const selected = data.items[0]; setFocusedItem(timeline);
setFocusedItem( const selected = timeline.timestamp;
playback.timelineItems.find(
(timeline) => timeline.timestamp == selected
)
);
playerRef.current?.pause(); playerRef.current?.pause();
let seekSeconds = 0; let seekSeconds = 0;
@ -135,6 +131,8 @@ export default function HistoryTimelineView({
return true; return true;
}); });
playerRef.current?.currentTime(seekSeconds); playerRef.current?.currentTime(seekSeconds);
} else {
setFocusedItem(undefined);
} }
}, },
[annotationOffset, recordings, playerRef] [annotationOffset, recordings, playerRef]
@ -197,7 +195,6 @@ export default function HistoryTimelineView({
hasRelevantPreview={hasRelevantPreview} hasRelevantPreview={hasRelevantPreview}
scrubbing={scrubbing} scrubbing={scrubbing}
focusedItem={focusedItem} focusedItem={focusedItem}
setFocusedItem={setFocusedItem}
setSeeking={setSeeking} setSeeking={setSeeking}
onSelectItem={onSelectItem} onSelectItem={onSelectItem}
onScrubTime={onScrubTime} onScrubTime={onScrubTime}
@ -218,7 +215,6 @@ export default function HistoryTimelineView({
hasRelevantPreview={hasRelevantPreview} hasRelevantPreview={hasRelevantPreview}
scrubbing={scrubbing} scrubbing={scrubbing}
focusedItem={focusedItem} focusedItem={focusedItem}
setFocusedItem={setFocusedItem}
setSeeking={setSeeking} setSeeking={setSeeking}
onSelectItem={onSelectItem} onSelectItem={onSelectItem}
onScrubTime={onScrubTime} onScrubTime={onScrubTime}
@ -238,9 +234,8 @@ type DesktopViewProps = {
hasRelevantPreview: boolean; hasRelevantPreview: boolean;
scrubbing: boolean; scrubbing: boolean;
focusedItem: Timeline | undefined; focusedItem: Timeline | undefined;
setFocusedItem: (item: Timeline | undefined) => void;
setSeeking: (seeking: boolean) => void; setSeeking: (seeking: boolean) => void;
onSelectItem: ({ items }: { items: number[] }) => void; onSelectItem: (timeline: Timeline | undefined) => void;
onScrubTime: ({ time }: { time: Date }) => void; onScrubTime: ({ time }: { time: Date }) => void;
onStopScrubbing: ({ time }: { time: Date }) => void; onStopScrubbing: ({ time }: { time: Date }) => void;
}; };
@ -255,7 +250,6 @@ function DesktopView({
hasRelevantPreview, hasRelevantPreview,
scrubbing, scrubbing,
focusedItem, focusedItem,
setFocusedItem,
setSeeking, setSeeking,
onSelectItem, onSelectItem,
onScrubTime, onScrubTime,
@ -275,7 +269,8 @@ function DesktopView({
preload: "auto", preload: "auto",
autoplay: true, autoplay: true,
fluid: false, fluid: false,
height: "320", height: "608",
width: "1080",
sources: [ sources: [
{ {
src: playbackUri, src: playbackUri,
@ -288,7 +283,7 @@ function DesktopView({
playerRef.current = player; playerRef.current = player;
player.currentTime(timelineTime - playbackTimes.start); player.currentTime(timelineTime - playbackTimes.start);
player.on("playing", () => { player.on("playing", () => {
setFocusedItem(undefined); onSelectItem(undefined);
}); });
}} }}
onDispose={() => { onDispose={() => {
@ -331,13 +326,14 @@ function DesktopView({
</div> </div>
)} )}
</> </>
<div className="px-2 w-full h-80 overflow-auto"> <div className="px-2 w-full h-[608px] overflow-auto">
{playback.timelineItems.map((timeline) => { {playback.timelineItems.map((timeline) => {
return ( return (
<TimelineItemCard <TimelineItemCard
key={timeline.timestamp} key={timeline.timestamp}
timeline={timeline} timeline={timeline}
relevantPreview={playback.relevantPreview} relevantPreview={playback.relevantPreview}
onSelect={() => onSelectItem(timeline)}
/> />
); );
})} })}
@ -346,7 +342,7 @@ function DesktopView({
<div className="m-1"> <div className="m-1">
{playback != undefined && ( {playback != undefined && (
<ActivityScrubber <ActivityScrubber
items={timelineItemsToScrubber(playback.timelineItems)} items={[]}
timeBars={ timeBars={
hasRelevantPreview hasRelevantPreview
? [{ time: new Date(timelineTime * 1000), id: "playback" }] ? [{ time: new Date(timelineTime * 1000), id: "playback" }]
@ -359,7 +355,16 @@ function DesktopView({
}} }}
timechangeHandler={onScrubTime} timechangeHandler={onScrubTime}
timechangedHandler={onStopScrubbing} timechangedHandler={onStopScrubbing}
selectHandler={onSelectItem} selectHandler={(data) => {
if (data.items.length > 0) {
const selected = data.items[0];
onSelectItem(
playback.timelineItems.find(
(timeline) => timeline.timestamp == selected
)
);
}
}}
/> />
)} )}
</div> </div>
@ -378,9 +383,8 @@ type MobileViewProps = {
hasRelevantPreview: boolean; hasRelevantPreview: boolean;
scrubbing: boolean; scrubbing: boolean;
focusedItem: Timeline | undefined; focusedItem: Timeline | undefined;
setFocusedItem: (item: Timeline | undefined) => void;
setSeeking: (seeking: boolean) => void; setSeeking: (seeking: boolean) => void;
onSelectItem: ({ items }: { items: number[] }) => void; onSelectItem: (timeline: Timeline | undefined) => void;
onScrubTime: ({ time }: { time: Date }) => void; onScrubTime: ({ time }: { time: Date }) => void;
onStopScrubbing: ({ time }: { time: Date }) => void; onStopScrubbing: ({ time }: { time: Date }) => void;
}; };
@ -395,7 +399,6 @@ function MobileView({
hasRelevantPreview, hasRelevantPreview,
scrubbing, scrubbing,
focusedItem, focusedItem,
setFocusedItem,
setSeeking, setSeeking,
onSelectItem, onSelectItem,
onScrubTime, onScrubTime,
@ -425,7 +428,7 @@ function MobileView({
playerRef.current = player; playerRef.current = player;
player.currentTime(timelineTime - playbackTimes.start); player.currentTime(timelineTime - playbackTimes.start);
player.on("playing", () => { player.on("playing", () => {
setFocusedItem(undefined); onSelectItem(undefined);
}); });
}} }}
onDispose={() => { onDispose={() => {
@ -491,7 +494,16 @@ function MobileView({
}} }}
timechangeHandler={onScrubTime} timechangeHandler={onScrubTime}
timechangedHandler={onStopScrubbing} timechangedHandler={onStopScrubbing}
selectHandler={onSelectItem} selectHandler={(data) => {
if (data.items.length > 0) {
const selected = data.items[0];
onSelectItem(
playback.timelineItems.find(
(timeline) => timeline.timestamp == selected
)
);
}
}}
/> />
)} )}
</div> </div>