1
- import { Box , RangeSlider , RangeSliderValue } from "@mantine/core" ;
2
- import { ArrowFatLinesRight , Pause , Play } from "@phosphor-icons/react" ;
1
+ import { Box , Button , RangeSlider , RangeSliderValue } from "@mantine/core" ;
2
+ import { ArrowFatLinesRight , CaretDoubleRight , Pause , Play } from "@phosphor-icons/react" ;
3
3
import { useCallback , useEffect , useMemo , useRef , useState } from "react" ;
4
4
import { useDataMethods } from "../data-processing/DataMethodsProvider" ;
5
5
import DataSourceType from "@/models/DataSourceType" ;
6
6
import useDebounceCallbackGreedy from "../utils/useGreedyDebounce" ;
7
+ import { timeColumnName } from "../data-processing/datatypes" ;
7
8
8
9
export default function TimelineBar ( ) {
9
10
const [ paused , setPaused ] = useState ( true ) ;
11
+ const { switchToRecording } = useDataMethods ( ) ;
10
12
11
13
return (
12
14
< >
@@ -23,61 +25,73 @@ export default function TimelineBar() {
23
25
< MainSlider />
24
26
</ div >
25
27
< SyncButton />
28
+ < Button
29
+ onClick = { ( ) =>
30
+ switchToRecording ( "fs-data/FS-2/2025-03-06-BrakingTests1.parquet" )
31
+ }
32
+ />
26
33
</ div >
27
34
</ >
28
35
) ;
29
36
}
30
37
31
38
function SyncButton ( ) {
32
- const [ isTimelineSynced , setIsTimelineSynced ] = useState ( false ) ;
33
- const { subscribeIsTimelineSynced } = useDataMethods ( ) ;
39
+ const [ enabled , setEnabled ] = useState ( false ) ;
40
+ const [ visible , setVisible ] = useState ( false ) ;
41
+ const { subscribeIsTimelineSynced, setIsTimelineSynced, subscribeDataSource } =
42
+ useDataMethods ( ) ;
34
43
useEffect ( ( ) => {
35
- return subscribeIsTimelineSynced ( ( isTimelineSynced : boolean ) => {
36
- setIsTimelineSynced ( isTimelineSynced ) ;
44
+ const unsub1 = subscribeIsTimelineSynced ( ( isTimelineSynced : boolean ) => {
45
+ setEnabled ( isTimelineSynced ) ;
37
46
} ) ;
47
+ const unsub2 = subscribeDataSource ( ( dataSourceType ) => {
48
+ setVisible ( dataSourceType == DataSourceType . LIVE ) ;
49
+ } ) ;
50
+ return ( ) => {
51
+ unsub1 ( ) ;
52
+ unsub2 ( ) ;
53
+ }
54
+ } , [ ] ) ;
55
+ const setTimelineSynced = useCallback ( ( ) => {
56
+ setEnabled ( true ) ;
57
+ setIsTimelineSynced ( true , "timelineBar" ) ;
38
58
} , [ ] ) ;
39
- const toggleIsTimelineSynced = useCallback ( ( ) => setIsTimelineSynced ( ! isTimelineSynced ) , [ ] ) ;
40
59
41
- return (
42
- < Box c = { isTimelineSynced ? "neutral.8" : "neutral.5" } >
43
- < ArrowFatLinesRight color = "currentColor" weight = "fill" onClick = { toggleIsTimelineSynced } />
60
+ return visible ? (
61
+ < Box c = { enabled ? "neutral.9" : "neutral.4" } >
62
+ < CaretDoubleRight
63
+ color = "currentColor"
64
+ weight = "fill"
65
+ size = { 24 }
66
+ onClick = { enabled ? undefined : setTimelineSynced }
67
+ />
44
68
</ Box >
45
- ) ;
69
+ ) : null ;
46
70
}
47
71
48
72
function MainSlider ( ) {
49
73
const [ disabled , setDisabled ] = useState < boolean > ( false ) ;
50
- const [ minMax , setMinMax ] = useState < RangeSliderValue > ( [ 0 , 10 ] ) ; // timestamp (seconds)
74
+ const [ minMax , setMinMax ] = useState < RangeSliderValue > ( [ 0 , 10 ] ) ;
51
75
const [ value , setValue ] = useState < RangeSliderValue > ( [ 0 , 10 ] ) ;
52
76
const debouncedSetValue = useDebounceCallbackGreedy ( ( value ) => setValue ( value ) , 10 ) ;
53
77
const ref = useRef < HTMLDivElement > ( null ) ;
54
- // id is only used to differentiate between who set viewEdges (avoid infinite recursion)
78
+ // id is only used to differentiate between who set viewInterval (avoid infinite recursion)
55
79
const id = "timelineBar" ;
56
80
81
+ useEffect ( ( ) => console . log ( "value:" , value ) , [ value ] ) ;
82
+
57
83
const {
58
84
setViewInterval,
59
85
subscribeDataSource,
60
86
subscribeNumRows,
61
87
subscribeViewInterval,
62
88
subscribeDataInterval,
63
89
viewIntervalRef,
90
+ dataArraysRef,
64
91
// setCursorPosition, // eventually?
65
92
} = useDataMethods ( ) ;
66
93
67
- // useEffect(() => {
68
- // console.log("Updated minMax:", minMax);
69
- // }, [minMax]); // Runs whenever minMax updates
70
-
71
94
useEffect ( ( ) => {
72
- // const unsub1 = subscribeFullArrays((fullArrays) => {
73
- // const timeCol = fullArrays[timeColumnName];
74
- // // Need at least one point to set min/max!
75
- // if (timeCol && timeCol.length > 0) {
76
- // // Give 0.5s padding on either side
77
- // setMinMax([timeCol[0] - 0.5, timeCol[timeCol.length - 1] + 0.5]);
78
- // // console.log([timeCol[0] - 0.5, timeCol[timeCol.length - 1] + 0.5]);
79
- // }
80
- // });
81
95
const unsub1 = subscribeDataInterval ( ( [ left , right ] ) => {
82
96
setMinMax ( [ left , right ] ) ;
83
97
} ) ;
@@ -105,12 +119,22 @@ function MainSlider() {
105
119
106
120
const onChange = useCallback ( ( range : RangeSliderValue ) => {
107
121
if ( range [ 1 ] == viewIntervalRef . current [ 1 ] ) {
108
- console . log ( "range[1] ==" , range [ 1 ] , "== value[1] ==" , viewIntervalRef . current [ 1 ] ) ;
122
+ // console.log("range[1] ==", range[1], "== value[1] ==", viewIntervalRef.current[1]);
109
123
} else {
110
- console . log ( "range[1] ==" , range [ 1 ] , "=/= value[1] ==" , viewIntervalRef . current [ 1 ] ) ;
124
+ // console.log(
125
+ // "range[1] ==",
126
+ // range[1],
127
+ // "=/= value[1] ==",
128
+ // viewIntervalRef.current[1],
129
+ // );
111
130
}
112
131
setValue ( range ) ;
113
- setViewInterval ( range , id ) ;
132
+ // setViewInterval(range, id);
133
+
134
+ const val = dataArraysRef . current [ timeColumnName ] ! [ range [ 0 ] ] ;
135
+ console . log ( "idx:" , range [ 0 ] , val , dataArraysRef . current [ ":Time" ] ) ;
136
+ console . log ( "timeline setting range:" , range ) ;
137
+
114
138
} , [ ] ) ;
115
139
116
140
const sliderStyles = useMemo (
@@ -122,20 +146,29 @@ function MainSlider() {
122
146
[ ] ,
123
147
) ;
124
148
149
+ const formatLabel = ( idx : number ) => {
150
+ const val = dataArraysRef . current [ timeColumnName ] ! [ idx ] ;
151
+
152
+ // console.log("idx:", idx, val, dataArraysRef.current[":Time"]);
153
+ return val !== undefined ? val . toFixed ( 2 ) : "???" ;
154
+
155
+ } ;
156
+
125
157
return (
126
158
< >
127
159
< RangeSlider
128
160
ref = { ref }
129
- step = { 0.01 } // 100Hz == 0.01s per point
161
+ step = { 1 } // timeline _only_ refers to indexes into data arrays, so must be integers only
130
162
disabled = { disabled }
131
163
onChange = { onChange }
132
164
// it's right around the corner I can feel it...
133
- min = { 55000 } // min={ minMax[0]}
134
- max = { 58000 } // max={ minMax[1]}
135
- minRange = { 10 }
136
- // maxRange ??
165
+ min = { minMax [ 0 ] }
166
+ max = { minMax [ 1 ] }
167
+ minRange = { 1 }
168
+ maxRange = { minMax [ 1 ] - minMax [ 0 ] }
137
169
value = { value }
138
170
styles = { sliderStyles }
171
+ label = { formatLabel }
139
172
/>
140
173
{ /* <DraggableRangeSlider */ }
141
174
{ /* value={sliderRange} */ }
0 commit comments