chore: hide timeline bars and stack from ui mode (#21590)

This commit is contained in:
Pavel Feldman 2023-03-10 22:52:31 -08:00 committed by GitHub
parent ea8aa63f1a
commit 428ea66578
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 26 deletions

View file

@ -19,6 +19,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative; position: relative;
min-height: 50px;
} }
.film-strip-lane { .film-strip-lane {

View file

@ -30,7 +30,8 @@ type StackInfo = {
export const SourceTab: React.FunctionComponent<{ export const SourceTab: React.FunctionComponent<{
action: ActionTraceEvent | undefined, action: ActionTraceEvent | undefined,
}> = ({ action }) => { hideStackFrames?: boolean,
}> = ({ action, hideStackFrames }) => {
const [lastAction, setLastAction] = React.useState<ActionTraceEvent | undefined>(); const [lastAction, setLastAction] = React.useState<ActionTraceEvent | undefined>();
const [selectedFrame, setSelectedFrame] = React.useState<number>(0); const [selectedFrame, setSelectedFrame] = React.useState<number>(0);
@ -69,7 +70,7 @@ export const SourceTab: React.FunctionComponent<{
const targetLine = stackInfo.frames[selectedFrame]?.line || 0; const targetLine = stackInfo.frames[selectedFrame]?.line || 0;
const error = action?.error?.message; const error = action?.error?.message;
return <SplitView sidebarSize={200} orientation='horizontal'> return <SplitView sidebarSize={200} orientation='horizontal' sidebarHidden={hideStackFrames}>
<CodeMirrorWrapper text={content} language='javascript' highlight={[{ line: targetLine, type: error ? 'error' : 'running', message: error }]} revealLine={targetLine} readOnly={true} lineNumbers={true}></CodeMirrorWrapper> <CodeMirrorWrapper text={content} language='javascript' highlight={[{ line: targetLine, type: error ? 'error' : 'running', message: error }]} revealLine={targetLine} readOnly={true} lineNumbers={true}></CodeMirrorWrapper>
<StackTraceView action={action} selectedFrame={selectedFrame} setSelectedFrame={setSelectedFrame}></StackTraceView> <StackTraceView action={action} selectedFrame={selectedFrame} setSelectedFrame={setSelectedFrame}></StackTraceView>
</SplitView>; </SplitView>;

View file

@ -41,7 +41,8 @@ export const Timeline: React.FunctionComponent<{
model: MultiTraceModel | undefined, model: MultiTraceModel | undefined,
selectedAction: ActionTraceEvent | undefined, selectedAction: ActionTraceEvent | undefined,
onSelected: (action: ActionTraceEvent) => void, onSelected: (action: ActionTraceEvent) => void,
}> = ({ model, selectedAction, onSelected }) => { hideTimelineBars?: boolean,
}> = ({ model, selectedAction, onSelected, hideTimelineBars }) => {
const [measure, ref] = useMeasure<HTMLDivElement>(); const [measure, ref] = useMeasure<HTMLDivElement>();
const barsRef = React.useRef<HTMLDivElement | null>(null); const barsRef = React.useRef<HTMLDivElement | null>(null);
@ -50,6 +51,10 @@ export const Timeline: React.FunctionComponent<{
const { boundaries, offsets } = React.useMemo(() => { const { boundaries, offsets } = React.useMemo(() => {
const boundaries = { minimum: model?.startTime || 0, maximum: model?.endTime || 30000 }; 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. // Leave some nice free space on the right hand side.
boundaries.maximum += (boundaries.maximum - boundaries.minimum) / 20; boundaries.maximum += (boundaries.maximum - boundaries.minimum) / 20;
return { boundaries, offsets: calculateDividerOffsets(measure.width, boundaries) }; 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); let targetBar: TimelineBar | undefined = bars.find(bar => bar.action === selectedAction);
targetBar = hoveredBar || targetBar; targetBar = hoveredBar || targetBar;
const findHoveredBarIndex = (x: number, y: number) => { const findHoveredBarIndex = (x: number) => {
const time = positionToTime(measure.width, boundaries, x); const time = positionToTime(measure.width, boundaries, x);
const time1 = positionToTime(measure.width, boundaries, x - 5); const time1 = positionToTime(measure.width, boundaries, x - 5);
const time2 = positionToTime(measure.width, boundaries, x + 5); const time2 = positionToTime(measure.width, boundaries, x + 5);
let index: number | undefined; let index: number | undefined;
let yDistance: number | undefined;
let xDistance: number | undefined; let xDistance: number | undefined;
for (let i = 0; i < bars.length; i++) { for (let i = 0; i < bars.length; i++) {
const bar = bars[i]; const bar = bars[i];
const yMiddle = kBarHeight / 2 + barTop(bar);
const left = Math.max(bar.leftTime, time1); const left = Math.max(bar.leftTime, time1);
const right = Math.min(bar.rightTime, time2); const right = Math.min(bar.rightTime, time2);
const xMiddle = (bar.leftTime + bar.rightTime) / 2; const xMiddle = (bar.leftTime + bar.rightTime) / 2;
const xd = Math.abs(time - xMiddle); const xd = Math.abs(time - xMiddle);
const yd = Math.abs(y - yMiddle);
if (left > right) if (left > right)
continue; continue;
// Prefer closest yDistance (the same bar), among those prefer the closest xDistance. // Prefer closest yDistance (the same bar), among those prefer the closest xDistance.
if (index === undefined || if (index === undefined || xd < xDistance!) {
(yd < yDistance!) ||
(Math.abs(yd - yDistance!) < 1e-2 && xd < xDistance!)) {
index = i; index = i;
xDistance = xd; xDistance = xd;
yDistance = yd;
} }
} }
return index; return index;
}; };
const onMouseMove = (event: React.MouseEvent) => { const onMouseMove = (event: React.MouseEvent) => {
if (!ref.current || !barsRef.current) if (!ref.current)
return; return;
const x = event.clientX - ref.current.getBoundingClientRect().left; const x = event.clientX - ref.current.getBoundingClientRect().left;
const y = event.clientY - barsRef.current.getBoundingClientRect().top; const index = findHoveredBarIndex(x);
const index = findHoveredBarIndex(x, y);
setPreviewPoint({ x, clientY: event.clientY }); setPreviewPoint({ x, clientY: event.clientY });
setHoveredBarIndex(index); setHoveredBarIndex(index);
}; };
@ -141,11 +139,10 @@ export const Timeline: React.FunctionComponent<{
const onClick = (event: React.MouseEvent) => { const onClick = (event: React.MouseEvent) => {
setPreviewPoint(undefined); setPreviewPoint(undefined);
if (!ref.current || !barsRef.current) if (!ref.current)
return; return;
const x = event.clientX - ref.current.getBoundingClientRect().left; const x = event.clientX - ref.current.getBoundingClientRect().left;
const y = event.clientY - barsRef.current.getBoundingClientRect().top; const index = findHoveredBarIndex(x);
const index = findHoveredBarIndex(x, y);
if (index === undefined) if (index === undefined)
return; return;
const entry = bars[index].action; const entry = bars[index].action;
@ -162,7 +159,7 @@ export const Timeline: React.FunctionComponent<{
</div>; </div>;
}) })
}</div> }</div>
<div className='timeline-lane timeline-labels'>{ {!hideTimelineBars && <div className='timeline-lane timeline-labels'>{
bars.map((bar, index) => { bars.map((bar, index) => {
return <div key={index} return <div key={index}
className={'timeline-label ' + bar.className + (targetBar === bar ? ' selected' : '')} className={'timeline-label ' + bar.className + (targetBar === bar ? ' selected' : '')}
@ -174,8 +171,8 @@ export const Timeline: React.FunctionComponent<{
{bar.label} {bar.label}
</div>; </div>;
}) })
}</div> }</div>}
<div className='timeline-lane timeline-bars' ref={barsRef}>{ {!hideTimelineBars && <div className='timeline-lane timeline-bars' ref={barsRef}>{
bars.map((bar, index) => { bars.map((bar, index) => {
return <div key={index} return <div key={index}
className={'timeline-bar ' + (bar.action ? 'action ' : '') + (bar.event ? 'event ' : '') + bar.className + (targetBar === bar ? ' selected' : '')} className={'timeline-bar ' + (bar.action ? 'action ' : '') + (bar.event ? 'event ' : '') + bar.className + (targetBar === bar ? ' selected' : '')}
@ -187,7 +184,7 @@ export const Timeline: React.FunctionComponent<{
title={bar.title} title={bar.title}
></div>; ></div>;
}) })
}</div> }</div>}
<FilmStrip model={model} boundaries={boundaries} previewPoint={previewPoint} /> <FilmStrip model={model} boundaries={boundaries} previewPoint={previewPoint} />
<div className='timeline-marker timeline-marker-hover' style={{ <div className='timeline-marker timeline-marker-hover' style={{
display: (previewPoint !== undefined) ? 'block' : 'none', display: (previewPoint !== undefined) ? 'block' : 'none',
@ -239,7 +236,6 @@ function trimRight(s: string, maxLength: number): string {
return s.length <= maxLength ? s : s.substring(0, maxLength - 1) + '\u2026'; return s.length <= maxLength ? s : s.substring(0, maxLength - 1) + '\u2026';
} }
const kBarHeight = 11;
function barTop(bar: TimelineBar): number { function barTop(bar: TimelineBar): number {
return bar.event ? 22 : (bar.action?.method === 'waitForEventInfo' ? 0 : 11); return bar.event ? 22 : (bar.action?.method === 'waitForEventInfo' ? 0 : 11);
} }

View file

@ -346,7 +346,7 @@ export const TraceView: React.FC<{
const xterm = <XtermWrapper source={xtermDataSource}></XtermWrapper>; const xterm = <XtermWrapper source={xtermDataSource}></XtermWrapper>;
return <Workbench model={model} output={xterm} rightToolbar={[ return <Workbench model={model} output={xterm} rightToolbar={[
<ToolbarButton icon='trash' title='Clear output' onClick={() => xtermDataSource.clear()}></ToolbarButton>, <ToolbarButton icon='trash' title='Clear output' onClick={() => xtermDataSource.clear()}></ToolbarButton>,
]}/>; ]} hideTimelineBars={true} hideStackFrames={true} />;
}; };
declare global { declare global {

View file

@ -35,7 +35,9 @@ export const Workbench: React.FunctionComponent<{
model?: MultiTraceModel, model?: MultiTraceModel,
output?: React.ReactElement, output?: React.ReactElement,
rightToolbar?: React.ReactElement[], rightToolbar?: React.ReactElement[],
}> = ({ model, output, rightToolbar }) => { hideTimelineBars?: boolean,
hideStackFrames?: boolean,
}> = ({ model, output, rightToolbar, hideTimelineBars, hideStackFrames }) => {
const [selectedAction, setSelectedAction] = React.useState<ActionTraceEvent | undefined>(undefined); const [selectedAction, setSelectedAction] = React.useState<ActionTraceEvent | undefined>(undefined);
const [highlightedAction, setHighlightedAction] = React.useState<ActionTraceEvent | undefined>(); const [highlightedAction, setHighlightedAction] = React.useState<ActionTraceEvent | undefined>();
const [selectedNavigatorTab, setSelectedNavigatorTab] = React.useState<string>('actions'); const [selectedNavigatorTab, setSelectedNavigatorTab] = React.useState<string>('actions');
@ -49,7 +51,7 @@ export const Workbench: React.FunctionComponent<{
if (failedAction) if (failedAction)
setSelectedAction(failedAction); setSelectedAction(failedAction);
// In the UI mode, selecting the first error should reveal source. // In the UI mode, selecting the first error should reveal source.
if (output) if (failedAction && output)
setSelectedPropertiesTab('source'); setSelectedPropertiesTab('source');
}, [model, output, selectedAction, setSelectedAction, setSelectedPropertiesTab]); }, [model, output, selectedAction, setSelectedAction, setSelectedPropertiesTab]);
@ -60,7 +62,7 @@ export const Workbench: React.FunctionComponent<{
const tabs: TabbedPaneTabModel[] = [ const tabs: TabbedPaneTabModel[] = [
{ id: 'call', title: 'Call', render: () => <CallTab action={activeAction} sdkLanguage={sdkLanguage} /> }, { id: 'call', title: 'Call', render: () => <CallTab action={activeAction} sdkLanguage={sdkLanguage} /> },
{ id: 'source', title: 'Source', count: 0, render: () => <SourceTab action={activeAction} /> }, { id: 'source', title: 'Source', count: 0, render: () => <SourceTab action={activeAction} hideStackFrames={hideStackFrames}/> },
{ id: 'console', title: 'Console', count: consoleCount, render: () => <ConsoleTab action={activeAction} /> }, { id: 'console', title: 'Console', count: consoleCount, render: () => <ConsoleTab action={activeAction} /> },
{ id: 'network', title: 'Network', count: networkCount, render: () => <NetworkTab action={activeAction} /> }, { id: 'network', title: 'Network', count: networkCount, render: () => <NetworkTab action={activeAction} /> },
]; ];
@ -73,6 +75,7 @@ export const Workbench: React.FunctionComponent<{
model={model} model={model}
selectedAction={activeAction} selectedAction={activeAction}
onSelected={action => setSelectedAction(action)} onSelected={action => setSelectedAction(action)}
hideTimelineBars={hideTimelineBars}
/> />
<SplitView sidebarSize={output ? 250 : 350} orientation={output ? 'vertical' : 'horizontal'}> <SplitView sidebarSize={output ? 250 : 350} orientation={output ? 'vertical' : 'horizontal'}>
<SplitView sidebarSize={250} orientation='horizontal' sidebarIsFirst={true}> <SplitView sidebarSize={250} orientation='horizontal' sidebarIsFirst={true}>