diff --git a/chrome.html b/chrome.html
index 3bb2da43..1994c0e5 100644
--- a/chrome.html
+++ b/chrome.html
@@ -905,11 +905,19 @@
lastButtons.push({ kind: "menu", key: "m:" + m.addonId, addonId: m.addonId, icon: String(m.icon || "•"), title: m.title || m.addonId, items: m.items || [] });
}
// User prefs: drag-reorder order and buttons hidden via the right-click
- // menu. Unknown keys keep registration order after the ordered ones.
+ // menu. Unknown keys keep registration order after the ordered ones; the
+ // document editors sort LAST so smaller utilities (Notepad, Screenshot,
+ // Translate…) stay near the start of the strip.
if (d.dock) lastDock = d.dock;
const order = Array.isArray(lastDock.order) ? lastDock.order : [];
const hidden = new Set(Array.isArray(lastDock.hidden) ? lastDock.hidden : []);
- const rank = (k) => { const i = order.indexOf(k); return i < 0 ? order.length : i; };
+ const LAST_ADDON_IDS = new Set(["docx-editor", "pdf-editor"]);
+ const addonIdOf = (k) => k.startsWith("p:") ? k.slice(2).split(":")[0] : k.slice(2);
+ const rank = (k) => {
+ const i = order.indexOf(k);
+ if (i >= 0) return i;
+ return LAST_ADDON_IDS.has(addonIdOf(k)) ? order.length + 1 : order.length;
+ };
lastButtons = lastButtons.filter((b) => !hidden.has(b.key)).map((b, i) => ({ ...b, i })).sort((a, b) => rank(a.key) - rank(b.key) || a.i - b.i);
lastPanels = lastPanels.filter((p) => !hidden.has("p:" + p.panelId));
lastMenus = lastMenus.filter((m) => !hidden.has("m:" + m.addonId));
diff --git a/package.json b/package.json
index abdf5df2..2ef56bf1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "theseus-navigator",
- "version": "0.3.121",
+ "version": "0.3.122",
"license": "MPL-2.0",
"description": "Theseus Navigator — a browser that follows the thread. By Silent Mode, a Deviant project.",
"author": "Silent Mode",
diff --git a/settings.html b/settings.html
index debee010..020fbd61 100644
--- a/settings.html
+++ b/settings.html
@@ -313,16 +313,17 @@
@@ -330,20 +331,47 @@
General
Changes apply immediately and are saved for next time.
-
Startup
+
+
+
+
Make Theseus the default browser
+
Register Theseus for http and https links. Windows still asks you to confirm the switch in Settings › Default apps; the button opens that page.
+
+
+
+
+
+
+
Show "Open with Theseus" in file menus
+
Right-click an .html, .htm, .pdf, .svg or .xhtml file and Theseus appears in the Open-with menu. Theseus opens it as a local-file tab.
+
+
+
+
+
+
+
Theseus Shield ›
+
Click to open its own settings. Blocks third-party trackers and ads on every site.
+
+
+
+
-
Open previous windows and tabs
Restore the tabs from your last session when Theseus starts, even when history is cleared on quit.
+
Startup
Restore the tabs from your last session when Theseus starts.
-
-
-
Updates
-
Theseus checks the release manifest shortly after launch — and retries with backoff if that first attempt is offline — then every 6 hours while it is running. Click below to check right now.
-
-
Loading…
-
-
-
+
+
+
Updates
Loading…
+
+
+
+
+
Theseus ID
Your Silent Mode account, kept in your Theseus Vault.
+ ›
Appearance
Choose a theme for the browser. System follows your operating system's light/dark setting.
@@ -400,22 +428,6 @@
-
Default handling
-
-
-
Make Theseus the default browser
-
Register Theseus for http and https links. Windows still asks you to confirm the switch in Settings › Default apps; the button opens that page.
-
-
-
-
-
-
-
Show "Open with Theseus" in file menus
-
Right-click an .html, .htm, .pdf, .svg or .xhtml file and Theseus appears in the Open-with menu. Theseus opens it as a local-file tab.
-
-
-
About
Theseus Navigator is free software
@@ -486,14 +498,6 @@
Name resolvers
-
-
-
Bitcoin Cash Name System (BNS)
-
.x, .bch, .sia, .coin, .dgb, and the rest of the seeded TLDs. Powered by Ariadne's Thread.
-
-
-
-
Ethereum Name Service (ENS)
@@ -599,38 +603,69 @@
Plug-ins
-
Silent Mode components that live alongside Theseus — each with its own on/off, updates and settings page.
+
Silent Mode components that live alongside Theseus — each with its own on/off, updates and settings page. Ariadne's Thread and Aegis now have their own entries in the sidebar.
Resolves BCDN names for every browser on this machine — not just Theseus.
-
checking…
-
-
-
-
-
-
-
+
+
Ariadne's Thread
System-wide BCDN resolver.
+ ›
+
+
Aegis
Built-in multi-chain wallet.
+ ›
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
Aegis — built-in wallet›
-
Multi-chain wallet (BCH, BTC, TRX, ETH, SOL, SC, DGB). Ships in the box, updates over-the-air.
-
loading…
+
+
+
Ariadne's Thread
+
A local daemon that resolves BCDN names for every browser on this machine, not just Theseus. Theseus has its own built-in resolver either way; this plug-in is for Chrome, Edge, Firefox and the rest.
+
+
+
Open Ariadne's Thread settings
+
Install, update, uninstall; collision policy, sources and the live status report.
-
-
-
+ ›
+
+
+
+
+
+
Aegis
+
Multi-chain wallet (BCH, BTC, TRX, ETH, SOL, SC, DGB) that ships with Theseus and updates over-the-air.
+
+
+
Open the Aegis wallet
+
Opens Aegis in the sidebar panel beside the page.
+ ›
+
+
+
+
Aegis plug-in settings
+
Version, updates and Apply update now.
+
+ ›
@@ -1130,7 +1165,17 @@
The sparkle button at the bottom of the strip opens your default AI engine (right-click it to pick from any you've enabled, or set up more under Search).
-
Web apps
+
+
Theseus native apps
+
System apps bundled with Theseus. They open from the sidebar strip.
+
+
+
+
+
Third-party apps
Sites that open in the panel. Switch one off to take it off the strip; it stays here, still signed in, for switching back on. A site you installed as an app can be added from Apps.
@@ -1141,7 +1186,7 @@
Extension panels
-
Extensions that open from the strip. Switch one off to take it off the strip; the extension keeps working.
+
Extensions that open from the strip. Switch one off to take it off the strip; the extension keeps working. The native apps above live under their own card.
@@ -1240,7 +1285,7 @@
try {
if (C && typeof C.appVersion === "function") {
C.appVersion().then((v) => {
- updStatus.textContent = v ? `You're on v${v}.` : "Version unavailable — try Check for updates.";
+ updStatus.textContent = v ? `Theseus current version v${v}.` : "Version unavailable — try Check for updates.";
}).catch((e) => {
updStatus.textContent = "Could not read version: " + (e?.message || e) + " — try Check for updates.";
});
@@ -1272,7 +1317,6 @@
(async () => {
const row = document.getElementById("defaultBrowserRow");
const assocRow = document.getElementById("fileAssocsRow");
- const head = document.getElementById("defHandlingHead");
const defBrowser = document.getElementById("defaultBrowser");
const assoc = document.getElementById("fileAssocs");
const openSys = document.getElementById("openSysDefaults");
@@ -1280,7 +1324,7 @@
try {
const d = await cfg.defaultBrowserState();
if (!d.supported) return;
- head.hidden = false; row.hidden = false; assocRow.hidden = false;
+ row.hidden = false; assocRow.hidden = false;
defBrowser.checked = !!d.isDefault;
assoc.checked = !!d.hasAssocs;
} catch {}
@@ -1301,6 +1345,51 @@
openSys.addEventListener("click", () => cfg.openSystemDefaults());
refresh();
})();
+ // General › Theseus Shield row — chevron opens the Shield add-on's panel;
+ // toggle flips the blocker on/off. State comes from listAddons().
+ (function () {
+ const openEl = document.getElementById("generalShieldOpen");
+ const onEl = document.getElementById("generalShieldOn");
+ if (!openEl || !onEl) return;
+ const openShield = () => {
+ // Prefer the add-on's own panel; fall back to the Extensions page.
+ if (C && typeof C.openPanel === "function") {
+ try { C.openPanel("blocker:main"); return; } catch {}
+ }
+ try { showSection("addons"); } catch {}
+ };
+ openEl.addEventListener("click", openShield);
+ openEl.addEventListener("keydown", (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); openShield(); } });
+ async function refresh() {
+ try {
+ const list = await (C.listAddons ? C.listAddons() : Promise.resolve({}));
+ const blocker = ((list && list.installed) || []).find((a) => a.id === "blocker");
+ onEl.checked = !!(blocker && blocker.enabled);
+ } catch {}
+ }
+ onEl.addEventListener("change", async () => {
+ try { if (C.setAddonEnabled) await C.setAddonEnabled("blocker", onEl.checked); } catch {}
+ // Give the host a moment to flip, then refresh so the toggle shows the
+ // real state (an add-on that refused the flip stays as it was).
+ setTimeout(refresh, 400);
+ });
+ refresh();
+ document.addEventListener("section", (e) => { if (e.detail === "general") refresh(); });
+ })();
+ // Aegis landing-section chevron — opens Aegis's own sidebar panel. Falls
+ // back to the plug-in sub-page if the panel isn't registered.
+ (function () {
+ const row = document.getElementById("aegisOpenRow");
+ if (!row) return;
+ row.addEventListener("click", async (e) => {
+ // The row's own data-go would route to Settings, not the Aegis panel.
+ e.preventDefault(); e.stopPropagation();
+ if (C && typeof C.openPanel === "function") {
+ try { await C.openPanel("aegis:main"); return; } catch {}
+ }
+ try { showSection("plugins/aegis"); } catch {}
+ });
+ })();
// sidebar navigation
// "naming" is intentionally absent: the Registries section was folded
// into General in 0.3.21. Leaving the id in this list threw a
@@ -1672,26 +1761,47 @@
if (C.onSettingsUpdate) C.onSettingsUpdate((next) => { cur = next; render(next.quickLinks || []); });
})();
// ---- Extension panels on the strip (Sidebar) ---------------------------
+ // Two cards: native apps (Hermes + Pithos) are rendered into #sbNativeApps,
+ // every other left panel into #sbPanels. The native-id test matches a
+ // panel.id of the form "p::" (what sidebar-left-panels
+ // returns), so hermes:main / pithos:main land in the native card.
(function () {
+ const nativeBox = document.getElementById("sbNativeApps");
const box = document.getElementById("sbPanels");
- if (!box || !C.sidebarLeftPanels) return;
+ if ((!nativeBox && !box) || !C.sidebarLeftPanels) return;
const esc = (v) => String(v || "").replace(/[&<>"']/g, (c) => ({ "&":"&","<":"<",">":">","\"":""","'":"'" })[c]);
+ const NATIVE_IDS = new Set(["hermes", "pithos"]);
+ const addonOf = (pid) => String(pid || "").replace(/^p:/, "").split(":")[0];
+ const isNative = (p) => NATIVE_IDS.has(addonOf(p.id));
let cur = s;
+ function rowHtml(p, widths, B) {
+ const icon = /^data:image\//.test(p.icon) ? `` : esc(p.icon || (p.title || "?").slice(0, 1));
+ return `
+
${icon}
+
${esc(p.title)}
${p.hidden ? "Off the strip" : "On the strip"}${widths[p.id] ? " · " + Number(widths[p.id]) + " px" : ""}
`;
+ if (B) B.wireOnStrip(nativeBox);
+ if (window.__sbWireWidth) window.__sbWireWidth(nativeBox);
+ }
+ if (box) {
+ box.innerHTML = rest.length
+ ? rest.map((p) => rowHtml(p, widths, B)).join("")
+ : `
No extension opens from the strip.
`;
+ if (B) B.wireOnStrip(box);
+ if (window.__sbWireWidth) window.__sbWireWidth(box);
+ }
}
render();
document.addEventListener("section", (e) => { if (String(e.detail) === "sidebar") render(); });
@@ -3048,10 +3158,26 @@
"session-proxy": "Can route the browser's traffic through a proxy it controls.",
"tab-control": "Can open, read and operate your web tabs for a program on this computer that you connect to it, on sites you approve one by one.",
};
+ // Extensions list ordering rules:
+ // HIDDEN_IDS — Hermes and Pithos are Theseus native apps; they appear in
+ // the Sidebar settings card instead of here.
+ // LAST_IDS — docx-editor and pdf-editor sort last within each group so
+ // the smaller utilities (Notepad, Screenshot, Translate, …)
+ // stay near the top of the list.
+ const ADDONS_HIDDEN_IDS = new Set(["hermes", "pithos"]);
+ const ADDONS_LAST_IDS = ["docx-editor", "pdf-editor"];
+ function addonSortLast(a, b) {
+ const ai = ADDONS_LAST_IDS.indexOf(a.id);
+ const bi = ADDONS_LAST_IDS.indexOf(b.id);
+ const ar = ai < 0 ? -1 : ai;
+ const br = bi < 0 ? -1 : bi;
+ return ar - br;
+ }
function renderAddons(snap) {
lastAddonSnap = snap;
// Plug-ins (Aegis, category "plugin") have their own cards under Plug-ins.
- const items = ((snap && snap.installed) || []).filter((a) => a.category !== "plugin");
+ const items = ((snap && snap.installed) || [])
+ .filter((a) => a.category !== "plugin" && !ADDONS_HIDDEN_IDS.has(a.id));
if (!items.length) {
addonsList.innerHTML = '
No extensions installed. Install one from theseus.x/extensions, or drop a folder into the extensions directory.
';
return;
@@ -3071,8 +3197,10 @@
+ ''
+ '
';
};
- const enabled = items.filter((a) => !a.error && a.enabled);
- const disabled = items.filter((a) => !a.error && !a.enabled);
+ // Stable sort inside each bucket keeps registration order; the compare
+ // only moves ADDONS_LAST_IDS to the end of their bucket.
+ const enabled = items.filter((a) => !a.error && a.enabled).sort(addonSortLast);
+ const disabled = items.filter((a) => !a.error && !a.enabled).sort(addonSortLast);
const failed = items.filter((a) => a.error);
let html = "";
if (enabled.length) html += '