Commit Graph

1256 Commits

Author SHA1 Message Date
zarzet cb9b27920f fix: reset OutputExt on extension→extension fallback too 2026-04-14 02:25:40 +07:00
zarzet e6b77d4b41 fix: reset OutputExt on extension→built-in fallback 2026-04-14 02:22:08 +07:00
zarzet 31ba1431d0 fix: normalize extension codec for built-in fallback, remove dead Tidal ISRC 2026-04-14 02:19:49 +07:00
zarzet a556110068 chore: reduce Gradle memory, add extension network timeout, fix tr locale 2026-04-14 02:10:53 +07:00
zarzet ddd976de35 fix: respect user provider choice over source extension priority 2026-04-14 02:09:14 +07:00
zarzet d47ac0934d chore: bump version to 4.3.0 and fix SAF document file race condition
- Bump app version to 4.3.0 (build 125)
- Extract createOrReuseDocumentFile() to handle SAF auto-rename races
  between findFile() and createFile(), preferring the exact-named sibling
  and discarding duplicate documents
2026-04-13 23:35:03 +07:00
zarzet dbba4d6630 feat: propagate download cancel to extension HTTP requests and fix SAF filename extension mismatch
- Bind cancel context to all extension HTTP calls (fetch, httpGet, httpPost,
  httpRequest, fileDownload, authExchangeCodeWithPKCE) so in-flight requests
  are aborted when user cancels a download
- Make initDownloadCancel idempotent: return existing context if entry already
  exists and preserve pre-cancelled state
- Force SAF output filename to match actual file extension when extension
  returns a different format than requested (e.g. FLAC requested but M4A produced)
- Map ALAC/AAC quality to .m4a instead of falling through to default .flac
2026-04-13 23:35:03 +07:00
zarzet 7405855e01 fix: handle extension oauth callback on ios 2026-04-13 23:35:03 +07:00
zarzet ed020c9303 feat: native M4A ReplayGain tag writing and SAF picker error handling 2026-04-13 23:35:03 +07:00
zarzet 378742e37a refactor: remove author field from extension manifest and UI 2026-04-13 23:35:03 +07:00
zarzet c79bee534e fix: align default search tab layout with primary provider selector using Row+Expanded 2026-04-13 23:35:03 +07:00
zarzet 1d6df75829 fix: preserve existing M4A metadata during embed and enable BuildConfig generation 2026-04-13 23:35:03 +07:00
zarzet b7f51b5f14 feat: expose extension utils, preserve M4A native container, and bump to v4.2.3+124 2026-04-13 23:35:03 +07:00
zarzet 1c8e9df727 feat: add artist search filter and normalize search filter handling 2026-04-13 23:35:03 +07:00
zarzet 01540fe3fc fix: improve ALAC M4A quality parsing 2026-04-13 23:35:03 +07:00
zarzet 071db2f109 refactor: move deezer search flow to extension 2026-04-13 23:35:02 +07:00
zarzet e097d3f605 fix: stabilize shared extension link handling 2026-04-13 23:35:02 +07:00
zarzet 277f783f62 feat: add default search tab preference 2026-04-13 23:35:02 +07:00
zarzet 7637aaf168 fix: fallback extra metadata genre 2026-04-13 23:35:02 +07:00
zarzet c4878470bf chore: thank Ldav Nico and Feuerstern on donate page 2026-04-13 23:35:02 +07:00
zarzet a3725e8c48 feat: add keep android open link 2026-04-13 23:35:02 +07:00
zarzet 917ba842f5 fix: align metadata sanitization and lyrics editing 2026-04-13 23:32:19 +07:00
zarzet dac17ead33 chore: bump app to v4.2.2 2026-04-13 23:32:19 +07:00
zarzet 6845ebe04c refactor: move deezer to extension 2026-04-13 23:32:18 +07:00
zarzet eff709480d fix: preserve flat singles output for extension releases 2026-04-13 23:32:18 +07:00
zarzet 67833424cc fix: align re-enrich matching with autofill metadata 2026-04-13 23:32:18 +07:00
zarzet 5c48e1b476 fix: persist downloaded metadata and refine metadata navigation 2026-04-13 23:32:18 +07:00
zarzet 5e17c9f238 feat: add configurable extension download fallback 2026-04-13 23:32:18 +07:00
zarzet 7d330fb2ec fix: preserve composer metadata across qobuz and history 2026-04-13 23:32:18 +07:00
zarzet cd6a4594fa chore: bump app version to v4.2.1 2026-04-13 23:32:17 +07:00
zarzet bcf727f4ec fix: remove stale audio service manifest entries causing crashes on some devices 2026-04-13 23:32:17 +07:00
zarzet 4c4553913f fix: harden gomobile extension bindings and m4a cover retention 2026-04-13 23:32:17 +07:00
zarzet f0013fac16 fix: preserve local convert format and library entries 2026-04-13 23:32:17 +07:00
zarzet ce4be0ba97 feat: enrich composer and track totals metadata 2026-04-13 23:32:17 +07:00
zarzet 4bac38ef2a fix: preserve embedded metadata details 2026-04-13 23:32:17 +07:00
zarzet 4b213f47d9 ci: pin iOS release builds to macOS 15 and Xcode 26.1.1 2026-04-13 23:32:16 +07:00
zarzet a1010f72f2 fix: patch device_info_plus iOS build for older Xcode SDKs 2026-04-13 23:32:16 +07:00
zarzet 21077a26d0 feat: add additional search/metadata API with separate rate limiting 2026-04-13 23:32:16 +07:00
zarzet b50eec5a47 perf: incremental download queue lookup updates, async cover cleanup, and native JSON decoding on iOS
- Embed DownloadQueueLookup into DownloadQueueState; add updatedForIndices() for O(changed) incremental updates during frequent progress ticks instead of full O(n) rebuild
- downloadQueueLookupProvider now reads pre-computed lookup from state directly
- Replace sync file deletion in DownloadedEmbeddedCoverResolver with unawaited async cleanup to avoid blocking the main thread
- Parse JSON payloads on iOS native side (parseJsonPayload) so event sinks and method channel responses return native objects, avoiding redundant Dart-side JSON decode
- Use .cast<String, dynamic>() instead of Map.from() in _decodeMapResult for zero-copy map handling
2026-04-13 23:32:16 +07:00
zarzet 38a8b715f8 perf: reduce UI jank via memoization, compute isolates, SQL-backed playlist picker, and viewport-aware image caching
- Move explore JSON decode/encode to compute() isolate to avoid blocking main thread
- Memoize search sort results (artists/albums/playlists/tracks) in HomeTab; invalidate on new query
- Extract _DownloadedOrRemoteCover StatefulWidget with proper embedded-cover lifecycle management
- Replace O(playlists x tracks) in-memory playlist picker check with SQL loadPlaylistPickerSummaries query
- Add FutureProvider.family (libraryPlaylistPickerSummariesProvider) invalidated on all playlist mutations
- Memoize _buildQueueHistoryStats, localPathMatchKeys, and localSingleItems in QueueTab
- Add coverCacheWidthForViewport util; apply memCacheWidth/cacheWidth based on real DPR across all album/playlist/track screens
- Convert sync file ops in TrackMetadataScreen to async; use mtime+size as validation token
- Fetch Deezer album nb_tracks in parallel via fetchAlbumTrackCounts
2026-04-13 23:32:16 +07:00
zarzet 2b47537bb5 fix: route Qobuz API calls through authenticated gateway to resolve 401 errors 2026-04-13 23:32:16 +07:00
zarzet a5cf241846 refactor: consolidate FLAC/MP3/Opus metadata embedding into unified _embedMetadataToFile 2026-04-13 23:32:16 +07:00
zarzet 53a4773480 feat: add skipLyrics manifest field for extensions to opt out of lyrics fetching 2026-04-13 23:32:16 +07:00
zarzet 89603af1f1 chore: remove redundant comments and update donor list 2026-04-13 23:32:15 +07:00
zarzet 2143084d3c fix: resolve missing track/disc numbers from search downloads and suppress FFmpeg log noise
- Tidal: use actual API track_number/disc_number when request values are 0
  (fixes search/popular downloads having no track position in metadata)
- Extension enrichment: copy TrackNumber/DiscNumber back from enriched results
- Extension fallback download: add request metadata fallback for non-source
  extensions (Album, AlbumArtist, ReleaseDate, ISRC, TrackNumber, DiscNumber)
- FFmpeg: add -v error -hide_banner to all commands (embed, convert, CUE split)
  to eliminate banner, build config, and full metadata/lyrics dump in logcat
- ebur128: add framelog=quiet to suppress per-frame loudness measurements
  while keeping the summary needed for ReplayGain parsing
- Track metadata screen: separate embedded lyrics check from online fetch,
  show file-only state with manual online fetch button
2026-04-13 23:32:15 +07:00
zarzet 0e265193b8 fix: improve extension runtime safety, HTTP response URL, SongLink parsing, and recommended service for extensions
- Add 'url' field (final URL after redirects) to all extension HTTP responses and fix fetch polyfill to return final URL instead of original request URL
- Fix RunWithTimeout race condition: increase force-timeout from 1s to 60s to prevent concurrent VM access crashes, add nil guards
- Use lockReadyVM() for thread-safe VM access in GetPlaylistWithExtensionJSON and InvokeAction
- Handle mixed JSON types (string, null, array) in SongLink resolve API SongUrls field
- Fix recommended download service not showing for extension-based searches in download picker
2026-04-13 23:32:15 +07:00
zarzet c7e9749ce4 fix: resolve label and copyright from file metadata on info screen
The info screen was not reading label/copyright from the actual file metadata, so these fields were always empty for local library items and download history items that lacked them in-memory. Now _resolveAudioMetadata() extracts and displays them without requiring a manual save first.
2026-04-13 23:32:15 +07:00
zarzet e21cffff0b fix: validate ISRC in track metadata screen to prevent ID leakage
Sanitize the isrc getter to only return valid ISRC codes (12-char format per ISO 3901). Invalid values such as Spotify/Deezer/Tidal IDs that may leak into the ISRC field are now silently discarded, preventing them from being displayed or embedded into file tags.
2026-04-13 23:32:15 +07:00
zarzet d9e20040be fix: correct track/disc defaults, forward extension metadata, and fix service ID display
- Default track/disc number to 0 (unknown) instead of 1, letting the
  backend use the service-provided value or skip the field entirely
- Add releaseDate to ExploreItem so explore downloads carry release info
- Pass discNumber and releaseDate from extension album/playlist tracks
- Fix isDeezer detection using service field instead of substring match
- Add _displayServiceTrackId() to properly strip prefixes for all services
2026-04-13 23:32:15 +07:00
zarzet 6689173525 chore: bump version to 4.2.0 (build 121) 2026-04-13 23:32:14 +07:00