opt change episode

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-08-05 19:56:22 +08:00
parent 170b2aa6d9
commit 80a4c8c24d
10 changed files with 79 additions and 81 deletions

View File

@@ -5,7 +5,6 @@ import 'package:PiliPlus/models_new/media_list/ogv_info.dart';
import 'package:PiliPlus/models_new/media_list/page.dart';
import 'package:PiliPlus/models_new/media_list/rights.dart';
import 'package:PiliPlus/models_new/video/video_detail/episode.dart';
import 'package:PiliPlus/utils/extension.dart';
class MediaListItemModel extends BaseEpisodeItem {
@override
@@ -35,6 +34,8 @@ class MediaListItemModel extends BaseEpisodeItem {
bool? forbidFav;
int? moreType;
int? businessOid;
@override
int? get cid => pages?.firstOrNull?.id;
MediaListItemModel({
super.aid,
@@ -105,6 +106,5 @@ class MediaListItemModel extends BaseEpisodeItem {
forbidFav = json['forbid_fav'] as bool?;
moreType = json['more_type'] as int?;
businessOid = json['business_oid'] as int?;
cid = pages.getOrNull((page ?? 1) - 1)?.id;
}
}

View File

@@ -24,7 +24,7 @@ mixin BaseFavController
bool get isOwner;
int get mediaId;
ValueChanged<int>? updateLength;
ValueChanged<int>? updateCount;
void onViewFav(FavDetailItemModel item, int? index);
@@ -37,7 +37,7 @@ mixin BaseFavController
loadingState
..value.data!.removeAt(index)
..refresh();
updateLength?.call(1);
updateCount?.call(1);
SmartDialog.showToast('取消收藏');
} else {
SmartDialog.showToast(result['msg']);
@@ -59,7 +59,7 @@ mixin BaseFavController
delIds: mediaId.toString(),
);
if (result['status']) {
updateLength?.call(removeList.length);
updateCount?.call(removeList.length);
afterDelete(removeList);
SmartDialog.showToast('取消收藏');
} else {
@@ -124,7 +124,7 @@ class FavDetailController
}
@override
ValueChanged<int>? get updateLength =>
ValueChanged<int>? get updateCount =>
(count) => folderInfo
..value.mediaCount -= count
..refresh();
@@ -147,9 +147,6 @@ class FavDetailController
if (element.ugc?.firstCid == null) {
continue;
} else {
if (element.bvid != list.first.bvid) {
SmartDialog.showToast('已跳过不支持播放的视频');
}
onViewFav(element, null);
break;
}

View File

@@ -76,6 +76,7 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
}
var videoItem = response[index];
return VideoCardHLater(
index: index,
videoItem: videoItem,
ctr: _laterController,
onViewLater: (cid) {
@@ -97,12 +98,6 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
},
);
},
onRemove: () => _laterController.toViewDel(
context,
index,
videoItem.aid,
onSuccess: () => _laterController.updateLength?.call(1),
),
);
},
childCount: response!.length,

View File

@@ -22,7 +22,7 @@ mixin BaseLaterController
CommonListController<LaterData, LaterItemModel>,
CommonMultiSelectMixin<LaterItemModel>,
DeleteItemMixin<LaterData, LaterItemModel> {
ValueChanged<int>? updateLength;
ValueChanged<int>? updateCount;
@override
void onRemove() {
@@ -37,7 +37,7 @@ mixin BaseLaterController
aids: removeList.map((item) => item.aid).join(','),
);
if (res['status']) {
updateLength?.call(removeList.length);
updateCount?.call(removeList.length);
afterDelete(removeList);
}
SmartDialog.dismiss();
@@ -50,9 +50,8 @@ mixin BaseLaterController
void toViewDel(
BuildContext context,
int index,
int? aid, {
VoidCallback? onSuccess,
}) {
int? aid,
) {
showDialog(
context: context,
builder: (context) {
@@ -75,7 +74,7 @@ mixin BaseLaterController
loadingState
..value.data!.removeAt(index)
..refresh();
onSuccess?.call();
updateCount?.call(1);
}
SmartDialog.showToast(res['msg']);
},
@@ -169,9 +168,6 @@ class LaterController extends MultiSelectController<LaterData, LaterItemModel>
if (item.cid == null || item.pgcLabel?.isNotEmpty == true) {
continue;
} else {
if (item.bvid != list.first.bvid) {
SmartDialog.showToast('已跳过不支持播放的视频');
}
PageUtils.toVideoPage(
bvid: item.bvid,
cid: item.cid!,
@@ -192,7 +188,7 @@ class LaterController extends MultiSelectController<LaterData, LaterItemModel>
}
@override
ValueChanged<int>? get updateLength =>
ValueChanged<int>? get updateCount =>
(count) => baseCtr.counts[laterViewType] =
baseCtr.counts[laterViewType]! - count;

View File

@@ -21,14 +21,14 @@ class VideoCardHLater extends StatelessWidget {
const VideoCardHLater({
super.key,
required this.ctr,
required this.index,
required this.videoItem,
this.onViewLater,
required this.onRemove,
required this.onViewLater,
});
final int index;
final BaseLaterController ctr;
final LaterItemModel videoItem;
final ValueChanged<int>? onViewLater;
final VoidCallback onRemove;
final ValueChanged<int> onViewLater;
@override
Widget build(BuildContext context) {
@@ -72,7 +72,7 @@ class VideoCardHLater extends StatelessWidget {
bvid: videoItem.bvid,
);
if (cid != null) {
onViewLater!(cid);
onViewLater(cid);
}
} catch (err) {
SmartDialog.showToast(err.toString());
@@ -192,7 +192,7 @@ class VideoCardHLater extends StatelessWidget {
iconButton(
tooltip: '移除',
context: context,
onPressed: onRemove,
onPressed: () => ctr..toViewDel(context, index, videoItem.aid),
icon: Icons.clear,
iconColor: theme.colorScheme.outline,
bgColor: Colors.transparent,

View File

@@ -38,6 +38,7 @@ class _LaterSearchPageState
}
final item = list[index];
return VideoCardHLater(
index: index,
videoItem: item,
ctr: controller,
onViewLater: (cid) {
@@ -57,11 +58,6 @@ class _LaterSearchPageState
},
);
},
onRemove: () => controller.toViewDel(
context,
index,
item.aid!,
),
);
}),
);

View File

@@ -11,7 +11,6 @@ import 'package:PiliPlus/pages/common/common_list_controller.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/page_utils.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class MemberVideoCtr
@@ -186,9 +185,6 @@ class MemberVideoCtr
if (element.cid == null) {
continue;
} else {
if (element.bvid != list.first.bvid) {
SmartDialog.showToast('已跳过不支持播放的视频');
}
bool desc = seasonId != null ? false : true;
desc =
(seasonId != null || seriesId != null) &&

View File

@@ -534,17 +534,16 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
/// 播放上一个
@override
bool prevPlay([bool skipPages = false]) {
bool prevPlay([bool skipPart = false]) {
final List<BaseEpisodeItem> episodes = <BaseEpisodeItem>[];
bool isPages = false;
bool isPart = false;
final videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
final videoDetail = this.videoDetail.value;
if (!skipPages && (videoDetail.pages?.length ?? 0) > 1) {
isPages = true;
final List<Part> pages = videoDetail.pages!;
episodes.addAll(pages);
if (!skipPart && (videoDetail.pages?.length ?? 0) > 1) {
isPart = true;
episodes.addAll(videoDetail.pages!);
} else if (videoDetailCtr.isPlayAll) {
episodes.addAll(videoDetailCtr.mediaList);
} else if (videoDetail.ugcSeason != null) {
@@ -559,18 +558,19 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
final int currentIndex = episodes.indexWhere(
(e) =>
e.cid ==
(skipPages
(skipPart
? videoDetail.isPageReversed == true
? videoDetail.pages!.last.cid
: videoDetail.pages!.first.cid
: cid.value),
: this.cid.value),
);
int prevIndex = currentIndex - 1;
final PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
// 列表循环
if (prevIndex < 0) {
if (isPages &&
if (isPart &&
(videoDetailCtr.isPlayAll || videoDetail.ugcSeason != null)) {
return prevPlay(true);
}
@@ -580,22 +580,36 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
return false;
}
}
onChangeEpisode(episodes[prevIndex]);
return true;
int? cid = episodes[prevIndex].cid;
while (cid == null) {
prevIndex--;
if (prevIndex < 0) {
return false;
}
cid = episodes[prevIndex].cid;
}
if (cid != this.cid.value) {
onChangeEpisode(episodes[prevIndex]);
return true;
} else {
return false;
}
}
/// 列表循环或者顺序播放时,自动播放下一个
@override
bool nextPlay([bool skipPages = false]) {
bool nextPlay([bool skipPart = false]) {
try {
final List<BaseEpisodeItem> episodes = <BaseEpisodeItem>[];
bool isPages = false;
bool isPart = false;
final videoDetailCtr = Get.find<VideoDetailController>(tag: heroTag);
final videoDetail = this.videoDetail.value;
// part -> playall -> season
if (!skipPages && (videoDetail.pages?.length ?? 0) > 1) {
isPages = true;
if (!skipPart && (videoDetail.pages?.length ?? 0) > 1) {
isPart = true;
final List<Part> pages = videoDetail.pages!;
episodes.addAll(pages);
} else if (videoDetailCtr.isPlayAll) {
@@ -623,16 +637,16 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
final int currentIndex = episodes.indexWhere(
(e) =>
e.cid ==
(skipPages
(skipPart
? videoDetail.isPageReversed == true
? videoDetail.pages!.last.cid
: videoDetail.pages!.first.cid
: videoDetailCtr.cid.value),
: this.cid.value),
);
int nextIndex = currentIndex + 1;
if (!isPages &&
if (!isPart &&
videoDetailCtr.isPlayAll &&
currentIndex == episodes.length - 2) {
videoDetailCtr.getMediaList();
@@ -640,7 +654,7 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
// 列表循环
if (nextIndex >= episodes.length) {
if (isPages &&
if (isPart &&
(videoDetailCtr.isPlayAll || videoDetail.ugcSeason != null)) {
return nextPlay(true);
}
@@ -655,18 +669,21 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
}
}
int cid = episodes[nextIndex].cid!;
while (cid == -1) {
SmartDialog.showToast('当前视频暂不支持播放,自动跳过');
int? cid = episodes[nextIndex].cid;
while (cid == null) {
nextIndex++;
if (nextIndex >= episodes.length) {
return false;
}
cid = episodes[nextIndex].cid!;
cid = episodes[nextIndex].cid;
}
if (cid != this.cid.value) {
onChangeEpisode(episodes[nextIndex]);
return true;
} else {
return false;
}
onChangeEpisode(episodes[nextIndex]);
return true;
} catch (_) {
return false;
}

View File

@@ -2011,7 +2011,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
}
void showEpisodes([int? index, season, episodes, bvid, aid, cid]) {
if (bvid == null) {
if (cid == null) {
videoDetailController.showMediaListPanel(context);
return;
}

View File

@@ -7,7 +7,6 @@ import 'package:PiliPlus/common/widgets/progress_bar/audio_video_progress_bar.da
import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart';
import 'package:PiliPlus/models/common/super_resolution_type.dart';
import 'package:PiliPlus/models_new/video/video_detail/episode.dart';
import 'package:PiliPlus/models_new/video/video_detail/page.dart';
import 'package:PiliPlus/models_new/video/video_detail/section.dart';
import 'package:PiliPlus/models_new/video/video_shot/data.dart';
import 'package:PiliPlus/pages/common/common_intro_controller.dart';
@@ -257,11 +256,14 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
// 动态构建底部控制条
Widget buildBottomControl() {
final videoDetail = introController.videoDetail.value;
bool isSeason = videoDetail.ugcSeason != null;
bool isPage = videoDetail.pages != null && videoDetail.pages!.length > 1;
bool isPgc = pgcIntroController != null;
bool anySeason = isSeason || isPage || isPgc;
double widgetWidth = isFullScreen && context.isLandscape ? 42 : 35;
final isSeason = videoDetail.ugcSeason != null;
final isPart = videoDetail.pages != null && videoDetail.pages!.length > 1;
final isPgc = pgcIntroController != null;
final anySeason = isSeason || isPart || isPgc;
final isPlayAll = widget.videoDetailController?.isPlayAll == true;
final double widgetWidth = isFullScreen && context.isLandscape ? 42 : 35;
Map<BottomControlType, Widget> videoProgressWidgets = {
/// 上一集
BottomControlType.pre: Container(
@@ -460,7 +462,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
color: Colors.white,
),
onTap: () {
if (!anySeason || widget.videoDetailController?.isPlayAll == true) {
// part -> playAll -> season(pgc)
if (!anySeason || !isPart) {
widget.showEpisodes?.call();
return;
}
@@ -481,9 +484,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}
}
}
} else if (isPage) {
final List<Part> pages = videoDetail.pages!;
episodes = pages;
} else if (isPart) {
episodes = videoDetail.pages!;
} else if (isPgc) {
episodes = pgcIntroController!.pgcItem.episodes!;
}
@@ -493,7 +495,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
isSeason ? null : episodes,
bvid,
IdUtils.bv2av(bvid),
isSeason && isPage
isSeason && isPart
? widget.videoDetailController?.seasonCid ?? currentCid
: currentCid,
);
@@ -642,7 +644,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
List<BottomControlType> userSpecifyItemLeft = [
BottomControlType.playOrPause,
BottomControlType.time,
if (anySeason || widget.videoDetailController?.isPlayAll == true) ...[
if (anySeason || isPlayAll) ...[
BottomControlType.pre,
BottomControlType.next,
],
@@ -652,8 +654,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
BottomControlType.dmChart,
BottomControlType.superResolution,
BottomControlType.viewPoints,
if (anySeason || widget.videoDetailController?.isPlayAll == true)
BottomControlType.episode,
if (anySeason || isPlayAll) BottomControlType.episode,
if (isFullScreen) BottomControlType.fit,
BottomControlType.subtitle,
BottomControlType.speed,