Skip to content

Fix 'Create new playlist' button in 'currently playing' menu not adding the song into the created playlist#88

Merged
dddevid merged 2 commits intodddevid:masterfrom
Kreedyy:master
Mar 9, 2026
Merged

Fix 'Create new playlist' button in 'currently playing' menu not adding the song into the created playlist#88
dddevid merged 2 commits intodddevid:masterfrom
Kreedyy:master

Conversation

@Kreedyy
Copy link
Copy Markdown
Contributor

@Kreedyy Kreedyy commented Mar 8, 2026

Fixes #87

Summary by CodeRabbit

  • New Features

    • Now-playing flow creates playlists and refreshes the playlist list immediately after creation.
  • Bug Fixes

    • Improved error handling and clearer network error messages for playlist creation and updates.
    • More robust response validation for playlist operations to surface failures reliably.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 8, 2026

Warning

Rate limit exceeded

@Kreedyy has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 20 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e59508f3-5e75-4428-ba28-f57783792d53

📥 Commits

Reviewing files that changed from the base of the PR and between f32521f and 1bf92b5.

📒 Files selected for processing (1)
  • lib/services/subsonic_service.dart
📝 Walkthrough

Walkthrough

Replaces direct playlist creation in the now-playing flow with LibraryProvider.createPlaylist, and refactors SubsonicService.createPlaylist to build URLs with repeated songId query parameters, call Dio directly, and perform explicit response parsing and error handling.

Changes

Cohort / File(s) Summary
Now-playing playlist flow
lib/screens/now_playing_screen.dart
Replaces direct SubsonicService playlist creation with LibraryProvider.createPlaylist to create a playlist for the current song and trigger library refresh.
Subsonic HTTP and response handling
lib/services/subsonic_service.dart
Rewrites createPlaylist to construct endpoint URLs with individual songId query params, uses direct Dio GET requests, adds decoding of responses, validates subsonic-response.status == 'ok', and maps Dio errors to network errors. Also harmonizes updatePlaylist response parsing and adds debug logs.

Sequence Diagram(s)

sequenceDiagram
    participant UI as NowPlayingScreen
    participant Provider as LibraryProvider
    participant Service as SubsonicService
    participant Server as Subsonic Server

    UI->>Provider: createPlaylist(name, [songId])
    Provider->>Service: createPlaylist(name, [songId])
    Service->>Server: GET /createPlaylist?songId=...&name=...
    Server-->>Service: HTTP 200 with subsonic-response
    Service-->>Provider: parsed result / success or error
    Provider-->>UI: success -> refresh playlists / error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped from now-playing into the code,
Swapped a call, built a URL on the road,
Songs now land where playlists grow,
Responses parsed, the logs now know,
A little hop, and the library glows. 🎶

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main issue being fixed: enabling the 'Create new playlist' button in the currently playing menu to add songs to the created playlist.
Linked Issues check ✅ Passed The PR addresses both objectives from issue #87: adds the current song to newly created playlists via LibraryProvider.createPlaylist [#87] and refreshes the library UI after playlist creation [#87].
Out of Scope Changes check ✅ Passed All changes are within scope: modifications to now_playing_screen.dart and subsonic_service.dart focus exclusively on fixing playlist creation and adding songs, with proper response handling and error management.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/services/subsonic_service.dart`:
- Around line 468-470: The code sets subsonicResponse differently for String vs
Map data but when response.data is a JSON string json.decode(data) returns the
whole payload instead of the nested 'subsonic-response' object; change the
String branch to json.decode(data)['subsonic-response'] (or decode to a Map and
then read the 'subsonic-response' key) so the variable subsonicResponse always
holds the nested object used later when checking status; update the logic around
response.data / json.decode accordingly to avoid reading status from the wrong
level.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 971c78b1-9e47-4689-bde4-285088e691ed

📥 Commits

Reviewing files that changed from the base of the PR and between 8b4aa2c and 04f3a28.

📒 Files selected for processing (2)
  • lib/screens/now_playing_screen.dart
  • lib/services/subsonic_service.dart

Comment thread lib/services/subsonic_service.dart Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/services/subsonic_service.dart (1)

494-525: ⚠️ Potential issue | 🟠 Major

Avoid logging the raw updatePlaylist URL.

Line 508 prints the fully assembled URL, which includes auth query params (u and either p or t/s). That bypasses _sanitizeUrl() and can leak credentials into device logs or crash reports.

🔒 Proposed fix
-    debugPrint('updatePlaylist URL: $url');
+    debugPrint('updatePlaylist URL: ${_sanitizeUrl(url)}');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/services/subsonic_service.dart` around lines 494 - 525, The
updatePlaylist method currently logs the full URL (variable url) which may
contain auth credentials; replace that raw logging by passing the URL through
the existing _sanitizeUrl helper before printing (i.e., use _sanitizeUrl(url) in
the debugPrint call) so credentials are redacted; update the debugPrint in
updatePlaylist accordingly and ensure _sanitizeUrl is used wherever raw URLs are
logged elsewhere in this class (e.g., any other debugPrints that reference
_buildUrl output).
🧹 Nitpick comments (1)
lib/services/subsonic_service.dart (1)

464-480: Extract the Subsonic unwrap/status check into one helper.

createPlaylist, updatePlaylist, jukeboxControl, and _request are now all decoding and validating the same payload shape a little differently. Pulling that into one helper will keep playlist creation/update behavior aligned and prevent the next response-parsing fix from landing in only one path.

♻️ Sketch of the refactor
-      final response = await _dio.get(url);
-      final data = response.data;
-
-      final decoded = data is String ? json.decode(data) : data;
-      final subsonicResponse = decoded['subsonic-response'];
-      if (subsonicResponse == null) {
-        throw Exception('Invalid response format');
-      }
-
-      if (subsonicResponse['status'] != 'ok') {
-        final error = subsonicResponse['error'];
-        throw Exception(error?['message'] ?? 'Unknown error');
-      }
+      _parseSubsonicResponse((await _dio.get(url)).data);
Map<String, dynamic> _parseSubsonicResponse(dynamic data) {
  final decoded = data is String ? json.decode(data) : data;
  final subsonicResponse = decoded['subsonic-response'];
  if (subsonicResponse == null) {
    throw Exception('Invalid response format');
  }
  if (subsonicResponse['status'] != 'ok') {
    final error = subsonicResponse['error'];
    throw Exception(error?['message'] ?? 'Unknown error');
  }
  return Map<String, dynamic>.from(subsonicResponse as Map);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/services/subsonic_service.dart` around lines 464 - 480, Multiple methods
(createPlaylist, updatePlaylist, jukeboxControl, and _request) duplicate
decoding/validation of the Subsonic payload; extract that logic into a single
helper (e.g., _parseSubsonicResponse) that accepts the raw response data,
decodes JSON when necessary, validates presence of 'subsonic-response', checks
status == 'ok', throws the same Exceptions on error, and returns the validated
subsonic-response as a Map<String, dynamic>; then replace the inline
decoding/validation in createPlaylist, updatePlaylist, jukeboxControl, and
_request to call _parseSubsonicResponse and use its returned map.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@lib/services/subsonic_service.dart`:
- Around line 494-525: The updatePlaylist method currently logs the full URL
(variable url) which may contain auth credentials; replace that raw logging by
passing the URL through the existing _sanitizeUrl helper before printing (i.e.,
use _sanitizeUrl(url) in the debugPrint call) so credentials are redacted;
update the debugPrint in updatePlaylist accordingly and ensure _sanitizeUrl is
used wherever raw URLs are logged elsewhere in this class (e.g., any other
debugPrints that reference _buildUrl output).

---

Nitpick comments:
In `@lib/services/subsonic_service.dart`:
- Around line 464-480: Multiple methods (createPlaylist, updatePlaylist,
jukeboxControl, and _request) duplicate decoding/validation of the Subsonic
payload; extract that logic into a single helper (e.g., _parseSubsonicResponse)
that accepts the raw response data, decodes JSON when necessary, validates
presence of 'subsonic-response', checks status == 'ok', throws the same
Exceptions on error, and returns the validated subsonic-response as a
Map<String, dynamic>; then replace the inline decoding/validation in
createPlaylist, updatePlaylist, jukeboxControl, and _request to call
_parseSubsonicResponse and use its returned map.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 66ccc39b-9179-4b34-9d39-c92c3e8cf32b

📥 Commits

Reviewing files that changed from the base of the PR and between 04f3a28 and f32521f.

📒 Files selected for processing (1)
  • lib/services/subsonic_service.dart

@dddevid dddevid merged commit e9055f7 into dddevid:master Mar 9, 2026
1 check 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.

Creating new playlist from 'currently playing' menu not adding song to newly created playlist

2 participants