diff --git a/addon-updater.js b/addon-updater.js index fd85966d..f89fce5f 100644 --- a/addon-updater.js +++ b/addon-updater.js @@ -197,8 +197,24 @@ async function stageOne({ id, currentVer, updateURL, stagedDir, pubkeysHex, log, // arrives at tar as `C:\\Users...\\dir` and it can't open the path. // Forward-slash paths dodge both — bsdtar (Win10 built-in), GNU tar, // and MSYS2 tar all accept `C:/Users/...` as a plain path. + // BUT: Windows 10's built-in bsdtar does NOT recognise --force-local at + // all and errors out with "unknown option". Try WITHOUT the flag first + // (safe with posix paths on every tar we care about) and fall back to + // WITH it for MSYS2 tar which parses `C:/…` as a host prefix. Either + // path is a single tar invocation — the fallback only fires on the + // exit-code failure of the first. const posix = (p) => p.replace(/\\/g, "/"); - execFileSync("tar", ["--force-local", "-x", "-z", "-f", posix(tmpFile), "-C", posix(tmpDir)], { stdio: "ignore" }); + const baseArgs = ["-x", "-z", "-f", posix(tmpFile), "-C", posix(tmpDir)]; + try { + execFileSync("tar", baseArgs, { stdio: "ignore" }); + } catch (e1) { + try { + execFileSync("tar", ["--force-local", ...baseArgs], { stdio: "ignore" }); + } catch (e2) { + // Surface the first error; --force-local retry is opportunistic. + throw e1; + } + } } catch (e) { log(`updates: extract ${id}@${best.version} failed:`, e.message); try { fs.rmSync(tmpFile, { force: true }); } catch {} diff --git a/main.js b/main.js index 65309d42..33eb883d 100644 --- a/main.js +++ b/main.js @@ -2128,10 +2128,17 @@ function installDownloadTracker() { }); } function setActive(id) { + const switching = id !== activeId; activeId = id; if (popVisible) showPopover(false); // don't carry a stale popover across tabs if (epVisible) showEnginePicker(false); if (linkStatusVisible) showLinkStatus(""); // clear any lingering hover pill + // A user action that switches to a different tab (New Tab, Settings, + // address-bar nav that opens elsewhere, tab-strip click) shouldn't leave + // the incoming tab hidden behind a maximized sidebar. Auto-restore the + // sidebar to its pre-max width so the tab is actually visible; the + // user can re-maximize when they're done. + if (switching && sidebarMaximized) setSidebarMaximized(false); // Show the NEW active tab first, THEN hide the others. Reversing this // order eliminates the "no tab is visible" frame on switch that made the // tab strip flash — the compositor always has at least one tab view up.