Files
PiliPlus/lib/pages/setting/models/play_settings.dart
2026-06-08 23:38:31 +08:00

191 lines
5.3 KiB
Dart

import 'dart:io' show Platform;
import 'package:PiliPlus/common/widgets/custom_icon.dart';
import 'package:PiliPlus/pages/setting/models/model.dart';
import 'package:PiliPlus/pages/setting/widgets/slider_dialog.dart';
import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart';
import 'package:PiliPlus/utils/extension/num_ext.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_key.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
List<SettingsModel> get playSettings => [
const SwitchModel(
title: '弹幕开关',
subtitle: '是否展示弹幕',
leading: Icon(CustomIcons.dm_settings),
setKey: SettingBoxKey.enableShowDanmaku,
defaultVal: true,
),
NormalModel(
onTap: (context, setState) => Get.toNamed('/playSpeedSet'),
leading: const Icon(Icons.speed_outlined),
title: '倍速设置',
subtitle: '设置视频播放速度',
),
if (Platform.isAndroid)
NormalModel(
onTap: _showAngleDegreesDialog,
leading: const Icon(MdiIcons.angleAcute),
title: '倾斜角度阈值',
getSubtitle: () => '当前:「${Pref.angleDegrees}°」',
),
SwitchModel(
title: '全屏显示电池电量',
leading: const Icon(Icons.battery_3_bar),
setKey: SettingBoxKey.showBatteryLevel,
defaultVal: PlatformUtils.isMobile,
),
if (PlatformUtils.isMobile)
NormalModel(
title: '播放器音量',
leading: const Icon(Icons.volume_up),
getSubtitle: () => '当前:「${Pref.playerVolume.toStringAsFixed(0)}%」',
onTap: showPlayerVolumeDialog,
)
else
NormalModel(
title: '最高音量',
leading: const Icon(Icons.volume_up),
getSubtitle: () => '当前:「${(Pref.maxVolume * 100).toStringAsFixed(0)}%」',
onTap: _showMaxVolumeDialog,
),
getVideoFilterSelectModel(
title: '双击快进/快退时长',
suffix: 's',
key: SettingBoxKey.fastForBackwardDuration,
values: [5, 10, 15],
defaultValue: 10,
isFilter: false,
),
getVideoFilterSelectModel(
title: '滑动快进/快退时长',
subtitle: '从播放器一端滑到另一端的快进/快退时长',
suffix: 's',
key: SettingBoxKey.sliderDuration,
values: [25, 50, 90, 100],
defaultValue: 90,
isFilter: false,
),
SwitchModel(
title: '启用键盘控制',
leading: const Icon(Icons.keyboard_alt_outlined),
setKey: SettingBoxKey.keyboardControl,
defaultVal: PlatformUtils.isDesktop,
),
if (PlatformUtils.isMobile)
const SwitchModel(
title: '后台播放',
subtitle: '进入后台时继续播放',
leading: Icon(Icons.motion_photos_pause_outlined),
setKey: SettingBoxKey.continuePlayInBackground,
defaultVal: false,
),
const SwitchModel(
title: '观看人数',
subtitle: '展示同时在看人数',
leading: Icon(Icons.people_outlined),
setKey: SettingBoxKey.enableOnlineTotal,
defaultVal: false,
),
PopupModel(
title: '播放顺序',
leading: const Icon(Icons.repeat),
value: () => Pref.playRepeat,
items: PlayRepeat.values,
onSelected: (value, setState) => GStorage.video
.put(VideoBoxKey.playRepeat, value.index)
.whenComplete(setState),
),
];
Future<void> _showAngleDegreesDialog(
BuildContext context,
VoidCallback setState,
) async {
final res = await showDialog<double>(
context: context,
builder: (context) => SliderDialog(
title: const Text('倾斜角度阈值'),
min: 10.0,
max: 90.0,
divisions: 80,
precise: 0,
value: Pref.angleDegrees.toDouble(),
suffix: '°',
),
);
if (res != null) {
await GStorage.setting.put(SettingBoxKey.angleDegrees, res.toInt());
setState();
}
}
Future<void> showPlayerVolumeDialog(
BuildContext context,
VoidCallback setState, {
ValueChanged<double>? onChanged,
}) {
return showVolumeDialog(
context,
title: const Text('播放器音量'),
value: Pref.playerVolume,
onChanged: (value) => GStorage.setting
.put(SettingBoxKey.playerVolume, value)
.whenComplete(() {
setState();
onChanged?.call(value);
}),
);
}
Future<void> _showMaxVolumeDialog(
BuildContext context,
VoidCallback setState,
) {
return showVolumeDialog(
context,
title: const Text('最高音量'),
value: Pref.maxVolume * 100,
onChanged: (rawValue) {
final maxVolume = (rawValue / 100).toPrecision(2);
if (Pref.desktopVolume > maxVolume) {
GStorage.setting.put(SettingBoxKey.desktopVolume, maxVolume);
}
GStorage.setting
.put(SettingBoxKey.maxVolume, maxVolume)
.whenComplete(setState);
},
);
}
const kMinVolume = 100.0;
const kMaxVolume = 300.0;
Future<void> showVolumeDialog(
BuildContext context, {
required Widget title,
required double value,
required ValueChanged<double> onChanged,
}) async {
final res = await showDialog<double>(
context: context,
builder: (context) => SliderDialog(
title: title,
min: kMinVolume,
max: kMaxVolume,
divisions: 40,
precise: 0,
value: value,
suffix: '%',
),
);
if (res != null) {
onChanged(res);
}
}