Merge branch 'main' into design
This commit is contained in:
@ -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']);
|
||||
|
@ -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 {
|
||||
|
@ -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<String, dynamic> 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<Match> matches = regex.allMatches(url);
|
||||
List<String> numbers = [];
|
||||
for (Match match in matches) {
|
||||
numbers.add(match.group(0)!);
|
||||
}
|
||||
return numbers[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Match> matches = regex.allMatches(json['redirect_url']);
|
||||
List<String> 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<Match> matches = regex.allMatches(url);
|
||||
List<String> numbers = [];
|
||||
for (Match match in matches) {
|
||||
numbers.add(match.group(0)!);
|
||||
}
|
||||
return numbers[0];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"bvid": bvid,
|
||||
"aid": aid,
|
||||
|
@ -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<VideoReplyController>(tag: Get.arguments['heroTag']);
|
||||
videoReplyCtr.aid = aid;
|
||||
videoReplyCtr.queryReplyList(type: 'init');
|
||||
try {
|
||||
/// 未渲染回复组件时可能异常
|
||||
VideoReplyController videoReplyCtr =
|
||||
Get.find<VideoReplyController>(tag: Get.arguments['heroTag']);
|
||||
videoReplyCtr.aid = aid;
|
||||
videoReplyCtr.queryReplyList(type: 'init');
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
@ -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<BangumiInfo> {
|
||||
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<BangumiInfo> {
|
||||
? 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<BangumiInfo> {
|
||||
() => 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<BangumiInfo> {
|
||||
? 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(),
|
||||
|
@ -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<String, String> 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: [
|
||||
|
@ -504,12 +504,14 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
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;
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user