diff --git a/lib/models/dynamics/result.dart b/lib/models/dynamics/result.dart index 10059e05..9aa94fd1 100644 --- a/lib/models/dynamics/result.dart +++ b/lib/models/dynamics/result.dart @@ -849,6 +849,8 @@ class DynamicMajorModel { ModuleBlocked? blocked; Map? medialist; + SubscriptionNew? subscriptionNew; + DynamicMajorModel.fromJson(Map json) { archive = json['archive'] != null ? DynamicArchiveModel.fromJson(json['archive']) @@ -877,9 +879,157 @@ class DynamicMajorModel { ? null : ModuleBlocked.fromJson(json['blocked']); medialist = json['medialist']; + subscriptionNew = json['subscription_new'] == null + ? null + : SubscriptionNew.fromJson(json['subscription_new']); } } +class SubscriptionNew { + LiveRcmd? liveRcmd; + String? style; + + SubscriptionNew({ + this.liveRcmd, + this.style, + }); + + factory SubscriptionNew.fromJson(Map json) => + SubscriptionNew( + liveRcmd: json["live_rcmd"] == null + ? null + : LiveRcmd.fromJson(json["live_rcmd"]), + style: json["style"], + ); +} + +class LiveRcmd { + LiveRcmdContent? content; + int? reserveType; + + LiveRcmd({ + this.content, + this.reserveType, + }); + + factory LiveRcmd.fromJson(Map json) => LiveRcmd( + content: json["content"] == null + ? null + : LiveRcmdContent.fromJson(jsonDecode(json["content"])), + reserveType: json["reserve_type"], + ); +} + +class LiveRcmdContent { + int? type; + LivePlayInfo? livePlayInfo; + + LiveRcmdContent({ + this.type, + this.livePlayInfo, + }); + + factory LiveRcmdContent.fromJson(Map json) => + LiveRcmdContent( + type: json["type"], + livePlayInfo: json["live_play_info"] == null + ? null + : LivePlayInfo.fromJson(json["live_play_info"]), + ); +} + +class LivePlayInfo { + int? roomId; + int? uid; + int? liveStatus; + int? roomType; + int? playType; + String? title; + String? cover; + int? online; + int? areaId; + String? areaName; + int? parentAreaId; + String? parentAreaName; + int? liveScreenType; + int? liveStartTime; + String? link; + WatchedShow? watchedShow; + int? roomPaidType; + + LivePlayInfo({ + this.roomId, + this.uid, + this.liveStatus, + this.roomType, + this.playType, + this.title, + this.cover, + this.online, + this.areaId, + this.areaName, + this.parentAreaId, + this.parentAreaName, + this.liveScreenType, + this.liveStartTime, + this.link, + this.watchedShow, + this.roomPaidType, + }); + + factory LivePlayInfo.fromJson(Map json) => LivePlayInfo( + roomId: json["room_id"], + uid: json["uid"], + liveStatus: json["live_status"], + roomType: json["room_type"], + playType: json["play_type"], + title: json["title"], + cover: json["cover"], + online: json["online"], + areaId: json["area_id"], + areaName: json["area_name"], + parentAreaId: json["parent_area_id"], + parentAreaName: json["parent_area_name"], + liveScreenType: json["live_screen_type"], + liveStartTime: json["live_start_time"], + link: json["link"], + watchedShow: json["watched_show"] == null + ? null + : WatchedShow.fromJson(json["watched_show"]), + roomPaidType: json["room_paid_type"], + ); +} + +class WatchedShow { + bool? watchedShowSwitch; + int? num; + String? textSmall; + String? textLarge; + String? icon; + String? iconLocation; + String? iconWeb; + + WatchedShow({ + this.watchedShowSwitch, + this.num, + this.textSmall, + this.textLarge, + this.icon, + this.iconLocation, + this.iconWeb, + }); + + factory WatchedShow.fromJson(Map json) => WatchedShow( + watchedShowSwitch: json["switch"], + num: json["num"], + textSmall: json["text_small"], + textLarge: json["text_large"], + icon: json["icon"], + iconLocation: json["icon_location"], + iconWeb: json["icon_web"], + ); +} + class DynamicTopicModel { DynamicTopicModel({ this.id, @@ -1129,7 +1279,7 @@ class DynamicLiveModel { String? areaName; String? title; int? liveStartTime; - Map? watchedShow; + WatchedShow? watchedShow; DynamicLiveModel.fromJson(Map json) { content = json['content']; @@ -1148,7 +1298,9 @@ class DynamicLiveModel { areaName = livePlayInfo['area_name']; title = livePlayInfo['title']; liveStartTime = livePlayInfo['live_start_time']; - watchedShow = livePlayInfo['watched_show']; + watchedShow = livePlayInfo['watched_show'] == null + ? null + : WatchedShow.fromJson(livePlayInfo['watched_show']); } } } diff --git a/lib/pages/dynamics/widgets/forward_panel.dart b/lib/pages/dynamics/widgets/forward_panel.dart index 6ec42416..ec7d2d0f 100644 --- a/lib/pages/dynamics/widgets/forward_panel.dart +++ b/lib/pages/dynamics/widgets/forward_panel.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/pages/article/widgets/opus_content.dart'; import 'package:PiliPlus/pages/dynamics/widgets/additional_panel.dart'; import 'package:PiliPlus/pages/dynamics/widgets/article_panel.dart'; import 'package:PiliPlus/pages/dynamics/widgets/live_panel.dart'; +import 'package:PiliPlus/pages/dynamics/widgets/live_panel_sub.dart'; import 'package:PiliPlus/pages/dynamics/widgets/live_rcmd_panel.dart'; import 'package:PiliPlus/pages/dynamics/widgets/pic_panel.dart'; import 'package:PiliPlus/pages/dynamics/widgets/rich_node_panel.dart'; @@ -524,10 +525,16 @@ Widget forWard( ], ); + case 'DYNAMIC_TYPE_SUBSCRIPTION_NEW' + when item.modules.moduleDynamic?.major?.type == + 'MAJOR_TYPE_SUBSCRIPTION_NEW': + return livePanelSub(theme, source, item, context, floor: floor); default: - return const SizedBox( - width: double.infinity, - child: Text('πŸ™ ζš‚ζœͺζ”―ζŒηš„η±»εž‹οΌŒθ―·θ”η³»εΌ€ε‘θ€…ει¦ˆ '), + return Padding( + padding: floor == 1 + ? const EdgeInsets.symmetric(horizontal: 12) + : EdgeInsets.zero, + child: Text('ζš‚ζœͺζ”―ζŒηš„η±»εž‹: \n${item.idStr}\n${item.type}'), ); } } diff --git a/lib/pages/dynamics/widgets/live_panel.dart b/lib/pages/dynamics/widgets/live_panel.dart index 1e775f7c..14eebc63 100644 --- a/lib/pages/dynamics/widgets/live_panel.dart +++ b/lib/pages/dynamics/widgets/live_panel.dart @@ -18,7 +18,7 @@ Widget livePanel( return const SizedBox.shrink(); } late final authorStyle = TextStyle(color: theme.colorScheme.primary); - TextSpan? richNodes = richNode(theme, item, context); + late TextSpan? richNodes = richNode(theme, item, context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/dynamics/widgets/live_panel_sub.dart b/lib/pages/dynamics/widgets/live_panel_sub.dart new file mode 100644 index 00000000..7b62c337 --- /dev/null +++ b/lib/pages/dynamics/widgets/live_panel_sub.dart @@ -0,0 +1,167 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/badge.dart'; +import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/models/common/badge_type.dart'; +import 'package:PiliPlus/models/dynamics/result.dart'; +import 'package:PiliPlus/pages/dynamics/widgets/rich_node_panel.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +Widget livePanelSub( + ThemeData theme, + String? source, + DynamicItemModel item, + BuildContext context, { + int floor = 1, +}) { + SubscriptionNew? subItem = item.modules.moduleDynamic!.major?.subscriptionNew; + LivePlayInfo? content = subItem?.liveRcmd?.content?.livePlayInfo; + if (subItem == null || content == null) { + return const SizedBox.shrink(); + } + late TextSpan? richNodes = richNode(theme, item, context); + late final authorStyle = TextStyle(color: theme.colorScheme.primary); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (floor == 2) ...[ + Row( + children: [ + GestureDetector( + onTap: () => Get.toNamed( + '/member?mid=${item.modules.moduleAuthor?.mid}', + arguments: {'face': item.modules.moduleAuthor?.face}, + ), + child: Text( + '@${item.modules.moduleAuthor?.name}', + style: authorStyle, + ), + ), + const SizedBox(width: 6), + Text( + Utils.dateFormat(item.modules.moduleAuthor?.pubTs), + style: TextStyle( + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, + ), + ), + ], + ), + ], + const SizedBox(height: 4), + if (item.modules.moduleDynamic?.topic != null) ...[ + GestureDetector( + onTap: () => Get.toNamed( + '/dynTopic', + parameters: { + 'id': item.modules.moduleDynamic!.topic!.id!.toString(), + 'name': item.modules.moduleDynamic!.topic!.name!, + }, + ), + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + child: Text( + '#${item.modules.moduleDynamic!.topic!.name}', + style: authorStyle, + ), + ), + ), + const SizedBox(height: 6), + ], + if (floor == 2 && + item.modules.moduleDynamic?.desc != null && + richNodes != null) ...[ + Text.rich(richNodes), + const SizedBox(height: 6), + ], + Padding( + padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + child: GestureDetector( + onTap: () => Get.toNamed('/liveRoom?roomid=${content.roomId}'), + child: LayoutBuilder( + builder: (context, box) { + double width = box.maxWidth; + return Stack( + clipBehavior: Clip.none, + children: [ + Hero( + tag: content.roomId.toString(), + child: NetworkImgLayer( + width: width, + height: width / StyleString.aspectRatio, + src: content.cover, + ), + ), + PBadge( + text: content.watchedShow?.textLarge, + top: 6, + right: 56, + type: PBadgeType.gray, + ), + PBadge( + text: content.liveStatus == 1 ? 'η›΄ζ’­δΈ­' : 'η›΄ζ’­η»“ζŸ', + top: 6, + right: 6, + ), + if (content.areaName != null) + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Container( + height: 80, + alignment: Alignment.bottomLeft, + padding: const EdgeInsets.fromLTRB(12, 0, 10, 10), + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + gradient: const LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.transparent, + Colors.black45, + ], + ), + borderRadius: floor == 1 + ? const BorderRadius.only( + bottomLeft: StyleString.imgRadius, + bottomRight: StyleString.imgRadius, + ) + : const BorderRadius.only( + bottomLeft: Radius.circular(6), + bottomRight: Radius.circular(6), + ), + ), + child: Text( + content.areaName!, + style: TextStyle( + fontSize: theme.textTheme.labelMedium!.fontSize, + color: Colors.white, + ), + ), + ), + ), + ], + ); + }, + ), + ), + ), + const SizedBox(height: 6), + if (content.title != null) + Padding( + padding: + const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + child: Text( + content.title!, + maxLines: source == 'detail' ? null : 1, + style: const TextStyle(fontWeight: FontWeight.bold), + overflow: source == 'detail' ? null : TextOverflow.ellipsis, + ), + ), + const SizedBox(height: 2), + ], + ); +} diff --git a/lib/pages/dynamics/widgets/live_rcmd_panel.dart b/lib/pages/dynamics/widgets/live_rcmd_panel.dart index 59f28d7d..6f88cfb4 100644 --- a/lib/pages/dynamics/widgets/live_rcmd_panel.dart +++ b/lib/pages/dynamics/widgets/live_rcmd_panel.dart @@ -20,9 +20,7 @@ Widget liveRcmdPanel( if (liveRcmd == null) { return const SizedBox.shrink(); } - int? liveStatus = liveRcmd.liveStatus; - Map? watchedShow = liveRcmd.watchedShow; - TextSpan? richNodes = richNode(theme, item, context); + late TextSpan? richNodes = richNode(theme, item, context); late final authorStyle = TextStyle(color: theme.colorScheme.primary); return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -97,13 +95,13 @@ Widget liveRcmdPanel( ), ), PBadge( - text: watchedShow?['text_large'], + text: liveRcmd.watchedShow?.textLarge, top: 6, right: 56, type: PBadgeType.gray, ), PBadge( - text: liveStatus == 1 ? 'η›΄ζ’­δΈ­' : 'η›΄ζ’­η»“ζŸ', + text: liveRcmd.liveStatus == 1 ? 'η›΄ζ’­δΈ­' : 'η›΄ζ’­η»“ζŸ', top: 6, right: 6, ),