fix: reverse play

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2024-12-31 17:02:12 +08:00
parent 273e5649c3
commit df41729d74
12 changed files with 142 additions and 125 deletions

View File

@@ -133,10 +133,12 @@ class VideoIntroController extends GetxController
if (videoDetail.value.ugcSeason?.id == result['data']?.ugcSeason?.id) {
// keep reversed season
result['data']?.ugcSeason = videoDetail.value.ugcSeason;
result['data']?.isSeasonReversed = videoDetail.value.isSeasonReversed;
}
if (videoDetail.value.cid == result['data']?.cid) {
// keep reversed pages
result['data']?.pages = videoDetail.value.pages;
result['data']?.isPageReversed = videoDetail.value.isPageReversed;
}
videoDetail.value = result['data'];
videoItem!['staff'] = result['data'].staff;

View File

@@ -82,6 +82,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
onShowMemberPage: widget.onShowMemberPage,
)
: VideoInfo(
key: ValueKey(widget.heroTag),
loadingStatus: false,
videoIntroController: videoIntroController,
heroTag: widget.heroTag,
@@ -109,12 +110,12 @@ class VideoInfo extends StatefulWidget {
const VideoInfo({
super.key,
this.loadingStatus = false,
required this.videoIntroController,
required this.heroTag,
required this.showAiBottomSheet,
required this.showIntroDetail,
required this.showEpisodes,
required this.onShowMemberPage,
required this.videoIntroController,
});
@override
@@ -642,10 +643,9 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
),
),
),
const SizedBox(height: 8),
Obx(
() => videoIntroController.queryVideoIntroData.value["status"]
? const SizedBox()
? const SizedBox.shrink()
: Center(
child: TextButton.icon(
icon: const Icon(Icons.refresh),
@@ -676,19 +676,13 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
(context.orientation != Orientation.landscape ||
(context.orientation == Orientation.landscape &&
videoDetailCtr.horizontalSeasonPanel.not)))
Obx(
() => SeasonPanel(
heroTag: widget.heroTag,
ugcSeason: videoDetail.ugcSeason!,
cid: videoIntroController.lastPlayCid.value != 0
? (videoDetail.pages?.isNotEmpty == true
? videoDetail.pages!.first.cid
: videoIntroController.lastPlayCid.value)
: videoDetail.pages!.first.cid,
changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: widget.showEpisodes,
pages: videoDetail.pages,
),
SeasonPanel(
heroTag: widget.heroTag,
ugcSeason: videoDetail.ugcSeason!,
changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: widget.showEpisodes,
pages: videoDetail.pages,
videoIntroController: videoIntroController,
),
if (!widget.loadingStatus &&
videoDetail.pages != null &&
@@ -696,15 +690,12 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
(context.orientation != Orientation.landscape ||
(context.orientation == Orientation.landscape &&
videoDetailCtr.horizontalSeasonPanel.not))) ...[
Obx(
() => PagesPanel(
heroTag: widget.heroTag,
videoDetailData: videoIntroController.videoDetail.value,
cid: videoIntroController.lastPlayCid.value,
bvid: videoIntroController.bvid,
changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: widget.showEpisodes,
),
PagesPanel(
heroTag: widget.heroTag,
videoIntroController: videoIntroController,
bvid: videoIntroController.bvid,
changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: widget.showEpisodes,
),
],
],

View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:math';
import 'package:PiliPalaX/pages/video/detail/introduction/controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:PiliPalaX/models/video_detail_res.dart';
@@ -11,19 +12,17 @@ import '../../../../../utils/id_utils.dart';
class PagesPanel extends StatefulWidget {
const PagesPanel({
super.key,
required this.cid,
required this.bvid,
required this.changeFuc,
required this.heroTag,
required this.showEpisodes,
required this.videoDetailData,
required this.videoIntroController,
});
final int cid;
final String bvid;
final Function changeFuc;
final String heroTag;
final Function showEpisodes;
final VideoDetailData videoDetailData;
final VideoIntroController videoIntroController;
@override
State<PagesPanel> createState() => _PagesPanelState();
@@ -36,19 +35,20 @@ class _PagesPanelState extends State<PagesPanel> {
final ScrollController _scrollController = ScrollController();
StreamSubscription? _listener;
List<Part> get pages => widget.videoIntroController.videoDetail.value.pages!;
@override
void initState() {
super.initState();
cid = widget.cid;
cid = widget.videoIntroController.lastPlayCid.value;
_videoDetailController =
Get.find<VideoDetailController>(tag: widget.heroTag);
pageIndex =
widget.videoDetailData.pages!.indexWhere((Part e) => e.cid == cid);
pageIndex = pages.indexWhere((Part e) => e.cid == cid);
_listener = _videoDetailController.cid.listen((int cid) {
this.cid = cid;
pageIndex = max(0,
widget.videoDetailData.pages!.indexWhere((Part e) => e.cid == cid));
pageIndex = max(0, pages.indexWhere((Part e) => e.cid == cid));
if (!mounted) return;
setState(() {});
const double itemWidth = 150; // 每个列表项的宽度
final double targetOffset = min((pageIndex * itemWidth) - (itemWidth / 2),
_scrollController.position.maxScrollExtent);
@@ -73,14 +73,14 @@ class _PagesPanelState extends State<PagesPanel> {
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 10, bottom: 2),
padding: const EdgeInsets.only(top: 8, bottom: 2),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('视频选集 '),
Expanded(
child: Text(
' 正在播放:${widget.videoDetailData.pages![pageIndex].pagePart}',
' 正在播放:${pages[pageIndex].pagePart}',
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12,
@@ -98,13 +98,13 @@ class _PagesPanelState extends State<PagesPanel> {
onPressed: () => widget.showEpisodes(
null,
null,
widget.videoDetailData.pages!,
pages,
widget.bvid,
IdUtils.bv2av(widget.bvid),
cid,
),
child: Text(
'${widget.videoDetailData.pages!.length}',
'${pages.length}',
style: const TextStyle(fontSize: 13),
),
),
@@ -112,20 +112,19 @@ class _PagesPanelState extends State<PagesPanel> {
],
),
),
Container(
SizedBox(
height: 35,
margin: const EdgeInsets.only(bottom: 8),
child: ListView.builder(
controller: _scrollController,
scrollDirection: Axis.horizontal,
itemCount: widget.videoDetailData.pages!.length,
itemCount: pages.length,
itemExtent: 150,
itemBuilder: (BuildContext context, int i) {
bool isCurrentIndex = pageIndex == i;
return Container(
width: 150,
margin: EdgeInsets.only(
right: i != widget.videoDetailData.pages!.length - 1 ? 10 : 0,
right: i != pages.length - 1 ? 10 : 0,
),
child: Material(
color: Theme.of(context).colorScheme.onInverseSurface,
@@ -136,7 +135,7 @@ class _PagesPanelState extends State<PagesPanel> {
widget.changeFuc(
null,
widget.bvid,
widget.videoDetailData.pages![i].cid,
pages[i].cid,
IdUtils.bv2av(widget.bvid),
null,
)
@@ -157,7 +156,7 @@ class _PagesPanelState extends State<PagesPanel> {
],
Expanded(
child: Text(
widget.videoDetailData.pages![i].pagePart!,
pages[i].pagePart!,
maxLines: 1,
style: TextStyle(
fontSize: 13,

View File

@@ -1,5 +1,7 @@
import 'dart:async';
import 'package:PiliPalaX/pages/video/detail/introduction/controller.dart';
import 'package:PiliPalaX/utils/extension.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:PiliPalaX/models/video_detail_res.dart';
@@ -9,20 +11,20 @@ class SeasonPanel extends StatefulWidget {
const SeasonPanel({
super.key,
required this.ugcSeason,
this.cid,
required this.changeFuc,
required this.heroTag,
required this.showEpisodes,
required this.pages,
this.onTap,
required this.videoIntroController,
});
final UgcSeason ugcSeason;
final int? cid;
final Function changeFuc;
final String heroTag;
final Function showEpisodes;
final List<Part>? pages;
final bool? onTap;
final VideoIntroController videoIntroController;
@override
State<SeasonPanel> createState() => _SeasonPanelState();
@@ -34,12 +36,26 @@ class _SeasonPanelState extends State<SeasonPanel> {
StreamSubscription? _listener;
List<EpisodeItem> episodes = <EpisodeItem>[];
VideoIntroController get videoIntroController => widget.videoIntroController;
VideoDetailData get videoDetail =>
widget.videoIntroController.videoDetail.value;
@override
void initState() {
super.initState();
_videoDetailController =
Get.find<VideoDetailController>(tag: widget.heroTag)
..seasonCid = widget.cid!;
Get.find<VideoDetailController>(tag: widget.heroTag);
_videoDetailController.seasonCid =
videoIntroController.lastPlayCid.value != 0
? (videoDetail.pages?.isNotEmpty == true
? videoDetail.isPageReversed
? videoDetail.pages!.last.cid
: videoDetail.pages!.first.cid
: videoIntroController.lastPlayCid.value)
: videoDetail.isPageReversed
? videoDetail.pages!.last.cid
: videoDetail.pages!.first.cid;
/// 根据 cid 找到对应集,找到对应 episodes
/// 有多个episodes时只显示其中一个
@@ -55,16 +71,12 @@ class _SeasonPanelState extends State<SeasonPanel> {
currentIndex.value = episodes.indexWhere(
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid);
_listener = _videoDetailController.cid.listen((int cid) {
if (_videoDetailController.seasonCid == cid) {
//refresh
_findEpisode();
currentIndex.value = episodes.indexWhere(
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid);
return;
if (_videoDetailController.seasonCid != cid) {
bool isPart = widget.pages?.indexWhere((item) => item.cid == cid) != -1;
if (isPart.not) {
_videoDetailController.seasonCid = cid;
}
}
bool isPart = widget.pages?.indexWhere((item) => item.cid == cid) != -1;
if (isPart) return;
_videoDetailController.seasonCid = cid;
_findEpisode();
currentIndex.value = episodes.indexWhere(
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid);
@@ -99,7 +111,6 @@ class _SeasonPanelState extends State<SeasonPanel> {
top: 8,
left: 2,
right: 2,
bottom: 2,
),
child: Material(
color: Theme.of(context).colorScheme.onInverseSurface,