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 = [];
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;
final List<Part> pages = videoDetail.value.pages!;
episodes.addAll(pages);
} else if (videoDetailCtr.isPlayAll) {
episodes.addAll(videoDetailCtr.mediaList);
} else if (videoDetail.value.ugcSeason != null) {
final UgcSeason ugcSeason = videoDetail.value.ugcSeason!;
final List<SectionItem> sections = ugcSeason.sections!;
@@ -755,14 +760,19 @@ class VideoIntroController extends GetxController
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;
final videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
final PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
// 列表循环
if (prevIndex < 0) {
if (isPages &&
(videoDetailCtr.isPlayAll || videoDetail.value.ugcSeason != null)) {
return prevPlay(true);
}
if (playRepeat == PlayRepeat.listCycle) {
prevIndex = episodes.length - 1;
} else {
@@ -777,14 +787,14 @@ class VideoIntroController extends GetxController
}
/// 列表循环或者顺序播放时,自动播放下一个
bool nextPlay() {
bool nextPlay([bool skipPages = false]) {
try {
final List episodes = [];
bool isPages = false;
final videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
// part -> playall -> season
if ((videoDetail.value.pages?.length ?? 0) > 1) {
if (skipPages.not && (videoDetail.value.pages?.length ?? 0) > 1) {
isPages = true;
final List<Part> pages = videoDetail.value.pages!;
episodes.addAll(pages);
@@ -810,16 +820,26 @@ class VideoIntroController extends GetxController
return false;
}
final int currentIndex =
episodes.indexWhere((e) => e.cid == videoDetailCtr.cid.value);
final int currentIndex = episodes.indexWhere((e) =>
e.cid ==
(skipPages
? videoDetail.value.pages!.first.cid
: videoDetailCtr.cid.value));
int nextIndex = currentIndex + 1;
if (videoDetailCtr.isPlayAll && currentIndex == episodes.length - 2) {
if (isPages.not &&
videoDetailCtr.isPlayAll &&
currentIndex == episodes.length - 2) {
videoDetailCtr.getMediaList();
}
// 列表循环
if (nextIndex >= episodes.length) {
if (isPages &&
(videoDetailCtr.isPlayAll || videoDetail.value.ugcSeason != null)) {
return nextPlay(true);
}
if (playRepeat == PlayRepeat.listCycle) {
nextIndex = 0;
} 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 &&
videoDetailCtr.horizontalSeasonPanel.not)))
SeasonPanel(
heroTag: widget.heroTag,
ugcSeason: videoDetail.ugcSeason!,
changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: widget.showEpisodes,
pages: videoDetail.pages,
videoIntroController: videoIntroController,
Obx(
() => SeasonPanel(
key: ValueKey(videoIntroController.videoDetail.value),
heroTag: widget.heroTag,
changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: widget.showEpisodes,
videoIntroController: videoIntroController,
),
),
if (!widget.loadingStatus &&
videoDetail.pages != null &&
@@ -852,12 +853,15 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
(context.orientation != Orientation.landscape ||
(context.orientation == Orientation.landscape &&
videoDetailCtr.horizontalSeasonPanel.not))) ...[
PagesPanel(
heroTag: widget.heroTag,
videoIntroController: videoIntroController,
bvid: videoIntroController.bvid,
changeFuc: videoIntroController.changeSeasonOrbangu,
showEpisodes: widget.showEpisodes,
Obx(
() => PagesPanel(
key: ValueKey(videoIntroController.videoDetail.value),
heroTag: widget.heroTag,
videoIntroController: videoIntroController,
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 {
const SeasonPanel({
super.key,
required this.ugcSeason,
required this.changeFuc,
required this.heroTag,
required this.showEpisodes,
required this.pages,
this.onTap,
required this.videoIntroController,
});
final UgcSeason ugcSeason;
final Function changeFuc;
final String heroTag;
final Function showEpisodes;
final List<Part>? pages;
final bool? onTap;
final VideoIntroController videoIntroController;
@@ -72,7 +68,8 @@ class _SeasonPanelState extends State<SeasonPanel> {
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid);
_listener = _videoDetailController.cid.listen((int 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) {
_videoDetailController.seasonCid = cid;
}
@@ -121,7 +118,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
? null
: () => widget.showEpisodes(
_videoDetailController.seasonIndex.value,
widget.ugcSeason,
videoDetail.ugcSeason,
null,
_videoDetailController.bvid,
null,
@@ -133,7 +130,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
children: <Widget>[
Expanded(
child: Text(
'合集:${widget.ugcSeason.title!}',
'合集:${videoDetail.ugcSeason!.title!}',
style: Theme.of(context).textTheme.labelMedium,
overflow: TextOverflow.ellipsis,
),
@@ -170,7 +167,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
}
void _findEpisode() {
final List<SectionItem> sections = widget.ugcSeason.sections!;
final List<SectionItem> sections = videoDetail.ugcSeason!.sections!;
for (int i = 0; i < sections.length; i++) {
final List<EpisodeItem> episodesList = sections[i].episodes!;
for (int j = 0; j < episodesList.length; j++) {

View File

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

View File

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