Commit Graph

162 Commits

Author SHA1 Message Date
Samuele Giacomin
57750d247e
Merge 880235e43d into 08f8f65a2a 2026-11-02 09:34:00 +01:00
Kingkor Roy Tirtho
9f4ce11509 fix(player): smooth the expanded player swipe
Read sheet progress in draw/derived scopes instead of composition so a
drag no longer recomposes the player every frame, keep the expanded
player, floating player and bottom bar composed once shown instead of
building them mid-drag, and settle with a spring that carries fling
velocity. Add a drag test for CompactPlayerOverlay.
2026-10-30 14:16:51 +06:00
Kingkor Roy Tirtho
bba725a139 fix(android): fully close the app on swipe-away and avoid duplicate cookie DataStore
Initialize NewPipeDownloader once per process so recreating the Activity
no longer opens a second DataStore on spotube_cookies.preferences_pb.
Kill the process after PlaybackService shuts down on task removal so the
proxy server, MQTT client and singletons don't linger in the background.
2026-10-30 13:35:39 +06:00
Kingkor Roy Tirtho
c058074cff fix(plugin): update default selected plugins to use built-in plugins with distinct abilities 2026-10-30 13:08:34 +06:00
Kingkor Roy Tirtho
2aaa0db81e fix(broker): update default broker settings and improve connection error handling 2026-10-30 11:50:39 +06:00
Kingkor Roy Tirtho
14bc279653 fix(ios): crashing on search screen 2026-10-30 11:10:25 +06:00
Kingkor Roy Tirtho
2c1148a126 chore: remove devil's name 2026-10-30 10:33:11 +06:00
sibylla canton
05d92a73fd Add iOS background playback support
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-27 18:56:48 +01:00
Kingkor Roy Tirtho
aca3aeb592 fix(theme): follow the OS dark mode on desktop
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>
2026-10-27 18:53:47 +06:00
Kingkor Roy Tirtho
5b36edd259 fix(windows): make VLC playback work through the stream proxy
The proxy copied every upstream header, duplicating Content-Length, which VLC
rejects. Forward only the range/validator headers. Bump vlcj-bundler to 0.2.1,
which bundles the Matroska demuxer needed for WebM. Make StreamingUrlRepository's
platform injectable and add VLC log switch via DebugConfig.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 18:49:20 +06:00
Kingkor Roy Tirtho
ea01dec6ea fix(settings): palette swatches follow the active light/dark appearance
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 18:49:20 +06:00
Kingkor Roy Tirtho
79266fd483 fix(windows): window not spawning due to early COM initialization 2026-10-27 16:35:27 +06:00
Kingkor Roy Tirtho
1ea5f1d1ee fix: update website URLs from spotube.org to spotube.cc 2026-10-26 15:31:17 +06:00
Kingkor Roy Tirtho
bdf3655a23 fix(ios): make the login WebView identify as Mobile Safari
accounts.spotify.com rejected iOS logins ("Oops, something went wrong") because
the WebView sent WKWebView's default User-Agent, which lacks Safari's
"Version/x ... Safari/604.1" and reads as an embedded browser. The random
User-Agent header never reached any request: the screen replaces the content
before it loads.

Have WebKit build Safari's exact UA (with its frozen OS version) via a probe
WKWebView using Safari's applicationNameForUserAgent, prime it at startup and
apply it through webSettings.customUserAgentString so every request uses it.
2026-10-26 15:04:26 +06:00
Kingkor Roy Tirtho
7fa3b029f6 Merge branch 'dev' into ios-crash-fix
# Conflicts:
#	gradle/libs.versions.toml
2026-10-26 13:45:32 +06:00
Kingkor Roy Tirtho
cb8316d141 fix(ios): stream formats AVPlayer can play
AVPlayer can't open WebM/Ogg or DASH, so the default opus/webm stream failed
silently on iOS.

- Rank streams the platform's player can play above format/quality prefs
- Default iOS streaming to aac/mp4, migrate saved WebM/Ogg prefs on iOS and
  hide unplayable formats in the picker (desktop/Android keep opus/webm)
- Normalize codec/container names on iOS like androidJvm (mp4a -> aac, m4a -> mp4)
- Wait up to 30s for the audio plugin to load when resolving, so the queue
  restored at startup isn't failed permanently before plugins are ready
2026-10-26 13:40:00 +06:00
Kingkor Roy Tirtho
99ba08501b fix(server): don't crash when the proxy port is still in use
CIO reports a failed bind from its accept coroutine; unhandled, that
exception terminates the process on Kotlin/Native before the port fallback
can run, so relaunching iOS shortly after playback crashed (EADDRINUSE).
Contain it with a parent CoroutineExceptionHandler and enable reuseAddress
so the preferred port can be rebound while old connections are in TIME_WAIT.
2026-10-26 13:40:00 +06:00
Kingkor Roy Tirtho
0acc457890 feat(plugin): implement automatic plugin updates and enhance JSON parsing 2026-10-26 12:44:04 +06:00
Kingkor Roy Tirtho
7eb56c8593 fix(ios): run Zipline on an 8 MiB stack thread
newSingleThreadContext threads get only 512 KiB of stack on iOS, while
QuickJS may recurse ~6 MiB deep when compiling a plugin, so the app crashed
with SIGBUS at startup once a plugin was installed. Host the dispatcher on an
NSThread with an 8 MiB stack, matching JVM/Android.
2026-10-23 11:54:29 +06:00
Kingkor Roy Tirtho
ff7a1714ff refactor(network): central HttpClientFactory; drop Ktor CIO client
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.
2026-10-23 11:54:29 +06:00
Kingkor Roy Tirtho
09df4b494c build: upgrade to Kotlin 2.4.21 and Compose Multiplatform 1.12.2
Several dependencies (coil 3.5.0, millennium, mqtt/ditchoom, composeunstyled,
markdown-renderer, composewebview, kmp-zip, filekit) now ship klibs built with
Kotlin 2.4, which Kotlin/Native 2.3 refuses to read, breaking the iOS build.

- Bump zipline (1.28.0), mokkery (3.5.1) and ksp (2.3.12) for the new compiler
- Type TOP_LEVEL_ROUTES as Set<NavKey> (Kotlin 2.4 inferred Set<Any>)
- Import ComposeApp in iOSApp.swift, which uses ExternalUriHandler
2026-10-23 11:54:29 +06:00
Kingkor Roy Tirtho
79d47c1d87 feat: enhance loading states for various UI components and update dependencies 2026-10-20 20:32:47 +06:00
Kingkor Roy Tirtho
08892c2aa0 fix(downloads): respect download format/quality and never save manifests or video
- Downloads resolve streams with the user's download format/quality via a
  new StreamRequest instead of the streaming settings, and bypass the
  playback stream-URL cache in both directions
- Downloads only consider progressive streams; DASH/HLS manifests were
  previously saved as-is instead of audio
- NewPipe: map AAC "mp4a.40.x"/"m4a" to the advertised "aac"/"mp4" so real
  AAC streams can match (previously the hard-coded aac/mp4 manifests always
  won), report each stream's real delivery method, skip streams without a
  format or non-URL content
- Fail the download on non-2xx responses, on a range request answered with
  a full 200, and on video/* content, with localized reasons, instead of
  writing the response body to disk
- Save AAC as .m4a
- Tests for request overrides, manifest exclusion and cache isolation
2026-10-20 16:03:48 +06:00
Kingkor Roy Tirtho
8bbefdfb7d fix(android): app stuck on splash screen from main-thread string loading
PlaybackService.onCreate runs on the main thread and called
runBlocking { getString(...) } for its notification strings. Compose
resources share one in-flight load per strings file (AsyncCache creates the
Deferred in the caller's scope); when App()'s stringResource started that
load on the main dispatcher first, blocking main to await it deadlocked and
the first frame never rendered. Timing-dependent, so mostly seen under the
debugger.

Create the notification channel immediately under the app name and update
its localized name/description from serviceScope. The short-lived
placeholder notification no longer carries localized text.
2026-10-20 16:03:48 +06:00
Kingkor Roy Tirtho
d4961bb5ed feat: download diagnostics, live connect status, remote settings on devices screen
Downloads
- Show the real download folder: "Current folder: <path> (default)" in
  settings instead of the misleading "default music folder", and a
  "Saved to <path>" line on the Downloads screen
- Register finished downloads with Android's MediaStore (MediaScanner) so
  music players and the Files app see them immediately
- Add tagged logs across the download path to diagnose format/quality
  selection: raw NewPipe streams ([Streams]), every selection candidate
  with its rank key and fallback warnings ([Resolve]), and per-download
  enqueue prefs, resolved stream, HEAD/GET status + content type, segment
  responses and written vs expected bytes ([Download])

Connect status
- Mobile Home keeps its Devices / Group Jam / Support icons (Jam now uses
  the sound icon) and shows a slim banner only while remote-controlling a
  device or in a Jam ("Playing on krtx", "Hosting · 3 listeners")
- Sidebar Devices / Group Jam rows get a live dot and status line
- New ConnectStatusViewModel feeds both

Remote control settings
- Extract "Allow remote control" and "Device name" into shared
  remoteControlSettingCards, used by Playback settings and a new
  "This device" section on the Devices screen
2026-10-20 15:54:23 +06:00
Kingkor Roy Tirtho
b38a4f6963 feat(remote): redesign remote control and devices screens, fix connection issues
- Remove the unused "Enable Connect" setting and its strings
- Redesign RemoteControlScreen to match the expanded player: artwork sized
  to fit, side-by-side queue panel on wide screens, proper connecting /
  disconnected / error states, "Playing on <device>" subtitle
- Seek and volume sliders keep local drag state and only commit on release
  (volume throttled while dragging) instead of sending a command per frame
- Redesign DevicesScreen with the settings card components, a connected
  device card, error banner and empty state; ViewModels expose one UiState
- Fix tapping an already-connected device doing nothing; reopen its remote
  screen instead, and switch devices by disconnecting first
- Fix the controller getting stuck in Connecting after the host denies a
  request: Ktor never delivers Close frames to `incoming`, so detect the
  close reason after the receive loop ends
- Fix a UI freeze when leaving the devices screen on desktop: run discovery
  (and JmDNS's blocking close/resolve) on Dispatchers.IO
- Advertise the LAN address of the default-route interface on desktop;
  dns-sd-kt otherwise picks any site-local address, e.g. a Docker bridge
2026-10-20 15:11:10 +06:00
Kingkor Roy Tirtho
facc8ed0b9 fix(android): update playback state management to ensure guests follow host's play state 2026-10-20 14:28:18 +06:00
Kingkor Roy Tirtho
0b21eff4c7 fix(android): simplify service start logic for PlaybackService to avoid crashes on background playback 2026-10-20 13:44:30 +06:00
Kingkor Roy Tirtho
9d5854023b fix(android): update sharing functionality to use chooser intent with new task flag 2026-10-20 13:19:04 +06:00
Kingkor Roy Tirtho
e92e62613e chore: implement Linux AppImage bundling for GTK and WebKitGTK, update dependencies and documentation 2026-10-19 19:15:13 +06:00
Kingkor Roy Tirtho
17f2068950 feat(navigation): implement fade-through and stack transition animations for navigation 2026-10-18 18:31:51 +06:00
Kingkor Roy Tirtho
75ced1285e feat(local-tracks): implement LocalFolder screen and view model for folder navigation 2026-10-18 18:04:53 +06:00
Kingkor Roy Tirtho
62c1fe7902 feat: enhance Android build configuration with stable/nightly flavors and update launcher icons 2026-10-16 21:34:44 +06:00
Kingkor Roy Tirtho
9fba2aa33d feat(window): implement window state persistence and restoration 2026-10-16 20:49:16 +06:00
Kingkor Roy Tirtho
9db35e092b feat(server): implement port fallback mechanism for playback proxy server 2026-10-16 20:06:12 +06:00
Kingkor Roy Tirtho
2474c26a83 refactor: move package name from dev.krtirtho to org.spotube 2026-10-16 15:37:15 +06:00
Kingkor Roy Tirtho
7743d6d4c3 feat(lyrics): implement SyncedLyricsList component and enhance LyricsViewModel for better state management 2026-10-16 15:12:10 +06:00
Kingkor Roy Tirtho
77a9cef3a1 fix(stream-proxy): improve logging for cache timeout and handle disconnection scenarios 2026-10-16 14:44:39 +06:00
Kingkor Roy Tirtho
c9d16a25c6 fix(audio-player): android shuffle wasnt working 2026-10-16 14:36:27 +06:00
Kingkor Roy Tirtho
da394d40ea fix(audio-api): enhance fallback mechanism for text search results in YouTube 2026-10-16 14:29:43 +06:00
Kingkor Roy Tirtho
09d77211b9 fix(newpipe): fall back through multiple searches when ISRC search misses
NewPipe durations are seconds, not ms, so duration scoring never matched.
Fix the uploader match direction, normalize titles, and walk a ladder of
searches (ISRC, songs, videos, title only) until a confident match is found.
Return nothing rather than unrelated results. Add detailed ISRC/NewPipe logs.
2026-10-16 14:26:39 +06:00
Kingkor Roy Tirtho
61dd89f3ed fix(stream-proxy): stream upstream audio instead of buffering the whole track
Ktor's request() buffers the full body before returning, so ExoPlayer timed
out waiting for headers. Use prepareRequest().execute{} and tee the body to
the cache file, committing only complete 200 responses. Treat player
disconnects (broken pipe) as debug-level noise rather than upstream errors.
2026-10-16 14:26:39 +06:00
Kingkor Roy Tirtho
ba62ff03c3 feat(user-agents): implement dynamic user agent fetching and caching mechanism 2026-10-16 13:47:08 +06:00
Kingkor Roy Tirtho
83115ea99a feat(plugin): add login prompt for metadata plugin access and implement authentication view model 2026-10-16 12:06:13 +06:00
Kingkor Roy Tirtho
59f1b82368 feat(ui): update MillenniumModalBottomSheet with compact padding and spacing adjustments 2026-10-16 12:01:36 +06:00
Kingkor Roy Tirtho
c57e33fe0d feat(ui): replace IndeterminateProgress with new loading components and enhance dialog structures 2026-10-16 11:49:48 +06:00
Kingkor Roy Tirtho
daf54b74f4 feat(plugin): implement MetadataPluginGuard to manage plugin dependencies and user prompts 2026-10-16 09:29:08 +06:00
Kingkor Roy Tirtho
2bef59ee76 chore: add l10n strings 2026-10-15 23:26:42 +06:00
Kingkor Roy Tirtho
9f79505e1c feat(i18n): replace hardcoded strings with localized resources across multiple components 2026-10-15 14:07:56 +06:00
Kingkor Roy Tirtho
0e0e242095 feat(navigation): add custom navigation transition specifications for push and pop actions 2026-10-15 13:18:26 +06:00