feat(trace): allow scrolling the filmstrip (#24015)

Fixes https://github.com/microsoft/playwright/issues/23963
This commit is contained in:
Pavel Feldman 2023-07-03 13:03:33 -07:00 committed by GitHub
parent 6e78dcb7dc
commit 6343ea2795
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 23 deletions

View file

@ -19,7 +19,16 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative; position: relative;
}
.film-strip-lanes {
flex: none;
display: flex;
flex-direction: column;
position: relative;
min-height: 50px; min-height: 50px;
max-height: 200px;
overflow: auto;
} }
.film-strip-lane { .film-strip-lane {

View file

@ -22,6 +22,8 @@ import type { PageEntry } from '../entries';
import type { MultiTraceModel } from './modelUtil'; import type { MultiTraceModel } from './modelUtil';
const tileSize = { width: 200, height: 45 }; const tileSize = { width: 200, height: 45 };
const frameMargin = 2.5;
const rowHeight = tileSize.height + frameMargin * 2;
export const FilmStrip: React.FunctionComponent<{ export const FilmStrip: React.FunctionComponent<{
model?: MultiTraceModel, model?: MultiTraceModel,
@ -29,11 +31,12 @@ export const FilmStrip: React.FunctionComponent<{
previewPoint?: { x: number, clientY: number }, previewPoint?: { x: number, clientY: number },
}> = ({ model, boundaries, previewPoint }) => { }> = ({ model, boundaries, previewPoint }) => {
const [measure, ref] = useMeasure<HTMLDivElement>(); const [measure, ref] = useMeasure<HTMLDivElement>();
const lanesRef = React.useRef<HTMLDivElement>(null);
let pageIndex = 0; let pageIndex = 0;
if (ref.current && previewPoint) { if (lanesRef.current && previewPoint) {
const bounds = ref.current.getBoundingClientRect(); const bounds = lanesRef.current.getBoundingClientRect();
pageIndex = ((previewPoint.clientY - bounds.top) / tileSize.height) | 0; pageIndex = ((previewPoint.clientY - bounds.top + lanesRef.current.scrollTop) / rowHeight) | 0;
} }
const screencastFrames = model?.pages?.[pageIndex]?.screencastFrames; const screencastFrames = model?.pages?.[pageIndex]?.screencastFrames;
@ -42,28 +45,28 @@ export const FilmStrip: React.FunctionComponent<{
if (previewPoint !== undefined && screencastFrames) { if (previewPoint !== undefined && screencastFrames) {
const previewTime = boundaries.minimum + (boundaries.maximum - boundaries.minimum) * previewPoint.x / measure.width; const previewTime = boundaries.minimum + (boundaries.maximum - boundaries.minimum) * previewPoint.x / measure.width;
previewImage = screencastFrames[upperBound(screencastFrames, previewTime, timeComparator) - 1]; previewImage = screencastFrames[upperBound(screencastFrames, previewTime, timeComparator) - 1];
previewSize = previewImage ? inscribe({ width: previewImage.width, height: previewImage.height }, { width: (window.innerWidth * 3 / 4) | 0, height: (window.innerHeight * 3 / 4) | 0 }) : undefined; previewSize = previewImage ? inscribe({ width: previewImage.width, height: previewImage.height }, { width: (window.innerWidth * 3 / 4) | 0, height: (window.innerHeight * 3 / 4) | 0 }) : undefined;
} }
return <div className='film-strip' ref={ref}>{ return <div className='film-strip' ref={ref}>
model?.pages.filter(p => p.screencastFrames.length).map((page, index) => <FilmStripLane <div className='film-strip-lanes' ref={lanesRef}>{
boundaries={boundaries} model?.pages.map((page, index) => <FilmStripLane
page={page} boundaries={boundaries}
width={measure.width} page={page}
key={index} width={measure.width}
/>) key={index}
} />)
{previewImage && previewSize && previewPoint?.x !== undefined && }</div>
<div className='film-strip-hover' style={{ {previewImage && previewSize && previewPoint?.x !== undefined &&
width: previewSize.width, <div className='film-strip-hover' style={{
height: previewSize.height, width: previewSize.width,
top: measure.bottom + 5, height: previewSize.height,
left: Math.min(previewPoint!.x, measure.width - previewSize.width - 10), top: measure.bottom + 5,
}}> left: Math.min(previewPoint!.x, measure.width - previewSize.width - 10),
<img src={`sha1/${previewImage.sha1}`} width={previewSize.width} height={previewSize.height} /> }}>
</div> <img src={`sha1/${previewImage.sha1}`} width={previewSize.width} height={previewSize.height} />
} </div>
}
</div>; </div>;
}; };
@ -79,7 +82,6 @@ const FilmStripLane: React.FunctionComponent<{
viewportSize.height = Math.max(viewportSize.height, frame.height); viewportSize.height = Math.max(viewportSize.height, frame.height);
} }
const frameSize = inscribe(viewportSize!, tileSize); const frameSize = inscribe(viewportSize!, tileSize);
const frameMargin = 2.5;
const startTime = screencastFrames[0].timestamp; const startTime = screencastFrames[0].timestamp;
const endTime = screencastFrames[screencastFrames.length - 1].timestamp; const endTime = screencastFrames[screencastFrames.length - 1].timestamp;