Commit graph

4730 commits

Author SHA1 Message Date
Xabi
93631cdee9
fix(ui): update Basque localisation (#5278)
Added missing strings
2026-04-04 15:17:40 -04:00
Deluan Quintão
c87db92cee
fix(artwork): address WebP performance regression on low-power hardware (#5286)
* refactor(artwork): rename DevJpegCoverArt to EnableWebPEncoding

Replaced the internal DevJpegCoverArt flag with a user-facing
EnableWebPEncoding config option (defaults to true). When disabled, the
fallback encoding now preserves the original image format — PNG sources
stay PNG for non-square resizes, matching v0.60.3 behavior. The previous
implementation incorrectly re-encoded PNG sources as JPEG in non-square
mode. Also added EnableWebPEncoding to the insights data.

* feat: add configurable UICoverArtSize option

Converted the hardcoded UICoverArtSize constant (600px) into a
configurable option, allowing users to reduce the cover art size
requested by the UI to mitigate slow image encoding. The value is
served to the frontend via the app config and used by all components
that request cover art. Also simplified the cache warmer by removing
a single-iteration loop in favor of direct code.

* style: fix prettier formatting in subsonic test

* feat: log WebP encoder/decoder selection

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(artwork): address PR review feedback

- Add DevJpegCoverArt to logRemovedOptions so users with the old config
  key get a clear warning instead of a silent ignore.
- Include EnableWebPEncoding in the resized artwork cache key to prevent
  stale WebP responses after toggling the setting.
- Skip animated GIF to WebP conversion via ffmpeg when EnableWebPEncoding
  is false, so the setting is consistent across all image types.
- Fix data race in cache warmer by reading UICoverArtSize at construction
  time instead of per-image, avoiding concurrent access with config
  cleanup in tests.
- Clarify cache warmer docstring to accurately describe caching behavior.

* Revert "fix(artwork): address PR review feedback"

This reverts commit 3a213ef03e.

* fix(artwork): avoid data race in cache warmer config access

Capture UICoverArtSize at construction time instead of reading from
conf.Server on each doCacheImage call. The background goroutine could
race with test config cleanup, causing intermittent race detector
failures in CI.

* fix(configuration): clamp UICoverArtSize to be within 200 and 1200

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(artwork): preserve album cache key compatibility with v0.60.3

Restored the v0.60.3 hash input order for album artwork cache keys
(Agents + CoverArtPriority) so that existing caches remain valid on
upgrade when EnableExternalServices is true. Also ensures
CoverArtPriority is always part of the hash even when external services
are disabled, fixing a v0.60.3 bug where changing CoverArtPriority had
no effect on cache invalidation.

Signed-off-by: Deluan <deluan@navidrome.org>

* fix: default EnableWebPEncoding to false and reduce artwork parallelism

Changed EnableWebPEncoding default to false so that upgrading users get
the same JPEG/PNG encoding behavior as v0.60.3 out of the box, avoiding
the WebP WASM overhead until native libwebp is available. Users can
opt in to WebP by setting EnableWebPEncoding=true. Also reduced the
default DevArtworkMaxRequests to half the CPU count (min 2) to lower
resource pressure during artwork processing.

* fix(configuration): update DefaultUICoverArtSize to 300

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(Makefile): append EXTRA_BUILD_TAGS to GO_BUILD_TAGS

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-04-04 15:17:01 -04:00
Deluan
80c1e60259 feat(playlists): add sampleRate, codec, and missing fields for smart playlists
Some checks are pending
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Closes #5302
2026-04-04 10:37:28 -04:00
Deluan
23f3556371 fix(subsonic): strip OpenSubsonic extensions from playlists for legacy clients
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test JS code (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint i18n files (push) Has been cancelled
Pipeline: Test, Lint, Build / Check Docker configuration (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been cancelled
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-1 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-2 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-3 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-4 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-5 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-6 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-7 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-8 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-9 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-10 (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been cancelled
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been cancelled
Pipeline: Test, Lint, Build / Package/Release (push) Has been cancelled
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been cancelled
buildOSPlaylist was the only OpenSubsonic builder function missing the
LegacyClients guard, causing attributes like `validUntil` and `readonly`
to appear in playlist XML responses for legacy clients like DSub2000.
This caused a crash when DSub2000 tried to parse evaluated smart
playlists containing the `validUntil` attribute.
2026-04-02 16:37:52 -04:00
Deluan
c60637de24 fix(subsonic): return proper artwork ID format in getInternetRadioStations
The coverArt field was returning the raw uploaded image filename instead
of the standard ra-{id} artwork ID format. This caused getCoverArt to
fail when clients passed the coverArt value directly. Now uses
CoverArtID().String() consistent with how albums, artists, and playlists
return their coverArt values. Fixes #5293.
2026-04-02 15:44:20 -04:00
Deluan
220019a9f1 fix: add missing viper defaults for mpvpath, artistimagefolder, and plugins.loglevel
Some checks are pending
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Fix #5284

Several configOptions struct fields were missing corresponding
viper.SetDefault entries, making them invisible to environment variable
overrides and config file parsing. Added defaults for mpvpath (consistent
with ffmpegpath), artistimagefolder, and plugins.loglevel.

Signed-off-by: Deluan <deluan@navidrome.org>
2026-04-01 18:20:01 -04:00
Deluan
6109bf5192 chore(deps): update go-sqlite3 to v1.14.38 and go-toml to v2.3.0
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Signed-off-by: Deluan <deluan@navidrome.org>
2026-04-01 08:51:10 -04:00
Deluan
4030bfe06f fix(artwork): preserve animation for square thumbnails with animated images
Signed-off-by: Deluan <deluan@navidrome.org>
2026-04-01 08:38:29 -04:00
dependabot[bot]
c5bb920b88
chore(deps): bump golang.org/x/image from 0.37.0 to 0.38.0 (#5268)
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.37.0 to 0.38.0.
- [Commits](https://github.com/golang/image/compare/v0.37.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-version: 0.38.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 18:57:43 -04:00
Deluan Quintão
0f6a076dca
fix(artwork): refresh stale artist image URLs on expiry (#5267)
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test JS code (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint i18n files (push) Has been cancelled
Pipeline: Test, Lint, Build / Check Docker configuration (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-1 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-2 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-3 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-4 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-5 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-6 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-7 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-8 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-9 (push) Has been cancelled
Pipeline: Test, Lint, Build / Build-10 (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been cancelled
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been cancelled
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been cancelled
Pipeline: Test, Lint, Build / Package/Release (push) Has been cancelled
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been cancelled
* fix(external): refresh stale artist image URLs on expiry

ArtistImage() was serving cached image URLs from the database
indefinitely, ignoring ExternalInfoUpdatedAt. When users changed agent
configuration (e.g. disabling Deezer), old URLs persisted because only
the UpdateArtistInfo code path checked the TTL.

Now ArtistImage() checks the expiry and enqueues a background refresh
when the cached info is stale, matching the pattern used by
refreshArtistInfo(). The stale URL is still returned immediately to
avoid blocking clients.

Fixes #5266

* test: add expired artist image info test with log assertion

Verify that ArtistImage() enqueues a background refresh when cached
info is expired, by capturing log output and checking for the expected
debug message. Also asserts the stale URL is returned immediately
without calling the agent.

Signed-off-by: Deluan <deluan@navidrome.org>

* fix: only enqueue refresh when returning a stale cached URL

Move the expiry check to the else branch so we only enqueue a
background refresh when a cached image URL exists and is being
returned. This avoids doubling external API calls when the URL is
empty (synchronous fetch) but ExternalInfoUpdatedAt is old.

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-30 09:35:02 -04:00
Deluan
420d2c8e5a fix(artwork): validate ffmpeg pipe before returning in cover art fallback
ffmpeg.ExtractImage returns a pipe-based reader immediately, before ffmpeg
finishes processing. When the audio file has no embedded image stream (e.g.
a plain MP3), ffmpeg exits with an error that closes the pipe asynchronously.
The selectImageReader function saw the non-nil reader as a success and
returned it instead of falling through to the next source in the chain
(album art). This caused getCoverArt to return an error response for tracks
on albums where the disc artwork reader was invoked but no embedded art
existed.

Fixed by reading one byte from the pipe to validate the stream delivers
data before returning it. If the read fails, the reader is closed and nil
is returned, allowing the fallback chain to continue to album artwork.

Closes #5265
2026-03-30 07:01:38 -04:00
Deluan Quintão
9fe9cf3ff6
fix(ui): update Spanish, French translations from POEditor (#5260)
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
POEditor export / push-translations (push) Has been cancelled
Co-authored-by: navidrome-bot <navidrome-bot@navidrome.org>
2026-03-29 19:55:29 -04:00
ChekeredList71
a293d12034
fix(ui): update Hungarian translation (#5263)
* [ui] hungarian translation

* Update resources/i18n/hu.json

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update resources/i18n/hu.json

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

---------

Co-authored-by: ChekeredList71 <asd@asd.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-29 19:50:58 -04:00
Deluan
dc99994bdd feat: add EnableArtworkUpload and CoverArtQuality to insights
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-29 14:57:57 -04:00
Deluan
049fc78177 refactor: extract logFatal helper for config error handling
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Replace 14 repeated fmt.Fprintln(os.Stderr, "FATAL:", ...)/os.Exit(1)
patterns with a single logFatal function. This reduces duplication
and makes all fatal config paths testable via SetLogFatal.

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-28 13:36:27 -04:00
Deluan Quintão
2b041c02ad
feat: accept ND_-prefixed env var names in config files (#5258)
* feat: add toPascalCase helper for config key display

Adds a toPascalCase helper that converts dotted lowercase Viper config keys
(e.g. 'scanner.schedule') to PascalCase (e.g. 'Scanner.Schedule') for use
in user-facing warning messages. Includes export_test.go binding and a
full Ginkgo DescribeTable test suite covering simple, dotted, multi-segment,
already-capitalized, and empty-string cases.

* feat: remap ND_-prefixed env var names found in config files

Detect when users mistakenly use environment variable names (like
ND_ADDRESS) in config files, remap them to canonical keys, and warn.
Fatal error if both ND_ and canonical versions of the same key exist.

Closes #5242
2026-03-28 13:17:31 -04:00
Deluan
2588558946 fix: resolve flaky ffmpeg context cancellation test
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
POEditor export / push-translations (push) Has been cancelled
Replaced single Read assertion with Eventually loop to drain buffered
pipe data after context cancellation. The previous test assumed the first
Read after cancel() would fail, but ffmpeg may have already written data
into the pipe buffer before being killed, causing the Read to succeed
from buffered content.
2026-03-27 19:38:42 -04:00
Deluan
f33ca75378 refactor: rename EnableCoverArtUpload to EnableArtworkUpload
The config flag gates all image uploads (artists, radios, playlists),
not just cover art. Rename it to accurately reflect its scope across
the backend config, native API permission check, Subsonic CoverArtRole,
serve_index JSON key, and frontend config.
2026-03-27 19:33:46 -04:00
Deluan Quintão
79e1af7cd6
fix(ui): update Danish, German, Greek, Finnish, Galician, Portuguese (BR), Swedish, Ukrainian, Chinese (traditional) translations from POEditor (#5218)
Co-authored-by: navidrome-bot <navidrome-bot@navidrome.org>
2026-03-27 18:04:47 -04:00
Deluan
ccee33f474 fix(search): use explicit AND in FTS5 queries to fix apostrophe search
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
FTS5's implicit AND (space-separated tokens) silently fails when combined
with parenthesized OR groups produced by processPunctuatedWords. For example,
searching "you've got" generated the query `("you ve" OR youve*) got*` which
returned no results. Using explicit AND (`("you ve" OR youve*) AND got*`)
resolves this FTS5 quirk. Since implicit and explicit AND are semantically
identical in FTS5, this change is safe for all queries unconditionally.
2026-03-26 20:15:28 -04:00
Deluan Quintão
33e20d355e
fix(ui): cancel in-flight image requests on pagination, cache across remounts (#5249)
Some checks are pending
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
* feat(ui): cancel in-flight image requests on pagination and cache across remounts

When paginating quickly through list/grid views, image requests for previous
pages were never canceled, queuing on the server and blocking new images.
This adds a useImageUrl hook that loads images via fetch() with AbortController,
so requests are canceled when components unmount. A module-level cache (URL →
blob URL) with reference counting ensures React Admin refreshes display images
instantly without re-fetching.

* feat(ui): update AlbumListPagination to conditionally render based on albumListType

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(ui): abort all in-flight image fetches on pagination change

Pagination component now watches page/perPage via useListContext and
calls abortAllInFlight() when either changes, freeing the browser
connection pool immediately for the next page's data request.

Also adds empty placeholder style to CoverArtAvatar so it renders as a
clean transparent area while loading instead of the default person icon.

* Revert "feat(ui): abort all in-flight image fetches on pagination change"

This reverts commit 3bc09f9d03.

* fix(ui): limit concurrent image fetches to prevent connection pool saturation

With <img src>, the browser prioritizes API requests over image loads.
With fetch(), all requests compete equally for the HTTP/1.1 connection
pool (6 per origin), causing API requests to queue behind images and
making pagination feel unresponsive. Caps concurrent image fetches at
4 with a pending queue, leaving connections free for API requests.
Queued fetches for unmounted components are removed without ever
hitting the network.

* fix(ui): fix queued fetch not aborted on unmount

Set queued=false when doFetch executes from the pending queue, so
cleanup correctly calls controller.abort() instead of searching an
already-drained queue.

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-25 21:30:40 -04:00
dependabot[bot]
4c91936848
chore(deps): bump picomatch in /ui (#5248)
Bumps  and [picomatch](https://github.com/micromatch/picomatch). These dependencies needed to be updated together.

Updates `picomatch` from 2.3.1 to 2.3.2
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-25 18:24:46 -04:00
cafecitopuro
0a0f1779cb
feat(ui): add Nutball theme (#4544)
Some checks are pending
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
* add nutball theme

* fix album grid outline

* cleanup

* Pagination fix + accent color update

* Fix animation on Activity icon

* style: fix prettier formatting in nutball theme

---------

Co-authored-by: Deluan <deluan@navidrome.org>
2026-03-24 19:39:02 -04:00
Tom Boucher
356b0716b6
fix(scanner): exclude Vorbis VERSION from albumversion tag mapping (#5194)
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
The Vorbis/FLAC VERSION field is for track-level disambiguation (e.g.
remix, live, 30s edit), not album versioning. Including it in the
albumversion aliases caused albums to split incorrectly when tracks
had different VERSION values and no MusicBrainz Album ID was set.

Remove 'version' from the albumversion aliases in mappings.yaml.
Users who want the old behavior can re-add it via Tags config.

Update the PID test to use 'albumversion' directly instead of
'version' as the raw PID attribute, with a realistic value.

Fixes #5082

Co-authored-by: Deluan Quintão <deluan@navidrome.org>
2026-03-23 18:32:05 -04:00
Kendall Garner
8a19fa9991
fix(server): require additional variable to enable systemd logging (#5222)
* fix(logging): require additional variable to enable systemd logging

* use a better name
2026-03-23 18:09:59 -04:00
dependabot[bot]
221d301c42
chore(deps): bump nick-fields/retry from 3 to 4 in /.github/workflows (#5241)
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Bumps [nick-fields/retry](https://github.com/nick-fields/retry) from 3 to 4.
- [Release notes](https://github.com/nick-fields/retry/releases)
- [Commits](https://github.com/nick-fields/retry/compare/v3...v4)

---
updated-dependencies:
- dependency-name: nick-fields/retry
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 14:19:16 -04:00
Deluan
4cca7bce4e test: increase FlakeAttempts for library directory tests and remove flaky job test 2026-03-23 11:59:11 -04:00
Deluan
d91b5e8f4d refactor: simplify playlist name extraction using strings.CutPrefix 2026-03-23 11:40:16 -04:00
Deluan
03608d3eef feat(subsonic): add coverArt to internetRadioStation response
Some checks are pending
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Add OpenSubsonic coverArt extension to GetInternetRadios, showing
uploaded radio images for non-legacy clients.

Ref: https://github.com/opensubsonic/open-subsonic-api/pull/224
Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-22 15:22:02 -04:00
Deluan
cb396f3dba feat(ui): increase cover art size to 600px and use CatmullRom scaling
Increased the UI cover art request size from 300px to 600px for sharper
images on high-DPI displays. Replaced BiLinear with CatmullRom (bicubic)
interpolation for higher quality image resizing. Extracted the hardcoded
size into a COVER_ART_SIZE constant in the frontend and consolidated
backend sizes into a CacheWarmerImageSizes slice. Removed the unused
UIThumbnailSize constant.

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-22 14:55:14 -04:00
Deluan
400a079fcd fix(ui): fix hover overlay not covering full album cover
Some checks are pending
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Removed marginBottom: '3px' from tileBar and tileBarMobile styles that
was causing the hover overlay to not fully cover the album cover art.
The margin pushed the absolutely-positioned GridListTileBar up, leaving
a visible gap at the bottom. This became apparent after d2a54243a added
aspectRatio: 1 to the cover container.
2026-03-21 19:19:03 -04:00
Deluan
03844a9a36 feat(plugins): add NoFollowRedirects option to HTTPRequest
Some checks are pending
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Allow plugins to opt out of automatic redirect following on a per-request
basis. When set to true, the response returns the redirect status code and
Location header directly instead of following to the final destination.
2026-03-20 18:16:07 -04:00
Deluan Quintão
5cd1fcb492
feat(scheduler): add crontab(5) random ~ syntax support (#5233)
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
* feat(scheduler): add CrontabSchedule with crontab(5) random ~ syntax

Implement ParseCrontab() that extends robfig/cron with support for
the crontab(5) random ~ operator (e.g., 0~30 * * * *). Random values
are resolved fresh on each Next() call for load spreading.

Supports A~B, ~B, A~, and bare ~ forms in all 6 fields (including
seconds). Expressions without ~ delegate to robfig's standard parser
with zero overhead.

Integrates into scheduler.Add() and conf.validateSchedule() so that
scanner.schedule and backup.schedule config values accept ~ syntax.

* refactor(scheduler): resolve random ~ values once at parse time

Change from per-Next() randomization to per-parse randomization,
matching crontab(5) semantics. This prevents double-firing within
the same period when random values land after the current time.

ParseCrontab now resolves ~ fields to concrete values, substitutes
them into the spec string, and delegates to robfig's parser. This
eliminates CrontabSchedule, randomField, and resolveField entirely.

* test(scheduler): replace WaitGroup with channel for job execution synchronization

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-20 08:57:13 -04:00
JRoshthen1
a4c289b28c
feat(ui): add Slovak language translation (#5231)
Some checks failed
Pipeline: Test, Lint, Build / Lint Go code (push) Failing after 4s
Pipeline: Test, Lint, Build / Test Go code (push) Failing after 3s
Pipeline: Test, Lint, Build / Get version info (push) Failing after 4s
Pipeline: Test, Lint, Build / Test JS code (push) Failing after 3s
Pipeline: Test, Lint, Build / Check Docker configuration (push) Successful in 2s
Pipeline: Test, Lint, Build / Lint i18n files (push) Failing after 9s
Pipeline: Test, Lint, Build / Build (push) Has been skipped
Pipeline: Test, Lint, Build / Build-1 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-2 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-3 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-4 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-5 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-6 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-7 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-8 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-9 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-10 (push) Has been skipped
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been skipped
Pipeline: Test, Lint, Build / Package/Release (push) Has been skipped
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been skipped
POEditor export / push-translations (push) Has been skipped
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been skipped
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been skipped
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been skipped
* feat(i18n): Add Slovak language translation

Signed-off-by: jrosh <martin@jrosh.eu>

* fix(i18n): Fix typos and add missing translations

Signed-off-by: jrosh <martin@jrosh.eu>

---------

Signed-off-by: jrosh <martin@jrosh.eu>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
2026-03-19 13:33:09 -04:00
Deluan
f7b60c7952 fix(tests): fix race condition in CacheWarmer pre-cache size test
The test was checking that the buffer was drained before asserting on
cached sizes, but the buffer is cleared before processBatch completes.
Use Eventually on getCachedSizes() directly to properly wait for the
artwork caching to finish.
2026-03-19 13:14:24 -04:00
Deluan Quintão
ba8d427890
feat(ui): add cover art support for internet radio stations (#5229)
Some checks failed
Pipeline: Test, Lint, Build / Lint Go code (push) Failing after 11s
Pipeline: Test, Lint, Build / Get version info (push) Failing after 12s
Pipeline: Test, Lint, Build / Test Go code (push) Failing after 4s
Pipeline: Test, Lint, Build / Test JS code (push) Failing after 3s
Pipeline: Test, Lint, Build / Check Docker configuration (push) Successful in 2s
Pipeline: Test, Lint, Build / Lint i18n files (push) Failing after 3s
Pipeline: Test, Lint, Build / Build (push) Has been skipped
Pipeline: Test, Lint, Build / Build-1 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-2 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-3 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-4 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-5 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-6 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-7 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-8 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-9 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-10 (push) Has been skipped
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been skipped
Pipeline: Test, Lint, Build / Package/Release (push) Has been skipped
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been skipped
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been skipped
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been skipped
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been skipped
* feat(artwork): add KindRadioArtwork and EntityRadio constant

* feat(model): add UploadedImage field and artwork methods to Radio

* feat(model): add Radio to GetEntityByID lookup chain

* feat(db): add uploaded_image column to radio table

* feat(artwork): add radio artwork reader with uploaded image fallback

* feat(api): add radio image upload/delete endpoints

* feat(ui): add radio artwork ID prefix to getCoverArtUrl

* feat(ui): add cover art display and upload to RadioEdit

* feat(ui): add cover art thumbnails to radio list

* feat(ui): prefer artwork URL in radio player helper

* refactor: remove redundant code in radio artwork

- Remove duplicate Avatar rendering in RadioList by reusing CoverArtField
- Remove redundant UpdatedAt assignment in radio image handlers (already set by repository Put)

* refactor(ui): extract shared useImageLoadingState hook

Move image loading/error/lightbox state management into a shared
useImageLoadingState hook in common/. Consolidates duplicated logic
from AlbumDetails, PlaylistDetails, RadioEdit, and artist detail views.

* feat(ui): use radio placeholder icon when no uploaded image

Remove album placeholder fallback from radio artwork reader so radios
without an uploaded image return ErrUnavailable. On the frontend, show
the internet-radio-icon.svg placeholder instead of requesting server
artwork when no image is uploaded, allowing favicon fallback in the
player.

* refactor(ui): update defaultOff fields in useSelectedFields for RadioList

Signed-off-by: Deluan <deluan@navidrome.org>

* fix: address code review feedback

- Add missing alt attribute to CardMedia in RadioEdit for accessibility
- Fix UpdateInternetRadio to preserve UploadedImage field by fetching
  existing radio before updating (prevents Subsonic API from clearing
  custom artwork)
- Add Reader() level tests to verify ErrUnavailable is returned when
  radio has no uploaded image

* refactor: add colsToUpdate to RadioRepository.Put

Use the base sqlRepository.put with column filtering instead of
hand-rolled SQL. UpdateInternetRadio now specifies only the Subsonic API
fields, preventing UploadedImage from being cleared. Image upload/delete
handlers specify only UploadedImage.

* fix: ensure UpdatedAt is included in colsToUpdate for radio Put

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-18 18:57:33 -04:00
Deluan Quintão
3f7226d253
fix(server): improve transcoding failure diagnostics and error responses (#5227)
* fix(server): capture ffmpeg stderr and warn on empty transcoded output

When ffmpeg fails during transcoding (e.g., missing codec like libopus),
the error was silently discarded because stderr was sent to io.Discard
and the HTTP response returned 200 OK with a 0-byte body.

- Capture ffmpeg stderr in a bounded buffer (4KB) and include it in the
  error message when the process exits with a non-zero status code
- Log a warning when transcoded output is 0 bytes, guiding users to
  check codec support and enable Trace logging for details
- Remove log level guard so transcoding errors are always logged, not
  just at Debug level

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(server): return proper error responses for empty transcoded output

Instead of returning HTTP 200 with 0-byte body when transcoding fails,
return a Subsonic error response (for stream/download/getTranscodeStream)
or HTTP 500 (for public shared streams). This gives clients a clear
signal that the request failed rather than a misleading empty success.

Signed-off-by: Deluan <deluan@navidrome.org>

* test(e2e): add tests for empty transcoded stream error responses

Add E2E tests verifying that stream and download endpoints return
Subsonic error responses when transcoding produces empty output.
Extend spyStreamer with SimulateEmptyStream and SimulateError fields
to support failure injection in tests.

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor(server): extract stream serving logic into Stream.Serve method

Extract the duplicated non-seekable stream serving logic (header setup,
estimateContentLength, HEAD draining, io.Copy with error/empty detection)
from server/subsonic/stream.go and server/public/handle_streams.go into a
single Stream.Serve method on core/stream. Both callers now delegate to it,
eliminating ~30 lines of near-identical code.

* fix(server): return 200 with empty body for stream/download on empty transcoded output

Don't return a Subsonic error response when transcoding produces empty
output on stream/download endpoints — just log the error and return 200
with an empty body. The getTranscodeStream and public share endpoints
still return HTTP 500 for empty output. Stream.Serve now returns
(int64, error) so callers can check the byte count.

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-18 12:39:03 -04:00
Deluan
00b8fbd789 feat(artwork): add UIThumbnailSize constant and update cache warmer to pre-cache thumbnails
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Failing after 5s
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been skipped
Pipeline: Test, Lint, Build / Build (push) Has been skipped
Pipeline: Test, Lint, Build / Build-10 (push) Has been skipped
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been skipped
Pipeline: Test, Lint, Build / Lint Go code (push) Failing after 5s
Pipeline: Test, Lint, Build / Test JS code (push) Failing after 10s
Pipeline: Test, Lint, Build / Test Go code (push) Failing after 10s
Pipeline: Test, Lint, Build / Check Docker configuration (push) Successful in 2s
Pipeline: Test, Lint, Build / Lint i18n files (push) Failing after 3s
Pipeline: Test, Lint, Build / Package/Release (push) Has been skipped
Pipeline: Test, Lint, Build / Build-1 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-2 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-3 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-4 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-5 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-6 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-7 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-8 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-9 (push) Has been skipped
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been skipped
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been skipped
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been skipped
Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-18 08:52:52 -04:00
Deluan Quintão
31d94acfe7
fix(scanner): widen WASM panic recovery to cover tag/property reading (#5223)
* fix(scanner): widen WASM panic recovery to cover tag/property reading

The panic recovery in gotaglib's extractMetadata was only inside
openFile(), which covers taglib.OpenStream(). Panics from f.AllTags()
and f.Properties() (e.g. readString crashes on malformed files) were
uncaught, crashing the scanner subprocess with exit status 2.

Move the recover() up to extractMetadata() so it covers the entire
tag reading lifecycle, matching the CGO taglib wrapper's approach.

Fixes #5220

* fix(scanner): use consistent log key "filePath" in panic recovery

* fix(scanner): include stack trace in WASM panic recovery log

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-18 08:03:46 -04:00
Deluan
b5164c61ab build(worktree): add script for setting up git worktrees
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Failing after 5s
Pipeline: Test, Lint, Build / Lint Go code (push) Failing after 5s
Pipeline: Test, Lint, Build / Test Go code (push) Failing after 3s
Pipeline: Test, Lint, Build / Test JS code (push) Failing after 3s
Pipeline: Test, Lint, Build / Lint i18n files (push) Failing after 3s
Pipeline: Test, Lint, Build / Check Docker configuration (push) Successful in 2s
Pipeline: Test, Lint, Build / Build (push) Has been skipped
Pipeline: Test, Lint, Build / Build-1 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-2 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-3 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-4 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-5 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-6 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-7 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-8 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-9 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-10 (push) Has been skipped
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been skipped
Pipeline: Test, Lint, Build / Package/Release (push) Has been skipped
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been skipped
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been skipped
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been skipped
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been skipped
Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-17 21:34:00 -04:00
Deluan
a83ebd1c98 fix(ui): hide pagination during album list loading
Added a custom AlbumListPagination component that returns null while the
list is loading, preventing stale pagination controls from appearing
alongside the Loading spinner when navigating to the Random album view.
2026-03-17 20:49:35 -04:00
Deluan
d2a54243a8 fix(ui): prevent layout flash on album grid during cover loading
Added aspect-ratio: 1 to the cover container so it reserves the correct
square dimensions immediately on first render, before react-measure
reports the container width. Previously, contentRect.bounds.width started
as undefined/0, causing images to render with zero height and producing a
brief flash of compressed tiles before the measurement callback fired.
2026-03-17 20:24:21 -04:00
Deluan
b013b71ba9 fix(server): clean up uploaded artist images during GC
When artists are purged during garbage collection, any custom uploaded
cover images were left orphaned on disk. Modified purgeEmpty() to query
for uploaded_image filenames before the bulk DELETE, then remove the
corresponding files from disk afterwards. Image cleanup is best-effort
to avoid failing the GC if a file is already missing or inaccessible.

Also populated album_artists entries in the persistence test suite setup
to reflect the actual album-artist relationships from test data, ensuring
purgeEmpty() doesn't inadvertently delete shared test artists.
2026-03-17 19:47:09 -04:00
Deluan
ad92b752be chore(deps): update dependencies for go-sqlite3, golang.org/x packages
Some checks failed
Pipeline: Test, Lint, Build / Lint Go code (push) Failing after 12s
Pipeline: Test, Lint, Build / Get version info (push) Failing after 15s
Pipeline: Test, Lint, Build / Test Go code (push) Failing after 3s
Pipeline: Test, Lint, Build / Test JS code (push) Failing after 3s
Pipeline: Test, Lint, Build / Lint i18n files (push) Failing after 3s
Pipeline: Test, Lint, Build / Check Docker configuration (push) Successful in 2s
Pipeline: Test, Lint, Build / Build (push) Has been skipped
Pipeline: Test, Lint, Build / Build-1 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-2 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-3 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-4 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-5 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-6 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-7 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-8 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-9 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-10 (push) Has been skipped
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been skipped
Pipeline: Test, Lint, Build / Package/Release (push) Has been skipped
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been skipped
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been skipped
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been skipped
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been skipped
Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-17 18:34:13 -04:00
Kendall Garner
f39d75e7d2
fix(subsonic): never omit duration for AlbumID3 (#5217) 2026-03-17 13:20:10 -04:00
Deluan
693abe2f6b fix(build): regenerate package-lock.json for navidrome-music-player 4.25.2
The lockfile still referenced the local file path from testing,
causing CI to fail resolving the navidrome-music-player import.
Regenerated to point to the npm registry.
2026-03-17 12:28:20 -04:00
Deluan
a0fe728098 fix(player): fix play next after transcoding changes
Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-17 12:15:03 -04:00
Simon Teixidor
8f05f7815e
fix(server): use http.TimeFormat for Last-Modified header (#5219)
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Failing after 5s
Pipeline: Test, Lint, Build / Lint Go code (push) Failing after 5s
Pipeline: Test, Lint, Build / Test Go code (push) Failing after 3s
Pipeline: Test, Lint, Build / Test JS code (push) Failing after 4s
Pipeline: Test, Lint, Build / Check Docker configuration (push) Successful in 2s
Pipeline: Test, Lint, Build / Lint i18n files (push) Failing after 3s
Pipeline: Test, Lint, Build / Build (push) Has been skipped
Pipeline: Test, Lint, Build / Build-1 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-2 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-3 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-4 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-5 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-6 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-7 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-8 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-9 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-10 (push) Has been skipped
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been skipped
Pipeline: Test, Lint, Build / Package/Release (push) Has been skipped
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been skipped
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been skipped
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been skipped
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been skipped
Navidrome returns Last-Modified values like `Fri, 12 Dec 2025 03:32:26
UTC`. This is invalid according to RFC 7231 which requires HTTP dates to
use GMT instead of UTC. Switch to http.TimeFormat instead of
time.RFC1123 to resolve the issue.
2026-03-17 08:04:47 -04:00
Deluan Quintão
2f5b2b5135
fix(artwork): fallback mediafile cover art to disc artwork before album (#5216)
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Failing after 3s
Pipeline: Test, Lint, Build / Lint Go code (push) Failing after 9s
Pipeline: Test, Lint, Build / Test Go code (push) Failing after 2s
Pipeline: Test, Lint, Build / Lint i18n files (push) Failing after 3s
Pipeline: Test, Lint, Build / Build-4 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-5 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-6 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-7 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-8 (push) Has been skipped
Pipeline: Test, Lint, Build / Test JS code (push) Failing after 3s
Pipeline: Test, Lint, Build / Check Docker configuration (push) Successful in 2s
Pipeline: Test, Lint, Build / Build (push) Has been skipped
Pipeline: Test, Lint, Build / Build-1 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-2 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-3 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-9 (push) Has been skipped
Pipeline: Test, Lint, Build / Build-10 (push) Has been skipped
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been skipped
Pipeline: Test, Lint, Build / Package/Release (push) Has been skipped
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been skipped
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been skipped
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been skipped
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been skipped
* fix(artwork): fallback mediafile cover art to disc artwork before album

Changed the mediafile cover art fallback chain to go through disc artwork
before album artwork (mediafile → disc → album). Previously, mediafiles
without embedded art fell back directly to album cover, bypassing any
disc-specific artwork. Renamed AlbumCoverArtID() to DiscCoverArtID() to
encapsulate the disc-vs-album decision in a single method, used by both
CoverArtID() and the mediafile artwork reader.

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(artwork): fix cache invalidation for mediafile and album cover art

Include imagesUpdatedAt from album folders in the mediafile artwork
reader's cache key, so that when a cover image file changes on disk
(without audio metadata changes) the mediafile cache properly
invalidates. Also include CoverArtPriority unconditionally in the album
artwork reader's cache key hash, so that changing the priority order
with external services disabled correctly invalidates the album cache.

* fix(artwork): skip disc artwork resolution for single-disc albums

Single-disc albums with DiscNumber=1 were unnecessarily routed through
discArtworkReader, which does extra DB queries only to fall through to
album art anyway. Now only multi-disc albums use the disc fallback path.

* refactor(artwork): restore AlbumCoverArtID as a separate method

Extract AlbumCoverArtID back out of DiscCoverArtID so the single-disc
fallback path in reader_mediafile can reference it by name instead of
inlining the artwork ID construction.

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-16 18:08:39 -04:00
Deluan Quintão
e7c6e78dd0
fix(db): normalize timestamps and fix recently added album sorting (#5176)
Some checks are pending
Pipeline: Test, Lint, Build / Get version info (push) Waiting to run
Pipeline: Test, Lint, Build / Lint Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test Go code (push) Waiting to run
Pipeline: Test, Lint, Build / Test JS code (push) Waiting to run
Pipeline: Test, Lint, Build / Lint i18n files (push) Waiting to run
Pipeline: Test, Lint, Build / Check Docker configuration (push) Waiting to run
Pipeline: Test, Lint, Build / Build (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-1 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-2 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-3 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-4 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-5 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-6 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-7 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-8 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-9 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build-10 (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to GHCR (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Build Windows installers (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Package/Release (push) Blocked by required conditions
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Blocked by required conditions
* fix(db): normalize timestamps and fix recently added album sorting

SQLite stores timestamps as TEXT and uses string comparison for ORDER BY.
Timestamps in RFC3339 T-format ('2024-01-01T10:00:00Z') sort incorrectly
against space-format ('2024-01-01 10:00:00+00:00') because 'T' (ASCII 84)
> ' ' (ASCII 32), causing albums with T-format timestamps to appear as
newer than they are in the "Recently Added" list.

This adds a migration to normalize all T-format timestamps across all
tables to the space-format expected by go-sqlite3, wraps the
recently_added sort with datetime() to make it format-agnostic, and
replaces the plain album timestamp indexes with expression indexes to
maintain query performance.

* fix(test): improve recently_added sort test robustness

Use same-date timestamps (2024-01-15T08:00:00Z vs 2024-01-15 20:00:00)
so the T-vs-space character difference at position 10 actually triggers
the sorting bug. Initialize index variables to -1 and assert both test
albums are found before comparing positions.

* chore(db): update migration timestamp to 2026-03-16
2026-03-16 07:55:22 -04:00