diff --git a/main.js b/main.js index 7dd66878..8b84f959 100644 --- a/main.js +++ b/main.js @@ -2506,11 +2506,6 @@ function zoomSet(t, percent) { } ipcMain.handle("zoom-step", (_e, dir) => zoomStep(activeTab(), Number(dir) > 0 ? 1 : -1)); ipcMain.handle("zoom-reset", () => zoomSet(activeTab(), 100)); -// Pull the tab's real URL from webContents after Electron navigates, so in-page -// clicks (subpages of a BCNR site, subdomain hops, cross-origin redirects) update -// the address bar. Without this, t.url is only refreshed on programmatic loads — -// navigateTab / the collision switcher — and everything else sticks on the parent. -// Internal bns:// → https:// for display, matching navigateTab's convention that // ---- HTTP authentication (401 / 407 challenges) ---- // Without a `login` listener Electron cancels every challenge, so a site @@ -2575,6 +2570,11 @@ app.on("login", (event, _wc, details, authInfo, callback) => { } p.then((c) => { if (c) callback(c.username, c.password); else callback(); }, () => callback()); }); +// Pull the tab's real URL from webContents after Electron navigates, so in-page +// clicks (subpages of a BCNR site, subdomain hops, cross-origin redirects) update +// the address bar. Without this, t.url is only refreshed on programmatic loads — +// navigateTab / the collision switcher — and everything else sticks on the parent. +// Internal bns:// → https:// for display, matching navigateTab's convention that // https:// is what the user sees regardless of how the bytes were fetched. function refreshTabUrl(tab) { if (!tab || tab.prov?.kind === "home") return; // home is loadFile → file://; leave t.url = "" @@ -2985,14 +2985,14 @@ async function navigateTab(id, input) { const t = tabById(id); if (!t) return; let q = String(input).trim(); if (!q) return; + // Local paths open as files — never BCNR, never a search. + const fileUrl = localFileUrl(q); + if (fileUrl) return loadLocalFile(t, id, fileUrl); // Address bar doubles as a search box: anything that isn't a URL/hostname // (a bare word, or a phrase with spaces) becomes a web search. if (!looksLikeUrl(q)) q = SEARCH(q); const raw = q.replace(/^[a-z]+:\/\//i, ""); const host = raw.split("/")[0].toLowerCase(); - // Local paths open as files — never BCNR, never a search. - const fileUrl = localFileUrl(q); - if (fileUrl) return loadLocalFile(t, id, fileUrl); const rest = raw.slice(host.length) || "/"; // Reflect the target URL immediately so the address bar doesn't keep // showing the previous page's URL for the whole load duration. Without @@ -3019,11 +3019,6 @@ async function navigateTab(id, input) { emitTabs(); } -// Load a name from BCNR into a tab. Called for every dotted host — BCNR is -// tried first; on NXDOMAIN or resolver failure we always fall through to the -// clearnet (https://) so the user isn't stranded when the chain -// is down or the name isn't registered. -async function loadBns(t, id, host, rest, tld) { // Open a local file (file:// URL) in a tab. A missing file surfaces through // did-fail-load → loadErrorPage like any other failed navigation. async function loadLocalFile(t, id, fileUrl) { @@ -3039,6 +3034,11 @@ async function loadLocalFile(t, id, fileUrl) { catch (e) { console.warn("local file load failed:", e?.message); } } +// Load a name from BCNR into a tab. Called for every dotted host — BCNR is +// tried first; on NXDOMAIN or resolver failure we always fall through to the +// clearnet (https://) so the user isn't stranded when the chain +// is down or the name isn't registered. +async function loadBns(t, id, host, rest, tld) { const registry = registryOf(tld); if (id === activeId) pushNav({ host, kind: "resolving", tld, registry }); const fallbackToWeb = async (reason) => {