WebUI Improvements and fixes (#9613)

* Show toast instead of text for success and errors

* Show correct times

* Start playing next hour when current hour ends

* Fix refreshing camera image

* Fix timeline
This commit is contained in:
Nicolas Mowen
2024-02-05 16:54:08 -07:00
committed by GitHub
parent 3df8b5829c
commit f4310862aa
10 changed files with 435 additions and 57 deletions

View File

@@ -24,6 +24,9 @@ export default function DynamicCameraImage({
aspect,
}: DynamicCameraImageProps) {
const [key, setKey] = useState(Date.now());
const [timeoutId, setTimeoutId] = useState<NodeJS.Timeout | undefined>(
undefined
);
const [activeObjects, setActiveObjects] = useState<string[]>([]);
const hasActiveObjects = useMemo(
() => activeObjects.length > 0,
@@ -58,6 +61,8 @@ export default function DynamicCameraImage({
if (eventIndex == -1) {
const newActiveObjects = [...activeObjects, event.after.id];
setActiveObjects(newActiveObjects);
clearTimeout(timeoutId);
setKey(Date.now());
}
}
}
@@ -69,12 +74,13 @@ export default function DynamicCameraImage({
? INTERVAL_ACTIVE_MS
: INTERVAL_INACTIVE_MS;
setTimeout(
const tId = setTimeout(
() => {
setKey(Date.now());
},
loadTime > loadInterval ? 1 : loadInterval
);
setTimeoutId(tId);
}, [key]);
return (

View File

@@ -228,6 +228,7 @@ export default function DynamicVideoPlayer({
player.on("timeupdate", () => {
controller.updateProgress(player.currentTime() || 0);
});
player.on("ended", () => controller.fireClipEndEvent());
if (onControllerReady) {
onControllerReady(controller);
@@ -284,6 +285,7 @@ export class DynamicVideoController {
// playback
private recordings: Recording[] = [];
private onPlaybackTimestamp: ((time: number) => void) | undefined = undefined;
private onClipEnded: (() => void) | undefined = undefined;
private annotationOffset: number;
private timeToStart: number | undefined = undefined;
@@ -393,6 +395,16 @@ export class DynamicVideoController {
this.onPlaybackTimestamp = listener;
}
onClipEndedEvent(listener: () => void) {
this.onClipEnded = listener;
}
fireClipEndEvent() {
if (this.onClipEnded) {
this.onClipEnded();
}
}
scrubToTimestamp(time: number) {
if (this.playerMode != "scrubbing") {
this.playerMode = "scrubbing";

View File

@@ -0,0 +1,32 @@
import { useTheme } from "next-themes";
import { Toaster as Sonner } from "sonner";
type ToasterProps = React.ComponentProps<typeof Sonner>;
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme();
return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
success:
"group toast group-[.toaster]:bg-success group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
error: "group toast group-[.toaster]:bg-danger group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
},
}}
{...props}
/>
);
};
export { Toaster };