Repository navigation
feat(player): 编辑弹幕时暂停播放 - #2706
JesseLee-CN wants to merge 1 commit into
Conversation
| /// | ||
| /// 想让所有平台都默认暂停:把 `defaultResolver` 这一行删掉即可(`defaultValue` | ||
| /// 就是 `true`);用户也可以在「设置 → 弹幕 → 弹幕显示」里自行打开。 | ||
| static final pauseOnDanmakuEdit = SettingKey<bool>( |
There was a problem hiding this comment.
WARNING: pauseOnDanmakuEdit is not registered in SettingsKeys.all
SettingsKeys.byGroup() iterates all, and GStorage.resetDanmakuSettings() uses byGroup(SettingGroup.danmaku) to choose which keys to clear. This key is missing from the all list (around line 595, next to danmakuEnhance), so "恢复默认弹幕设置" will not reset it. A user who toggled it keeps the old value after a reset, even though the dialog says display settings go back to defaults. Add pauseOnDanmakuEdit, to all.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| ); | ||
| switch (action) { | ||
| case DanmakuEditPauseAction.pause: | ||
| unawaited(playerController.pause()); |
There was a problem hiding this comment.
WARNING: In a SyncPlay session, the auto pause/resume is sent to the whole room
playerController.pause() and play() default to enableSync: true. When syncplay.hasSession is true they call requestSyncPlaySync(). So when one participant focuses the composer, for example to send a chat-room danmaku (a supported destination), playback pauses for everyone in the room. On blur, play() resumes for everyone. It also overrides a pause another participant made while this user was typing. The option is on by default on mobile, so typing a chat message in an 一起看 room would interrupt all peers. You could skip the auto-pause when playerController.syncplay.hasSession is true, or pass enableSync: false and handle the local desync.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (5 files)
Note: The incremental diff from Fix these issues in Kilo Cloud Previous Review Summary (commit 204a6bc)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 204a6bc)Status: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (5 files)
Reviewed by claude-opus-5.5 · Input: 296 · Output: 10K · Cached: 825.1K |
## 问题 在播放器底部的弹幕输入框里打字时视频仍在播放,想发的弹幕对应的画面往往已经过去, 只能先手动暂停、发完再手动继续。这个行为与 B 站客户端的发弹幕逻辑类似, 同时参考了 animeko 的 pauseVideoOnEditDanmaku。 ## 修改 - 新增 DanmakuEditPauseController:聚焦输入框时暂停,失焦时恢复; 只撤销自己造成的暂停,用户手动暂停的视频不会被自动播放,开关关闭时完全不接触播放; - 面板把 textFieldFocus 的焦点变化接入该控制器,并且只影响本地播放 (pause/play(enableSync: false)):一起看房间内写弹幕不会暂停或恢复所有人的播放, 也不会覆盖同伴的暂停; - 编辑期间用 TapRegion.consumeOutsideTaps 把输入框之外的点击从手势竞技场里摘掉: 这一次点击只用于退出输入框(失焦即恢复播放),不会再落到视频画面、播放/暂停键 或进度条上。否则同一次点击会「先恢复、再切回暂停」,看起来像点了没反应。 这里复用的是项目已有的框架机制:倍速、超分辨率等菜单用的 KazumiMenuButton → MenuAnchor.consumeOutsideTap 就是同一套语义 (TapRegion.consumeOutsideTaps:把该指针下的其它手势识别器全部拒绝); 只在开关开启且正在编辑时消费,因此关闭开关后行为与改动前完全一致; - 默认值与 B 站客户端一致:桌面端(Windows/macOS/Linux)不暂停、移动端暂停。 用已有的 SettingKey.defaultResolver 按平台解析,用户手动设置后以存储值为准; 想让所有平台都默认暂停,删掉 defaultResolver 一行即可(defaultValue 已是 true); - 新增设置项 SettingsKeys.pauseOnDanmakuEdit,位置在「设置 → 弹幕 → 弹幕显示」, 并登记进 SettingsKeys.all,因此「恢复默认弹幕设置」会一并重置它。 ## 验证 - 新增 9 个用例(test/danmaku_edit_pause_test.dart):聚焦即暂停并在失焦后恢复、 手动暂停不被覆盖、开关关闭时不介入、失焦幂等、重复聚焦不重复暂停、多轮聚焦循环、 默认值按平台解析(桌面关闭 / 移动开启)、设置项会被「恢复默认弹幕设置」重置; - flutter test:全量 222 项通过; - flutter analyze --no-fatal-infos --fatal-warnings:退出码 0,且改动文件没有任何 新增提示(仍为改动前既有的 17 条 info)。
204a6bc to
1e90471
Compare
| ); | ||
| switch (action) { | ||
| case DanmakuEditPauseAction.pause: | ||
| unawaited(playerController.pause(enableSync: false)); |
There was a problem hiding this comment.
WARNING: In a SyncPlay session the local auto-pause is undone within about a second, and a misleading toast appears
pause(enableSync: false) pauses only the local player. The room on the server stays playing. On the next server State message, SyncplayClient (syncplay_client.dart ~L642-661) sets _isPaused back to the room state and emits onPositionChangedMessage. The listener in player_syncplay_controller.dart ~L219-233 sees message['paused'] != !playing(), so it calls play(enableSync: false) and shows "SyncPlay: 开始了播放". The composer therefore pauses, then playback resumes almost at once while the user is still typing. If a peer pauses the room during editing, the blur-time play(enableSync: false) also desyncs this client from the paused room until the next correction.
The option is on by default on mobile, so this happens whenever someone types in an 一起看 room. The simplest fix is to skip the auto pause/resume when playerController.syncplay.hasSession is true, for example by passing enabled: setting && !playerController.syncplay.hasSession.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| case DanmakuEditPauseAction.pause: | ||
| unawaited(playerController.pause(enableSync: false)); | ||
| case DanmakuEditPauseAction.resume: | ||
| unawaited(playerController.play(enableSync: false)); |
There was a problem hiding this comment.
SUGGESTION: Sending a danmaku resumes playback before the destination is chosen
_submitDanmakuText calls textFieldFocus.unfocus() first (L153), and only then awaits showDanmakuDestinationSheet. The blur fires this resume branch right away, so the video starts playing while the destination sheet is open. The danmaku is echoed only after the user picks a destination, by which time the moment they paused for may have passed. That works against the purpose of the feature. You could defer the resume until _submitDanmakuText finishes (or is cancelled), for example by suppressing the blur-triggered resume during submission and calling it explicitly at the end.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
|
关闭此 PR。 我先核对了 #933:同样的需求在 2025-04 被关闭,理由是「我个人倾向于不暂停,bilibili 的设计也是这样的」。这份 PR 的默认值论证恰好建立在对 B 站行为的相反理解上,属于不在计划内的功能,因此不再占用审查时间。 功能本身已按项目惯例实现(设置项默认关闭的形态可直接启用;Kilo Code Review、analyze、测试与 6 个平台构建均通过),代码保留在本地分支,若将来方向有变化可以复用。 感谢审查。 |
描述
在播放器底部的弹幕输入框(B 站等来源的弹幕都在这里编辑)里打字时,视频仍在继续播放:等弹幕打完,想吐槽的那一幕往往已经过去,只能先手动暂停、发完再手动继续。这个 PR 让聚焦输入框时自动暂停播放、输入框失焦后自动恢复,和 B 站发弹幕逻辑类似,同时参考了 animeko 的
pauseVideoOnEditDanmaku的行为。默认值与 B 站客户端一致:桌面端不暂停,移动端暂停(移动端行为已在 Android / 鸿蒙 / iOS 上确认,见 #2708)。设置项位于 设置 → 弹幕 → 弹幕显示 → 编辑弹幕时暂停播放,可随时开关。
开启后的行为:
inactive)paused/hidden才拦)实现要点
lib/pages/player/controller/danmaku_edit_pause.dart:记录「这次暂停是否由输入框造成」,因此只撤销自己造成的暂停 —— 用户手动暂停的视频不会被自动播放,开关关闭时完全不接触播放状态;门槛抽成纯函数shouldPause({enabled, hasSession}),发送期间的延迟恢复由onSubmitStarted/onSubmitFinished表达,面板卸载由onDisposed归还暂停,这些都能直接单测;lib/pages/player/player_item_panel.dart把输入框的焦点变化接入该控制器:聚焦 → 暂停,失焦 → 恢复;TapRegion.consumeOutsideTaps把输入框之外的点击从手势竞技场里摘掉:这一次点击只用于退出输入框(失焦即恢复播放),不会再落到视频画面、播放/暂停键或进度条上。否则同一次点击会「先恢复、再切回暂停」,看起来像点了没反应。这里复用项目已有的机制 —— 倍速、超分辨率等菜单用的KazumiMenuButton → MenuAnchor.consumeOutsideTap就是同一套语义;pausedByEdit),并如实说明边界:它消费的是以 pointer-down 起手的整条手势,因此编辑期间进度条拖拽、亮度/音量滑动第一次会被吞掉;无障碍语义点击框架层面拦不住(tap_region.dart里仍是 TODO),读屏用户仍可能遇到同一次点击先恢复再暂停;syncplay.hasSession(不是房间名——房间名要等joinRoom之后才有值,连接窗口内房间消息已经在驱动本机播放了);改动只作用于本地(pause/play(enableSync: false)),既不暂停/恢复所有人的播放,也不会把本地的编辑暂停广播给房间;player_item.dart的既有做法):应用真正进入后台不恢复(桌面切窗口只是inactive,不算后台)、有一起看会话不恢复、有弹窗或弹层在顶层不恢复(编辑到一半定时关闭弹窗夺焦时,视频必须保持暂停)、暂停的播放器已被替换不恢复、也不越过编辑期间到期的睡眠定时;被拦下的那次恢复不会丢:所有权保留到真正恢复为止,回到前台会自动重试;ListenableBuilder重算一个布尔量,输入框所在子树不重建,因此编辑期间焦点与输入法连接不受影响;SettingKey.defaultResolver按平台解析:Windows / macOS / Linux 默认关闭,移动端默认开启;用户手动改过之后以存储值为准;SettingsKeys.all,因此「设置 → 弹幕 → 恢复默认弹幕设置」会一并重置它。关联的 Issues
PR 类型
AI 辅助开发
AI 辅助模型: deepseek-v4.1-flash
提交前检查
附注
SettingsKeys.pauseOnDanmakuEdit的defaultResolver那一行即可(defaultValue已经是true);用户也可以在「设置 → 弹幕 → 弹幕显示」里自行打开。pauseVideoOnEditDanmaku提供了同样的能力,见 VideoScaffoldConfig.kt。_submitDanmakuText拆出_sendDanmakuText,外层加try/finally),目的是把恢复播放推迟到「发送到」弹窗关闭之后;发送本身的逻辑未改动。test/danmaku_edit_pause_test.dart,17 个用例:聚焦暂停、失焦恢复、手动暂停不被覆盖、开关关闭不介入、一起看会话内不介入(含连接窗口)、失焦幂等、重复聚焦不重复暂停、多轮聚焦循环、发送期间延迟恢复且恰好一次、销毁时归还暂停、默认值按平台解析(Windows/macOS/Linux 关闭,Android/iOS 开启),以及用真实 Hive box 验证「写入 → 恢复默认弹幕设置 → 回落平台默认」;flutter test全量 230 项通过;flutter analyze --no-fatal-infos --fatal-warnings退出码 0,未引入新的提示;