Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-06-21 12:46:34 +08:00
parent 5f3f158932
commit 604d78ad6a
161 changed files with 4873 additions and 4770 deletions

View File

@@ -0,0 +1,221 @@
import 'package:PiliPlus/models/common/settings_type.dart';
import 'package:PiliPlus/pages/setting/widgets/normal_item.dart';
import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart';
import 'package:PiliPlus/pages/setting/widgets/switch_item.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show FilteringTextInputFormatter;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
extension SettingsModelExt on SettingsModel {
Widget get widget => switch (settingsType) {
SettingsType.normal => NormalItem(
title: title,
getTitle: getTitle,
subtitle: subtitle,
getSubtitle: getSubtitle,
setKey: setKey,
defaultVal: defaultVal,
onChanged: onChanged,
needReboot: needReboot,
leading: leading,
getTrailing: getTrailing,
onTap: onTap,
contentPadding: contentPadding,
titleStyle: titleStyle,
),
SettingsType.sw1tch => SetSwitchItem(
title: title,
subtitle: subtitle,
setKey: setKey,
defaultVal: defaultVal,
onChanged: onChanged,
needReboot: needReboot,
leading: leading,
onTap: onTap,
contentPadding: contentPadding,
titleStyle: titleStyle,
),
};
}
class SettingsModel {
final SettingsType settingsType;
final String? title;
final Function? getTitle;
final String? subtitle;
final Function? getSubtitle;
final String? setKey;
final bool? defaultVal;
final ValueChanged<bool>? onChanged;
final bool? needReboot;
final Widget? leading;
final Function? getTrailing;
final Function? onTap;
final EdgeInsetsGeometry? contentPadding;
final TextStyle? titleStyle;
SettingsModel({
required this.settingsType,
this.title,
this.getTitle,
this.subtitle,
this.getSubtitle,
this.setKey,
this.defaultVal,
this.onChanged,
this.needReboot,
this.leading,
this.getTrailing,
this.onTap,
this.contentPadding,
this.titleStyle,
});
}
SettingsModel getBanwordModel({
required BuildContext context,
required String title,
required String key,
required ValueChanged<RegExp> callback,
}) {
String banWord = GStorage.setting.get(key, defaultValue: '');
return SettingsModel(
settingsType: SettingsType.normal,
leading: const Icon(Icons.filter_alt_outlined),
title: title,
getSubtitle: () => banWord.isEmpty ? "点击添加" : banWord,
onTap: (setState) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(title),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('使用|隔开,如:尝试|测试'),
TextFormField(
autofocus: true,
initialValue: banWord,
textInputAction: TextInputAction.newline,
minLines: 1,
maxLines: 4,
onChanged: (value) => banWord = value,
)
],
),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'取消',
style:
TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
TextButton(
child: const Text('保存'),
onPressed: () async {
Get.back();
await GStorage.setting.put(key, banWord);
setState();
callback(RegExp(banWord, caseSensitive: false));
SmartDialog.showToast('已保存');
},
),
],
);
},
);
},
);
}
SettingsModel getVideoFilterSelectModel({
required BuildContext context,
required String title,
String? subtitle,
String? suffix,
required String key,
required List<int> values,
int defaultValue = 0,
bool isFilter = true,
ValueChanged<int>? onChanged,
}) {
assert(!isFilter || onChanged != null);
int value = GStorage.setting.get(key, defaultValue: defaultValue);
return SettingsModel(
settingsType: SettingsType.normal,
title: '$title${isFilter ? '过滤' : ''}',
leading: const Icon(Icons.timelapse_outlined),
subtitle: subtitle,
getSubtitle: subtitle == null
? () => isFilter
? '过滤掉$title小于$value${suffix ?? ""}」的视频'
: '当前$title:「$value${suffix ?? ""}'
: null,
onTap: (setState) async {
var result = await showDialog<int>(
context: context,
builder: (context) {
return SelectDialog<int>(
title: '选择$title${isFilter ? '0即不过滤' : ''}',
value: value,
values: (values
..addIf(!values.contains(value), value)
..sort())
.map((e) => (e, suffix == null ? e.toString() : '$e $suffix'))
.toList()
..add((-1, '自定义')));
},
);
if (result != null) {
if (result == -1 && context.mounted) {
await showDialog(
context: context,
builder: (context) {
String valueStr = '';
return AlertDialog(
title: Text('自定义$title'),
content: TextField(
autofocus: true,
onChanged: (value) => valueStr = value,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'\d+')),
],
decoration: InputDecoration(suffixText: suffix),
),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'取消',
style: TextStyle(
color: Theme.of(context).colorScheme.outline),
),
),
TextButton(
onPressed: () {
Get.back();
result = int.tryParse(valueStr) ?? 0;
},
child: const Text('确定'),
),
],
);
},
);
}
if (result != -1) {
onChanged?.call(result!);
await GStorage.setting.put(key, result);
setState();
}
}
},
);
}