Skip to content

feat: enhance login capabilities with error messages, QR code, and cookie persistence#2

Open
Zhenghao-Wen wants to merge 14 commits into2697a:masterfrom
Zhenghao-Wen:login_test
Open

feat: enhance login capabilities with error messages, QR code, and cookie persistence#2
Zhenghao-Wen wants to merge 14 commits into2697a:masterfrom
Zhenghao-Wen:login_test

Conversation

@Zhenghao-Wen
Copy link
Copy Markdown

@Zhenghao-Wen Zhenghao-Wen commented Feb 25, 2026

Description

This PR significantly improves the login functionality of the library:

  1. LoginEntity: Added message field to receive server error details (e.g., code 8860), allowing clients to display user-friendly error messages.
  2. QR Code Login: Fully implemented the three required endpoints (/login/qr/key, /login/qr/create, /login/qr/check) with proper cookie extraction.
  3. Cookie Management: Introduced addCookie(String cookieStr) and clearCookies() methods that store cookies in cookieJar (persistent). The previous setCookie (memory only) is deprecated but kept for backward compatibility.
  4. Code Generation: Unified all entity files to use part directives instead of export. Regenerated all .g.dart files to ensure they are in sync with the entities. Fixed missing _ in private method calls.
  5. Dependencies: Downgraded json_annotation to ^4.10.0 for compatibility with json_serializable ^6.7.0.

Testing

  • Manual testing with both phone number + captcha and QR code login flows.
  • Verified that after QR code login, the obtained cookie is correctly stored and survives app restarts.
  • All existing APIs (playlist, song, etc.) remain unaffected.

Notes

  • This PR does not introduce any breaking changes to existing public APIs.
  • The setCookie method is now deprecated; use addCookie instead (which is asynchronous, so remember to await it).

Please review and let me know if any further adjustments are needed.

Actually, this is my first pull request and my fork may no longer be maintained.

Summary by CodeRabbit

  • New Features

    • Added QR code login functionality for user authentication.
    • Introduced manual cookie management for enhanced session handling.
  • Chores

    • Updated JSON serialization infrastructure for improved data handling.
    • Expanded public API exports for better library usability.
    • Added development dependencies for code generation support.
    • Re-enabled shared preferences dependency.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

This pull request refactors JSON serialization across multiple entity files from an export-based pattern to a part-based pattern using json_serializable, adds generated serialization helpers for several entities, introduces a new QR code login flow with cookie management support, and adds new public API exports and dependencies.

Changes

Cohort / File(s) Summary
JSON Serialization Infrastructure Migration
lib/api/album/entity/album_info_entity.dart, lib/api/album/entity/new_album_entity.dart, lib/api/mv/entity/mv_url_entity.dart, lib/api/playlist/entity/catalogue_entity.dart, lib/api/playlist/entity/create_playlist_entity.dart, lib/api/playlist/entity/high_quality_tags_entity.dart, lib/api/playlist/entity/playlist_detail_entity.dart, lib/api/recommend/entity/recommend_resource_entity.dart, lib/api/recommend/entity/recommend_song_entity.dart, lib/api/song/entity/new_song_entity.dart, lib/api/song/entity/song_detail_entity.dart, lib/api/song/entity/song_quality_detail_entity.dart, lib/api/song/entity/song_url_entity.dart, lib/api/top/entity/top_artist_entity.dart, lib/api/user/entity/bool_entity.dart, lib/api/user/entity/like_list_entity.dart, lib/api/user/entity/qrcode_key_entity.dart, lib/api/user/entity/string_entity.dart, lib/api/user/entity/user_info_entity.dart, lib/api/user/entity/user_playlist_entity.dart
Migrated JSON (de)serialization from generated $ClassName{FromJson,ToJson} helpers to _$ClassName{FromJson,ToJson} style via part directive and json_annotation import, replacing previous export-based pattern. All .dart files updated with new generator references; corresponding .g.dart files added or modified with generated serialization boilerplate.
Generated Serialization Files
lib/api/album/entity/album_info_entity.g.dart, lib/api/album/entity/new_album_entity.g.dart, lib/api/mv/entity/mv_url_entity.g.dart, lib/api/playlist/entity/catalogue_entity.g.dart, lib/api/playlist/entity/create_playlist_entity.g.dart, lib/api/playlist/entity/high_quality_tags_entity.g.dart, lib/api/playlist/entity/playlist_detail_entity.g.dart, lib/api/recommend/entity/recommend_resource_entity.g.dart, lib/api/recommend/entity/recommend_song_entity.g.dart, lib/api/song/entity/new_song_entity.g.dart, lib/api/song/entity/song_detail_entity.g.dart, lib/api/song/entity/song_quality_detail_entity.g.dart, lib/api/song/entity/song_url_entity.g.dart, lib/api/top/entity/top_artist_entity.g.dart, lib/api/user/entity/bool_entity.g.dart, lib/api/user/entity/like_list_entity.g.dart, lib/api/user/entity/qrcode_key_entity.g.dart, lib/api/user/entity/string_entity.g.dart, lib/api/user/entity/user_info_entity.g.dart, lib/api/user/entity/user_playlist_entity.g.dart
Generated JSON serialization helpers implementing fromJson and toJson for respective entity classes with null-safety handling, type conversions, and nested object support.
User Entity Refactoring
lib/api/user/entity/login_entity.dart, lib/api/user/entity/login_entity.g.dart
LoginEntity and related classes restructured with explicit nullable fields replacing defaults; generated JSON serialization layer introduced with comprehensive fromJson/toJson support for LoginEntity, LoginAccount, LoginProfile, and nested types.
New QR Entities
lib/api/user/entity/qr_check_result_entity.dart, lib/api/user/entity/qr_check_result_entity.g.dart
Added new QrCheckResultEntity with code, message, and cookie fields; includes json_serializable infrastructure and generated (de)serialization helpers.
QR Code Login Feature
lib/api/user/user_api.dart
Introduced new public method qrCodeLogin({required String key, int type = 1}) supporting QR code-based authentication with response parsing and cookie extraction.
Cookie Management
lib/common/music_api.dart
Added manual in-memory cookie handling via setCookie(String) and clearCookie() methods; integrated interceptor to inject stored cookie into outgoing requests alongside existing cookieJar management; made PrettyDioLogger conditional on debug flag.
Public API Surface Expansion
lib/bujuan_music_api.dart
Added multiple export directives exposing API surface and user entity classes (BoolEntity, LikeListEntity, LoginEntity, QrcodeKeyEntity, QrCheckEntity, QrCheckResultEntity, StringEntity, UserInfoEntity, UserPlaylistEntity).
Project Configuration
pubspec.yaml
Restored shared_preferences dependency; added build_runner and json_serializable dev dependencies for JSON code generation.
Submodule Update
flutter
Updated Flutter submodule pointer to commit 90673a4eef275d1a6692c26ac80d6d746d41a73a; no code or configuration changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 JSON flows like spring streams so clear,
Part directives bring the generated cheer!
QR codes dance in login's bright glow,
Cookies tucked safely, off they go—
Refactored and ready, the API shines true!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main enhancements: login capabilities with error messages, QR code support, and cookie persistence, which are the core objectives of the PR.
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: 14

Caution

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

⚠️ Outside diff range comments (7)
pubspec.yaml (1)

9-25: ⚠️ Potential issue | 🔴 Critical

Add json_annotation to dependencies (not only codegen tooling).

Lines 24-25 add codegen tooling, but lib/ directly imports json_annotation across 24+ entity files. Without a direct runtime dependency, downstream package consumers will fail dependency resolution.

🔧 Proposed fix
 dependencies:
   flutter:
     sdk: flutter
+  json_annotation: ^4.10.0
   dio: ^5.7.0
   dio_cookie_manager: ^3.1.1
   cookie_jar: ^4.0.8
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pubspec.yaml` around lines 9 - 25, The pubspec currently lists
json_serializable and build_runner under dev_dependencies but the library code
imports json_annotation at runtime; update the pubspec so json_annotation is
added to the regular dependencies section (not dev_dependencies), e.g. add the
package name "json_annotation" with a compatible version alongside other
dependencies so downstream consumers can resolve it; ensure you remove it from
dev_dependencies if present and run flutter pub get to confirm resolution.
lib/api/song/entity/song_detail_entity.dart (1)

54-55: ⚠️ Potential issue | 🔴 Critical

Same @JSONField-is-silently-ignored bug: sId will never deserialize from API responses.

@JSONField(name: "s_id") is not recognized by json_serializable. The generated code reads json['sId'] instead of json['s_id'], so this field will always be null.

🐛 Proposed fix
-  `@JSONField`(name: "s_id")
+  `@JsonKey`(name: 's_id')
   int? sId = 0;

Regenerate song_detail_entity.g.dart after the change.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/song/entity/song_detail_entity.dart` around lines 54 - 55, The sId
field uses the `@JSONField`(name: "s_id") annotation which json_serializable
ignores, so deserialization looks for json['sId'] and yields null; update the
Dart model to use the json_serializable-supported annotation (e.g.
`@JsonKey`(name: 's_id')) on the int? sId field in song_detail_entity.dart and
then regenerate the generated file (song_detail_entity.g.dart) so the generated
fromJson/toJson use 's_id' correctly.
lib/api/album/entity/album_info_entity.dart (1)

98-99: ⚠️ Potential issue | 🔴 Critical

@JSONField is silently ignored by json_serializable — these fields will always deserialize as null.

json_serializable only recognizes @JsonKey from package:json_annotation to customize field mappings. The custom @JSONField annotation from json_field.dart is not recognized by the code generator, so it falls back to using the Dart identifier name as the JSON key.

This is confirmed in the generated album_info_entity.g.dart: the code reads json['picStr'] instead of json['pic_str'], json['picidStr'] instead of json['picId_str'], and so on for all five affected fields:

  • AlbumInfoSongsAl.picStr → reads json['picStr'] instead of json['pic_str'] (Line 98)
  • AlbumInfoAlbum.picidStr → reads json['picidStr'] instead of json['picId_str'] (Line 307)
  • AlbumInfoAlbumArtists.img1v1idStr → reads json['img1v1idStr'] instead of json['img1v1Id_str'] (Line 338)
  • AlbumInfoAlbumArtist.picidStr → reads json['picidStr'] instead of json['picId_str'] (Line 368)
  • AlbumInfoAlbumArtist.img1v1idStr → reads json['img1v1idStr'] instead of json['img1v1Id_str'] (Line 371)

Replace @JSONField(name: "...") with @JsonKey(name: '...') on all five affected fields and regenerate with dart run build_runner build --delete-conflicting-outputs.

Proposed fixes
-  `@JSONField`(name: "pic_str")
+  `@JsonKey`(name: 'pic_str')
   String? picStr = '';
-  `@JSONField`(name: "picId_str")
+  `@JsonKey`(name: 'picId_str')
   String? picidStr = '';
-  `@JSONField`(name: "img1v1Id_str")
+  `@JsonKey`(name: 'img1v1Id_str')
   String? img1v1idStr = '';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/album/entity/album_info_entity.dart` around lines 98 - 99, The
`@JSONField` annotations are ignored by json_serializable so fields deserialize
with wrong keys; replace each `@JSONField`(name: "...") with `@JsonKey`(name: '...')
on the affected fields—AlbumInfoSongsAl.picStr, AlbumInfoAlbum.picidStr,
AlbumInfoAlbumArtists.img1v1idStr, AlbumInfoAlbumArtist.picidStr, and
AlbumInfoAlbumArtist.img1v1idStr—and then regenerate the generated code by
running dart run build_runner build --delete-conflicting-outputs.
lib/api/playlist/entity/create_playlist_entity.dart (1)

65-66: ⚠️ Potential issue | 🟠 Major

Replace @JSONField with @JsonKey — annotation is silently ignored by json_serializable.

The @JSONField(name: "coverImgId_str") annotation at line 65 belongs to the old custom code generator and is not recognized by json_serializable, which only processes @JsonKey from json_annotation. The generated code confirms this: the field serializes to 'coverimgidStr' (the Dart field name) instead of the intended 'coverImgId_str', causing a silent serialization regression.

Fix
-	`@JSONField`(name: "coverImgId_str")
-	String? coverimgidStr = '';
+	`@JsonKey`(name: 'coverImgId_str')
+	String? coverimgidStr = '';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/playlist/entity/create_playlist_entity.dart` around lines 65 - 66,
The `@JSONField` annotation on the field coverimgidStr is not recognized by
json_serializable; replace `@JSONField`(name: "coverImgId_str") with
`@JsonKey`(name: "coverImgId_str") and ensure the file imports the json_annotation
package (import 'package:json_annotation/json_annotation.dart';) so
json_serializable will generate the correct key mapping for the field in
CreatePlaylistEntity (and update any other fields using `@JSONField` similarly).
lib/api/song/entity/new_song_entity.dart (1)

166-167: ⚠️ Potential issue | 🟠 Major

@JSONField ignored by json_serializable across four fields — wrong JSON keys will be generated.

All four @JSONField(name: ...) usages in this file (NewSongDataArtists.img1v1idStr, NewSongDataAlbum.picidStr, NewSongDataAlbumArtists.img1v1idStr, NewSongDataAlbumArtist.img1v1idStr) are silently ignored by json_serializable, which only processes @JsonKey. The generated code emits the Dart field name as the JSON key (e.g., img1v1idStr instead of img1v1Id_str), breaking round-trip serialization.

🐛 Proposed fix (apply to all four occurrences)

Replace all instances of @JSONField(name: ...) with @JsonKey(name: ...):

Lines 166–167 and 308–309 and 338–339:

-	`@JSONField`(name: "img1v1Id_str")
+	`@JsonKey`(name: 'img1v1Id_str')

Lines 278–279:

-	`@JSONField`(name: "picId_str")
+	`@JsonKey`(name: 'picId_str')

Also applies to: 278–279, 308–309, 338–339

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/song/entity/new_song_entity.dart` around lines 166 - 167, Replace the
incorrect `@JSONField` usages with json_serializable's `@JsonKey` for the four
fields so the generated JSON keys match the desired names: update
NewSongDataArtists.img1v1idStr, NewSongDataAlbum.picidStr,
NewSongDataAlbumArtists.img1v1idStr, and NewSongDataAlbumArtist.img1v1idStr to
use `@JsonKey`(name: "img1v1Id_str") or `@JsonKey`(name: "picId_str") as
appropriate; ensure the json_annotation import is present so the generator
recognizes `@JsonKey` and then re-run code generation.
lib/api/user/entity/user_playlist_entity.dart (1)

64-65: ⚠️ Potential issue | 🟠 Major

Replace @JSONField with @JsonKeyjson_serializable ignores @JSONField and generates incorrect JSON key mappings.

The @JSONField annotation is not recognized by json_serializable. Instead, use @JsonKey from the json_annotation package. The generated code currently maps coverimgidStr and avatarimgidStr to lowercase JSON keys, not the intended coverImgId_str and avatarImgId_str.

🐛 Proposed fix
-	`@JSONField`(name: "coverImgId_str")
+	`@JsonKey`(name: 'coverImgId_str')
	String? coverimgidStr = '';
-	`@JSONField`(name: "avatarImgId_str")
+	`@JsonKey`(name: 'avatarImgId_str')
	String? avatarimgidStr = '';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/entity/user_playlist_entity.dart` around lines 64 - 65, Replace
the unrecognized `@JSONField` annotations with `@JsonKey` from json_annotation for
the fields coverimgidStr and avatarimgidStr so json_serializable generates the
correct JSON names; specifically, update the annotations on the String?
coverimgidStr and String? avatarimgidStr members to `@JsonKey`(name:
'coverImgId_str') and `@JsonKey`(name: 'avatarImgId_str') respectively and ensure
json_annotation is imported so the generated code maps to the exact
camelCase+suffix keys.
lib/api/album/entity/new_album_entity.dart (1)

53-54: ⚠️ Potential issue | 🔴 Critical

Replace @JSONField with @JsonKey — field name mappings are being silently ignored.

@JSONField is a custom annotation from the legacy code generator that is no longer being processed. The current code generator (json_serializable) only recognizes @JsonKey from the json_annotation package. The generated code at line 59 of new_album_entity.g.dart reads json['picidStr'] instead of json['picId_str'], causing these fields to deserialize as null when the API sends snake_case field names.

This affects all 28 @JSONField occurrences across the codebase (in new_album_entity.dart, album_info_entity.dart, new_song_entity.dart, and 8 other entity files).

Proposed fix — replace `@JSONField` with `@JsonKey`
-	`@JSONField`(name: "picId_str")
+	`@JsonKey`(name: 'picId_str')
 	String? picidStr = '';

Apply the same change to all other @JSONField occurrences across the codebase (all 28 instances).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/album/entity/new_album_entity.dart` around lines 53 - 54, Replace
legacy `@JSONField` annotations with json_serializable's `@JsonKey` and ensure the
name mapping matches the snake_case API keys (e.g., change the field annotation
on String? picidStr from `@JSONField`(name: "picId_str") to `@JsonKey`(name:
"picId_str")); update all other occurrences of `@JSONField` across entity classes
(e.g., in new_album_entity.dart, album_info_entity.dart, new_song_entity.dart)
and add/import package: json_annotation/json_annotation.dart if missing, then
re-run the build_runner code generation to regenerate *.g.dart files so the
deserialization reads json['picId_str'] correctly.
♻️ Duplicate comments (1)
lib/api/user/entity/bool_entity.dart (1)

1-4: Same stale json_field.dart import as in song_url_entity.dart — no @JSONField annotations are present in this file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/entity/bool_entity.dart` around lines 1 - 4, The file contains
an unused import of package:bujuan_music_api/generated/json/base/json_field.dart
in bool_entity.dart; either remove that import line (since there are no
`@JSONField` annotations) or if you intended to use JSONField, add the appropriate
`@JSONField` annotations to the relevant class/fields (e.g., the BoolEntity class
and its members) and then regenerate the part file; update the import
accordingly.
🧹 Nitpick comments (6)
lib/api/song/entity/song_url_entity.dart (1)

1-4: Stale import: json_field.dart is no longer used in this file.

No field in SongUrlEntity or any of its nested classes uses @JSONField. The import can be removed.

🧹 Proposed cleanup
 import 'package:json_annotation/json_annotation.dart';
-import 'package:bujuan_music_api/generated/json/base/json_field.dart';
 import 'dart:convert';
 part 'song_url_entity.g.dart';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/song/entity/song_url_entity.dart` around lines 1 - 4, The import
'package:bujuan_music_api/generated/json/base/json_field.dart' is unused in this
file; remove that import line from lib/api/song/entity/song_url_entity.dart so
only the needed imports remain (retain imports for json_annotation, dart:convert
and the part 'song_url_entity.g.dart'); update any analyzer/formatting by
running the Dart analyzer/formatter to ensure no remaining references to
JSONField or unused-import warnings for the SongUrlEntity related code.
lib/api/user/entity/login_entity.g.dart (1)

26-37: Nested objects not explicitly serialized in _$LoginEntityToJson — add explicitToJson: true.

With the default explicitToJson: false, instance.account, instance.profile, and instance.bindings are placed into the map as raw Dart objects, not as Map<String, dynamic>. jsonEncode handles this recursively, but any caller that consumes the returned map directly (e.g., for building an HTTP request body) will receive un-serialized nested objects.

The same issue exists in _$LoginProfileToJson at Line 122 (instance.experts).

Fix in the source entity file (login_entity.dart):

-@JsonSerializable()
+@JsonSerializable(explicitToJson: true)
 class LoginEntity {

After regenerating, the output will become:

-'account': instance.account,
+'account': instance.account?.toJson(),
-'profile': instance.profile,
+'profile': instance.profile?.toJson(),
-'bindings': instance.bindings,
+'bindings': instance.bindings?.map((e) => e.toJson()).toList(),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/entity/login_entity.g.dart` around lines 26 - 37, The generated
JSON serializers _$LoginEntityToJson and _$LoginProfileToJson are leaving nested
fields (LoginEntity.account, LoginEntity.profile, LoginEntity.bindings and
LoginProfile.experts) as raw Dart objects; update the source model annotation in
login_entity.dart to enable explicitToJson: true for the JsonSerializable on
LoginEntity (and LoginProfile if separate), re-run the code generator to
regenerate _$LoginEntityToJson and _$LoginProfileToJson so nested objects are
serialized via their toJson() methods instead of being embedded as raw objects.
lib/api/user/user_api.dart (2)

7-7: Remove trailing inline comment // 新增.

Debug/development comments like this shouldn't be committed. The import itself is self-explanatory.

Proposed fix
-import 'package:bujuan_music_api/api/user/entity/qr_check_result_entity.dart'; // 新增
+import 'package:bujuan_music_api/api/user/entity/qr_check_result_entity.dart';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/user_api.dart` at line 7, Remove the trailing inline comment
from the import statement that brings in qr_check_result_entity (import
'package:bujuan_music_api/api/user/entity/qr_check_result_entity.dart';) so the
import stands alone without the debug/dev comment "// 新增"; simply delete the
comment text and keep the import unchanged.

88-115: qrCodeLogin bypasses the library's own post<T> abstraction.

Every other method in this mixin delegates to BujuanMusicManager().post<T>(...), which handles response parsing, interceptors, and error flow uniformly. This method calls dio.post(...) directly, introducing a parallel code path with manual JSON parsing (lines 97-102) and ad-hoc cookie extraction.

If the motivation is cookie access, consider extending BujuanMusicManager.post<T> (or adding a variant) that exposes the raw Response so cookie headers can be extracted without duplicating response-handling logic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/user_api.dart` around lines 88 - 115, The qrCodeLogin method
bypasses the shared HTTP abstraction by calling BujuanMusicManager().dio.post
directly and doing manual JSON parsing and cookie extraction; change qrCodeLogin
to use BujuanMusicManager.post<T>(...) so it benefits from unified
parsing/interceptors, or add a new BujuanMusicManager.postRaw(...) (or a flag on
post) that returns the raw Response so qrCodeLogin can call that, parse the body
into QrCheckResultEntity via the existing JSON parsing path, and extract cookies
from response.headers['set-cookie'] to set result.cookie; update qrCodeLogin to
remove the manual jsonDecode branch and rely on the manager's parsing behavior.
lib/api/user/entity/login_entity.dart (1)

1-5: Unused import from old codegen system.

Line 2 imports json_field.dart which provides the @JSONField annotation from the previous code generation approach. Now that all classes use @JsonSerializable() (from json_annotation), @JSONField should not be used. Once the annotation on Line 79 is replaced with @JsonKey, this import becomes dead code and should be removed.

♻️ Proposed fix (after fixing the `@JSONField` → `@JsonKey` issue)
 import 'package:json_annotation/json_annotation.dart';
-import 'package:bujuan_music_api/generated/json/base/json_field.dart';
 import 'dart:convert';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/entity/login_entity.dart` around lines 1 - 5, The file imports
an unused legacy annotation package (import
'package:bujuan_music_api/generated/json/base/json_field.dart') and still uses
`@JSONField`; update the class to use `@JsonKey` instead of `@JSONField` (replace the
annotation on the login entity) and then remove the now-dead import statement;
ensure only 'package:json_annotation/json_annotation.dart' remains and
regenerate/verify generated files for the changes to login_entity (look for
`@JSONField`, `@JsonKey`, and the import at the top to locate the spots to edit).
lib/api/song/entity/new_song_entity.g.dart (1)

72-108: Nested objects in toJson aren't recursively serialized to maps.

The toJson methods insert nested object instances directly (e.g., 'privilege': instance.privilege) instead of calling .toJson() on them. This is the default json_serializable behavior when explicitToJson: true is not set. It works fine with jsonEncode() (which calls toJson() automatically), but if consumers inspect the raw Map without encoding, nested values will be object references, not plain maps.

Consider adding @JsonSerializable(explicitToJson: true) to the parent classes in new_song_entity.dart if the raw Map representation needs to be fully serialized.

Also applies to: 146-175, 355-381

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/song/entity/new_song_entity.g.dart` around lines 72 - 108, The
generated toJson (e.g., _$NewSongDataToJson) is embedding nested object
instances (fields like privilege, artists, album, hMusic, mMusic, lMusic,
bMusic, etc.) instead of their Maps; fix by annotating the corresponding parent
classes in new_song_entity.dart (e.g., class NewSongData and any nested entity
classes referenced) with `@JsonSerializable`(explicitToJson: true), then re-run
the code generator (build_runner) to regenerate the *.g.dart so the generated
toJson calls use .toJson() for nested objects; ensure you update all affected
classes mentioned in the review so sections at lines ~72-108, 146-175 and
355-381 are regenerated correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@flutter`:
- Line 1: The Flutter submodule was advanced to commit
90673a4eef275d1a6692c26ac80d6d746d41a73a (Flutter 3.41.2) without explanation;
either document the upgrade rationale in the PR and commit message (e.g.,
required API, dependency, or bugfix) and add a minimum SDK constraint in
pubspec.yaml (e.g., environment.sdk / flutter minimum version) to prevent
accidental use on older toolchains, or if the bump was unintentional revert the
flutter submodule to the previous pinned commit and update the PR description to
state that no Flutter version change is intended.

In `@lib/api/album/entity/album_info_entity.g.dart`:
- Around line 133-148: The generated serialization uses Dart field names for
keys (e.g., AlbumInfoSongsAl.picStr, picidStr, img1v1idStr) instead of the API
keys (pic_str, picId_str, img1v1Id_str), causing incorrect fromJson/toJson
behavior; to fix, update the model annotations in album_info_entity.dart by
replacing the incorrect `@JSONField` annotations with the proper
JsonSerializable-compatible `@JsonKey`(name: '...') attributes for the fields
(e.g., use `@JsonKey`(name: 'pic_str') for picStr, `@JsonKey`(name: 'picId_str') for
picidStr, `@JsonKey`(name: 'img1v1Id_str') for img1v1idStr), then re-run the code
generator to regenerate the _$AlbumInfoSongsAlFromJson/_$AlbumInfoSongsAlToJson
and other affected serializers so they read/write the correct JSON keys.

In `@lib/api/playlist/entity/playlist_detail_entity.dart`:
- Around line 1-4: The custom `@JSONField` annotations are not recognized by
json_serializable so the aliased JSON keys aren’t used; replace each
`@JSONField`(name: "...") with `@JsonKey`(name: "...") on the listed fields so the
generated code uses the correct JSON names: change the annotation on
coverImgId_str in class PlaylistDetailPlaylist, avatarImgId_str in
PlaylistDetailPlaylistSubscribers, avatarImgId_str in
PlaylistDetailPlaylistCreator, s_id in PlaylistDetailPlaylistTracks, and pic_str
in PlaylistDetailPlaylistTracksAl to use `@JsonKey`(name: "...") and re-run code
generation.

In `@lib/api/recommend/entity/recommend_resource_entity.g.dart`:
- Around line 20-27: Add explicitToJson: true to the JsonSerializable
annotation(s) for the affected classes so nested objects are serialized via
their toJson methods (e.g., annotate RecommendResourceEntity with
`@JsonSerializable`(explicitToJson: true) and do the same for nested types if
needed such as RecommendResourceRecommend and
RecommendResourceRecommendCreator), then re-run the code generator
(build_runner) so the generated _$RecommendResourceEntityToJson will call
.toJson() for 'recommend' and 'creator' instead of embedding Dart objects
directly.
- Around line 15-18: The generated deserializer assumes json['recommend'] is
non-nullable and will throw if absent; update the source model's field
declaration for recommend in RecommendResourceEntity (in
recommend_resource_entity.dart) to either be nullable (e.g.,
List<RecommendResourceRecommend>? recommend) or provide a default via
JsonKey(defaultValue: <RecommendResourceRecommend>[]) so the generator emits a
null-safe mapping (using (json['recommend'] as List<dynamic>?)?.map(...) or a ??
[] fallback); then re-run code generation (build_runner) to regenerate
recommend_resource_entity.g.dart.
- Around line 77-78: The generated deserialization uses (json['avatarImgId'] as
num?)?.toInt() for avatarImgId and backgroundImgId which causes precision loss
on Dart web; update the source model (the class that generates
recommend_resource_entity.g.dart) to read these IDs from avatarImgIdStr and
backgroundImgIdStr instead and store them as String or BigInt (e.g. change the
field types for avatarImgId/backgroundImgId or add new fields
avatarImgIdStr/backgroundImgIdStr with `@JsonKey`(name:
'avatarImgIdStr')/@JsonKey(name: 'backgroundImgIdStr') as appropriate), then
re-run json_serializable to regenerate recommend_resource_entity.g.dart so
deserialization uses the string-based values and avoids numeric truncation.

In `@lib/api/recommend/entity/recommend_song_entity.dart`:
- Around line 1-4: The JSON key mapping regressed because the json_serializable
generator is ignoring the legacy `@JSONField` annotations; update the model class
(RecommendSongEntity) to annotate the Dart fields that must map to snake_case
API keys (e.g., sId and picStr) with JsonKey(name: 's_id') and JsonKey(name:
'pic_str') respectively (and remove or replace any lingering `@JSONField`
annotations), then re-run the code generator (build_runner) to regenerate
recommend_song_entity.g.dart so the generated toJson/fromJson use the correct
API keys.

In `@lib/api/song/entity/new_song_entity.g.dart`:
- Around line 247-257: Change the volumeDelta field from int? to double? on the
audio quality classes (NewSongDataHMusic, NewSongDataMMusic, NewSongDataLMusic,
NewSongDataBMusic) in lib/api/song/entity/new_song_entity.dart, then re-run
build_runner to regenerate new_song_entity.g.dart so the deserializer uses
(json['volumeDelta'] as num?)?.toDouble() instead of .toInt(); this preserves
fractional dB values and prevents silent truncation.

In `@lib/api/song/entity/song_detail_entity.g.dart`:
- Around line 67-68: The generated code reads sId from the wrong JSON key; open
song_detail_entity.dart and add a JsonKey mapping for the sId field (e.g.,
annotate the sId property with `@JsonKey`(name: 's_id')) so the model expects the
correct key, then re-run the code generator (build_runner/Equivalent) to
regenerate song_detail_entity.g.dart and confirm the generated line uses
json['s_id'] for sId.

In `@lib/api/top/entity/top_artist_entity.dart`:
- Around line 1-4: The class field annotations using `@JSONField` are incompatible
with json_serializable; replace the `@JSONField` annotations on the picidStr and
img1v1idStr fields with `@JsonKey`(name: 'picId_str') and `@JsonKey`(name:
'img1v1Id_str') respectively (keep the existing import of
package:json_annotation/json_annotation.dart and remove or ignore the custom
json_field import if unused) so the generated mapper reads the correct JSON keys
for those fields in the TopArtistEntity (and then re-run build_runner to
regenerate top_artist_entity.g.dart).

In `@lib/api/user/entity/login_entity.dart`:
- Around line 79-80: The field annotation `@JSONField` on avatarimgIdStr is from
the old codegen and is ignored by the current `@JsonSerializable` system; replace
`@JSONField`(name: "avatarImgId_str") with `@JsonKey`(name: "avatarImgId_str") so
the generated _$LoginProfileFromJson maps to the correct JSON key, and
remove/replace any unused import for the old FlutterJsonBeanFactory if present;
ensure package:json_annotation/json_annotation.dart is imported so `@JsonKey` is
recognized.

In `@lib/api/user/user_api.dart`:
- Line 62: The JSON payloads built in qrCodeKey, checkQrCode, and qrCodeLogin
use the misspelled key 'timerstamp' instead of 'timestamp'; confirm whether the
server expects the typo—if it's a bug, rename the key to 'timestamp' in all
three methods (qrCodeKey, checkQrCode, qrCodeLogin); if the server requires
'timerstamp', add a short inline comment above each payload construction
explaining that the misspelling is intentional and tied to server compatibility
to avoid accidental future changes.
- Around line 111-114: Remove the blanket try/catch that uses print() in the QR
code login flow (the catch block in lib/api/user/user_api.dart) and either let
exceptions propagate like the other mixin methods (loginCellPhone, checkQrCode)
or catch only expected errors and rethrow unexpected ones; replace any stdout
prints with proper logging if you must handle specific cases, and ensure callers
can distinguish network/JSON/“not-yet-scanned” errors rather than receiving a
silent null.

In `@lib/common/music_api.dart`:
- Around line 56-64: The PrettyDioLogger is currently configured to log request
headers which will expose the injected Cookie header; update the interceptor
setup on _dio.interceptors to avoid logging sensitive headers by either
disabling requestHeader in PrettyDioLogger (set requestHeader: false) or add a
small sanitizer interceptor before PrettyDioLogger that strips/masks the
"Cookie" header from RequestOptions.headers; adjust uses of PrettyDioLogger (the
instantiation with requestHeader/requestBody/responseBody options) so headers
are not emitted while preserving body/error logging.

---

Outside diff comments:
In `@lib/api/album/entity/album_info_entity.dart`:
- Around line 98-99: The `@JSONField` annotations are ignored by json_serializable
so fields deserialize with wrong keys; replace each `@JSONField`(name: "...") with
`@JsonKey`(name: '...') on the affected fields—AlbumInfoSongsAl.picStr,
AlbumInfoAlbum.picidStr, AlbumInfoAlbumArtists.img1v1idStr,
AlbumInfoAlbumArtist.picidStr, and AlbumInfoAlbumArtist.img1v1idStr—and then
regenerate the generated code by running dart run build_runner build
--delete-conflicting-outputs.

In `@lib/api/album/entity/new_album_entity.dart`:
- Around line 53-54: Replace legacy `@JSONField` annotations with
json_serializable's `@JsonKey` and ensure the name mapping matches the snake_case
API keys (e.g., change the field annotation on String? picidStr from
`@JSONField`(name: "picId_str") to `@JsonKey`(name: "picId_str")); update all other
occurrences of `@JSONField` across entity classes (e.g., in new_album_entity.dart,
album_info_entity.dart, new_song_entity.dart) and add/import package:
json_annotation/json_annotation.dart if missing, then re-run the build_runner
code generation to regenerate *.g.dart files so the deserialization reads
json['picId_str'] correctly.

In `@lib/api/playlist/entity/create_playlist_entity.dart`:
- Around line 65-66: The `@JSONField` annotation on the field coverimgidStr is not
recognized by json_serializable; replace `@JSONField`(name: "coverImgId_str") with
`@JsonKey`(name: "coverImgId_str") and ensure the file imports the json_annotation
package (import 'package:json_annotation/json_annotation.dart';) so
json_serializable will generate the correct key mapping for the field in
CreatePlaylistEntity (and update any other fields using `@JSONField` similarly).

In `@lib/api/song/entity/new_song_entity.dart`:
- Around line 166-167: Replace the incorrect `@JSONField` usages with
json_serializable's `@JsonKey` for the four fields so the generated JSON keys
match the desired names: update NewSongDataArtists.img1v1idStr,
NewSongDataAlbum.picidStr, NewSongDataAlbumArtists.img1v1idStr, and
NewSongDataAlbumArtist.img1v1idStr to use `@JsonKey`(name: "img1v1Id_str") or
`@JsonKey`(name: "picId_str") as appropriate; ensure the json_annotation import is
present so the generator recognizes `@JsonKey` and then re-run code generation.

In `@lib/api/song/entity/song_detail_entity.dart`:
- Around line 54-55: The sId field uses the `@JSONField`(name: "s_id") annotation
which json_serializable ignores, so deserialization looks for json['sId'] and
yields null; update the Dart model to use the json_serializable-supported
annotation (e.g. `@JsonKey`(name: 's_id')) on the int? sId field in
song_detail_entity.dart and then regenerate the generated file
(song_detail_entity.g.dart) so the generated fromJson/toJson use 's_id'
correctly.

In `@lib/api/user/entity/user_playlist_entity.dart`:
- Around line 64-65: Replace the unrecognized `@JSONField` annotations with
`@JsonKey` from json_annotation for the fields coverimgidStr and avatarimgidStr so
json_serializable generates the correct JSON names; specifically, update the
annotations on the String? coverimgidStr and String? avatarimgidStr members to
`@JsonKey`(name: 'coverImgId_str') and `@JsonKey`(name: 'avatarImgId_str')
respectively and ensure json_annotation is imported so the generated code maps
to the exact camelCase+suffix keys.

In `@pubspec.yaml`:
- Around line 9-25: The pubspec currently lists json_serializable and
build_runner under dev_dependencies but the library code imports json_annotation
at runtime; update the pubspec so json_annotation is added to the regular
dependencies section (not dev_dependencies), e.g. add the package name
"json_annotation" with a compatible version alongside other dependencies so
downstream consumers can resolve it; ensure you remove it from dev_dependencies
if present and run flutter pub get to confirm resolution.

---

Duplicate comments:
In `@lib/api/user/entity/bool_entity.dart`:
- Around line 1-4: The file contains an unused import of
package:bujuan_music_api/generated/json/base/json_field.dart in
bool_entity.dart; either remove that import line (since there are no `@JSONField`
annotations) or if you intended to use JSONField, add the appropriate `@JSONField`
annotations to the relevant class/fields (e.g., the BoolEntity class and its
members) and then regenerate the part file; update the import accordingly.

---

Nitpick comments:
In `@lib/api/song/entity/new_song_entity.g.dart`:
- Around line 72-108: The generated toJson (e.g., _$NewSongDataToJson) is
embedding nested object instances (fields like privilege, artists, album,
hMusic, mMusic, lMusic, bMusic, etc.) instead of their Maps; fix by annotating
the corresponding parent classes in new_song_entity.dart (e.g., class
NewSongData and any nested entity classes referenced) with
`@JsonSerializable`(explicitToJson: true), then re-run the code generator
(build_runner) to regenerate the *.g.dart so the generated toJson calls use
.toJson() for nested objects; ensure you update all affected classes mentioned
in the review so sections at lines ~72-108, 146-175 and 355-381 are regenerated
correctly.

In `@lib/api/song/entity/song_url_entity.dart`:
- Around line 1-4: The import
'package:bujuan_music_api/generated/json/base/json_field.dart' is unused in this
file; remove that import line from lib/api/song/entity/song_url_entity.dart so
only the needed imports remain (retain imports for json_annotation, dart:convert
and the part 'song_url_entity.g.dart'); update any analyzer/formatting by
running the Dart analyzer/formatter to ensure no remaining references to
JSONField or unused-import warnings for the SongUrlEntity related code.

In `@lib/api/user/entity/login_entity.dart`:
- Around line 1-5: The file imports an unused legacy annotation package (import
'package:bujuan_music_api/generated/json/base/json_field.dart') and still uses
`@JSONField`; update the class to use `@JsonKey` instead of `@JSONField` (replace the
annotation on the login entity) and then remove the now-dead import statement;
ensure only 'package:json_annotation/json_annotation.dart' remains and
regenerate/verify generated files for the changes to login_entity (look for
`@JSONField`, `@JsonKey`, and the import at the top to locate the spots to edit).

In `@lib/api/user/entity/login_entity.g.dart`:
- Around line 26-37: The generated JSON serializers _$LoginEntityToJson and
_$LoginProfileToJson are leaving nested fields (LoginEntity.account,
LoginEntity.profile, LoginEntity.bindings and LoginProfile.experts) as raw Dart
objects; update the source model annotation in login_entity.dart to enable
explicitToJson: true for the JsonSerializable on LoginEntity (and LoginProfile
if separate), re-run the code generator to regenerate _$LoginEntityToJson and
_$LoginProfileToJson so nested objects are serialized via their toJson() methods
instead of being embedded as raw objects.

In `@lib/api/user/user_api.dart`:
- Line 7: Remove the trailing inline comment from the import statement that
brings in qr_check_result_entity (import
'package:bujuan_music_api/api/user/entity/qr_check_result_entity.dart';) so the
import stands alone without the debug/dev comment "// 新增"; simply delete the
comment text and keep the import unchanged.
- Around line 88-115: The qrCodeLogin method bypasses the shared HTTP
abstraction by calling BujuanMusicManager().dio.post directly and doing manual
JSON parsing and cookie extraction; change qrCodeLogin to use
BujuanMusicManager.post<T>(...) so it benefits from unified
parsing/interceptors, or add a new BujuanMusicManager.postRaw(...) (or a flag on
post) that returns the raw Response so qrCodeLogin can call that, parse the body
into QrCheckResultEntity via the existing JSON parsing path, and extract cookies
from response.headers['set-cookie'] to set result.cookie; update qrCodeLogin to
remove the manual jsonDecode branch and rely on the manager's parsing behavior.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dff61e6 and e88b5bc.

⛔ Files ignored due to path filters (24)
  • lib/generated/json/album_info_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/base/json_field.dart is excluded by !**/generated/**
  • lib/generated/json/bool_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/catalogue_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/create_playlist_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/high_quality_tags_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/like_list_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/login_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/mv_url_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/new_album_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/new_song_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/playlist_detail_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/qr_check_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/qrcode_key_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/recommend_resource_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/recommend_song_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/song_detail_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/song_like_check_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/song_quality_detail_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/song_url_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/string_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/top_artist_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/user_info_entity.g.dart is excluded by !**/generated/**
  • lib/generated/json/user_playlist_entity.g.dart is excluded by !**/generated/**
📒 Files selected for processing (53)
  • flutter
  • lib/api/album/entity/album_info_entity.dart
  • lib/api/album/entity/album_info_entity.g.dart
  • lib/api/album/entity/new_album_entity.dart
  • lib/api/album/entity/new_album_entity.g.dart
  • lib/api/mv/entity/mv_url_entity.dart
  • lib/api/mv/entity/mv_url_entity.g.dart
  • lib/api/playlist/entity/catalogue_entity.dart
  • lib/api/playlist/entity/catalogue_entity.g.dart
  • lib/api/playlist/entity/create_playlist_entity.dart
  • lib/api/playlist/entity/create_playlist_entity.g.dart
  • lib/api/playlist/entity/high_quality_tags_entity.dart
  • lib/api/playlist/entity/high_quality_tags_entity.g.dart
  • lib/api/playlist/entity/playlist_detail_entity.dart
  • lib/api/playlist/entity/playlist_detail_entity.g.dart
  • lib/api/recommend/entity/recommend_resource_entity.dart
  • lib/api/recommend/entity/recommend_resource_entity.g.dart
  • lib/api/recommend/entity/recommend_song_entity.dart
  • lib/api/recommend/entity/recommend_song_entity.g.dart
  • lib/api/song/entity/new_song_entity.dart
  • lib/api/song/entity/new_song_entity.g.dart
  • lib/api/song/entity/song_detail_entity.dart
  • lib/api/song/entity/song_detail_entity.g.dart
  • lib/api/song/entity/song_like_check_entity.dart
  • lib/api/song/entity/song_like_check_entity.g.dart
  • lib/api/song/entity/song_quality_detail_entity.dart
  • lib/api/song/entity/song_quality_detail_entity.g.dart
  • lib/api/song/entity/song_url_entity.dart
  • lib/api/song/entity/song_url_entity.g.dart
  • lib/api/top/entity/top_artist_entity.dart
  • lib/api/top/entity/top_artist_entity.g.dart
  • lib/api/user/entity/bool_entity.dart
  • lib/api/user/entity/bool_entity.g.dart
  • lib/api/user/entity/like_list_entity.dart
  • lib/api/user/entity/like_list_entity.g.dart
  • lib/api/user/entity/login_entity.dart
  • lib/api/user/entity/login_entity.g.dart
  • lib/api/user/entity/qr_check_entity.dart
  • lib/api/user/entity/qr_check_entity.g.dart
  • lib/api/user/entity/qr_check_result_entity.dart
  • lib/api/user/entity/qr_check_result_entity.g.dart
  • lib/api/user/entity/qrcode_key_entity.dart
  • lib/api/user/entity/qrcode_key_entity.g.dart
  • lib/api/user/entity/string_entity.dart
  • lib/api/user/entity/string_entity.g.dart
  • lib/api/user/entity/user_info_entity.dart
  • lib/api/user/entity/user_info_entity.g.dart
  • lib/api/user/entity/user_playlist_entity.dart
  • lib/api/user/entity/user_playlist_entity.g.dart
  • lib/api/user/user_api.dart
  • lib/bujuan_music_api.dart
  • lib/common/music_api.dart
  • pubspec.yaml

Comment thread flutter
@@ -0,0 +1 @@
Subproject commit 90673a4eef275d1a6692c26ac80d6d746d41a73a
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Flutter commit 90673a4eef275d1a6692c26ac80d6d746d41a73a version release tag

💡 Result:

Commit 90673a4eef275d1a6692c26ac80d6d746d41a73a corresponds to the Flutter 3.41.2 (stable) release tag. [1][2]

Sources: [1] commit page, [2] tags listing showing 3.41.290673a4e.


🏁 Script executed:

# Search for any git history or context about this change
git log --oneline -20 --all -- flutter 2>/dev/null || echo "No git history available"

# Look for any PR description or motivation in common places
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "COMMIT_EDITMSG" \) -exec grep -l "90673a4\|flutter.*submodule" {} \; 2>/dev/null | head -5

# Check if there's any recent context in the repo root
ls -la | grep -i readme

Repository: 2697a/bujuan_music_api

Length of output: 152


🏁 Script executed:

# Find and examine pubspec.yaml to see what dependencies might require Flutter 3.41.2
fd pubspec.yaml -type f

# If found, show its contents
if [ -f pubspec.yaml ]; then
  echo "=== pubspec.yaml ===" 
  cat pubspec.yaml
fi

Repository: 2697a/bujuan_music_api

Length of output: 2019


🏁 Script executed:

# Also check git log for the pubspec.yaml change to see commit message
git log --oneline --all -- "**/pubspec.yaml" 2>/dev/null | head -10 || echo "Git log not available"

# Try to find any change summary or PR notes
git show e88b5bc 2>/dev/null | head -50 || echo "Commit details not available"

Repository: 2697a/bujuan_music_api

Length of output: 1196


Document the rationale for the Flutter 3.41.2 submodule bump or revert if unintentional.

The submodule was updated to commit 90673a4eef275d1a6692c26ac80d6d746d41a73a (Flutter 3.41.2 stable). While this is a legitimate release, the PR description makes no mention of a Flutter version upgrade, and the commit message ("Update pubspec.yaml") provides no rationale. Additionally, pubspec.yaml does not specify a minimum Flutter version constraint, implying earlier versions should remain compatible.

If this bump is intentional, document the reason (e.g., required for a specific API or dependency). If accidental, revert to the previously pinned commit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@flutter` at line 1, The Flutter submodule was advanced to commit
90673a4eef275d1a6692c26ac80d6d746d41a73a (Flutter 3.41.2) without explanation;
either document the upgrade rationale in the PR and commit message (e.g.,
required API, dependency, or bugfix) and add a minimum SDK constraint in
pubspec.yaml (e.g., environment.sdk / flutter minimum version) to prevent
accidental use on older toolchains, or if the bump was unintentional revert the
flutter submodule to the previous pinned commit and update the PR description to
state that no Flutter version change is intended.

Comment on lines +133 to +148
AlbumInfoSongsAl _$AlbumInfoSongsAlFromJson(Map<String, dynamic> json) =>
AlbumInfoSongsAl()
..id = (json['id'] as num?)?.toInt()
..name = json['name'] as String?
..picUrl = json['picUrl'] as String?
..picStr = json['picStr'] as String?
..pic = (json['pic'] as num?)?.toInt();

Map<String, dynamic> _$AlbumInfoSongsAlToJson(AlbumInfoSongsAl instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'picUrl': instance.picUrl,
'picStr': instance.picStr,
'pic': instance.pic,
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Wrong JSON key strings — downstream effect of ignored @JSONField annotations.

picStr, picidStr, and img1v1idStr are read/written using the Dart field names (e.g. json['picStr'], json['picidStr'], json['img1v1idStr']) instead of the intended API key names (pic_str, picId_str, img1v1Id_str). This affects the fromJson reads (Lines 138, 366, 420, 457, 461) and the toJson writes (Lines 147, 400, 438, 479, 481).

Root cause is in album_info_entity.dart — replace @JSONField with @JsonKey and regenerate this file. See the comment on album_info_entity.dart.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/album/entity/album_info_entity.g.dart` around lines 133 - 148, The
generated serialization uses Dart field names for keys (e.g.,
AlbumInfoSongsAl.picStr, picidStr, img1v1idStr) instead of the API keys
(pic_str, picId_str, img1v1Id_str), causing incorrect fromJson/toJson behavior;
to fix, update the model annotations in album_info_entity.dart by replacing the
incorrect `@JSONField` annotations with the proper JsonSerializable-compatible
`@JsonKey`(name: '...') attributes for the fields (e.g., use `@JsonKey`(name:
'pic_str') for picStr, `@JsonKey`(name: 'picId_str') for picidStr, `@JsonKey`(name:
'img1v1Id_str') for img1v1idStr), then re-run the code generator to regenerate
the _$AlbumInfoSongsAlFromJson/_$AlbumInfoSongsAlToJson and other affected
serializers so they read/write the correct JSON keys.

Comment on lines +1 to +4
import 'package:json_annotation/json_annotation.dart';
import 'package:bujuan_music_api/generated/json/base/json_field.dart';
import 'package:bujuan_music_api/generated/json/playlist_detail_entity.g.dart';
import 'dart:convert';
export 'package:bujuan_music_api/generated/json/playlist_detail_entity.g.dart';
part 'playlist_detail_entity.g.dart';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking if playlist_detail_entity.dart exists ==="
if [ -f "lib/api/playlist/entity/playlist_detail_entity.dart" ]; then
  echo "File found"
else
  echo "File not found, searching for it..."
  find . -name "playlist_detail_entity.dart" -type f
fi

echo
echo "=== First 50 lines of playlist_detail_entity.dart ==="
head -50 lib/api/playlist/entity/playlist_detail_entity.dart || echo "Cannot read file"

Repository: 2697a/bujuan_music_api

Length of output: 1423


🏁 Script executed:

#!/bin/bash

echo "=== Checking for `@JSONField` annotations in source ==="
rg -n 'JSONField\(' lib/api/playlist/entity/playlist_detail_entity.dart || echo "No `@JSONField` found"

echo
echo "=== Checking for generated file ==="
if [ -f "lib/api/playlist/entity/playlist_detail_entity.g.dart" ]; then
  echo "Generated file exists, checking size..."
  wc -l lib/api/playlist/entity/playlist_detail_entity.g.dart
else
  echo "Generated file does not exist"
fi

echo
echo "=== Checking for aliased keys in generated code ==="
rg '"(coverImgId_str|avatarImgId_str|s_id|pic_str)"' lib/api/playlist/entity/playlist_detail_entity.g.dart || echo "No aliased keys found in generated code"

Repository: 2697a/bujuan_music_api

Length of output: 531


🏁 Script executed:

#!/bin/bash

echo "=== Full content of playlist_detail_entity.dart ==="
cat lib/api/playlist/entity/playlist_detail_entity.dart

echo
echo "=== Content of generated file (first 100 lines) ==="
head -100 lib/api/playlist/entity/playlist_detail_entity.g.dart || echo "Cannot read generated file"

Repository: 2697a/bujuan_music_api

Length of output: 18075


Replace @JSONField with @JsonKey for aliased fields—json_serializable doesn't recognize the custom annotations.

The generated code at line 49 (..coverimgidStr = json['coverimgidStr'] as String?) reads from the Dart field name coverimgidStr, not the aliased JSON key coverImgId_str. This occurs on 5 fields in this file:

  • coverImgId_str (PlaylistDetailPlaylist, line 37)
  • avatarImgId_str (PlaylistDetailPlaylistSubscribers, line 139)
  • avatarImgId_str (PlaylistDetailPlaylistCreator, line 186)
  • s_id (PlaylistDetailPlaylistTracks, line 249)
  • pic_str (PlaylistDetailPlaylistTracksAl, line 309)

Without this change, JSON responses with these aliased keys will fail to deserialize.

Fix

Replace @JSONField(name: "...") with @JsonKey(name: "...") on all 5 fields.

-import 'package:bujuan_music_api/generated/json/base/json_field.dart';

-@JSONField(name: "coverImgId_str")
+@JsonKey(name: "coverImgId_str")
 String? coverimgidStr = '';

-@JSONField(name: "avatarImgId_str")
+@JsonKey(name: "avatarImgId_str")
 String? avatarimgidStr = '';

-@JSONField(name: "s_id")
+@JsonKey(name: "s_id")
 int? sId = 0;

-@JSONField(name: "pic_str")
+@JsonKey(name: "pic_str")
 String? picStr = '';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/playlist/entity/playlist_detail_entity.dart` around lines 1 - 4, The
custom `@JSONField` annotations are not recognized by json_serializable so the
aliased JSON keys aren’t used; replace each `@JSONField`(name: "...") with
`@JsonKey`(name: "...") on the listed fields so the generated code uses the
correct JSON names: change the annotation on coverImgId_str in class
PlaylistDetailPlaylist, avatarImgId_str in PlaylistDetailPlaylistSubscribers,
avatarImgId_str in PlaylistDetailPlaylistCreator, s_id in
PlaylistDetailPlaylistTracks, and pic_str in PlaylistDetailPlaylistTracksAl to
use `@JsonKey`(name: "...") and re-run code generation.

Comment on lines +15 to +18
..recommend = (json['recommend'] as List<dynamic>)
.map((e) =>
RecommendResourceRecommend.fromJson(e as Map<String, dynamic>))
.toList();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

recommend list deserialization will throw if the field is null or absent

Unlike expertTags (line 81, which uses ?.map), json['recommend'] is cast directly as a non-nullable List<dynamic>. Any API response that omits or nulls this field (e.g., an error state or empty result) throws a runtime exception.

Since this is generated code, the fix belongs in the source class annotation/field declaration in recommend_resource_entity.dart. If the field is intended to be non-nullable, ensure the API contract guarantees its presence; otherwise, declare it nullable or provide a default.

🛡️ Expected generated output after fixing the source field
-     ..recommend = (json['recommend'] as List<dynamic>)
-         .map((e) =>
-             RecommendResourceRecommend.fromJson(e as Map<String, dynamic>))
-         .toList();
+     ..recommend = (json['recommend'] as List<dynamic>?)
+         ?.map((e) =>
+             RecommendResourceRecommend.fromJson(e as Map<String, dynamic>))
+         .toList() ?? [];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
..recommend = (json['recommend'] as List<dynamic>)
.map((e) =>
RecommendResourceRecommend.fromJson(e as Map<String, dynamic>))
.toList();
..recommend = (json['recommend'] as List<dynamic>?)
?.map((e) =>
RecommendResourceRecommend.fromJson(e as Map<String, dynamic>))
.toList() ?? [];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/recommend/entity/recommend_resource_entity.g.dart` around lines 15 -
18, The generated deserializer assumes json['recommend'] is non-nullable and
will throw if absent; update the source model's field declaration for recommend
in RecommendResourceEntity (in recommend_resource_entity.dart) to either be
nullable (e.g., List<RecommendResourceRecommend>? recommend) or provide a
default via JsonKey(defaultValue: <RecommendResourceRecommend>[]) so the
generator emits a null-safe mapping (using (json['recommend'] as
List<dynamic>?)?.map(...) or a ?? [] fallback); then re-run code generation
(build_runner) to regenerate recommend_resource_entity.g.dart.

Comment on lines +20 to +27
Map<String, dynamic> _$RecommendResourceEntityToJson(
RecommendResourceEntity instance) =>
<String, dynamic>{
'code': instance.code,
'featureFirst': instance.featureFirst,
'haveRcmdSongs': instance.haveRcmdSongs,
'recommend': instance.recommend,
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Nested objects are not serialized to maps in toJson()explicitToJson: true is missing

'recommend': instance.recommend (line 26) stores a List<RecommendResourceRecommend> of Dart objects directly, and 'creator': instance.creator (line 57) stores a RecommendResourceRecommendCreator object directly. jsonEncode(entity.toJson()) will throw an Unhandled Exception: Converting object to an encodable object failed at runtime because the JSON encoder cannot handle these opaque Dart objects.

This is a json_serializable default behavior: nested .toJson() calls are only emitted when explicitToJson: true is set on the source annotation. Fix in recommend_resource_entity.dart:

🐛 Fix in the source class (triggers regeneration of this file)
-@JsonSerializable()
+@JsonSerializable(explicitToJson: true)
 class RecommendResourceEntity { ... }

-@JsonSerializable()
+@JsonSerializable(explicitToJson: true)
 class RecommendResourceRecommend { ... }

After regeneration, the generated output should look like:

-'recommend': instance.recommend,
+'recommend': instance.recommend.map((e) => e.toJson()).toList(),

-'creator': instance.creator,
+'creator': instance.creator?.toJson(),

Also applies to: 47-61

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/recommend/entity/recommend_resource_entity.g.dart` around lines 20 -
27, Add explicitToJson: true to the JsonSerializable annotation(s) for the
affected classes so nested objects are serialized via their toJson methods
(e.g., annotate RecommendResourceEntity with `@JsonSerializable`(explicitToJson:
true) and do the same for nested types if needed such as
RecommendResourceRecommend and RecommendResourceRecommendCreator), then re-run
the code generator (build_runner) so the generated
_$RecommendResourceEntityToJson will call .toJson() for 'recommend' and
'creator' instead of embedding Dart objects directly.

Comment on lines +1 to +4
import 'package:json_annotation/json_annotation.dart';
import 'package:bujuan_music_api/generated/json/base/json_field.dart';
import 'package:bujuan_music_api/generated/json/top_artist_entity.g.dart';
import 'dart:convert';
export 'package:bujuan_music_api/generated/json/top_artist_entity.g.dart';
part 'top_artist_entity.g.dart';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking if files exist ==="
ls -la lib/api/top/entity/top_artist_entity.dart 2>/dev/null || echo "File not found"
ls -la lib/api/top/entity/top_artist_entity.g.dart 2>/dev/null || echo "Generated file not found"

echo
echo "=== Lines 1-4 of source file ==="
head -4 lib/api/top/entity/top_artist_entity.dart

echo
echo "=== Checking for JSONField vs JsonKey annotations ==="
echo "Source file - JSONField usage:"
rg -n '@JSONField\(name:' lib/api/top/entity/top_artist_entity.dart || echo "No `@JSONField` found"

echo
echo "Source file - JsonKey usage:"
rg -n '@JsonKey\(name:' lib/api/top/entity/top_artist_entity.dart || echo "No `@JsonKey` found"

echo
echo "=== Checking specific lines mentioned (14-16, 51-53) ==="
echo "Lines 14-16:"
sed -n '14,16p' lib/api/top/entity/top_artist_entity.dart

echo
echo "Lines 51-53:"
sed -n '51,53p' lib/api/top/entity/top_artist_entity.dart

echo
echo "=== Generated mapper key usage ==="
if [ -f lib/api/top/entity/top_artist_entity.g.dart ]; then
  echo "Keys referenced in generated file:"
  rg -n '"(picId_str|img1v1Id_str|picidStr|img1v1idStr)"' lib/api/top/entity/top_artist_entity.g.dart || echo "No matching keys found"
else
  echo "Generated file does not exist"
fi

Repository: 2697a/bujuan_music_api

Length of output: 1210


🏁 Script executed:

#!/bin/bash

echo "=== Source file lines 38-45 (context around line 40) ==="
sed -n '38,45p' lib/api/top/entity/top_artist_entity.dart

echo
echo "=== Full source file ==="
cat -n lib/api/top/entity/top_artist_entity.dart

echo
echo "=== Full generated file ==="
cat -n lib/api/top/entity/top_artist_entity.g.dart

Repository: 2697a/bujuan_music_api

Length of output: 5386


Replace @JSONField with @JsonKey for json_serializable compatibility.

The @JSONField annotations on lines 40 and 42 are not recognized by json_serializable. The generated mapper reads picidStr and img1v1idStr keys instead of the intended picId_str and img1v1Id_str, breaking JSON deserialization for those fields.

Proposed fix
 import 'package:json_annotation/json_annotation.dart';
-import 'package:bujuan_music_api/generated/json/base/json_field.dart';

-	`@JSONField`(name: "picId_str")
+	`@JsonKey`(name: "picId_str")
 	String? picidStr = '';
-	`@JSONField`(name: "img1v1Id_str")
+	`@JsonKey`(name: "img1v1Id_str")
 	String? img1v1idStr = '';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/top/entity/top_artist_entity.dart` around lines 1 - 4, The class
field annotations using `@JSONField` are incompatible with json_serializable;
replace the `@JSONField` annotations on the picidStr and img1v1idStr fields with
`@JsonKey`(name: 'picId_str') and `@JsonKey`(name: 'img1v1Id_str') respectively
(keep the existing import of package:json_annotation/json_annotation.dart and
remove or ignore the custom json_field import if unused) so the generated mapper
reads the correct JSON keys for those fields in the TopArtistEntity (and then
re-run build_runner to regenerate top_artist_entity.g.dart).

Comment on lines +79 to +80
@JSONField(name: "avatarImgId_str")
String? avatarimgIdStr;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

fd 'login_entity.g.dart' -type f

Repository: 2697a/bujuan_music_api

Length of output: 236


🏁 Script executed:

fd 'login_entity.g.dart' --type f

Repository: 2697a/bujuan_music_api

Length of output: 105


🏁 Script executed:

cat lib/api/user/entity/login_entity.g.dart | grep -A 5 -B 5 'avatarimgIdStr'

Repository: 2697a/bujuan_music_api

Length of output: 1089


🏁 Script executed:

sed -n '75,85p' lib/api/user/entity/login_entity.dart

Repository: 2697a/bujuan_music_api

Length of output: 305


@JSONField is not recognized by json_serializable; use @JsonKey instead.

@JSONField comes from the old FlutterJsonBeanFactory/custom codegen system (imported on Line 2). Since this class now uses @JsonSerializable() with generated _$LoginProfileFromJson, only @JsonKey annotations are honored. The generated code maps this field to JSON key "avatarimgIdStr" instead of "avatarImgId_str", causing deserialization to fail for the intended JSON key.

🐛 Proposed fix
-  `@JSONField`(name: "avatarImgId_str")
+  `@JsonKey`(name: 'avatarImgId_str')
   String? avatarimgIdStr;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@JSONField(name: "avatarImgId_str")
String? avatarimgIdStr;
`@JsonKey`(name: 'avatarImgId_str')
String? avatarimgIdStr;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/entity/login_entity.dart` around lines 79 - 80, The field
annotation `@JSONField` on avatarimgIdStr is from the old codegen and is ignored
by the current `@JsonSerializable` system; replace `@JSONField`(name:
"avatarImgId_str") with `@JsonKey`(name: "avatarImgId_str") so the generated
_$LoginProfileFromJson maps to the correct JSON key, and remove/replace any
unused import for the old FlutterJsonBeanFactory if present; ensure
package:json_annotation/json_annotation.dart is imported so `@JsonKey` is
recognized.

///
/// [type] 类型(可选,默认为 3)
Future<QrcodeKeyEntity?> qrCodeKey({int type = 1}) async {
final data = {'type': type, 'timerstamp': '${DateTime.now()}'};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Typo: 'timerstamp' — is this intentional for server compatibility?

This key appears across qrCodeKey (line 62), checkQrCode (line 77), and qrCodeLogin (line 87). If the server genuinely expects timerstamp, please add a brief comment to prevent future "fixes" that would break the API. If it's a bug, it should be timestamp.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/user_api.dart` at line 62, The JSON payloads built in qrCodeKey,
checkQrCode, and qrCodeLogin use the misspelled key 'timerstamp' instead of
'timestamp'; confirm whether the server expects the typo—if it's a bug, rename
the key to 'timestamp' in all three methods (qrCodeKey, checkQrCode,
qrCodeLogin); if the server requires 'timerstamp', add a short inline comment
above each payload construction explaining that the misspelling is intentional
and tied to server compatibility to avoid accidental future changes.

Comment on lines +111 to +114
} catch (e) {
print('QR code login error: $e');
return null;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid print() in library code; silent catch-all hides failures.

print() in a library pollutes the consumer's stdout and cannot be disabled. More importantly, the blanket catch (e) returns null for every failure — network timeouts, JSON parse errors, and legitimate "not-yet-scanned" responses are all indistinguishable to the caller.

Consider either:

  • Removing the try/catch and letting exceptions propagate (consistent with other methods in this mixin), or
  • Catching only expected cases and rethrowing unexpected ones.
Proposed fix — remove blanket catch, let exceptions propagate
-    } catch (e) {
-      print('QR code login error: $e');
-      return null;
-    }
+    } on FormatException {
+      return null;
+    }

Or remove the try/catch entirely to stay consistent with loginCellPhone, checkQrCode, etc.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (e) {
print('QR code login error: $e');
return null;
}
} on FormatException {
return null;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/user/user_api.dart` around lines 111 - 114, Remove the blanket
try/catch that uses print() in the QR code login flow (the catch block in
lib/api/user/user_api.dart) and either let exceptions propagate like the other
mixin methods (loginCellPhone, checkQrCode) or catch only expected errors and
rethrow unexpected ones; replace any stdout prints with proper logging if you
must handle specific cases, and ensure callers can distinguish
network/JSON/“not-yet-scanned” errors rather than receiving a silent null.

Comment thread lib/common/music_api.dart
Comment on lines +56 to +64
_dio.interceptors.add(PrettyDioLogger(
requestHeader: true,
requestBody: true,
responseBody: true,
responseHeader: false,
error: true,
compact: true,
maxWidth: 200,
enabled: _debug));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd lib/common/music_api.dart

Repository: 2697a/bujuan_music_api

Length of output: 48


🏁 Script executed:

cat -n lib/common/music_api.dart | head -80

Repository: 2697a/bujuan_music_api

Length of output: 3375


🌐 Web query:

PrettyDioLogger requestHeader true logs headers Cookie authentication

💡 Result:

PrettyDioLogger(requestHeader: true) only prints what’s in RequestOptions.headers (i.e., headers your Dio code can set/see). It does not guarantee you’ll see the final on-the-wire Cookie header. (pub.dev)

Why Cookie often won’t show up (especially on Flutter Web)

On the web, Cookie is a forbidden request header—the browser won’t let JavaScript (and thus Flutter Web/Dio) set or override it programmatically. So there may be nothing for PrettyDioLogger to print, even though cookies may still be handled by the browser automatically. (developer.mozilla.org)

What to do for cookie-based authentication on Web

Let the server set cookies via Set-Cookie, and tell Dio’s browser adapter to send cookies on (cross-site) requests by enabling withCredentials:

import 'package:dio/adapter_browser.dart';
import 'package:dio/dio.dart';

final dio = Dio();
final adapter = BrowserHttpClientAdapter()..withCredentials = true;
dio.httpClientAdapter = adapter;

dio.interceptors.add(PrettyDioLogger(requestHeader: true, responseHeader: true));

This is the commonly used Dio-for-browser equivalent of Axios withCredentials: true. (stackoverflow.com)

If you tell me whether you’re on Flutter Web vs Android/iOS and whether the request is cross-origin, I can pinpoint exactly why the cookie isn’t appearing in your logs (vs not being sent at all).

Citations:


🏁 Script executed:

# Search for usage patterns of PrettyDioLogger in the codebase to understand the intent
rg "PrettyDioLogger" --type dart -B 2 -A 10

Repository: 2697a/bujuan_music_api

Length of output: 709


🏁 Script executed:

# Check if this is web-only or supports mobile
rg "android|ios|mobile|platform" lib/common/music_api.dart
rg "kIsWeb" -A 2 -B 2 lib/common/music_api.dart

Repository: 2697a/bujuan_music_api

Length of output: 283


🏁 Script executed:

# Check the pubspec or main init to see supported platforms
fd pubspec.yaml -x head -50

Repository: 2697a/bujuan_music_api

Length of output: 1415


Do not log authentication headers (Cookie) in HTTP logger.

At Line 50 you inject Cookie into request headers, and at Line 57 requestHeader: true logs all request headers. On mobile platforms (Android/iOS) this will leak session cookies/tokens into logs. While the Cookie header cannot be logged on Flutter Web (it's a forbidden header), this package supports both mobile and web platforms.

🔧 Minimal safe change
     if (_debug) {
       _dio.interceptors.add(PrettyDioLogger(
-          requestHeader: true,
+          requestHeader: false,
           requestBody: true,
           responseBody: true,
           responseHeader: false,
           error: true,
           compact: true,
           maxWidth: 200,
           enabled: _debug));
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_dio.interceptors.add(PrettyDioLogger(
requestHeader: true,
requestBody: true,
responseBody: true,
responseHeader: false,
error: true,
compact: true,
maxWidth: 200,
enabled: _debug));
_dio.interceptors.add(PrettyDioLogger(
requestHeader: false,
requestBody: true,
responseBody: true,
responseHeader: false,
error: true,
compact: true,
maxWidth: 200,
enabled: _debug));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/common/music_api.dart` around lines 56 - 64, The PrettyDioLogger is
currently configured to log request headers which will expose the injected
Cookie header; update the interceptor setup on _dio.interceptors to avoid
logging sensitive headers by either disabling requestHeader in PrettyDioLogger
(set requestHeader: false) or add a small sanitizer interceptor before
PrettyDioLogger that strips/masks the "Cookie" header from
RequestOptions.headers; adjust uses of PrettyDioLogger (the instantiation with
requestHeader/requestBody/responseBody options) so headers are not emitted while
preserving body/error logging.

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.

1 participant