diff --git a/lib/common/controller/block_controller.dart b/lib/common/controller/block_controller.dart index f4923ee4d..6b9f7d96e 100644 --- a/lib/common/controller/block_controller.dart +++ b/lib/common/controller/block_controller.dart @@ -13,6 +13,49 @@ class BlockController extends GetxController { final ruleForCommentator = [].obs; final ruleForComment = [].obs; + bool matchRule({String? text, required BlockType blockType}) { + if (text == null || text.isEmpty) { + return false; + } + final List _ruleList = getRuleListByType(blockType); + for (final BlockRule _rule in _ruleList) { + final _ruleText = _rule.ruleText?.trim(); + + // default enabled + if (!(_rule.enabled ?? true) || _ruleText == null || _ruleText.isEmpty) { + continue; + } + if (_rule.enableRegex ?? false) { + final RegExp _regExp = RegExp(_ruleText); + if (_regExp.hasMatch(text)) { + logger.d('matchRule:${_rule.toJson()}\ntext: $text'); + return true; + } + } else { + if (text.contains(_ruleText)) { + logger.d('matchRule: ${_rule.toJson()}\ntext: $text'); + return true; + } + } + } + return false; + } + + List getRuleListByType(BlockType? blockType) { + switch (blockType) { + case BlockType.title: + return ruleForTitle; + case BlockType.uploader: + return ruleForUploader; + case BlockType.commentator: + return ruleForCommentator; + case BlockType.comment: + return ruleForComment; + default: + return []; + } + } + @override void onInit() { super.onInit(); @@ -24,13 +67,14 @@ class BlockController extends GetxController { ruleForComment.value = ehSettingService.blockConfig.ruleForComment ?? []; } - void updateBlockRule() { + void saveBlockRule() { ehSettingService.blockConfig = ehSettingService.blockConfig.copyWith( ruleForTitle: ruleForTitle, ruleForUploader: ruleForUploader, ruleForCommentator: ruleForCommentator, ruleForComment: ruleForComment, ); + Global.saveProfile(); } void addBlockRule(BlockRule result) { @@ -40,21 +84,42 @@ class BlockController extends GetxController { } final BlockType? _blockType = BlockType.values.asNameMap()[result.blockType]; - switch (_blockType) { - case BlockType.title: - ruleForTitle.add(result); - break; - case BlockType.uploader: - ruleForUploader.add(result); - break; - case BlockType.commentator: - ruleForCommentator.add(result); - break; - case BlockType.comment: - ruleForComment.add(result); - break; - default: - break; + getRuleListByType(_blockType).add(result); + saveBlockRule(); + } + + void updateBlockRule(BlockRule oldBlockRule, BlockRule newBlockRule) { + logger.d('oldBlockRule ${oldBlockRule.toJson()}'); + logger.d('newBlockRule ${newBlockRule.toJson()}'); + + // if type is different, remove old rule and add new rule + if (oldBlockRule.blockType != newBlockRule.blockType) { + final _oldBlockType = + BlockType.values.asNameMap()[oldBlockRule.blockType]; + removeRule( + oldBlockRule.blockType, + getRuleListByType(_oldBlockType).indexOf(oldBlockRule), + ); + addBlockRule(newBlockRule); + return; } + + if (newBlockRule.ruleText?.trim().isEmpty ?? true) { + return; + } + final BlockType? _blockType = + BlockType.values.asNameMap()[oldBlockRule.blockType]; + + final int _index = getRuleListByType(_blockType).indexOf(oldBlockRule); + getRuleListByType(_blockType)[_index] = newBlockRule; + + saveBlockRule(); + } + + void removeRule(String? blockType, int index) { + logger.d('removeRule $blockType $index'); + final BlockType? _blockType = BlockType.values.asNameMap()[blockType]; + getRuleListByType(_blockType).removeAt(index); + saveBlockRule(); } } diff --git a/lib/pages/gallery/view/comment_page.dart b/lib/pages/gallery/view/comment_page.dart index 22e9a8ee5..6b54a5dba 100644 --- a/lib/pages/gallery/view/comment_page.dart +++ b/lib/pages/gallery/view/comment_page.dart @@ -1,3 +1,4 @@ +import 'package:fehviewer/common/controller/block_controller.dart'; import 'package:fehviewer/common/service/controller_tag_service.dart'; import 'package:fehviewer/common/service/ehsetting_service.dart'; import 'package:fehviewer/common/service/theme_service.dart'; @@ -34,6 +35,7 @@ class _CommentPageState extends State late CommentController controller; EhSettingService get _ehSettingService => Get.find(); + BlockController get _blockController => Get.find(); @override void initState() { @@ -76,7 +78,7 @@ class _CommentPageState extends State return Obx(() { logger.t('build commentListView'); - late final List? _comments; + List? _comments; if (_ehSettingService.showOnlyUploaderComment) { final _uploaderId = controller.comments @@ -95,7 +97,18 @@ class _CommentPageState extends State } else { _comments = controller.comments; } - // _comments = controller.comments; + + // 根据屏蔽规则过滤评论 + _comments = _comments?.where((element) { + return !_blockController.matchRule( + text: element.text, + blockType: BlockType.comment, + ) && + !_blockController.matchRule( + text: element.name, + blockType: BlockType.commentator, + ); + }).toList(); return Container( padding: const EdgeInsets.symmetric(horizontal: kPadding), diff --git a/lib/pages/gallery/view/gallery_widget.dart b/lib/pages/gallery/view/gallery_widget.dart index d6c266d22..fd5beb23e 100644 --- a/lib/pages/gallery/view/gallery_widget.dart +++ b/lib/pages/gallery/view/gallery_widget.dart @@ -1,3 +1,4 @@ +import 'package:fehviewer/common/controller/block_controller.dart'; import 'package:fehviewer/common/service/controller_tag_service.dart'; import 'package:fehviewer/common/service/ehsetting_service.dart'; import 'package:fehviewer/common/service/layout_service.dart'; @@ -349,6 +350,7 @@ class TopCommentEx extends StatelessWidget { final String? uploader; EhSettingService get _ehSettingService => Get.find(); + BlockController get _blockController => Get.find(); @override Widget build(BuildContext context) { @@ -377,6 +379,18 @@ class TopCommentEx extends StatelessWidget { _ehSettingService.scoreFilteringThreshold); } + // 根据屏蔽规则过滤评论 + _comments = _comments.where((element) { + return !_blockController.matchRule( + text: element.text, + blockType: BlockType.comment, + ) && + !_blockController.matchRule( + text: element.name, + blockType: BlockType.commentator, + ); + }); + _comments = _comments.take(max); return _comments diff --git a/lib/pages/setting/block/block_rule_edit_page.dart b/lib/pages/setting/block/block_rule_edit_page.dart index d53219b05..c99a3cd7f 100644 --- a/lib/pages/setting/block/block_rule_edit_page.dart +++ b/lib/pages/setting/block/block_rule_edit_page.dart @@ -14,15 +14,21 @@ class BlockRuleEditPage extends GetView { @override Widget build(BuildContext context) { final String _title = L10n.of(context).edit_block_rule; - final blockRuleTextEditingController = TextEditingController(); + + final BlockRule? _blockRuleFromArg = + Get.arguments is BlockRule ? Get.arguments as BlockRule : null; BlockRule _blockRule = blockRule ?? + _blockRuleFromArg ?? BlockRule( ruleText: '', blockType: controller.latestBlockType?.name ?? BlockType.title.name, enabled: true, enableRegex: controller.latestEnableRegex ?? false, ); + final blockRuleTextEditingController = TextEditingController( + text: _blockRule.ruleText, + ); final List _list = [ TextSwitchItem( @@ -70,9 +76,14 @@ class BlockRuleEditPage extends GetView { color: CupertinoColors.placeholderText, height: 1.25, ), + textInputAction: TextInputAction.done, style: const TextStyle(height: 1.2), + onEditingComplete: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, + keyboardType: TextInputType.text, onChanged: (value) { - logger.d('value $value'); + logger.t('value $value'); _blockRule = _blockRule.copyWith( ruleText: value.replaceAll('\n', ' ')); }, diff --git a/lib/pages/setting/block/block_rules_page.dart b/lib/pages/setting/block/block_rules_page.dart index 79e0e1e9a..f343d22cd 100644 --- a/lib/pages/setting/block/block_rules_page.dart +++ b/lib/pages/setting/block/block_rules_page.dart @@ -1,9 +1,13 @@ import 'package:fehviewer/common/controller/block_controller.dart'; import 'package:fehviewer/common/service/layout_service.dart'; import 'package:fehviewer/common/service/theme_service.dart'; +import 'package:fehviewer/component/setting_base.dart'; import 'package:fehviewer/fehviewer.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:get/get.dart'; +import 'package:sliver_tools/sliver_tools.dart'; class BlockRulesPage extends GetView { const BlockRulesPage({super.key}); @@ -12,6 +16,16 @@ class BlockRulesPage extends GetView { Widget build(BuildContext context) { final String _title = L10n.of(context).block_rules; + final List<({String groupName, List rules})> ruleGroups = [ + (groupName: L10n.of(context).title, rules: controller.ruleForTitle), + (groupName: L10n.of(context).uploader, rules: controller.ruleForUploader), + ( + groupName: L10n.of(context).commentator, + rules: controller.ruleForCommentator + ), + (groupName: L10n.of(context).comment, rules: controller.ruleForComment), + ]; + return Obx(() { return CupertinoPageScaffold( backgroundColor: !ehTheme.isDarkMode @@ -24,7 +38,6 @@ class BlockRulesPage extends GetView { padding: const EdgeInsets.all(0), minSize: 40, child: const Icon( - // FontAwesomeIcons.plus, CupertinoIcons.plus_circle, size: 28, ), @@ -39,10 +52,81 @@ class BlockRulesPage extends GetView { }, ), ), - child: SafeArea( - bottom: false, - top: false, - child: ListView(), + child: CustomScrollView( + slivers: [ + SliverSafeArea( + left: false, + right: false, + sliver: MultiSliver(children: [ + ...ruleGroups.map( + (e) => MultiSliver( + pushPinnedChildren: true, + children: [ + if (e.rules.isNotEmpty) + Container( + padding: const EdgeInsets.only( + left: 20, + bottom: 4, + top: 20, + ), + width: double.infinity, + child: Text( + e.groupName ?? '', + style: const TextStyle(fontSize: 14), + textAlign: TextAlign.start, + ), + ), + SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + final BlockRule _blockRule = e.rules[index]; + return Slidable( + key: Key( + '_blockRule.blockType${_blockRule.hashCode}'), + endActionPane: ActionPane( + extentRatio: 0.25, + motion: const ScrollMotion(), + children: [ + SlidableAction( + onPressed: (_) => controller.removeRule( + _blockRule.blockType, index), + backgroundColor: + CupertinoDynamicColor.resolve( + CupertinoColors.systemRed, context), + foregroundColor: Colors.white, + icon: CupertinoIcons.delete, + // label: L10n.of(context).delete, + ), + ], + ), + child: SelectorSettingItem( + title: _blockRule.ruleText ?? '', + hideDivider: _blockRule == e.rules.last, + onTap: () async { + final result = await Get.toNamed( + EHRoutes.blockRuleEdit, + arguments: _blockRule, + id: isLayoutLarge ? 2 : null, + ); + if (result != null && result is BlockRule) { + controller.updateBlockRule( + _blockRule, + result, + ); + } + }, + ), + ); + }, + childCount: e.rules.length, + ), + ), + ], + ), + ), + ]), + ), + ], ), ); }); diff --git a/lib/pages/tab/view/tab_base.dart b/lib/pages/tab/view/tab_base.dart index 30f8affb8..322b28881 100644 --- a/lib/pages/tab/view/tab_base.dart +++ b/lib/pages/tab/view/tab_base.dart @@ -1,8 +1,6 @@ +import 'package:fehviewer/common/controller/block_controller.dart'; import 'package:fehviewer/common/service/ehsetting_service.dart'; -import 'package:fehviewer/const/const.dart'; -import 'package:fehviewer/extension.dart'; -import 'package:fehviewer/generated/l10n.dart'; -import 'package:fehviewer/models/index.dart'; +import 'package:fehviewer/fehviewer.dart'; import 'package:fehviewer/pages/item/controller/galleryitem_controller.dart'; import 'package:fehviewer/pages/item/gallery_item.dart'; import 'package:fehviewer/pages/item/gallery_item_debug_simple.dart'; @@ -13,8 +11,6 @@ import 'package:fehviewer/pages/item/gallery_item_simple.dart'; import 'package:fehviewer/pages/item/gallery_item_simple_placeholder.dart'; import 'package:fehviewer/pages/tab/controller/enum.dart'; import 'package:fehviewer/pages/tab/controller/search_page_controller.dart'; -import 'package:fehviewer/route/routes.dart'; -import 'package:fehviewer/utils/logger.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; @@ -581,6 +577,23 @@ Widget getGallerySliverList( final EhSettingService ehSettingService = Get.find(); final _key = key ?? ValueKey(galleryProviders.hashCode); + final BlockController _blockController = Get.find(); + + galleryProviders = galleryProviders?.where((GalleryProvider element) { + return !_blockController.matchRule( + blockType: BlockType.title, + text: element.englishTitle, + ) && + !_blockController.matchRule( + blockType: BlockType.title, + text: element.japaneseTitle, + ) && + !_blockController.matchRule( + blockType: BlockType.uploader, + text: element.uploader, + ); + }).toList(); + // logger.d('next $next'); return Obx(() { diff --git a/lib/pages/tab/view/tabbar/custom_profiles_page.dart b/lib/pages/tab/view/tabbar/custom_profiles_page.dart index 14bfa7949..1f5a5aaad 100644 --- a/lib/pages/tab/view/tabbar/custom_profiles_page.dart +++ b/lib/pages/tab/view/tabbar/custom_profiles_page.dart @@ -41,7 +41,7 @@ class CustomProfilesPage extends GetView { backgroundColor: CupertinoDynamicColor.resolve( CupertinoColors.systemRed, context), foregroundColor: Colors.white, - icon: Icons.delete, + icon: CupertinoIcons.delete, // label: L10n.of(context).delete, ), ],