mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
mod: video sheet
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -113,480 +113,444 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
right: 12,
|
right: 12,
|
||||||
bottom: 12 + MediaQuery.paddingOf(context).bottom,
|
bottom: 12 + MediaQuery.paddingOf(context).bottom,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Material(
|
||||||
children: [
|
color: Colors.transparent,
|
||||||
SizedBox(
|
child: MediaQuery.removePadding(
|
||||||
height: 35,
|
context: context,
|
||||||
child: Center(
|
removeBottom: true,
|
||||||
child: Container(
|
child: ListView(
|
||||||
width: 32,
|
children: [
|
||||||
height: 3,
|
const SizedBox(height: 14),
|
||||||
decoration: BoxDecoration(
|
// ListTile(
|
||||||
color: Theme.of(context)
|
// onTap: () {},
|
||||||
.colorScheme
|
// dense: true,
|
||||||
.onSecondaryContainer
|
// enabled: false,
|
||||||
.withOpacity(0.5),
|
// leading:
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(3))),
|
// const Icon(Icons.network_cell_outlined, size: 20),
|
||||||
|
// title: Text('省流模式', style: titleStyle),
|
||||||
|
// subtitle: Text('低画质 | 减少视频缓存', style: subTitleStyle),
|
||||||
|
// trailing: Transform.scale(
|
||||||
|
// scale: 0.75,
|
||||||
|
// child: Switch(
|
||||||
|
// thumbIcon: WidgetStateProperty.resolveWith<Icon?>(
|
||||||
|
// (Set<WidgetState> states) {
|
||||||
|
// if (states.isNotEmpty &&
|
||||||
|
// states.first == WidgetState.selected) {
|
||||||
|
// return const Icon(Icons.done);
|
||||||
|
// }
|
||||||
|
// return null; // All other states will use the default thumbIcon.
|
||||||
|
// }),
|
||||||
|
// value: false,
|
||||||
|
// onChanged: (value) => {},
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// if (widget.videoDetailCtr.userInfo != null)
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () async {
|
||||||
|
Get.back();
|
||||||
|
final res = await UserHttp.toViewLater(
|
||||||
|
bvid: widget.videoDetailCtr.bvid);
|
||||||
|
SmartDialog.showToast(res['msg']);
|
||||||
|
},
|
||||||
|
leading: const Icon(Icons.watch_later_outlined, size: 20),
|
||||||
|
title: const Text('添加至「稍后再看」', style: titleStyle),
|
||||||
),
|
),
|
||||||
),
|
ListTile(
|
||||||
),
|
dense: true,
|
||||||
Expanded(
|
onTap: () => {Get.back(), scheduleExit()},
|
||||||
child: Material(
|
leading: const Icon(Icons.hourglass_top_outlined, size: 20),
|
||||||
color: Colors.transparent,
|
title: const Text('定时关闭', style: titleStyle),
|
||||||
child: MediaQuery.removePadding(
|
),
|
||||||
context: context,
|
ListTile(
|
||||||
removeBottom: true,
|
dense: true,
|
||||||
child: ListView(
|
onTap: () => {
|
||||||
|
Get.back(),
|
||||||
|
widget.videoDetailCtr.queryVideoUrl(
|
||||||
|
widget.videoDetailCtr.playedTime,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
leading: const Icon(Icons.refresh_outlined, size: 20),
|
||||||
|
title: const Text('重载视频', style: titleStyle),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
leading: const Icon(Icons.stay_current_landscape_outlined,
|
||||||
|
size: 20),
|
||||||
|
title: Row(
|
||||||
children: [
|
children: [
|
||||||
// ListTile(
|
const Text(
|
||||||
// onTap: () {},
|
'超分辨率',
|
||||||
// dense: true,
|
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||||
// enabled: false,
|
style: TextStyle(
|
||||||
// leading:
|
height: 1,
|
||||||
// const Icon(Icons.network_cell_outlined, size: 20),
|
fontSize: 14,
|
||||||
// title: Text('省流模式', style: titleStyle),
|
),
|
||||||
// subtitle: Text('低画质 | 减少视频缓存', style: subTitleStyle),
|
|
||||||
// trailing: Transform.scale(
|
|
||||||
// scale: 0.75,
|
|
||||||
// child: Switch(
|
|
||||||
// thumbIcon: WidgetStateProperty.resolveWith<Icon?>(
|
|
||||||
// (Set<WidgetState> states) {
|
|
||||||
// if (states.isNotEmpty &&
|
|
||||||
// states.first == WidgetState.selected) {
|
|
||||||
// return const Icon(Icons.done);
|
|
||||||
// }
|
|
||||||
// return null; // All other states will use the default thumbIcon.
|
|
||||||
// }),
|
|
||||||
// value: false,
|
|
||||||
// onChanged: (value) => {},
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// if (widget.videoDetailCtr.userInfo != null)
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
onTap: () async {
|
|
||||||
Get.back();
|
|
||||||
final res = await UserHttp.toViewLater(
|
|
||||||
bvid: widget.videoDetailCtr.bvid);
|
|
||||||
SmartDialog.showToast(res['msg']);
|
|
||||||
},
|
|
||||||
leading:
|
|
||||||
const Icon(Icons.watch_later_outlined, size: 20),
|
|
||||||
title: const Text('添加至「稍后再看」', style: titleStyle),
|
|
||||||
),
|
),
|
||||||
ListTile(
|
const SizedBox(width: 10),
|
||||||
dense: true,
|
Builder(
|
||||||
onTap: () => {Get.back(), scheduleExit()},
|
builder: (context) => PopupMenuButton(
|
||||||
leading:
|
initialValue: SuperResolutionType
|
||||||
const Icon(Icons.hourglass_top_outlined, size: 20),
|
.values[widget.controller.superResolutionType],
|
||||||
title: const Text('定时关闭', style: titleStyle),
|
child: Padding(
|
||||||
),
|
padding: const EdgeInsets.all(4),
|
||||||
ListTile(
|
child: Row(
|
||||||
dense: true,
|
mainAxisSize: MainAxisSize.min,
|
||||||
onTap: () => {
|
children: [
|
||||||
Get.back(),
|
Text(
|
||||||
widget.videoDetailCtr.queryVideoUrl(
|
SuperResolutionType
|
||||||
widget.videoDetailCtr.playedTime,
|
.values[
|
||||||
)
|
widget.controller.superResolutionType]
|
||||||
},
|
.title,
|
||||||
leading: const Icon(Icons.refresh_outlined, size: 20),
|
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||||
title: const Text('重载视频', style: titleStyle),
|
style: TextStyle(
|
||||||
),
|
height: 1,
|
||||||
ListTile(
|
fontSize: 14,
|
||||||
dense: true,
|
color:
|
||||||
leading: const Icon(
|
Theme.of(context).colorScheme.secondary,
|
||||||
Icons.stay_current_landscape_outlined,
|
),
|
||||||
size: 20),
|
),
|
||||||
title: Row(
|
Icon(
|
||||||
children: [
|
MdiIcons.unfoldMoreHorizontal,
|
||||||
const Text(
|
size: MediaQuery.textScalerOf(context)
|
||||||
'超分辨率',
|
.scale(14),
|
||||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
color:
|
||||||
style: TextStyle(
|
Theme.of(context).colorScheme.secondary,
|
||||||
height: 1,
|
)
|
||||||
fontSize: 14,
|
],
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
),
|
||||||
Builder(
|
onSelected: (value) {
|
||||||
builder: (context) => PopupMenuButton(
|
widget.controller.setShader(value.index);
|
||||||
initialValue: SuperResolutionType.values[
|
if (context.mounted) {
|
||||||
widget.controller.superResolutionType],
|
(context as Element).markNeedsBuild();
|
||||||
child: Padding(
|
}
|
||||||
padding: const EdgeInsets.all(4),
|
},
|
||||||
child: Row(
|
itemBuilder: (context) => SuperResolutionType.values
|
||||||
mainAxisSize: MainAxisSize.min,
|
.map((item) => PopupMenuItem(
|
||||||
children: [
|
value: item,
|
||||||
Text(
|
child: Text(item.title),
|
||||||
SuperResolutionType
|
))
|
||||||
.values[widget
|
.toList(),
|
||||||
.controller.superResolutionType]
|
|
||||||
.title,
|
|
||||||
strutStyle:
|
|
||||||
StrutStyle(leading: 0, height: 1),
|
|
||||||
style: TextStyle(
|
|
||||||
height: 1,
|
|
||||||
fontSize: 14,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.secondary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Icon(
|
|
||||||
MdiIcons.unfoldMoreHorizontal,
|
|
||||||
size: MediaQuery.textScalerOf(context)
|
|
||||||
.scale(14),
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.secondary,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onSelected: (value) {
|
|
||||||
widget.controller.setShader(value.index);
|
|
||||||
if (context.mounted) {
|
|
||||||
(context as Element).markNeedsBuild();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemBuilder: (context) =>
|
|
||||||
SuperResolutionType.values
|
|
||||||
.map((item) => PopupMenuItem(
|
|
||||||
value: item,
|
|
||||||
child: Text(item.title),
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text('CDN 设置', style: titleStyle),
|
|
||||||
leading: Icon(MdiIcons.cloudPlusOutline, size: 20),
|
|
||||||
subtitle: Text(
|
|
||||||
'当前:${CDNServiceCode.fromCode(defaultCDNService)!.description},无法播放请切换',
|
|
||||||
style: subTitleStyle,
|
|
||||||
),
|
|
||||||
onTap: () async {
|
|
||||||
Get.back();
|
|
||||||
String? result = await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return SelectDialog<String>(
|
|
||||||
title: 'CDN 设置',
|
|
||||||
value: defaultCDNService,
|
|
||||||
values: CDNService.values.map((e) {
|
|
||||||
return {
|
|
||||||
'title': e.description,
|
|
||||||
'value': e.code
|
|
||||||
};
|
|
||||||
}).toList());
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (result != null) {
|
|
||||||
defaultCDNService = result;
|
|
||||||
setting.put(SettingBoxKey.CDNService, result);
|
|
||||||
SmartDialog.showToast(
|
|
||||||
'已设置为 ${CDNServiceCode.fromCode(result)!.description},正在重载视频');
|
|
||||||
setState(() {});
|
|
||||||
widget.videoDetailCtr.queryVideoUrl(
|
|
||||||
widget.videoDetailCtr.playedTime,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SelfSizedHorizontalList(
|
|
||||||
itemCount: 4,
|
|
||||||
gapSize: 10,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
childBuilder: (index) {
|
|
||||||
return switch (index) {
|
|
||||||
0 => Obx(
|
|
||||||
() => ActionRowLineItem(
|
|
||||||
iconData: Icons.flip,
|
|
||||||
onTap: () {
|
|
||||||
widget.controller.flipX.value =
|
|
||||||
!widget.controller.flipX.value;
|
|
||||||
},
|
|
||||||
text: " 左右翻转 ",
|
|
||||||
selectStatus: widget.controller.flipX.value,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
1 => Obx(
|
|
||||||
() => ActionRowLineItem(
|
|
||||||
icon: Transform.rotate(
|
|
||||||
angle: pi / 2,
|
|
||||||
child: Icon(
|
|
||||||
Icons.flip,
|
|
||||||
size: 13,
|
|
||||||
color: widget.controller.flipY.value
|
|
||||||
? Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.onSecondaryContainer
|
|
||||||
: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
widget.controller.flipY.value =
|
|
||||||
!widget.controller.flipY.value;
|
|
||||||
},
|
|
||||||
text: " 上下翻转 ",
|
|
||||||
selectStatus: widget.controller.flipY.value,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
2 => Obx(
|
|
||||||
() => ActionRowLineItem(
|
|
||||||
iconData: Icons.headphones,
|
|
||||||
onTap: widget.controller.setOnlyPlayAudio,
|
|
||||||
text: " 听视频 ",
|
|
||||||
selectStatus:
|
|
||||||
widget.controller.onlyPlayAudio.value,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
3 => Obx(
|
|
||||||
() => ActionRowLineItem(
|
|
||||||
iconData: Icons.play_circle_outline,
|
|
||||||
onTap: widget
|
|
||||||
.controller.setContinuePlayInBackground,
|
|
||||||
text: " 后台播放 ",
|
|
||||||
selectStatus: widget.controller
|
|
||||||
.continuePlayInBackground.value,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
int() => throw UnimplementedError(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
onTap: () => {Get.back(), showSetVideoQa()},
|
|
||||||
leading:
|
|
||||||
const Icon(Icons.play_circle_outline, size: 20),
|
|
||||||
title: const Text('选择画质', style: titleStyle),
|
|
||||||
subtitle: Text(
|
|
||||||
'当前画质 ${widget.videoDetailCtr.currentVideoQa.description}',
|
|
||||||
style: subTitleStyle),
|
|
||||||
),
|
|
||||||
if (widget.videoDetailCtr.currentAudioQa != null)
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
onTap: () => {Get.back(), showSetAudioQa()},
|
|
||||||
leading: const Icon(Icons.album_outlined, size: 20),
|
|
||||||
title: const Text('选择音质', style: titleStyle),
|
|
||||||
subtitle: Text(
|
|
||||||
'当前音质 ${widget.videoDetailCtr.currentAudioQa!.description}',
|
|
||||||
style: subTitleStyle),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
onTap: () => {Get.back(), showSetDecodeFormats()},
|
|
||||||
leading: const Icon(Icons.av_timer_outlined, size: 20),
|
|
||||||
title: const Text('解码格式', style: titleStyle),
|
|
||||||
subtitle: Text(
|
|
||||||
'当前解码格式 ${widget.videoDetailCtr.currentDecodeFormats.description}',
|
|
||||||
style: subTitleStyle),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
onTap: () => {Get.back(), showSetRepeat()},
|
|
||||||
leading: const Icon(Icons.repeat, size: 20),
|
|
||||||
title: const Text('播放顺序', style: titleStyle),
|
|
||||||
subtitle: Text(widget.controller.playRepeat.description,
|
|
||||||
style: subTitleStyle),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
onTap: () => {Get.back(), showSetDanmaku()},
|
|
||||||
leading: const Icon(Icons.subtitles_outlined, size: 20),
|
|
||||||
title: const Text('弹幕/字幕设置', style: titleStyle),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text('播放信息', style: titleStyle),
|
|
||||||
leading: const Icon(Icons.info_outline, size: 20),
|
|
||||||
onTap: () {
|
|
||||||
Player? player =
|
|
||||||
widget.controller.videoPlayerController;
|
|
||||||
if (player == null) {
|
|
||||||
SmartDialog.showToast('播放器未初始化');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: const Text('播放信息'),
|
|
||||||
content: SizedBox(
|
|
||||||
width: double.maxFinite,
|
|
||||||
child: ListView(
|
|
||||||
children: [
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("Resolution"),
|
|
||||||
subtitle: Text(
|
|
||||||
'${player.state.width}x${player.state.height}'),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'Resolution\n${player.state.width}x${player.state.height}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("VideoParams"),
|
|
||||||
subtitle: Text(player.state.videoParams
|
|
||||||
.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'VideoParams\n${player.state.videoParams}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("AudioParams"),
|
|
||||||
subtitle: Text(player.state.audioParams
|
|
||||||
.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'AudioParams\n${player.state.audioParams}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("Media"),
|
|
||||||
subtitle: Text(
|
|
||||||
player.state.playlist.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'Media\n${player.state.playlist}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("AudioTrack"),
|
|
||||||
subtitle: Text(player.state.track.audio
|
|
||||||
.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'AudioTrack\n${player.state.track.audio}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("VideoTrack"),
|
|
||||||
subtitle: Text(player.state.track.video
|
|
||||||
.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'VideoTrack\n${player.state.track.audio}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("pitch"),
|
|
||||||
subtitle: Text(
|
|
||||||
player.state.pitch.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'pitch\n${player.state.pitch}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("rate"),
|
|
||||||
subtitle: Text(
|
|
||||||
player.state.rate.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'rate\n${player.state.rate}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("AudioBitrate"),
|
|
||||||
subtitle: Text(player.state.audioBitrate
|
|
||||||
.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'AudioBitrate\n${player.state.audioBitrate}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
title: const Text("Volume"),
|
|
||||||
subtitle: Text(
|
|
||||||
player.state.volume.toString()),
|
|
||||||
onTap: () {
|
|
||||||
Utils.copyText(
|
|
||||||
'Volume\n${player.state.volume}',
|
|
||||||
needToast: false,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Get.back(),
|
|
||||||
child: Text(
|
|
||||||
'确定',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
dense: true,
|
|
||||||
onTap: () {
|
|
||||||
if (widget.videoDetailCtr.userInfo == null) {
|
|
||||||
SmartDialog.showToast('账号未登录');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Get.back();
|
|
||||||
Get.toNamed('/webview', parameters: {
|
|
||||||
'url':
|
|
||||||
'https://www.bilibili.com/appeal/?avid=${IdUtils.bv2av(widget.videoDetailCtr.bvid)}&bvid=${widget.videoDetailCtr.bvid}'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
leading: const Icon(Icons.error_outline, size: 20),
|
|
||||||
title: const Text('举报', style: titleStyle),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 14),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text('CDN 设置', style: titleStyle),
|
||||||
|
leading: Icon(MdiIcons.cloudPlusOutline, size: 20),
|
||||||
|
subtitle: Text(
|
||||||
|
'当前:${CDNServiceCode.fromCode(defaultCDNService)!.description},无法播放请切换',
|
||||||
|
style: subTitleStyle,
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
Get.back();
|
||||||
|
String? result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return SelectDialog<String>(
|
||||||
|
title: 'CDN 设置',
|
||||||
|
value: defaultCDNService,
|
||||||
|
values: CDNService.values.map((e) {
|
||||||
|
return {'title': e.description, 'value': e.code};
|
||||||
|
}).toList());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
defaultCDNService = result;
|
||||||
|
setting.put(SettingBoxKey.CDNService, result);
|
||||||
|
SmartDialog.showToast(
|
||||||
|
'已设置为 ${CDNServiceCode.fromCode(result)!.description},正在重载视频');
|
||||||
|
setState(() {});
|
||||||
|
widget.videoDetailCtr.queryVideoUrl(
|
||||||
|
widget.videoDetailCtr.playedTime,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SelfSizedHorizontalList(
|
||||||
|
itemCount: 4,
|
||||||
|
gapSize: 10,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
childBuilder: (index) {
|
||||||
|
return switch (index) {
|
||||||
|
0 => Obx(
|
||||||
|
() => ActionRowLineItem(
|
||||||
|
iconData: Icons.flip,
|
||||||
|
onTap: () {
|
||||||
|
widget.controller.flipX.value =
|
||||||
|
!widget.controller.flipX.value;
|
||||||
|
},
|
||||||
|
text: " 左右翻转 ",
|
||||||
|
selectStatus: widget.controller.flipX.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
1 => Obx(
|
||||||
|
() => ActionRowLineItem(
|
||||||
|
icon: Transform.rotate(
|
||||||
|
angle: pi / 2,
|
||||||
|
child: Icon(
|
||||||
|
Icons.flip,
|
||||||
|
size: 13,
|
||||||
|
color: widget.controller.flipY.value
|
||||||
|
? Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSecondaryContainer
|
||||||
|
: Theme.of(context).colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
widget.controller.flipY.value =
|
||||||
|
!widget.controller.flipY.value;
|
||||||
|
},
|
||||||
|
text: " 上下翻转 ",
|
||||||
|
selectStatus: widget.controller.flipY.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 => Obx(
|
||||||
|
() => ActionRowLineItem(
|
||||||
|
iconData: Icons.headphones,
|
||||||
|
onTap: widget.controller.setOnlyPlayAudio,
|
||||||
|
text: " 听视频 ",
|
||||||
|
selectStatus: widget.controller.onlyPlayAudio.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
3 => Obx(
|
||||||
|
() => ActionRowLineItem(
|
||||||
|
iconData: Icons.play_circle_outline,
|
||||||
|
onTap:
|
||||||
|
widget.controller.setContinuePlayInBackground,
|
||||||
|
text: " 后台播放 ",
|
||||||
|
selectStatus: widget
|
||||||
|
.controller.continuePlayInBackground.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
int() => throw UnimplementedError(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () => {Get.back(), showSetVideoQa()},
|
||||||
|
leading: const Icon(Icons.play_circle_outline, size: 20),
|
||||||
|
title: const Text('选择画质', style: titleStyle),
|
||||||
|
subtitle: Text(
|
||||||
|
'当前画质 ${widget.videoDetailCtr.currentVideoQa.description}',
|
||||||
|
style: subTitleStyle),
|
||||||
|
),
|
||||||
|
if (widget.videoDetailCtr.currentAudioQa != null)
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () => {Get.back(), showSetAudioQa()},
|
||||||
|
leading: const Icon(Icons.album_outlined, size: 20),
|
||||||
|
title: const Text('选择音质', style: titleStyle),
|
||||||
|
subtitle: Text(
|
||||||
|
'当前音质 ${widget.videoDetailCtr.currentAudioQa!.description}',
|
||||||
|
style: subTitleStyle),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () => {Get.back(), showSetDecodeFormats()},
|
||||||
|
leading: const Icon(Icons.av_timer_outlined, size: 20),
|
||||||
|
title: const Text('解码格式', style: titleStyle),
|
||||||
|
subtitle: Text(
|
||||||
|
'当前解码格式 ${widget.videoDetailCtr.currentDecodeFormats.description}',
|
||||||
|
style: subTitleStyle),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () => {Get.back(), showSetRepeat()},
|
||||||
|
leading: const Icon(Icons.repeat, size: 20),
|
||||||
|
title: const Text('播放顺序', style: titleStyle),
|
||||||
|
subtitle: Text(widget.controller.playRepeat.description,
|
||||||
|
style: subTitleStyle),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () => {Get.back(), showSetDanmaku()},
|
||||||
|
leading: const Icon(Icons.subtitles_outlined, size: 20),
|
||||||
|
title: const Text('弹幕/字幕设置', style: titleStyle),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text('播放信息', style: titleStyle),
|
||||||
|
leading: const Icon(Icons.info_outline, size: 20),
|
||||||
|
onTap: () {
|
||||||
|
Player? player = widget.controller.videoPlayerController;
|
||||||
|
if (player == null) {
|
||||||
|
SmartDialog.showToast('播放器未初始化');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('播放信息'),
|
||||||
|
content: SizedBox(
|
||||||
|
width: double.maxFinite,
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("Resolution"),
|
||||||
|
subtitle: Text(
|
||||||
|
'${player.state.width}x${player.state.height}'),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'Resolution\n${player.state.width}x${player.state.height}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("VideoParams"),
|
||||||
|
subtitle:
|
||||||
|
Text(player.state.videoParams.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'VideoParams\n${player.state.videoParams}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("AudioParams"),
|
||||||
|
subtitle:
|
||||||
|
Text(player.state.audioParams.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'AudioParams\n${player.state.audioParams}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("Media"),
|
||||||
|
subtitle:
|
||||||
|
Text(player.state.playlist.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'Media\n${player.state.playlist}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("AudioTrack"),
|
||||||
|
subtitle:
|
||||||
|
Text(player.state.track.audio.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'AudioTrack\n${player.state.track.audio}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("VideoTrack"),
|
||||||
|
subtitle:
|
||||||
|
Text(player.state.track.video.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'VideoTrack\n${player.state.track.audio}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("pitch"),
|
||||||
|
subtitle:
|
||||||
|
Text(player.state.pitch.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'pitch\n${player.state.pitch}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("rate"),
|
||||||
|
subtitle:
|
||||||
|
Text(player.state.rate.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'rate\n${player.state.rate}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("AudioBitrate"),
|
||||||
|
subtitle: Text(
|
||||||
|
player.state.audioBitrate.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'AudioBitrate\n${player.state.audioBitrate}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: const Text("Volume"),
|
||||||
|
subtitle:
|
||||||
|
Text(player.state.volume.toString()),
|
||||||
|
onTap: () {
|
||||||
|
Utils.copyText(
|
||||||
|
'Volume\n${player.state.volume}',
|
||||||
|
needToast: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
child: Text(
|
||||||
|
'确定',
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
Theme.of(context).colorScheme.outline),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () {
|
||||||
|
if (widget.videoDetailCtr.userInfo == null) {
|
||||||
|
SmartDialog.showToast('账号未登录');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Get.back();
|
||||||
|
Get.toNamed('/webview', parameters: {
|
||||||
|
'url':
|
||||||
|
'https://www.bilibili.com/appeal/?avid=${IdUtils.bv2av(widget.videoDetailCtr.bvid)}&bvid=${widget.videoDetailCtr.bvid}'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
leading: const Icon(Icons.error_outline, size: 20),
|
||||||
|
title: const Text('举报', style: titleStyle),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 14),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -619,7 +583,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 10),
|
||||||
const Center(child: Text('定时关闭', style: titleStyle)),
|
const Center(child: Text('定时关闭', style: titleStyle)),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
...[
|
...[
|
||||||
@@ -1149,8 +1113,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
Get.toNamed('/danmakuBlock',
|
Get.toNamed('/danmakuBlock',
|
||||||
arguments: widget.controller)
|
arguments: widget.controller)
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text("屏蔽管理(${widget.controller.filterCount})")),
|
||||||
"屏蔽管理(${widget.controller.filterCount})")),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
|
|||||||
Reference in New Issue
Block a user