diff --git a/main.js b/main.js index 2ff2e93..71bba56 100644 --- a/main.js +++ b/main.js @@ -1534,8 +1534,24 @@ function initAddons() { // region — run the caller-supplied overlay source in the tab, wait // for a rect (or null = cancel), then capturePage(rect). captureTab: async (opts, addonId) => { - const t = activeTab(); + // Prefer the currently-active tab, BUT if that's an add-on-owned page + // (e.g. the screenshot editor is already up when the user re-picks a + // mode from the dropdown), fall back to the most-recently-active real + // tab. Otherwise a second capture snapshots the editor's still-blank + // canvas and every follow-up produces a white PNG. + let t = activeTab(); + if (t && (t.addonId || t.settings)) { + const fallback = tabById(lastCapturableTabId); + if (fallback && !fallback.addonId && !fallback.settings) t = fallback; + else { + // Last resort: any non-addon non-settings tab in the list. + t = tabs.find((x) => !x.addonId && !x.settings) || t; + } + } if (!t) throw new Error("no active tab"); + if (t.addonId || t.settings) { + throw new Error("no capturable tab — open a page you'd like to shoot first"); + } const wc = t.view.webContents; const host = t?.prov?.host || (() => { try { return new URL(wc.getURL()).host; } catch { return ""; } })(); const mode = String(opts?.mode || "visible"); @@ -1686,6 +1702,11 @@ const tabs = []; // { id, view, title, url, prov } let activeId = null, tabSeq = 0; const tabById = (id) => tabs.find((t) => t.id === id); const activeTab = () => tabById(activeId); +// The most-recently-active non-addon tab. captureTab falls back to this when +// the currently-active tab is an add-on-owned page (e.g. the screenshot +// editor itself) — otherwise a re-triggered capture snapshots the editor's +// still-blank canvas instead of the page the user actually wants to shoot. +let lastCapturableTabId = null; // Provenance goes to BOTH the top chrome (registry badge + site-info panel) and // the bottom status line, so the resolver detail lives on the bottom bar. @@ -2018,6 +2039,10 @@ function setActive(id) { if (target) target.view.setVisible(true); for (const t of tabs) if (t.id !== id) t.view.setVisible(false); const t = activeTab(); + // Track the last active tab that isn't an add-on-owned page so captureTab + // has a sensible fallback when the user re-triggers the dropdown from + // inside (say) the screenshot editor. + if (t && !t.addonId && !t.settings) lastCapturableTabId = t.id; if (t?.prov) pushNav(t.prov); chrome.webContents.send("bcnr-offer", t?.bcnrOffer ? { host: t.bcnrOffer.host, tld: t.bcnrOffer.tld, registry: REGISTRY } : null); emitTabs();