mod: 历史记录跳转番剧播放

This commit is contained in:
guozhigq
2023-08-04 18:29:38 +08:00
parent c961dc6cf5
commit 01829ad965
5 changed files with 330 additions and 250 deletions

View File

@ -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<String, dynamic> 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<Match> matches = regex.allMatches(json['redirect_url']);
List<String> numbers = [];
for (Match match in matches) {
numbers.add(match.group(0)!);
}
epId = numbers[0];
}
}
Map<String, dynamic> toJson() => {

View File

@ -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'];
}

View File

@ -86,7 +86,7 @@ class BangumiInfo extends StatefulWidget {
}
class _BangumiInfoState extends State<BangumiInfo> {
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<BangumiInfo> {
@override
void initState() {
super.initState();
bangumiItem = bangumiIntroController.bangumiItem!;
bangumiItem = bangumiIntroController.bangumiItem;
videoDetailCtr =
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
sheetHeight = localCache.get('sheetHeight');
@ -139,176 +139,189 @@ class _BangumiInfoState extends State<BangumiInfo> {
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(),
),
),
),
);
}

View File

@ -143,88 +143,93 @@ class _BangumiPanelState extends State<BangumiPanel> {
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,
)
],
),
),
),
),
),
),
]
],
]
],
),
),
)
],

View File

@ -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,