feat: pin the community playlist to the top of the sidebar - #426
Conversation
Adds a pinned spotatui community entry at the top of the Spotify playlists sidebar that opens the shared playlist the Discord /queue bot fills. It is toggleable (default on) with a Settings row and a one-time first-run prompt that points people to /queue in Discord, and it hides itself once you follow the playlist. Also moves the Add Playlist button to the top of the sidebar and makes that row mouse-clickable, which it was not before.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds a configurable Spotify community playlist pin. The pin uses a synthetic sidebar row, appears after the add-playlist row, opens the playlist, and hides after following. A first-launch prompt records its state and supports keep, hide, and dismiss actions. ChangesCommunity playlist pin
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant SpotifyRefresh
participant App
participant Sidebar
participant User
participant CommunityPinPrompt
SpotifyRefresh->>App: refresh playlists
App->>App: check source, setting, follow state, and prompt state
App->>Sidebar: insert CommunityPin after + Add Playlist
App->>CommunityPinPrompt: open first-launch prompt when conditions match
User->>CommunityPinPrompt: choose H, Enter, or Esc
CommunityPinPrompt->>App: update setting and prompt state
App->>Sidebar: redraw playlist rows
Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/core/app.rs`:
- Around line 3417-3438: Update get_selected_playlist_id so the raw
self.playlists fallback subtracts the visible CommunityPin offset when the pin
is shown and playlist_folder_items is empty, matching the display ordering used
by get_playlist_display_items and the library UI. Preserve existing handling for
the add row, pin, folders, and normal display items. Add a regression test with
the pin visible, empty playlist_folder_items, and multiple raw playlists,
asserting a row after the pin returns the corresponding playlist id.
In `@src/tui/runner.rs`:
- Around line 774-777: Update the back-key handler in runner.rs to add an
ActiveBlock::CommunityPinPrompt branch alongside AnnouncementPrompt, invoking
handlers::community_pin_prompt::handler(Key::Esc, &mut app) instead of falling
through to app.pop_navigation_stack().
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: f625b7d9-1868-474f-a2e2-658158a658d4
📒 Files selected for processing (14)
CHANGELOG.mdsrc/core/app.rssrc/core/plugin_api.rssrc/core/state.rssrc/core/user_config.rssrc/infra/network/library.rssrc/tui/handlers/community_pin_prompt.rssrc/tui/handlers/mod.rssrc/tui/handlers/mouse.rssrc/tui/handlers/playlist.rssrc/tui/runner.rssrc/tui/ui/library.rssrc/tui/ui/mod.rssrc/tui/ui/popups.rs
| ActiveBlock::CommunityPinPrompt => { | ||
| ui::draw_main_layout(f, &app); | ||
| ui::draw_community_pin_prompt(f, &app); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Confirm back_key_clears_playlist_filter's scope and
# community_pin_prompt::handler's match arms, to validate the fix above.
rg -n -A20 'fn back_key_clears_playlist_filter' src/tui/runner.rs
fd community_pin_prompt.rs src/tui/handlers --exec cat -n {}
rg -n -B2 -A10 'fn handler\(key: Key, app: &mut App\)' src/tui/handlers/community_pin_prompt.rsRepository: LargeModGames/spotatui
Length of output: 6038
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== runner outline relevant regions =="
wc -l src/tui/runner.rs
rg -n -A8 -B8 'ActiveBlock::CommunityPinPrompt|ActiveBlock::AnnouncementPrompt|app.user_config.keys.back|Back|handle_app' src/tui/runner.rs | sed -n '1,220p'
echo "== handlers module imports/exports =="
cat -n src/tui/handlers/mod.rs | sed -n '1,120p'
echo "== network finish_playlists_fetch =="
wg='700,720'
if command -v sed >/dev/null; then
sed -n '700,720p' src/infra/network/library.rs | cat -n
fi
echo "== app field persistence =="
rg -n -B3 -A3 'community_pin_prompt_shown|save_runtime_state|PersistedRuntimeState' src/core src/lib.rs src/tui -g '*.rs' | sed -n '1,180p'
echo "== deterministic path check in runner source =="
python3 - <<'PY'
from pathlib import Path
p=Path("src/tui/runner.rs")
s=p.read_text()
checks={
"runner_imports_handlers_community_pin_prompt":"handlers::community_pin_prompt::handler" in s,
"runner_imports_handlers_module":"crate::tui::handlers" in s,
"community_pin_prompt_handler_mentions_back":any("ActiveBlock::CommunityPinPrompt" in line and s.split("\n").index(line) for line in s.splitlines()),
}
# Extract back-key block lines approximately
lines=s.splitlines(keepends=True)
for i,l in enumerate(lines,1):
if "app.user_config.keys.back" in l:
start=max(1,i-8); end=min(len(lines),i+28)
print(f"\n-- back-key block around line {i} --")
for n in range(start,end+1):
print(f"{n}: {lines[n-1]}", end="")
break
print(checks)
PYRepository: LargeModGames/spotatui
Length of output: 21516
Add a CommunityPinPrompt branch to the back-key handler.
Esc works because handlers::handle_app routes it to handlers::community_pin_prompt::handler(Key::Esc, app), which marks the prompt shown and persists it. The back key is handled earlier in src/tui/runner.rs and falls through to app.pop_navigation_stack() for ActiveBlock::CommunityPinPrompt, so the prompt closes without the shown flag and can reappear on the next playlist refresh, follow, or unfollow. Add a dedicated branch next to AnnouncementPrompt that calls handlers::community_pin_prompt::handler(Key::Esc, &mut app).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/tui/runner.rs` around lines 774 - 777, Update the back-key handler in
runner.rs to add an ActiveBlock::CommunityPinPrompt branch alongside
AnnouncementPrompt, invoking handlers::community_pin_prompt::handler(Key::Esc,
&mut app) instead of falling through to app.pop_navigation_stack().
Corrects two issues from review: the raw-page fallback in get_selected_playlist_id now offsets for the pinned row, so a selection past the pin maps to the right playlist while playlist_folder_items is still loading; and the first-run prompt is marked shown when it is pushed rather than only on dismiss, so it cannot reappear after a dismissal that bypasses the handler.
Summary
Pins the "spotatui community" playlist to the top of the Spotify playlists sidebar so people can open the shared, Discord-curated playlist in one keystroke. Toggleable (default on) via a Settings row and a one-time first-run prompt that tells people how to add songs (the
/queuecommand in the spotatui Discord). It hides itself automatically once you follow the playlist, so it never double-shows. Also moves "+ Add Playlist" to the top of the sidebar and makes that row mouse-clickable (it was keyboard-only before).Testing
cargo fmt --all: cleancargo clippy --no-default-features --features telemetry -- -D warnings: cleancargo test --no-default-features --features telemetry: 562 passedcargo check --features all-sources,cover-art: cleancargo clippy --features all-sources,cover-art -- -D warnings: cleanAdditional notes
PlaylistFolderItem::CommunityPinvariant, injected only at display time (never persisted), so the compiler enforces handling at every match site.state.yml(community_pin_prompt_shown); the pin and prompt only appear when Spotify is the active source and you don't already follow the playlist.💬 Questions or want to chat with other contributors? Join the spotatui Discord.
Summary by CodeRabbit