Skip to content

Add MUSIC_LIBRARIES checkbox UI to setup wizard and migration assistant#459

Merged
NeptuneHub merged 12 commits intoNeptuneHub:mainfrom
rendyhd:feat/music-libraries-checkbox-ui
May 1, 2026
Merged

Add MUSIC_LIBRARIES checkbox UI to setup wizard and migration assistant#459
NeptuneHub merged 12 commits intoNeptuneHub:mainfrom
rendyhd:feat/music-libraries-checkbox-ui

Conversation

@rendyhd
Copy link
Copy Markdown
Contributor

@rendyhd rendyhd commented Apr 25, 2026

STILL TESTING


Replaces the "type comma-separated library names" advanced field with a checkbox list rendered after a successful test connection.

Setup wizard (/setup)

  • New POST /api/setup/providers/libraries returns the live library list using the form's credentials.
  • setup.html + setup.js render checkboxes below the test-connection result; pre-checked from saved MUSIC_LIBRARIES; auto-fetches on page load when the provider is already configured.
  • MUSIC_LIBRARIES removed from the Advanced section; saved alongside provider creds.

Migration assistant (/provider-migration)

  • New POST /api/migration/libraries (uses session creds, never config) and POST /api/migration/libraries/select (writes to migration_session.state['selected_libraries']).
  • Step 2 renders the checkbox list after test connection. Selection POSTs are debounced (300 ms) so rapid clicks don't race the JSONB read-modify-write in _update_state.
  • _write_provider_to_app_config now writes MUSIC_LIBRARIES at execute time — overwriting (or deleting) the source provider's old value.

Library listers — new sibling functions (one per provider) that return the raw [{id, name}] list with optional user_creds. Existing get_target* filter helpers untouched.

Sustainable Navidrome migration fix

  • _get_target_music_folder_ids(user_creds=None) now forwards creds into _navidrome_request, so getMusicFolders works against a target server during migration.
  • get_all_songs(user_creds=None, apply_filter=True) — explicit flag; provider_probe.fetch_all_tracks passes apply_filter=False because config.MUSIC_LIBRARIES holds the source provider's names, which would falsely zero out the target catalog during dry-run.

The contract is now visible in the function signature instead of inferred from another argument's presence.

rendyhd and others added 2 commits April 25, 2026 17:18
After a successful test connection, the setup wizard and migration
assistant now fetch the provider's actual library list and render a
checkbox per library. All checked = scan everything. Selection persists
to the same MUSIC_LIBRARIES app_config key, replacing the easy-to-mistype
free-text advanced field. The migration write also wipes the source
provider's old filter value automatically (single shared key).

Sustainable Navidrome migration fix: rather than the implicit "skip
filter when user_creds is set" heuristic, threads user_creds through
_get_target_music_folder_ids and adds an explicit apply_filter parameter
on get_all_songs. Migration probes pass apply_filter=False so the source
provider's library names don't falsely zero out the target catalog
during dry-run; live-provider scans default to apply_filter=True so the
saved selection is still honored.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a library selection feature for the setup wizard and migration assistant, allowing users to filter which music folders are scanned. New API endpoints and UI components were added to support listing and persisting these selections across various media server providers. Review feedback points out that the filtering logic is currently only active for Navidrome, rendering the UI selection ineffective for other providers. It was also suggested that the migration dry-run should incorporate the user's target library selection for accurate track matching, and that the Navidrome implementation should more robustly handle API responses that return single objects instead of lists.

Comment thread tasks/mediaserver.py
Comment thread tasks/provider_probe.py
Comment thread tasks/mediaserver_navidrome.py Outdated
Subsonic-compatible servers may return musicFolder as a single dict
(not a list) when only one folder exists, depending on the JSON parser
configuration. Coerce to a list in both list_libraries and
_get_target_music_folder_ids so iteration is consistent. Adds a
regression test covering the single-folder response shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@NeptuneHub
Copy link
Copy Markdown
Owner

NeptuneHub commented Apr 25, 2026

Just some observation, for the migration:

  • you put it in step 2: user select the provider, do test connection, IF it success it return also the list of music library with the checkbox of the new provider
  • Run automatic matching at step 3 will use them. If you want to change the result you need to change the selection at step 2 and re run the matching at step 3
  • IF user reload the page in the middle, I did a step that read the status to the database. So you need to save also this status in the database. IF you want to change this selection after a refresh you need to click the button "discard"

For the setup wizard:

  • decide if you want to keep or not in the advanced parameter list: maybe not all user need it?
  • If you put out of the advanced parameter list, remove from there. Avoid to have it duplicated.
  • Off course save button will save also it => add some kind of disclaimer that this take effect only for new analysis. So if you add new music library you can run an analysis and analyze the new. IF you then need to do a cleaning task (please check that cleaning task work good by removing music library).

In both the scenario you keep MUSIC_LIBRARY parameter in the config table as a comma separated list and you please avoid to change the logic to avoid regression.
The logic is:

  • Empty list: use all the music library
  • List present: use only the present one.

Off course if you have better idea let me know.

@rendyhd
Copy link
Copy Markdown
Contributor Author

rendyhd commented Apr 25, 2026

Just some observation, for the migration:

* you put it in step 2: user select the provider, do test connection, IF it success it return also the list of music library with the checkbox of **the new provider**

* Run automatic matching at step 3 will use them. If you want to change the result you need to change the selection at step 2 and re run the matching at step 3

* IF user reload the page in the middle, I did a step that read the status to the database. So you need to save also this status in the database. IF you want to change this selection after a refresh you need to click the button "discard"

Currently provider_probe.fetch_all_tracks passes apply_filter=False, so dry-run fetches the entire target catalog regardless of selection. So it's not used for step 3. For migration all tracks are used because starting point is existing library.

Regarding the reload, that needs to be fixed

For the setup wizard:

* decide if you want to keep or not in the advanced parameter list: maybe not all user need it?

* If you put out of the advanced parameter list, remove from there. Avoid to have it duplicated.

It is removed from advanced fields, no duplication.

* Off course save button will save also it => add some kind of disclaimer that this take effect only for new analysis. So if you add new music library you can run an analysis and analyze the new. IF you then need to do a cleaning task (please check that cleaning task work good by removing music library).

Will add the disclaimer
Checking for the cleaning task

In both the scenario you keep MUSIC_LIBRARY parameter in the config table as a comma separated list and you please avoid to change the logic to avoid regression. The logic is:

* Empty list: use all the music library

* List present: use only the present one.

Already what I have.

rendyhd and others added 2 commits April 25, 2026 20:53
Lyrion's scan-time filter (_get_target_paths_for_filtering) treats
MUSIC_LIBRARIES as filesystem paths and substring-matches them against
album file URLs. Prior to this change list_libraries returned the folder
name, so a user who picked "MyMusic" in the checkbox UI wrote
MUSIC_LIBRARIES="MyMusic" — which only matched if the folder name
happened to be a substring of the file path (a brittle coincidence).

list_libraries now returns the path reported by the musicfolders
JSON-RPC command as the display/persisted name, falling back to the
folder name when the server omits the path. The saved MUSIC_LIBRARIES
value now matches what _get_target_paths_for_filtering expects, so the
Cleaning task and live-provider scans correctly include/exclude the
selected libraries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Migration: /api/migration/libraries now also returns
state.selected_libraries; renderMigLibraries pre-checks the matching
names so a page reload in step 2 shows the user's prior selection
instead of resetting to all-checked. The maintainer's UX expectation
("if you want to change selection after a refresh, click discard") now
holds: refresh preserves state, discard is the only way to reset.

Setup wizard: added a small disclaimer below the music-libraries
checkbox list explaining that changes only affect new analyses, and
that Cleaning is the way to remove already-analyzed tracks from
libraries the user unchecks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@NeptuneHub
Copy link
Copy Markdown
Owner

Ok I think it make sense: if you already analyzed them you already want them without overcomplicating the logic. So you select the library of the target server to find all of your song on the target server.

rendyhd and others added 4 commits April 28, 2026 10:43
Two fixes for the library checkbox UI:

* The global ``.field-row input { width: 100% }`` rule was stretching
  each checkbox across the row, pushing the library names to the far
  right. Override the checkbox width/margin inline so it sits flush
  against its label text.

* When the saved MUSIC_LIBRARIES value has no overlap with the current
  provider's library names (e.g. user pointed the wizard at a
  different server, or library names changed), the rendered list was
  showing every box unchecked plus the "select at least one" hint —
  looked like a bug to the user. Detect "stale selection has zero
  matches" and fall back to all-checked, matching the maintainer's
  "empty MUSIC_LIBRARIES means scan everything" semantics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When Navidrome's "Report Real Path" setting is disabled, the
``getAlbum`` and ``search3`` Subsonic responses report the file path
under ``url`` instead of ``path``. ``navidrome_test_connection`` (the
step-2 probe) already handled this with ``s.get('path') or s.get('url')``,
but ``get_all_songs`` (the step-3 dry-run probe) and
``get_tracks_from_album`` only read ``path``, leaving the migration
matcher with no path data.

Pre-existed but was masked: prior to the apply_filter=False path, the
migration probe usually fell through ``_get_target_music_folder_ids``'s
empty-set branch and returned 0 songs (the bug commit b426682 was
trying to fix). Now that the dry-run actually returns songs, the
missing url fallback breaks path-based matching.

Apply the same ``path or url`` fallback in both helpers to restore
path detection in the dry-run when Report Real Path is off.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ename

Two interconnected bugs that prevented the migration assistant from
ever showing checkboxes for a Lyrion target:

* Wrong CLI command. The JSON-RPC command is ``musicfolder`` (singular).
  ``musicfolders`` (plural) is undocumented on Lyrion 9.0.x and the
  server drops the connection without responding ("Connection
  aborted, RemoteDisconnected"). The pre-existing
  ``_get_target_music_folder_ids`` had the same plural bug but it's
  dead code — ``get_recent_albums`` uses ``_get_target_paths_for_filtering``
  for live filtering, so nobody actually exercised
  ``_get_target_music_folder_ids``. ``list_libraries`` was the first
  caller to actually invoke the broken command and surface the issue.

* Wrong field name on Lyrion 9.0.x. The folder loop entries report the
  display name under ``filename``, not ``name`` or ``folder`` (which
  older Lyrion versions used). The previous code skipped every folder
  because it required ``name``/``folder``, so even after fixing the
  command the list would have come back empty.

list_libraries now calls ``musicfolder`` and reads
``filename or name or folder`` so it works against both 9.0.x and
older releases. Adds a regression test covering the 9.0.x response
shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rendyhd rendyhd marked this pull request as ready for review April 28, 2026 09:14
@rendyhd
Copy link
Copy Markdown
Contributor Author

rendyhd commented Apr 28, 2026

@NeptuneHub tested every provider

@rendyhd
Copy link
Copy Markdown
Contributor Author

rendyhd commented May 1, 2026

@NeptuneHub just make sure you didn't miss. Think it's done. UI improvement for setup wizard, adding library filter to migration and fix for #449

NeptuneHub added 3 commits May 1, 2026 13:18
…matched cap

- Add 'No restriction' pseudo-checkbox in setup + migration library pickers (empty list = scan all); preserve checkbox state across test-connection re-renders.
- Cap unmatched-albums payload at MIGRATION_UNMATCHED_ALBUMS_PAYLOAD_LIMIT (env/DB-overridable, default 200); show truncation warning with full count.
- Step-4 'matched albums' view now lists only manually-corrected albums and labels them as such; refresh list after every match (not just rematch).
- Make Prev/Next pagination buttons use btn-primary.
@NeptuneHub
Copy link
Copy Markdown
Owner

Hi rendy here my review:

  • From an UX point of view, the fact that in the migration you select some library but then you match againstr all is not the best. Anyway I still things that this is the safe approch to don't lose data. Let's merge in this way for now but please brainstorm for the future a better UX flow. Here the risk is that the user deselect some library for error, see ALL the song matched, and then don't understand the error.

Then I directly push some fix:

  • For both Setup Wizard and Migration, in the music library I added the option to "no add restriction" that match the fact that you want to match everything and not a restricted list
  • I did a fix on the UI so that when you click check connection you don't lose the previous state, this on both setup and migration
  • For migration I found out that if you have long list of unmatched song UI become very slow to show thousand of unmatched song. Is not fesable that an user match manually more than few album, so I put a configurable paramter that cap to 200
  • Still for migration, the list of automated matched is anotbher time a very long lit. I did in a way that in this list only the manually matched song appear.

Please do a re-check of this change to be sure I didn't introduced any bug (better have a doublecheck):
If it's all ok please confirm and I'll merge, otherwise let's discuss any other possible issue on this.

Thanks!

@NeptuneHub
Copy link
Copy Markdown
Owner

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces music library filtering for both the setup wizard and the provider migration process. It adds backend logic to list libraries from various media servers, frontend checkbox UI for selection, and persistence of these settings in the application configuration. Additionally, it optimizes the migration review process by capping the number of unmatched albums and refining song-fetching filters. Feedback was provided to improve error handling consistency by using standard HTTP error codes for failed library listing requests.

Comment thread app_provider_migration.py
@NeptuneHub NeptuneHub merged commit bb63082 into NeptuneHub:main May 1, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants