Skip to content

feat: option to list playlist folders at the top#335

Merged
LargeModGames merged 2 commits into
LargeModGames:mainfrom
Ritze03:feat/playlist-folders-first
Jul 5, 2026
Merged

feat: option to list playlist folders at the top#335
LargeModGames merged 2 commits into
LargeModGames:mainfrom
Ritze03:feat/playlist-folders-first

Conversation

@Ritze03

@Ritze03 Ritze03 commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a behavior.group_folders_first toggle (Settings → "Playlist Folders First") that lists your Spotify playlist folders at the top of the Playlists tab, above playlists, keeping each group's existing order. Off by default. Handy because folders keep their creation date and otherwise sink to the bottom of the recency-sorted list.

Implementation

The reorder lives in get_playlist_display_items() — the single source of truth for the visible list — as a stable sort_by_key that hoists Folder items. get_playlist_display_count() and get_playlist_display_item_at() delegate to it, so rendering and index-based selection (keyboard + mouse) can't desync. No-op where there are no folders (slim/Web-API builds, non-Spotify sources), so nothing changes when the toggle is off.

Testing

  • New unit test: folders hoist stably only when enabled; selection index resolves against the reordered list.
  • cargo fmt --all, cargo clippy --no-default-features --features telemetry -- -D warnings, cargo test --no-default-features --features telemetry — all green (327 tests).

New behavior.group_folders_first toggle (Settings -> Playlist Folders
First) hoists Spotify playlist folders to the top of the Playlists tab,
above playlists, via a stable sort that preserves each group's existing
order. Off by default.

The reorder lives in get_playlist_display_items() (the single source of
truth for the visible list), with get_playlist_display_count() and
get_playlist_display_item_at() delegating to it, so rendering and
index-based selection (keyboard + mouse) stay consistent.

@LargeModGames LargeModGames left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Nice feature, and routing count/selection through get_playlist_display_items() is the right call. One thing to fix before merge though:

reconcile_playlist_selection bypasses the new folders-first sort. In src/infra/network/library.rs, both index lookups (~L1299 and ~L1332) compute the restored selection by enumerating playlist_folder_items.iter().filter(is_visible) — same filter, but without the group_folders_first sort that get_playlist_display_items() now applies. The resulting index is stored in selected_playlist_index, which rendering and get_playlist_display_item_at then resolve against the sorted list.

So with the toggle ON, after a library refresh: root [P0, folderA, P1, folderB], preferred = P1 → reconcile computes index 2 (P1's spot in unsorted order), but the displayed order is [A, B, P0, P1], so index 2 is now P0. The highlight lands on the wrong playlist whenever a folder precedes the selected playlist in root order.

Fix is small: derive these two indices from the sorted get_playlist_display_items() (or apply the same folder hoist) instead of re-filtering playlist_folder_items directly, so this path shares the single source of truth like the rest.

Everything else (config plumbing, stable sort key, settings wiring, unit test) looks correct.

reconcile_playlist_selection computed the restored selection index by
re-filtering playlist_folder_items directly, bypassing the folders-first
sort that get_playlist_display_items() applies. With group_folders_first
on, the stored index pointed into unsorted order while rendering and
get_playlist_display_item_at resolve against the sorted list, so the
highlight could land on the wrong playlist.

Source both index lookups from get_playlist_display_items() so this path
shares the single source of truth. Latent today (no UI path refreshes
with a playlist selected), but restores the invariant. Adds a regression
test for the [P0, folderA, P1, folderB] case.
@Ritze03 Ritze03 requested a review from LargeModGames July 4, 2026 23:17

@LargeModGames LargeModGames left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Re-reviewed after 7bad466. The reconcile_playlist_selection bypass is fixed exactly as intended: both index lookups (the direct-visible path at L1344 and the folder-descent path at L1376) now enumerate get_playlist_display_items() instead of re-filtering playlist_folder_items directly, so the stored selected_playlist_index is computed against the same sorted list that rendering and get_playlist_display_item_at resolve against. get_playlist_display_items() is now the sole place the visibility filter is applied.

The added regression test (reconcile_restores_selection_against_folders_first_order) nails the exact [P0, folderA, P1, folderB] failure case from the last review: with the toggle on, restoring selection to P1 now yields display index 3 and resolves back to the Playlist { index: 1 }, not P0.

Verified locally on the branch:

  • cargo clippy --no-default-features --features telemetry -- -D warnings — clean
  • cargo test --no-default-features --features telemetry — 328 passed, 0 failed

LGTM. Thanks for the quick turnaround.

@LargeModGames LargeModGames merged commit 7d4cb56 into LargeModGames:main Jul 5, 2026
11 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