TF-3977 Add disable spam banner in preferences setting

This commit is contained in:
dab246
2025-08-29 18:21:10 +07:00
committed by Dat H. Pham
parent 7f4dcf8b38
commit 612fc75f02
41 changed files with 534 additions and 404 deletions
@@ -1,32 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/local_setting_detail/thread_detail_local_setting_detail.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/local_setting_options.dart';
abstract class LocalSettingDetail<T> extends Equatable {
const LocalSettingDetail(this.value);
final T value;
Map<String, dynamic> toJson();
}
class LocalSettingDetailConverter extends JsonConverter<LocalSettingDetail, Map<String, dynamic>> {
const LocalSettingDetailConverter();
@override
LocalSettingDetail fromJson(Map<String, dynamic> json) {
final type = json['type'] as String?;
if (type == SupportedLocalSetting.threadDetail.name) {
return ThreadDetailLocalSettingDetail.fromJson(json);
}
throw UnimplementedError();
}
@override
Map<String, dynamic> toJson(LocalSettingDetail object) {
return object.toJson();
}
}
@@ -1,24 +0,0 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/local_setting_detail/local_setting_detail.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/local_setting_options.dart';
part 'thread_detail_local_setting_detail.g.dart';
@JsonSerializable()
class ThreadDetailLocalSettingDetail extends LocalSettingDetail<bool> {
const ThreadDetailLocalSettingDetail(
super.value, [
this.type = SupportedLocalSetting.threadDetail,
]);
@JsonKey(defaultValue: SupportedLocalSetting.threadDetail)
final SupportedLocalSetting type;
factory ThreadDetailLocalSettingDetail.fromJson(Map<String, dynamic> json) =>
_$ThreadDetailLocalSettingDetailFromJson(json);
@override
Map<String, dynamic> toJson() => _$ThreadDetailLocalSettingDetailToJson(this);
@override
List<Object?> get props => [value, type];
}
@@ -1,26 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/local_setting_detail/local_setting_detail.dart';
part 'local_setting_options.g.dart';
enum SupportedLocalSetting {
threadDetail,
}
@JsonSerializable(converters: [LocalSettingDetailConverter()])
class LocalSettingOptions with EquatableMixin {
const LocalSettingOptions({
required this.setting,
});
final LocalSettingDetail? setting;
factory LocalSettingOptions.fromJson(Map<String, dynamic> json) =>
_$LocalSettingOptionsFromJson(json);
Map<String, dynamic> toJson() => _$LocalSettingOptionsToJson(this);
@override
List<Object?> get props => [setting];
}
@@ -0,0 +1,50 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_setting.dart';
part 'preferences_root.g.dart';
@JsonSerializable(explicitToJson: true)
class PreferencesRoot with EquatableMixin {
final PreferencesSetting setting;
PreferencesRoot({required this.setting});
factory PreferencesRoot.initial() {
return PreferencesRoot(
setting: PreferencesSetting.initial(),
);
}
factory PreferencesRoot.fromJson(Map<String, dynamic> json) =>
_$PreferencesRootFromJson(json);
Map<String, dynamic> toJson() => _$PreferencesRootToJson(this);
@override
List<Object?> get props => [setting];
}
extension PreferencesRootExtension on PreferencesRoot {
PreferencesRoot copyWith({PreferencesSetting? setting}) {
return PreferencesRoot(
setting: setting ?? this.setting,
);
}
PreferencesRoot updateThreadDetail(bool enabled) {
return copyWith(setting: setting.updateThreadDetail(enabled));
}
PreferencesRoot updateSpamReport({
bool? isEnabled,
int? lastTimeDismissedMilliseconds,
}) {
return copyWith(
setting: setting.updateSpamReport(
isEnabled: isEnabled,
lastTimeDismissedMilliseconds: lastTimeDismissedMilliseconds,
),
);
}
}
@@ -0,0 +1,61 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/spam_report_config.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/thread_detail_config.dart';
part 'preferences_setting.g.dart';
@JsonSerializable(explicitToJson: true)
class PreferencesSetting with EquatableMixin {
final ThreadDetailConfig threadDetail;
final SpamReportConfig spamReport;
PreferencesSetting({
required this.threadDetail,
required this.spamReport,
});
factory PreferencesSetting.initial() {
return PreferencesSetting(
threadDetail: ThreadDetailConfig.initial(),
spamReport: SpamReportConfig.initial(),
);
}
factory PreferencesSetting.fromJson(Map<String, dynamic> json) =>
_$PreferencesSettingFromJson(json);
Map<String, dynamic> toJson() => _$PreferencesSettingToJson(this);
@override
List<Object?> get props => [threadDetail, spamReport];
}
extension PreferencesSettingExtension on PreferencesSetting {
PreferencesSetting copyWith({
ThreadDetailConfig? threadDetail,
SpamReportConfig? spamReport,
}) {
return PreferencesSetting(
threadDetail: threadDetail ?? this.threadDetail,
spamReport: spamReport ?? this.spamReport,
);
}
PreferencesSetting updateThreadDetail(bool enabled) {
return copyWith(threadDetail: threadDetail.copyWith(isEnabled: enabled));
}
PreferencesSetting updateSpamReport({
bool? isEnabled,
int? lastTimeDismissedMilliseconds,
}) {
return copyWith(
spamReport: spamReport.copyWith(
isEnabled: isEnabled ?? spamReport.isEnabled,
lastTimeDismissedMilliseconds: lastTimeDismissedMilliseconds ??
spamReport.lastTimeDismissedMilliseconds,
),
);
}
}
@@ -0,0 +1,47 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart';
part 'spam_report_config.g.dart';
@JsonSerializable()
class SpamReportConfig with EquatableMixin {
final bool isEnabled;
final int lastTimeDismissedMilliseconds;
SpamReportConfig({
this.isEnabled = true,
this.lastTimeDismissedMilliseconds = 0,
});
factory SpamReportConfig.initial() {
return SpamReportConfig(
isEnabled: true,
lastTimeDismissedMilliseconds: 0,
);
}
factory SpamReportConfig.fromJson(Map<String, dynamic> json) =>
_$SpamReportConfigFromJson(json);
Map<String, dynamic> toJson() => _$SpamReportConfigToJson(this);
@override
List<Object> get props => [isEnabled, lastTimeDismissedMilliseconds];
}
extension SpamReportConfigExtension on SpamReportConfig {
SpamReportConfig copyWith({
bool? isEnabled,
int? lastTimeDismissedMilliseconds,
}) {
return SpamReportConfig(
isEnabled: isEnabled ?? this.isEnabled,
lastTimeDismissedMilliseconds:
lastTimeDismissedMilliseconds ?? this.lastTimeDismissedMilliseconds,
);
}
SpamReportState get spamReportState =>
isEnabled ? SpamReportState.enabled : SpamReportState.disabled;
}
@@ -0,0 +1,33 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'thread_detail_config.g.dart';
@JsonSerializable()
class ThreadDetailConfig with EquatableMixin {
final bool isEnabled;
ThreadDetailConfig({this.isEnabled = false});
factory ThreadDetailConfig.initial() {
return ThreadDetailConfig(
isEnabled: false,
);
}
factory ThreadDetailConfig.fromJson(Map<String, dynamic> json) =>
_$ThreadDetailConfigFromJson(json);
Map<String, dynamic> toJson() => _$ThreadDetailConfigToJson(this);
@override
List<Object> get props => [isEnabled];
}
extension ThreadDetailConfigExtension on ThreadDetailConfig {
ThreadDetailConfig copyWith({bool? isEnabled}) {
return ThreadDetailConfig(
isEnabled: isEnabled ?? this.isEnabled,
);
}
}
@@ -1,66 +1,71 @@
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/manage_account/presentation/extensions/local_settings_map_extension.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/local_setting_options.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_setting.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
enum SettingOptionType {
readReceipt,
senderPriority,
thread;
enum PreferencesOptionType {
readReceipt(isLocal: false),
senderPriority(isLocal: false),
thread(isLocal: true),
spamReport(isLocal: true);
final bool isLocal;
const PreferencesOptionType({required this.isLocal});
String getTitle(AppLocalizations appLocalizations) {
switch(this) {
case SettingOptionType.readReceipt:
case PreferencesOptionType.readReceipt:
return appLocalizations.emailReadReceipts;
case SettingOptionType.senderPriority:
case PreferencesOptionType.senderPriority:
return appLocalizations.senderSetImportantFlag;
case SettingOptionType.thread:
case PreferencesOptionType.thread:
return appLocalizations.thread;
case PreferencesOptionType.spamReport:
return appLocalizations.spamReports;
}
}
String getExplanation(AppLocalizations appLocalizations) {
switch(this) {
case SettingOptionType.readReceipt:
case PreferencesOptionType.readReceipt:
return appLocalizations.emailReadReceiptsSettingExplanation;
case SettingOptionType.senderPriority:
case PreferencesOptionType.senderPriority:
return appLocalizations.senderImportantSettingExplanation;
case SettingOptionType.thread:
case PreferencesOptionType.thread:
return appLocalizations.threadSettingExplanation;
case PreferencesOptionType.spamReport:
return appLocalizations.spamReportsSettingExplanation;
}
}
String getToggleDescription(AppLocalizations appLocalizations) {
switch(this) {
case SettingOptionType.readReceipt:
case PreferencesOptionType.readReceipt:
return appLocalizations.emailReadReceiptsToggleDescription;
case SettingOptionType.senderPriority:
case PreferencesOptionType.senderPriority:
return appLocalizations.senderImportantSettingToggleDescription;
case SettingOptionType.thread:
case PreferencesOptionType.thread:
return appLocalizations.threadToggleDescription;
case PreferencesOptionType.spamReport:
return appLocalizations.spamReportToggleDescription;
}
}
bool isEnabled(
TMailServerSettingOptions? settingOption,
Map<SupportedLocalSetting, LocalSettingOptions?> localSettings,
PreferencesSetting preferencesSetting,
) {
switch(this) {
case SettingOptionType.readReceipt:
case PreferencesOptionType.readReceipt:
return settingOption?.isAlwaysReadReceipts ?? false;
case SettingOptionType.senderPriority:
case PreferencesOptionType.senderPriority:
return settingOption?.isDisplaySenderPriority ?? false;
case SettingOptionType.thread:
return localSettings.threadDetailEnabled ?? false;
case PreferencesOptionType.thread:
return preferencesSetting.threadDetail.isEnabled;
case PreferencesOptionType.spamReport:
return preferencesSetting.spamReport.isEnabled;
}
}
bool get isLocal {
return switch (this) {
thread => true,
_ => false,
};
}
}