feat: 视频切换分p

This commit is contained in:
guozhigq
2023-08-05 23:24:48 +08:00
parent 1676f6f473
commit c83f70c08a
3 changed files with 280 additions and 107 deletions

View File

@ -8,6 +8,7 @@ import 'package:pilipala/http/video.dart';
import 'package:pilipala/models/user/fav_folder.dart'; import 'package:pilipala/models/user/fav_folder.dart';
import 'package:pilipala/models/video_detail_res.dart'; import 'package:pilipala/models/video_detail_res.dart';
import 'package:pilipala/pages/video/detail/controller.dart'; import 'package:pilipala/pages/video/detail/controller.dart';
import 'package:pilipala/pages/video/detail/reply/index.dart';
import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/id_utils.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
@ -391,11 +392,22 @@ class VideoIntroController extends GetxController {
} }
// 修改分P或番剧分集 // 修改分P或番剧分集
Future changeSeasonOrbangu(bvid, cid) async { Future changeSeasonOrbangu(bvid, cid, aid) async {
var _videoDetailCtr = // 重新获取视频资源
VideoDetailController videoDetailCtr =
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']); Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
_videoDetailCtr.bvid = bvid; videoDetailCtr.bvid = bvid;
_videoDetailCtr.cid = cid; videoDetailCtr.cid = cid;
_videoDetailCtr.queryVideoUrl(); videoDetailCtr.queryVideoUrl();
// 重新请求评论
try {
/// 未渲染回复组件时可能异常
VideoReplyController videoReplyCtr =
Get.find<VideoReplyController>(tag: Get.arguments['heroTag']);
videoReplyCtr.aid = aid;
videoReplyCtr.queryReplyList(type: 'init');
} catch (_) {}
this.bvid = bvid;
await queryVideoIntro();
} }
} }

View File

@ -63,7 +63,11 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
if (snapshot.data['status']) { if (snapshot.data['status']) {
// 请求成功 // 请求成功
// return _buildView(context, false, videoDetail); // return _buildView(context, false, videoDetail);
return VideoInfo(loadingStatus: false, videoDetail: videoDetail); return Obx(
() => VideoInfo(
loadingStatus: false,
videoDetail: videoIntroController.videoDetail.value),
);
} else { } else {
// 请求错误 // 请求错误
return HttpError( return HttpError(
@ -235,8 +239,13 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
// 合集 // 合集
if (!widget.loadingStatus && if (!widget.loadingStatus &&
widget.videoDetail!.ugcSeason != null) ...[ widget.videoDetail!.ugcSeason != null) ...[
seasonPanel(widget.videoDetail!.ugcSeason!, SeasonPanel(
widget.videoDetail!.pages!.first.cid, sheetHeight) ugcSeason: widget.videoDetail!.ugcSeason!,
cid: widget.videoDetail!.pages!.first.cid,
sheetHeight: sheetHeight,
changeFuc: (bvid, cid, aid) => videoIntroController
.changeSeasonOrbangu(bvid, cid, aid),
)
], ],
GestureDetector( GestureDetector(
onTap: () { onTap: () {

View File

@ -1,111 +1,263 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/models/video_detail_res.dart'; import 'package:pilipala/models/video_detail_res.dart';
import 'package:pilipala/utils/id_utils.dart';
Widget seasonPanel(UgcSeason ugcSeason, cid, sheetHeight) { class SeasonPanel extends StatefulWidget {
return Builder(builder: (context) { final UgcSeason ugcSeason;
List<EpisodeItem> episodes = ugcSeason.sections!.first.episodes!; final int? cid;
int currentIndex = episodes.indexWhere((e) => e.cid == cid); final double? sheetHeight;
return Container( final Function? changeFuc;
margin: const EdgeInsets.only(
top: 8, const SeasonPanel({
left: 2, super.key,
right: 2, required this.ugcSeason,
bottom: 2, this.cid,
), this.sheetHeight,
child: Material( this.changeFuc,
color: Theme.of(context).colorScheme.onInverseSurface, });
borderRadius: BorderRadius.circular(6),
clipBehavior: Clip.hardEdge, @override
child: InkWell( State<SeasonPanel> createState() => _SeasonPanelState();
onTap: () => showBottomSheet( }
context: context,
builder: (_) => Container( class _SeasonPanelState extends State<SeasonPanel> {
height: sheetHeight, late List<EpisodeItem> episodes;
color: Theme.of(context).colorScheme.background, late int currentIndex;
child: Column(
children: [ @override
Container( void initState() {
height: 45, super.initState();
padding: const EdgeInsets.only(left: 14, right: 14), episodes = widget.ugcSeason.sections!.first.episodes!;
child: Row( currentIndex = episodes.indexWhere((e) => e.cid == widget.cid);
mainAxisAlignment: MainAxisAlignment.spaceBetween, }
children: [
Text( void changeFucCall(item, i) async {
'合集(${episodes.length}', await widget.changeFuc!(
style: Theme.of(context).textTheme.titleMedium, IdUtils.av2bv(item.aid),
), item.cid,
IconButton( item.aid,
icon: const Icon(Icons.close), );
onPressed: () => Navigator.pop(context), Get.back();
), }
],
), @override
), Widget build(BuildContext context) {
Divider( return Builder(builder: (context) {
height: 1, return Container(
color: Theme.of(context).dividerColor.withOpacity(0.1), margin: const EdgeInsets.only(
), top: 8,
Expanded( left: 2,
child: Material( right: 2,
child: ListView.builder( bottom: 2,
itemCount: episodes.length, ),
itemBuilder: (context, index) { child: Material(
return InkWell( color: Theme.of(context).colorScheme.onInverseSurface,
onTap: () {}, borderRadius: BorderRadius.circular(6),
child: Padding( clipBehavior: Clip.hardEdge,
padding: const EdgeInsets.only( child: InkWell(
top: 10, bottom: 10, left: 15, right: 15), onTap: () => showBottomSheet(
child: Text( context: context,
episodes[index].title!, builder: (_) => Container(
style: TextStyle( height: widget.sheetHeight,
color: index == currentIndex color: Theme.of(context).colorScheme.background,
? Theme.of(context).colorScheme.primary child: Column(
: Theme.of(context) children: [
.colorScheme Container(
.onSurface), height: 45,
), padding: const EdgeInsets.only(left: 14, right: 14),
), child: Row(
); mainAxisAlignment: MainAxisAlignment.spaceBetween,
}, children: [
Text(
'合集(${episodes.length}',
style: Theme.of(context).textTheme.titleMedium,
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () => Navigator.pop(context),
),
],
), ),
), ),
Divider(
height: 1,
color: Theme.of(context).dividerColor.withOpacity(0.1),
),
Expanded(
child: Material(
child: ListView.builder(
itemCount: episodes.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () =>
changeFucCall(episodes[index], index),
child: Padding(
padding: const EdgeInsets.only(
top: 10, bottom: 10, left: 15, right: 15),
child: Text(
episodes[index].title!,
style: TextStyle(
color: index == currentIndex
? Theme.of(context)
.colorScheme
.primary
: Theme.of(context)
.colorScheme
.onSurface),
),
),
);
},
),
),
),
],
),
),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
child: Row(
children: [
Expanded(
child: Text(
'合集:${widget.ugcSeason.title!}',
style: Theme.of(context).textTheme.labelMedium,
overflow: TextOverflow.ellipsis,
),
), ),
const SizedBox(width: 15),
Image.asset(
'assets/images/live.gif',
color: Theme.of(context).colorScheme.primary,
height: 12,
),
const SizedBox(width: 10),
Text(
'${currentIndex + 1}/${widget.ugcSeason.epCount}',
style: Theme.of(context).textTheme.labelMedium,
),
const SizedBox(width: 6),
const Icon(
Icons.arrow_forward_ios_outlined,
size: 13,
)
], ],
), ),
), ),
), ),
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
child: Row(
children: [
Expanded(
child: Text(
'合集:${ugcSeason.title!}',
style: Theme.of(context).textTheme.labelMedium,
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 15),
Image.asset(
'assets/images/live.gif',
color: Theme.of(context).colorScheme.primary,
height: 12,
),
const SizedBox(width: 10),
Text(
'${currentIndex + 1}/${ugcSeason.epCount}',
style: Theme.of(context).textTheme.labelMedium,
),
const SizedBox(width: 6),
const Icon(
Icons.arrow_forward_ios_outlined,
size: 13,
)
],
),
),
), ),
), );
); });
}); }
} }
// Widget seasonPanel(UgcSeason ugcSeason, cid, sheetHeight) {
// return Builder(builder: (context) {
// List<EpisodeItem> episodes = ugcSeason.sections!.first.episodes!;
// int currentIndex = episodes.indexWhere((e) => e.cid == cid);
// return Container(
// margin: const EdgeInsets.only(
// top: 8,
// left: 2,
// right: 2,
// bottom: 2,
// ),
// child: Material(
// color: Theme.of(context).colorScheme.onInverseSurface,
// borderRadius: BorderRadius.circular(6),
// clipBehavior: Clip.hardEdge,
// child: InkWell(
// onTap: () => showBottomSheet(
// context: context,
// builder: (_) => Container(
// height: sheetHeight,
// color: Theme.of(context).colorScheme.background,
// child: Column(
// children: [
// Container(
// height: 45,
// padding: const EdgeInsets.only(left: 14, right: 14),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text(
// '合集(${episodes.length}',
// style: Theme.of(context).textTheme.titleMedium,
// ),
// IconButton(
// icon: const Icon(Icons.close),
// onPressed: () => Navigator.pop(context),
// ),
// ],
// ),
// ),
// Divider(
// height: 1,
// color: Theme.of(context).dividerColor.withOpacity(0.1),
// ),
// Expanded(
// child: Material(
// child: ListView.builder(
// itemCount: episodes.length,
// itemBuilder: (context, index) {
// return InkWell(
// onTap: () {},
// child: Padding(
// padding: const EdgeInsets.only(
// top: 10, bottom: 10, left: 15, right: 15),
// child: Text(
// episodes[index].title!,
// style: TextStyle(
// color: index == currentIndex
// ? Theme.of(context).colorScheme.primary
// : Theme.of(context)
// .colorScheme
// .onSurface),
// ),
// ),
// );
// },
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// child: Padding(
// padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
// child: Row(
// children: [
// Expanded(
// child: Text(
// '合集:${ugcSeason.title!}',
// style: Theme.of(context).textTheme.labelMedium,
// overflow: TextOverflow.ellipsis,
// ),
// ),
// const SizedBox(width: 15),
// Image.asset(
// 'assets/images/live.gif',
// color: Theme.of(context).colorScheme.primary,
// height: 12,
// ),
// const SizedBox(width: 10),
// Text(
// '${currentIndex + 1}/${ugcSeason.epCount}',
// style: Theme.of(context).textTheme.labelMedium,
// ),
// const SizedBox(width: 6),
// const Icon(
// Icons.arrow_forward_ios_outlined,
// size: 13,
// )
// ],
// ),
// ),
// ),
// ),
// );
// });
// }