blakeblackshear.frigate/web/src/components/bar/TimelineBar.tsx
Nicolas Mowen af3f6dadcb Improve graph using pandas (#9234)
* Ensure viewport is always full screen

* Protect against hour with no cards and ensure data is consistent

* Reduce grouped up image refreshes

* Include current hour and fix scrubbing bugginess

* Scroll initially selected timeline in to view

* Expand timelne class type

* Use poster image for preview on video player instead of using separate image view

* Fix available streaming modes

* Incrase timing for grouping timline items

* Fix audio activity listener

* Fix player not switching views correctly

* Use player time to convert to timeline time

* Update sub labels for previous timeline items

* Show mini timeline bar for non selected items

* Rewrite desktop timeline to use separate dynamic video player component

* Extend improvements to mobile as well

* Improve time formatting

* Fix scroll

* Fix no preview case

* Mobile fixes

* Audio toggle fixes

* More fixes for mobile

* Improve scaling of graph motion activity

* Add keyboard shortcut hook and support shortcuts for playback page

* Fix sizing of dialog

* Improve height scaling of dialog

* simplify and fix layout system for timeline

* Fix timeilne items not working

* Implement basic Frigate+ submitting from timeline
2024-01-31 12:56:11 +00:00

192 lines
7.2 KiB
TypeScript

import { FrigateConfig } from "@/types/frigateConfig";
import { GraphDataPoint } from "@/types/graph";
import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
import useSWR from "swr";
import ActivityIndicator from "../ui/activity-indicator";
type TimelineBarProps = {
startTime: number;
graphData:
| {
objects: number[];
motion: GraphDataPoint[];
}
| undefined;
onClick?: () => void;
};
export default function TimelineBar({
startTime,
graphData,
onClick,
}: TimelineBarProps) {
const { data: config } = useSWR<FrigateConfig>("config");
if (!config) {
return <ActivityIndicator />;
}
return (
<div
className="my-1 p-1 w-full h-18 border rounded cursor-pointer hover:bg-secondary hover:bg-opacity-30"
onClick={onClick}
>
{graphData != undefined && (
<div className="relative w-full h-8 flex">
{getHourBlocks().map((idx) => {
return (
<div
key={idx}
className={`h-2 flex-auto ${
(graphData.motion.at(idx)?.y || 0) == 0
? ""
: graphData.objects.includes(idx)
? "bg-object"
: "bg-motion"
}`}
/>
);
})}
<div className="absolute left-0 top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:00" : "%I:00%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[8.3%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:05" : "%I:05%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[16.7%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:10" : "%I:10%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[25%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:15" : "%I:15%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[33.3%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:20" : "%I:20%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[41.7%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:25" : "%I:25%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[50%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:30" : "%I:30%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[58.3%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:35" : "%I:35%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[66.7%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:40" : "%I:40%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[75%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:45" : "%I:45%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[83.3%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:50" : "%I:50%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
<div className="absolute left-[91.7%] top-0 bottom-0 align-bottom border-l border-gray-500">
<div className="absolute ml-1 bottom-0 text-sm text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config?.ui.time_format == "24hour" ? "%H:55" : "%I:55%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
</div>
)}
<div className="text-gray-500">
{formatUnixTimestampToDateTime(startTime, {
strftime_fmt:
config.ui.time_format == "24hour" ? "%m/%d %H:%M" : "%m/%d %I:%M%P",
time_style: "medium",
date_style: "medium",
})}
</div>
</div>
);
}
function getHourBlocks() {
const arr = [];
for (let x = 0; x <= 59; x++) {
arr.push(x);
}
return arr;
}