fix(settings): close the two self-update UX gaps from 2026-04-16 VM test
Drive upd-current from the /api/furtka/update/check response so a post-update Check reflects the new installed version without Ctrl+F5, and arm a 45s fallback location.reload on apply-click so the page still comes up on the new version when the mid-apply API restart drops the /update-state.json poll before stage=done is observed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bf86ffaf4c
commit
a5de3d7622
2 changed files with 11 additions and 3 deletions
|
|
@ -7,10 +7,10 @@ This project uses calendar versioning: `YY.N-stage` (e.g. `26.0-alpha` = 2026, r
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Known UX gaps (to fix in the next release)
|
||||
### Fixed
|
||||
|
||||
- **Settings page "Installed" field doesn't refresh right after a self-update.** After `/settings` → Update now → success, the browser's `refresh()` against `/status.json` reads a page-load snapshot rather than the new value. A force-reload (Ctrl+F5) shows the correct version. Fix idea: have the update-check endpoint response also drive `upd-current` (we already set `upd-latest` from it).
|
||||
- **Auto-reload on update completion is unreliable.** The JS polls `/update-state.json` and calls `location.reload()` 5s after seeing `stage: done`. On the 2026-04-16 VM test the browser never auto-reloaded — user reloaded manually. Probable cause: the API restart mid-apply drops the polling connection between the browser and the page before the done state is observed. Fix idea: fallback `setTimeout(reload, 45_000)` on apply-click regardless of poll outcome.
|
||||
- **Settings page "Installed" field now refreshes after a self-update.** The `/api/furtka/update/check` response already carries `current` — the settings JS now drives `upd-current` from it the same way it drives `upd-latest`, so clicking "Check for updates" after a successful update reflects the new installed version without a force-reload.
|
||||
- **Auto-reload on update completion is now reliable.** Clicking "Update now" arms a 45 s fallback `setTimeout(location.reload)` in addition to the existing `/update-state.json` polling loop. If the mid-apply API restart drops the poll connection before `stage: done` is ever observed (as seen on the 2026-04-16 VM test), the fallback still brings the page up on the new version. The fallback is cleared on `done` (5 s reload wins) or `rolled_back` (user needs the error visible).
|
||||
|
||||
## [26.3-alpha] - 2026-04-16
|
||||
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@
|
|||
};
|
||||
|
||||
let pollHandle = null;
|
||||
let fallbackReloadHandle = null;
|
||||
const statusEl = document.getElementById('update-status');
|
||||
const checkBtn = document.getElementById('check-updates-btn');
|
||||
const applyBtn = document.getElementById('apply-update-btn');
|
||||
|
|
@ -135,6 +136,7 @@
|
|||
return;
|
||||
}
|
||||
document.getElementById('upd-latest').textContent = data.latest || '—';
|
||||
document.getElementById('upd-current').textContent = data.current || '—';
|
||||
if (data.update_available) {
|
||||
applyBtn.hidden = false;
|
||||
applyBtn.textContent = `Update to ${data.latest}`;
|
||||
|
|
@ -169,6 +171,10 @@
|
|||
// Poll /update-state.json (served by Caddy, unaffected by the
|
||||
// API restart the updater is about to trigger) every 2s.
|
||||
pollHandle = setInterval(pollUpdateState, 2000);
|
||||
// Fallback: reload regardless of whether polling observes 'done'.
|
||||
// The mid-apply API restart can drop the poll connection before
|
||||
// the terminal state is ever seen by this page.
|
||||
fallbackReloadHandle = setTimeout(() => location.reload(), 45000);
|
||||
} catch (e) {
|
||||
setStatus(`Network error: ${e.message}`, true);
|
||||
applyBtn.disabled = false;
|
||||
|
|
@ -185,9 +191,11 @@
|
|||
setStatus(label, s.stage === 'rolled_back');
|
||||
if (s.stage === 'done') {
|
||||
clearInterval(pollHandle);
|
||||
clearTimeout(fallbackReloadHandle);
|
||||
setTimeout(() => location.reload(), 5000);
|
||||
} else if (s.stage === 'rolled_back') {
|
||||
clearInterval(pollHandle);
|
||||
clearTimeout(fallbackReloadHandle);
|
||||
if (s.reason) {
|
||||
setStatus(`${label} — ${s.reason}`, true);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue