diff --git a/bundled-addons/aegis/addon.json b/bundled-addons/aegis/addon.json index a42a1fa..4e1abc4 100644 --- a/bundled-addons/aegis/addon.json +++ b/bundled-addons/aegis/addon.json @@ -1,10 +1,10 @@ { "id": "aegis", "name": "Aegis Wallet", - "version": "0.4.0", + "version": "0.4.1", "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", - "icon": "🛡", + "icon": "data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none'%3E%3Cpolygon points='16,2 28,9 28,23 16,30 4,23 4,9' fill='%230a0a0d' stroke='%23D6FF3D' stroke-width='1.6' stroke-linejoin='round'/%3E%3Ccircle cx='16' cy='16' r='4.5' fill='none' stroke='%23D6FF3D' stroke-width='1.4'/%3E%3Ccircle cx='16' cy='16' r='1.6' fill='%23D6FF3D'/%3E%3C/svg%3E", "main": "index.js", "capabilities": ["sidebar-panel", "vault-derive", "page-inject", "approval-modal"], "absorbs": ["bchwallet", "siawallet"], diff --git a/chrome.html b/chrome.html index f2159b5..d3b597a 100644 --- a/chrome.html +++ b/chrome.html @@ -576,7 +576,18 @@ const dataAttr = b.kind === "panel" ? `data-panel="${b.panelId.replace(/"/g,""")}"` : `data-menu="${b.addonId.replace(/"/g,""")}"`; - return ``; }).join(""); extButtons.querySelectorAll(".extbtn").forEach((btn) => { btn.onclick = () => { diff --git a/main.js b/main.js index 94abc62..2ff2e93 100644 --- a/main.js +++ b/main.js @@ -1355,13 +1355,21 @@ function migrateAegisRename() { const aegisDir = path.join(addonsRoot, "aegis"); const bchJson = path.join(dataRoot, "bchwallet.json"); const aegisJson = path.join(dataRoot, "aegis.json"); - if (fs.existsSync(bchDir) && !fs.existsSync(aegisDir)) { - if (fs.existsSync(bchJson) && !fs.existsSync(aegisJson)) { - try { fs.copyFileSync(bchJson, aegisJson); console.log("[addons] migrated bchwallet.json -> aegis.json"); } - catch (err) { console.warn("[addons] migrate storage failed:", err?.message); } - } + // Copy legacy storage into the new file exactly once, only when the new + // file doesn't exist yet (a downgrade to 0.3.x would otherwise clobber + // fresh state written by 0.4+). + if (fs.existsSync(bchJson) && !fs.existsSync(aegisJson)) { + try { fs.copyFileSync(bchJson, aegisJson); console.log("[addons] migrated bchwallet.json -> aegis.json"); } + catch (err) { console.warn("[addons] migrate storage failed:", err?.message); } + } + // Retire the bchwallet folder EVERY LAUNCH it exists. The signed OTA + // update endpoint may still advertise `id=bchwallet` updates, and + // promoteStagedUpdates (which runs before us) could reinstall it. Left + // active it would load as a second Aegis under a stale id, doubling + // every wallet in the sidebar. + if (fs.existsSync(bchDir)) { const backup = path.join(backups, `bchwallet-migrated-${stamp}`); - try { fs.renameSync(bchDir, backup); console.log(`[addons] retired addons/bchwallet -> addons-backups/${path.basename(backup)} (folder renamed to aegis/)`); } + try { fs.renameSync(bchDir, backup); console.log(`[addons] retired addons/bchwallet -> addons-backups/${path.basename(backup)}${fs.existsSync(aegisDir) ? " (aegis already present)" : " (folder renamed to aegis/)"}`); } catch (err) { console.warn("[addons] retire bchwallet failed:", err?.message); } } diff --git a/settings.html b/settings.html index b475427..46f5283 100644 --- a/settings.html +++ b/settings.html @@ -1219,7 +1219,13 @@ const builtInBadge = isBundled ? 'BUILT-IN' : ""; - return '
' + a.icon + ' ' + escapeHtml(a.name) + builtInBadge + ' v' + escapeHtml(a.version) + '' + caps + '
' + escapeHtml(a.description || "") + (a.author ? ' — ' + escapeHtml(a.author) + '' : '') + '
'; + // Manifest icons may be an emoji ("🛡"), a "•" fallback, or a + // data: URI to a branded SVG/PNG — render as for URIs, + // as escaped text otherwise so the emoji case keeps working. + const iconHtml = /^data:image\//i.test(a.icon || "") + ? '' + : escapeHtml(a.icon || "•"); + return '
' + iconHtml + ' ' + escapeHtml(a.name) + builtInBadge + ' v' + escapeHtml(a.version) + '' + caps + '
' + escapeHtml(a.description || "") + (a.author ? ' — ' + escapeHtml(a.author) + '' : '') + '
'; }; const sectionHeader = (label, hint) => '
' + escapeHtml(label) + '
'