diff --git a/web/src/components/Statusbar.tsx b/web/src/components/Statusbar.tsx index d2a038209..63f9ed891 100644 --- a/web/src/components/Statusbar.tsx +++ b/web/src/components/Statusbar.tsx @@ -65,7 +65,7 @@ export default function Statusbar({}) { const gpu = parseInt(stats.gpu); return ( -
+
)} - {!playingBack && - (review.severity == "alert" || review.severity == "detection") && ( -
- {review.data.objects.map((object) => { - return getIconForLabel(object, "w-3 h-3 text-white"); - })} - {review.data.audio.map((audio) => { - return getIconForLabel(audio, "w-3 h-3 text-white"); - })} - {review.data.sub_labels?.map((sub) => { - return getIconForSubLabel(sub, "w-3 h-3 text-white"); - })} -
- )} + {(review.severity == "alert" || review.severity == "detection") && ( + + {review.data.objects.map((object) => { + return getIconForLabel(object, "w-3 h-3 text-white"); + })} + {review.data.audio.map((audio) => { + return getIconForLabel(audio, "w-3 h-3 text-white"); + })} + {review.data.sub_labels?.map((sub) => { + return getIconForSubLabel(sub, "w-3 h-3 text-white"); + })} + + )} {!playingBack && (
- + {config && formatUnixTimestampToDateTime(review.start_time, { strftime_fmt: @@ -184,6 +185,26 @@ function PreviewContent({ setProgress, setReviewed, }: PreviewContentProps) { + // manual playback + // safari is incapable of playing at a speed > 2x + // so manual seeking is required on iOS + + const [manualPlayback, setManualPlayback] = useState(false); + useEffect(() => { + if (!manualPlayback || !playerRef.current) { + return; + } + + const intervalId: NodeJS.Timeout = setInterval(() => { + if (playerRef.current) { + playerRef.current.currentTime(playerRef.current.currentTime()!! + 1); + } + }, 125); + return () => clearInterval(intervalId); + }, [manualPlayback, playerRef]); + + // preview + if (relevantPreview && playback) { return ( { - if (!setProgress || playerRef.current?.paused()) { + if (!setProgress) { return; } @@ -242,6 +269,7 @@ function PreviewContent({ if (playerPercent > 100) { playerRef.current?.pause(); + setManualPlayback(false); setProgress(100.0); } else { setProgress(playerPercent); diff --git a/web/src/views/events/DesktopEventView.tsx b/web/src/views/events/DesktopEventView.tsx index 78e42e450..ddf3c0aea 100644 --- a/web/src/views/events/DesktopEventView.tsx +++ b/web/src/views/events/DesktopEventView.tsx @@ -116,6 +116,16 @@ export default function DesktopEventView() { [reviewPages] ); + const currentItems = useMemo(() => { + const current = reviewItems[severity]; + + if (!current || current.length == 0) { + return null; + } + + return current; + }, [reviewItems, severity]); + // review interaction const pagingObserver = useRef(); @@ -244,8 +254,6 @@ export default function DesktopEventView() { return ; } - console.log("end of the timeline is " + after + " vs " + (Math.floor(Date.now() / 1000) + 2 * 60 * 60)) - return (
@@ -303,68 +311,57 @@ export default function DesktopEventView() { ref={contentRef} className="absolute left-0 top-12 bottom-0 right-28 flex flex-wrap content-start gap-2 overflow-y-auto no-scrollbar" > - {reviewItems[severity]?.map((value, segIdx) => { - const lastRow = segIdx == reviewItems[severity].length - 1; - const relevantPreview = Object.values(allPreviews || []).find( - (preview) => - preview.camera == value.camera && - preview.start < value.start_time && - preview.end > value.end_time - ); + {currentItems ? ( + currentItems.map((value, segIdx) => { + const lastRow = segIdx == reviewItems[severity].length - 1; + const relevantPreview = Object.values(allPreviews || []).find( + (preview) => + preview.camera == value.camera && + preview.start < value.start_time && + preview.end > value.end_time + ); - return ( -
-
- setReviewed(value.id)} - /> + return ( +
+
+ setReviewed(value.id)} + /> +
+ {lastRow && !isDone && }
- {lastRow && !isDone && } -
- ); - })} + ); + }) + ) : ( +
+ )}
- {after != 0 && ()} + {after != 0 && ( + + )}
); } -/** - * - */ - function ReviewCalendarButton() { const disabledDates = useMemo(() => { const tomorrow = new Date(); diff --git a/web/src/views/events/MobileEventView.tsx b/web/src/views/events/MobileEventView.tsx index eb4c9fb29..c48d5f4b0 100644 --- a/web/src/views/events/MobileEventView.tsx +++ b/web/src/views/events/MobileEventView.tsx @@ -106,6 +106,16 @@ export default function MobileEventView() { [reviewPages] ); + const currentItems = useMemo(() => { + const current = reviewItems[severity]; + + if (!current || current.length == 0) { + return null; + } + + return current; + }, [reviewItems, severity]); + // review interaction const pagingObserver = useRef(); @@ -278,33 +288,37 @@ export default function MobileEventView() { ref={contentRef} className="w-full h-full grid grid-cols-1 sm:grid-cols-2 mt-2 gap-2 overflow-y-auto" > - {reviewItems[severity]?.map((value, segIdx) => { - const lastRow = segIdx == reviewItems[severity].length - 1; - const relevantPreview = Object.values(allPreviews || []).find( - (preview) => - preview.camera == value.camera && - preview.start < value.start_time && - preview.end > value.end_time - ); + {currentItems ? ( + currentItems.map((value, segIdx) => { + const lastRow = segIdx == reviewItems[severity].length - 1; + const relevantPreview = Object.values(allPreviews || []).find( + (preview) => + preview.camera == value.camera && + preview.start < value.start_time && + preview.end > value.end_time + ); - return ( -
-
- setReviewed(value.id)} - /> + return ( +
+
+ setReviewed(value.id)} + /> +
+ {lastRow && !isDone && }
- {lastRow && !isDone && } -
- ); - })} + ); + }) + ) : ( +
+ )}
);