mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
feat: search settings item
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -1,333 +1,16 @@
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:PiliPalaX/pages/setting/widgets/model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:PiliPalaX/models/common/rcmd_type.dart';
|
||||
import 'package:PiliPalaX/pages/setting/widgets/select_dialog.dart';
|
||||
import 'package:PiliPalaX/utils/recommend_filter.dart';
|
||||
import 'package:PiliPalaX/utils/storage.dart';
|
||||
|
||||
import 'widgets/switch_item.dart';
|
||||
|
||||
class RecommendSetting extends StatefulWidget {
|
||||
class RecommendSetting extends StatelessWidget {
|
||||
const RecommendSetting({super.key});
|
||||
|
||||
@override
|
||||
State<RecommendSetting> createState() => _RecommendSettingState();
|
||||
}
|
||||
|
||||
class _RecommendSettingState extends State<RecommendSetting> {
|
||||
late dynamic defaultRcmdType;
|
||||
late dynamic userInfo;
|
||||
bool userLogin = false;
|
||||
late dynamic accessKeyInfo;
|
||||
// late int filterUnfollowedRatio;
|
||||
late int minDurationForRcmd;
|
||||
late int minLikeRatioForRecommend;
|
||||
late String banWordForRecommend;
|
||||
|
||||
Box get setting => GStorage.setting;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 首页默认推荐类型
|
||||
defaultRcmdType =
|
||||
setting.get(SettingBoxKey.defaultRcmdType, defaultValue: 'app');
|
||||
userInfo = GStorage.userInfo.get('userInfoCache');
|
||||
userLogin = userInfo != null;
|
||||
accessKeyInfo =
|
||||
GStorage.localCache.get(LocalCacheKey.accessKey, defaultValue: null);
|
||||
// filterUnfollowedRatio = setting
|
||||
// .get(SettingBoxKey.filterUnfollowedRatio, defaultValue: 0);
|
||||
minDurationForRcmd =
|
||||
setting.get(SettingBoxKey.minDurationForRcmd, defaultValue: 0);
|
||||
minLikeRatioForRecommend =
|
||||
setting.get(SettingBoxKey.minLikeRatioForRecommend, defaultValue: 0);
|
||||
banWordForRecommend =
|
||||
setting.get(SettingBoxKey.banWordForRecommend, defaultValue: '');
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TextStyle titleStyle = Theme.of(context).textTheme.titleMedium!;
|
||||
TextStyle subTitleStyle = Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('推荐流设置')),
|
||||
body: ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
dense: false,
|
||||
title: Text('首页推荐类型', style: titleStyle),
|
||||
leading: const Icon(Icons.model_training_outlined),
|
||||
subtitle: Text(
|
||||
'当前使用「$defaultRcmdType端」推荐¹',
|
||||
style: subTitleStyle,
|
||||
),
|
||||
onTap: () async {
|
||||
String? result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SelectDialog<String>(
|
||||
title: '推荐类型',
|
||||
value: defaultRcmdType,
|
||||
values: RcmdType.values.map((e) {
|
||||
return {'title': e.labels, 'value': e.values};
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result != null) {
|
||||
if (result == 'app') {
|
||||
if (accessKeyInfo == null) {
|
||||
SmartDialog.showToast('尚未登录,无法收到个性化推荐');
|
||||
}
|
||||
}
|
||||
defaultRcmdType = result;
|
||||
setting.put(SettingBoxKey.defaultRcmdType, result);
|
||||
SmartDialog.showToast('下次启动时生效');
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
),
|
||||
const SetSwitchItem(
|
||||
title: '推荐动态',
|
||||
subTitle: '是否在推荐内容中展示动态(仅app端)',
|
||||
leading: Icon(Icons.motion_photos_on_outlined),
|
||||
setKey: SettingBoxKey.enableRcmdDynamic,
|
||||
defaultVal: true,
|
||||
),
|
||||
const SetSwitchItem(
|
||||
title: '首页推荐刷新',
|
||||
subTitle: '下拉刷新时保留上次内容',
|
||||
leading: Icon(Icons.refresh),
|
||||
setKey: SettingBoxKey.enableSaveLastData,
|
||||
defaultVal: false,
|
||||
needReboot: true,
|
||||
),
|
||||
// 分割线
|
||||
const Divider(height: 1),
|
||||
ListTile(
|
||||
dense: false,
|
||||
leading: const Icon(Icons.thumb_up_outlined),
|
||||
title: Text('点赞率过滤', style: titleStyle),
|
||||
subtitle: Text(
|
||||
'过滤掉点赞数/播放量「小于$minLikeRatioForRecommend%」的推荐视频(仅web端)',
|
||||
style: subTitleStyle,
|
||||
),
|
||||
onTap: () async {
|
||||
int? result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SelectDialog<int>(
|
||||
title: '选择点赞率(0即不过滤)',
|
||||
value: minLikeRatioForRecommend,
|
||||
values: [0, 1, 2, 3, 4].map((e) {
|
||||
return {'title': '$e %', 'value': e};
|
||||
}).toList());
|
||||
},
|
||||
);
|
||||
if (result != null) {
|
||||
minLikeRatioForRecommend = result;
|
||||
setting.put(SettingBoxKey.minLikeRatioForRecommend, result);
|
||||
RecommendFilter.update();
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: false,
|
||||
leading: const Icon(Icons.title_outlined),
|
||||
title: Text('标题关键词过滤', style: titleStyle),
|
||||
subtitle: Text(
|
||||
banWordForRecommend.isEmpty ? "点击添加" : banWordForRecommend,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
onTap: () async {
|
||||
final TextEditingController textController =
|
||||
TextEditingController(text: banWordForRecommend);
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
'标题关键词过滤',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('使用|隔开,如:尝试|测试'),
|
||||
TextField(
|
||||
autofocus: true,
|
||||
controller: textController,
|
||||
textInputAction: TextInputAction.newline,
|
||||
minLines: 1,
|
||||
maxLines: 4,
|
||||
)
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('保存'),
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
banWordForRecommend = textController.text;
|
||||
setting.put(SettingBoxKey.banWordForRecommend,
|
||||
banWordForRecommend);
|
||||
setState(() {});
|
||||
RecommendFilter.update();
|
||||
SmartDialog.showToast('已保存');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: false,
|
||||
title: Text('视频时长过滤', style: titleStyle),
|
||||
leading: const Icon(Icons.timelapse_outlined),
|
||||
subtitle: Text(
|
||||
'过滤掉时长「小于$minDurationForRcmd秒」的推荐视频',
|
||||
style: subTitleStyle,
|
||||
),
|
||||
onTap: () async {
|
||||
const List<int> defDurations = [0, 30, 60, 90, 120];
|
||||
int? result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SelectDialog<int>(
|
||||
title: '选择时长(0即不过滤)',
|
||||
value: minDurationForRcmd,
|
||||
values: [
|
||||
...[
|
||||
...defDurations,
|
||||
if (defDurations.contains(minDurationForRcmd).not)
|
||||
minDurationForRcmd,
|
||||
]..sort(),
|
||||
-1,
|
||||
].map((e) {
|
||||
if (e == -1) {
|
||||
return {'title': '自定义', 'value': e};
|
||||
}
|
||||
return {'title': '$e 秒', 'value': e};
|
||||
}).toList());
|
||||
},
|
||||
);
|
||||
if (result != null) {
|
||||
void updateDuration(int value) {
|
||||
minDurationForRcmd = value;
|
||||
setting.put(SettingBoxKey.minDurationForRcmd, value);
|
||||
RecommendFilter.update();
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
if (result == -1 && context.mounted) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
String duration = '';
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
'自定义时长',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
content: TextField(
|
||||
autofocus: true,
|
||||
onChanged: (value) => duration = value,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'\d+')),
|
||||
],
|
||||
decoration: const InputDecoration(suffixText: 's'),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
updateDuration(int.tryParse(duration) ?? 0);
|
||||
},
|
||||
child: Text('确定'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
updateDuration(result);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
SetSwitchItem(
|
||||
title: '已关注UP豁免推荐过滤',
|
||||
subTitle: '推荐中已关注用户发布的内容不会被过滤',
|
||||
leading: const Icon(Icons.favorite_border_outlined),
|
||||
setKey: SettingBoxKey.exemptFilterForFollowed,
|
||||
defaultVal: true,
|
||||
onChanged: (_) => {RecommendFilter.update},
|
||||
),
|
||||
// ListTile(
|
||||
// dense: false,
|
||||
// title: Text('按比例过滤未关注Up', style: titleStyle),
|
||||
// subtitle: Text(
|
||||
// '滤除推荐中占比「$filterUnfollowedRatio%」的未关注用户发布的内容',
|
||||
// style: subTitleStyle,
|
||||
// ),
|
||||
// onTap: () async {
|
||||
// int? result = await showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return SelectDialog<int>(
|
||||
// title: '选择滤除比例(0即不过滤)',
|
||||
// value: filterUnfollowedRatio,
|
||||
// values: [0, 16, 32, 48, 64].map((e) {
|
||||
// return {'title': '$e %', 'value': e};
|
||||
// }).toList());
|
||||
// },
|
||||
// );
|
||||
// if (result != null) {
|
||||
// filterUnfollowedRatio = result;
|
||||
// setting.put(
|
||||
// SettingBoxKey.filterUnfollowedRatio, result);
|
||||
// RecommendFilter.update();
|
||||
// setState(() {});
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
SetSwitchItem(
|
||||
title: '过滤器也应用于相关视频',
|
||||
subTitle: '视频详情页的相关视频也进行过滤²',
|
||||
leading: const Icon(Icons.explore_outlined),
|
||||
setKey: SettingBoxKey.applyFilterToRelatedVideos,
|
||||
defaultVal: true,
|
||||
onChanged: (_) => {RecommendFilter.update},
|
||||
),
|
||||
...recommendSettings.map((item) => item.widget),
|
||||
ListTile(
|
||||
dense: true,
|
||||
subtitle: Text(
|
||||
|
||||
Reference in New Issue
Block a user