Final pre-launch version: Update logic

This commit is contained in:
Andy Dixon
2026-04-28 09:35:53 +01:00
parent 5699d17fb6
commit c656d2ff44
13 changed files with 392 additions and 21 deletions
+3
View File
@@ -269,6 +269,9 @@
<span id="status-protocol"></span>
<span id="status-session-count">0 sessions</span>
<span class="status-spacer"></span>
<button class="status-update is-hidden" id="status-update" type="button">
Update available
</button>
<span id="status-vault">🔒 Locked</span>
</footer>
</div>
+21
View File
@@ -125,6 +125,27 @@
flex: 1;
}
.status-update {
border: 1px solid var(--accent);
background: rgba(78, 205, 196, 0.12);
color: var(--accent);
font-size: var(--text-xs);
padding: 2px 8px;
border-radius: 999px;
cursor: pointer;
transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}
.status-update:hover {
background: rgba(78, 205, 196, 0.2);
color: var(--text-primary);
border-color: var(--accent-strong, var(--accent));
}
.status-update.is-hidden {
display: none;
}
/* Status bar indicator dots */
.status-bar .status-dot {
width: 6px;
+52
View File
@@ -40,6 +40,7 @@
this.exportImport = new ExportImportUI(this);
this.sftp = new SFTPBrowser(this);
this.snippets = new SnippetLibrary(this);
this.updateInfo = null;
}
/**
@@ -61,6 +62,7 @@
await this.loadPreferences();
await this.checkSecretStore();
this.updateStatusBar();
this.checkForUpdates(true);
}
/**
@@ -254,6 +256,11 @@
);
});
// App-wide commands from the native menu
window.runtime.EventsOn("app:open-about", () => {
this.settings.openTab("about");
});
// Port-forwarding events
window.runtime.EventsOn("session:forward:started", (payload) => {
const fwd = payload.forward || {};
@@ -503,6 +510,12 @@
this._bindClick("btn-empty-connect", () => this.profileEditor.openNew());
this._bindClick("btn-empty-quick", () => this.quickConnect());
const updateBtn = document.getElementById("status-update");
if (updateBtn) {
updateBtn.addEventListener("mousedown", (e) => e.preventDefault());
updateBtn.addEventListener("click", () => this.settings.openTab("about"));
}
const searchInput = document.getElementById("profile-search");
if (searchInput) {
searchInput.addEventListener("input", (e) =>
@@ -851,6 +864,7 @@
const connEl = document.getElementById("status-connection");
const countEl = document.getElementById("status-session-count");
const vaultEl = document.getElementById("status-vault");
const updateEl = document.getElementById("status-update");
if (!connEl) return;
const sessions = this.state.getAllSessions();
@@ -874,6 +888,44 @@
? "🔓 Unlocked"
: "🔒 Locked";
}
if (updateEl) {
if (this.updateInfo && this.updateInfo.available) {
const version = this.updateInfo.latestVersion
? ` (${this.updateInfo.latestVersion})`
: "";
updateEl.textContent = `Update available${version}`;
updateEl.classList.remove("is-hidden");
} else {
updateEl.textContent = "Update available";
updateEl.classList.add("is-hidden");
}
}
}
async checkForUpdates(silent) {
if (!window.go || !window.go.api || !window.go.api.Service) {
return;
}
try {
const info = await window.go.api.Service.CheckForUpdates();
this.setUpdateInfo(info);
if (!silent && info && info.available) {
this.notifications.info(
`Update available: ${info.latestVersion || "new version"}`,
);
}
} catch (err) {
if (!silent) {
this.notifications.error("Update check failed: " + err);
}
}
}
setUpdateInfo(info) {
this.updateInfo = info || null;
this.updateStatusBar();
}
// ── Internal helpers ─────────────────────────────────────────────
+20 -1
View File
@@ -848,7 +848,7 @@
body.innerHTML = `
<div class="about-section">
<h3 class="about-title">Nexus Terminal</h3>
<p class="about-version">Version 1.0.0</p>
<p class="about-version" data-role="app-version">Version …</p>
<p class="about-desc">Developed by Andy Dixon - www.dixon.cx/nexus</p>
<div class="about-links">
<p>AES-256-GCM encrypted credential vault</p>
@@ -864,6 +864,22 @@
</div>
`;
const versionEl = body.querySelector("[data-role='app-version']");
if (versionEl) {
if (window.go && window.go.api && window.go.api.Service) {
window.go.api.Service.GetAppInfo()
.then((info) => {
const version = (info && info.version) || "dev";
versionEl.textContent = `Version ${version}`;
})
.catch(() => {
versionEl.textContent = "Version unavailable";
});
} else {
versionEl.textContent = "Version unavailable";
}
}
const updateBtn = body.querySelector("#settings-check-update");
if (updateBtn) {
updateBtn.addEventListener("click", async () => {
@@ -872,6 +888,9 @@
try {
const info = await window.go.api.Service.CheckForUpdates();
const resultEl = body.querySelector("#settings-update-result");
if (this.app && typeof this.app.setUpdateInfo === "function") {
this.app.setUpdateInfo(info);
}
if (info.available) {
resultEl.innerHTML =
`<span style="color:var(--accent)">Update available: <strong>${info.latestVersion}</strong></span>` +