feat(trace-viewer): show screenshot pointer (#32514)

Follow-up to https://github.com/microsoft/playwright/pull/32248. Adds a
glowing red circle that shows the click position. I made it glowing to
show that its position is inaccurate.
<img width="964" alt="Screenshot 2024-09-09 at 11 33 45"
src="https://github.com/user-attachments/assets/1903071d-6dc0-46c7-9951-844e49a51f35">
This commit is contained in:
Simon Knott 2024-09-09 14:00:22 +02:00 committed by GitHub
parent ae02331d00
commit 31e269ad06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 3 deletions

View File

@ -0,0 +1,48 @@
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export function ClickPointer({ point }: { point: { x: number; y: number } }) {
return (
<div
style={{
position: 'fixed',
backgroundColor: '#f44336',
width: '20px',
height: '20px',
borderRadius: '10px',
margin: '-10px 0 0 -10px',
zIndex: 2147483646,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
left: `${point.x}px`,
top: `${point.y}px`,
}}
>
<div
style={{
fontSize: '19px',
color: 'white',
marginTop: '-3.5px',
userSelect: 'none'
}}
title='Click positions on screenshots are inaccurate.'
>
</div>
</div>
);
}

View File

@ -29,6 +29,7 @@ import type { Language } from '@isomorphic/locatorGenerators';
import { locatorOrSelectorAsSelector } from '@isomorphic/locatorParser';
import { TabbedPaneTab } from '@web/components/tabbedPane';
import { BrowserFrame } from './browserFrame';
import { ClickPointer } from './clickPointer';
function findClosest<T extends { timestamp: number }>(items: T[], target: number) {
return items.find((item, index) => {
@ -73,7 +74,7 @@ export const SnapshotTab: React.FunctionComponent<{
return { snapshots: { action: actionSnapshot, before: beforeSnapshot, after: afterSnapshot } };
}, [action]);
const { snapshotInfoUrl, snapshotUrl, popoutUrl } = React.useMemo(() => {
const { snapshotInfoUrl, snapshotUrl, popoutUrl, point } = React.useMemo(() => {
const snapshot = snapshots[snapshotTab];
if (!snapshot)
return { snapshotUrl: kBlankSnapshotUrl };
@ -96,7 +97,7 @@ export const SnapshotTab: React.FunctionComponent<{
popoutParams.set('pointY', String(snapshot.point.y));
}
const popoutUrl = new URL(`snapshot.html?${popoutParams.toString()}`, window.location.href).toString();
return { snapshots, snapshotInfoUrl, snapshotUrl, popoutUrl };
return { snapshots, snapshotInfoUrl, snapshotUrl, popoutUrl, point: snapshot.point };
}, [snapshots, snapshotTab]);
const iframeRef0 = React.useRef<HTMLIFrameElement>(null);
@ -230,7 +231,12 @@ export const SnapshotTab: React.FunctionComponent<{
transform: `translate(${translate.x}px, ${translate.y}px) scale(${scale})`,
}}>
<BrowserFrame url={snapshotInfo.url} />
{(showScreenshotInsteadOfSnapshot && screencastFrame) && <img alt={`Screenshot of ${action?.apiName} > ${renderTitle(snapshotTab)}`} src={`sha1/${screencastFrame.sha1}`} width={screencastFrame.width} height={screencastFrame.height} />}
{(showScreenshotInsteadOfSnapshot && screencastFrame) && (
<>
{point && <ClickPointer point={point} />}
<img alt={`Screenshot of ${action?.apiName} > ${renderTitle(snapshotTab)}`} src={`sha1/${screencastFrame.sha1}`} width={screencastFrame.width} height={screencastFrame.height} />
</>
)}
<div className='snapshot-switcher' style={showScreenshotInsteadOfSnapshot ? { display: 'none' } : undefined}>
<iframe ref={iframeRef0} name='snapshot' title='DOM Snapshot' className={clsx(loadingRef.current.visibleIframe === 0 && 'snapshot-visible')}></iframe>
<iframe ref={iframeRef1} name='snapshot' title='DOM Snapshot' className={clsx(loadingRef.current.visibleIframe === 1 && 'snapshot-visible')}></iframe>