v1.0.1
This commit is contained in:
97
lib/modules/user/settings/settings_controller.dart
Normal file
97
lib/modules/user/settings/settings_controller.dart
Normal file
@@ -0,0 +1,97 @@
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_dmzj/services/app_settings_service.dart';
|
||||
import 'package:flutter_dmzj/services/local_storage_service.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class SettingsController extends GetxController {
|
||||
final settings = AppSettingsService.instance;
|
||||
var imageCacheSize = "正在计算缓存...".obs;
|
||||
var novelCacheSize = "正在计算缓存...".obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
getImageCachedSize();
|
||||
getNovelCachedSize();
|
||||
}
|
||||
|
||||
void getImageCachedSize() async {
|
||||
try {
|
||||
imageCacheSize.value = "正在计算缓存...";
|
||||
var bytes = await getCachedSizeBytes();
|
||||
imageCacheSize.value = "${(bytes / 1024 / 1024).toStringAsFixed(1)}MB";
|
||||
} catch (e) {
|
||||
imageCacheSize.value = "缓存计算失败";
|
||||
}
|
||||
}
|
||||
|
||||
void getNovelCachedSize() async {
|
||||
try {
|
||||
novelCacheSize.value = "正在计算缓存...";
|
||||
var bytes = await LocalStorageService.instance.getNovelCacheSize();
|
||||
novelCacheSize.value = "${(bytes / 1024 / 1024).toStringAsFixed(1)}MB";
|
||||
} catch (e) {
|
||||
novelCacheSize.value = "缓存计算失败";
|
||||
}
|
||||
}
|
||||
|
||||
void cleanImageCache() async {
|
||||
var result = await clearDiskCachedImages();
|
||||
if (!result) {
|
||||
SmartDialog.showToast("清除失败");
|
||||
}
|
||||
getImageCachedSize();
|
||||
}
|
||||
|
||||
void cleanNovelCache() async {
|
||||
var result = await LocalStorageService.instance.cleanNovelCacheSize();
|
||||
if (!result) {
|
||||
SmartDialog.showToast("清除失败");
|
||||
}
|
||||
getNovelCachedSize();
|
||||
}
|
||||
|
||||
void setDownloadComicTask() {
|
||||
Get.dialog(
|
||||
SimpleDialog(
|
||||
title: const Text("漫画最大任务数"),
|
||||
children: [0, 1, 2, 3, 4, 5]
|
||||
.map(
|
||||
(e) => RadioListTile<int>(
|
||||
title: Text(e == 0 ? "无限制" : "$e个"),
|
||||
value: e,
|
||||
groupValue: settings.downloadComicTaskCount.value,
|
||||
onChanged: (e) {
|
||||
Get.back();
|
||||
settings.setDownloadComicTaskCount(e ?? 0);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void setDownloadNovelTask() {
|
||||
Get.dialog(
|
||||
SimpleDialog(
|
||||
title: const Text("小说最大任务数"),
|
||||
children: [0, 1, 2, 3, 4, 5]
|
||||
.map(
|
||||
(e) => RadioListTile<int>(
|
||||
title: Text(e == 0 ? "无限制" : "$e个"),
|
||||
value: e,
|
||||
groupValue: settings.downloadNovelTaskCount.value,
|
||||
onChanged: (e) {
|
||||
Get.back();
|
||||
settings.setDownloadNovelTaskCount(e ?? 0);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
529
lib/modules/user/settings/settings_page.dart
Normal file
529
lib/modules/user/settings/settings_page.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user