mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: introduce Page.viewportSizeChanged
event (#35994)
This commit is contained in:
parent
6e8c67a3ce
commit
2a5d83a623
@ -84,7 +84,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||
_workers = new Set<Worker>();
|
||||
private _closed = false;
|
||||
readonly _closedOrCrashedScope = new LongStandingScope();
|
||||
private _viewportSize: Size | null;
|
||||
private _viewportSize: Size | undefined;
|
||||
_routes: RouteHandler[] = [];
|
||||
_webSocketRoutes: WebSocketRouteHandler[] = [];
|
||||
|
||||
@ -130,7 +130,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||
this._mainFrame = Frame.from(initializer.mainFrame);
|
||||
this._mainFrame._page = this;
|
||||
this._frames.add(this._mainFrame);
|
||||
this._viewportSize = initializer.viewportSize || null;
|
||||
this._viewportSize = initializer.viewportSize;
|
||||
this._closed = initializer.isClosed;
|
||||
this._opener = Page.fromNullable(initializer.opener);
|
||||
|
||||
@ -151,6 +151,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||
const artifactObject = Artifact.from(artifact);
|
||||
this._forceVideo()._artifactReady(artifactObject);
|
||||
});
|
||||
this._channel.on('viewportSizeChanged', ({ viewportSize }) => this._viewportSize = viewportSize);
|
||||
this._channel.on('webSocket', ({ webSocket }) => this.emit(Events.Page.WebSocket, WebSocket.from(webSocket)));
|
||||
this._channel.on('worker', ({ worker }) => this._onWorker(Worker.from(worker)));
|
||||
|
||||
@ -506,7 +507,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||
}
|
||||
|
||||
viewportSize(): Size | null {
|
||||
return this._viewportSize;
|
||||
return this._viewportSize || null;
|
||||
}
|
||||
|
||||
async evaluate<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> {
|
||||
|
@ -1122,6 +1122,12 @@ scheme.PageDownloadEvent = tObject({
|
||||
suggestedFilename: tString,
|
||||
artifact: tChannel(['Artifact']),
|
||||
});
|
||||
scheme.PageViewportSizeChangedEvent = tObject({
|
||||
viewportSize: tOptional(tObject({
|
||||
width: tNumber,
|
||||
height: tNumber,
|
||||
})),
|
||||
});
|
||||
scheme.PageFileChooserEvent = tObject({
|
||||
element: tChannel(['ElementHandle']),
|
||||
isMultiple: tBoolean,
|
||||
|
@ -268,10 +268,10 @@ export class BidiPage implements PageDelegate {
|
||||
|
||||
async updateEmulatedViewportSize(): Promise<void> {
|
||||
const options = this._browserContext._options;
|
||||
const deviceSize = this._page.emulatedSize();
|
||||
if (deviceSize === null)
|
||||
const emulatedSize = this._page.emulatedSize();
|
||||
if (!emulatedSize)
|
||||
return;
|
||||
const viewportSize = deviceSize.viewport;
|
||||
const viewportSize = emulatedSize.viewport;
|
||||
await this._session.send('browsingContext.setViewport', {
|
||||
context: this._session.sessionId,
|
||||
viewport: {
|
||||
|
@ -108,7 +108,7 @@ export class CRPage implements PageDelegate {
|
||||
const features = opener._nextWindowOpenPopupFeatures.shift() || [];
|
||||
const viewportSize = helper.getViewportSizeFromWindowFeatures(features);
|
||||
if (viewportSize)
|
||||
this._page.setEmulatedSize({ viewport: viewportSize, screen: viewportSize });
|
||||
this._page.setEmulatedSizeFromWindowOpen({ viewport: viewportSize, screen: viewportSize });
|
||||
}
|
||||
|
||||
const createdEvent = this._isBackgroundPage ? CRBrowserContext.CREvents.BackgroundPage : BrowserContext.Events.Page;
|
||||
@ -953,7 +953,7 @@ class FrameSession {
|
||||
assert(this._isMainFrame());
|
||||
const options = this._crPage._browserContext._options;
|
||||
const emulatedSize = this._page.emulatedSize();
|
||||
if (emulatedSize === null)
|
||||
if (!emulatedSize)
|
||||
return;
|
||||
const viewportSize = emulatedSize.viewport;
|
||||
const screenSize = emulatedSize.screen;
|
||||
|
@ -66,7 +66,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
|
||||
|
||||
super(parentScope, page, 'Page', {
|
||||
mainFrame,
|
||||
viewportSize: page.viewportSize() || undefined,
|
||||
viewportSize: page.emulatedSize()?.viewport,
|
||||
isClosed: page.isClosed(),
|
||||
opener: PageDispatcher.fromNullable(parentScope, page.opener())
|
||||
});
|
||||
@ -83,6 +83,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
|
||||
// Artifact can outlive the page, so bind to the context scope.
|
||||
this._dispatchEvent('download', { url: download.url, suggestedFilename: download.suggestedFilename(), artifact: ArtifactDispatcher.from(parentScope, download.artifact) });
|
||||
});
|
||||
this.addObjectListener(Page.Events.EmulatedSizeChanged, () => this._dispatchEvent('viewportSizeChanged', { viewportSize: page.emulatedSize()?.viewport }));
|
||||
this.addObjectListener(Page.Events.FileChooser, (fileChooser: FileChooser) => this._dispatchEvent('fileChooser', {
|
||||
element: ElementHandleDispatcher.from(mainFrame, fileChooser.element()),
|
||||
isMultiple: fileChooser.isMultiple()
|
||||
|
@ -334,7 +334,7 @@ export class FFPage implements PageDelegate {
|
||||
}
|
||||
|
||||
async updateEmulatedViewportSize(): Promise<void> {
|
||||
const viewportSize = this._page.viewportSize();
|
||||
const viewportSize = this._page.emulatedSize()?.viewport ?? null;
|
||||
await this._session.send('Page.setViewportSize', { viewportSize });
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,7 @@ export class Page extends SdkObject {
|
||||
Close: 'close',
|
||||
Crash: 'crash',
|
||||
Download: 'download',
|
||||
EmulatedSizeChanged: 'emulatedsizechanged',
|
||||
FileChooser: 'filechooser',
|
||||
FrameAttached: 'frameattached',
|
||||
FrameDetached: 'framedetached',
|
||||
@ -546,23 +547,24 @@ export class Page extends SdkObject {
|
||||
}
|
||||
|
||||
async setViewportSize(viewportSize: types.Size) {
|
||||
this._emulatedSize = { viewport: { ...viewportSize }, screen: { ...viewportSize } };
|
||||
this._setEmulatedSize({ viewport: { ...viewportSize }, screen: { ...viewportSize } });
|
||||
await this.delegate.updateEmulatedViewportSize();
|
||||
}
|
||||
|
||||
viewportSize(): types.Size | null {
|
||||
return this.emulatedSize()?.viewport || null;
|
||||
setEmulatedSizeFromWindowOpen(emulatedSize: EmulatedSize) {
|
||||
this._setEmulatedSize(emulatedSize);
|
||||
}
|
||||
|
||||
setEmulatedSize(emulatedSize: EmulatedSize) {
|
||||
private _setEmulatedSize(emulatedSize: EmulatedSize) {
|
||||
this._emulatedSize = emulatedSize;
|
||||
this.emit(Page.Events.EmulatedSizeChanged);
|
||||
}
|
||||
|
||||
emulatedSize(): EmulatedSize | null {
|
||||
emulatedSize(): EmulatedSize | undefined {
|
||||
if (this._emulatedSize)
|
||||
return this._emulatedSize;
|
||||
const contextOptions = this.browserContext._options;
|
||||
return contextOptions.viewport ? { viewport: contextOptions.viewport, screen: contextOptions.screen || contextOptions.viewport } : null;
|
||||
return contextOptions.viewport ? { viewport: contextOptions.viewport, screen: contextOptions.screen || contextOptions.viewport } : undefined;
|
||||
}
|
||||
|
||||
async bringToFront(): Promise<void> {
|
||||
|
@ -173,12 +173,11 @@ export class Screenshotter {
|
||||
this._queue = new TaskQueue();
|
||||
}
|
||||
|
||||
private async _originalViewportSize(progress: Progress): Promise<{ viewportSize: types.Size, originalViewportSize: types.Size | null }> {
|
||||
const originalViewportSize = this._page.viewportSize();
|
||||
let viewportSize = originalViewportSize;
|
||||
private async _originalViewportSize(progress: Progress): Promise<types.Size> {
|
||||
let viewportSize = this._page.emulatedSize()?.viewport;
|
||||
if (!viewportSize)
|
||||
viewportSize = await this._page.mainFrame().waitForFunctionValueInUtility(progress, () => ({ width: window.innerWidth, height: window.innerHeight }));
|
||||
return { viewportSize, originalViewportSize };
|
||||
return viewportSize;
|
||||
}
|
||||
|
||||
private async _fullPageSize(progress: Progress): Promise<types.Size> {
|
||||
@ -205,7 +204,7 @@ export class Screenshotter {
|
||||
const format = validateScreenshotOptions(options);
|
||||
return this._queue.postTask(async () => {
|
||||
progress.log('taking page screenshot');
|
||||
const { viewportSize } = await this._originalViewportSize(progress);
|
||||
const viewportSize = await this._originalViewportSize(progress);
|
||||
await this._preparePageForScreenshot(progress, this._page.mainFrame(), options.style, options.caret !== 'initial', options.animations === 'disabled');
|
||||
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
|
||||
|
||||
@ -233,7 +232,7 @@ export class Screenshotter {
|
||||
const format = validateScreenshotOptions(options);
|
||||
return this._queue.postTask(async () => {
|
||||
progress.log('taking element screenshot');
|
||||
const { viewportSize } = await this._originalViewportSize(progress);
|
||||
const viewportSize = await this._originalViewportSize(progress);
|
||||
|
||||
await this._preparePageForScreenshot(progress, handle._frame, options.style, options.caret !== 'initial', options.animations === 'disabled');
|
||||
progress.throwIfAborted(); // Do not do extra work.
|
||||
|
@ -358,7 +358,7 @@ export class WKBrowserContext extends BrowserContext {
|
||||
await this._browser._browserSession.send('Playwright.cancelDownload', { uuid });
|
||||
}
|
||||
|
||||
_validateEmulatedViewport(viewportSize?: types.Size | null) {
|
||||
_validateEmulatedViewport(viewportSize: types.Size | undefined) {
|
||||
if (!viewportSize)
|
||||
return;
|
||||
if (process.platform === 'win32' && this._browser.options.headful && (viewportSize.width < 250 || viewportSize.height < 240))
|
||||
|
@ -109,7 +109,7 @@ export class WKPage implements PageDelegate {
|
||||
const viewportSize = helper.getViewportSizeFromWindowFeatures(opener._nextWindowOpenPopupFeatures);
|
||||
opener._nextWindowOpenPopupFeatures = undefined;
|
||||
if (viewportSize)
|
||||
this._page.setEmulatedSize({ viewport: viewportSize, screen: viewportSize });
|
||||
this._page.setEmulatedSizeFromWindowOpen({ viewport: viewportSize, screen: viewportSize });
|
||||
}
|
||||
}
|
||||
|
||||
@ -677,7 +677,7 @@ export class WKPage implements PageDelegate {
|
||||
}
|
||||
|
||||
async updateEmulatedViewportSize(): Promise<void> {
|
||||
this._browserContext._validateEmulatedViewport(this._page.viewportSize());
|
||||
this._browserContext._validateEmulatedViewport(this._page.emulatedSize()?.viewport);
|
||||
await this._updateViewport();
|
||||
}
|
||||
|
||||
@ -694,11 +694,11 @@ export class WKPage implements PageDelegate {
|
||||
|
||||
async _updateViewport(): Promise<void> {
|
||||
const options = this._browserContext._options;
|
||||
const deviceSize = this._page.emulatedSize();
|
||||
if (deviceSize === null)
|
||||
const emulatedSize = this._page.emulatedSize();
|
||||
if (!emulatedSize)
|
||||
return;
|
||||
const viewportSize = deviceSize.viewport;
|
||||
const screenSize = deviceSize.screen;
|
||||
const viewportSize = emulatedSize.viewport;
|
||||
const screenSize = emulatedSize.screen;
|
||||
const promises: Promise<any>[] = [
|
||||
this._pageProxySession.send('Emulation.setDeviceMetricsOverride', {
|
||||
width: viewportSize.width,
|
||||
|
8
packages/protocol/src/channels.d.ts
vendored
8
packages/protocol/src/channels.d.ts
vendored
@ -2013,6 +2013,7 @@ export interface PageEventTarget {
|
||||
on(event: 'close', callback: (params: PageCloseEvent) => void): this;
|
||||
on(event: 'crash', callback: (params: PageCrashEvent) => void): this;
|
||||
on(event: 'download', callback: (params: PageDownloadEvent) => void): this;
|
||||
on(event: 'viewportSizeChanged', callback: (params: PageViewportSizeChangedEvent) => void): this;
|
||||
on(event: 'fileChooser', callback: (params: PageFileChooserEvent) => void): this;
|
||||
on(event: 'frameAttached', callback: (params: PageFrameAttachedEvent) => void): this;
|
||||
on(event: 'frameDetached', callback: (params: PageFrameDetachedEvent) => void): this;
|
||||
@ -2075,6 +2076,12 @@ export type PageDownloadEvent = {
|
||||
suggestedFilename: string,
|
||||
artifact: ArtifactChannel,
|
||||
};
|
||||
export type PageViewportSizeChangedEvent = {
|
||||
viewportSize?: {
|
||||
width: number,
|
||||
height: number,
|
||||
},
|
||||
};
|
||||
export type PageFileChooserEvent = {
|
||||
element: ElementHandleChannel,
|
||||
isMultiple: boolean,
|
||||
@ -2566,6 +2573,7 @@ export interface PageEvents {
|
||||
'close': PageCloseEvent;
|
||||
'crash': PageCrashEvent;
|
||||
'download': PageDownloadEvent;
|
||||
'viewportSizeChanged': PageViewportSizeChangedEvent;
|
||||
'fileChooser': PageFileChooserEvent;
|
||||
'frameAttached': PageFrameAttachedEvent;
|
||||
'frameDetached': PageFrameDetachedEvent;
|
||||
|
@ -2001,6 +2001,14 @@ Page:
|
||||
suggestedFilename: string
|
||||
artifact: Artifact
|
||||
|
||||
viewportSizeChanged:
|
||||
parameters:
|
||||
viewportSize:
|
||||
type: object?
|
||||
properties:
|
||||
width: number
|
||||
height: number
|
||||
|
||||
fileChooser:
|
||||
parameters:
|
||||
element: ElementHandle
|
||||
|
Loading…
x
Reference in New Issue
Block a user