From 436a00905904b108bb00de40a28e2992eeb79ddf Mon Sep 17 00:00:00 2001 From: roberts Date: Sat, 14 Mar 2026 21:49:37 -0500 Subject: [PATCH] Update panel: always show version status (up-to-date or update available) Replace dismissable toast with persistent status row showing a green dot + "Up to date" with commit hash, or amber dot + "Update available" with an inline Install button. One or the other is always visible. Co-Authored-By: Claude Opus 4.6 --- frontend/css/panel.css | 76 ++++++++++++++++++++---------------------- frontend/js/atlus.js | 49 +++++++++++++++------------ 2 files changed, 65 insertions(+), 60 deletions(-) diff --git a/frontend/css/panel.css b/frontend/css/panel.css index def26b3..7081453 100644 --- a/frontend/css/panel.css +++ b/frontend/css/panel.css @@ -213,74 +213,72 @@ color: var(--accent); } -/* Update toast */ +/* Update status */ .panel-updates { transition: all var(--transition-base); } -.update-toast { - position: relative; - padding: 12px; - background: var(--accent-dim); - border-left: 3px solid var(--accent); - border-radius: 0 var(--radius-sm) var(--radius-sm) 0; -} - -.update-dismiss { - position: absolute; - top: 4px; - right: 4px; - width: 24px; - height: 24px; - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - font-size: 14px; +.update-status { display: flex; align-items: center; - justify-content: center; - border-radius: var(--radius-sm); + gap: 10px; } -.update-dismiss:hover { - background: var(--accent-hover); - color: var(--text-primary); +.update-status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + flex-shrink: 0; } -.update-toast-title { +.update-status-dot.current { + background: var(--status-green); +} + +.update-status-dot.available { + background: var(--status-amber); +} + +.update-status-title { font-family: var(--font-ui); - font-size: 13px; + font-size: 12px; font-weight: 500; - color: var(--accent); - margin-bottom: 4px; + color: var(--text-primary); + line-height: 1.2; } -.update-toast-info { +.update-status-hash { font-family: var(--font-mono); - font-size: 11px; - color: var(--text-secondary); - margin-bottom: 10px; + font-size: 10px; + color: var(--text-muted); + line-height: 1.3; } -.update-toast-btn { - width: 100%; - height: 30px; +.update-status-text { + flex: 1; + min-width: 0; +} + +.update-install-btn { + flex-shrink: 0; + height: 26px; + padding: 0 12px; background: var(--accent); border: none; border-radius: var(--radius-sm); color: #fff; font-family: var(--font-ui); - font-size: 12px; + font-size: 11px; font-weight: 500; cursor: pointer; + white-space: nowrap; } -.update-toast-btn:hover { +.update-install-btn:hover { opacity: 0.9; } -.update-toast-btn:disabled { +.update-install-btn:disabled { opacity: 0.6; cursor: not-allowed; } diff --git a/frontend/js/atlus.js b/frontend/js/atlus.js index 9b0ea82..9873f0f 100644 --- a/frontend/js/atlus.js +++ b/frontend/js/atlus.js @@ -391,42 +391,50 @@ // ===================================================================== // Panel — Update checker // ===================================================================== - let updateDismissed = false; async function checkForUpdates() { - if (updateDismissed) return; + const panel = $('#panelUpdates'); + if (!panel) return; try { const res = await Atlus.apiFetch('/api/updates/check'); if (!res || !res.ok) return; const data = await res.json(); - const panel = $('#panelUpdates'); - if (!panel) return; + + panel.classList.remove('hidden'); if (data.available && data.behind_count > 0) { - showUpdateToast(panel, data); + showUpdateAvailable(panel, data); } else { - panel.classList.add('hidden'); + showUpToDate(panel, data); } } catch (e) { /* ignore */ } } - function showUpdateToast(panel, data) { - panel.classList.remove('hidden'); + function showUpToDate(panel, data) { panel.innerHTML = ` -
- -
Update available
-
${data.behind_count} commit${data.behind_count !== 1 ? 's' : ''} behind (${data.remote_hash})
- +
+ +
+
Up to date
+
${data.local_hash}
+
+
+ `; + } + + function showUpdateAvailable(panel, data) { + panel.innerHTML = ` +
+ +
+
Update available
+
${data.behind_count} commit${data.behind_count !== 1 ? 's' : ''} behind (${data.remote_hash})
+
+
`; - panel.querySelector('.update-dismiss').addEventListener('click', () => { - panel.classList.add('hidden'); - updateDismissed = true; - }); - - panel.querySelector('.update-toast-btn').addEventListener('click', async (e) => { + panel.querySelector('.update-install-btn').addEventListener('click', async (e) => { const btn = e.target; btn.disabled = true; btn.textContent = 'Updating…'; @@ -435,10 +443,9 @@ const res = await Atlus.apiFetch('/api/updates/apply', { method: 'POST' }); if (res.ok) { btn.textContent = 'Restarting…'; - // Server will restart — try to reload after a delay setTimeout(() => attemptReload(0), 4000); } else { - btn.textContent = 'Update failed'; + btn.textContent = 'Failed'; btn.disabled = false; } } catch (e) {