TF-4265 Additional config for include and exclude keywords

This commit is contained in:
dab246
2026-01-30 14:38:33 +07:00
committed by Dat H. Pham
parent 42fb24e6e5
commit 55e27c78ed
8 changed files with 187 additions and 2 deletions
@@ -890,6 +890,12 @@ class ComposerController extends BaseController
emailSubject: subjectEmail.value ?? '',
emailContent: emailContent,
);
if (!context.mounted) {
logWarning('ComposerController::_prepareToSendMessages: CONTEXT IS NOT MOUNTED');
return;
}
if (attachmentKeywords.isNotEmpty &&
uploadController.attachmentsUploaded.isEmpty) {
showAttachmentReminderModal(
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_manager.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/manager/attachment_text_detector.dart';
import 'package:tmail_ui_user/features/composer/presentation/manager/keyword_config_manager.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -16,8 +17,12 @@ extension AttachmentDetectionExtension on ComposerController {
try {
final fullContent = '$emailSubject $emailContent';
final plainText = HtmlUtils.extractPlainText(fullContent);
final keywords =
await AttachmentTextDetector.matchedKeywordsUnique(plainText);
final keywordConfig = await KeywordConfigManager().getConfig();
final keywords = await AttachmentTextDetector.matchedKeywordsUnique(
plainText,
includeList: keywordConfig.includeList,
excludeList: keywordConfig.excludeList,
);
if (keywords.isEmpty) {
return [];
} else {
@@ -0,0 +1,26 @@
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/config/app_config_parser.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/keyword_config.dart';
class AttachmentKeywordsConfigurationParser
extends AppConfigParser<KeywordConfig> {
@override
Future<KeywordConfig> parse(String value) async {
try {
final jsonObject = jsonDecode(value);
return KeywordConfig.fromJson(jsonObject);
} catch (e) {
logWarning('AttachmentKeywordsConfigurationParser::parse(): $e');
rethrow;
}
}
@override
Future<KeywordConfig> parseData(ByteData data) {
throw UnimplementedError();
}
}
@@ -0,0 +1,43 @@
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/config/app_config_loader.dart';
import 'package:tmail_ui_user/features/composer/presentation/manager/attachment_keywords_configuration_parser.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/keyword_config.dart';
import 'package:tmail_ui_user/main/utils/app_config.dart';
class KeywordConfigManager {
static final KeywordConfigManager _instance = KeywordConfigManager._();
factory KeywordConfigManager() => _instance;
KeywordConfigManager._();
KeywordConfig? _cachedConfig;
AppConfigLoader? _appConfigLoader;
static const String _configPath =
AppConfig.attachmentKeywordsConfigurationPath;
Future<KeywordConfig> getConfig() async {
if (_cachedConfig != null) {
return _cachedConfig!;
}
try {
_appConfigLoader ??= AppConfigLoader();
_cachedConfig = await _appConfigLoader?.load<KeywordConfig>(
_configPath,
AttachmentKeywordsConfigurationParser(),
);
} catch (e) {
logWarning(
"KeywordConfigManager::getConfig:Error loading keyword config: $e");
_cachedConfig = const KeywordConfig();
}
return _cachedConfig!;
}
void clearCache() {
_cachedConfig = null;
}
}
@@ -0,0 +1,23 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'keyword_config.g.dart';
@JsonSerializable(includeIfNull: false, explicitToJson: true)
class KeywordConfig with EquatableMixin {
final List<String> includeList;
final List<String> excludeList;
const KeywordConfig({
this.includeList = const [],
this.excludeList = const [],
});
factory KeywordConfig.fromJson(Map<String, dynamic> json) =>
_$KeywordConfigFromJson(json);
Map<String, dynamic> toJson() => _$KeywordConfigToJson(this);
@override
List<Object?> get props => [includeList, excludeList];
}
+1
View File
@@ -12,6 +12,7 @@ class AppConfig {
static const int defaultLimitAutocomplete = 8;
static const String appDashboardConfigurationPath = "configurations/app_dashboard.json";
static const String attachmentKeywordsConfigurationPath = "configurations/attachment_keywords.json";
static const String iOSKeychainSharingGroupId = 'KUT463DS29.com.linagora.ios.teammail.shared';
static const String iOSKeychainSharingService = 'com.linagora.ios.teammail.sessions';
static const String saasPlatform = 'saas';