Add back nav

This commit is contained in:
Nick Mowen 2023-12-21 14:18:23 -07:00
parent c0276f9686
commit 7c7a6a618a
4 changed files with 53 additions and 25 deletions

View File

@ -21,6 +21,9 @@ import HistoryFilterPopover from "@/components/filter/HistoryFilterPopover";
import useApiFilter from "@/hooks/use-api-filter"; import useApiFilter from "@/hooks/use-api-filter";
import HistoryCardView from "@/views/history/HistoryCardView"; import HistoryCardView from "@/views/history/HistoryCardView";
import HistoryTimelineView from "@/views/history/HistoryTimelineView"; import HistoryTimelineView from "@/views/history/HistoryTimelineView";
import { Button } from "@/components/ui/button";
import { LuStepBack } from "react-icons/lu";
import { IoMdArrowBack } from "react-icons/io";
const API_LIMIT = 200; const API_LIMIT = 200;
@ -80,7 +83,7 @@ function History() {
{ revalidateOnFocus: false } { revalidateOnFocus: false }
); );
const [playback, setPlayback] = useState<Card | undefined>(); const [playback, setPlayback] = useState<TimelinePlayback | undefined>();
const shouldAutoPlay = useMemo(() => { const shouldAutoPlay = useMemo(() => {
return playback == undefined && window.innerWidth < 480; return playback == undefined && window.innerWidth < 480;
@ -141,7 +144,16 @@ function History() {
return ( return (
<> <>
<div className="flex justify-between"> <div className="flex justify-between">
<div className="flex">
<Button
size="sm"
variant="ghost"
onClick={() => setPlayback(undefined)}
>
<IoMdArrowBack className="w-6 h-6" />
</Button>
<Heading as="h2">History</Heading> <Heading as="h2">History</Heading>
</div>
{!playback && ( {!playback && (
<HistoryFilterPopover <HistoryFilterPopover
filter={historyFilter} filter={historyFilter}
@ -192,10 +204,12 @@ function History() {
setSize(size + 1); setSize(size + 1);
}} }}
onDelete={onDelete} onDelete={onDelete}
onItemSelected={(card) => setPlayback(card)} onItemSelected={(item) => setPlayback(item)}
/> />
)} )}
{playback != undefined && <HistoryTimelineView card={playback} isMobile={shouldAutoPlay} />} {playback != undefined && (
<HistoryTimelineView playback={playback} isMobile={shouldAutoPlay} />
)}
</> </>
</> </>
); );

View File

@ -55,3 +55,9 @@ interface HistoryFilter extends FilterType {
after: number | undefined; after: number | undefined;
detailLevel: "normal" | "extra" | "full"; detailLevel: "normal" | "extra" | "full";
} }
type TimelinePlayback = {
camera: string;
timelineItems: Timeline[];
relevantPreview: Preview | undefined;
};

View File

@ -14,7 +14,7 @@ type HistoryCardViewProps = {
isDone: boolean; isDone: boolean;
onNextPage: () => void; onNextPage: () => void;
onDelete: (card: Card) => void; onDelete: (card: Card) => void;
onItemSelected: (card: Card) => void; onItemSelected: (item: TimelinePlayback) => void;
}; };
export default function HistoryCardView({ export default function HistoryCardView({
@ -115,7 +115,17 @@ export default function HistoryCardView({
shouldAutoPlay={isMobileView} shouldAutoPlay={isMobileView}
relevantPreview={relevantPreview} relevantPreview={relevantPreview}
onClick={() => { onClick={() => {
onItemSelected(timeline); onItemSelected({
camera: timeline.camera,
timelineItems: Object.values(
timelineHour
).flatMap((card) =>
card.camera == timeline.camera
? card.entries
: []
),
relevantPreview: relevantPreview,
});
}} }}
onDelete={() => onDelete(timeline)} onDelete={() => onDelete(timeline)}
/> />

View File

@ -1,21 +1,18 @@
import { useApiHost } from "@/api"; import { useApiHost } from "@/api";
import VideoPlayer from "@/components/player/VideoPlayer"; import VideoPlayer from "@/components/player/VideoPlayer";
import ActivityScrubber from "@/components/scrubber/ActivityScrubber"; import ActivityScrubber from "@/components/scrubber/ActivityScrubber";
import { import { Button } from "@/components/ui/button";
getTimelineIcon, import { getTimelineItemDescription } from "@/utils/timelineUtil";
getTimelineItemDescription,
} from "@/utils/timelineUtil";
import { useMemo, useRef, useState } from "react"; import { useMemo, useRef, useState } from "react";
import { LuDog } from "react-icons/lu";
import Player from "video.js/dist/types/player"; import Player from "video.js/dist/types/player";
type HistoryTimelineViewProps = { type HistoryTimelineViewProps = {
card: Card; playback: TimelinePlayback;
isMobile: boolean; isMobile: boolean;
}; };
export default function HistoryTimelineView({ export default function HistoryTimelineView({
card, playback,
isMobile, isMobile,
}: HistoryTimelineViewProps) { }: HistoryTimelineViewProps) {
const apiHost = useApiHost(); const apiHost = useApiHost();
@ -23,13 +20,14 @@ export default function HistoryTimelineView({
const previewRef = useRef<Player | undefined>(undefined); const previewRef = useRef<Player | undefined>(undefined);
const [scrubbing, setScrubbing] = useState(false); const [scrubbing, setScrubbing] = useState(false);
const relevantPreview = {
src: "http://localhost:5173/clips/previews/side_cam/1703174400.071426-1703178000.011979.mp4",
start: 1703174400.071426,
end: 1703178000.011979,
};
const timelineTime = useMemo(() => card.entries.at(0)!!.timestamp, [card]); const timelineTime = useMemo(() => {
if (!playback) {
return 0;
}
return playback.timelineItems.at(0)!!.timestamp;
}, [playback]);
const playbackTimes = useMemo(() => { const playbackTimes = useMemo(() => {
const date = new Date(timelineTime * 1000); const date = new Date(timelineTime * 1000);
date.setMinutes(0, 0, 0); date.setMinutes(0, 0, 0);
@ -40,12 +38,12 @@ export default function HistoryTimelineView({
}, [timelineTime]); }, [timelineTime]);
const playbackUri = useMemo(() => { const playbackUri = useMemo(() => {
if (!card) { if (!playback) {
return ""; return "";
} }
return `${apiHost}vod/${card?.camera}/start/${playbackTimes.start}/end/${playbackTimes.end}/master.m3u8`; return `${apiHost}vod/${playback.camera}/start/${playbackTimes.start}/end/${playbackTimes.end}/master.m3u8`;
}, [card, playbackTimes]); }, [playback, playbackTimes]);
return ( return (
<> <>
@ -92,7 +90,7 @@ export default function HistoryTimelineView({
loadingSpinner: false, loadingSpinner: false,
sources: [ sources: [
{ {
src: `${relevantPreview.src}`, src: `${playback.relevantPreview!!.src}`,
type: "video/mp4", type: "video/mp4",
}, },
], ],
@ -107,7 +105,7 @@ export default function HistoryTimelineView({
/> />
</div> </div>
<ActivityScrubber <ActivityScrubber
items={timelineItemsToScrubber(card.entries)} items={timelineItemsToScrubber(playback.timelineItems)}
timeBars={[{ time: new Date(timelineTime * 1000), id: "playback" }]} timeBars={[{ time: new Date(timelineTime * 1000), id: "playback" }]}
options={{ options={{
min: new Date(parseInt(playbackTimes.start) * 1000), min: new Date(parseInt(playbackTimes.start) * 1000),
@ -122,7 +120,7 @@ export default function HistoryTimelineView({
const seekTimestamp = data.time.getTime() / 1000; const seekTimestamp = data.time.getTime() / 1000;
previewRef.current?.currentTime( previewRef.current?.currentTime(
seekTimestamp - relevantPreview.start seekTimestamp - playback.relevantPreview!!.start
); );
}} }}
timechangedHandler={(data) => { timechangedHandler={(data) => {