This commit is contained in:
2026-03-07 17:24:59 +08:00
parent 4418ebecac
commit b0ec8ab4bd
417 changed files with 42546 additions and 2 deletions

View File

@@ -0,0 +1,529 @@
import 'dart:io';
import 'package:fluent_ui/fluent_ui.dart' as fluent;
import 'package:flutter/material.dart';
import 'package:flutter_dmzj/app/app_color.dart';
import 'package:flutter_dmzj/app/app_style.dart';
import 'package:flutter_dmzj/app/platform_utils.dart';
import 'package:flutter_dmzj/modules/user/settings/settings_controller.dart';
import 'package:get/get.dart';
import 'package:remixicon/remixicon.dart';
class SettingsPage extends StatelessWidget {
final int index;
SettingsPage({required this.index, super.key});
final controller = Get.put<SettingsController>(SettingsController());
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 4,
initialIndex: index,
child: Scaffold(
appBar: AppBar(
title: Container(
alignment: Alignment.center,
padding: const EdgeInsets.only(right: 56),
child: TabBar(
isScrollable: true,
tabAlignment: TabAlignment.start,
indicatorSize: TabBarIndicatorSize.label,
indicatorColor: Theme.of(context).colorScheme.primary,
labelColor: Theme.of(context).colorScheme.primary,
unselectedLabelColor:
Get.isDarkMode ? Colors.white70 : Colors.black87,
tabs: const [
Tab(text: "常规"),
Tab(text: "漫画"),
Tab(text: "小说"),
Tab(text: "下载"),
],
),
),
),
body: TabBarView(
children: [
buildGeneralSettings(),
buildComicSettings(),
buildNovelSettings(),
buildDownloadSettings(),
],
),
),
);
}
Widget buildGeneralSettings() {
return Obx(
() => ListView(
padding: AppStyle.edgeInsetsA12,
children: [
buildToggle(
value: controller.settings.useDynamicColor.value,
onChanged: (e) {
controller.settings.setUseDynamicColor(e);
},
title: "使用MD动态取色",
subtitle: "关闭后使用固定主题色 #4196f9",
),
ListTile(
title: const Text("清除图片缓存"),
subtitle: Text(controller.imageCacheSize.value),
trailing: OutlinedButton(
onPressed: () {
controller.cleanImageCache();
},
child: const Text("清除"),
),
),
ListTile(
title: const Text("清除小说缓存"),
subtitle: Text(controller.novelCacheSize.value),
trailing: OutlinedButton(
onPressed: () {},
child: const Text("清除"),
),
),
// SwitchListTile(
// value: controller.settings.comicSearchUseWebApi.value,
// onChanged: (e) {
// controller.settings.setComicSearchUseWebApi(e);
// },
// title: const Text("使用Web接口搜索漫画"),
// subtitle: const Text("开启后可以搜索到更多漫画"),
// ),
buildToggle(
value: controller.settings.useSystemFontSize.value,
onChanged: (e) {
controller.settings.setUseSystemFontSize(e);
},
title: "字体大小跟随系统",
subtitle: "开启可能会有布局错乱",
),
buildToggle(
value: controller.settings.collectHideComic.value,
onChanged: (e) {
controller.settings.setCollectHideComic(e);
},
title: "自动收藏神隐漫画",
subtitle: "浏览神隐漫画时自动添加到本机收藏",
),
ListTile(
title: const Text("代理地址"),
subtitle: TextField(
controller: TextEditingController(text: controller.settings.proxyAddress.value),
decoration: const InputDecoration(
hintText: "仅支持http协议,重启生效 eg:127.0.0.1:7890",
),
onSubmitted: (e){
controller.settings.setProxyAddress(e);
},
),
)
],
),
);
}
Widget buildComicSettings() {
return Obx(
() => ListView(
padding: AppStyle.edgeInsetsA12,
children: [
buildToggle(
value: controller.settings.comicReaderHD.value,
onChanged: (e) {
controller.settings.setComicReaderHD(e);
},
title: "优先加载高清图",
subtitle: "部分单行本可能未分页",
),
ListTile(
title: const Text("阅读方向"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
buildSelectedButton(
onTap: () {
controller.settings.setComicReaderDirection(0);
},
selected: controller.settings.comicReaderDirection.value == 0,
child: const Icon(Remix.arrow_right_line),
),
AppStyle.hGap8,
buildSelectedButton(
onTap: () {
controller.settings.setComicReaderDirection(2);
},
selected: controller.settings.comicReaderDirection.value == 2,
child: const Icon(Remix.arrow_left_line),
),
AppStyle.hGap8,
buildSelectedButton(
onTap: () {
controller.settings.setComicReaderDirection(1);
},
selected: controller.settings.comicReaderDirection.value == 1,
child: const Icon(Remix.arrow_down_line),
)
],
),
),
buildToggle(
value: controller.settings.comicReaderLeftHandMode.value,
onChanged: (e) {
controller.settings.setComicReaderLeftHandMode(e);
},
title: "操作反转",
subtitle: "点击左侧下一页,右侧上一页",
),
buildToggle(
value: controller.settings.comicReaderFullScreen.value,
onChanged: (e) {
controller.settings.setComicReaderFullScreen(e);
},
title: "全屏阅读",
),
buildToggle(
value: controller.settings.comicReaderShowStatus.value,
onChanged: (e) {
controller.settings.setComicReaderShowStatus(e);
},
title: "显示状态信息",
),
buildToggle(
value: controller.settings.comicReaderShowViewPoint.value,
onChanged: (e) {
controller.settings.setComicReaderShowViewPoint(e);
},
title: "显示吐槽",
),
buildToggle(
value: controller.settings.comicReaderOldViewPoint.value,
onChanged: (e) {
controller.settings.setComicReaderOldViewPoint(e);
},
title: "旧版吐槽",
),
buildToggle(
value: controller.settings.comicReaderPageAnimation.value,
onChanged: (e) {
controller.settings.setComicReaderPageAnimation(e);
},
title: "翻页动画",
),
],
),
);
}
Widget buildNovelSettings() {
return Obx(
() => ListView(
padding: AppStyle.edgeInsetsA12,
children: [
ListTile(
title: const Text("阅读方向"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
buildSelectedButton(
onTap: () {
controller.settings.setNovelReaderDirection(0);
},
selected: controller.settings.novelReaderDirection.value == 0,
child: const Icon(Remix.arrow_right_line),
),
AppStyle.hGap8,
buildSelectedButton(
onTap: () {
controller.settings.setNovelReaderDirection(2);
},
selected: controller.settings.novelReaderDirection.value == 2,
child: const Icon(Remix.arrow_left_line),
),
AppStyle.hGap8,
buildSelectedButton(
onTap: () {
controller.settings.setNovelReaderDirection(1);
},
selected: controller.settings.novelReaderDirection.value == 1,
child: const Icon(Remix.arrow_down_line),
)
],
),
),
buildToggle(
value: controller.settings.novelReaderLeftHandMode.value,
onChanged: (e) {
controller.settings.setNovelReaderLeftHandMode(e);
},
title: "操作反转",
subtitle: "点击左侧下一页,右侧上一页",
),
// SwitchListTile(
// value: settings.novelReaderFullScreen.value,
// onChanged: (e) {
// settings.setNovelReaderFullScreen(e);
// },
// title: const Text("全屏阅读"),
// ),
buildToggle(
value: controller.settings.novelReaderShowStatus.value,
onChanged: (e) {
controller.settings.setNovelReaderShowStatus(e);
},
title: "显示状态信息",
),
buildToggle(
value: controller.settings.novelReaderPageAnimation.value,
onChanged: (e) {
controller.settings.setNovelReaderPageAnimation(e);
},
title: "翻页动画",
),
ListTile(
title: const Text("字体大小"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
OutlinedButton(
onPressed: () {
controller.settings.setNovelReaderFontSize(
controller.settings.novelReaderFontSize.value + 1,
);
},
child: const Icon(
Icons.add,
),
),
AppStyle.hGap12,
Text("${controller.settings.novelReaderFontSize.value}"),
AppStyle.hGap12,
OutlinedButton(
onPressed: () {
controller.settings.setNovelReaderFontSize(
controller.settings.novelReaderFontSize.value - 1,
);
},
child: const Icon(
Icons.remove,
),
),
],
),
),
ListTile(
title: const Text("行距"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
OutlinedButton(
onPressed: () {
controller.settings.setNovelReaderLineSpacing(
controller.settings.novelReaderLineSpacing.value + 0.1,
);
},
child: const Icon(
Icons.add,
),
),
AppStyle.hGap12,
Text((controller.settings.novelReaderLineSpacing.value)
.toStringAsFixed(1)),
AppStyle.hGap12,
OutlinedButton(
onPressed: () {
controller.settings.setNovelReaderLineSpacing(
controller.settings.novelReaderLineSpacing.value - 0.1,
);
},
child: const Icon(
Icons.remove,
),
),
],
),
),
ListTile(
title: const Text("阅读主题"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: AppColor.novelThemes.keys
.map(
(e) => GestureDetector(
onTap: () {
controller.settings.setNovelReaderTheme(e);
},
child: Container(
margin: AppStyle.edgeInsetsL8,
height: 36,
width: 36,
decoration: BoxDecoration(
color: AppColor.novelThemes[e]!.first,
borderRadius: AppStyle.radius24,
),
child: Visibility(
visible:
AppColor.novelThemes.keys.toList().indexOf(e) ==
controller.settings.novelReaderTheme.value,
child: Icon(
Icons.check,
color: AppColor.novelThemes[e]!.last,
),
),
),
),
)
.toList(),
),
),
Container(
margin: AppStyle.edgeInsetsV12,
padding: AppStyle.edgeInsetsA8,
decoration: BoxDecoration(
borderRadius: AppStyle.radius4,
color: AppColor
.novelThemes[controller.settings.novelReaderTheme]!.first,
),
child: Text(
"""这是一段测试文字,可以预览上面的设置效果。
  晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。
  林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐……""",
//不需要跟随系统
textScaler: const TextScaler.linear(1.0),
style: TextStyle(
fontSize:
controller.settings.novelReaderFontSize.value.toDouble(),
height: controller.settings.novelReaderLineSpacing.value,
color: AppColor
.novelThemes[controller.settings.novelReaderTheme]!.last,
),
),
),
],
),
);
}
Widget buildDownloadSettings() {
return Obx(
() => ListView(
padding: AppStyle.edgeInsetsA12,
children: [
buildToggle(
value: controller.settings.downloadAllowCellular.value,
onChanged: (e) {
controller.settings.setDownloadAllowCellular(e);
},
title: "允许使用流量下载",
),
ListTile(
title: const Text("漫画最大任务数"),
onTap: () {
controller.setDownloadComicTask();
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
controller.settings.downloadComicTaskCount.value == 0
? "无限制"
: controller.settings.downloadComicTaskCount.toString(),
),
AppStyle.hGap4,
const Icon(
Icons.chevron_right,
color: Colors.grey,
),
],
),
),
ListTile(
title: const Text("小说最大任务数"),
onTap: () {
controller.setDownloadNovelTask();
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
controller.settings.downloadNovelTaskCount.value == 0
? "无限制"
: controller.settings.downloadNovelTaskCount.toString(),
),
AppStyle.hGap4,
const Icon(
Icons.chevron_right,
color: Colors.grey,
),
],
),
),
],
),
);
}
Widget buildSelectedButton(
{required Widget child, bool selected = false, Function()? onTap}) {
final primary = Get.theme.colorScheme.primary;
return OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: selected ? primary : Colors.grey,
side: BorderSide(
color: selected ? primary : Colors.grey,
),
),
onPressed: onTap,
child: child,
);
}
/// 平台自适应开关控件
/// Windows使用Fluent ToggleSwitch其他平台使用Material SwitchListTile
Widget buildToggle({
required String title,
required bool value,
required ValueChanged<bool> onChanged,
String? subtitle,
}) {
if (PlatformUtils.isWindows) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title,
style: Get.textTheme.bodyMedium),
if (subtitle != null)
Text(subtitle,
style: Get.textTheme.bodySmall
?.copyWith(color: Colors.grey)),
],
),
),
fluent.FluentTheme(
data: PlatformUtils.getFluentTheme(Get.context!),
child: fluent.ToggleSwitch(
checked: value,
onChanged: onChanged,
),
),
],
),
);
}
return SwitchListTile(
value: value,
onChanged: onChanged,
title: Text(title),
subtitle: subtitle != null ? Text(subtitle) : null,
);
}
}