Show approval in browser-action popup instead of a separate window
Some checks failed
check / check (push) Has been cancelled
Some checks failed
check / check (push) Has been cancelled
Use action.openPopup() to show the approval in the toolbar popup, which is anchored to the browser window and cannot trigger a macOS Space switch. Falls back to a separate window if openPopup() is unavailable. A port connection detects when the popup is dismissed without a response, and the popup URL is reset to the main UI after every approval resolution.
This commit is contained in:
@@ -18,6 +18,8 @@ const runtime =
|
|||||||
const windowsApi =
|
const windowsApi =
|
||||||
typeof browser !== "undefined" ? browser.windows : chrome.windows;
|
typeof browser !== "undefined" ? browser.windows : chrome.windows;
|
||||||
const tabsApi = typeof browser !== "undefined" ? browser.tabs : chrome.tabs;
|
const tabsApi = typeof browser !== "undefined" ? browser.tabs : chrome.tabs;
|
||||||
|
const actionApi =
|
||||||
|
typeof browser !== "undefined" ? browser.browserAction : chrome.action;
|
||||||
|
|
||||||
// Connected sites (in-memory, non-persisted): { "origin:address": true }
|
// Connected sites (in-memory, non-persisted): { "origin:address": true }
|
||||||
const connectedSites = {};
|
const connectedSites = {};
|
||||||
@@ -82,18 +84,18 @@ async function proxyRpc(method, params) {
|
|||||||
return json.result;
|
return json.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open an approval popup and return a promise that resolves with the user decision
|
function resetPopupUrl() {
|
||||||
function requestApproval(origin, hostname) {
|
if (actionApi && typeof actionApi.setPopup === "function") {
|
||||||
return new Promise((resolve) => {
|
actionApi.setPopup({ popup: "src/popup/index.html" });
|
||||||
const id = nextApprovalId++;
|
}
|
||||||
pendingApprovals[id] = { origin, hostname, resolve };
|
}
|
||||||
|
|
||||||
|
// Fallback: open approval in a separate window (used when openPopup is unavailable)
|
||||||
|
function openApprovalWindow(id) {
|
||||||
const popupUrl = runtime.getURL("src/popup/index.html?approval=" + id);
|
const popupUrl = runtime.getURL("src/popup/index.html?approval=" + id);
|
||||||
const popupWidth = 400;
|
const popupWidth = 400;
|
||||||
const popupHeight = 500;
|
const popupHeight = 500;
|
||||||
|
|
||||||
// Center the popup over the focused window so macOS keeps it
|
|
||||||
// on the same Space instead of switching desktops.
|
|
||||||
windowsApi.getLastFocused((currentWin) => {
|
windowsApi.getLastFocused((currentWin) => {
|
||||||
const opts = {
|
const opts = {
|
||||||
url: popupUrl,
|
url: popupUrl,
|
||||||
@@ -115,9 +117,48 @@ function requestApproval(origin, hostname) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open an approval popup and return a promise that resolves with the user decision.
|
||||||
|
// Prefers the browser-action popup (anchored to toolbar, no macOS Space switch).
|
||||||
|
function requestApproval(origin, hostname) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const id = nextApprovalId++;
|
||||||
|
pendingApprovals[id] = { origin, hostname, resolve };
|
||||||
|
|
||||||
|
if (actionApi && typeof actionApi.openPopup === "function") {
|
||||||
|
actionApi.setPopup({
|
||||||
|
popup: "src/popup/index.html?approval=" + id,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const result = actionApi.openPopup();
|
||||||
|
if (result && typeof result.catch === "function") {
|
||||||
|
result.catch(() => openApprovalWindow(id));
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
openApprovalWindow(id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
openApprovalWindow(id);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect when an approval popup (browser-action) closes without a response
|
||||||
|
runtime.onConnect.addListener((port) => {
|
||||||
|
if (port.name.startsWith("approval:")) {
|
||||||
|
const id = parseInt(port.name.split(":")[1], 10);
|
||||||
|
port.onDisconnect.addListener(() => {
|
||||||
|
const approval = pendingApprovals[id];
|
||||||
|
if (approval) {
|
||||||
|
approval.resolve({ approved: false, remember: false });
|
||||||
|
delete pendingApprovals[id];
|
||||||
|
}
|
||||||
|
resetPopupUrl();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Handle connection requests (eth_requestAccounts, wallet_requestPermissions)
|
// Handle connection requests (eth_requestAccounts, wallet_requestPermissions)
|
||||||
async function handleConnectionRequest(origin) {
|
async function handleConnectionRequest(origin) {
|
||||||
const s = await getState();
|
const s = await getState();
|
||||||
@@ -361,6 +402,7 @@ async function broadcastAccountsChanged() {
|
|||||||
}
|
}
|
||||||
delete pendingApprovals[id];
|
delete pendingApprovals[id];
|
||||||
}
|
}
|
||||||
|
resetPopupUrl();
|
||||||
const s = await getState();
|
const s = await getState();
|
||||||
const activeAddress = await getActiveAddress();
|
const activeAddress = await getActiveAddress();
|
||||||
const allowed = activeAddress ? s.allowedSites[activeAddress] || [] : [];
|
const allowed = activeAddress ? s.allowedSites[activeAddress] || [] : [];
|
||||||
@@ -451,6 +493,7 @@ runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
|||||||
});
|
});
|
||||||
delete pendingApprovals[msg.id];
|
delete pendingApprovals[msg.id];
|
||||||
}
|
}
|
||||||
|
resetPopupUrl();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ let approvalId = null;
|
|||||||
|
|
||||||
function show(id) {
|
function show(id) {
|
||||||
approvalId = id;
|
approvalId = id;
|
||||||
|
// Connect a port so the background detects if the popup closes
|
||||||
|
// without an explicit response (e.g. user clicks away).
|
||||||
|
runtime.connect({ name: "approval:" + id });
|
||||||
runtime.sendMessage({ type: "AUTISTMASK_GET_APPROVAL", id }, (details) => {
|
runtime.sendMessage({ type: "AUTISTMASK_GET_APPROVAL", id }, (details) => {
|
||||||
if (!details) {
|
if (!details) {
|
||||||
window.close();
|
window.close();
|
||||||
|
|||||||
Reference in New Issue
Block a user