From b42f304ce8457386100bad13c8e8a5d57b2e0bad Mon Sep 17 00:00:00 2001 From: Local Dev Date: Mon, 28 Sep 2026 23:05:48 +0200 Subject: [PATCH] =?UTF-8?q?feat(aegis):=200.16.0=20=E2=80=94=20Address=20&?= =?UTF-8?q?=20QR=20and=20Assets=20are=20peer=20chips,=20and=20the=20coin?= =?UTF-8?q?=20row=20loses=20its=20dropdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two changes to the same idea: one way to do each thing, and the same shape for every coin. **Assets is no longer buried under the QR.** The Receive body stacked address → QR → assets in one column, so in a 380px panel the token list sat permanently below the fold behind 200px of QR — and a coin holding no tokens simply lost a section, which made every coin look structurally different. Address & QR and Assets are now peers behind a persistent chip row. The count rides on the chip, and a wallet with nothing says "No assets held by this wallet" instead of the section vanishing. That mattered more than it sounds: a chipnet wallet with 46 CashToken categories was indistinguishable from an empty one until 0.15.0, because the only signal was an absent card. The choice persists across re-renders and wallet switches — comparing token balances between wallets should not throw you back to the QR on every click. Switching back to Address redraws the QR, since a canvas sized while hidden comes out blank and renderReceive only repaints when the address changes. **The coin row's ▾ network dropdown is gone.** The coin view already carries real network chips (data-browse-net: they filter the wallet list and show a per-network count), so the popover was a second control for one job — and the only one that hid its options behind a click. Chips are the single network control now and the ticker is plain text again. Verified in the panel: chips switch panes and track their own state, the count shows, the empty state reads correctly, the QR survives the round trip, and no .wchev / .wcname.wswitchable remain in the DOM. --- bundled-addons/aegis/addon.json | 2 +- bundled-addons/aegis/panel.html | 28 ++++++++---- bundled-addons/aegis/panel.js | 76 +++++++++++++++++++++++++++------ 3 files changed, 84 insertions(+), 22 deletions(-) diff --git a/bundled-addons/aegis/addon.json b/bundled-addons/aegis/addon.json index d21aef05..f7b2f020 100644 --- a/bundled-addons/aegis/addon.json +++ b/bundled-addons/aegis/addon.json @@ -1,7 +1,7 @@ { "id": "aegis", "name": "Aegis Wallet", - "version": "0.15.0", + "version": "0.16.0", "category": "plugin", "description": "Multi-chain wallet (BCH, BTC, TRX, ETH, SOL, SC, DGB) derived from your Theseus vault. Dapps get window.bitcoincash on .x sites; window.tronWeb / window.tronLink / window.ethereum / window.solana on any https page.", "author": "Silent Mode", diff --git a/bundled-addons/aegis/panel.html b/bundled-addons/aegis/panel.html index 3d0b5913..3ce0ac9c 100644 --- a/bundled-addons/aegis/panel.html +++ b/bundled-addons/aegis/panel.html @@ -768,10 +768,19 @@
- + +
+ + +
+
Receiving address
+
diff --git a/bundled-addons/aegis/panel.js b/bundled-addons/aegis/panel.js index 09574d77..72bc4d45 100644 --- a/bundled-addons/aegis/panel.js +++ b/bundled-addons/aegis/panel.js @@ -2136,6 +2136,29 @@ function paintSendMode() { if (host && consolidateInlineHost !== host) { consolidateInlineHost = host; renderConsolidateInline(host); } } } +// Which half of the Receive pane is showing. Persistent: the choice sticks +// across re-renders and across wallet switches, because someone comparing +// token balances between wallets should not be knocked back to the QR on +// every click. +let rcvView = "address"; +try { rcvView = localStorage.getItem("aegis/rcvView") === "assets" ? "assets" : "address"; } catch (_e) {} +function paintRcvView() { + const addr = $("rcvAddressPane"), assets = $("rcvAssetsPane"); + if (!addr || !assets) return; + document.querySelectorAll("[data-rcv-view]").forEach((b) => + b.classList.toggle("on", b.dataset.rcvView === rcvView)); + addr.hidden = rcvView !== "address"; + assets.hidden = rcvView !== "assets"; + // The QR's backing store is sized from its rendered box, so one drawn + // while its pane was hidden comes out blank. Redraw on reveal — and note + // renderReceive only redraws when the address CHANGES, so switching back + // to an unchanged address would otherwise never repaint it. + if (rcvView === "address") { + const a = sel()?.address || ""; + if (a) { try { drawQr(qrPayload(chain(), a, sel()?.network)); } catch (_e) {} } + } +} + function paintRcvMode() { const normal = $("rcvNormal"); const cons = $("rcvConsolidate"); if (!normal || !cons) return; @@ -2522,15 +2545,16 @@ function renderWalletStrip() { pill = `${esc(meta.networkLabel)}`; } - // ▾ chevron shown only when the chain has more than one network — - // otherwise the click affordance would be a lie and the ticker acts - // like plain text. - const multiNet = nets.length > 1; - const chevron = multiNet ? `` : ""; - const nameCls = multiNet ? "wcname wswitchable" : "wcname"; - const nameTitle = multiNet - ? `Switch network — ${nets.map((n) => networkLabelFor(chain, n, n)).join(" / ")}` - : meta.coinName; + // 0.16.0: no ▾ network dropdown on the coin row. The coin view already + // carries real network chips (data-browse-net — they filter the list and + // show a per-network count), so a popover menu doing the same job was a + // second way to do one thing, and the only one that hid its options + // behind a click. Chips are the single network control now; the ticker + // is plain text again. + const multiNet = false; + const chevron = ""; + const nameCls = "wcname"; + const nameTitle = meta.coinName; // Single wallet under the active network → click selects it. Multi- // wallet: click selects the "active" wallet for this bucket (defaults @@ -3323,6 +3347,7 @@ function render() { if (!showToggle) { sendMode = "send"; rcvMode = "receive"; } paintSendMode(); paintRcvMode(); + paintRcvView(); } // Sum every wallet's confirmed+unconfirmed × price and show "≈ $X across N @@ -3355,6 +3380,24 @@ function renderPortfolio() { el.innerHTML = `Portfolio: ${esc(fmtFiat(total))} across ${wallets.length} ${noun}`; } +// Assets is a chip now, not a card that disappears when the count is zero. +// The count rides on the chip and an empty wallet says so in the pane, so +// "this wallet holds nothing" is a visible answer rather than a missing +// section the user has to infer — which is exactly how 46 CashTokens managed +// to look like a working, empty wallet before 0.15.0. +function setAssetsCount(n) { + const chip = $("rcvAssetsCount"); + if (chip) chip.textContent = n ? String(n) : ""; + const card = $("tokensCard"); + if (card) card.hidden = false; + if (!n) { + const el = $("tokensList"); + if (el) el.innerHTML = `
No assets held by this wallet.
`; + const cnt = $("tokensCount"); + if (cnt) cnt.textContent = ""; + } +} + function renderTokens() { const s = sel(); const card = $("tokensCard"); @@ -3362,7 +3405,7 @@ function renderTokens() { // SOL wallets: SPL tokens with a Send button (existing flow). if (chain() === "sol") { const tokens = s?.tokens || []; - card.hidden = tokens.length === 0; + setAssetsCount(tokens.length); const hintEl = $("tokensHint"); if (hintEl) hintEl.textContent = "SPL tokens held by this wallet. Send by picking one under the Send tab's Asset dropdown."; if (!tokens.length) return; @@ -3388,7 +3431,7 @@ function renderTokens() { if (chain() === "bch") { const balances = s?.tokenBalances || {}; const cats = Object.keys(balances); - card.hidden = cats.length === 0; + setAssetsCount(cats.length); const hintEl = $("tokensHint"); if (hintEl) hintEl.textContent = "CashTokens held by this wallet. Names come from BCMR — configure custom registries in Settings."; if (!cats.length) return; @@ -3432,8 +3475,8 @@ function renderTokens() { // through to a hidden card the way ETH did until 0.9.3. { const tokens = s?.tokens || []; - if (!tokens.length) { card.hidden = true; return; } - card.hidden = false; + if (!tokens.length) { setAssetsCount(0); return; } + setAssetsCount(tokens.length); const hintEl = $("tokensHint"); const kindLabel = chain() === "trx" ? "TRC20" : chain() === "eth" ? "ERC20" : "Tokens"; if (hintEl) hintEl.textContent = `${kindLabel} tokens held by this wallet. Read-only in this build — open the explorer from the header to move them.`; @@ -3830,10 +3873,17 @@ document.querySelectorAll("[data-send-mode]").forEach((b) => b.addEventListener( consolidateInlineHost = null; // force re-render on next switch paintSendMode(); })); +// Address & QR / Assets — the persistent pair inside the Receive body. +document.querySelectorAll("[data-rcv-view]").forEach((b) => b.addEventListener("click", () => { + rcvView = b.dataset.rcvView === "assets" ? "assets" : "address"; + try { localStorage.setItem("aegis/rcvView", rcvView); } catch (_e) {} + paintRcvView(); +})); document.querySelectorAll("[data-rcv-mode]").forEach((b) => b.addEventListener("click", () => { rcvMode = b.dataset.rcvMode; consolidateInlineHost = null; paintRcvMode(); + paintRcvView(); })); ["sendTo", "sendAmt"].forEach((id) => $(id).addEventListener("input", () => { if (id === "sendAmt" && sendMax) return;