show live online count

update live title

update live watchedshow

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-11-26 11:46:56 +08:00
parent 38a7afd63a
commit 10808c2a84
9 changed files with 179 additions and 106 deletions

View File

@@ -1,14 +1,11 @@
class WatchedShow {
String? textSmall;
String? textLarge;
WatchedShow({
this.textSmall,
this.textLarge,
});
factory WatchedShow.fromJson(Map<String, dynamic> json) => WatchedShow(
textSmall: json['text_small'] as String?,
textLarge: json['text_large'] as String?,
);
}

View File

@@ -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),
),
],

View File

@@ -129,8 +129,9 @@ class LiveCardVFollow extends StatelessWidget {
'${liveItem.areaName}',
style: const TextStyle(fontSize: 11, color: Colors.white),
),
if (liveItem.textSmall case final textSmall?)
Text(
liveItem.textSmall ?? '',
'$textSmall围观',
style: const TextStyle(fontSize: 11, color: Colors.white),
),
],

View File

@@ -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<RichTextItem>? savedDanmaku;
@@ -91,6 +115,36 @@ class LiveRoomController extends GetxController {
final headerKey = GlobalKey<TimeBatteryMixin>();
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<String, dynamic> extra = jsonDecode(
content['extra'],
);
final Map<String, dynamic> 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 (_) {}
}

View File

@@ -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<LiveRoomPage>
onSendDanmaku: _liveRoomController.onSendDanmaku,
onPlayAudio: _liveRoomController.queryLiveUrl,
isPortrait: isPortrait,
liveController: _liveRoomController,
),
bottomControl: BottomControl(
plPlayerController: plPlayerController,
@@ -493,15 +493,19 @@ class _LiveRoomPageState extends State<LiveRoomPage>
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
titleTextStyle: const TextStyle(color: Colors.white),
title: Obx(
title: isFullScreen || plPlayerController.isDesktopPip
? null
: Obx(
() {
RoomInfoH5Data? roomInfoH5 = _liveRoomController.roomInfoH5.value;
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}'),
onTap: () =>
Get.toNamed('/member?mid=${roomInfoH5.roomInfo?.uid}'),
child: Row(
spacing: 10,
mainAxisSize: MainAxisSize.min,
@@ -512,38 +516,37 @@ class _LiveRoomPageState extends State<LiveRoomPage>
type: ImageType.avatar,
src: roomInfoH5.anchorInfo!.baseInfo!.face,
),
Column(
Expanded(
child: Column(
spacing: 1,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
Row(
spacing: 10,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: Text(
roomInfoH5.anchorInfo!.baseInfo!.uname!,
style: const TextStyle(fontSize: 14),
style: const TextStyle(
fontSize: 14,
color: Colors.white,
),
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));
}),
),
),
_liveRoomController.onlineWidget,
],
),
Row(
spacing: 10,
children: [
_liveRoomController.watchedWidget,
_liveRoomController.timeWidget,
],
),
],
),
),
],
),
);

View File

@@ -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<LiveHeaderControl> createState() => _LiveHeaderControlState();
@@ -36,6 +39,7 @@ class LiveHeaderControl extends StatefulWidget {
class _LiveHeaderControlState extends State<LiveHeaderControl>
with TimeBatteryMixin {
@override
late final plPlayerController = widget.plPlayerController;
@override
@@ -51,11 +55,12 @@ class _LiveHeaderControlState extends State<LiveHeaderControl>
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<LiveHeaderControl>
height: 1,
color: Colors.white,
),
),
);
if (isFullScreen && widget.upName != null) {
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(
widget.upName!,
maxLines: 1,
upName,
style: const TextStyle(
fontSize: 12,
height: 1,
color: Colors.white,
),
),
liveController.watchedWidget,
liveController.onlineWidget,
liveController.timeWidget,
],
),
],
);
}
child = Expanded(child: child);
} else {
child = const Spacer();
}
return AppBar(
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,

View File

@@ -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),
),
],

View File

@@ -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),
),
],

View File

@@ -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()) {