detail stream seeking fixes

This commit is contained in:
Josh Hawkins 2025-11-01 07:29:37 -05:00
parent b9ca9e49dd
commit 787668ba0c

View File

@ -57,7 +57,7 @@ export default function DetailStream({
elementRef: scrollRef, elementRef: scrollRef,
}); });
const effectiveTime = currentTime + annotationOffset / 1000; const effectiveTime = currentTime - annotationOffset / 1000;
const [upload, setUpload] = useState<Event | undefined>(undefined); const [upload, setUpload] = useState<Event | undefined>(undefined);
const [controlsExpanded, setControlsExpanded] = useState(false); const [controlsExpanded, setControlsExpanded] = useState(false);
const [alwaysExpandActive, setAlwaysExpandActive] = usePersistence( const [alwaysExpandActive, setAlwaysExpandActive] = usePersistence(
@ -213,6 +213,7 @@ export default function DetailStream({
config={config} config={config}
onSeek={onSeekCheckPlaying} onSeek={onSeekCheckPlaying}
effectiveTime={effectiveTime} effectiveTime={effectiveTime}
annotationOffset={annotationOffset}
isActive={activeReviewId == id} isActive={activeReviewId == id}
onActivate={() => setActiveReviewId(id)} onActivate={() => setActiveReviewId(id)}
onOpenUpload={(e) => setUpload(e)} onOpenUpload={(e) => setUpload(e)}
@ -278,6 +279,7 @@ type ReviewGroupProps = {
onActivate?: () => void; onActivate?: () => void;
onOpenUpload?: (e: Event) => void; onOpenUpload?: (e: Event) => void;
effectiveTime?: number; effectiveTime?: number;
annotationOffset: number;
alwaysExpandActive?: boolean; alwaysExpandActive?: boolean;
}; };
@ -290,11 +292,14 @@ function ReviewGroup({
onActivate, onActivate,
onOpenUpload, onOpenUpload,
effectiveTime, effectiveTime,
annotationOffset,
alwaysExpandActive = false, alwaysExpandActive = false,
}: ReviewGroupProps) { }: ReviewGroupProps) {
const { t } = useTranslation("views/events"); const { t } = useTranslation("views/events");
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const start = review.start_time ?? 0; const start = review.start_time ?? 0;
// review.start_time is in detect time, convert to record for seeking
const startRecord = start + annotationOffset / 1000;
// Auto-expand when this review becomes active and alwaysExpandActive is enabled // Auto-expand when this review becomes active and alwaysExpandActive is enabled
useEffect(() => { useEffect(() => {
@ -371,7 +376,7 @@ function ReviewGroup({
)} )}
onClick={() => { onClick={() => {
onActivate?.(); onActivate?.();
onSeek(start); onSeek(startRecord);
}} }}
> >
<div className="ml-4 mr-2 mt-1.5 flex flex-row items-start"> <div className="ml-4 mr-2 mt-1.5 flex flex-row items-start">
@ -450,6 +455,7 @@ function ReviewGroup({
key={event.id} key={event.id}
event={event} event={event}
effectiveTime={effectiveTime} effectiveTime={effectiveTime}
annotationOffset={annotationOffset}
onSeek={onSeek} onSeek={onSeek}
onOpenUpload={onOpenUpload} onOpenUpload={onOpenUpload}
/> />
@ -483,12 +489,14 @@ function ReviewGroup({
type EventListProps = { type EventListProps = {
event: Event; event: Event;
effectiveTime?: number; effectiveTime?: number;
annotationOffset: number;
onSeek: (ts: number, play?: boolean) => void; onSeek: (ts: number, play?: boolean) => void;
onOpenUpload?: (e: Event) => void; onOpenUpload?: (e: Event) => void;
}; };
function EventList({ function EventList({
event, event,
effectiveTime, effectiveTime,
annotationOffset,
onSeek, onSeek,
onOpenUpload, onOpenUpload,
}: EventListProps) { }: EventListProps) {
@ -505,14 +513,17 @@ function EventList({
if (event) { if (event) {
setSelectedObjectIds([]); setSelectedObjectIds([]);
setSelectedObjectIds([event.id]); setSelectedObjectIds([event.id]);
onSeek(event.start_time); // event.start_time is detect time, convert to record
const recordTime = event.start_time + annotationOffset / 1000;
onSeek(recordTime);
} else { } else {
setSelectedObjectIds([]); setSelectedObjectIds([]);
} }
}; };
const handleTimelineClick = (ts: number, play?: boolean) => { const handleTimelineClick = (ts: number, play?: boolean) => {
handleObjectSelect(event); setSelectedObjectIds([]);
setSelectedObjectIds([event.id]);
onSeek(ts, play); onSeek(ts, play);
}; };
@ -554,7 +565,6 @@ function EventList({
)} )}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
onSeek(event.start_time);
handleObjectSelect(event); handleObjectSelect(event);
}} }}
role="button" role="button"
@ -568,7 +578,6 @@ function EventList({
className="flex flex-1 items-center gap-2" className="flex flex-1 items-center gap-2"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
onSeek(event.start_time);
handleObjectSelect(event); handleObjectSelect(event);
}} }}
role="button" role="button"
@ -607,6 +616,7 @@ function EventList({
eventId={event.id} eventId={event.id}
onSeek={handleTimelineClick} onSeek={handleTimelineClick}
effectiveTime={effectiveTime} effectiveTime={effectiveTime}
annotationOffset={annotationOffset}
startTime={event.start_time} startTime={event.start_time}
endTime={event.end_time} endTime={event.end_time}
/> />
@ -621,6 +631,7 @@ type LifecycleItemProps = {
isActive?: boolean; isActive?: boolean;
onSeek?: (timestamp: number, play?: boolean) => void; onSeek?: (timestamp: number, play?: boolean) => void;
effectiveTime?: number; effectiveTime?: number;
annotationOffset: number;
isTimelineActive?: boolean; isTimelineActive?: boolean;
}; };
@ -629,6 +640,7 @@ function LifecycleItem({
isActive, isActive,
onSeek, onSeek,
effectiveTime, effectiveTime,
annotationOffset,
isTimelineActive = false, isTimelineActive = false,
}: LifecycleItemProps) { }: LifecycleItemProps) {
const { t } = useTranslation("views/events"); const { t } = useTranslation("views/events");
@ -682,7 +694,8 @@ function LifecycleItem({
<div <div
role="button" role="button"
onClick={() => { onClick={() => {
onSeek?.(item.timestamp, false); const recordTimestamp = item.timestamp + annotationOffset / 1000;
onSeek?.(recordTimestamp, false);
}} }}
className={cn( className={cn(
"flex cursor-pointer items-center gap-2 text-sm text-primary-variant", "flex cursor-pointer items-center gap-2 text-sm text-primary-variant",
@ -751,12 +764,14 @@ function ObjectTimeline({
eventId, eventId,
onSeek, onSeek,
effectiveTime, effectiveTime,
annotationOffset,
startTime, startTime,
endTime, endTime,
}: { }: {
eventId: string; eventId: string;
onSeek: (ts: number, play?: boolean) => void; onSeek: (ts: number, play?: boolean) => void;
effectiveTime?: number; effectiveTime?: number;
annotationOffset: number;
startTime?: number; startTime?: number;
endTime?: number; endTime?: number;
}) { }) {
@ -857,6 +872,7 @@ function ObjectTimeline({
onSeek={onSeek} onSeek={onSeek}
isActive={isActive} isActive={isActive}
effectiveTime={effectiveTime} effectiveTime={effectiveTime}
annotationOffset={annotationOffset}
isTimelineActive={isWithinEventRange} isTimelineActive={isWithinEventRange}
/> />
); );