// Transforms the "🔑 Sign in" nav pill on every sirius.x page into a dropdown // exposing the three wallet-onboarding options directly (New / Import / // WizardConnect). Signed-in state is read from localStorage.'siriusProfile' // (portal.html writes/clears it on sign-in / sign-out) — when present, the // menu switches to "profile" mode: address + sign-out link. // // One include line per page: // (path is absolute to silentmode.st root; the BCNR gateway serves the same URL). (() => { const NS = "silentmode.st"; const PORTAL_URL = "/sirius-x/portal.html"; // Find the .portal anchor already in the nav (the "Sign in" pill). const anchor = document.querySelector(".topnav a.portal"); if (!anchor) return; // page has no nav-portal button; nothing to do // Read profile state — portal.html sets this after successful sign-in with // { address, tokenAddress, source: "seed" | "wc" }; clears on sign-out. const readProfile = () => { try { return JSON.parse(localStorage.getItem("siriusProfile") || "null"); } catch { return null; } }; const profile = readProfile(); // Build wrapper + dropdown around the existing pill. const wrap = document.createElement("div"); wrap.className = "profile-wrap"; const btn = document.createElement("button"); btn.type = "button"; btn.className = anchor.className; // reuse .portal (and .here if present) btn.setAttribute("aria-haspopup", "menu"); btn.setAttribute("aria-expanded", "false"); btn.textContent = profile ? "🔑 " + shortAddr(profile.address) + " ▾" : "🔑 Wallet ▾"; const menu = document.createElement("div"); menu.className = "profile-menu"; menu.setAttribute("role", "menu"); menu.hidden = true; if (profile) { menu.innerHTML = `
Signed in ${escapeAttr(profile.address)}
📋 My names 🛠 Admin
🚪 Sign out `; } else { menu.innerHTML = `
Wallet onboarding
🆕 New wallet generate a fresh seed 📥 Add wallet import a seed phrase 🔗 WizardConnect Cashonize / Paytaca
🔑 Open sign-in page → `; } // Toggle + close-on-outside. const open = () => { menu.hidden = false; btn.setAttribute("aria-expanded", "true"); }; const close = () => { menu.hidden = true; btn.setAttribute("aria-expanded", "false"); }; btn.addEventListener("click", (e) => { e.stopPropagation(); menu.hidden ? open() : close(); }); document.addEventListener("click", (e) => { if (!wrap.contains(e.target)) close(); }); document.addEventListener("keydown", (e) => { if (e.key === "Escape") close(); }); // Sign-out clears localStorage and reloads (portal.html re-reads state). menu.addEventListener("click", (e) => { const t = e.target.closest("[data-action]"); if (t?.dataset.action === "signout") { e.preventDefault(); try { localStorage.removeItem("siriusProfile"); } catch {} // Also reload the current page so any signed-in UI resets. location.reload(); } }); wrap.appendChild(btn); wrap.appendChild(menu); anchor.replaceWith(wrap); // Inject the dropdown's CSS once. Kept inline so a single script tag is // the whole install; consumers don't need a matching stylesheet. if (!document.getElementById("profile-menu-css")) { const s = document.createElement("style"); s.id = "profile-menu-css"; s.textContent = ` .topnav .profile-wrap { position: relative; margin-left: auto; } .topnav .profile-wrap button.portal { cursor: pointer; font-family: inherit; } .topnav .profile-menu { position: absolute; right: 0; top: calc(100% + 6px); min-width: 240px; z-index: 30; background: rgba(20, 26, 36, .98); backdrop-filter: blur(8px); border: 1px solid rgba(255,255,255,.12); border-radius: 12px; padding: 8px; display: flex; flex-direction: column; gap: 2px; box-shadow: 0 8px 32px rgba(0,0,0,.4); } .topnav .profile-menu[hidden] { display: none; } .topnav .profile-menu > a { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: 8px; color: #e7eaf1; text-decoration: none; font-size: 14px; } .topnav .profile-menu > a:hover { background: rgba(214,255,61,.10); color: #d6ff3d; } .topnav .profile-menu .mi-hint { color: #5e6678; font-size: 11.5px; font-weight: 400; letter-spacing: 0; } .topnav .profile-menu hr { border: 0; border-top: 1px solid rgba(255,255,255,.08); margin: 4px 2px; } .topnav .profile-menu .profile-header { padding: 6px 10px 10px; display: flex; flex-direction: column; gap: 4px; border-bottom: 1px solid rgba(255,255,255,.08); margin-bottom: 4px; } .topnav .profile-menu .profile-hint { color: #8b98a9; font-size: 11px; text-transform: uppercase; letter-spacing: .4px; } .topnav .profile-menu code { font-family: ui-monospace, monospace; font-size: 11.5px; color: #e7eaf1; word-break: break-all; background: transparent; } `; document.head.appendChild(s); } // ---------- helpers ---------- function shortAddr(a) { if (!a) return "wallet"; const i = a.indexOf(":"); const body = i > 0 ? a.slice(i + 1) : a; return body.slice(0, 6) + "…" + body.slice(-4); } function escapeAttr(s) { return String(s).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", "\"": """, "'": "'" }[c])); } })();