diff --git a/lib/models/dynamics/result.dart b/lib/models/dynamics/result.dart index fdc2ae8c5..3e567957e 100644 --- a/lib/models/dynamics/result.dart +++ b/lib/models/dynamics/result.dart @@ -198,11 +198,13 @@ class DynamicMajorModel { DynamicMajorModel({ this.archive, this.draw, + this.ugcSeason, this.type, }); DynamicArchiveModel? archive; DynamicDrawModel? draw; + DynamicArchiveModel? ugcSeason; DynamicOpusModel? opus; // MAJOR_TYPE_DRAW 图片 // MAJOR_TYPE_ARCHIVE 视频 @@ -215,6 +217,9 @@ class DynamicMajorModel { : null; draw = json['draw'] != null ? DynamicDrawModel.fromJson(json['draw']) : null; + ugcSeason = json['ugc_season'] != null + ? DynamicArchiveModel.fromJson(json['ugc_season']) + : null; opus = json['opus'] != null ? DynamicOpusModel.fromJson(json['opus']) : null; type = json['type']; @@ -236,7 +241,7 @@ class DynamicArchiveModel { this.type, }); - String? aid; + int? aid; Map? badge; String? bvid; String? cover; @@ -249,14 +254,14 @@ class DynamicArchiveModel { int? type; DynamicArchiveModel.fromJson(Map json) { - aid = json['aid']; + aid = json['aid'] is String ? int.parse(json['aid']) : json['aid']; badge = json['badge']; bvid = json['bvid']; cover = json['cover']; disablePreview = json['disable_preview']; durationText = json['duration_text']; jumpUrl = json['jump_url']; - stat = Stat.fromJson(json['stat']); + stat = json['stat'] != null ? Stat.fromJson(json['stat']) : null; title = json['title']; type = json['type']; } @@ -265,17 +270,17 @@ class DynamicArchiveModel { class DynamicDrawModel { DynamicDrawModel({ this.id, - this.item, + this.items, }); int? id; - List? item; + List? items; DynamicDrawModel.fromJson(Map json) { id = json['id']; // ignore: prefer_null_aware_operators - item = json['item'] != null - ? json['item'] + items = json['items'] != null + ? json['items'] .map((e) => DynamicDrawItemModel.fromJson(e)) .toList() : null; @@ -332,7 +337,7 @@ class DynamicDrawItemModel { this.width, }); int? height; - int? size; + double? size; String? src; List? tags; int? width; diff --git a/lib/pages/dynamics/widgets/dynamic_panel.dart b/lib/pages/dynamics/widgets/dynamic_panel.dart index 3eb1487cc..a9aabcf5e 100644 --- a/lib/pages/dynamics/widgets/dynamic_panel.dart +++ b/lib/pages/dynamics/widgets/dynamic_panel.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/common/widgets/stat/danmu.dart'; @@ -99,7 +100,10 @@ class DynamicPanel extends StatelessWidget { switch (item.type) { // 图文 case 'DYNAMIC_TYPE_DRAW': - return const Text('DYNAMIC_TYPE_DRAW'); + return Padding( + padding: const EdgeInsets.only(left: 6, right: 6), + child: picWidget(item, context), + ); // 视频 case 'DYNAMIC_TYPE_AV': return Column( @@ -231,7 +235,112 @@ class DynamicPanel extends StatelessWidget { return const Text('DYNAMIC_TYPE_LIVE_RCMD'); // 合集 case 'DYNAMIC_TYPE_UGC_SEASON': - return const Text('DYNAMIC_TYPE_UGC_SEASON'); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // if (floor == 2) ...[ + // Text('@' + item.modules.moduleAuthor.name), + // const SizedBox(height: 8), + // ], + GestureDetector( + onTap: () {}, + child: LayoutBuilder(builder: (context, box) { + double width = box.maxWidth; + return Stack( + children: [ + NetworkImgLayer( + type: floor == 1 ? 'emote' : null, + width: width, + height: width / StyleString.aspectRatio, + src: item.modules.moduleDynamic.major.ugcSeason.cover, + ), + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Container( + padding: const EdgeInsets.fromLTRB(12, 22, 10, 15), + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + gradient: const LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.transparent, + Colors.black87, + ], + tileMode: TileMode.mirror, + ), + borderRadius: floor == 1 + ? null + : const BorderRadius.all(Radius.circular(6))), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + children: [ + Text( + item.modules.moduleDynamic.major.ugcSeason + .durationText, + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .labelMedium! + .fontSize, + color: Colors.white), + ), + const SizedBox(width: 10), + Text( + item.modules.moduleDynamic.major.ugcSeason + .stat.play, + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .labelMedium! + .fontSize, + color: Colors.white), + ), + const SizedBox(width: 10), + Text( + item.modules.moduleDynamic.major.ugcSeason + .stat.danmaku, + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .labelMedium! + .fontSize, + color: Colors.white), + ) + ], + ), + Image.asset( + 'assets/images/play.png', + width: 70, + height: 70, + ), + ], + ), + )), + ], + ); + }), + ), + const SizedBox(height: 6), + Padding( + padding: floor == 1 + ? const EdgeInsets.only(left: 12, right: 12) + : EdgeInsets.zero, + child: Text( + item.modules.moduleDynamic.major.ugcSeason.title, + maxLines: 1, + style: const TextStyle(fontWeight: FontWeight.bold), + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(height: 4), + ], + ); default: return const Text('渲染出错了'); } @@ -269,4 +378,57 @@ class DynamicPanel extends StatelessWidget { ], ); } + + Widget picWidget(item, context) { + List pictures = item.modules.moduleDynamic.major.draw.items; + int len = pictures.length; + List picList = []; + + List list = []; + for (var i = 0; i < len; i++) { + picList.add(pictures[i].src); + list.add( + LayoutBuilder( + builder: (context, BoxConstraints box) { + return GestureDetector( + onTap: () { + Get.toNamed('/preview', + arguments: {'initialPage': i, 'imgList': picList}); + }, + child: NetworkImgLayer( + src: pictures[i].src, + width: box.maxWidth, + height: box.maxWidth, + ), + ); + }, + ), + ); + } + return LayoutBuilder( + builder: (context, BoxConstraints box) { + double maxWidth = box.maxWidth; + double crossCount = len < 3 ? 2 : 3; + double height = maxWidth / + crossCount * + (len % crossCount == 0 + ? len ~/ crossCount + : len ~/ crossCount + 1) + + 6; + return Container( + padding: const EdgeInsets.only(top: 6), + height: height, + child: GridView.count( + padding: EdgeInsets.zero, + physics: const NeverScrollableScrollPhysics(), + crossAxisCount: crossCount.toInt(), + mainAxisSpacing: 4.0, + crossAxisSpacing: 4.0, + childAspectRatio: 1, + children: list, + ), + ); + }, + ); + } }