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 =
|
||||
typeof browser !== "undefined" ? browser.windows : chrome.windows;
|
||||
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 }
|
||||
const connectedSites = {};
|
||||
@@ -82,18 +84,18 @@ async function proxyRpc(method, params) {
|
||||
return json.result;
|
||||
}
|
||||
|
||||
// Open an approval popup and return a promise that resolves with the user decision
|
||||
function requestApproval(origin, hostname) {
|
||||
return new Promise((resolve) => {
|
||||
const id = nextApprovalId++;
|
||||
pendingApprovals[id] = { origin, hostname, resolve };
|
||||
function resetPopupUrl() {
|
||||
if (actionApi && typeof actionApi.setPopup === "function") {
|
||||
actionApi.setPopup({ popup: "src/popup/index.html" });
|
||||
}
|
||||
}
|
||||
|
||||
// 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 popupWidth = 400;
|
||||
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) => {
|
||||
const opts = {
|
||||
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)
|
||||
async function handleConnectionRequest(origin) {
|
||||
const s = await getState();
|
||||
@@ -361,6 +402,7 @@ async function broadcastAccountsChanged() {
|
||||
}
|
||||
delete pendingApprovals[id];
|
||||
}
|
||||
resetPopupUrl();
|
||||
const s = await getState();
|
||||
const activeAddress = await getActiveAddress();
|
||||
const allowed = activeAddress ? s.allowedSites[activeAddress] || [] : [];
|
||||
@@ -451,6 +493,7 @@ runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
});
|
||||
delete pendingApprovals[msg.id];
|
||||
}
|
||||
resetPopupUrl();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ let approvalId = null;
|
||||
|
||||
function show(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) => {
|
||||
if (!details) {
|
||||
window.close();
|
||||
|
||||
Reference in New Issue
Block a user