mod: 合集连播
This commit is contained in:
@ -9,6 +9,7 @@ import 'package:pilipala/models/bangumi/info.dart';
|
||||
import 'package:pilipala/models/user/fav_folder.dart';
|
||||
import 'package:pilipala/pages/video/detail/index.dart';
|
||||
import 'package:pilipala/pages/video/detail/reply/index.dart';
|
||||
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
||||
import 'package:pilipala/utils/feed_back.dart';
|
||||
import 'package:pilipala/utils/id_utils.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
@ -292,4 +293,31 @@ class BangumiIntroController extends GetxController {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 列表循环或者顺序播放时,自动播放下一个
|
||||
void nextPlay() {
|
||||
late List episodes;
|
||||
if (bangumiDetail.value.episodes != null) {
|
||||
episodes = bangumiDetail.value.episodes!;
|
||||
}
|
||||
VideoDetailController videoDetailCtr =
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
||||
int currentIndex =
|
||||
episodes.indexWhere((e) => e.cid == videoDetailCtr.cid.value);
|
||||
int nextIndex = currentIndex + 1;
|
||||
PlayRepeat platRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
||||
// 列表循环
|
||||
if (platRepeat == PlayRepeat.listCycle) {
|
||||
if (nextIndex == episodes.length - 1) {
|
||||
nextIndex = 0;
|
||||
}
|
||||
}
|
||||
if (nextIndex <= episodes.length - 1 &&
|
||||
platRepeat == PlayRepeat.listOrder) {}
|
||||
|
||||
int cid = episodes[nextIndex].cid!;
|
||||
String bvid = episodes[nextIndex].bvid!;
|
||||
int aid = episodes[nextIndex].aid!;
|
||||
changeSeasonOrbangu(bvid, cid, aid);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class VideoDetailController extends GetxController
|
||||
with GetSingleTickerProviderStateMixin {
|
||||
/// 路由传参
|
||||
String bvid = Get.parameters['bvid']!;
|
||||
int cid = int.parse(Get.parameters['cid']!);
|
||||
RxInt cid = int.parse(Get.parameters['cid']!).obs;
|
||||
RxInt danmakuCid = 0.obs;
|
||||
String heroTag = Get.arguments['heroTag'];
|
||||
// 视频详情
|
||||
@ -103,7 +103,7 @@ class VideoDetailController extends GetxController
|
||||
localCache.get(LocalCacheKey.historyPause) == true) {
|
||||
enableHeart = false;
|
||||
}
|
||||
danmakuCid.value = cid;
|
||||
danmakuCid.value = cid.value;
|
||||
}
|
||||
|
||||
showReplyReplyPanel() {
|
||||
@ -202,7 +202,7 @@ class VideoDetailController extends GetxController
|
||||
// 默认1倍速
|
||||
speed: 1.0,
|
||||
bvid: bvid,
|
||||
cid: cid,
|
||||
cid: cid.value,
|
||||
enableHeart: enableHeart,
|
||||
isFirstTime: isFirstTime,
|
||||
autoplay: autoplay,
|
||||
@ -211,7 +211,7 @@ class VideoDetailController extends GetxController
|
||||
|
||||
// 视频链接
|
||||
Future queryVideoUrl() async {
|
||||
var result = await VideoHttp.videoUrl(cid: cid, bvid: bvid);
|
||||
var result = await VideoHttp.videoUrl(cid: cid.value, bvid: bvid);
|
||||
if (result['status']) {
|
||||
data = result['data'];
|
||||
|
||||
|
@ -11,6 +11,7 @@ import 'package:pilipala/models/user/fav_folder.dart';
|
||||
import 'package:pilipala/models/video_detail_res.dart';
|
||||
import 'package:pilipala/pages/video/detail/controller.dart';
|
||||
import 'package:pilipala/pages/video/detail/reply/index.dart';
|
||||
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
||||
import 'package:pilipala/utils/feed_back.dart';
|
||||
import 'package:pilipala/utils/id_utils.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
@ -58,10 +59,14 @@ class VideoIntroController extends GetxController {
|
||||
RxString total = '1'.obs;
|
||||
Timer? timer;
|
||||
bool isPaused = false;
|
||||
String heroTag = '';
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
try {
|
||||
heroTag = Get.arguments['heroTag'];
|
||||
} catch (_) {}
|
||||
userInfo = userInfoCache.get('userInfoCache');
|
||||
if (Get.arguments.isNotEmpty) {
|
||||
if (Get.arguments.containsKey('videoItem')) {
|
||||
@ -486,4 +491,45 @@ class VideoIntroController extends GetxController {
|
||||
}
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
/// 列表循环或者顺序播放时,自动播放下一个
|
||||
void nextPlay() {
|
||||
late List episodes;
|
||||
bool isPages = false;
|
||||
if (videoDetail.value.ugcSeason != null) {
|
||||
UgcSeason ugcSeason = videoDetail.value.ugcSeason!;
|
||||
List<SectionItem> sections = ugcSeason.sections!;
|
||||
episodes = [];
|
||||
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
List<EpisodeItem> episodesList = sections[i].episodes!;
|
||||
episodes.addAll(episodesList);
|
||||
}
|
||||
} else if (videoDetail.value.pages != null) {
|
||||
isPages = true;
|
||||
List<Part> pages = videoDetail.value.pages!;
|
||||
episodes = [];
|
||||
episodes.addAll(pages);
|
||||
}
|
||||
|
||||
int currentIndex = episodes.indexWhere((e) => e.cid == lastPlayCid.value);
|
||||
int nextIndex = currentIndex + 1;
|
||||
VideoDetailController videoDetailCtr =
|
||||
Get.find<VideoDetailController>(tag: heroTag);
|
||||
PlayRepeat platRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
||||
|
||||
// 列表循环
|
||||
if (nextIndex >= episodes.length) {
|
||||
if (platRepeat == PlayRepeat.listCycle) {
|
||||
nextIndex = 0;
|
||||
}
|
||||
if (platRepeat == PlayRepeat.listOrder) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int cid = episodes[nextIndex].cid!;
|
||||
String rBvid = isPages ? bvid : episodes[nextIndex].bvid;
|
||||
int rAid = isPages ? IdUtils.bv2av(bvid) : episodes[nextIndex].aid!;
|
||||
changeSeasonOrbangu(rBvid, cid, rAid);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import 'package:pilipala/models/video/play/url.dart';
|
||||
import 'package:pilipala/pages/video/detail/index.dart';
|
||||
import 'package:pilipala/pages/video/detail/introduction/widgets/menu_row.dart';
|
||||
import 'package:pilipala/plugin/pl_player/index.dart';
|
||||
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
|
||||
class HeaderControl extends StatefulWidget implements PreferredSizeWidget {
|
||||
@ -149,13 +150,14 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
'当前解码格式 ${widget.videoDetailCtr!.currentDecodeFormats.description}',
|
||||
style: subTitleStyle),
|
||||
),
|
||||
// ListTile(
|
||||
// onTap: () {},
|
||||
// dense: true,
|
||||
// enabled: false,
|
||||
// leading: const Icon(Icons.play_circle_outline, size: 20),
|
||||
// title: Text('播放设置', style: titleStyle),
|
||||
// ),
|
||||
ListTile(
|
||||
onTap: () => {Get.back(), showSetRepeat()},
|
||||
dense: true,
|
||||
leading: const Icon(Icons.repeat, size: 20),
|
||||
title: Text('播放顺序', style: titleStyle),
|
||||
subtitle: Text(widget.controller!.playRepeat.description,
|
||||
style: subTitleStyle),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () => {Get.back(), showSetDanmaku()},
|
||||
dense: true,
|
||||
@ -704,6 +706,60 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 播放顺序
|
||||
void showSetRepeat() async {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
height: 250,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
margin: const EdgeInsets.all(12),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 45,
|
||||
child: Center(child: Text('选择播放顺序', style: titleStyle))),
|
||||
Expanded(
|
||||
child: Material(
|
||||
child: ListView(
|
||||
children: [
|
||||
for (var i in PlayRepeat.values) ...[
|
||||
ListTile(
|
||||
onTap: () {
|
||||
widget.controller!.setPlayRepeat(i);
|
||||
Get.back();
|
||||
},
|
||||
dense: true,
|
||||
contentPadding:
|
||||
const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(i.description),
|
||||
trailing: widget.controller!.playRepeat == i
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
)
|
||||
: const SizedBox(),
|
||||
)
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final _ = widget.controller!;
|
||||
|
@ -13,6 +13,7 @@ import 'package:media_kit_video/media_kit_video.dart';
|
||||
import 'package:ns_danmaku/ns_danmaku.dart';
|
||||
import 'package:pilipala/http/video.dart';
|
||||
import 'package:pilipala/plugin/pl_player/index.dart';
|
||||
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
||||
import 'package:pilipala/utils/feed_back.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
import 'package:screen_brightness/screen_brightness.dart';
|
||||
@ -209,6 +210,9 @@ class PlPlayerController {
|
||||
late double fontSizeVal;
|
||||
late double danmakuSpeedVal;
|
||||
|
||||
// 播放顺序相关
|
||||
PlayRepeat playRepeat = PlayRepeat.pause;
|
||||
|
||||
// 添加一个私有构造函数
|
||||
PlPlayerController._() {
|
||||
_videoType = videoType;
|
||||
@ -226,6 +230,12 @@ class PlPlayerController {
|
||||
// 弹幕速度
|
||||
danmakuSpeedVal =
|
||||
localCache.get(LocalCacheKey.danmakuSpeed, defaultValue: 4.0);
|
||||
playRepeat = PlayRepeat.values.toList().firstWhere(
|
||||
(e) =>
|
||||
e.value ==
|
||||
videoStorage.get(VideoBoxKey.playRepeat,
|
||||
defaultValue: PlayRepeat.pause.value),
|
||||
);
|
||||
// _playerEventSubs = onPlayerStatusChanged.listen((PlayerStatus status) {
|
||||
// if (status == PlayerStatus.playing) {
|
||||
// WakelockPlus.enable();
|
||||
@ -902,6 +912,11 @@ class PlPlayerController {
|
||||
}
|
||||
}
|
||||
|
||||
setPlayRepeat(PlayRepeat type) {
|
||||
playRepeat = type;
|
||||
videoStorage.put(VideoBoxKey.playRepeat, type.value);
|
||||
}
|
||||
|
||||
Future<void> dispose({String type = 'single'}) async {
|
||||
// 每次减1,最后销毁
|
||||
if (type == 'single' && playerCount.value > 1) {
|
||||
|
25
lib/plugin/pl_player/models/play_repeat.dart
Normal file
25
lib/plugin/pl_player/models/play_repeat.dart
Normal file
@ -0,0 +1,25 @@
|
||||
enum PlayRepeat {
|
||||
pause,
|
||||
listOrder,
|
||||
singleCycle,
|
||||
listCycle,
|
||||
}
|
||||
|
||||
extension PlayRepeatExtension on PlayRepeat {
|
||||
static final List<String> _descList = [
|
||||
'播完暂停',
|
||||
'顺序播放',
|
||||
'单个循环',
|
||||
'列表循环',
|
||||
];
|
||||
get description => _descList[index];
|
||||
|
||||
static final List<double> _valueList = [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
];
|
||||
get value => _valueList[index];
|
||||
get defaultValue => _valueList[1];
|
||||
}
|
@ -156,4 +156,6 @@ class VideoBoxKey {
|
||||
static const String videoBrightness = 'videoBrightness';
|
||||
// 倍速
|
||||
static const String videoSpeed = 'videoSpeed';
|
||||
// 播放顺序
|
||||
static const String playRepeat = 'playRepeat';
|
||||
}
|
||||
|
Reference in New Issue
Block a user