mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-01 00:28:18 +08:00
show live online count
update live title update live watchedshow Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -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?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -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 (_) {}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
Reference in New Issue
Block a user