@@ -37,6 +37,33 @@ import { useTabs } from "~/store/zustand/tabs";
3737import { useTimelineSelection } from "~/store/zustand/timeline-selection" ;
3838import { useListener } from "~/stt/contexts" ;
3939
40+ const EMPTY_TIMELINE_ITEM_KEYS : string [ ] = [ ] ;
41+
42+ type ItemBaseProps = {
43+ title : string ;
44+ displayTime : string ;
45+ isLive ?: boolean ;
46+ amplitude ?: number ;
47+ showSpinner ?: boolean ;
48+ selected : boolean ;
49+ ignored ?: boolean ;
50+ muted ?: boolean ;
51+ multiSelected : boolean ;
52+ onClick : ( ) => void ;
53+ onDoubleClick ?: ( ) => void ;
54+ onCmdClick : ( ) => void ;
55+ onShiftClick : ( ) => void ;
56+ onStop ?: ( ) => void ;
57+ onDragStart ?: ( event : DragEvent < HTMLElement > ) => void ;
58+ contextMenu : MenuItemDef [ ] ;
59+ draggable ?: boolean ;
60+ selectedNodeRef ?: RefCallback < HTMLDivElement > ;
61+ itemNodeRef ?: RefCallback < HTMLDivElement > ;
62+ timelineSessionId ?: string ;
63+ isUpcoming ?: boolean ;
64+ upcomingLabel ?: string ;
65+ } ;
66+
4067export const TimelineItemComponent = memo (
4168 ( {
4269 item,
@@ -45,6 +72,7 @@ export const TimelineItemComponent = memo(
4572 timezone,
4673 multiSelected,
4774 flatItemKeys,
75+ getFlatItemKeys,
4876 selectedNodeRef,
4977 itemNodeRef,
5078 isUpcoming,
@@ -55,12 +83,16 @@ export const TimelineItemComponent = memo(
5583 selected : boolean ;
5684 timezone ?: string ;
5785 multiSelected : boolean ;
58- flatItemKeys : string [ ] ;
86+ flatItemKeys ?: string [ ] ;
87+ getFlatItemKeys ?: ( ) => string [ ] ;
5988 selectedNodeRef ?: RefCallback < HTMLDivElement > ;
6089 itemNodeRef ?: RefCallback < HTMLDivElement > ;
6190 isUpcoming ?: boolean ;
6291 upcomingLabel ?: string ;
6392 } ) => {
93+ const readFlatItemKeys =
94+ getFlatItemKeys ?? ( ( ) => flatItemKeys ?? EMPTY_TIMELINE_ITEM_KEYS ) ;
95+
6496 if ( item . type === "event" ) {
6597 return (
6698 < EventItem
@@ -69,7 +101,7 @@ export const TimelineItemComponent = memo(
69101 selected = { selected }
70102 timezone = { timezone }
71103 multiSelected = { multiSelected }
72- flatItemKeys = { flatItemKeys }
104+ getFlatItemKeys = { readFlatItemKeys }
73105 selectedNodeRef = { selectedNodeRef }
74106 itemNodeRef = { itemNodeRef }
75107 isUpcoming = { isUpcoming }
@@ -84,7 +116,7 @@ export const TimelineItemComponent = memo(
84116 selected = { selected }
85117 timezone = { timezone }
86118 multiSelected = { multiSelected }
87- flatItemKeys = { flatItemKeys }
119+ getFlatItemKeys = { readFlatItemKeys }
88120 selectedNodeRef = { selectedNodeRef }
89121 itemNodeRef = { itemNodeRef }
90122 isUpcoming = { isUpcoming }
@@ -94,7 +126,7 @@ export const TimelineItemComponent = memo(
94126 } ,
95127) ;
96128
97- function ItemBase ( {
129+ const ItemBase = memo ( function ItemBase ( {
98130 title,
99131 displayTime,
100132 isLive,
@@ -117,30 +149,7 @@ function ItemBase({
117149 timelineSessionId,
118150 isUpcoming,
119151 upcomingLabel,
120- } : {
121- title : string ;
122- displayTime : string ;
123- isLive ?: boolean ;
124- amplitude ?: number ;
125- showSpinner ?: boolean ;
126- selected : boolean ;
127- ignored ?: boolean ;
128- muted ?: boolean ;
129- multiSelected : boolean ;
130- onClick : ( ) => void ;
131- onDoubleClick ?: ( ) => void ;
132- onCmdClick : ( ) => void ;
133- onShiftClick : ( ) => void ;
134- onStop ?: ( ) => void ;
135- onDragStart ?: ( event : DragEvent < HTMLElement > ) => void ;
136- contextMenu : MenuItemDef [ ] ;
137- draggable ?: boolean ;
138- selectedNodeRef ?: RefCallback < HTMLDivElement > ;
139- itemNodeRef ?: RefCallback < HTMLDivElement > ;
140- timelineSessionId ?: string ;
141- isUpcoming ?: boolean ;
142- upcomingLabel ?: string ;
143- } ) {
152+ } : ItemBaseProps ) {
144153 const { t } = useLingui ( ) ;
145154 const hasSelection = useTimelineSelection ( ( s ) => s . selectedIds . length > 0 ) ;
146155 const showLiveStop = isLive && onStop ;
@@ -271,6 +280,33 @@ function ItemBase({
271280 ) : null }
272281 </ div >
273282 ) ;
283+ } , itemBasePropsAreEqual ) ;
284+
285+ function itemBasePropsAreEqual ( prev : ItemBaseProps , next : ItemBaseProps ) {
286+ return (
287+ prev . title === next . title &&
288+ prev . displayTime === next . displayTime &&
289+ prev . isLive === next . isLive &&
290+ prev . amplitude === next . amplitude &&
291+ prev . showSpinner === next . showSpinner &&
292+ prev . selected === next . selected &&
293+ prev . ignored === next . ignored &&
294+ prev . muted === next . muted &&
295+ prev . multiSelected === next . multiSelected &&
296+ prev . onClick === next . onClick &&
297+ prev . onDoubleClick === next . onDoubleClick &&
298+ prev . onCmdClick === next . onCmdClick &&
299+ prev . onShiftClick === next . onShiftClick &&
300+ prev . onStop === next . onStop &&
301+ prev . onDragStart === next . onDragStart &&
302+ prev . contextMenu === next . contextMenu &&
303+ prev . draggable === next . draggable &&
304+ prev . selectedNodeRef === next . selectedNodeRef &&
305+ prev . itemNodeRef === next . itemNodeRef &&
306+ prev . timelineSessionId === next . timelineSessionId &&
307+ prev . isUpcoming === next . isUpcoming &&
308+ prev . upcomingLabel === next . upcomingLabel
309+ ) ;
274310}
275311
276312const EventItem = memo (
@@ -280,7 +316,7 @@ const EventItem = memo(
280316 selected,
281317 timezone,
282318 multiSelected,
283- flatItemKeys ,
319+ getFlatItemKeys ,
284320 selectedNodeRef,
285321 itemNodeRef,
286322 isUpcoming,
@@ -291,7 +327,7 @@ const EventItem = memo(
291327 selected : boolean ;
292328 timezone ?: string ;
293329 multiSelected : boolean ;
294- flatItemKeys : string [ ] ;
330+ getFlatItemKeys : ( ) => string [ ] ;
295331 selectedNodeRef ?: RefCallback < HTMLDivElement > ;
296332 itemNodeRef ?: RefCallback < HTMLDivElement > ;
297333 isUpcoming ?: boolean ;
@@ -343,8 +379,8 @@ const EventItem = memo(
343379 } , [ itemKey ] ) ;
344380
345381 const handleShiftClick = useCallback ( ( ) => {
346- useTimelineSelection . getState ( ) . selectRange ( flatItemKeys , itemKey ) ;
347- } , [ flatItemKeys , itemKey ] ) ;
382+ useTimelineSelection . getState ( ) . selectRange ( getFlatItemKeys ( ) , itemKey ) ;
383+ } , [ getFlatItemKeys , itemKey ] ) ;
348384
349385 const handleIgnore = useCallback ( ( ) => {
350386 if ( ! trackingIdEvent ) return ;
@@ -439,7 +475,7 @@ const SessionItem = memo(
439475 selected,
440476 timezone,
441477 multiSelected,
442- flatItemKeys ,
478+ getFlatItemKeys ,
443479 selectedNodeRef,
444480 itemNodeRef,
445481 isUpcoming,
@@ -450,7 +486,7 @@ const SessionItem = memo(
450486 selected : boolean ;
451487 timezone ?: string ;
452488 multiSelected : boolean ;
453- flatItemKeys : string [ ] ;
489+ getFlatItemKeys : ( ) => string [ ] ;
454490 selectedNodeRef ?: RefCallback < HTMLDivElement > ;
455491 itemNodeRef ?: RefCallback < HTMLDivElement > ;
456492 isUpcoming ?: boolean ;
@@ -512,8 +548,8 @@ const SessionItem = memo(
512548 } , [ itemKey ] ) ;
513549
514550 const handleShiftClick = useCallback ( ( ) => {
515- useTimelineSelection . getState ( ) . selectRange ( flatItemKeys , itemKey ) ;
516- } , [ flatItemKeys , itemKey ] ) ;
551+ useTimelineSelection . getState ( ) . selectRange ( getFlatItemKeys ( ) , itemKey ) ;
552+ } , [ getFlatItemKeys , itemKey ] ) ;
517553
518554 const handleOpenStandaloneWindow = useCallback ( ( ) => {
519555 void openStandaloneNoteWindow ( sessionId ) ;
0 commit comments