mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-15 13:43:56 +08:00
@@ -1,15 +1,9 @@
|
||||
import 'dart:io';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:PiliPlus/common/widgets/color_palette.dart';
|
||||
import 'package:PiliPlus/common/widgets/scale_app.dart';
|
||||
import 'package:PiliPlus/common/widgets/stateful_builder.dart';
|
||||
import 'package:PiliPlus/models/common/bar_hide_type.dart';
|
||||
import 'package:PiliPlus/models/common/dynamic/dynamic_badge_mode.dart';
|
||||
import 'package:PiliPlus/models/common/dynamic/up_panel_position.dart';
|
||||
import 'package:PiliPlus/models/common/home_tab_type.dart';
|
||||
import 'package:PiliPlus/models/common/msg/msg_unread_type.dart';
|
||||
import 'package:PiliPlus/models/common/nav_bar_config.dart';
|
||||
import 'package:PiliPlus/models/common/theme/theme_color_type.dart';
|
||||
import 'package:PiliPlus/models/common/theme/theme_type.dart';
|
||||
import 'package:PiliPlus/pages/main/controller.dart';
|
||||
@@ -20,13 +14,9 @@ import 'package:PiliPlus/pages/setting/widgets/multi_select_dialog.dart';
|
||||
import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart';
|
||||
import 'package:PiliPlus/pages/setting/widgets/slider_dialog.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
|
||||
import 'package:PiliPlus/utils/extension/file_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/get_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/num_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
||||
import 'package:PiliPlus/utils/global_data.dart';
|
||||
import 'package:PiliPlus/utils/path_utils.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';
|
||||
@@ -36,26 +26,8 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
List<SettingsModel> get styleSettings => [
|
||||
if (PlatformUtils.isDesktop) ...[
|
||||
const SwitchModel(
|
||||
title: '显示窗口标题栏',
|
||||
leading: Icon(Icons.window),
|
||||
setKey: SettingBoxKey.showWindowTitleBar,
|
||||
defaultVal: true,
|
||||
needReboot: true,
|
||||
),
|
||||
const SwitchModel(
|
||||
title: '显示托盘图标',
|
||||
leading: Icon(Icons.donut_large_rounded),
|
||||
setKey: SettingBoxKey.showTrayIcon,
|
||||
defaultVal: true,
|
||||
needReboot: true,
|
||||
),
|
||||
],
|
||||
if (Platform.isLinux) _useSSDModel(),
|
||||
SwitchModel(
|
||||
title: '横屏适配',
|
||||
subtitle: '启用横屏布局与逻辑,平板、折叠屏等可开启;建议全屏方向设为【不改变当前方向】',
|
||||
@@ -70,12 +42,6 @@ List<SettingsModel> get styleSettings => [
|
||||
}
|
||||
},
|
||||
),
|
||||
NormalModel(
|
||||
title: '界面缩放',
|
||||
getSubtitle: () => '当前缩放比例:${Pref.uiScale.toStringAsFixed(2)}',
|
||||
leading: const Icon(Icons.zoom_in_outlined),
|
||||
onTap: _showUiScaleDialog,
|
||||
),
|
||||
NormalModel(
|
||||
title: '页面过渡动画',
|
||||
leading: const Icon(Icons.animation),
|
||||
@@ -96,18 +62,6 @@ List<SettingsModel> get styleSettings => [
|
||||
'当前: 主页${Pref.recommendCardWidth.toInt()}dp 其他${Pref.smallCardWidth.toInt()}dp,屏幕宽度:${MediaQuery.widthOf(Get.context!).toPrecision(2)}dp。宽度越小列数越多。',
|
||||
onTap: _showCardWidthDialog,
|
||||
),
|
||||
const SwitchModel(
|
||||
title: '播放页移除安全边距',
|
||||
leading: Icon(Icons.fit_screen_outlined),
|
||||
setKey: SettingBoxKey.removeSafeArea,
|
||||
defaultVal: false,
|
||||
),
|
||||
const SwitchModel(
|
||||
title: '视频播放页使用深色主题',
|
||||
leading: Icon(Icons.dark_mode_outlined),
|
||||
setKey: SettingBoxKey.darkVideoPage,
|
||||
defaultVal: false,
|
||||
),
|
||||
SwitchModel(
|
||||
title: '动态页启用瀑布流',
|
||||
subtitle: '关闭会显示为单列',
|
||||
@@ -122,20 +76,6 @@ List<SettingsModel> get styleSettings => [
|
||||
getSubtitle: () => '当前:${Pref.upPanelPosition.label}',
|
||||
onTap: _showUpPosDialog,
|
||||
),
|
||||
const SwitchModel(
|
||||
title: '动态页显示所有已关注UP主',
|
||||
leading: Icon(Icons.people_alt_outlined),
|
||||
setKey: SettingBoxKey.dynamicsShowAllFollowedUp,
|
||||
defaultVal: false,
|
||||
needReboot: true,
|
||||
),
|
||||
const SwitchModel(
|
||||
title: '动态页展开正在直播UP列表',
|
||||
leading: Icon(Icons.live_tv),
|
||||
setKey: SettingBoxKey.expandDynLivePanel,
|
||||
defaultVal: false,
|
||||
needReboot: true,
|
||||
),
|
||||
NormalModel(
|
||||
title: '动态未读标记',
|
||||
leading: const Icon(Icons.motion_photos_on_outlined),
|
||||
@@ -155,28 +95,6 @@ List<SettingsModel> get styleSettings => [
|
||||
getSubtitle: () =>
|
||||
'当前消息类型:${Pref.msgUnReadTypeV2.map((item) => item.title).join('、')}',
|
||||
),
|
||||
NormalModel(
|
||||
onTap: _showBarHideTypeDialog,
|
||||
title: '顶/底栏收起类型',
|
||||
leading: const Icon(MdiIcons.arrowExpandVertical),
|
||||
getSubtitle: () => '当前:${Pref.barHideType.label}',
|
||||
),
|
||||
SwitchModel(
|
||||
title: '首页顶栏收起',
|
||||
subtitle: '首页列表滑动时,收起顶栏',
|
||||
leading: const Icon(Icons.vertical_align_top_outlined),
|
||||
setKey: SettingBoxKey.hideTopBar,
|
||||
defaultVal: PlatformUtils.isMobile,
|
||||
needReboot: true,
|
||||
),
|
||||
SwitchModel(
|
||||
title: '首页底栏收起',
|
||||
subtitle: '首页列表滑动时,收起底栏',
|
||||
leading: const Icon(Icons.vertical_align_bottom_outlined),
|
||||
setKey: SettingBoxKey.hideBottomBar,
|
||||
defaultVal: PlatformUtils.isMobile,
|
||||
needReboot: true,
|
||||
),
|
||||
NormalModel(
|
||||
onTap: (context, setState) => _showQualityDialog(
|
||||
context: context,
|
||||
@@ -220,17 +138,6 @@ List<SettingsModel> get styleSettings => [
|
||||
title: '主题模式',
|
||||
getSubtitle: () => '当前模式:${Pref.themeType.desc}',
|
||||
),
|
||||
SwitchModel(
|
||||
leading: const Icon(Icons.invert_colors),
|
||||
title: '纯黑主题',
|
||||
setKey: SettingBoxKey.isPureBlackTheme,
|
||||
defaultVal: false,
|
||||
onChanged: (value) {
|
||||
if (ThemeUtils.isDarkMode || Pref.darkVideoPage) {
|
||||
Get.updateMyAppTheme();
|
||||
}
|
||||
},
|
||||
),
|
||||
NormalModel(
|
||||
onTap: (context, setState) => Get.toNamed('/colorSetting'),
|
||||
leading: const Icon(Icons.color_lens_outlined),
|
||||
@@ -248,65 +155,11 @@ List<SettingsModel> get styleSettings => [
|
||||
),
|
||||
),
|
||||
),
|
||||
NormalModel(
|
||||
leading: const Icon(Icons.home_outlined),
|
||||
title: '默认启动页',
|
||||
getSubtitle: () => '当前启动页:${Pref.defaultHomePage.label}',
|
||||
onTap: _showDefHomeDialog,
|
||||
),
|
||||
const NormalModel(
|
||||
title: '滑动动画弹簧参数',
|
||||
leading: Icon(Icons.chrome_reader_mode_outlined),
|
||||
onTap: _showSpringDialog,
|
||||
),
|
||||
NormalModel(
|
||||
onTap: (context, setState) async {
|
||||
final res = await Get.toNamed('/fontSizeSetting');
|
||||
if (res != null) {
|
||||
setState();
|
||||
}
|
||||
},
|
||||
title: '字体大小',
|
||||
leading: const Icon(Icons.format_size_outlined),
|
||||
getSubtitle: () {
|
||||
final scale = Pref.defaultTextScale;
|
||||
return scale == 1.0 ? '默认' : scale.toString();
|
||||
},
|
||||
),
|
||||
NormalModel(
|
||||
onTap: (context, setState) => Get.toNamed(
|
||||
'/barSetting',
|
||||
arguments: {
|
||||
'key': SettingBoxKey.tabBarSort,
|
||||
'defaultBars': HomeTabType.values,
|
||||
'title': '首页标签页',
|
||||
},
|
||||
),
|
||||
title: '首页标签页',
|
||||
subtitle: '删除或调换首页标签页',
|
||||
leading: const Icon(Icons.toc_outlined),
|
||||
),
|
||||
NormalModel(
|
||||
onTap: (context, setState) => Get.toNamed(
|
||||
'/barSetting',
|
||||
arguments: {
|
||||
'key': SettingBoxKey.navBarSort,
|
||||
'defaultBars': NavigationBarType.values,
|
||||
'title': 'Navbar',
|
||||
},
|
||||
),
|
||||
title: 'Navbar编辑',
|
||||
subtitle: '删除或调换Navbar',
|
||||
leading: const Icon(Icons.toc_outlined),
|
||||
),
|
||||
SwitchModel(
|
||||
title: '返回时直接退出',
|
||||
subtitle: '开启后在主页任意tab按返回键都直接退出,关闭则先回到Navbar的第一个tab',
|
||||
leading: const Icon(Icons.exit_to_app_outlined),
|
||||
setKey: SettingBoxKey.directExitOnBack,
|
||||
defaultVal: false,
|
||||
onChanged: (value) => Get.find<MainController>().directExitOnBack = value,
|
||||
),
|
||||
];
|
||||
|
||||
void _showQualityDialog({
|
||||
@@ -334,107 +187,6 @@ void _showQualityDialog({
|
||||
});
|
||||
}
|
||||
|
||||
void _showUiScaleDialog(
|
||||
BuildContext context,
|
||||
VoidCallback setState,
|
||||
) {
|
||||
const minUiScale = 0.5;
|
||||
const maxUiScale = 2.0;
|
||||
|
||||
double uiScale = Pref.uiScale;
|
||||
final textController = TextEditingController(
|
||||
text: uiScale.toStringAsFixed(2),
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('界面缩放'),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 12),
|
||||
content: StatefulBuilder(
|
||||
onDispose: textController.dispose,
|
||||
builder: (context, setDialogState) => Column(
|
||||
spacing: 20,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Slider(
|
||||
padding: .zero,
|
||||
value: uiScale,
|
||||
min: minUiScale,
|
||||
max: maxUiScale,
|
||||
secondaryTrackValue: 1.0,
|
||||
divisions: ((maxUiScale - minUiScale) * 20).toInt(),
|
||||
label: textController.text,
|
||||
onChanged: (value) => setDialogState(() {
|
||||
uiScale = value.toPrecision(2);
|
||||
textController.text = uiScale.toStringAsFixed(2);
|
||||
}),
|
||||
),
|
||||
TextFormField(
|
||||
controller: textController,
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
decimal: true,
|
||||
),
|
||||
inputFormatters: [
|
||||
LengthLimitingTextInputFormatter(4),
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[\d.]+')),
|
||||
],
|
||||
decoration: const InputDecoration(
|
||||
labelText: '缩放比例',
|
||||
hintText: '0.50 - 2.00',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {
|
||||
final parsed = double.tryParse(value);
|
||||
if (parsed != null &&
|
||||
parsed >= minUiScale &&
|
||||
parsed <= maxUiScale) {
|
||||
setDialogState(() {
|
||||
uiScale = parsed;
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
GStorage.setting.delete(SettingBoxKey.uiScale).whenComplete(() {
|
||||
setState();
|
||||
Get.appUpdate();
|
||||
ScaledWidgetsFlutterBinding.instance.scaleFactor = 1.0;
|
||||
});
|
||||
},
|
||||
child: const Text('重置'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(color: ColorScheme.of(context).outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
GStorage.setting.put(SettingBoxKey.uiScale, uiScale).whenComplete(
|
||||
() {
|
||||
setState();
|
||||
Get.appUpdate();
|
||||
ScaledWidgetsFlutterBinding.instance.scaleFactor = uiScale;
|
||||
},
|
||||
);
|
||||
},
|
||||
child: const Text('确定'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showSpringDialog(BuildContext context, _) {
|
||||
final List<String> springDescription = Pref.springDescription
|
||||
.map((i) => i.toString())
|
||||
@@ -729,69 +481,3 @@ Future<void> _showThemeTypeDialog(
|
||||
setState();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showDefHomeDialog(
|
||||
BuildContext context,
|
||||
VoidCallback setState,
|
||||
) async {
|
||||
final res = await showDialog<NavigationBarType>(
|
||||
context: context,
|
||||
builder: (context) => SelectDialog<NavigationBarType>(
|
||||
title: '首页启动页',
|
||||
value: Pref.defaultHomePage,
|
||||
values: NavigationBarType.values.map((e) => (e, e.label)).toList(),
|
||||
),
|
||||
);
|
||||
if (res != null) {
|
||||
await GStorage.setting.put(SettingBoxKey.defaultHomePage, res.index);
|
||||
SmartDialog.showToast('设置成功,重启生效');
|
||||
setState();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showBarHideTypeDialog(
|
||||
BuildContext context,
|
||||
VoidCallback setState,
|
||||
) async {
|
||||
final res = await showDialog<BarHideType>(
|
||||
context: context,
|
||||
builder: (context) => SelectDialog<BarHideType>(
|
||||
title: '顶/底栏收起类型',
|
||||
value: Pref.barHideType,
|
||||
values: BarHideType.values.map((e) => (e, e.label)).toList(),
|
||||
),
|
||||
);
|
||||
if (res != null) {
|
||||
await GStorage.setting.put(SettingBoxKey.barHideType, res.index);
|
||||
SmartDialog.showToast('重启生效');
|
||||
setState();
|
||||
}
|
||||
}
|
||||
|
||||
NormalModel _useSSDModel() {
|
||||
final file = File(path.join(appSupportDirPath, 'use_ssd'));
|
||||
void onChanged(BuildContext context, VoidCallback setState) {
|
||||
(file.existsSync() ? file.tryDel() : file.create()).whenComplete(() {
|
||||
if (context.mounted) {
|
||||
setState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return NormalModel(
|
||||
title: '使用SSD(Server-Side Decoration)',
|
||||
leading: const Icon(Icons.web_asset),
|
||||
onTap: onChanged,
|
||||
getTrailing: (theme) => Builder(
|
||||
builder: (context) => Transform.scale(
|
||||
scale: 0.8,
|
||||
alignment: .centerRight,
|
||||
child: Switch(
|
||||
value: file.existsSync(),
|
||||
onChanged: (_) =>
|
||||
onChanged(context, (context as Element).markNeedsBuild),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user