fix: parse live info

opt: items

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-04-30 13:01:47 +08:00
parent 77e4a30bc5
commit 23813eb224
9 changed files with 247 additions and 286 deletions

View File

@@ -31,82 +31,73 @@ class VideoCardHGrpc extends StatelessWidget {
final int aid = videoItem.smallCoverV5.base.args.aid.toInt();
String type = 'video';
final String heroTag = Utils.makeHeroTag(aid);
return Stack(
clipBehavior: Clip.none,
children: [
Semantics(
excludeSemantics: true,
child: InkWell(
borderRadius: BorderRadius.circular(12),
onLongPress: () => imageSaveDialog(
title: videoItem.smallCoverV5.base.title,
cover: videoItem.smallCoverV5.base.cover,
),
onTap: () async {
if (type == 'ketang') {
SmartDialog.showToast('课堂视频暂不支持播放');
return;
}
try {
PiliScheme.routePushFromUrl(videoItem.smallCoverV5.base.uri);
} catch (err) {
SmartDialog.showToast(err.toString());
}
},
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints boxConstraints) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: StyleString.aspectRatio,
child: LayoutBuilder(
builder: (BuildContext context,
BoxConstraints boxConstraints) {
final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
Hero(
tag: heroTag,
child: NetworkImgLayer(
src: videoItem.smallCoverV5.base.cover,
width: maxWidth,
height: maxHeight,
),
),
if (videoItem
.smallCoverV5.coverRightText1.isNotEmpty)
PBadge(
text: Utils.timeFormat(
videoItem.smallCoverV5.coverRightText1),
right: 6.0,
bottom: 6.0,
type: 'gray',
),
if (type != 'video')
PBadge(
text: type,
left: 6.0,
bottom: 6.0,
type: 'primary',
),
],
);
},
),
),
const SizedBox(width: 10),
videoContent(context),
],
);
},
),
),
),
],
return InkWell(
borderRadius: BorderRadius.circular(12),
onLongPress: () => imageSaveDialog(
title: videoItem.smallCoverV5.base.title,
cover: videoItem.smallCoverV5.base.cover,
),
onTap: () async {
if (type == 'ketang') {
SmartDialog.showToast('课堂视频暂不支持播放');
return;
}
try {
PiliScheme.routePushFromUrl(videoItem.smallCoverV5.base.uri);
} catch (err) {
SmartDialog.showToast(err.toString());
}
},
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints boxConstraints) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: StyleString.aspectRatio,
child: LayoutBuilder(
builder:
(BuildContext context, BoxConstraints boxConstraints) {
final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
Hero(
tag: heroTag,
child: NetworkImgLayer(
src: videoItem.smallCoverV5.base.cover,
width: maxWidth,
height: maxHeight,
),
),
if (videoItem.smallCoverV5.coverRightText1.isNotEmpty)
PBadge(
text: Utils.timeFormat(
videoItem.smallCoverV5.coverRightText1),
right: 6.0,
bottom: 6.0,
type: 'gray',
),
if (type != 'video')
PBadge(
text: type,
left: 6.0,
bottom: 6.0,
type: 'primary',
),
],
);
},
),
),
const SizedBox(width: 10),
videoContent(context),
],
);
},
),
);
}

View File

@@ -55,57 +55,49 @@ class VideoCardVMemberHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
clipBehavior: Clip.none,
children: [
Semantics(
excludeSemantics: true,
child: Card(
clipBehavior: Clip.hardEdge,
margin: EdgeInsets.zero,
child: InkWell(
onTap: () => onPushDetail(Utils.makeHeroTag(videoItem.bvid)),
onLongPress: () => imageSaveDialog(
title: videoItem.title,
cover: videoItem.cover,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AspectRatio(
aspectRatio: StyleString.aspectRatio,
child: LayoutBuilder(
builder: (context, boxConstraints) {
double maxWidth = boxConstraints.maxWidth;
double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: videoItem.cover,
width: maxWidth,
height: maxHeight,
),
if ((videoItem.duration ?? -1) > 0)
PBadge(
bottom: 6,
right: 7,
size: 'small',
type: 'gray',
text: Utils.timeFormat(videoItem.duration),
)
],
);
},
),
),
videoContent(context, videoItem)
],
return Card(
clipBehavior: Clip.hardEdge,
margin: EdgeInsets.zero,
child: InkWell(
onTap: () => onPushDetail(Utils.makeHeroTag(videoItem.bvid)),
onLongPress: () => imageSaveDialog(
title: videoItem.title,
cover: videoItem.cover,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AspectRatio(
aspectRatio: StyleString.aspectRatio,
child: LayoutBuilder(
builder: (context, boxConstraints) {
double maxWidth = boxConstraints.maxWidth;
double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: videoItem.cover,
width: maxWidth,
height: maxHeight,
),
if ((videoItem.duration ?? -1) > 0)
PBadge(
bottom: 6,
right: 7,
size: 'small',
type: 'gray',
text: Utils.timeFormat(videoItem.duration),
)
],
);
},
),
),
),
videoContent(context, videoItem)
],
),
],
),
);
}
}

View File

@@ -16,11 +16,16 @@ class RoomInfoH5Model {
Map? blockInfo;
RoomInfoH5Model.fromJson(Map<String, dynamic> json) {
roomInfo = RoomInfo.fromJson(json['room_info']);
anchorInfo = AnchorInfo.fromJson(json['anchor_info']);
roomInfo =
json['room_info'] == null ? null : RoomInfo.fromJson(json['room_info']);
anchorInfo = json['anchor_info'] == null
? null
: AnchorInfo.fromJson(json['anchor_info']);
isRoomFeed = json['is_room_feed'];
watchedShow = json['watched_show'];
likeInfoV3 = LikeInfoV3.fromJson(json['like_info_v3']);
likeInfoV3 = json['like_info_v3'] == null
? null
: LikeInfoV3.fromJson(json['like_info_v3']);
blockInfo = json['block_info'];
}
}
@@ -82,15 +87,18 @@ class RoomInfo {
class AnchorInfo {
AnchorInfo({
this.baseInfo,
this.relationInfo,
// this.relationInfo,
});
BaseInfo? baseInfo;
RelationInfo? relationInfo;
// RelationInfo? relationInfo;
AnchorInfo.fromJson(Map<String, dynamic> json) {
baseInfo = BaseInfo.fromJson(json['base_info']);
relationInfo = RelationInfo.fromJson(json['relation_info']);
baseInfo =
json['base_info'] == null ? null : BaseInfo.fromJson(json['base_info']);
// relationInfo = json['relation_info'] == null
// ? null
// : RelationInfo.fromJson(json['relation_info']);
}
}

View File

@@ -43,20 +43,13 @@ class BangumiCardVMemberHome extends StatelessWidget {
child: AspectRatio(
aspectRatio: 0.75,
child: LayoutBuilder(builder: (context, boxConstraints) {
final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
Hero(
tag: heroTag,
child: NetworkImgLayer(
src: bangumiItem.cover,
width: maxWidth,
height: maxHeight,
),
),
],
return Hero(
tag: heroTag,
child: NetworkImgLayer(
src: bangumiItem.cover,
width: boxConstraints.maxWidth,
height: boxConstraints.maxHeight,
),
);
}),
),

View File

@@ -30,7 +30,7 @@ class LiveRoomController extends GetxController {
RxBool volumeOff = false.obs;
PlPlayerController plPlayerController =
PlPlayerController.getInstance(videoType: 'live');
Rx<RoomInfoH5Model> roomInfoH5 = RoomInfoH5Model().obs;
Rx<RoomInfoH5Model?> roomInfoH5 = Rx<RoomInfoH5Model?>(null);
RxList<dynamic> messages = [].obs;
RxBool disableAutoScroll = false.obs;
@@ -50,6 +50,7 @@ class LiveRoomController extends GetxController {
void onInit() {
super.onInit();
roomId = int.parse(Get.parameters['roomid']!);
queryLiveInfoH5();
if (Accounts.main.isLogin && !MineController.anonymity.value) {
VideoHttp.roomEntryAction(roomId: roomId);
}
@@ -131,7 +132,6 @@ class LiveRoomController extends GetxController {
heroTag,
);
}
return res;
}
LiveMessageStream? msgStream;

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:io';
import 'dart:ui';
import 'package:PiliPlus/models/live/room_info_h5.dart';
import 'package:PiliPlus/pages/live_room/send_dm_panel.dart';
import 'package:PiliPlus/pages/live_room/widgets/chat.dart';
import 'package:PiliPlus/pages/live_room/widgets/header_control.dart';
@@ -36,7 +37,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
late final int _roomId;
late final LiveRoomController _liveRoomController;
late final PlPlayerController plPlayerController;
late Future? _futureBuilder;
late Future? _futureBuilderFuture;
bool get isFullScreen => plPlayerController.isFullScreen.value;
@@ -113,7 +113,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
}
void videoSourceInit() {
_futureBuilder = _liveRoomController.queryLiveInfoH5();
plPlayerController = _liveRoomController.plPlayerController;
}
@@ -222,14 +221,14 @@ class _LiveRoomPageState extends State<LiveRoomPage>
: Positioned.fill(
child: Opacity(
opacity: 0.6,
child: _liveRoomController.roomInfoH5.value.roomInfo
child: _liveRoomController.roomInfoH5.value?.roomInfo
?.appBackground?.isNotEmpty ==
true
? CachedNetworkImage(
fit: BoxFit.cover,
width: Get.width,
height: Get.height,
imageUrl: _liveRoomController.roomInfoH5.value
imageUrl: _liveRoomController.roomInfoH5.value!
.roomInfo!.appBackground!.http2https,
)
: Image.asset(
@@ -367,62 +366,54 @@ class _LiveRoomPageState extends State<LiveRoomPage>
foregroundColor: Colors.white,
toolbarHeight: isFullScreen ? 0 : null,
titleTextStyle: TextStyle(color: Colors.white),
title: FutureBuilder(
future: _futureBuilder,
builder: (context, snapshot) {
if (snapshot.data == null) {
return const SizedBox.shrink();
}
Map data = snapshot.data as Map;
if (data['status']) {
return Obx(
() => Row(
children: [
GestureDetector(
onTap: () {
dynamic uid =
_liveRoomController.roomInfoH5.value.roomInfo?.uid;
Get.toNamed(
'/member?mid=$uid',
arguments: {
'heroTag': Utils.makeHeroTag(uid),
},
);
},
child: NetworkImgLayer(
width: 34,
height: 34,
type: 'avatar',
src: _liveRoomController
.roomInfoH5.value.anchorInfo!.baseInfo!.face,
),
),
const SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_liveRoomController
.roomInfoH5.value.anchorInfo!.baseInfo!.uname!,
style: const TextStyle(fontSize: 14),
title: Obx(
() {
return _liveRoomController.roomInfoH5.value == null
? const SizedBox.shrink()
: Row(
children: [
GestureDetector(
onTap: () {
dynamic uid = _liveRoomController
.roomInfoH5.value!.roomInfo?.uid;
Get.toNamed(
'/member?mid=$uid',
arguments: {
'heroTag': Utils.makeHeroTag(uid),
},
);
},
child: NetworkImgLayer(
width: 34,
height: 34,
type: 'avatar',
src: _liveRoomController
.roomInfoH5.value!.anchorInfo!.baseInfo!.face,
),
const SizedBox(height: 1),
if (_liveRoomController.roomInfoH5.value.watchedShow !=
null)
),
const SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_liveRoomController.roomInfoH5.value
.watchedShow!['text_large'] ??
'',
style: const TextStyle(fontSize: 12),
_liveRoomController
.roomInfoH5.value!.anchorInfo!.baseInfo!.uname!,
style: const TextStyle(fontSize: 14),
),
],
),
],
),
);
} else {
return const SizedBox.shrink();
}
const SizedBox(height: 1),
if (_liveRoomController
.roomInfoH5.value!.watchedShow !=
null)
Text(
_liveRoomController.roomInfoH5.value!
.watchedShow!['text_large'] ??
'',
style: const TextStyle(fontSize: 12),
),
],
),
],
);
},
),
actions: [
@@ -452,42 +443,39 @@ class _LiveRoomPageState extends State<LiveRoomPage>
],
),
),
PopupMenuItem(
onTap: () {
try {
PageUtils.pmShare(
this.context,
content: {
"cover": _liveRoomController
.roomInfoH5.value.roomInfo!.cover!,
"sourceID": _liveRoomController.roomId.toString(),
"title": _liveRoomController
.roomInfoH5.value.roomInfo!.title!,
"url":
"https://live.bilibili.com/${_liveRoomController.roomId}",
"authorID": _liveRoomController
.roomInfoH5.value.roomInfo!.uid
.toString(),
"source": "直播",
"desc": _liveRoomController
.roomInfoH5.value.roomInfo!.title!,
"author": _liveRoomController
.roomInfoH5.value.anchorInfo!.baseInfo!.uname,
},
);
} catch (e) {
SmartDialog.showToast(e.toString());
}
},
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.forward_to_inbox, size: 19),
SizedBox(width: 10),
Text('分享至消息'),
],
if (_liveRoomController.roomInfoH5.value != null)
PopupMenuItem(
onTap: () {
try {
RoomInfoH5Model roomInfo =
_liveRoomController.roomInfoH5.value!;
PageUtils.pmShare(
this.context,
content: {
"cover": roomInfo.roomInfo!.cover!,
"sourceID": _liveRoomController.roomId.toString(),
"title": roomInfo.roomInfo!.title!,
"url":
"https://live.bilibili.com/${_liveRoomController.roomId}",
"authorID": roomInfo.roomInfo!.uid.toString(),
"source": "直播",
"desc": roomInfo.roomInfo!.title!,
"author": roomInfo.anchorInfo!.baseInfo!.uname,
},
);
} catch (e) {
SmartDialog.showToast(e.toString());
}
},
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.forward_to_inbox, size: 19),
SizedBox(width: 10),
Text('分享至消息'),
],
),
),
),
],
),
],

View File

@@ -45,15 +45,10 @@ class MemberFavItem extends StatelessWidget {
aspectRatio: StyleString.aspectRatio,
child: LayoutBuilder(
builder: (context, boxConstraints) {
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: item['cover'],
width: boxConstraints.maxWidth,
height: boxConstraints.maxHeight,
),
],
return NetworkImgLayer(
src: item['cover'],
width: boxConstraints.maxWidth,
height: boxConstraints.maxHeight,
);
},
),

View File

@@ -85,47 +85,42 @@ class SubVideoCardH extends StatelessWidget {
Widget videoContent(context) {
return Expanded(
child: Stack(
clipBehavior: Clip.none,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
Expanded(
child: Text(
'${videoItem.title}',
textAlign: TextAlign.start,
style: const TextStyle(
letterSpacing: 0.3,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
Text(
Utils.dateFormat(videoItem.pubtime),
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.outline,
),
),
const SizedBox(height: 3),
Row(
children: [
Expanded(
child: Text(
'${videoItem.title}',
textAlign: TextAlign.start,
style: const TextStyle(
letterSpacing: 0.3,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
StatView(
context: context,
theme: 'gray',
value: Utils.numFormat(videoItem.cntInfo?['play']),
),
Text(
Utils.dateFormat(videoItem.pubtime),
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.outline,
),
),
const SizedBox(height: 3),
Row(
children: [
StatView(
context: context,
theme: 'gray',
value: Utils.numFormat(videoItem.cntInfo?['play']),
),
const SizedBox(width: 8),
StatDanMu(
context: context,
theme: 'gray',
value: Utils.numFormat(videoItem.cntInfo?['danmaku']),
),
const Spacer(),
],
const SizedBox(width: 8),
StatDanMu(
context: context,
theme: 'gray',
value: Utils.numFormat(videoItem.cntInfo?['danmaku']),
),
const Spacer(),
],
),
],

View File

@@ -732,7 +732,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
return Stack(
fit: StackFit.passthrough,
key: _playerKey,
clipBehavior: Clip.none,
children: <Widget>[
Obx(
() => Video(