diff --git a/lib/models_new/live/live_feed_index/watched_show.dart b/lib/models_new/live/live_feed_index/watched_show.dart index 9bf391562..8f0c30b51 100644 --- a/lib/models_new/live/live_feed_index/watched_show.dart +++ b/lib/models_new/live/live_feed_index/watched_show.dart @@ -1,14 +1,11 @@ class WatchedShow { - String? textSmall; String? textLarge; WatchedShow({ - this.textSmall, this.textLarge, }); factory WatchedShow.fromJson(Map json) => WatchedShow( - textSmall: json['text_small'] as String?, textLarge: json['text_large'] as String?, ); } diff --git a/lib/pages/live/widgets/live_item_app.dart b/lib/pages/live/widgets/live_item_app.dart index 056410336..976d2bb2a 100644 --- a/lib/pages/live/widgets/live_item_app.dart +++ b/lib/pages/live/widgets/live_item_app.dart @@ -2,7 +2,6 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/live/live_feed_index/card_data_list_item.dart'; -import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -130,9 +129,9 @@ class LiveCardVApp extends StatelessWidget { '${item.areaName}', style: const TextStyle(fontSize: 11, color: Colors.white), ), - if (item.watchedShow?.textSmall != null) + if (item.watchedShow?.textLarge case final textLarge?) Text( - '${NumUtils.numFormat(item.watchedShow!.textSmall)}围观', + textLarge, style: const TextStyle(fontSize: 11, color: Colors.white), ), ], diff --git a/lib/pages/live_follow/widgets/live_item_follow.dart b/lib/pages/live_follow/widgets/live_item_follow.dart index b61d70f3d..6f0d8ac83 100644 --- a/lib/pages/live_follow/widgets/live_item_follow.dart +++ b/lib/pages/live_follow/widgets/live_item_follow.dart @@ -129,10 +129,11 @@ class LiveCardVFollow extends StatelessWidget { '${liveItem.areaName}', style: const TextStyle(fontSize: 11, color: Colors.white), ), - Text( - liveItem.textSmall ?? '', - style: const TextStyle(fontSize: 11, color: Colors.white), - ), + if (liveItem.textSmall case final textSmall?) + Text( + '$textSmall围观', + style: const TextStyle(fontSize: 11, color: Colors.white), + ), ], ), ); diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index 73134cbe8..8bb4c6675 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -21,7 +21,9 @@ import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/tcp/live.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/danmaku_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:PiliPlus/utils/video_utils.dart'; @@ -62,6 +64,28 @@ class LiveRoomController extends GetxController { liveTimeTimer = null; } + Widget get timeWidget => Obx(() { + final liveTime = this.liveTime.value; + String text = ''; + if (liveTime != null) { + final duration = DurationUtils.formatDurationBetween( + liveTime * 1000, + DateTime.now().millisecondsSinceEpoch, + ); + text += duration.isEmpty ? '刚刚开播' : '开播$duration'; + } + if (text.isEmpty) { + return const SizedBox.shrink(); + } + return Text( + text, + style: const TextStyle( + fontSize: 12, + color: Colors.white, + ), + ); + }); + // dm LiveDmInfoData? dmInfo; List? savedDanmaku; @@ -91,6 +115,36 @@ class LiveRoomController extends GetxController { final headerKey = GlobalKey(); + final RxString title = ''.obs; + + final RxnString onlineCount = RxnString(); + Widget get onlineWidget => Obx(() { + if (onlineCount.value case final onlineCount?) { + return Text( + '高能观众($onlineCount)', + style: const TextStyle( + fontSize: 12, + color: Colors.white, + ), + ); + } + return const SizedBox.shrink(); + }); + + final RxnString watchedShow = RxnString(); + Widget get watchedWidget => Obx(() { + if (watchedShow.value case final watchedShow?) { + return Text( + watchedShow, + style: const TextStyle( + fontSize: 12, + color: Colors.white, + ), + ); + } + return const SizedBox.shrink(); + }); + @override void onInit() { super.onInit(); @@ -179,6 +233,8 @@ class LiveRoomController extends GetxController { if (res['status']) { RoomInfoH5Data data = res['data']; roomInfoH5.value = data; + title.value = data.roomInfo?.title ?? ''; + watchedShow.value = data.watchedShow?.textLarge; videoPlayerServiceHandler?.onVideoDetailChange(data, roomId, heroTag); } else { if (res['msg'] != null) { @@ -347,9 +403,7 @@ class LiveRoomController extends GetxController { final info = obj['info']; final first = info[0]; final content = first[15]; - final Map extra = jsonDecode( - content['extra'], - ); + final Map extra = jsonDecode(content['extra']); final user = content['user']; // final midHash = first[7]; final uid = user['uid']; @@ -408,6 +462,15 @@ class LiveRoomController extends GetxController { fsSC.value = item; } break; + case 'WATCHED_CHANGE': + watchedShow.value = obj['data']['text_large']; + break; + case 'ONLINE_RANK_COUNT': + onlineCount.value = NumUtils.numFormat(obj['data']['count']); + break; + case 'ROOM_CHANGE': + title.value = obj['data']['title']; + break; } } catch (_) {} } diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index be03cc917..e7887b1d9 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -23,7 +23,6 @@ import 'package:PiliPlus/plugin/pl_player/models/play_status.dart'; import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart'; import 'package:PiliPlus/plugin/pl_player/view.dart'; import 'package:PiliPlus/services/service_locator.dart'; -import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; @@ -240,6 +239,7 @@ class _LiveRoomPageState extends State onSendDanmaku: _liveRoomController.onSendDanmaku, onPlayAudio: _liveRoomController.queryLiveUrl, isPortrait: isPortrait, + liveController: _liveRoomController, ), bottomControl: BottomControl( plPlayerController: plPlayerController, @@ -493,62 +493,65 @@ class _LiveRoomPageState extends State backgroundColor: Colors.transparent, foregroundColor: Colors.white, titleTextStyle: const TextStyle(color: Colors.white), - title: Obx( - () { - RoomInfoH5Data? roomInfoH5 = _liveRoomController.roomInfoH5.value; - if (roomInfoH5 == null) { - return const SizedBox.shrink(); - } - return GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => Get.toNamed('/member?mid=${roomInfoH5.roomInfo?.uid}'), - child: Row( - spacing: 10, - mainAxisSize: MainAxisSize.min, - children: [ - NetworkImgLayer( - width: 34, - height: 34, - type: ImageType.avatar, - src: roomInfoH5.anchorInfo!.baseInfo!.face, - ), - Column( - spacing: 1, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - roomInfoH5.anchorInfo!.baseInfo!.uname!, - style: const TextStyle(fontSize: 14), - ), - Obx(() { - final liveTime = _liveRoomController.liveTime.value; - final textLarge = roomInfoH5.watchedShow?.textLarge; - String text = ''; - if (textLarge != null) { - text += textLarge; - } - if (liveTime != null) { - if (text.isNotEmpty) { - text += ' '; - } - final duration = DurationUtils.formatDurationBetween( - liveTime * 1000, - DateTime.now().millisecondsSinceEpoch, - ); - text += duration.isEmpty ? '刚刚开播' : '开播$duration'; - } - if (text.isEmpty) { - return const SizedBox.shrink(); - } - return Text(text, style: const TextStyle(fontSize: 12)); - }), - ], - ), - ], + title: isFullScreen || plPlayerController.isDesktopPip + ? null + : Obx( + () { + RoomInfoH5Data? roomInfoH5 = + _liveRoomController.roomInfoH5.value; + if (roomInfoH5 == null) { + return const SizedBox.shrink(); + } + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => + Get.toNamed('/member?mid=${roomInfoH5.roomInfo?.uid}'), + child: Row( + spacing: 10, + mainAxisSize: MainAxisSize.min, + children: [ + NetworkImgLayer( + width: 34, + height: 34, + type: ImageType.avatar, + src: roomInfoH5.anchorInfo!.baseInfo!.face, + ), + Expanded( + child: Column( + spacing: 1, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + spacing: 10, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Flexible( + child: Text( + roomInfoH5.anchorInfo!.baseInfo!.uname!, + style: const TextStyle( + fontSize: 14, + color: Colors.white, + ), + ), + ), + _liveRoomController.onlineWidget, + ], + ), + Row( + spacing: 10, + children: [ + _liveRoomController.watchedWidget, + _liveRoomController.timeWidget, + ], + ), + ], + ), + ), + ], + ), + ); + }, ), - ); - }, - ), actions: [ // IconButton( // tooltip: '刷新', diff --git a/lib/pages/live_room/widgets/header_control.dart b/lib/pages/live_room/widgets/header_control.dart index 1dcd77db9..f31196844 100644 --- a/lib/pages/live_room/widgets/header_control.dart +++ b/lib/pages/live_room/widgets/header_control.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:PiliPlus/common/widgets/marquee.dart'; +import 'package:PiliPlus/pages/live_room/controller.dart'; import 'package:PiliPlus/pages/video/widgets/header_control.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; import 'package:PiliPlus/plugin/pl_player/widgets/common_btn.dart'; @@ -21,6 +22,7 @@ class LiveHeaderControl extends StatefulWidget { required this.onSendDanmaku, required this.onPlayAudio, required this.isPortrait, + required this.liveController, }); final String? title; @@ -29,6 +31,7 @@ class LiveHeaderControl extends StatefulWidget { final VoidCallback onSendDanmaku; final VoidCallback onPlayAudio; final bool isPortrait; + final LiveRoomController liveController; @override State createState() => _LiveHeaderControlState(); @@ -36,6 +39,7 @@ class LiveHeaderControl extends StatefulWidget { class _LiveHeaderControlState extends State with TimeBatteryMixin { + @override late final plPlayerController = widget.plPlayerController; @override @@ -51,11 +55,12 @@ class _LiveHeaderControlState extends State Widget build(BuildContext context) { final isFullScreen = this.isFullScreen; showCurrTimeIfNeeded(isFullScreen); + final liveController = widget.liveController; Widget child; - if (widget.title case final title?) { - child = MarqueeText( + child = Obx( + () => MarqueeText( key: titleKey, - title, + liveController.title.value, spacing: 30, velocity: 30, style: const TextStyle( @@ -63,30 +68,35 @@ class _LiveHeaderControlState extends State height: 1, color: Colors.white, ), + ), + ); + if (isFullScreen) { + child = Column( + spacing: 5, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + child, + Row( + spacing: 10, + children: [ + if (widget.upName case final upName?) + Text( + upName, + style: const TextStyle( + fontSize: 12, + color: Colors.white, + ), + ), + liveController.watchedWidget, + liveController.onlineWidget, + liveController.timeWidget, + ], + ), + ], ); - if (isFullScreen && widget.upName != null) { - child = Column( - spacing: 5, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - child, - Text( - widget.upName!, - maxLines: 1, - style: const TextStyle( - fontSize: 12, - height: 1, - color: Colors.white, - ), - ), - ], - ); - } - child = Expanded(child: child); - } else { - child = const Spacer(); } + child = Expanded(child: child); return AppBar( backgroundColor: Colors.transparent, foregroundColor: Colors.white, diff --git a/lib/pages/live_search/widgets/live_search_room.dart b/lib/pages/live_search/widgets/live_search_room.dart index fb56a9e6a..34e119a44 100644 --- a/lib/pages/live_search/widgets/live_search_room.dart +++ b/lib/pages/live_search/widgets/live_search_room.dart @@ -2,7 +2,6 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/live/live_search/room_item.dart'; -import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -101,9 +100,9 @@ class LiveCardVSearch extends StatelessWidget { '${item.name}', style: const TextStyle(fontSize: 11, color: Colors.white), ), - if (item.watchedShow?.textSmall != null) + if (item.watchedShow?.textLarge case final textLarge?) Text( - '${NumUtils.numFormat(item.watchedShow!.textSmall)}围观', + textLarge, style: const TextStyle(fontSize: 11, color: Colors.white), ), ], diff --git a/lib/pages/search_panel/live/widgets/item.dart b/lib/pages/search_panel/live/widgets/item.dart index ec7a9b714..a686686fa 100644 --- a/lib/pages/search_panel/live/widgets/item.dart +++ b/lib/pages/search_panel/live/widgets/item.dart @@ -2,6 +2,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/search/result.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -126,7 +127,7 @@ class LiveItem extends StatelessWidget { style: const TextStyle(fontSize: 11, color: Colors.white), ), Text( - '围观:${online.toString()}', + '${NumUtils.numFormat(online)}围观', style: const TextStyle(fontSize: 11, color: Colors.white), ), ], diff --git a/lib/pages/video/widgets/player_focus.dart b/lib/pages/video/widgets/player_focus.dart index d6c51c60a..ac0513099 100644 --- a/lib/pages/video/widgets/player_focus.dart +++ b/lib/pages/video/widgets/player_focus.dart @@ -209,6 +209,14 @@ class PlayerFocus extends StatelessWidget { } return true; + case LogicalKeyboardKey.keyL: + if (isFullScreen || plPlayerController.isDesktopPip) { + plPlayerController.onLockControl( + !plPlayerController.controlsLock.value, + ); + } + return true; + case LogicalKeyboardKey.enter: if (onSkipSegment?.call() ?? false) { return true; @@ -248,14 +256,6 @@ class PlayerFocus extends StatelessWidget { } return true; - case LogicalKeyboardKey.keyL: - if (isFullScreen || plPlayerController.isDesktopPip) { - plPlayerController.onLockControl( - !plPlayerController.controlsLock.value, - ); - } - return true; - case LogicalKeyboardKey.bracketLeft: if (introController case final introController?) { if (!introController.prevPlay()) {