opt: prev/next play

Closes #506

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-03-23 21:47:10 +08:00
parent 5a758ebb3a
commit 1f8955d0b3
5 changed files with 52 additions and 35 deletions

View File

@@ -740,13 +740,18 @@ class VideoIntroController extends GetxController
} }
/// 播放上一个 /// 播放上一个
bool prevPlay() { bool prevPlay([bool skipPages = false]) {
final List episodes = []; final List episodes = [];
bool isPages = false; bool isPages = false;
if ((videoDetail.value.pages?.length ?? 0) > 1) {
final videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
if (skipPages.not && (videoDetail.value.pages?.length ?? 0) > 1) {
isPages = true; isPages = true;
final List<Part> pages = videoDetail.value.pages!; final List<Part> pages = videoDetail.value.pages!;
episodes.addAll(pages); episodes.addAll(pages);
} else if (videoDetailCtr.isPlayAll) {
episodes.addAll(videoDetailCtr.mediaList);
} else if (videoDetail.value.ugcSeason != null) { } else if (videoDetail.value.ugcSeason != null) {
final UgcSeason ugcSeason = videoDetail.value.ugcSeason!; final UgcSeason ugcSeason = videoDetail.value.ugcSeason!;
final List<SectionItem> sections = ugcSeason.sections!; final List<SectionItem> sections = ugcSeason.sections!;
@@ -755,14 +760,19 @@ class VideoIntroController extends GetxController
episodes.addAll(episodesList); episodes.addAll(episodesList);
} }
} }
final int currentIndex =
episodes.indexWhere((e) => e.cid == lastPlayCid.value); final int currentIndex = episodes.indexWhere((e) =>
e.cid ==
(skipPages ? videoDetail.value.pages!.first.cid : lastPlayCid.value));
int prevIndex = currentIndex - 1; int prevIndex = currentIndex - 1;
final videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
final PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat; final PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
// 列表循环 // 列表循环
if (prevIndex < 0) { if (prevIndex < 0) {
if (isPages &&
(videoDetailCtr.isPlayAll || videoDetail.value.ugcSeason != null)) {
return prevPlay(true);
}
if (playRepeat == PlayRepeat.listCycle) { if (playRepeat == PlayRepeat.listCycle) {
prevIndex = episodes.length - 1; prevIndex = episodes.length - 1;
} else { } else {
@@ -777,14 +787,14 @@ class VideoIntroController extends GetxController
} }
/// 列表循环或者顺序播放时,自动播放下一个 /// 列表循环或者顺序播放时,自动播放下一个
bool nextPlay() { bool nextPlay([bool skipPages = false]) {
try { try {
final List episodes = []; final List episodes = [];
bool isPages = false; bool isPages = false;
final videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag); final videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
// part -> playall -> season // part -> playall -> season
if ((videoDetail.value.pages?.length ?? 0) > 1) { if (skipPages.not && (videoDetail.value.pages?.length ?? 0) > 1) {
isPages = true; isPages = true;
final List<Part> pages = videoDetail.value.pages!; final List<Part> pages = videoDetail.value.pages!;
episodes.addAll(pages); episodes.addAll(pages);
@@ -810,16 +820,26 @@ class VideoIntroController extends GetxController
return false; return false;
} }
final int currentIndex = final int currentIndex = episodes.indexWhere((e) =>
episodes.indexWhere((e) => e.cid == videoDetailCtr.cid.value); e.cid ==
(skipPages
? videoDetail.value.pages!.first.cid
: videoDetailCtr.cid.value));
int nextIndex = currentIndex + 1; int nextIndex = currentIndex + 1;
if (videoDetailCtr.isPlayAll && currentIndex == episodes.length - 2) { if (isPages.not &&
videoDetailCtr.isPlayAll &&
currentIndex == episodes.length - 2) {
videoDetailCtr.getMediaList(); videoDetailCtr.getMediaList();
} }
// 列表循环 // 列表循环
if (nextIndex >= episodes.length) { if (nextIndex >= episodes.length) {
if (isPages &&
(videoDetailCtr.isPlayAll || videoDetail.value.ugcSeason != null)) {
return nextPlay(true);
}
if (playRepeat == PlayRepeat.listCycle) { if (playRepeat == PlayRepeat.listCycle) {
nextIndex = 0; nextIndex = 0;
} else if (playRepeat == PlayRepeat.autoPlayRelated && } else if (playRepeat == PlayRepeat.autoPlayRelated &&

View File

@@ -838,13 +838,14 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
(context.orientation != Orientation.landscape || (context.orientation != Orientation.landscape ||
(context.orientation == Orientation.landscape && (context.orientation == Orientation.landscape &&
videoDetailCtr.horizontalSeasonPanel.not))) videoDetailCtr.horizontalSeasonPanel.not)))
SeasonPanel( Obx(
heroTag: widget.heroTag, () => SeasonPanel(
ugcSeason: videoDetail.ugcSeason!, key: ValueKey(videoIntroController.videoDetail.value),
changeFuc: videoIntroController.changeSeasonOrbangu, heroTag: widget.heroTag,
showEpisodes: widget.showEpisodes, changeFuc: videoIntroController.changeSeasonOrbangu,
pages: videoDetail.pages, showEpisodes: widget.showEpisodes,
videoIntroController: videoIntroController, videoIntroController: videoIntroController,
),
), ),
if (!widget.loadingStatus && if (!widget.loadingStatus &&
videoDetail.pages != null && videoDetail.pages != null &&
@@ -852,12 +853,15 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
(context.orientation != Orientation.landscape || (context.orientation != Orientation.landscape ||
(context.orientation == Orientation.landscape && (context.orientation == Orientation.landscape &&
videoDetailCtr.horizontalSeasonPanel.not))) ...[ videoDetailCtr.horizontalSeasonPanel.not))) ...[
PagesPanel( Obx(
heroTag: widget.heroTag, () => PagesPanel(
videoIntroController: videoIntroController, key: ValueKey(videoIntroController.videoDetail.value),
bvid: videoIntroController.bvid, heroTag: widget.heroTag,
changeFuc: videoIntroController.changeSeasonOrbangu, videoIntroController: videoIntroController,
showEpisodes: widget.showEpisodes, bvid: videoIntroController.bvid,
changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: widget.showEpisodes,
),
), ),
], ],
], ],

View File

@@ -10,19 +10,15 @@ import 'package:PiliPlus/pages/video/detail/index.dart';
class SeasonPanel extends StatefulWidget { class SeasonPanel extends StatefulWidget {
const SeasonPanel({ const SeasonPanel({
super.key, super.key,
required this.ugcSeason,
required this.changeFuc, required this.changeFuc,
required this.heroTag, required this.heroTag,
required this.showEpisodes, required this.showEpisodes,
required this.pages,
this.onTap, this.onTap,
required this.videoIntroController, required this.videoIntroController,
}); });
final UgcSeason ugcSeason;
final Function changeFuc; final Function changeFuc;
final String heroTag; final String heroTag;
final Function showEpisodes; final Function showEpisodes;
final List<Part>? pages;
final bool? onTap; final bool? onTap;
final VideoIntroController videoIntroController; final VideoIntroController videoIntroController;
@@ -72,7 +68,8 @@ class _SeasonPanelState extends State<SeasonPanel> {
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid); (EpisodeItem e) => e.cid == _videoDetailController.seasonCid);
_listener = _videoDetailController.cid.listen((int cid) { _listener = _videoDetailController.cid.listen((int cid) {
if (_videoDetailController.seasonCid != cid) { if (_videoDetailController.seasonCid != cid) {
bool isPart = widget.pages?.indexWhere((item) => item.cid == cid) != -1; bool isPart =
videoDetail.pages?.indexWhere((item) => item.cid == cid) != -1;
if (isPart.not) { if (isPart.not) {
_videoDetailController.seasonCid = cid; _videoDetailController.seasonCid = cid;
} }
@@ -121,7 +118,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
? null ? null
: () => widget.showEpisodes( : () => widget.showEpisodes(
_videoDetailController.seasonIndex.value, _videoDetailController.seasonIndex.value,
widget.ugcSeason, videoDetail.ugcSeason,
null, null,
_videoDetailController.bvid, _videoDetailController.bvid,
null, null,
@@ -133,7 +130,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: Text( child: Text(
'合集:${widget.ugcSeason.title!}', '合集:${videoDetail.ugcSeason!.title!}',
style: Theme.of(context).textTheme.labelMedium, style: Theme.of(context).textTheme.labelMedium,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@@ -170,7 +167,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
} }
void _findEpisode() { void _findEpisode() {
final List<SectionItem> sections = widget.ugcSeason.sections!; final List<SectionItem> sections = videoDetail.ugcSeason!.sections!;
for (int i = 0; i < sections.length; i++) { for (int i = 0; i < sections.length; i++) {
final List<EpisodeItem> episodesList = sections[i].episodes!; final List<EpisodeItem> episodesList = sections[i].episodes!;
for (int j = 0; j < episodesList.length; j++) { for (int j = 0; j < episodesList.length; j++) {

View File

@@ -1657,10 +1657,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
child: SeasonPanel( child: SeasonPanel(
heroTag: heroTag, heroTag: heroTag,
onTap: false, onTap: false,
ugcSeason: videoIntroController.videoDetail.value.ugcSeason!,
changeFuc: videoIntroController.changeSeasonOrbangu, changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: showEpisodes, showEpisodes: showEpisodes,
pages: videoIntroController.videoDetail.value.pages,
videoIntroController: videoIntroController, videoIntroController: videoIntroController,
), ),
), ),

View File

@@ -2060,10 +2060,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
child: SeasonPanel( child: SeasonPanel(
heroTag: heroTag, heroTag: heroTag,
onTap: false, onTap: false,
ugcSeason: videoIntroController.videoDetail.value.ugcSeason!,
changeFuc: videoIntroController.changeSeasonOrbangu, changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: showEpisodes, showEpisodes: showEpisodes,
pages: videoIntroController.videoDetail.value.pages,
videoIntroController: videoIntroController, videoIntroController: videoIntroController,
), ),
), ),