diff --git a/lib/http/user.dart b/lib/http/user.dart index 3b734d79f..14292e730 100644 --- a/lib/http/user.dart +++ b/lib/http/user.dart @@ -69,7 +69,8 @@ class UserHttp { 'keyword': keyword, 'order': order, 'type': 0, - 'tid': 0 + 'tid': 0, + 'platform': 'web' }); if (res.data['code'] == 0) { FavDetailData data = FavDetailData.fromJson(res.data['data']); diff --git a/lib/main.dart b/lib/main.dart index bd38bb875..303c5b19c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:flutter/services.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -16,11 +17,15 @@ import 'package:media_kit/media_kit.dart'; // Provides [Player], [Media], [Playl void main() async { WidgetsFlutterBinding.ensureInitialized(); MediaKit.ensureInitialized(); - await GStrorage.init(); - runApp(const MyApp()); - await Request.setCookie(); - await Data.init(); - await GStrorage.lazyInit(); + SystemChrome.setPreferredOrientations( + [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]) + .then((_) async { + await GStrorage.init(); + runApp(const MyApp()); + await Request.setCookie(); + await Data.init(); + await GStrorage.lazyInit(); + }); } class MyApp extends StatelessWidget { diff --git a/lib/models/user/fav_detail.dart b/lib/models/user/fav_detail.dart index d8013b75d..e69697e6e 100644 --- a/lib/models/user/fav_detail.dart +++ b/lib/models/user/fav_detail.dart @@ -41,9 +41,10 @@ class FavDetailItemData { this.bvId, this.bvid, // this.season, - // this.ogv, + this.ogv, this.stat, this.cid, + this.epId, }); int? id; @@ -62,8 +63,10 @@ class FavDetailItemData { int? favTime; String? bvId; String? bvid; + Map? ogv; Stat? stat; int? cid; + String? epId; FavDetailItemData.fromJson(Map json) { id = json['id']; @@ -82,8 +85,22 @@ class FavDetailItemData { favTime = json['fav_time']; bvId = json['bv_id']; bvid = json['bvid']; + ogv = json['ogv']; stat = Stat.fromJson(json['cnt_info']); - cid = json['ugc']['first_cid']; + cid = json['ugc'] != null ? json['ugc']['first_cid'] : null; + if (json['link'] != null && json['link'].contains('/bangumi')) { + epId = resolveEpId(json['link']); + } + } + + String resolveEpId(url) { + RegExp regex = RegExp(r'\d+'); + Iterable matches = regex.allMatches(url); + List numbers = []; + for (Match match in matches) { + numbers.add(match.group(0)!); + } + return numbers[0]; } } diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index 5ac9dcf00..277d1e309 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -153,16 +153,20 @@ class VideoDetailData { 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]; + epId = resolveEpId(json['redirect_url']); } } + String resolveEpId(url) { + RegExp regex = RegExp(r'\d+'); + Iterable matches = regex.allMatches(url); + List numbers = []; + for (Match match in matches) { + numbers.add(match.group(0)!); + } + return numbers[0]; + } + Map toJson() => { "bvid": bvid, "aid": aid, diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index c4bb1bb8b..b2114fc80 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -96,13 +96,13 @@ class BangumiIntroController extends GetxController { } if (userLogin) { // 获取点赞状态 - // queryHasLikeVideo(); + queryHasLikeVideo(); // 获取投币状态 - // queryHasCoinVideo(); + queryHasCoinVideo(); // 获取收藏状态 - // queryHasFavVideo(); + queryHasFavVideo(); // - // queryFollowStatus(); + queryFollowStatus(); } return result; } @@ -340,9 +340,12 @@ class BangumiIntroController extends GetxController { videoDetailCtr.cid = cid; videoDetailCtr.queryVideoUrl(); // 重新请求评论 - VideoReplyController videoReplyCtr = - Get.find(tag: Get.arguments['heroTag']); - videoReplyCtr.aid = aid; - videoReplyCtr.queryReplyList(type: 'init'); + try { + /// 未渲染回复组件时可能异常 + VideoReplyController videoReplyCtr = + Get.find(tag: Get.arguments['heroTag']); + videoReplyCtr.aid = aid; + videoReplyCtr.queryReplyList(type: 'init'); + } catch (_) {} } } diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index 41d7dc51b..b71ec77ca 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -13,6 +13,7 @@ import 'package:pilipala/pages/bangumi/widgets/bangumi_panel.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/introduction/widgets/action_item.dart'; import 'package:pilipala/pages/video/detail/introduction/widgets/action_row_item.dart'; +import 'package:pilipala/pages/video/detail/introduction/widgets/fav_panel.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; @@ -110,14 +111,14 @@ class _BangumiInfoState extends State { SmartDialog.showToast('账号未登录'); return; } - // showModalBottomSheet( - // context: context, - // useRootNavigator: true, - // isScrollControlled: true, - // builder: (context) { - // return FavPanel(ctr: videoIntroController); - // }, - // ); + showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + builder: (context) { + return FavPanel(ctr: bangumiIntroController); + }, + ); } // 视频介绍 @@ -356,12 +357,6 @@ class _BangumiInfoState extends State { ? widget.bangumiDetail!.stat!['likes']!.toString() : '-'), ), - ActionItem( - icon: const Icon(FontAwesomeIcons.clock), - onTap: () => () {}, - selectStatus: false, - loadingStatus: widget.loadingStatus, - text: '稍后再看'), Obx( () => ActionItem( icon: const Icon(FontAwesomeIcons.b), @@ -377,7 +372,6 @@ class _BangumiInfoState extends State { () => ActionItem( icon: const Icon(FontAwesomeIcons.star), selectIcon: const Icon(FontAwesomeIcons.solidStar), - // onTap: () => videoIntroController.actionFavVideo(), onTap: () => showFavBottomSheet(), selectStatus: bangumiIntroController.hasFav.value, loadingStatus: widget.loadingStatus, @@ -385,6 +379,16 @@ class _BangumiInfoState extends State { ? widget.bangumiDetail!.stat!['favorite']!.toString() : '-'), ), + ActionItem( + icon: const Icon(FontAwesomeIcons.comment), + selectIcon: const Icon(FontAwesomeIcons.reply), + onTap: () => videoDetailCtr!.tabCtr!.animateTo(1), + selectStatus: false, + loadingStatus: widget.loadingStatus, + text: !widget.loadingStatus + ? widget.bangumiDetail!.stat!['reply']!.toString() + : '-', + ), ActionItem( icon: const Icon(FontAwesomeIcons.shareFromSquare), onTap: () => bangumiIntroController.actionShareVideo(), diff --git a/lib/pages/favDetail/widget/fav_video_card.dart b/lib/pages/favDetail/widget/fav_video_card.dart index 433cbb6b7..084a86811 100644 --- a/lib/pages/favDetail/widget/fav_video_card.dart +++ b/lib/pages/favDetail/widget/fav_video_card.dart @@ -3,6 +3,9 @@ import 'package:flutter/material.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/stat/danmu.dart'; import 'package:pilipala/common/widgets/stat/view.dart'; +import 'package:pilipala/http/search.dart'; +import 'package:pilipala/http/video.dart'; +import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; @@ -20,7 +23,7 @@ class FavVideoCardH extends StatelessWidget { @override Widget build(BuildContext context) { int id = videoItem.id; - String bvid = IdUtils.av2bv(id); + String bvid = videoItem.bvid ?? IdUtils.av2bv(id); String heroTag = Utils.makeHeroTag(id); return Dismissible( movementDuration: const Duration(milliseconds: 300), @@ -44,9 +47,33 @@ class FavVideoCardH extends StatelessWidget { }, child: InkWell( onTap: () async { - await Future.delayed(const Duration(milliseconds: 200)); - Get.toNamed('/video?bvid=$bvid&cid=${videoItem.cid}', - arguments: {'videoItem': videoItem, 'heroTag': heroTag}); + // int? seasonId; + String? epId; + if (videoItem.ogv != null && videoItem.ogv['type_name'] == '番剧') { + videoItem.cid = await SearchHttp.ab2c(bvid: bvid); + // seasonId = videoItem.ogv['season_id']; + epId = videoItem.epId; + } else if (videoItem.page == 0 || videoItem.page > 1) { + var result = await VideoHttp.videoIntro(bvid: bvid); + if (result['status']) { + epId = result['data'].epId; + } + } + + Map parameters = { + 'bvid': bvid, + 'cid': videoItem.cid.toString(), + 'epId': epId ?? '', + }; + // if (seasonId != null) { + // parameters['seasonId'] = seasonId.toString(); + // } + Get.toNamed('/video', parameters: parameters, arguments: { + 'videoItem': videoItem, + 'heroTag': heroTag, + 'videoType': + epId != null ? SearchType.media_bangumi : SearchType.video, + }); }, child: Column( children: [ diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index f359b5c50..aa3349e95 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -504,12 +504,14 @@ class _PLVideoPlayerState extends State final double dy = details.delta.dy; const double threshold = 7.0; // 滑动阈值 if (dy > _distance && dy > threshold) { - if (!_.isFullScreen.value) { + if (_.isFullScreen.value) { + // 下滑退出全屏 await triggerFullScreen(); } _distance = 0.0; } else if (dy < _distance && dy < -threshold) { - if (_.isFullScreen.value) { + if (!_.isFullScreen.value) { + // 上滑进入全屏 await triggerFullScreen(); } _distance = 0.0; diff --git a/lib/plugin/pl_player/widgets/bottom_control.dart b/lib/plugin/pl_player/widgets/bottom_control.dart index 0fd6c95d2..e73236fc4 100644 --- a/lib/plugin/pl_player/widgets/bottom_control.dart +++ b/lib/plugin/pl_player/widgets/bottom_control.dart @@ -144,7 +144,7 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget { () => ComBtn( icon: Icon( _.isFullScreen.value - ? FontAwesomeIcons.a + ? FontAwesomeIcons.compress : FontAwesomeIcons.expand, size: 15, color: Colors.white,