diff --git a/bundled-addons/aegis/addon.json b/bundled-addons/aegis/addon.json
index 5837e7e4..9a4980b7 100644
--- a/bundled-addons/aegis/addon.json
+++ b/bundled-addons/aegis/addon.json
@@ -1,17 +1,29 @@
{
"id": "aegis",
"name": "Aegis Wallet",
- "version": "0.11.0",
+ "version": "0.12.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",
"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",
"updateURL": "https://navigate.st/bns/theseus.x/extensions/aegis/updates.json",
- "capabilities": ["sidebar-panel", "vault-derive", "page-inject", "approval-modal", "scan-page"],
- "absorbs": ["bchwallet", "siawallet"],
+ "capabilities": [
+ "sidebar-panel",
+ "vault-derive",
+ "page-inject",
+ "approval-modal",
+ "scan-page",
+ "open-tab"
+ ],
+ "absorbs": [
+ "bchwallet",
+ "siawallet"
+ ],
"page-inject": {
"preload": "wallet-inject.js",
- "origins": ["https://*/*"]
+ "origins": [
+ "https://*/*"
+ ]
}
}
diff --git a/bundled-addons/aegis/index.js b/bundled-addons/aegis/index.js
index cc9bd7a5..bd95eb1e 100644
--- a/bundled-addons/aegis/index.js
+++ b/bundled-addons/aegis/index.js
@@ -1598,6 +1598,20 @@ function registerPanelMessages(api) {
return { entry, rt };
}
+ // Open the wallet as a full Theseus tab. It loads panel.html — the very
+ // same file the sidebar uses — with ?surface=web, because an add-on's own
+ // tab is handed the same window.silentmode surface and main dispatches it
+ // as from:"panel". So this is a re-layout, not a second wallet: one set of
+ // handlers, one UI, no drift between the two.
+ api.onMessage("openFullScreen", (_p, m) => {
+ fromPanel(m);
+ if (typeof api.openTab !== "function") {
+ throw new Error("This Theseus build can't open add-on tabs — update Theseus.");
+ }
+ api.openTab("panel.html", { query: { surface: "web" } });
+ return true;
+ });
+
api.onMessage("promotePreview", async (p, m) => {
fromPanel(m);
const { entry, rt } = promotableImport(p && p.walletId);
diff --git a/bundled-addons/aegis/panel.html b/bundled-addons/aegis/panel.html
index dba704de..6c70ab3c 100644
--- a/bundled-addons/aegis/panel.html
+++ b/bundled-addons/aegis/panel.html
@@ -202,6 +202,58 @@
nav button.on { background: var(--acid); color: #0b0f08; font-weight: 650; }
nav button:hover:not(.on) { background: rgb(from var(--ink) r g b / .08); color: var(--ink); }
main { flex: 1; overflow: auto; padding: 14px; }
+
+ /* ---- full-screen surface (?surface=web) -------------------------------
+ The same panel.html, opened as a Theseus tab through the "open-tab"
+ capability. Nothing is duplicated: an add-on's own tab gets a
+ window.silentmode with the SAME invoke/on surface as the sidebar, and
+ main dispatches it as from:"panel", so panel.js runs here unchanged and
+ this is purely a re-layout.
+
+ The sidebar becomes a left rail — identity, network, balance, section
+ nav and the wallet list, in the order they already appear — and the
+ tab body gets the rest of the window. Everything below only applies
+ when the surface flag is set, so the 380px panel is untouched. */
+ :root[data-surface="web"] body {
+ display: grid;
+ grid-template-columns: 340px minmax(0, 1fr);
+ grid-template-rows: auto auto minmax(0, 1fr) auto;
+ grid-template-areas: "head main" "nav main" "strip main" "foot main";
+ height: 100vh; overflow: hidden;
+ }
+ :root[data-surface="web"] header { grid-area: head; }
+ :root[data-surface="web"] nav { grid-area: nav; }
+ :root[data-surface="web"] .wstrip{ grid-area: strip; max-height: none; }
+ :root[data-surface="web"] .brandfoot { grid-area: foot; position: static; }
+ :root[data-surface="web"] main {
+ grid-area: main; padding: 22px 26px 40px;
+ border-left: 1px solid var(--line); background: var(--bg);
+ }
+ /* Forms and lists stop stretching into unreadable line lengths on a wide
+ monitor; the column keeps the measure the sidebar already tuned for. */
+ :root[data-surface="web"] main > #tabs,
+ :root[data-surface="web"] main > .gate { max-width: 720px; }
+ /* The picker sheet is fixed-position and sized for a 380px panel. Pin it
+ to the rail instead of letting it cover the whole window. */
+ :root[data-surface="web"] #drop { right: auto; width: 340px; bottom: 34px; }
+ /* The lock screen still owns the whole window — a locked vault should not
+ look like a half-usable app. */
+ :root[data-surface="web"] #lockScreen { inset: 0; }
+ @media (max-width: 900px) {
+ /* Narrow window: fall back to the stacked sidebar layout. */
+ :root[data-surface="web"] body {
+ display: flex; flex-direction: column; height: auto; overflow: visible;
+ }
+ :root[data-surface="web"] main { border-left: 0; padding: 14px; }
+ :root[data-surface="web"] #drop { right: 0; width: auto; }
+ }
+ /* The QR is drag-sized against the 380px sidebar and its size is
+ remembered. Given a 720px column it stretches to fill and dominates the
+ page, so cap it here rather than touching the stored size — the user's
+ sidebar preference stays exactly as they left it. */
+ :root[data-surface="web"] .qrwrap { max-width: 320px; }
+ /* "Open full screen" chip — hidden once we ARE the full-screen surface. */
+ :root[data-surface="web"] #hFull { display: none; }
/* Persistent aegis.x brand strip. Sticks to the panel's bottom edge so the
wallet always advertises its own front-door site — helps users bookmark
it, and doubles as a version marker for support triage. */
@@ -659,6 +711,7 @@
Create new / Import / Connect / About — replacing the old
three-chip cluster (+ ⋯ ✎). Method chosen there routes into
the coin picker inside #drop or an appropriate modal. -->
+
diff --git a/bundled-addons/aegis/panel.js b/bundled-addons/aegis/panel.js
index 90a300fe..ec88edac 100644
--- a/bundled-addons/aegis/panel.js
+++ b/bundled-addons/aegis/panel.js
@@ -3,6 +3,16 @@
// input; it never touches keys or the vault.
const $ = (id) => document.getElementById(id);
const S = window.silentmode;
+
+// Which surface is this? The sidebar panel and the full-screen tab are the
+// SAME file — an add-on's own tab is handed a window.silentmode with the
+// same invoke/on surface, and main dispatches it as from:"panel", so
+// everything below works identically in both. The flag only drives layout.
+const SURFACE = (function () {
+ try { return new URL(location.href).searchParams.get("surface") || "panel"; }
+ catch (e) { return "panel"; }
+})();
+if (SURFACE === "web") document.documentElement.dataset.surface = "web";
let state = null; // full state (all wallets + selected)
let tab = "receive";
let unit = null; // "big" | "small" — chain-dependent
@@ -454,6 +464,13 @@ $("pickerBtn").addEventListener("click", (e) => {
// 0.8.4: separate netchip row. Click jumps straight to the browse:chain
// view for the current wallet's chain — the network-chip strip at the
// top of that view is what actually switches networks.
+// Open the same wallet as a full Theseus tab. CSS hides this chip on the
+// full-screen surface, so it never offers to open a second copy of itself.
+$("hFull") && $("hFull").addEventListener("click", async (e) => {
+ e.stopPropagation();
+ try { await S.invoke("openFullScreen"); }
+ catch (err) { showErr(cleanErr(err)); }
+});
$("hNet").addEventListener("click", (e) => {
e.stopPropagation();
const w = (state?.wallets || []).find((x) => x.id === state?.selectedWalletId);