77 * @flow
88 */
99
10- import type {
11- Point ,
12- HorizontalPanAndZoomViewOnChangeCallback ,
13- } from './view-base' ;
10+ import type { Point } from './view-base' ;
1411import type {
1512 ReactHoverContextInfo ,
1613 ReactProfilerData ,
1714 ReactMeasure ,
15+ ViewState ,
1816} from './types' ;
1917
2018import * as React from 'react' ;
2119import {
2220 Fragment ,
21+ useContext ,
2322 useEffect ,
2423 useLayoutEffect ,
2524 useRef ,
@@ -54,29 +53,37 @@ import {
5453 UserTimingMarksView ,
5554} from './content-views' ;
5655import { COLORS } from './content-views/constants' ;
57-
56+ import { clampState , moveStateToRange } from './view-base/utils/scrollState' ;
5857import EventTooltip from './EventTooltip' ;
58+ import { RegistryContext } from 'react-devtools-shared/src/devtools/ContextMenu/Contexts' ;
5959import ContextMenu from 'react-devtools-shared/src/devtools/ContextMenu/ContextMenu' ;
6060import ContextMenuItem from 'react-devtools-shared/src/devtools/ContextMenu/ContextMenuItem' ;
6161import useContextMenu from 'react-devtools-shared/src/devtools/ContextMenu/useContextMenu' ;
6262import { getBatchRange } from './utils/getBatchRange' ;
63+ import { MAX_ZOOM_LEVEL , MIN_ZOOM_LEVEL } from './view-base/constants' ;
6364
6465import styles from './CanvasPage.css' ;
6566
6667const CONTEXT_MENU_ID = 'canvas' ;
6768
6869type Props = { |
6970 profilerData : ReactProfilerData ,
71+ viewState : ViewState ,
7072| } ;
7173
72- function CanvasPage ( { profilerData} : Props ) {
74+ function CanvasPage ( { profilerData, viewState } : Props ) {
7375 return (
7476 < div
7577 className = { styles . CanvasPage }
7678 style = { { backgroundColor : COLORS . BACKGROUND } } >
7779 < AutoSizer >
7880 { ( { height, width} : { height : number , width : number } ) => (
79- < AutoSizedCanvas data = { profilerData } height = { height } width = { width } />
81+ < AutoSizedCanvas
82+ data = { profilerData }
83+ height = { height }
84+ viewState = { viewState }
85+ width = { width }
86+ />
8087 ) }
8188 </ AutoSizer >
8289 </ div >
@@ -98,27 +105,43 @@ const copySummary = (data: ReactProfilerData, measure: ReactMeasure) => {
98105 ) ;
99106} ;
100107
101- // TODO (scheduling profiler) Why is the "zoom" feature so much slower than normal rendering?
102108const zoomToBatch = (
103109 data : ReactProfilerData ,
104110 measure : ReactMeasure ,
105- syncedHorizontalPanAndZoomViews : HorizontalPanAndZoomView [ ] ,
111+ viewState : ViewState ,
112+ width : number ,
106113) => {
107114 const { batchUID} = measure ;
108- const [ startTime , stopTime ] = getBatchRange ( batchUID , data ) ;
109- syncedHorizontalPanAndZoomViews . forEach ( syncedView =>
110- // Using time as range works because the views' intrinsic content size is based on time.
111- syncedView . zoomToRange ( startTime , stopTime ) ,
112- ) ;
115+ const [ rangeStart , rangeEnd ] = getBatchRange ( batchUID , data ) ;
116+
117+ // Convert from time range to ScrollState
118+ const scrollState = moveStateToRange ( {
119+ state : viewState . horizontalScrollState ,
120+ rangeStart,
121+ rangeEnd,
122+ contentLength : data . duration ,
123+
124+ minContentLength : data . duration * MIN_ZOOM_LEVEL ,
125+ maxContentLength : data . duration * MAX_ZOOM_LEVEL ,
126+ containerLength : width ,
127+ } ) ;
128+
129+ viewState . updateHorizontalScrollState ( scrollState ) ;
113130} ;
114131
115132type AutoSizedCanvasProps = { |
116133 data : ReactProfilerData ,
117134 height : number ,
135+ viewState : ViewState ,
118136 width : number ,
119137| } ;
120138
121- function AutoSizedCanvas ( { data, height, width} : AutoSizedCanvasProps ) {
139+ function AutoSizedCanvas ( {
140+ data,
141+ height,
142+ viewState,
143+ width,
144+ } : AutoSizedCanvasProps ) {
122145 const canvasRef = useRef < HTMLCanvasElement | null > ( null ) ;
123146
124147 const [ isContextMenuShown , setIsContextMenuShown ] = useState < boolean > ( false ) ;
@@ -136,30 +159,31 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
136159 const componentMeasuresViewRef = useRef ( null ) ;
137160 const reactMeasuresViewRef = useRef ( null ) ;
138161 const flamechartViewRef = useRef ( null ) ;
139- const syncedHorizontalPanAndZoomViewsRef = useRef < HorizontalPanAndZoomView [ ] > (
140- [ ] ,
141- ) ;
162+
163+ const { hideMenu : hideContextMenu } = useContext ( RegistryContext ) ;
142164
143165 useLayoutEffect ( ( ) => {
144166 const surface = surfaceRef . current ;
145167 const defaultFrame = { origin : zeroPoint , size : { width, height} } ;
146168
147- // Clear synced views
148- syncedHorizontalPanAndZoomViewsRef . current = [ ] ;
169+ // Auto hide context menu when panning.
170+ viewState . onHorizontalScrollStateChange ( scrollState => {
171+ hideContextMenu ( ) ;
172+ } ) ;
149173
150- const syncAllHorizontalPanAndZoomViewStates : HorizontalPanAndZoomViewOnChangeCallback = (
151- newState ,
152- triggeringView ? : HorizontalPanAndZoomView ,
153- ) => {
154- syncedHorizontalPanAndZoomViewsRef . current . forEach (
155- syncedView =>
156- triggeringView !== syncedView && syncedView . setScrollState ( newState ) ,
157- ) ;
158- } ;
174+ // Initialize horizontal view state
175+ viewState . updateHorizontalScrollState (
176+ clampState ( {
177+ state : viewState . horizontalScrollState ,
178+ minContentLength : data . duration * MIN_ZOOM_LEVEL ,
179+ maxContentLength : data . duration * MAX_ZOOM_LEVEL ,
180+ containerLength : defaultFrame . size . width ,
181+ } ) ,
182+ ) ;
159183
160184 function createViewHelper (
161185 view : View ,
162- resizeLabel : string = '' ,
186+ label : string ,
163187 shouldScrollVertically : boolean = false ,
164188 shouldResizeVertically : boolean = false ,
165189 ) : View {
@@ -169,6 +193,8 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
169193 surface ,
170194 defaultFrame ,
171195 view ,
196+ viewState ,
197+ label ,
172198 ) ;
173199 }
174200
@@ -177,31 +203,30 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
177203 defaultFrame ,
178204 verticalScrollView !== null ? verticalScrollView : view ,
179205 data . duration ,
180- syncAllHorizontalPanAndZoomViewStates ,
206+ viewState ,
181207 ) ;
182208
183- syncedHorizontalPanAndZoomViewsRef . current . push ( horizontalPanAndZoomView ) ;
184-
185- let viewToReturn = horizontalPanAndZoomView ;
209+ let resizableView = null ;
186210 if ( shouldResizeVertically ) {
187- viewToReturn = new ResizableView (
211+ resizableView = new ResizableView (
188212 surface ,
189213 defaultFrame ,
190214 horizontalPanAndZoomView ,
215+ viewState ,
191216 canvasRef ,
192- resizeLabel ,
217+ label ,
193218 ) ;
194219 }
195220
196- return viewToReturn ;
221+ return resizableView || horizontalPanAndZoomView ;
197222 }
198223
199224 const axisMarkersView = new TimeAxisMarkersView (
200225 surface ,
201226 defaultFrame ,
202227 data . duration ,
203228 ) ;
204- const axisMarkersViewWrapper = createViewHelper ( axisMarkersView ) ;
229+ const axisMarkersViewWrapper = createViewHelper ( axisMarkersView , 'time' ) ;
205230
206231 let userTimingMarksViewWrapper = null ;
207232 if ( data . otherUserTimingMarks . length > 0 ) {
@@ -212,7 +237,10 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
212237 data . duration ,
213238 ) ;
214239 userTimingMarksViewRef . current = userTimingMarksView ;
215- userTimingMarksViewWrapper = createViewHelper ( userTimingMarksView ) ;
240+ userTimingMarksViewWrapper = createViewHelper (
241+ userTimingMarksView ,
242+ 'user timing api' ,
243+ ) ;
216244 }
217245
218246 const nativeEventsView = new NativeEventsView ( surface , defaultFrame , data ) ;
@@ -230,7 +258,10 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
230258 data ,
231259 ) ;
232260 schedulingEventsViewRef . current = schedulingEventsView ;
233- const schedulingEventsViewWrapper = createViewHelper ( schedulingEventsView ) ;
261+ const schedulingEventsViewWrapper = createViewHelper (
262+ schedulingEventsView ,
263+ 'react updates' ,
264+ ) ;
234265
235266 let suspenseEventsViewWrapper = null ;
236267 if ( data . suspenseEvents . length > 0 ) {
@@ -256,7 +287,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
256287 reactMeasuresViewRef . current = reactMeasuresView ;
257288 const reactMeasuresViewWrapper = createViewHelper (
258289 reactMeasuresView ,
259- 'react' ,
290+ 'react scheduling ' ,
260291 true ,
261292 true ,
262293 ) ;
@@ -269,7 +300,10 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
269300 data ,
270301 ) ;
271302 componentMeasuresViewRef . current = componentMeasuresView ;
272- componentMeasuresViewWrapper = createViewHelper ( componentMeasuresView ) ;
303+ componentMeasuresViewWrapper = createViewHelper (
304+ componentMeasuresView ,
305+ 'react components' ,
306+ ) ;
273307 }
274308
275309 const flamechartView = new FlamechartView (
@@ -329,7 +363,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
329363 return ;
330364 }
331365
332- // Wheel events should always hide the current toolltip .
366+ // Wheel events should always hide the current tooltip .
333367 switch ( interaction . type ) {
334368 case 'wheel-control' :
335369 case 'wheel-meta' :
@@ -617,11 +651,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
617651 { measure !== null && (
618652 < ContextMenuItem
619653 onClick = { ( ) =>
620- zoomToBatch (
621- contextData . data ,
622- measure ,
623- syncedHorizontalPanAndZoomViewsRef . current ,
624- )
654+ zoomToBatch ( contextData . data , measure , viewState , width )
625655 }
626656 title = "Zoom to batch" >
627657 Zoom to batch
0 commit comments