384 MB left little headroom for large libraries and long sessions. It is
a ceiling, not a reservation: the serial GC only grows the heap to what
is live.
- Add jam-server/: a Cloudflare Worker with one Durable Object per room code.
It tracks membership, host handoff and kicks/bans, keeps the queue for late
joiners, routes guest commands to the host and serves the room clock.
- Sync playback: devices estimate the server clock, the host sends position
anchors in server time, guests follow by nudging playback rate (seeking only
when far off) and stream the host's audio source when they share a plugin.
- Seek, play/pause, skip and jump apply to the whole room.
- Recover from network loss instead of crashing: socket failures reconnect
with backoff, silent sockets are detected, and an expired room is recreated
by its host.
- Keep cost and battery low: anchors only on change (plus host drift and a
60 s heartbeat), kept in memory rather than storage, free runtime keep-alives
once a minute, rare clock re-syncs, and no polling while paused or buffering.
- Remove the MQTT broker settings and libraries.
- Add sync unit tests, client/session integration tests (JAM_TEST_URL) and a
network-loss test, plus a deploy workflow for the server.
Compose's isSystemInDarkTheme never updates under the Tao window, so Theme.SYSTEM
stayed light. Use Nucleus' darkmode-detector on JVM and keep Compose's check on mobile.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A beta is the stable build released as <version>-beta.N, with N set via
betaNumber in composeApp/build.gradle.kts. Betas and stable releases are
drafts; only nightly publishes immediately.
On iOS the CIO client engine competed with Darwin as the default engine and
has no TLS on Kotlin/Native, so HTTPS requests (e.g. plugin discovery) failed.
Remove ktor-client-cio and build every client through a Koin-provided
HttpClientFactory that owns one client on the platform default engine
(Darwin on iOS, OkHttp on Android/desktop). Consumers use the shared
default/json clients or derive their own via create { }, sharing the engine.
- Flatpak manifest (GNOME 51, libvlc built from source) installing from a new
portable spotube-linux-<version>-<arch>.tar.xz, shared with the AUR package
- Release workflow builds and attaches the Linux tarballs for x86_64 and aarch64
- Package files are JMustache templates rendered by :composeApp:renderPackaging<Target>
with the version, release asset checksums and git-cliff release notes; the
metainfo release history is generated
- Publish workflow (workflow_dispatch, release tag input) renders once and pushes to
Flathub, the AUR, WinGet (PR from team-spotube/winget-pkgs) and Chocolatey
- Chocolatey and WinGet updated for the NSIS installer