quintodrome/ui/src
adrbn d004f99f8f
feat(playlist): add custom playlist cover art upload (#5110)
* feat(playlist): add custom playlist cover art upload - #406

Allow users to upload, view, and remove custom cover images for playlists.
Custom images take priority over the auto-generated tiled artwork.

Backend:
- Add `image_path` column to playlist table (migration with proper rollback)
- Add `SetImage`/`RemoveImage` methods to playlist service
- Add `POST/DELETE /api/playlist/{id}/image` endpoints
- Prioritize custom image in artwork reader pipeline
- Clean up image files on playlist deletion
- Use glob-based cleanup to prevent orphaned files across format changes
- Reject uploads with undetermined image type (400)

Frontend:
- Hover overlay on playlist cover with upload (camera) and remove (trash) buttons
- Lightbox for full-size cover art viewing
- Cover art thumbnails in the playlist list view
- Loading/error states and i18n strings

Closes #406

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: adrbn <128328324+adrbn@users.noreply.github.com>

* refactor: rename playlist image path migration file

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

* fix(playlist): address review feedback for cover art upload - #406

- Use httpClient instead of raw fetch for image upload/remove
- Revert glob cleanup to simple imagePath check
- Add log.Error before all error HTTP responses
- Add backend tests for SetImage and RemoveImage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: adrbn <128328324+adrbn@users.noreply.github.com>

* refactor(playlist): use Playlist.ArtworkPath() for image storage

Migrate all playlist image path handling to use the new
Playlist.ArtworkPath() method as the single source of truth. The DB now
stores only the filename (e.g. "pls-1.jpg") instead of a relative path,
and images are stored under {DataFolder}/artwork/playlist/ instead of
{DataFolder}/playlist_images/. The artwork root directory is created at
startup alongside DataFolder and CacheFolder. This also removes the
conf dependency from reader_playlist.go since path resolution is now
fully encapsulated in the model.

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

* refactor(playlist): streamline artwork image selection logic

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

* refactor: move translation keys, add pt-BR translations

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

* refactor(playlist): rename image_path to image_file

Rename the playlist cover art column and field from image_path/ImagePath
to image_file/ImageFile across the migration, model, service, tests, and
UI. The new name more accurately describes what the field stores (a
filename, not a path) and aligns with the existing ImageFiles/IsImageFile
naming conventions in the codebase.

---------

Signed-off-by: adrbn <128328324+adrbn@users.noreply.github.com>
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
2026-03-01 14:07:18 -05:00
..
actions feat: Multi-library support (#4181) 2025-07-18 18:41:12 -04:00
album chore: format JSX components 2026-02-03 12:46:39 -05:00
artist fix(ui): use div for fragment, check lastfm url for artist page (#4980) 2026-02-04 17:34:26 -05:00
audioplayer feat(ui): prompt before closing window if music is playing (#4899) 2026-01-18 13:11:12 -05:00
common feat(server): implement FTS5-based full-text search (#5079) 2026-02-21 17:52:42 -05:00
dataProvider fix(ui): fix library selection state for single-library users (#4686) 2025-11-15 17:42:28 -05:00
dialogs feat(ui): add download config toml link, disable copy when clipboard not available (#5035) 2026-02-12 10:54:04 -05:00
i18n feat(playlist): add custom playlist cover art upload (#5110) 2026-03-01 14:07:18 -05:00
icons build(ui): migrate from CRA/Jest to Vite/Vitest (#3311) 2024-09-28 11:54:36 -04:00
layout feat(server): add ExtAuth logout URL configuration (#5074) 2026-02-23 20:28:38 -05:00
library feat(ui): conditionally display 'path' field in LibraryList for desktop view 2026-03-01 10:50:37 -05:00
missing fix(ui): export all missing files instead of first 1000 2025-12-16 06:43:02 -05:00
personal fix(ui): show last.fm api-key missing in a FormHelperText 2024-12-19 16:59:26 -05:00
player build(ui): migrate from CRA/Jest to Vite/Vitest (#3311) 2024-09-28 11:54:36 -04:00
playlist feat(playlist): add custom playlist cover art upload (#5110) 2026-03-01 14:07:18 -05:00
plugin feat(plugins): allow mounting library directories as read-write (#5122) 2026-02-28 10:59:13 -05:00
radio fix(ui): update titles for radios, shares and show pages (#4128) 2025-05-27 09:01:52 -04:00
reducers fix(ui): prevent "Play Next" restarting play at top of queue (#5049) 2026-02-17 08:34:24 -05:00
share fix(ui): allow scrolling in shareplayer queue by adding delay #4748 2025-11-29 12:54:46 -05:00
song feat(ui): add composer field to table views (#4857) 2026-01-18 13:15:53 -05:00
store feat: Multi-library support (#4181) 2025-07-18 18:41:12 -04:00
subsonic feat(scanner): implement selective folder scanning and file system watcher improvements (#4674) 2025-11-14 22:15:43 -05:00
themes fix(ui): make toggle switches visible in Gruvbox Dark theme (#5063) (#5064) 2026-02-18 15:38:20 -05:00
transcoding fix(ui): minor icon inconsistencies and "no missing files" translation (#3837) 2025-03-16 19:39:19 -04:00
user feat: Multi-library support (#4181) 2025-07-18 18:41:12 -04:00
utils fix(ui): use div for fragment, check lastfm url for artist page (#4980) 2026-02-04 17:34:26 -05:00
App.jsx feat(plugins): New Plugin System with multi-language PDK support (#4833) 2026-01-14 19:22:48 -05:00
authProvider.js feat(server): add ExtAuth logout URL configuration (#5074) 2026-02-23 20:28:38 -05:00
config.js feat(server): implement FTS5-based full-text search (#5079) 2026-02-21 17:52:42 -05:00
consts.js feat(Insights): add anonymous usage data collection (#3543) 2024-12-17 17:10:55 -05:00
eventStream.js fix(ui): keep the NowPlayingPanel badge in sync. 2025-06-29 11:35:10 -04:00
eventStream.test.js chore(deps): update all dependencies (#4618) 2025-10-25 17:05:16 -04:00
hotkeys.js Change "Go to current song" hotkey. 2022-12-18 20:58:01 -05:00
index.css chore(deps): bump JS dependencies 2025-03-07 19:47:08 -05:00
index.jsx fix(ui): service worker does not load new version of ui (#3402) 2024-10-16 21:39:14 -04:00
routes.jsx build(ui): migrate from CRA/Jest to Vite/Vitest (#3311) 2024-09-28 11:54:36 -04:00
setupTests.js Use the default import path for jest-dom. 2024-01-17 17:07:43 -05:00
sw.js fix(ui): service worker crashing on precacheAndRoute (#3528) 2024-12-08 17:43:34 -05:00
useChangeThemeColor.jsx build(ui): migrate from CRA/Jest to Vite/Vitest (#3311) 2024-09-28 11:54:36 -04:00
vite-env.d.ts build(ui): migrate from CRA/Jest to Vite/Vitest (#3311) 2024-09-28 11:54:36 -04:00