Compare commits

...

4 Commits

Author SHA1 Message Date
Josh Hawkins
7edc36dbd4
Merge 426699d3d0 into de066d0062 2025-11-12 23:23:00 +00:00
Nicolas Mowen
426699d3d0 Use timeline tab by default for notifications but add a query arg for customization 2025-11-12 16:22:55 -07:00
Josh Hawkins
73b9193a19 fix blue line height calc for in progress events 2025-11-12 11:42:50 -06:00
Josh Hawkins
daa9919966 don't show object track until video metadata is loaded 2025-11-12 11:21:40 -06:00
4 changed files with 35 additions and 8 deletions

View File

@ -221,12 +221,26 @@ export function TrackingDetails({
displaySource,
]);
const isWithinEventRange =
effectiveTime !== undefined &&
event.start_time !== undefined &&
event.end_time !== undefined &&
effectiveTime >= event.start_time &&
effectiveTime <= event.end_time;
const isWithinEventRange = useMemo(() => {
if (effectiveTime === undefined || event.start_time === undefined) {
return false;
}
// If an event has not ended yet, fall back to last timestamp in eventSequence
let eventEnd = event.end_time;
if (eventEnd == null && eventSequence && eventSequence.length > 0) {
const last = eventSequence[eventSequence.length - 1];
if (last && last.timestamp !== undefined) {
eventEnd = last.timestamp;
}
}
if (eventEnd == null) {
return false;
}
return effectiveTime >= event.start_time && effectiveTime <= eventEnd;
}, [effectiveTime, event.start_time, event.end_time, eventSequence]);
// Calculate how far down the blue line should extend based on effectiveTime
const calculateLineHeight = useCallback(() => {

View File

@ -318,6 +318,7 @@ export default function HlsVideoPlayer({
{isDetailMode &&
camera &&
currentTime &&
loadedMetadata &&
videoDimensions.width > 0 &&
videoDimensions.height > 0 && (
<div className="absolute z-50 size-full">

View File

@ -15,6 +15,7 @@ import {
ReviewSummary,
SegmentedReviewData,
} from "@/types/review";
import { TimelineType } from "@/types/timeline";
import {
getBeginningOfDayTimestamp,
getEndOfDayTimestamp,
@ -49,6 +50,16 @@ export default function Events() {
false,
);
const [notificationTab, setNotificationTab] =
useState<TimelineType>("timeline");
useSearchEffect("tab", (tab: string) => {
if (tab === "timeline" || tab === "events" || tab === "detail") {
setNotificationTab(tab as TimelineType);
}
return true;
});
useSearchEffect("id", (reviewId: string) => {
axios
.get(`review/${reviewId}`)
@ -66,7 +77,7 @@ export default function Events() {
camera: resp.data.camera,
startTime,
severity: resp.data.severity,
timelineType: "detail",
timelineType: notificationTab,
},
true,
);

View File

@ -1,4 +1,5 @@
import { ReviewSeverity } from "./review";
import { TimelineType } from "./timeline";
export type Recording = {
id: string;
@ -37,7 +38,7 @@ export type RecordingStartingPoint = {
camera: string;
startTime: number;
severity: ReviewSeverity;
timelineType?: "timeline" | "events" | "detail";
timelineType?: TimelineType;
};
export type RecordingPlayerError = "stalled" | "startup";