@@ -22,36 +22,24 @@ import {
2222 getAvailableDatesForSegments ,
2323 getClippedSegmentHourRange ,
2424 getLocalDayBounds ,
25+ getTimelineDayLengthHours ,
26+ localClockTimeToTimestamp ,
2527 panTimelineRange ,
28+ timelineOffsetToTimestamp ,
29+ timestampToTimelineOffset ,
2630 zoomTimelineRange
2731} from './timelineUtils.js' ;
2832
2933const RECORDINGS_RETURN_URL_KEY = 'lightnvr_recordings_return_url' ;
3034
31- // Convert fractional hour (0–24) → Unix timestamp (seconds) for the given date
35+ // Convert an elapsed timeline offset → Unix timestamp (seconds) for the selected local day.
3236function timelineHourToTimestamp ( hour , selectedDate ) {
33- const numericHour = Number ( hour ) ;
34- if ( ! Number . isFinite ( numericHour ) ) {
35- throw new Error ( `timelineHourToTimestamp: invalid hour value "${ hour } "` ) ;
36- }
37-
38- const normalizedHour = Math . min ( 24 , Math . max ( 0 , numericHour ) ) ;
39-
40- let date ;
41- if ( selectedDate && typeof selectedDate === 'string' && selectedDate . includes ( '-' ) ) {
42- const [ year , month , day ] = selectedDate . split ( '-' ) . map ( Number ) ;
43- date = new Date ( year , month - 1 , day , 0 , 0 , 0 , 0 ) ;
44- } else {
45- date = new Date ( ) ;
46- date . setHours ( 0 , 0 , 0 , 0 ) ;
47- }
48- return Math . floor ( ( date . getTime ( ) + normalizedHour * 3600000 ) / 1000 ) ;
37+ return timelineOffsetToTimestamp ( hour , selectedDate ) ;
4938}
5039
51- // Utility function to convert timestamp to timeline hour
52- function timestampToTimelineHour ( timestamp ) {
53- const date = new Date ( timestamp * 1000 ) ;
54- return date . getHours ( ) + ( date . getMinutes ( ) / 60 ) + ( date . getSeconds ( ) / 3600 ) ;
40+ // Convert a Unix timestamp to an elapsed timeline offset for the selected local day.
41+ function timestampToTimelineHour ( timestamp , selectedDate = null ) {
42+ return timestampToTimelineOffset ( timestamp , selectedDate ) ;
5543}
5644
5745// Global timeline state for child components
@@ -264,7 +252,7 @@ export function TimelinePage() {
264252
265253 const handleWheel = ( event ) => {
266254 const startHour = timelineState . timelineStartHour ?? 0 ;
267- const endHour = timelineState . timelineEndHour ?? 24 ;
255+ const endHour = timelineState . timelineEndHour ?? getTimelineDayLengthHours ( timelineState . selectedDate ) ;
268256 const currentRange = endHour - startHour ;
269257 if ( currentRange <= 0 ) {
270258 return ;
@@ -280,7 +268,7 @@ export function TimelinePage() {
280268 const pointerRatio = Math . min ( Math . max ( ( event . clientX - rect . left ) / rect . width , 0 ) , 1 ) ;
281269 const anchorHour = startHour + ( pointerRatio * currentRange ) ;
282270 const zoomFactor = event . deltaY < 0 ? 0.8 : 1.25 ;
283- const nextRange = zoomTimelineRange ( startHour , endHour , zoomFactor , anchorHour ) ;
271+ const nextRange = zoomTimelineRange ( startHour , endHour , zoomFactor , anchorHour , getTimelineDayLengthHours ( timelineState . selectedDate ) ) ;
284272 timelineState . setState ( {
285273 timelineStartHour : nextRange . startHour ,
286274 timelineEndHour : nextRange . endHour
@@ -295,7 +283,7 @@ export function TimelinePage() {
295283 if ( horizontalDelta !== 0 ) {
296284 event . preventDefault ( ) ;
297285 const deltaHours = ( horizontalDelta / rect . width ) * currentRange ;
298- const nextRange = panTimelineRange ( startHour , endHour , deltaHours ) ;
286+ const nextRange = panTimelineRange ( startHour , endHour , deltaHours , getTimelineDayLengthHours ( timelineState . selectedDate ) ) ;
299287 timelineState . setState ( {
300288 timelineStartHour : nextRange . startHour ,
301289 timelineEndHour : nextRange . endHour
@@ -360,10 +348,11 @@ export function TimelinePage() {
360348 setSegments ( segmentsCopy ) ;
361349
362350 const dayBounds = getLocalDayBounds ( effectiveDate ) ;
351+ const dayLengthHours = getTimelineDayLengthHours ( effectiveDate ) ;
363352 const visibleIndices = [ ] ;
364353
365354 // Compute auto-fit range from segments for the selected day
366- let earliest = 24 ;
355+ let earliest = dayLengthHours ;
367356 let latest = 0 ;
368357 segmentsCopy . forEach ( ( seg , index ) => {
369358 const visibleRange = getClippedSegmentHourRange ( seg , effectiveDate ) ;
@@ -382,9 +371,9 @@ export function TimelinePage() {
382371 isPlaying : false ,
383372 selectedDate : effectiveDate ,
384373 timelineStartHour : 0 ,
385- timelineEndHour : 24 ,
374+ timelineEndHour : dayLengthHours ,
386375 autoFitStartHour : 0 ,
387- autoFitEndHour : 24
376+ autoFitEndHour : dayLengthHours
388377 } ) ;
389378 return false ;
390379 }
@@ -428,10 +417,8 @@ export function TimelinePage() {
428417 }
429418
430419 if ( initialSegmentIndex === - 1 && initialTimeRef . current ) {
431- const timeParts = initialTimeRef . current . match ( / ^ ( \d { 2 } ) : ( \d { 2 } ) : ( \d { 2 } ) $ / ) ;
432- if ( timeParts ) {
433- const [ , h , m , s ] = timeParts . map ( Number ) ;
434- const seekTs = timelineHourToTimestamp ( h + m / 60 + s / 3600 , effectiveDate ) ;
420+ const seekTs = localClockTimeToTimestamp ( initialTimeRef . current , effectiveDate ) ;
421+ if ( seekTs !== null ) {
435422
436423 const containingIndex = findContainingSegmentIndex ( segmentsCopy , seekTs ) ;
437424 if ( containingIndex !== - 1 && getClippedSegmentHourRange ( segmentsCopy [ containingIndex ] , effectiveDate ) ) {
@@ -460,16 +447,16 @@ export function TimelinePage() {
460447 }
461448
462449 let fitStart = 0 ;
463- let fitEnd = 24 ;
464- if ( earliest < 24 && latest > 0 ) {
450+ let fitEnd = dayLengthHours ;
451+ if ( earliest < dayLengthHours && latest > 0 ) {
465452 const span = latest - earliest ;
466453 const pad = Math . max ( 0.5 , Math . min ( 1 , span * 0.1 ) ) ;
467454 fitStart = Math . max ( 0 , Math . floor ( ( earliest - pad ) * 2 ) / 2 ) ;
468- fitEnd = Math . min ( 24 , Math . ceil ( ( latest + pad ) * 2 ) / 2 ) ;
455+ fitEnd = Math . min ( dayLengthHours , Math . ceil ( ( latest + pad ) * 2 ) / 2 ) ;
469456 if ( fitEnd - fitStart < 2 ) {
470457 const center = ( earliest + latest ) / 2 ;
471458 fitStart = Math . max ( 0 , Math . floor ( ( center - 1 ) * 2 ) / 2 ) ;
472- fitEnd = Math . min ( 24 , fitStart + 2 ) ;
459+ fitEnd = Math . min ( dayLengthHours , fitStart + 2 ) ;
473460 }
474461 }
475462
0 commit comments