From 9e5af5bedc689f15d4c1322d9bf35afa6e2ea852 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 08:21:57 +0000 Subject: [PATCH 1/2] feat: Add "More Options" button to live room UI This commit introduces a "More Options" button to the top-right corner of the live broadcast player interface. This change refactors the UI by consolidating several individual action buttons into a single popup menu, creating a cleaner and more consistent user experience that aligns with the UGC player's design. Key changes include: - Added a `PopupMenuButton` to `lib/pages/live_room/widgets/header_control.dart` to house the options. - Relocated the "Send Danmaku," "Audio Only," "Picture-in-Picture," "Scheduled Shutdown," and "Playback Info" actions into the new menu. - Added a `GlobalKey` to the `PopupMenuButton` and a `showMenu` method to allow it to be triggered programmatically. - Extended the `PlayerFocus` widget in `lib/pages/video/widgets/player_focus.dart` to handle the `LogicalKeyboardKey.menu` key event. - Connected the D-pad menu key press to the `showMenu` method in `lib/pages/live_room/view.dart`. This addresses issue #232. --- lib/pages/live_room/view.dart | 2 + .../live_room/widgets/header_control.dart | 137 ++++++++---------- lib/pages/video/widgets/player_focus.dart | 1 + 3 files changed, 65 insertions(+), 75 deletions(-) diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index b0310754b5..d32193e584 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -199,6 +199,8 @@ class _LiveRoomPageState extends State child = PlayerFocus( plPlayerController: plPlayerController, onSendDanmaku: _liveRoomController.onSendDanmaku, + onShowMenu: () => + (_liveRoomController.headerKey.currentState as dynamic)?.showMenu(), child: child, ); } diff --git a/lib/pages/live_room/widgets/header_control.dart b/lib/pages/live_room/widgets/header_control.dart index f311968444..fe98d8e6c4 100644 --- a/lib/pages/live_room/widgets/header_control.dart +++ b/lib/pages/live_room/widgets/header_control.dart @@ -39,6 +39,14 @@ class LiveHeaderControl extends StatefulWidget { class _LiveHeaderControlState extends State with TimeBatteryMixin { + final GlobalKey _menuKey = GlobalKey(); + + void showMenu() { + final PopupMenuButtonState? menuButtonState = + _menuKey.currentState as PopupMenuButtonState?; + menuButtonState?.showButtonMenu(); + } + @override late final plPlayerController = widget.plPlayerController; @@ -121,86 +129,65 @@ class _LiveHeaderControlState extends State child, ...?timeBatteryWidgets, const SizedBox(width: 10), - ComBtn( - height: 30, - tooltip: '发弹幕', - icon: const Icon( - size: 18, - Icons.comment_outlined, - color: Colors.white, + _moreBtn(), + ], + ), + ); + } + + Widget _moreBtn() { + return PopupMenuButton( + key: _menuKey, + icon: const Icon( + Icons.more_vert, + color: Colors.white, + size: 18, + ), + tooltip: '更多选项', + itemBuilder: (BuildContext context) => [ + PopupMenuItem( + onTap: widget.onSendDanmaku, + child: const Text('发弹幕'), + ), + PopupMenuItem( + onTap: () { + plPlayerController.onlyPlayAudio.value = + !plPlayerController.onlyPlayAudio.value; + widget.onPlayAudio(); + }, + child: Obx( + () => Text( + plPlayerController.onlyPlayAudio.value ? '关闭仅音频' : '仅播放音频', ), - onTap: widget.onSendDanmaku, ), - Obx( - () { - final onlyPlayAudio = plPlayerController.onlyPlayAudio.value; - return ComBtn( - height: 30, - tooltip: '仅播放音频', - onTap: () { - plPlayerController.onlyPlayAudio.value = !onlyPlayAudio; - widget.onPlayAudio(); - }, - icon: onlyPlayAudio - ? const Icon( - size: 18, - MdiIcons.musicCircle, - color: Colors.white, - ) - : const Icon( - size: 18, - MdiIcons.musicCircleOutline, - color: Colors.white, - ), - ); + ), + if (Platform.isAndroid || (Utils.isDesktop && !isFullScreen)) + PopupMenuItem( + onTap: () async { + if (Utils.isDesktop) { + plPlayerController.toggleDesktopPip(); + return; + } + if (await Floating().isPipAvailable) { + plPlayerController + ..showControls.value = false + ..enterPip(); + } }, + child: const Text('画中画'), ), - if (Platform.isAndroid || (Utils.isDesktop && !isFullScreen)) - ComBtn( - height: 30, - tooltip: '画中画', - onTap: () async { - if (Utils.isDesktop) { - plPlayerController.toggleDesktopPip(); - return; - } - if (await Floating().isPipAvailable) { - plPlayerController - ..showControls.value = false - ..enterPip(); - } - }, - icon: const Icon( - size: 18, - Icons.picture_in_picture_outlined, - color: Colors.white, - ), - ), - ComBtn( - height: 30, - tooltip: '定时关闭', - onTap: () => PageUtils.scheduleExit(context, isFullScreen, true), - icon: const Icon( - size: 18, - Icons.schedule, - color: Colors.white, - ), - ), - ComBtn( - height: 30, - tooltip: '播放信息', - onTap: () => HeaderControlState.showPlayerInfo( - context, - plPlayerController: plPlayerController, - ), - icon: const Icon( - size: 18, - Icons.info_outline, - color: Colors.white, - ), + PopupMenuItem( + onTap: () => PageUtils.scheduleExit(context, isFullScreen, true), + child: const Text('定时关闭'), + ), + PopupMenuItem( + onTap: () => HeaderControlState.showPlayerInfo( + context, + plPlayerController: plPlayerController, ), - ], - ), + child: const Text('播放信息'), + ), + ], ); } } diff --git a/lib/pages/video/widgets/player_focus.dart b/lib/pages/video/widgets/player_focus.dart index b75ca1fdd9..0cc0c21ffc 100644 --- a/lib/pages/video/widgets/player_focus.dart +++ b/lib/pages/video/widgets/player_focus.dart @@ -219,6 +219,7 @@ class PlayerFocus extends StatelessWidget { } return true; case LogicalKeyboardKey.contextMenu: + case LogicalKeyboardKey.menu: if (plPlayerController.isLive || (canPlay?.call() ?? false)) { if (hasPlayer) { onShowMenu?.call(); From 56fff58054d48d5f20da8ae9c5455badb566ab12 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 08:28:31 +0000 Subject: [PATCH 2/2] fix: Resolve build failure by removing LogicalKeyboardKey.menu Removes the use of `LogicalKeyboardKey.menu` which was causing CI build failures due to being unavailable in the project's Flutter version. The existing `LogicalKeyboardKey.contextMenu` provides the necessary D-pad menu key functionality. feat: Add "More Options" button to live room UI This commit introduces a "More Options" button to the top-right corner of the live broadcast player interface. This change refactors the UI by consolidating several individual action buttons into a single popup menu, creating a cleaner and more consistent user experience that aligns with the UGC player's design. Key changes include: - Added a `PopupMenuButton` to `lib/pages/live_room/widgets/header_control.dart` to house the options. - Relocated the "Send Danmaku," "Audio Only," "Picture-in-Picture," "Scheduled Shutdown," and "Playback Info" actions into the new menu. - Added a `GlobalKey` to the `PopupMenuButton` and a `showMenu` method to allow it to be triggered programmatically. - Extended the `PlayerFocus` widget in `lib/pages/video/widgets/player_focus.dart` to handle the `LogicalKeyboardKey.contextMenu` key event. - Connected the D-pad menu key press to the `showMenu` method in `lib/pages/live_room/view.dart`. This addresses issue #232. --- lib/pages/video/widgets/player_focus.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pages/video/widgets/player_focus.dart b/lib/pages/video/widgets/player_focus.dart index 0cc0c21ffc..b75ca1fdd9 100644 --- a/lib/pages/video/widgets/player_focus.dart +++ b/lib/pages/video/widgets/player_focus.dart @@ -219,7 +219,6 @@ class PlayerFocus extends StatelessWidget { } return true; case LogicalKeyboardKey.contextMenu: - case LogicalKeyboardKey.menu: if (plPlayerController.isLive || (canPlay?.call() ?? false)) { if (hasPlayer) { onShowMenu?.call();