mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: show preview for page under cursor (#6548)
This commit is contained in:
parent
cc43b0d23f
commit
a7ea00d02e
@ -21,18 +21,26 @@ import { useMeasure } from './helpers';
|
|||||||
import { upperBound } from '../../uiUtils';
|
import { upperBound } from '../../uiUtils';
|
||||||
import { ContextEntry, PageEntry } from '../../../server/trace/viewer/traceModel';
|
import { ContextEntry, PageEntry } from '../../../server/trace/viewer/traceModel';
|
||||||
|
|
||||||
|
const tileSize = { width: 200, height: 45 };
|
||||||
|
|
||||||
export const FilmStrip: React.FunctionComponent<{
|
export const FilmStrip: React.FunctionComponent<{
|
||||||
context: ContextEntry,
|
context: ContextEntry,
|
||||||
boundaries: Boundaries,
|
boundaries: Boundaries,
|
||||||
previewX?: number,
|
previewPoint?: { x: number, clientY: number },
|
||||||
}> = ({ context, boundaries, previewX }) => {
|
}> = ({ context, boundaries, previewPoint }) => {
|
||||||
const [measure, ref] = useMeasure<HTMLDivElement>();
|
const [measure, ref] = useMeasure<HTMLDivElement>();
|
||||||
|
|
||||||
const screencastFrames = context.pages[0]?.screencastFrames;
|
let pageIndex = 0;
|
||||||
|
if (ref.current && previewPoint) {
|
||||||
|
const bounds = ref.current.getBoundingClientRect();
|
||||||
|
pageIndex = ((previewPoint.clientY - bounds.top) / tileSize.height) | 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const screencastFrames = context.pages[pageIndex]?.screencastFrames;
|
||||||
// TODO: pick file from the Y position.
|
// TODO: pick file from the Y position.
|
||||||
let previewImage = undefined;
|
let previewImage = undefined;
|
||||||
if (previewX !== undefined && context.pages.length) {
|
if (previewPoint !== undefined && screencastFrames) {
|
||||||
const previewTime = boundaries.minimum + (boundaries.maximum - boundaries.minimum) * previewX / 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];
|
||||||
}
|
}
|
||||||
const previewSize = inscribe(context.created.viewportSize!, { width: 600, height: 600 });
|
const previewSize = inscribe(context.created.viewportSize!, { width: 600, height: 600 });
|
||||||
@ -45,12 +53,12 @@ export const FilmStrip: React.FunctionComponent<{
|
|||||||
key={index}
|
key={index}
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
{previewImage && previewX !== undefined &&
|
{previewImage && previewPoint?.x !== undefined &&
|
||||||
<div className='film-strip-hover' style={{
|
<div className='film-strip-hover' style={{
|
||||||
width: previewSize.width,
|
width: previewSize.width,
|
||||||
height: previewSize.height,
|
height: previewSize.height,
|
||||||
top: measure.bottom + 5,
|
top: measure.bottom + 5,
|
||||||
left: Math.min(previewX, measure.width - previewSize.width - 10),
|
left: Math.min(previewPoint!.x, measure.width - previewSize.width - 10),
|
||||||
}}>
|
}}>
|
||||||
<img src={`/sha1/${previewImage.sha1}`} width={previewSize.width} height={previewSize.height} />
|
<img src={`/sha1/${previewImage.sha1}`} width={previewSize.width} height={previewSize.height} />
|
||||||
</div>
|
</div>
|
||||||
@ -69,7 +77,7 @@ const FilmStripLane: React.FunctionComponent<{
|
|||||||
viewportSize.width = Math.max(viewportSize.width, frame.width);
|
viewportSize.width = Math.max(viewportSize.width, frame.width);
|
||||||
viewportSize.height = Math.max(viewportSize.height, frame.height);
|
viewportSize.height = Math.max(viewportSize.height, frame.height);
|
||||||
}
|
}
|
||||||
const frameSize = inscribe(viewportSize!, { width: 200, height: 45 });
|
const frameSize = inscribe(viewportSize!, tileSize);
|
||||||
const frameMargin = 2.5;
|
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;
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export const Timeline: React.FunctionComponent<{
|
|||||||
onHighlighted: (action: ActionEntry | undefined) => void,
|
onHighlighted: (action: ActionEntry | undefined) => void,
|
||||||
}> = ({ context, boundaries, selectedAction, highlightedAction, onSelected, onHighlighted }) => {
|
}> = ({ context, boundaries, selectedAction, highlightedAction, onSelected, onHighlighted }) => {
|
||||||
const [measure, ref] = useMeasure<HTMLDivElement>();
|
const [measure, ref] = useMeasure<HTMLDivElement>();
|
||||||
const [previewX, setPreviewX] = React.useState<number | undefined>();
|
const [previewPoint, setPreviewPoint] = React.useState<{ x: number, clientY: number } | undefined>();
|
||||||
const [hoveredBarIndex, setHoveredBarIndex] = React.useState<number | undefined>();
|
const [hoveredBarIndex, setHoveredBarIndex] = React.useState<number | undefined>();
|
||||||
|
|
||||||
const offsets = React.useMemo(() => {
|
const offsets = React.useMemo(() => {
|
||||||
@ -144,22 +144,23 @@ export const Timeline: React.FunctionComponent<{
|
|||||||
const onMouseMove = (event: React.MouseEvent) => {
|
const onMouseMove = (event: React.MouseEvent) => {
|
||||||
if (!ref.current)
|
if (!ref.current)
|
||||||
return;
|
return;
|
||||||
const x = event.clientX - ref.current.getBoundingClientRect().left;
|
const bounds = ref.current.getBoundingClientRect();
|
||||||
|
const x = event.clientX - bounds.left;
|
||||||
const index = findHoveredBarIndex(x);
|
const index = findHoveredBarIndex(x);
|
||||||
setPreviewX(x);
|
setPreviewPoint({ x, clientY: event.clientY });
|
||||||
setHoveredBarIndex(index);
|
setHoveredBarIndex(index);
|
||||||
if (typeof index === 'number')
|
if (typeof index === 'number')
|
||||||
onHighlighted(bars[index].entry);
|
onHighlighted(bars[index].entry);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMouseLeave = () => {
|
const onMouseLeave = () => {
|
||||||
setPreviewX(undefined);
|
setPreviewPoint(undefined);
|
||||||
setHoveredBarIndex(undefined);
|
setHoveredBarIndex(undefined);
|
||||||
onHighlighted(undefined);
|
onHighlighted(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClick = (event: React.MouseEvent) => {
|
const onClick = (event: React.MouseEvent) => {
|
||||||
setPreviewX(undefined);
|
setPreviewPoint(undefined);
|
||||||
if (!ref.current)
|
if (!ref.current)
|
||||||
return;
|
return;
|
||||||
const x = event.clientX - ref.current.getBoundingClientRect().left;
|
const x = event.clientX - ref.current.getBoundingClientRect().left;
|
||||||
@ -203,10 +204,10 @@ export const Timeline: React.FunctionComponent<{
|
|||||||
></div>;
|
></div>;
|
||||||
})
|
})
|
||||||
}</div>
|
}</div>
|
||||||
<FilmStrip context={context} boundaries={boundaries} previewX={previewX} />
|
<FilmStrip context={context} boundaries={boundaries} previewPoint={previewPoint} />
|
||||||
<div className='timeline-marker timeline-marker-hover' style={{
|
<div className='timeline-marker timeline-marker-hover' style={{
|
||||||
display: (previewX !== undefined) ? 'block' : 'none',
|
display: (previewPoint !== undefined) ? 'block' : 'none',
|
||||||
left: (previewX || 0) + 'px',
|
left: (previewPoint?.x || 0) + 'px',
|
||||||
}}></div>
|
}}></div>
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user