Repository navigation
Bug-fix release on top of v1.39.1. Repairs the in-app update center, which on v1.39.1 / v1.39.0 stalls when the window is not visible, crashes mid-download, and forgets the partial file on restart.
Update center
- Download survives backgrounding. The HTTP stream-to-disk loop now runs in its own worker isolate. The Flutter embedder throttles the main isolate when the desktop window is minimized, and Android suspends the UI isolate when the app is backgrounded — neither of those affects the worker. The Android foreground service holds the process alive; the isolate keeps draining bytes.
- Auto-resume on app launch and after every periodic check. A
.partialfile from a previous session is detected at startup and (whenautoDownloadUpdatesis on) the download is kicked silently — the existing Range-header resume path picks up where the previous session left off. No more "restart wipes my 90% download". - Task Monitor visibility. The active download appears in Settings → Tasks as
Update Downloadso you can see whether it's actually running. - Cancel is cooperative + force-killable. Cancel sends a signal to the worker isolate; if the cooperative cancel doesn't take effect within 5 s the isolate is killed outright.
Crash hardening
_updateDownloadServiceProgressno longer silently swallows method-channel errors. First failure logs immediately, then at most once per 10 s with the accumulated count.- All
unawaited()recovery / auto-download / auto-install calls now have.catchError(...)+ LogService — exceptions no longer disappear. - Update page nulls listener slots after
removeListenerin dispose;_setStateIfMountedearly-returns when both are null, closing the dispose-window race that could firesetStateon a dead State.
Internal cleanup
- Extracted
_extensionFor(release)+_downloadCacheDirs()to dedupe the three places inupdate_service.dartthat resolved release-asset paths.