diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index 5de83ce2..5ac9dcf0 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -66,6 +66,7 @@ class VideoDetailData { HonorReply? honorReply; String? likeIcon; bool? needJumpBv; + String? epId; VideoDetailData({ this.bvid, @@ -101,6 +102,7 @@ class VideoDetailData { this.honorReply, this.likeIcon, this.needJumpBv, + this.epId, }); VideoDetailData.fromJson(Map json) { @@ -150,6 +152,15 @@ class VideoDetailData { : HonorReply.fromJson(json["honor_reply"]); likeIcon = json["like_icon"]; needJumpBv = json["need_jump_bv"]; + if (json['redirect_url'] != null) { + RegExp regex = RegExp(r'\d+'); + Iterable matches = regex.allMatches(json['redirect_url']); + List numbers = []; + for (Match match in matches) { + numbers.add(match.group(0)!); + } + epId = numbers[0]; + } } Map toJson() => { diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index d3cbabda..91e3d527 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -18,7 +18,12 @@ import 'package:share_plus/share_plus.dart'; class BangumiIntroController extends GetxController { // 视频bvid String bvid = Get.parameters['bvid']!; - int seasonId = int.parse(Get.parameters['seasonId']!); + var seasonId = Get.parameters['seasonId'] != null + ? int.parse(Get.parameters['seasonId']!) + : null; + var epId = Get.parameters['epId'] != null + ? int.parse(Get.parameters['epId']!) + : null; // 是否预渲染 骨架屏 bool preRender = false; @@ -84,9 +89,7 @@ class BangumiIntroController extends GetxController { // 获取番剧简介&选集 Future queryBangumiIntro() async { - print('🐶🐶: $seasonId'); - var result = await SearchHttp.bangumiInfo(seasonId: seasonId); - print("🐶🐶:${result['data']}"); + var result = await SearchHttp.bangumiInfo(seasonId: seasonId, epId: epId); if (result['status']) { bangumiDetail.value = result['data']; } diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index dc1d5252..081ecc4e 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -86,7 +86,7 @@ class BangumiInfo extends StatefulWidget { } class _BangumiInfoState extends State { - late BangumiInfoModel bangumiItem; + late BangumiInfoModel? bangumiItem; final BangumiIntroController bangumiIntroController = Get.put(BangumiIntroController(), tag: Get.arguments['heroTag']); bool isExpand = false; @@ -98,7 +98,7 @@ class _BangumiInfoState extends State { @override void initState() { super.initState(); - bangumiItem = bangumiIntroController.bangumiItem!; + bangumiItem = bangumiIntroController.bangumiItem; videoDetailCtr = Get.find(tag: Get.arguments['heroTag']); sheetHeight = localCache.get('sheetHeight'); @@ -139,176 +139,189 @@ class _BangumiInfoState extends State { padding: const EdgeInsets.only( left: StyleString.safeSpace, right: StyleString.safeSpace, top: 13), sliver: SliverToBoxAdapter( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - NetworkImgLayer( - width: 105, - height: 160, - src: !widget.loadingStatus - ? widget.bangumiDetail!.cover! - : bangumiItem.cover!, - ), - const SizedBox(width: 10), - Expanded( - child: InkWell( - onTap: () => showIntroDetail(), - child: SizedBox( - height: 158, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - Expanded( - child: Text( - !widget.loadingStatus - ? widget.bangumiDetail!.title! - : bangumiItem.title!, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - const SizedBox(width: 20), - SizedBox( - width: 34, - height: 34, - child: IconButton( - style: ButtonStyle( - padding: MaterialStateProperty.all( - EdgeInsets.zero), - backgroundColor: - MaterialStateProperty.resolveWith( - (states) { - return t.colorScheme.primaryContainer - .withOpacity(0.7); - }), - ), - onPressed: () {}, - icon: Icon( - Icons.favorite_border_rounded, - color: t.colorScheme.primary, - size: 22, - ), - ), - ), - ], - ), - Row( - children: [ - // const SizedBox(width: 6), - StatView( - theme: 'gray', - view: !widget.loadingStatus - ? widget.bangumiDetail!.stat!['views'] - : bangumiItem.stat!['views'], - size: 'medium', - ), - const SizedBox(width: 6), - StatDanMu( - theme: 'gray', - danmu: !widget.loadingStatus - ? widget.bangumiDetail!.stat!['danmakus'] - : bangumiItem.stat!['danmakus'], - size: 'medium', - ), - ], - ), - const SizedBox(height: 2), - Row( - children: [ - Text( - !widget.loadingStatus - ? widget.bangumiDetail!.areas!.first['name'] - : bangumiItem.areas!.first['name'], - style: TextStyle( - fontSize: 12, - color: t.colorScheme.outline, - ), - ), - const SizedBox(width: 6), - Text( - !widget.loadingStatus - ? widget.bangumiDetail! - .publish!['pub_time_show'] - : bangumiItem.publish!['pub_time_show'], - style: TextStyle( - fontSize: 12, - color: t.colorScheme.outline, - ), - ), - const SizedBox(width: 6), - Text( - !widget.loadingStatus - ? widget.bangumiDetail!.newEp!['desc'] - : bangumiItem.newEp!['desc'], - style: TextStyle( - fontSize: 12, - color: t.colorScheme.outline, - ), - ), - ], - ), - const SizedBox(height: 10), - Text( - '简介:${!widget.loadingStatus ? widget.bangumiDetail!.evaluate! : bangumiItem.evaluate!}', - maxLines: 3, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12, - color: t.colorScheme.outline, - ), - ), - const Spacer(), - Text( - '评分 ${!widget.loadingStatus ? widget.bangumiDetail!.rating!['score']! : bangumiItem.rating!['score']!}', - style: TextStyle( - fontSize: 13, - color: t.colorScheme.primary, - ), - ), - ], + child: !widget.loadingStatus || bangumiItem != null + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + NetworkImgLayer( + width: 105, + height: 160, + src: !widget.loadingStatus + ? widget.bangumiDetail!.cover! + : bangumiItem!.cover!, ), - ), + const SizedBox(width: 10), + Expanded( + child: InkWell( + onTap: () => showIntroDetail(), + child: SizedBox( + height: 158, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Expanded( + child: Text( + !widget.loadingStatus + ? widget.bangumiDetail!.title! + : bangumiItem!.title!, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(width: 20), + SizedBox( + width: 34, + height: 34, + child: IconButton( + style: ButtonStyle( + padding: MaterialStateProperty.all( + EdgeInsets.zero), + backgroundColor: + MaterialStateProperty.resolveWith( + (states) { + return t + .colorScheme.primaryContainer + .withOpacity(0.7); + }), + ), + onPressed: () {}, + icon: Icon( + Icons.favorite_border_rounded, + color: t.colorScheme.primary, + size: 22, + ), + ), + ), + ], + ), + Row( + children: [ + // const SizedBox(width: 6), + StatView( + theme: 'gray', + view: !widget.loadingStatus + ? widget.bangumiDetail!.stat!['views'] + : bangumiItem!.stat!['views'], + size: 'medium', + ), + const SizedBox(width: 6), + StatDanMu( + theme: 'gray', + danmu: !widget.loadingStatus + ? widget + .bangumiDetail!.stat!['danmakus'] + : bangumiItem!.stat!['danmakus'], + size: 'medium', + ), + ], + ), + const SizedBox(height: 2), + Row( + children: [ + Text( + !widget.loadingStatus + ? widget.bangumiDetail!.areas! + .first['name'] + : bangumiItem!.areas!.first['name'], + style: TextStyle( + fontSize: 12, + color: t.colorScheme.outline, + ), + ), + const SizedBox(width: 6), + Text( + !widget.loadingStatus + ? widget.bangumiDetail! + .publish!['pub_time_show'] + : bangumiItem! + .publish!['pub_time_show'], + style: TextStyle( + fontSize: 12, + color: t.colorScheme.outline, + ), + ), + const SizedBox(width: 6), + Text( + !widget.loadingStatus + ? widget.bangumiDetail!.newEp!['desc'] + : bangumiItem!.newEp!['desc'], + style: TextStyle( + fontSize: 12, + color: t.colorScheme.outline, + ), + ), + ], + ), + const SizedBox(height: 10), + Text( + '简介:${!widget.loadingStatus ? widget.bangumiDetail!.evaluate! : bangumiItem!.evaluate!}', + maxLines: 3, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12, + color: t.colorScheme.outline, + ), + ), + const Spacer(), + if (bangumiItem != null && + bangumiItem!.rating != null) + Text( + '评分 ${!widget.loadingStatus ? widget.bangumiDetail!.rating!['score']! : bangumiItem!.rating!['score']!}', + style: TextStyle( + fontSize: 13, + color: t.colorScheme.primary, + ), + ), + ], + ), + ), + ), + ), + ], ), - ), - ], - ), - const SizedBox(height: 6), - // 点赞收藏转发 布局样式1 - // SingleChildScrollView( - // padding: const EdgeInsets.only(top: 7, bottom: 7), - // scrollDirection: Axis.horizontal, - // child: actionRow( - // context, - // bangumiIntroController, - // videoDetailCtr, - // ), - // ), - // 点赞收藏转发 布局样式2 - actionGrid(context, bangumiIntroController), - // 番剧分p - if (!widget.loadingStatus && - widget.bangumiDetail!.episodes!.isNotEmpty) ...[ - BangumiPanel( - pages: widget.bangumiDetail!.episodes!, - cid: widget.bangumiDetail!.episodes!.first.cid, - sheetHeight: sheetHeight, - changeFuc: (bvid, cid) => - bangumiIntroController.changeSeasonOrbangu(bvid, cid), + const SizedBox(height: 6), + // 点赞收藏转发 布局样式1 + // SingleChildScrollView( + // padding: const EdgeInsets.only(top: 7, bottom: 7), + // scrollDirection: Axis.horizontal, + // child: actionRow( + // context, + // bangumiIntroController, + // videoDetailCtr, + // ), + // ), + // 点赞收藏转发 布局样式2 + actionGrid(context, bangumiIntroController), + // 番剧分p + if (!widget.loadingStatus && + widget.bangumiDetail!.episodes!.isNotEmpty) ...[ + BangumiPanel( + pages: widget.bangumiDetail!.episodes!, + cid: widget.bangumiDetail!.episodes!.first.cid, + sheetHeight: sheetHeight, + changeFuc: (bvid, cid) => + bangumiIntroController.changeSeasonOrbangu(bvid, cid), + ) + ], + ], ) - ], - ], - ), + : const SizedBox( + height: 100, + child: Center( + child: CircularProgressIndicator(), + ), + ), ), ); } diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index 6ee22024..5d39b7cd 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -143,88 +143,93 @@ class _BangumiPanelState extends State { SingleChildScrollView( padding: const EdgeInsets.only(top: 7, bottom: 7), scrollDirection: Axis.horizontal, - child: Row( - children: [ - for (int i = 0; i < widget.pages.length; i++) ...[ - Container( - width: 150, - margin: const EdgeInsets.only(right: 10), - child: Material( - color: Theme.of(context).colorScheme.onInverseSurface, - borderRadius: BorderRadius.circular(6), - clipBehavior: Clip.hardEdge, - child: InkWell( - onTap: () async { - if (widget.pages[i].badge != null) { - SmartDialog.showToast('需要大会员'); - return; - } - await widget.changeFuc!( - widget.pages[i].bvid, - widget.pages[i].cid, - ); - currentIndex = i; - setState(() {}); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - if (i == currentIndex) ...[ - Image.asset( - 'assets/images/live.gif', - color: - Theme.of(context).colorScheme.primary, - height: 12, + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: MediaQuery.of(context).size.width, + ), + child: Row( + children: [ + for (int i = 0; i < widget.pages.length; i++) ...[ + Container( + width: 150, + margin: const EdgeInsets.only(right: 10), + child: Material( + color: Theme.of(context).colorScheme.onInverseSurface, + borderRadius: BorderRadius.circular(6), + clipBehavior: Clip.hardEdge, + child: InkWell( + onTap: () async { + if (widget.pages[i].badge != null) { + SmartDialog.showToast('需要大会员'); + return; + } + await widget.changeFuc!( + widget.pages[i].bvid, + widget.pages[i].cid, + ); + currentIndex = i; + setState(() {}); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + if (i == currentIndex) ...[ + Image.asset( + 'assets/images/live.gif', + color: + Theme.of(context).colorScheme.primary, + height: 12, + ), + const SizedBox(width: 6) + ], + Text( + '第${i + 1}话', + style: TextStyle( + fontSize: 13, + color: i == currentIndex + ? Theme.of(context) + .colorScheme + .primary + : Theme.of(context) + .colorScheme + .onSurface), ), - const SizedBox(width: 6) + const SizedBox(width: 2), + if (widget.pages[i].badge != null) ...[ + Image.asset( + 'assets/images/big-vip.png', + height: 16, + ), + ], ], - Text( - '第${i + 1}话', - style: TextStyle( - fontSize: 13, - color: i == currentIndex - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .onSurface), - ), - const SizedBox(width: 2), - if (widget.pages[i].badge != null) ...[ - Image.asset( - 'assets/images/big-vip.png', - height: 16, - ), - ], - ], - ), - const SizedBox(height: 3), - Text( - widget.pages[i].longTitle!, - maxLines: 1, - style: TextStyle( - fontSize: 13, - color: i == currentIndex - ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onSurface), - overflow: TextOverflow.ellipsis, - ) - ], + ), + const SizedBox(height: 3), + Text( + widget.pages[i].longTitle!, + maxLines: 1, + style: TextStyle( + fontSize: 13, + color: i == currentIndex + ? Theme.of(context).colorScheme.primary + : Theme.of(context) + .colorScheme + .onSurface), + overflow: TextOverflow.ellipsis, + ) + ], + ), ), ), ), ), - ), - ] - ], + ] + ], + ), ), ) ], diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index b5dc3ee3..c4a7b791 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -1,10 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/badge.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/http/search.dart'; +import 'package:pilipala/http/video.dart'; +import 'package:pilipala/models/bangumi/info.dart'; import 'package:pilipala/models/common/business_type.dart'; +import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/models/live/item.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/utils.dart'; @@ -47,6 +51,50 @@ class HistoryItem extends StatelessWidget { '/liveRoom?roomid=${videoItem.history.oid}', arguments: {'liveItem': liveItem}, ); + } else if (videoItem.badge == '番剧' || + videoItem.tagName.contains('动画')) { + /// hack + var bvid = videoItem.history.bvid; + if (bvid != null && bvid != '') { + var result = await VideoHttp.videoIntro(bvid: bvid); + if (result['status']) { + String bvid = result['data'].bvid!; + int cid = result['data'].cid!; + String pic = result['data'].pic!; + String heroTag = Utils.makeHeroTag(cid); + Get.toNamed( + '/video?bvid=$bvid&cid=$cid&epId=${result['data'].epId}', + arguments: { + 'pic': pic, + 'heroTag': heroTag, + 'videoType': SearchType.media_bangumi, + }, + ); + } + } else { + if (videoItem.history.epid != '') { + SmartDialog.showLoading(msg: '获取中...'); + var res = + await SearchHttp.bangumiInfo(epId: videoItem.history.epid); + SmartDialog.dismiss(); + if (res['status']) { + EpisodeItem episode = res['data'].episodes.first; + String bvid = episode.bvid!; + int cid = episode.cid!; + String pic = episode.cover!; + String heroTag = Utils.makeHeroTag(cid); + Get.toNamed( + '/video?bvid=$bvid&cid=$cid&seasonId=${res['data'].seasonId}', + arguments: { + 'pic': pic, + 'heroTag': heroTag, + 'videoType': SearchType.media_bangumi, + 'bangumiItem': res['data'], + }, + ); + } + } + } } else { int cid = videoItem.history.cid ?? // videoItem.history.oid ?? @@ -150,7 +198,7 @@ class VideoContent extends StatelessWidget { maxLines: videoItem.videos > 1 ? 1 : 2, overflow: TextOverflow.ellipsis, ), - if (videoItem.videos > 1) + if (videoItem.showTitle != null) Text( videoItem.showTitle, textAlign: TextAlign.start,