Merge branch 'design' into alpha
This commit is contained in:
@ -24,7 +24,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'];
|
||||
// 视频详情
|
||||
@ -109,7 +109,7 @@ class VideoDetailController extends GetxController
|
||||
localCache.get(LocalCacheKey.historyPause) == true) {
|
||||
enableHeart = false;
|
||||
}
|
||||
danmakuCid.value = cid;
|
||||
danmakuCid.value = cid.value;
|
||||
|
||||
///
|
||||
if (Platform.isAndroid) {
|
||||
@ -218,7 +218,7 @@ class VideoDetailController extends GetxController
|
||||
// 默认1倍速
|
||||
speed: 1.0,
|
||||
bvid: bvid,
|
||||
cid: cid,
|
||||
cid: cid.value,
|
||||
enableHeart: enableHeart,
|
||||
isFirstTime: isFirstTime,
|
||||
autoplay: autoplay,
|
||||
@ -230,7 +230,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,11 +11,14 @@ 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';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import 'widgets/group_panel.dart';
|
||||
|
||||
class VideoIntroController extends GetxController {
|
||||
// 视频bvid
|
||||
String bvid = Get.parameters['bvid']!;
|
||||
@ -58,6 +61,7 @@ class VideoIntroController extends GetxController {
|
||||
RxString total = '1'.obs;
|
||||
Timer? timer;
|
||||
bool isPaused = false;
|
||||
String heroTag = Get.arguments['heroTag'];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
@ -102,9 +106,10 @@ class VideoIntroController extends GetxController {
|
||||
if (videoDetail.value.pages!.isNotEmpty && lastPlayCid.value == 0) {
|
||||
lastPlayCid.value = videoDetail.value.pages!.first.cid!;
|
||||
}
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag'])
|
||||
.tabs
|
||||
.value = ['简介', '评论 ${result['data']!.stat!.reply}'];
|
||||
// Get.find<VideoDetailController>(tag: heroTag).tabs.value = [
|
||||
// '简介',
|
||||
// '评论 ${result['data']!.stat!.reply}'
|
||||
// ];
|
||||
// 获取到粉丝数再返回
|
||||
await queryUserStat();
|
||||
}
|
||||
@ -425,6 +430,20 @@ class VideoIntroController extends GetxController {
|
||||
}
|
||||
followStatus['attribute'] = actionStatus;
|
||||
followStatus.refresh();
|
||||
if (actionStatus == 2) {
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text('关注成功'),
|
||||
duration: const Duration(seconds: 2),
|
||||
action: SnackBarAction(
|
||||
label: '设置分组',
|
||||
onPressed: setFollowGroup,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
@ -440,16 +459,16 @@ class VideoIntroController extends GetxController {
|
||||
Future changeSeasonOrbangu(bvid, cid, aid) async {
|
||||
// 重新获取视频资源
|
||||
VideoDetailController videoDetailCtr =
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
||||
Get.find<VideoDetailController>(tag: heroTag);
|
||||
videoDetailCtr.bvid = bvid;
|
||||
videoDetailCtr.cid = cid;
|
||||
videoDetailCtr.cid.value = cid;
|
||||
videoDetailCtr.danmakuCid.value = cid;
|
||||
videoDetailCtr.queryVideoUrl();
|
||||
// 重新请求评论
|
||||
try {
|
||||
/// 未渲染回复组件时可能异常
|
||||
VideoReplyController videoReplyCtr =
|
||||
Get.find<VideoReplyController>(tag: Get.arguments['heroTag']);
|
||||
Get.find<VideoReplyController>(tag: heroTag);
|
||||
videoReplyCtr.aid = aid;
|
||||
videoReplyCtr.queryReplyList(type: 'init');
|
||||
} catch (_) {}
|
||||
@ -486,4 +505,60 @@ class VideoIntroController extends GetxController {
|
||||
}
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
/// 列表循环或者顺序播放时,自动播放下一个
|
||||
void nextPlay() {
|
||||
late List episodes;
|
||||
// if (videoDetail.value.ugcSeason != null) {
|
||||
// UgcSeason ugcSeason = videoDetail.value.ugcSeason!;
|
||||
// List<SectionItem> sections = ugcSeason.sections!;
|
||||
// for (int i = 0; i < sections.length; i++) {
|
||||
// List<EpisodeItem> episodesList = sections[i].episodes!;
|
||||
// for (int j = 0; j < episodesList.length; j++) {
|
||||
// if (episodesList[j].cid == lastPlayCid.value) {
|
||||
// episodes = episodesList;
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 bvid = episodes[nextIndex].bvid!;
|
||||
int aid = episodes[nextIndex].aid!;
|
||||
changeSeasonOrbangu(bvid, cid, aid);
|
||||
}
|
||||
|
||||
// 设置关注分组
|
||||
void setFollowGroup() {
|
||||
Get.bottomSheet(
|
||||
GroupPanel(mid: videoDetail.value.owner!.mid!),
|
||||
isScrollControlled: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,17 +330,17 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(height: 7),
|
||||
// 点赞收藏转发 布局样式1
|
||||
SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(top: 7, bottom: 7),
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: actionRow(
|
||||
context,
|
||||
videoIntroController,
|
||||
videoDetailCtr,
|
||||
),
|
||||
),
|
||||
// SingleChildScrollView(
|
||||
// padding: const EdgeInsets.only(top: 7, bottom: 7),
|
||||
// scrollDirection: Axis.horizontal,
|
||||
// child: actionRow(
|
||||
// context,
|
||||
// videoIntroController,
|
||||
// videoDetailCtr,
|
||||
// ),
|
||||
// ),
|
||||
// 点赞收藏转发 布局样式2
|
||||
// actionGrid(context, videoIntroController),
|
||||
actionGrid(context, videoIntroController),
|
||||
// 合集
|
||||
if (!loadingStatus &&
|
||||
widget.videoDetail!.ugcSeason != null) ...[
|
||||
@ -458,7 +458,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
Widget actionGrid(BuildContext context, videoIntroController) {
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(top: 6, bottom: 10),
|
||||
margin: const EdgeInsets.only(top: 6, bottom: 4),
|
||||
height: constraints.maxWidth / 5 * 0.8,
|
||||
child: GridView.count(
|
||||
primary: false,
|
||||
@ -477,12 +477,12 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
? widget.videoDetail!.stat!.like!.toString()
|
||||
: '-'),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.clock),
|
||||
onTap: () => videoIntroController.actionShareVideo(),
|
||||
selectStatus: false,
|
||||
loadingStatus: loadingStatus,
|
||||
text: '稍后再看'),
|
||||
// ActionItem(
|
||||
// icon: const Icon(FontAwesomeIcons.clock),
|
||||
// onTap: () => videoIntroController.actionShareVideo(),
|
||||
// selectStatus: false,
|
||||
// loadingStatus: loadingStatus,
|
||||
// text: '稍后再看'),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
@ -498,22 +498,28 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.star),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidStar),
|
||||
// onTap: () => videoIntroController.actionFavVideo(),
|
||||
onTap: () => showFavBottomSheet(),
|
||||
onLongPress: () => showFavBottomSheet(type: 'longPress'),
|
||||
selectStatus: videoIntroController.hasFav.value,
|
||||
loadingStatus: loadingStatus,
|
||||
text: !loadingStatus
|
||||
? widget.videoDetail!.stat!.favorite!.toString()
|
||||
: '-'),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.comment),
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
selectStatus: false,
|
||||
loadingStatus: loadingStatus,
|
||||
text: !loadingStatus
|
||||
? widget.videoDetail!.stat!.reply!.toString()
|
||||
: '评论'),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||
onTap: () => videoIntroController.actionShareVideo(),
|
||||
selectStatus: false,
|
||||
loadingStatus: loadingStatus,
|
||||
text: !loadingStatus
|
||||
? widget.videoDetail!.stat!.share!.toString()
|
||||
: '-'),
|
||||
text: '分享'),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@ -6,6 +6,7 @@ class ActionItem extends StatelessWidget {
|
||||
final Icon? icon;
|
||||
final Icon? selectIcon;
|
||||
final Function? onTap;
|
||||
final Function? onLongPress;
|
||||
final bool? loadingStatus;
|
||||
final String? text;
|
||||
final bool selectStatus;
|
||||
@ -15,6 +16,7 @@ class ActionItem extends StatelessWidget {
|
||||
this.icon,
|
||||
this.selectIcon,
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.loadingStatus,
|
||||
this.text,
|
||||
this.selectStatus = false,
|
||||
@ -27,6 +29,9 @@ class ActionItem extends StatelessWidget {
|
||||
feedBack(),
|
||||
onTap!(),
|
||||
},
|
||||
onLongPress: () => {
|
||||
if (onLongPress != null) {onLongPress!()}
|
||||
},
|
||||
borderRadius: StyleString.mdRadius,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
156
lib/pages/video/detail/introduction/widgets/group_panel.dart
Normal file
156
lib/pages/video/detail/introduction/widgets/group_panel.dart
Normal file
@ -0,0 +1,156 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/common/widgets/http_error.dart';
|
||||
import 'package:pilipala/http/member.dart';
|
||||
import 'package:pilipala/models/member/tags.dart';
|
||||
import 'package:pilipala/utils/feed_back.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
|
||||
class GroupPanel extends StatefulWidget {
|
||||
final int? mid;
|
||||
const GroupPanel({super.key, this.mid});
|
||||
|
||||
@override
|
||||
State<GroupPanel> createState() => _GroupPanelState();
|
||||
}
|
||||
|
||||
class _GroupPanelState extends State<GroupPanel> {
|
||||
Box localCache = GStrorage.localCache;
|
||||
late double sheetHeight;
|
||||
late Future _futureBuilderFuture;
|
||||
late List<MemberTagItemModel> tagsList;
|
||||
bool showDefault = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
sheetHeight = localCache.get('sheetHeight');
|
||||
_futureBuilderFuture = MemberHttp.followUpTags();
|
||||
}
|
||||
|
||||
void onSave() async {
|
||||
feedBack();
|
||||
// 是否有选中的 有选中的带id,没选使用默认0
|
||||
bool anyHasChecked = tagsList.any((e) => e.checked == true);
|
||||
late String tagids;
|
||||
if (anyHasChecked) {
|
||||
List checkedList = tagsList.where((e) => e.checked == true).toList();
|
||||
List<int> tagidList = checkedList.map<int>((e) => e.tagid).toList();
|
||||
tagids = tagidList.join(',');
|
||||
} else {
|
||||
tagids = '0';
|
||||
}
|
||||
// 保存
|
||||
var res = await MemberHttp.addUsers(widget.mid, tagids);
|
||||
SmartDialog.showToast(res['msg']);
|
||||
if (res['status']) {
|
||||
Get.back();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: sheetHeight,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: Column(
|
||||
children: [
|
||||
AppBar(
|
||||
centerTitle: false,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
onPressed: () => Get.back(),
|
||||
icon: const Icon(Icons.close_outlined)),
|
||||
title:
|
||||
Text('设置关注分组', style: Theme.of(context).textTheme.titleMedium),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
child: FutureBuilder(
|
||||
future: _futureBuilderFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
Map data = snapshot.data as Map;
|
||||
if (data['status']) {
|
||||
tagsList = data['data'];
|
||||
return ListView.builder(
|
||||
itemCount: data['data'].length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
data['data'][index].checked =
|
||||
!data['data'][index].checked;
|
||||
showDefault =
|
||||
!data['data'].any((e) => e.checked == true);
|
||||
setState(() {});
|
||||
},
|
||||
dense: true,
|
||||
leading: const Icon(Icons.group_outlined),
|
||||
minLeadingWidth: 0,
|
||||
title: Text(data['data'][index].name),
|
||||
subtitle: data['data'][index].tip != ''
|
||||
? Text(data['data'][index].tip)
|
||||
: null,
|
||||
trailing: Transform.scale(
|
||||
scale: 0.9,
|
||||
child: Checkbox(
|
||||
value: data['data'][index].checked,
|
||||
onChanged: (bool? checkValue) {
|
||||
data['data'][index].checked = checkValue;
|
||||
showDefault = !data['data']
|
||||
.any((e) => e.checked == true);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return HttpError(
|
||||
errMsg: data['msg'],
|
||||
fn: () => setState(() {}),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// 骨架屏
|
||||
return const Text('请求中');
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).disabledColor.withOpacity(0.08),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 20,
|
||||
right: 20,
|
||||
top: 12,
|
||||
bottom: MediaQuery.of(context).padding.bottom + 12,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () => onSave(),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.only(left: 30, right: 30),
|
||||
foregroundColor: Theme.of(context).colorScheme.onPrimary,
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.primary, // 设置按钮背景色
|
||||
),
|
||||
child: Text(showDefault ? '保存至默认分组' : '保存'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/models/video_detail_res.dart';
|
||||
import 'package:pilipala/pages/video/detail/index.dart';
|
||||
|
||||
class PagesPanel extends StatefulWidget {
|
||||
final List<Part> pages;
|
||||
@ -22,13 +23,23 @@ class PagesPanel extends StatefulWidget {
|
||||
|
||||
class _PagesPanelState extends State<PagesPanel> {
|
||||
late List<Part> episodes;
|
||||
late int cid;
|
||||
late int currentIndex;
|
||||
String heroTag = Get.arguments['heroTag'];
|
||||
late VideoDetailController _videoDetailController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
cid = widget.cid!;
|
||||
episodes = widget.pages;
|
||||
currentIndex = episodes.indexWhere((e) => e.cid == widget.cid);
|
||||
_videoDetailController = Get.find<VideoDetailController>(tag: heroTag);
|
||||
currentIndex = episodes.indexWhere((e) => e.cid == cid);
|
||||
_videoDetailController.cid.listen((p0) {
|
||||
cid = p0;
|
||||
setState(() {});
|
||||
currentIndex = episodes.indexWhere((e) => e.cid == cid);
|
||||
});
|
||||
}
|
||||
|
||||
void changeFucCall(item, i) async {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/models/video_detail_res.dart';
|
||||
import 'package:pilipala/pages/video/detail/index.dart';
|
||||
import 'package:pilipala/utils/id_utils.dart';
|
||||
|
||||
class SeasonPanel extends StatefulWidget {
|
||||
@ -23,11 +24,16 @@ class SeasonPanel extends StatefulWidget {
|
||||
|
||||
class _SeasonPanelState extends State<SeasonPanel> {
|
||||
late List<EpisodeItem> episodes;
|
||||
late int cid;
|
||||
late int currentIndex;
|
||||
String heroTag = Get.arguments['heroTag'];
|
||||
late VideoDetailController _videoDetailController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
cid = widget.cid!;
|
||||
_videoDetailController = Get.find<VideoDetailController>(tag: heroTag);
|
||||
|
||||
/// 根据 cid 找到对应集,找到对应 episodes
|
||||
/// 有多个episodes时,只显示其中一个
|
||||
@ -36,7 +42,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
List<EpisodeItem> episodesList = sections[i].episodes!;
|
||||
for (int j = 0; j < episodesList.length; j++) {
|
||||
if (episodesList[j].cid == widget.cid) {
|
||||
if (episodesList[j].cid == cid) {
|
||||
episodes = episodesList;
|
||||
continue;
|
||||
}
|
||||
@ -47,7 +53,12 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
// episodes = widget.ugcSeason.sections!
|
||||
// .firstWhere((e) => e.seasonId == widget.ugcSeason.id)
|
||||
// .episodes!;
|
||||
currentIndex = episodes.indexWhere((e) => e.cid == widget.cid);
|
||||
currentIndex = episodes.indexWhere((e) => e.cid == cid);
|
||||
_videoDetailController.cid.listen((p0) {
|
||||
cid = p0;
|
||||
setState(() {});
|
||||
currentIndex = episodes.indexWhere((e) => e.cid == cid);
|
||||
});
|
||||
}
|
||||
|
||||
void changeFucCall(item, i) async {
|
||||
@ -57,6 +68,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
item.aid,
|
||||
);
|
||||
currentIndex = i;
|
||||
setState(() {});
|
||||
Get.back();
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ import 'package:pilipala/pages/video/detail/controller.dart';
|
||||
import 'package:pilipala/pages/video/detail/introduction/index.dart';
|
||||
import 'package:pilipala/pages/video/detail/related/index.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';
|
||||
|
||||
import 'widgets/app_bar.dart';
|
||||
@ -41,6 +42,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
final ScrollController _extendNestCtr = ScrollController();
|
||||
late StreamController<double> appbarStream;
|
||||
late VideoIntroController videoIntroController;
|
||||
late BangumiIntroController bangumiIntroController;
|
||||
late String heroTag;
|
||||
|
||||
PlayerStatus playerStatus = PlayerStatus.playing;
|
||||
@ -61,6 +63,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
heroTag = Get.arguments['heroTag'];
|
||||
videoDetailController = Get.put(VideoDetailController(), tag: heroTag);
|
||||
videoIntroController = Get.put(VideoIntroController(), tag: heroTag);
|
||||
bangumiIntroController = Get.put(BangumiIntroController(), tag: heroTag);
|
||||
statusBarHeight = localCache.get('statusBarHeight');
|
||||
autoExitFullcreen =
|
||||
setting.get(SettingBoxKey.enableAutoExit, defaultValue: false);
|
||||
@ -98,6 +101,23 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
if (autoExitFullcreen) {
|
||||
plPlayerController!.triggerFullScreen(status: false);
|
||||
}
|
||||
|
||||
/// 顺序播放 列表循环
|
||||
if (plPlayerController!.playRepeat != PlayRepeat.pause &&
|
||||
plPlayerController!.playRepeat != PlayRepeat.singleCycle) {
|
||||
if (videoDetailController.videoType == SearchType.video) {
|
||||
videoIntroController.nextPlay();
|
||||
}
|
||||
if (videoDetailController.videoType == SearchType.media_bangumi) {
|
||||
bangumiIntroController.nextPlay();
|
||||
}
|
||||
}
|
||||
|
||||
/// 单个循环
|
||||
if (plPlayerController!.playRepeat == PlayRepeat.singleCycle) {
|
||||
plPlayerController!.seekTo(Duration.zero);
|
||||
plPlayerController!.play();
|
||||
}
|
||||
// 播放完展示控制栏
|
||||
try {
|
||||
PiPStatus currentStatus =
|
||||
@ -385,8 +405,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
const VideoIntroPanel(),
|
||||
] else if (videoDetailController.videoType ==
|
||||
SearchType.media_bangumi) ...[
|
||||
BangumiIntroPanel(
|
||||
cid: videoDetailController.cid)
|
||||
Obx(() => BangumiIntroPanel(
|
||||
cid: videoDetailController.cid.value)),
|
||||
],
|
||||
// if (videoDetailController.videoType ==
|
||||
// SearchType.video) ...[
|
||||
|
||||
@ -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 {
|
||||
@ -56,7 +57,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
builder: (_) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
height: 400,
|
||||
height: 440,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
@ -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!;
|
||||
|
||||
Reference in New Issue
Block a user