feat: detect new web builds + hard-refresh escape hatch (0.1.17/batch78)

Root cause of "the fix works on mobile but not on desktop/web": nothing was wrong with
the code — the desktop app now CLOSES TO TRAY, so it can run for weeks on the page it
loaded on day one and never re-fetch after a deploy. There was also no way to force it
off a stale page (no menu bar → no reload accelerator).

- Server: GET /api/build returns home.html's __BUILD marker.
- Client: polls it (boot, on focus/visibility, every 10 min); when the server's build
  differs from the running one, shows a branded "A new version is available — Refresh"
  banner. Settings gains an always-available "Refresh app" with the current build shown.
- hardReloadApp(): in the browser it unregisters service workers + clears CacheStorage
  then reloads cache-busted; in the shell it calls the native hard reload.
- Desktop: hard-reload IPC (clears the session HTTP cache + reloadIgnoringCache), wired to
  Ctrl+R (reload), Ctrl+Shift+R / F5 (hard reload), and a "Refresh app (get latest)" tray
  item. Previously there was literally no way to clear the cache from the app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 13:38:55 +05:30
parent 5a138f5bc4
commit a0017f2036
5 changed files with 76 additions and 2 deletions
+3
View File
@@ -34,6 +34,9 @@ contextBridge.exposeInMainWorld('bizConnectNative', Object.freeze({
rcAvailable: () => { try { return !!ipcRenderer.sendSync('rc-available'); } catch (_) { return false; } },
rcArm: (on) => { try { ipcRenderer.send('rc-arm', !!on); } catch (_) {} },
rcInput: (evt) => { try { ipcRenderer.send('rc-input', evt); } catch (_) {} },
// Force the newest web build: clears the shell's HTTP cache and reloads ignoring cache. The app closes
// to tray and can run for weeks, so without this it would keep serving the page it first loaded.
hardReload: () => { try { return ipcRenderer.invoke('hard-reload'); } catch (_) { return Promise.resolve(false); } },
// Manual "Check for updates" from Settings. Resolves {status:'available'|'current'|'dev'|'error', version?}.
// On 'available' the shell downloads in the background and prompts to restart when ready.
checkForUpdates: () => ipcRenderer.invoke('check-updates'),