feat(trace): allow scrolling the filmstrip (#24015)
Fixes https://github.com/microsoft/playwright/issues/23963
This commit is contained in:
parent
6e78dcb7dc
commit
6343ea2795
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue