fix: approval windows open as wide as the page (closes #518)
The approval window opened 360 pixels wide while the page is 396, cutting off the Reject button; it now opens at 396. The browser counts the window's frame in that width, and a tall screen gives some of it to a vertical scrollbar, so once the approval's screen is up the page widens its own window by however far it would scroll sideways, times the zoom of its own tab. Firefox draws some zoom steps a little larger than it reports, so the page measures again after each widening, three times at most. The toolbar popup's window is left alone. The Firefox suite checks that the sign prompt fits at 170%. README's Visual Style line now gives the page's real width. Model: opus-5-5
This commit was merged in pull request #555.
This commit is contained in:
@@ -453,7 +453,10 @@ function releaseApproval(approval) {
|
||||
// the result on the floor, so a rejection here would be unhandled.
|
||||
async function openApprovalWindow(id) {
|
||||
const popupUrl = runtime.getURL("src/popup/index.html?approval=" + id);
|
||||
const popupWidth = 360;
|
||||
// As wide as the page: body in src/popup/styles/main.css. The browser
|
||||
// counts the window's frame in this width; the page itself adds back
|
||||
// whatever the frame takes (src/popup/index.js).
|
||||
const popupWidth = 396;
|
||||
const popupHeight = 600;
|
||||
|
||||
let currentWin = null;
|
||||
@@ -473,7 +476,7 @@ async function openApprovalWindow(id) {
|
||||
// Centred on a browser window only. The last focused window can be
|
||||
// another approval window still open, and centring on one can give a
|
||||
// position the browser refuses ("Bounds must be at least 50% within
|
||||
// visible screen space"): headless Chrome reports this 360x600 popup as
|
||||
// visible screen space"): headless Chrome reports this 396x600 popup as
|
||||
// 1280x720. The request then failed with no window at all. Over a popup,
|
||||
// the browser picks the position.
|
||||
if (currentWin && currentWin.type === "normal") {
|
||||
|
||||
+42
-2
@@ -21,6 +21,12 @@ const {
|
||||
goBack,
|
||||
} = require("./views/helpers");
|
||||
const { applyTheme } = require("./theme");
|
||||
const {
|
||||
tabsGetCurrent,
|
||||
tabsGetZoom,
|
||||
windowsGetCurrent,
|
||||
windowsUpdate,
|
||||
} = require("../shared/browserApi");
|
||||
// Renders a view the popup lands on without having navigated to it forward:
|
||||
// on restore here, and on Back. Only the views that can be fully re-rendered
|
||||
// from persisted state (RESTORABLE_VIEWS, src/shared/restorableViews.js) go
|
||||
@@ -163,6 +169,40 @@ function fallbackView() {
|
||||
showView("main");
|
||||
}
|
||||
|
||||
// The background opens the approval window as wide as the page, but the
|
||||
// browser counts the window's frame in that width, and a screen taller than
|
||||
// the window takes a vertical scrollbar out of it too. So once the screen is
|
||||
// up, the window is widened by however far the page would scroll sideways.
|
||||
// That distance is in page pixels and the window's width in screen pixels:
|
||||
// at 150% zoom one page pixel is 1.5 screen pixels. The zoom is read for this
|
||||
// page's own tab, because asked without a tab id Firefox answers for the
|
||||
// window focused last. Firefox draws some zoom steps a little larger than the
|
||||
// zoom it reports, 170% among them, so once the page has its new width (its
|
||||
// resize event) it is measured again, and the window widened again while the
|
||||
// page still falls short, three times at most. A window that cannot grow sends
|
||||
// no resize event, and the page stops there. The connection prompt can also
|
||||
// show in the toolbar popup, whose window is the user's browser window; that
|
||||
// one is left alone.
|
||||
async function widenApprovalWindow() {
|
||||
const page = document.documentElement;
|
||||
if (page.scrollWidth <= page.clientWidth) return;
|
||||
const win = await windowsGetCurrent();
|
||||
if (win.type !== "popup") return;
|
||||
const tab = await tabsGetCurrent();
|
||||
const zoom = await tabsGetZoom(tab.id);
|
||||
let width = win.width;
|
||||
for (let tries = 0; tries < 3; tries++) {
|
||||
const sideways = page.scrollWidth - page.clientWidth;
|
||||
if (sideways <= 0) return;
|
||||
width += Math.ceil(sideways * zoom);
|
||||
const resized = new Promise((resolve) =>
|
||||
window.addEventListener("resize", resolve, { once: true }),
|
||||
);
|
||||
await windowsUpdate(win.id, { width });
|
||||
await resized;
|
||||
}
|
||||
}
|
||||
|
||||
async function init() {
|
||||
// First, before anything can save: showView() saves on every navigation
|
||||
// without awaiting, so a save that fails from here on has somewhere to be
|
||||
@@ -239,8 +279,8 @@ async function init() {
|
||||
// the run on both harnesses (Playwright `pageerror`, and the Firefox
|
||||
// driver's console-service drain), so nothing is lost by leaving it
|
||||
// on that path. show() puts the approval's own screen up once the
|
||||
// background has described it.
|
||||
approval.show(approvalId);
|
||||
// background has described it; the window is widened to fit it then.
|
||||
approval.show(approvalId).then(widenApprovalWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -243,6 +243,22 @@ function tabsSendMessage(tabId, message) {
|
||||
return invoke(tabsApi(), "sendMessage", tabId, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<Object|undefined>} the tab the calling page is in, or
|
||||
* undefined for a page not in a tab, such as the toolbar popup.
|
||||
*/
|
||||
function tabsGetCurrent() {
|
||||
return invoke(tabsApi(), "getCurrent");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} tabId
|
||||
* @returns {Promise<number>} that tab's zoom: 1.5 at 150%.
|
||||
*/
|
||||
function tabsGetZoom(tabId) {
|
||||
return invoke(tabsApi(), "getZoom", tabId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} createData
|
||||
* @returns {Promise<Object>} the created window.
|
||||
@@ -258,6 +274,22 @@ function windowsGetLastFocused() {
|
||||
return invoke(windowsApi(), "getLastFocused");
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<Object>} the window the calling page is in.
|
||||
*/
|
||||
function windowsGetCurrent() {
|
||||
return invoke(windowsApi(), "getCurrent");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} windowId
|
||||
* @param {Object} updateInfo
|
||||
* @returns {Promise<Object>} the updated window.
|
||||
*/
|
||||
function windowsUpdate(windowId, updateInfo) {
|
||||
return invoke(windowsApi(), "update", windowId, updateInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} windowId
|
||||
* @returns {Promise<void>}
|
||||
@@ -280,10 +312,14 @@ module.exports = {
|
||||
storageRemove,
|
||||
storageSet,
|
||||
tabsApi,
|
||||
tabsGetCurrent,
|
||||
tabsGetZoom,
|
||||
tabsQuery,
|
||||
tabsSendMessage,
|
||||
windowsApi,
|
||||
windowsCreate,
|
||||
windowsGetCurrent,
|
||||
windowsGetLastFocused,
|
||||
windowsRemove,
|
||||
windowsUpdate,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user