* fix(ui): improve the lyric button of the AMusic theme
* fix(amusic): update styles for music player panel SVG and disabled button states
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
Fixed issue #4787 where plugin scrobblers received an empty username during NowPlaying events. The async worker was passing context.Background() which lost all user information.
Changed nowPlayingEntry to store the full context (with cancellation removed via context.WithoutCancel) and pass it to dispatchNowPlaying. This ensures plugin scrobblers can extract username from the context for authorization checks.
Updated tests to verify username is properly propagated through the async workflow, matching the actual plugin adapter behavior of checking both request.UsernameFrom and request.UserFrom.
* fix: handle cross-library relative paths in playlists
Playlists can now reference songs in other libraries using relative paths.
Previously, relative paths like '../Songs/abc.mp3' would not resolve correctly
when pointing to files in a different library than the playlist file.
The fix resolves relative paths to absolute paths first, then checks which
library they belong to using the library regex. This allows playlists to
reference files across library boundaries while maintaining backward
compatibility with existing single-library relative paths.
Fixes#4617
* fix: enhance playlist path normalization for cross-library support
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: improve handling of relative paths in playlists for cross-library compatibility
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: ensure longest library path matches first to resolve prefix conflicts in playlists
Signed-off-by: Deluan <deluan@navidrome.org>
* test: refactor tests isolation
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: enhance handling of library-qualified paths and improve cross-library playlist support
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: simplify mocks
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: lint
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: improve path resolution for cross-library playlists and enhance error handling
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: remove unnecessary path validation fallback
Remove validatePathInLibrary function and its fallback logic in
resolveRelativePath. The library matcher should always find the correct
library, including the playlist's own library. If this fails, we now
return an invalid resolution instead of attempting a fallback validation.
This simplifies the code by removing redundant validation logic that
was masking test setup issues. Also fixes test mock configuration to
properly set up library paths that match folder LibraryPath values.
* refactor: consolidate path resolution logic
Collapse resolveRelativePath and resolveAbsolutePath into a unified
resolvePath function, extracting common library matching logic into a
new findInLibraries helper method.
This eliminates duplicate code (~20 lines) while maintaining clear
separation of concerns: resolvePath handles path normalization
(relative vs absolute), and findInLibraries handles library matching.
Update tests to call resolvePath directly with appropriate parameters,
maintaining full test coverage for both absolute and relative path
scenarios.
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: add FindByPaths comment
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: enhance Unicode normalization for path comparisons in playlists. Fixes 4663
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* ci: improve docker manifest push reliability and isolation
Split Docker manifest push into separate GHCR and Docker Hub jobs to improve pipeline reliability and resilience:
- Separated push-manifest job into push-manifest-ghcr and push-manifest-dockerhub for independent execution
- Filter tags per registry using jq to prevent cross-registry push attempts
- Add automatic retry logic (3 attempts with 30s delay) for Docker Hub push using nick-fields/retry action
- Make Docker Hub job continue-on-error to prevent Docker Hub intermittent failures from failing the entire pipeline
- Add dedicated cleanup-digests job that only requires GHCR job success
- GHCR is now the critical path and will fail the pipeline if it fails, while Docker Hub failures are tolerated with retries
This addresses the recurring 400 Bad Request errors from Docker Hub registry that were causing pipeline failures even when ghcr.io push succeeded.
* fix(ci): use ghcr.io as source for docker hub manifest creation
The docker buildx imagetools create command needs to reference the source images from where they exist (ghcr.io) rather than from Docker Hub. The digests uploaded during the build step are stored on ghcr.io, so we need to pull from there and tag to Docker Hub.
* fix(ci): simplify Docker manifest push job names for clarity
* fix(ci): add permissions for Docker manifest push jobs
* fix(ci): update permissions for GHCR manifest push to write
* fix(ci): update Docker Hub image tagging in manifest creation
* fix(ci): update permissions for GHCR manifest push to read contents and write packages
* Revert "fix(ci): update Docker Hub image tagging in manifest creation"
This reverts commit b5f04d9c8b40a9f7d9c5952e5ca57c42dadfc20a.
* feat(server): add option Lastfm.ScrobbleFirstAlbumArtistOnly to send only the first album artist
* fix: remove config parameter scrobbleFirstAlbumArtist
* test: add NowPlaying test for ScrobbleFirstArtistOnly
Add a test case for the NowPlaying function when ScrobbleFirstArtistOnly is enabled. This ensures that only the first artist from the Participants list is sent to Last.fm for both artist and album artist fields, matching the existing test coverage for the Scrobble function.
* refactor: consolidate getArtistForScrobble and getAlbumArtistForScrobble
Merge the separate getArtistForScrobble and getAlbumArtistForScrobble functions into a single parameterized function. This eliminates code duplication and makes the scrobble artist handling logic more maintainable. The function now accepts a role parameter and display name, allowing it to handle both artist and album artist extraction based on the ScrobbleFirstArtistOnly configuration.
---------
Co-authored-by: Deluan <deluan@navidrome.org>
The bulk action buttons (Make Public, Make Private, Delete) on the playlists list were displaying with poor text contrast when using dark themes like AMusic. The buttons had pinkish text (theme's primary color) on a dark red background, making them difficult to read.
This fix applies the same styling pattern used for song bulk actions by adding a makeStyles hook that sets white text color for dark themes. This ensures proper contrast between the button text and background while maintaining correct styling on light themes.
Tested on AMusic (dark) and Light themes to verify contrast improvement and backward compatibility.
Signed-off-by: Deluan <deluan@navidrome.org>
Set document.body.style.backgroundColor to match the current theme's background
color whenever the theme changes. This fixes the white background that appeared
during pull-to-refresh gestures on mobile or overscroll on desktop, where the
browser reveals the area behind the app content.
The background color is determined by the theme's palette.background.default
value if defined, otherwise falls back to Material-UI defaults (#303030 for
dark themes, #fafafa for light themes).
Signed-off-by: Deluan <deluan@navidrome.org>
Always log the configuration source at startup: shows an INFO message with the
config file path when found, or a WARN message explaining how to specify one
when not found. This helps users understand why CLI commands may fail when
run outside of systemd (where --configfile is typically specified).
Closes#4758
* feat: make Unicode handling in external API calls configurable
- Add DevPreserveUnicodeInExternalCalls config option (default: false)
- Refactor external provider to use NameForExternal() method on auxArtist
- Remove redundant Name field from auxArtist struct
- Update all external API calls (image, URL, biography, similar, top songs, MBID) to use configurable Unicode handling
- Add comprehensive tests for both Unicode-preserving and normalized behaviors
- Refactor tests to use constants and improved structure with BeforeEach blocks
Fixes issue where Spotify integration failed to find artist images for artists with Unicode characters (e.g., en dash) in their names.
Signed-off-by: Deluan <deluan@navidrome.org>
* address comments
Signed-off-by: Deluan <deluan@navidrome.org>
* avoid calling str.Clean multiple times
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: apply Unicode handling pattern to auxAlbum
Extended the configurable Unicode handling to album names, matching the
pattern already implemented for artist names. This ensures consistent behavior
when DevPreserveUnicodeInExternalCalls is enabled for both artist and album
external API calls.
Changes:
- Removed Name field from auxAlbum struct, added Name() method with Unicode logic
- Updated getAlbum, UpdateAlbumInfo, populateAlbumInfo, and AlbumImage functions
- Added comprehensive tests for album Unicode handling (preserve and normalize)
- Fixed typo in artist image test description
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* Rename external auth options
ReverseProxyWhitelist was regularly confusing users that enabled it for
non-authenticating reverse proxy setups.
The new option name makes it clear that it's related to authentication, not
just reverse proxies.
* small refactor
Signed-off-by: Deluan <deluan@navidrome.org>
* add test
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
added: "quickscan", "fullscan"
updated:
- "manageUsers": `access` translates to `hozzáférés` in this context, not `elérés` (~reachableness)
- "quickscan", "fullscan", "scantype": updated to match new strings