Repository navigation
feat(danmaku): 支持自定义弹幕服务器 - #2716
qq164004640 wants to merge 1 commit into
Conversation
在设置中添加自定义弹幕服务器配置,播放页可选择该源加载弹幕; 修复自动匹配串集问题;新增弹幕来源展示。
|
|
||
| /// 当前弹幕来源描述, 用于播放信息面板展示 (动漫名 + 集数 + 服务器) | ||
| @observable | ||
| String danmakuSourceLabel = ''; |
There was a problem hiding this comment.
WARNING: MobX generated code was not regenerated for the new observables/actions
danmakuSourceLabel, danmakuSourceAnimeTitle, danmakuSourceEpisodeTitle are annotated @observable, and setDanmakuSource / updateDanmakuSourceLabel / clearDanmakuSource are annotated @action, but player_danmaku_controller.g.dart only contains atoms for danmakuOn / danmakuLoading (only the getDanDanmakuByEpisodeID wrapper was hand-edited). These fields are therefore plain fields: the Observer in video_details_sheet.dart that reads danmakuSourceLabel will not rebuild when the label changes, and the actions are not wrapped. Re-run build_runner and commit the regenerated .g.dart.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| return await _fetchDanDanmakuByBgmBangumiID( | ||
| bangumiId, | ||
| episode, | ||
| _applyDanmakuSourceLabel(result, title: title, episode: episode); |
There was a problem hiding this comment.
WARNING: Source label is written before the caller validates the load session
fetchDanmaku sets the label here, but VideoPageController only checks session.isActive && danmakuSession.isActive after this returns and drops stale results. A stale automatic load (previous episode, or one cancelled by a manual source switch via onBeforeApply) will still overwrite the current label with its own text (e.g. 弹幕获取失败 or a different episode), so the label no longer matches the loaded danmaku. Apply the label after the session check (e.g. in applyDanmakuLoad / applyUnavailableDanmakuLoad).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| // 自定义弹幕服务器的来源标签是平台名 (如 [bilibili]/[tencent]), | ||
| // 与弹弹play 关联源 ([BiliBili]/[Gamer]) 的过滤语义不同, 不套用这组开关, | ||
| // 避免关闭「弹弹play」来源时误过滤掉全部自定义服务器弹幕。 | ||
| if (CustomDanmakuServerConfig.isEnabled) { |
There was a problem hiding this comment.
WARNING: Source filters are disabled for all danmaku whenever the custom server is enabled, including dandanplay fallback danmaku
The bypass is decided by the global config, not by where the current danmaku came from. When the custom server returns nothing, playback/local/manual paths fall back to dandanplay (withRelated=true), which yields [BiliBili]/[Gamer] entries — yet the user's BiliBili/Gamer/弹弹play toggles are now ignored. Track the actual server of the current load (e.g. DanmakuLoadResult.danmakuServer / the serverName passed to setDanmakuSource) and skip filtering only when it is the custom server.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| ); | ||
| } | ||
| } | ||
| return _getCustomDanmakuByEpisodeOrder(title, episode); |
There was a problem hiding this comment.
WARNING: Turning off the auto-match setting does not stop automatic fetching
The setting says 关闭后仅在播放页手动搜索选择弹幕, but when autoMatch is false the code only skips the match call and still falls through to _getCustomDanmakuByEpisodeOrder, which auto-picks the first search result and the N-th episode by position (an even less accurate guess). Playback and download prefetch will still auto-load custom danmaku. Return an empty result when !CustomDanmakuServerConfig.autoMatch.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| return (danmakus: <DanmakuEntry>[], animeTitle: null, episodeTitle: null); | ||
| } | ||
| if (CustomDanmakuServerConfig.autoMatch) { | ||
| final match = await CustomDanmakuClient.instance |
There was a problem hiding this comment.
SUGGESTION: An exception from match bypasses the documented episode-order fallback
The doc comment says match failure degrades to search → first anime → episode by order, but matchEpisodeId throws on network errors/timeouts/non-JSON/missing /match endpoint and this call is not wrapped, so the exception propagates and _getCustomDanmakuByEpisodeOrder is never tried. Either catch here or fix the comment.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| } | ||
| final jsonData = await _get( | ||
| '$base${ApiEndpoints.customDanmuAPIComment}$episodeId', | ||
| queryParameters: {'format': 'json'}, |
There was a problem hiding this comment.
WARNING: The Simplified/Traditional conversion setting is ignored for custom-server danmaku
The dandanplay path (DanmakuApi._getComments) sends chConvert from SettingsKeys.danmakuChConvert, but the custom-server comment request only sends format=json and no client-side conversion is applied. Users who chose 转为简体/繁体 get unconverted danmaku whenever the custom server is used. Forward chConvert here (the server is dandanplay-v2 compatible) or convert client-side.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| if (comment is Map<String, dynamic> && | ||
| comment['p'] is String && | ||
| comment['m'] is String) | ||
| DanmakuEntry.fromJson(comment), |
There was a problem hiding this comment.
WARNING: One malformed comment still aborts the whole list
The guard only checks types, but DanmakuEntry.fromJson does double.parse(parts[0]), int.parse(parts[1]), int.parse(parts[2]) and parts[3]. A p with fewer than 4 fields (source is optional in some implementations) throws RangeError, and non-integer values throw FormatException; the exception escapes the list literal so every comment for the episode is lost, contradicting the comment above. Wrap each fromJson in try/catch (or validate the split length / use tryParse).
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| ], | ||
| ), | ||
| ); | ||
| controller.dispose(); |
There was a problem hiding this comment.
WARNING: TextEditingController disposed while the dialog's TextField is still mounted
KazumiDialog.show completes as soon as the route is popped, before the exit animation finishes. Disposing the controller here while the TextField (with autofocus) is still in the tree can trigger A TextEditingController was used after being disposed when it detaches/unfocuses. Move the dialog content into a StatefulWidget that owns and disposes the controller, or defer disposal until the route is fully removed.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| } | ||
|
|
||
| Future<void> testCustomDanmakuServer() async { | ||
| if (!CustomDanmakuServerConfig.isEnabled) { |
There was a problem hiding this comment.
SUGGESTION: Connection test is blocked by the enable switch with a misleading message
isEnabled returns false whenever the enable switch is off, even if the URL is valid, so a user testing a valid address before enabling sees 请先填写有效的服务器地址. testConnection() already handles a null baseUrl; check CustomDanmakuServerConfig.baseUrl == null instead.
| if (!CustomDanmakuServerConfig.isEnabled) { | |
| if (CustomDanmakuServerConfig.baseUrl == null) { |
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 9 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (13 files)
Fix these issues in Kilo Cloud Reviewed by claude-opus-5.5 · Input: 276 · Output: 12K · Cached: 613.3K |
|
感谢你的工作,但是我们暂时不打算实现这个功能 |
在设置中添加自定义弹幕服务器配置,播放页可选择该源加载弹幕【建议】
描述
【完全使用AI生成代码】
内置弹幕源(弹弹play)有时弹幕数量偏少,且曾遇到配额超限导致弹幕源不可用的情况。我自己部署过弹幕服务器,使用体验良好,但 Kazumi 目前只能选择内置弹幕源,无法使用自定义的弹幕服务器。
新增自定义弹幕服务器功能:
由于没有上游的密钥所以镜像搜索和软件自带的弹幕功能是没法使用的,所以只有自定义弹幕服务器配置的弹幕能用
只有Windows 构建上实测通过:自定义弹幕加载、切换集数、与内置弹幕源的双开/单开组合均正常。



对代码一窍不通,增加的代码挺多的,不知道能不能采纳或者大佬构建一个更好的代码出来
关联的 Issues
#2652,#2660,#2661
PR 类型
AI 辅助开发
AI 辅助模型:
Step-5-Preview
提交前检查
附注