TF-4141 Add the AI needs-action option into the user settings.

This commit is contained in:
dab246
2025-12-23 01:13:17 +07:00
committed by Dat H. Pham
parent cb0471ecb7
commit 1661210e04
19 changed files with 171 additions and 35 deletions
@@ -36,3 +36,7 @@ class OpenMailboxAction extends MailboxUIAction {
class SystemBackToInboxAction extends MailboxUIAction {} class SystemBackToInboxAction extends MailboxUIAction {}
class RefreshAllMailboxAction extends MailboxUIAction {} class RefreshAllMailboxAction extends MailboxUIAction {}
class AutoCreateActionRequiredFolderMailboxAction extends MailboxUIAction {}
class AutoRemoveActionRequiredFolderMailboxAction extends MailboxUIAction {}
@@ -42,4 +42,24 @@ extension HandleActionRequiredTabExtension on BaseMailboxController {
bool _allMailboxesContains(MailboxId id) { bool _allMailboxesContains(MailboxId id) {
return allMailboxes.any((mailbox) => mailbox.id == id); return allMailboxes.any((mailbox) => mailbox.id == id);
} }
void removeActionRequiredFolder() {
final folder = PresentationMailbox.actionRequiredFolder;
_removeFromDefaultMailboxTree(folder.id);
_removeFromAllMailboxes(folder.id);
}
void _removeFromDefaultMailboxTree(MailboxId folderId) {
final root = defaultMailboxTree.value.root;
final children = List<MailboxNode>.from(root.childrenItems ?? [])
..removeWhere((node) => node.item.id == folderId);
defaultMailboxTree.value = MailboxTree(
root.copyWith(children: children),
);
}
void _removeFromAllMailboxes(MailboxId folderId) {
allMailboxes.removeWhere((mailbox) => mailbox.id == folderId);
}
} }
@@ -319,6 +319,15 @@ class MailboxController extends BaseMailboxController
} else if (action is RefreshAllMailboxAction) { } else if (action is RefreshAllMailboxAction) {
refreshAllMailbox(); refreshAllMailbox();
mailboxDashBoardController.clearMailboxUIAction(); mailboxDashBoardController.clearMailboxUIAction();
} else if (action is AutoCreateActionRequiredFolderMailboxAction) {
addActionRequiredFolder();
mailboxDashBoardController.clearMailboxUIAction();
} else if (action is AutoRemoveActionRequiredFolderMailboxAction) {
removeActionRequiredFolder();
mailboxDashBoardController.clearMailboxUIAction();
if (selectedMailbox?.isActionRequired == true) {
_switchBackToMailboxDefault();
}
} }
}); });
@@ -1564,7 +1573,7 @@ class MailboxController extends BaseMailboxController
void autoCreateVirtualFolder() { void autoCreateVirtualFolder() {
addFavoriteFolderToMailboxList(); addFavoriteFolderToMailboxList();
if (mailboxDashBoardController.isAiCapabilitySupported) { if (mailboxDashBoardController.isAINeedsActionEnabled) {
addActionRequiredFolder(); addActionRequiredFolder();
} }
} }
@@ -120,6 +120,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dow
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart' as search; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart' as search;
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/ai_scribe/setup_ai_needs_action_setting_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/ai_scribe/setup_cached_ai_scribe_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/ai_scribe/setup_cached_ai_scribe_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/cleanup_recent_search_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/cleanup_recent_search_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/delete_emails_in_mailbox_extension.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/delete_emails_in_mailbox_extension.dart';
@@ -303,6 +304,7 @@ class MailboxDashBoardController extends ReloadableController
final isRecoveringDeletedMessage = RxBool(false); final isRecoveringDeletedMessage = RxBool(false);
final localFileDraggableAppState = Rxn<DraggableAppState>(); final localFileDraggableAppState = Rxn<DraggableAppState>();
final isSenderImportantFlagEnabled = RxBool(true); final isSenderImportantFlagEnabled = RxBool(true);
final isAINeedsActionSettingEnabled = RxBool(false);
final isAppGridDialogDisplayed = RxBool(false); final isAppGridDialogDisplayed = RxBool(false);
final isDrawerOpened = RxBool(false); final isDrawerOpened = RxBool(false);
final isContextMenuOpened = RxBool(false); final isContextMenuOpened = RxBool(false);
@@ -512,6 +514,7 @@ class MailboxDashBoardController extends ReloadableController
); );
} else if (success is GetServerSettingSuccess) { } else if (success is GetServerSettingSuccess) {
isSenderImportantFlagEnabled.value = success.settingOption.isDisplaySenderPriority; isSenderImportantFlagEnabled.value = success.settingOption.isDisplaySenderPriority;
setupAINeedsActionSetting(options: success.settingOption);
initializeAppLanguage(success); initializeAppLanguage(success);
} else if (success is ClearMailboxSuccess) { } else if (success is ClearMailboxSuccess) {
clearMailboxSuccess(success); clearMailboxSuccess(success);
@@ -568,6 +571,7 @@ class MailboxDashBoardController extends ReloadableController
_handleIdentityCache(); _handleIdentityCache();
} else if (failure is GetServerSettingFailure) { } else if (failure is GetServerSettingFailure) {
isSenderImportantFlagEnabled.value = true; isSenderImportantFlagEnabled.value = true;
setupAINeedsActionSetting();
} else if (failure is GetAllIdentitiesFailure) { } else if (failure is GetAllIdentitiesFailure) {
_handleGetAllIdentitiesFailure(); _handleGetAllIdentitiesFailure();
} else if (failure is ClearMailboxFailure) { } else if (failure is ClearMailboxFailure) {
@@ -0,0 +1,21 @@
import 'package:get/get.dart';
import 'package:server_settings/server_settings/tmail_server_settings.dart';
import 'package:server_settings/server_settings/tmail_server_settings_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
extension SetupAiNeedsActionSettingExtension on MailboxDashBoardController {
void setupAINeedsActionSetting({TMailServerSettingOptions? options}) {
if (options != null) {
isAINeedsActionSettingEnabled.value = options.isAINeedsActionEnabled;
} else {
isAINeedsActionSettingEnabled.value = false;
}
if (isAINeedsActionSettingEnabled.isTrue) {
dispatchMailboxUIAction(AutoCreateActionRequiredFolderMailboxAction());
} else {
dispatchMailboxUIAction(AutoRemoveActionRequiredFolderMailboxAction());
}
}
}
@@ -16,4 +16,7 @@ extension HandleAiActionExtension on MailboxDashBoardController {
currentAccountId, currentAccountId,
); );
} }
bool get isAINeedsActionEnabled =>
isAINeedsActionSettingEnabled.value && isAiCapabilitySupported;
} }
@@ -9,7 +9,8 @@ enum PreferencesOptionType {
senderPriority(isLocal: false), senderPriority(isLocal: false),
thread(isLocal: true), thread(isLocal: true),
spamReport(isLocal: true), spamReport(isLocal: true),
aiScribe(isLocal: true); aiScribe(isLocal: true),
aiNeedsAction(isLocal: false);
final bool isLocal; final bool isLocal;
@@ -27,6 +28,8 @@ enum PreferencesOptionType {
return appLocalizations.spamReports; return appLocalizations.spamReports;
case PreferencesOptionType.aiScribe: case PreferencesOptionType.aiScribe:
return appLocalizations.aiScribe; return appLocalizations.aiScribe;
case PreferencesOptionType.aiNeedsAction:
return appLocalizations.aiNeedsAction;
} }
} }
@@ -42,6 +45,8 @@ enum PreferencesOptionType {
return appLocalizations.spamReportsSettingExplanation; return appLocalizations.spamReportsSettingExplanation;
case PreferencesOptionType.aiScribe: case PreferencesOptionType.aiScribe:
return appLocalizations.aiScribeSettingExplanation; return appLocalizations.aiScribeSettingExplanation;
case PreferencesOptionType.aiNeedsAction:
return appLocalizations.aiNeedsActionSettingExplanation;
} }
} }
@@ -57,6 +62,8 @@ enum PreferencesOptionType {
return appLocalizations.spamReportToggleDescription; return appLocalizations.spamReportToggleDescription;
case PreferencesOptionType.aiScribe: case PreferencesOptionType.aiScribe:
return appLocalizations.aiScribeToggleDescription; return appLocalizations.aiScribeToggleDescription;
case PreferencesOptionType.aiNeedsAction:
return appLocalizations.aiNeedsActionToggleDescription;
} }
} }
@@ -75,6 +82,8 @@ enum PreferencesOptionType {
return preferencesSetting.spamReportConfig.isEnabled; return preferencesSetting.spamReportConfig.isEnabled;
case PreferencesOptionType.aiScribe: case PreferencesOptionType.aiScribe:
return preferencesSetting.aiScribeConfig.isEnabled; return preferencesSetting.aiScribeConfig.isEnabled;
case PreferencesOptionType.aiNeedsAction:
return settingOption?.isAINeedsActionEnabled ?? false;
} }
} }
} }
@@ -50,7 +50,7 @@ class PreferencesController extends BaseController {
final _manageAccountDashBoardController = Get.find<ManageAccountDashBoardController>(); final _manageAccountDashBoardController = Get.find<ManageAccountDashBoardController>();
bool get isAIScribeAvailable { bool get isAICapabilitySupported {
return _manageAccountDashBoardController.isAICapabilitySupported; return _manageAccountDashBoardController.isAICapabilitySupported;
} }
@@ -183,6 +183,11 @@ class PreferencesController extends BaseController {
displaySenderPriority: !isEnabled, displaySenderPriority: !isEnabled,
); );
break; break;
case PreferencesOptionType.aiNeedsAction:
newSettingOption = settingOption.value?.copyWith(
aiNeedsActionEnabled: !isEnabled,
);
break;
default: default:
break; break;
} }
@@ -68,17 +68,20 @@ class PreferencesView extends GetWidget<PreferencesController> with AppLoaderMix
final availableSettingOptions = [ final availableSettingOptions = [
if (settingOption != null) if (settingOption != null)
...PreferencesOptionType.values.where( ...PreferencesOptionType.values.where(
(optionType) => !optionType.isLocal, (type) =>
!type.isLocal &&
type != PreferencesOptionType.aiNeedsAction,
), ),
if (localSettingOption.configs.isNotEmpty) if (localSettingOption.configs.isNotEmpty)
...PreferencesOptionType.values.where( ...PreferencesOptionType.values.where(
(optionType) => optionType.isLocal, (type) =>
).where((optionType) { type.isLocal &&
if (optionType == PreferencesOptionType.aiScribe) { (type != PreferencesOptionType.aiScribe ||
return controller.isAIScribeAvailable && !PlatformInfo.isMobile; controller.isAICapabilitySupported),
} ),
return true; if (settingOption != null &&
}), controller.isAICapabilitySupported)
PreferencesOptionType.aiNeedsAction,
]; ];
return Expanded( return Expanded(
@@ -724,8 +724,7 @@ class SearchEmailView extends GetWidget<SearchEmailController>
final isSenderImportantFlagEnabled = final isSenderImportantFlagEnabled =
dashboardController.isSenderImportantFlagEnabled.value; dashboardController.isSenderImportantFlagEnabled.value;
final isAiCapabilitySupported = final isAINeedsActionEnabled = dashboardController.isAINeedsActionEnabled;
dashboardController.isAiCapabilitySupported;
return EmailTileBuilder( return EmailTileBuilder(
presentationEmail: presentationEmail, presentationEmail: presentationEmail,
@@ -734,7 +733,7 @@ class SearchEmailView extends GetWidget<SearchEmailController>
isShowingEmailContent: isShowingEmailContent, isShowingEmailContent: isShowingEmailContent,
isSenderImportantFlagEnabled: isSenderImportantFlagEnabled, isSenderImportantFlagEnabled: isSenderImportantFlagEnabled,
isSearchEmailRunning: true, isSearchEmailRunning: true,
isAIEnabled: isAiCapabilitySupported, isAINeedsActionEnabled: isAINeedsActionEnabled,
padding: SearchEmailViewStyle.getPaddingSearchResultList( padding: SearchEmailViewStyle.getPaddingSearchResultList(
context, context,
controller.responsiveUtils, controller.responsiveUtils,
@@ -902,7 +902,7 @@ class SearchMailboxController extends BaseMailboxController with MailboxActionHa
void autoCreateVirtualFolder() { void autoCreateVirtualFolder() {
addFavoriteFolderToMailboxList(); addFavoriteFolderToMailboxList();
if (dashboardController.isAiCapabilitySupported) { if (dashboardController.isAINeedsActionEnabled) {
addActionRequiredFolder(); addActionRequiredFolder();
} }
} }
@@ -11,6 +11,7 @@ extension TmailServerSettingsExtension on TMailServerSettings {
settings: TMailServerSettingOptions( settings: TMailServerSettingOptions(
alwaysReadReceipts: settings?.alwaysReadReceipts, alwaysReadReceipts: settings?.alwaysReadReceipts,
displaySenderPriority: settings?.displaySenderPriority, displaySenderPriority: settings?.displaySenderPriority,
aiNeedsActionEnabled: settings?.aiNeedsActionEnabled,
), ),
); );
} }
@@ -510,8 +510,7 @@ class ThreadView extends GetWidget<ThreadController>
final isSearchEmailRunning = final isSearchEmailRunning =
controller.searchController.isSearchEmailRunning; controller.searchController.isSearchEmailRunning;
final isAiCapabilitySupported = final isAINeedsActionEnabled = dashboardController.isAINeedsActionEnabled;
dashboardController.isAiCapabilitySupported;
return EmailTileBuilder( return EmailTileBuilder(
key: Key('email_tile_builder_${presentationEmail.id?.asString}'), key: Key('email_tile_builder_${presentationEmail.id?.asString}'),
@@ -523,7 +522,7 @@ class ThreadView extends GetWidget<ThreadController>
isSearchEmailRunning: isSearchEmailRunning, isSearchEmailRunning: isSearchEmailRunning,
isDrag: true, isDrag: true,
isSenderImportantFlagEnabled: isSenderImportantFlagEnabled, isSenderImportantFlagEnabled: isSenderImportantFlagEnabled,
isAIEnabled: isAiCapabilitySupported, isAINeedsActionEnabled: isAINeedsActionEnabled,
); );
}); });
} }
@@ -607,8 +606,7 @@ class ThreadView extends GetWidget<ThreadController>
final isSearchEmailRunning = final isSearchEmailRunning =
controller.searchController.isSearchEmailRunning; controller.searchController.isSearchEmailRunning;
final isAiCapabilitySupported = final isAINeedsActionEnabled = dashboardController.isAINeedsActionEnabled;
dashboardController.isAiCapabilitySupported;
return Dismissible( return Dismissible(
key: ValueKey<EmailId?>(presentationEmail.id), key: ValueKey<EmailId?>(presentationEmail.id),
@@ -632,7 +630,7 @@ class ThreadView extends GetWidget<ThreadController>
searchQuery: controller.searchQuery, searchQuery: controller.searchQuery,
mailboxContain: presentationEmail.mailboxContain, mailboxContain: presentationEmail.mailboxContain,
isSearchEmailRunning: isSearchEmailRunning, isSearchEmailRunning: isSearchEmailRunning,
isAIEnabled: isAiCapabilitySupported, isAINeedsActionEnabled: isAINeedsActionEnabled,
emailActionClick: _handleEmailActionClicked, emailActionClick: _handleEmailActionClicked,
onMoreActionClick: (email, position) => onMoreActionClick: (email, position) =>
_handleEmailContextMenuAction(context, email, position), _handleEmailContextMenuAction(context, email, position),
@@ -20,7 +20,7 @@ class EmailTileBuilder extends StatelessWidget with BaseEmailItemTile {
final bool isDrag; final bool isDrag;
final bool isShowingEmailContent; final bool isShowingEmailContent;
final bool isSenderImportantFlagEnabled; final bool isSenderImportantFlagEnabled;
final bool isAIEnabled; final bool isAINeedsActionEnabled;
final OnPressEmailActionClick? emailActionClick; final OnPressEmailActionClick? emailActionClick;
final OnMoreActionClick? onMoreActionClick; final OnMoreActionClick? onMoreActionClick;
@@ -32,7 +32,7 @@ class EmailTileBuilder extends StatelessWidget with BaseEmailItemTile {
this.searchQuery, this.searchQuery,
this.isSearchEmailRunning = false, this.isSearchEmailRunning = false,
this.isSenderImportantFlagEnabled = true, this.isSenderImportantFlagEnabled = true,
this.isAIEnabled = true, this.isAINeedsActionEnabled = true,
this.mailboxContain, this.mailboxContain,
this.padding, this.padding,
this.isDrag = false, this.isDrag = false,
@@ -141,5 +141,5 @@ class EmailTileBuilder extends StatelessWidget with BaseEmailItemTile {
} }
bool get _shouldShowAIAction => bool get _shouldShowAIAction =>
isAIEnabled && presentationEmail.hasNeedAction; isAINeedsActionEnabled && presentationEmail.hasNeedAction;
} }
@@ -27,7 +27,7 @@ class EmailTileBuilder extends StatefulWidget {
final bool isDrag; final bool isDrag;
final bool isShowingEmailContent; final bool isShowingEmailContent;
final bool isSenderImportantFlagEnabled; final bool isSenderImportantFlagEnabled;
final bool isAIEnabled; final bool isAINeedsActionEnabled;
final OnPressEmailActionClick? emailActionClick; final OnPressEmailActionClick? emailActionClick;
final OnMoreActionClick? onMoreActionClick; final OnMoreActionClick? onMoreActionClick;
@@ -42,7 +42,7 @@ class EmailTileBuilder extends StatefulWidget {
this.mailboxContain, this.mailboxContain,
this.padding, this.padding,
this.isDrag = false, this.isDrag = false,
this.isAIEnabled = false, this.isAINeedsActionEnabled = false,
this.emailActionClick, this.emailActionClick,
this.onMoreActionClick, this.onMoreActionClick,
}); });
@@ -423,7 +423,7 @@ class _EmailTileBuilderState extends State<EmailTileBuilder> with BaseEmailItem
} }
bool get _shouldShowAIAction => bool get _shouldShowAIAction =>
widget.isAIEnabled && widget.presentationEmail.hasNeedAction; widget.isAINeedsActionEnabled && widget.presentationEmail.hasNeedAction;
@override @override
void dispose() { void dispose() {
+37 -7
View File
@@ -1,5 +1,5 @@
{ {
"@@last_modified": "2025-12-17T00:04:15.124514", "@@last_modified": "2025-12-22T16:54:22.593873",
"initializing_data": "Initializing data...", "initializing_data": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
@@ -4862,6 +4862,24 @@
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
}, },
"aiScribe": "AI Scribe",
"@aiScribe": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"aiScribeSettingExplanation": "Use AI to help write and improve your emails",
"@aiScribeSettingExplanation": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"aiScribeToggleDescription": "Enable AI Scribe",
"@aiScribeToggleDescription": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"showMoreAttachmentButton": "Show +{count} more", "showMoreAttachmentButton": "Show +{count} more",
"@showMoreAttachmentButton": { "@showMoreAttachmentButton": {
"type": "text", "type": "text",
@@ -5130,12 +5148,6 @@
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
}, },
"aiAssistant": "AI assistant",
"@aiAssistant": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"actionRequired": "Action Required", "actionRequired": "Action Required",
"@actionRequired": { "@actionRequired": {
"type": "text", "type": "text",
@@ -5153,5 +5165,23 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"aiNeedsAction": "AI needs-action",
"@aiNeedsAction": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"aiNeedsActionToggleDescription": "Enable AI needs-action",
"@aiNeedsActionToggleDescription": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"aiNeedsActionSettingExplanation": "Detect emails that need your attention using AI. When turned off, AI will not process any emails.",
"@aiNeedsActionSettingExplanation": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
@@ -5478,4 +5478,25 @@ class AppLocalizations {
name: 'youDoNotHaveAnyActionRequiredEmails', name: 'youDoNotHaveAnyActionRequiredEmails',
); );
} }
String get aiNeedsAction {
return Intl.message(
'AI needs-action',
name: 'aiNeedsAction',
);
}
String get aiNeedsActionToggleDescription {
return Intl.message(
'Enable AI needs-action',
name: 'aiNeedsActionToggleDescription',
);
}
String get aiNeedsActionSettingExplanation {
return Intl.message(
'Detect emails that need your attention using AI. When turned off, AI will not process any emails.',
name: 'aiNeedsActionSettingExplanation',
);
}
} }
@@ -40,10 +40,14 @@ class TMailServerSettingOptions with EquatableMixin {
@JsonKey(name: 'language') @JsonKey(name: 'language')
final String? language; final String? language;
@JsonKey(name: 'ai.needs-action.enabled')
final bool? aiNeedsActionEnabled;
TMailServerSettingOptions({ TMailServerSettingOptions({
this.alwaysReadReceipts, this.alwaysReadReceipts,
this.displaySenderPriority, this.displaySenderPriority,
this.language, this.language,
this.aiNeedsActionEnabled,
}); });
factory TMailServerSettingOptions.fromJson(Map<String, dynamic> json) => factory TMailServerSettingOptions.fromJson(Map<String, dynamic> json) =>
@@ -55,11 +59,13 @@ class TMailServerSettingOptions with EquatableMixin {
bool? alwaysReadReceipts, bool? alwaysReadReceipts,
bool? displaySenderPriority, bool? displaySenderPriority,
String? language, String? language,
bool? aiNeedsActionEnabled,
}) { }) {
return TMailServerSettingOptions( return TMailServerSettingOptions(
alwaysReadReceipts: alwaysReadReceipts ?? this.alwaysReadReceipts, alwaysReadReceipts: alwaysReadReceipts ?? this.alwaysReadReceipts,
displaySenderPriority: displaySenderPriority ?? this.displaySenderPriority, displaySenderPriority: displaySenderPriority ?? this.displaySenderPriority,
language: language ?? this.language, language: language ?? this.language,
aiNeedsActionEnabled: aiNeedsActionEnabled ?? this.aiNeedsActionEnabled,
); );
} }
@@ -68,5 +74,6 @@ class TMailServerSettingOptions with EquatableMixin {
alwaysReadReceipts, alwaysReadReceipts,
displaySenderPriority, displaySenderPriority,
language, language,
aiNeedsActionEnabled,
]; ];
} }
@@ -5,4 +5,6 @@ extension TmailServerSettingsExtension on TMailServerSettingOptions {
bool get isDisplaySenderPriority => displaySenderPriority ?? true; bool get isDisplaySenderPriority => displaySenderPriority ?? true;
bool get isAlwaysReadReceipts => alwaysReadReceipts ?? false; bool get isAlwaysReadReceipts => alwaysReadReceipts ?? false;
bool get isAINeedsActionEnabled => aiNeedsActionEnabled ?? false;
} }