diff --git a/packages/trace-viewer/src/ui/filmStrip.css b/packages/trace-viewer/src/ui/filmStrip.css index 9570de199e..d9639b12bc 100644 --- a/packages/trace-viewer/src/ui/filmStrip.css +++ b/packages/trace-viewer/src/ui/filmStrip.css @@ -19,6 +19,7 @@ display: flex; flex-direction: column; position: relative; + min-height: 50px; } .film-strip-lane { diff --git a/packages/trace-viewer/src/ui/sourceTab.tsx b/packages/trace-viewer/src/ui/sourceTab.tsx index 248dd2ebef..6ed5431c28 100644 --- a/packages/trace-viewer/src/ui/sourceTab.tsx +++ b/packages/trace-viewer/src/ui/sourceTab.tsx @@ -30,7 +30,8 @@ type StackInfo = { export const SourceTab: React.FunctionComponent<{ action: ActionTraceEvent | undefined, -}> = ({ action }) => { + hideStackFrames?: boolean, +}> = ({ action, hideStackFrames }) => { const [lastAction, setLastAction] = React.useState(); const [selectedFrame, setSelectedFrame] = React.useState(0); @@ -69,7 +70,7 @@ export const SourceTab: React.FunctionComponent<{ const targetLine = stackInfo.frames[selectedFrame]?.line || 0; const error = action?.error?.message; - return + return ; diff --git a/packages/trace-viewer/src/ui/timeline.tsx b/packages/trace-viewer/src/ui/timeline.tsx index 48901bb396..4c6eb2f099 100644 --- a/packages/trace-viewer/src/ui/timeline.tsx +++ b/packages/trace-viewer/src/ui/timeline.tsx @@ -41,7 +41,8 @@ export const Timeline: React.FunctionComponent<{ model: MultiTraceModel | undefined, selectedAction: ActionTraceEvent | undefined, onSelected: (action: ActionTraceEvent) => void, -}> = ({ model, selectedAction, onSelected }) => { + hideTimelineBars?: boolean, +}> = ({ model, selectedAction, onSelected, hideTimelineBars }) => { const [measure, ref] = useMeasure(); const barsRef = React.useRef(null); @@ -50,6 +51,10 @@ export const Timeline: React.FunctionComponent<{ const { boundaries, offsets } = React.useMemo(() => { const boundaries = { minimum: model?.startTime || 0, maximum: model?.endTime || 30000 }; + if (boundaries.minimum > boundaries.maximum) { + boundaries.minimum = 0; + boundaries.maximum = 30000; + } // Leave some nice free space on the right hand side. boundaries.maximum += (boundaries.maximum - boundaries.minimum) / 20; return { boundaries, offsets: calculateDividerOffsets(measure.width, boundaries) }; @@ -95,41 +100,34 @@ export const Timeline: React.FunctionComponent<{ let targetBar: TimelineBar | undefined = bars.find(bar => bar.action === selectedAction); targetBar = hoveredBar || targetBar; - const findHoveredBarIndex = (x: number, y: number) => { + const findHoveredBarIndex = (x: number) => { const time = positionToTime(measure.width, boundaries, x); const time1 = positionToTime(measure.width, boundaries, x - 5); const time2 = positionToTime(measure.width, boundaries, x + 5); let index: number | undefined; - let yDistance: number | undefined; let xDistance: number | undefined; for (let i = 0; i < bars.length; i++) { const bar = bars[i]; - const yMiddle = kBarHeight / 2 + barTop(bar); const left = Math.max(bar.leftTime, time1); const right = Math.min(bar.rightTime, time2); const xMiddle = (bar.leftTime + bar.rightTime) / 2; const xd = Math.abs(time - xMiddle); - const yd = Math.abs(y - yMiddle); if (left > right) continue; // Prefer closest yDistance (the same bar), among those prefer the closest xDistance. - if (index === undefined || - (yd < yDistance!) || - (Math.abs(yd - yDistance!) < 1e-2 && xd < xDistance!)) { + if (index === undefined || xd < xDistance!) { index = i; xDistance = xd; - yDistance = yd; } } return index; }; const onMouseMove = (event: React.MouseEvent) => { - if (!ref.current || !barsRef.current) + if (!ref.current) return; const x = event.clientX - ref.current.getBoundingClientRect().left; - const y = event.clientY - barsRef.current.getBoundingClientRect().top; - const index = findHoveredBarIndex(x, y); + const index = findHoveredBarIndex(x); setPreviewPoint({ x, clientY: event.clientY }); setHoveredBarIndex(index); }; @@ -141,11 +139,10 @@ export const Timeline: React.FunctionComponent<{ const onClick = (event: React.MouseEvent) => { setPreviewPoint(undefined); - if (!ref.current || !barsRef.current) + if (!ref.current) return; const x = event.clientX - ref.current.getBoundingClientRect().left; - const y = event.clientY - barsRef.current.getBoundingClientRect().top; - const index = findHoveredBarIndex(x, y); + const index = findHoveredBarIndex(x); if (index === undefined) return; const entry = bars[index].action; @@ -162,7 +159,7 @@ export const Timeline: React.FunctionComponent<{ ; }) } -
{ + {!hideTimelineBars &&
{ bars.map((bar, index) => { return
; }) - }
-
{ + }
} + {!hideTimelineBars &&
{ bars.map((bar, index) => { return
; }) - }
+ }
}
; return xtermDataSource.clear()}>, - ]}/>; + ]} hideTimelineBars={true} hideStackFrames={true} />; }; declare global { diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index 6be206122d..2f50123aa9 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -35,7 +35,9 @@ export const Workbench: React.FunctionComponent<{ model?: MultiTraceModel, output?: React.ReactElement, rightToolbar?: React.ReactElement[], -}> = ({ model, output, rightToolbar }) => { + hideTimelineBars?: boolean, + hideStackFrames?: boolean, +}> = ({ model, output, rightToolbar, hideTimelineBars, hideStackFrames }) => { const [selectedAction, setSelectedAction] = React.useState(undefined); const [highlightedAction, setHighlightedAction] = React.useState(); const [selectedNavigatorTab, setSelectedNavigatorTab] = React.useState('actions'); @@ -49,7 +51,7 @@ export const Workbench: React.FunctionComponent<{ if (failedAction) setSelectedAction(failedAction); // In the UI mode, selecting the first error should reveal source. - if (output) + if (failedAction && output) setSelectedPropertiesTab('source'); }, [model, output, selectedAction, setSelectedAction, setSelectedPropertiesTab]); @@ -60,7 +62,7 @@ export const Workbench: React.FunctionComponent<{ const tabs: TabbedPaneTabModel[] = [ { id: 'call', title: 'Call', render: () => }, - { id: 'source', title: 'Source', count: 0, render: () => }, + { id: 'source', title: 'Source', count: 0, render: () => }, { id: 'console', title: 'Console', count: consoleCount, render: () => }, { id: 'network', title: 'Network', count: networkCount, render: () => }, ]; @@ -73,6 +75,7 @@ export const Workbench: React.FunctionComponent<{ model={model} selectedAction={activeAction} onSelected={action => setSelectedAction(action)} + hideTimelineBars={hideTimelineBars} />