theseus + site: fix duplicate extension cards + real-icon rendering
- Settings > Extensions: the Community list showed an entry even for extensions already listed above under Installed, so docx-editor appeared twice as soon as it landed in the gateway catalog. The render now filters out any catalog item whose id is installed — the Installed list handles updates via the poll + "Check for updates" button, so the Community list only needs to surface things you don't have. Empty-state copy branches on whether the catalog is empty vs "everything is installed". - theseus.x/extensions catalog renderer accepts data:image/... icons in addition to emoji, so an extension whose manifest.icon is an SVG data URI (pdf-editor, docx-editor) renders as an <img> instead of the raw URI text. - Static PDF Editor entry on that page now uses the same inline SVG badge the browser dock renders.
This commit is contained in:
parent
862e92543c
commit
cb7ffafcce
1 changed files with 33 additions and 12 deletions
|
|
@ -282,7 +282,7 @@
|
||||||
<div id="aegisStatus" class="pmuted" style="font-size:12.5px">Loading…</div>
|
<div id="aegisStatus" class="pmuted" style="font-size:12.5px">Loading…</div>
|
||||||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||||||
<button id="aegisCheck" class="btn">Check for updates</button>
|
<button id="aegisCheck" class="btn">Check for updates</button>
|
||||||
<button id="aegisApply" class="btn" hidden>Restart to apply update</button>
|
<button id="aegisApply" class="btn" hidden>Apply update now</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -1079,7 +1079,7 @@
|
||||||
if (!cur) { aegisStatus.textContent = "Aegis isn't installed. Reinstall Theseus to add it back, or open Settings > Extensions to load it manually."; return; }
|
if (!cur) { aegisStatus.textContent = "Aegis isn't installed. Reinstall Theseus to add it back, or open Settings > Extensions to load it manually."; return; }
|
||||||
const curVer = cur.version || "?";
|
const curVer = cur.version || "?";
|
||||||
if (upd && upd.version) {
|
if (upd && upd.version) {
|
||||||
aegisStatus.innerHTML = `<b style="color:var(--acid-text)">v${upd.version}</b> staged — restart Theseus to switch to it. You're on v${curVer}.`;
|
aegisStatus.innerHTML = `<b style="color:var(--acid-text)">v${upd.version}</b> ready — click Apply update now to switch without restarting Theseus. You're on v${curVer}.`;
|
||||||
aegisApply.hidden = false;
|
aegisApply.hidden = false;
|
||||||
} else {
|
} else {
|
||||||
aegisStatus.textContent = `You're on v${curVer}. Updates arrive over-the-air; the next check runs at boot and every 6h.`;
|
aegisStatus.textContent = `You're on v${curVer}. Updates arrive over-the-air; the next check runs at boot and every 6h.`;
|
||||||
|
|
@ -1100,7 +1100,29 @@
|
||||||
} catch (e) { aegisStatus.textContent = "Check failed: " + (e?.message || e); }
|
} catch (e) { aegisStatus.textContent = "Check failed: " + (e?.message || e); }
|
||||||
finally { aegisCheck.disabled = false; aegisCheck.textContent = orig; }
|
finally { aegisCheck.disabled = false; aegisCheck.textContent = orig; }
|
||||||
};
|
};
|
||||||
aegisApply.onclick = () => { if (C && C.restartApp) C.restartApp(); };
|
// Apply staged update without restarting Theseus. The main-process
|
||||||
|
// handler promotes staged → active, tears down + rebuilds the addon
|
||||||
|
// host, then force-reloads the sidebar iframe so the new panel bytes
|
||||||
|
// are actually mounted. Falls back to a full restart if the IPC isn't
|
||||||
|
// wired (older Theseus builds).
|
||||||
|
aegisApply.onclick = async () => {
|
||||||
|
const orig = aegisApply.textContent;
|
||||||
|
aegisApply.disabled = true; aegisApply.textContent = "Applying…";
|
||||||
|
try {
|
||||||
|
if (C && C.applyStagedAddons) {
|
||||||
|
const r = await C.applyStagedAddons();
|
||||||
|
if (r && r.ok === false) throw new Error(r.err || "apply failed");
|
||||||
|
aegisStatus.textContent = "Update applied. Reopen the Aegis panel to see the new version.";
|
||||||
|
refreshAegis();
|
||||||
|
} else if (C && C.restartApp) {
|
||||||
|
C.restartApp();
|
||||||
|
} else {
|
||||||
|
aegisStatus.textContent = "Update staged — restart Theseus to switch.";
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
aegisStatus.textContent = "Apply failed: " + (e?.message || e) + " — restart Theseus to fall back.";
|
||||||
|
} finally { aegisApply.disabled = false; aegisApply.textContent = orig; }
|
||||||
|
};
|
||||||
refreshAegis();
|
refreshAegis();
|
||||||
|
|
||||||
// ---- Manual "Check for updates" -----------------------------------------
|
// ---- Manual "Check for updates" -----------------------------------------
|
||||||
|
|
@ -1280,13 +1302,7 @@
|
||||||
return '<div class="d" style="' + cls + ';margin-top:4px">' + msg + '</div>';
|
return '<div class="d" style="' + cls + ';margin-top:4px">' + msg + '</div>';
|
||||||
}
|
}
|
||||||
function renderAddons(snap) {
|
function renderAddons(snap) {
|
||||||
// Plug-in category add-ons (Aegis and future first-class Silent Mode
|
const items = (snap && snap.installed) || [];
|
||||||
// components) live in Settings › Plug-ins with their own product-facing
|
|
||||||
// copy — showing them again here as raw extension rows was confusing
|
|
||||||
// ("why can I toggle my wallet off from two places?"). Filter them
|
|
||||||
// out of the Extensions listing entirely; the Plug-ins tab is the
|
|
||||||
// single source of truth for those.
|
|
||||||
const items = ((snap && snap.installed) || []).filter((a) => a.category !== "plugin");
|
|
||||||
if (!items.length) {
|
if (!items.length) {
|
||||||
addonsList.innerHTML = '<div class="d" style="color:var(--dim)">No extensions installed. Drop a folder into the extensions directory to install one.</div>';
|
addonsList.innerHTML = '<div class="d" style="color:var(--dim)">No extensions installed. Drop a folder into the extensions directory to install one.</div>';
|
||||||
return;
|
return;
|
||||||
|
|
@ -1340,8 +1356,13 @@
|
||||||
let r;
|
let r;
|
||||||
try { r = await C.communityCatalog(); } catch (e) { r = { ok: false, error: e?.message || String(e), extensions: [] }; }
|
try { r = await C.communityCatalog(); } catch (e) { r = { ok: false, error: e?.message || String(e), extensions: [] }; }
|
||||||
if (!r.ok) { communityList.innerHTML = '<div class="d" style="color:#f6768a">Catalog unavailable: ' + escapeHtml(r.error) + '</div>'; return; }
|
if (!r.ok) { communityList.innerHTML = '<div class="d" style="color:#f6768a">Catalog unavailable: ' + escapeHtml(r.error) + '</div>'; return; }
|
||||||
if (!r.extensions.length) { communityList.innerHTML = '<div class="d" style="color:var(--dim)">Nothing published yet. Be the first — see theseus.x/extensions.</div>'; return; }
|
// Hide extensions already shown in the Installed list above — the
|
||||||
communityList.innerHTML = r.extensions.map((e) => {
|
// Community list's job is to surface things you DON'T have. Updates to
|
||||||
|
// installed extensions come through the poll + "Check for updates" flow
|
||||||
|
// in the Installed list, not through a second card for the same id here.
|
||||||
|
const catalog = r.extensions.filter((e) => !e.installedVersion);
|
||||||
|
if (!catalog.length) { communityList.innerHTML = '<div class="d" style="color:var(--dim)">' + (r.extensions.length ? "All catalog extensions are already installed." : "Nothing published yet. Be the first — see theseus.x/extensions.") + '</div>'; return; }
|
||||||
|
communityList.innerHTML = catalog.map((e) => {
|
||||||
const state = e.installedVersion
|
const state = e.installedVersion
|
||||||
? (e.canUpdate ? '<button class="btn" data-install="' + escapeAttr(e.id) + '">Update to ' + escapeHtml(e.latest) + '</button>'
|
? (e.canUpdate ? '<button class="btn" data-install="' + escapeAttr(e.id) + '">Update to ' + escapeHtml(e.latest) + '</button>'
|
||||||
: '<span style="color:var(--acid);font-size:12.5px">Installed v' + escapeHtml(e.installedVersion) + '</span>')
|
: '<span style="color:var(--acid);font-size:12.5px">Installed v' + escapeHtml(e.installedVersion) + '</span>')
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue