From 5a88f3c36fa132af523f8fc0c929b537cc550ccc Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 9 Sep 2025 11:12:57 +0700 Subject: [PATCH] TF-3977 Separate settings keys for easier in conflict --- .../local_spam_report_datasource_impl.dart | 5 +- .../controller/spam_report_controller.dart | 14 +-- .../presentation/model/loader_status.dart | 1 + .../model/spam_report_loader_status.dart | 1 - .../datasource/manage_account_datasource.dart | 9 +- .../manage_account_datasource_impl.dart | 24 ++++- .../local/preferences_setting_manager.dart | 100 ++++++++++++++---- .../manage_account_repository_impl.dart | 9 +- .../default_preferences_config.dart | 18 ++++ .../preferences/empty_preferences_config.dart | 9 ++ .../model/preferences/preferences_config.dart | 9 ++ .../preferences/preferences_setting.dart | 41 +++++++ .../model/preferences/spam_report_config.dart | 5 +- .../preferences/thread_detail_config.dart | 5 +- .../repository/manage_account_repository.dart | 7 +- .../state/get_local_settings_state.dart | 8 +- .../state/update_local_settings_state.dart | 8 +- .../get_local_settings_interactor.dart | 2 - .../update_local_settings_interactor.dart | 14 ++- .../default_preferences_config_converter.dart | 14 +++ .../model/preferences/preferences_root.dart | 50 --------- .../preferences/preferences_setting.dart | 61 ----------- .../model/preferences_option_type.dart | 6 +- .../preferences/preferences_controller.dart | 61 ++++++++--- .../preferences/preferences_view.dart | 7 +- .../widgets/preferences_option_item.dart | 4 +- .../thread_detail_local_data_source_impl.dart | 4 +- 27 files changed, 290 insertions(+), 206 deletions(-) create mode 100644 lib/features/mailbox_dashboard/presentation/model/loader_status.dart delete mode 100644 lib/features/mailbox_dashboard/presentation/model/spam_report_loader_status.dart create mode 100644 lib/features/manage_account/domain/model/preferences/default_preferences_config.dart create mode 100644 lib/features/manage_account/domain/model/preferences/empty_preferences_config.dart create mode 100644 lib/features/manage_account/domain/model/preferences/preferences_config.dart create mode 100644 lib/features/manage_account/domain/model/preferences/preferences_setting.dart rename lib/features/manage_account/{presentation => domain}/model/preferences/spam_report_config.dart (88%) rename lib/features/manage_account/{presentation => domain}/model/preferences/thread_detail_config.dart (81%) create mode 100644 lib/features/manage_account/presentation/converters/default_preferences_config_converter.dart delete mode 100644 lib/features/manage_account/presentation/model/preferences/preferences_root.dart delete mode 100644 lib/features/manage_account/presentation/model/preferences/preferences_setting.dart diff --git a/lib/features/mailbox_dashboard/data/datasource_impl/local_spam_report_datasource_impl.dart b/lib/features/mailbox_dashboard/data/datasource_impl/local_spam_report_datasource_impl.dart index 6324d5866..b987efc86 100644 --- a/lib/features/mailbox_dashboard/data/datasource_impl/local_spam_report_datasource_impl.dart +++ b/lib/features/mailbox_dashboard/data/datasource_impl/local_spam_report_datasource_impl.dart @@ -8,7 +8,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/spam_re import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/unread_spam_emails_response.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/preferences_setting_manager.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/spam_report_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/spam_report_config.dart'; import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart'; class LocalSpamReportDataSourceImpl extends SpamReportDataSource { @@ -23,8 +23,7 @@ class LocalSpamReportDataSourceImpl extends SpamReportDataSource { @override Future getLastTimeDismissedSpamReported() async { return Future.sync(() async { - final spamReportConfig = - await _preferencesSettingManager.getSpamReportConfig(); + final spamReportConfig = await _preferencesSettingManager.getSpamReportConfig(); return DateTime.fromMillisecondsSinceEpoch( spamReportConfig.lastTimeDismissedMilliseconds, ); diff --git a/lib/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart index 7b8aa9bc2..de635206d 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart @@ -19,7 +19,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_spa import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_last_time_dismissed_spam_reported_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_spam_report_state_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; -import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/spam_report_loader_status.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/loader_status.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class SpamReportController extends BaseController { @@ -32,7 +32,7 @@ class SpamReportController extends BaseController { final spamReportState = Rx(SpamReportState.enabled); AppLifecycleListener? _appLifecycleListener; - SpamReportLoaderStatus _spamReportLoaderStatus = SpamReportLoaderStatus.idle; + LoaderStatus _spamReportLoaderStatus = LoaderStatus.idle; SpamReportController( this._storeSpamReportInteractor, @@ -46,7 +46,7 @@ class SpamReportController extends BaseController { super.onInit(); _appLifecycleListener ??= AppLifecycleListener( onResume: () { - if (_spamReportLoaderStatus == SpamReportLoaderStatus.loading) { + if (_spamReportLoaderStatus == LoaderStatus.loading) { return; } getSpamReportStateAction(); @@ -59,7 +59,7 @@ class SpamReportController extends BaseController { if (success is StoreLastTimeDismissedSpamReportSuccess) { presentationSpamMailbox.value = null; } else if (success is GetSpamReportStateLoading) { - _spamReportLoaderStatus = SpamReportLoaderStatus.loading; + _spamReportLoaderStatus = LoaderStatus.loading; } else if (success is GetSpamReportStateSuccess) { _loadSpamReportConfigSuccess(success.spamReportState); } else if (success is StoreSpamReportStateSuccess) { @@ -77,7 +77,7 @@ class SpamReportController extends BaseController { if (failure is GetSpamMailboxCachedFailure) { presentationSpamMailbox.value = null; } else if (failure is GetSpamReportStateFailure) { - _spamReportLoaderStatus = SpamReportLoaderStatus.completed; + _spamReportLoaderStatus = LoaderStatus.completed; } else { super.handleFailureViewState(failure); } @@ -86,12 +86,12 @@ class SpamReportController extends BaseController { @override void handleErrorViewState(Object error, StackTrace stackTrace) { super.handleErrorViewState(error, stackTrace); - _spamReportLoaderStatus = SpamReportLoaderStatus.completed; + _spamReportLoaderStatus = LoaderStatus.completed; } void _loadSpamReportConfigSuccess(SpamReportState newState) { spamReportState.value = newState; - _spamReportLoaderStatus = SpamReportLoaderStatus.completed; + _spamReportLoaderStatus = LoaderStatus.completed; getBinding()?.refreshSpamReportBanner(); } diff --git a/lib/features/mailbox_dashboard/presentation/model/loader_status.dart b/lib/features/mailbox_dashboard/presentation/model/loader_status.dart new file mode 100644 index 000000000..61171c74f --- /dev/null +++ b/lib/features/mailbox_dashboard/presentation/model/loader_status.dart @@ -0,0 +1 @@ +enum LoaderStatus { idle, loading, completed } diff --git a/lib/features/mailbox_dashboard/presentation/model/spam_report_loader_status.dart b/lib/features/mailbox_dashboard/presentation/model/spam_report_loader_status.dart deleted file mode 100644 index 5099dda84..000000000 --- a/lib/features/mailbox_dashboard/presentation/model/spam_report_loader_status.dart +++ /dev/null @@ -1 +0,0 @@ -enum SpamReportLoaderStatus { idle, loading, completed } diff --git a/lib/features/manage_account/data/datasource/manage_account_datasource.dart b/lib/features/manage_account/data/datasource/manage_account_datasource.dart index f7e6f0d9d..7591877a9 100644 --- a/lib/features/manage_account/data/datasource/manage_account_datasource.dart +++ b/lib/features/manage_account/data/datasource/manage_account_datasource.dart @@ -1,11 +1,12 @@ import 'dart:ui'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; abstract class ManageAccountDataSource { Future persistLanguage(Locale localeCurrent); - Future updateLocalSettings(PreferencesRoot preferencesRoot); + Future toggleLocalSettingsState(PreferencesConfig preferencesConfig); - Future getLocalSettings(); -} \ No newline at end of file + Future getLocalSettings(); +} diff --git a/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart b/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart index 3a4b1296d..b540baf56 100644 --- a/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart +++ b/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart @@ -3,7 +3,10 @@ import 'dart:ui'; import 'package:tmail_ui_user/features/manage_account/data/datasource/manage_account_datasource.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/preferences_setting_manager.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/spam_report_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/thread_detail_config.dart'; import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart'; class ManageAccountDataSourceImpl extends ManageAccountDataSource { @@ -26,14 +29,27 @@ class ManageAccountDataSourceImpl extends ManageAccountDataSource { } @override - Future updateLocalSettings(PreferencesRoot preferencesRoot) { + Future toggleLocalSettingsState(PreferencesConfig preferencesConfig) { return Future.sync(() async { - return await _preferencesSettingManager.savePreferences(preferencesRoot); + if (preferencesConfig is ThreadDetailConfig) { + await _preferencesSettingManager.updateThread( + preferencesConfig.isEnabled, + ); + } else if (preferencesConfig is SpamReportConfig) { + await _preferencesSettingManager.updateSpamReport( + isEnabled: preferencesConfig.isEnabled, + ); + } else { + await _preferencesSettingManager.savePreferences( + preferencesConfig, + ); + } + return await _preferencesSettingManager.loadPreferences(); }).catchError(_exceptionThrower.throwException); } @override - Future getLocalSettings() { + Future getLocalSettings() { return Future.sync(() async { return await _preferencesSettingManager.loadPreferences(); }).catchError(_exceptionThrower.throwException); diff --git a/lib/features/manage_account/data/local/preferences_setting_manager.dart b/lib/features/manage_account/data/local/preferences_setting_manager.dart index 2c2b7ef35..ecb702968 100644 --- a/lib/features/manage_account/data/local/preferences_setting_manager.dart +++ b/lib/features/manage_account/data/local/preferences_setting_manager.dart @@ -1,55 +1,113 @@ import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/spam_report_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/default_preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/empty_preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/spam_report_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/thread_detail_config.dart'; class PreferencesSettingManager { static const String _preferencesSettingKey = 'PREFERENCES_SETTING'; + static const String _preferencesSettingThreadKey = + '${_preferencesSettingKey}_THREAD'; + static const String _preferencesSettingSpamReportKey = + '${_preferencesSettingKey}_SPAM_REPORT'; const PreferencesSettingManager(this._sharedPreferences); final SharedPreferences _sharedPreferences; - Future loadPreferences() async { + Future loadPreferences() async { await _sharedPreferences.reload(); - final jsonString = _sharedPreferences.getString(_preferencesSettingKey); + final keys = _sharedPreferences.getKeys(); + final preferencesKeys = + keys.where((key) => key.startsWith(_preferencesSettingKey)).toList(); - if (jsonString != null) { - return PreferencesRoot.fromJson(jsonDecode(jsonString)); + final listConfigs = preferencesKeys.map((key) { + final jsonString = _sharedPreferences.getString(key); + if (jsonString != null) { + final jsonDecoded = jsonDecode(jsonString); + + switch (key) { + case _preferencesSettingThreadKey: + return ThreadDetailConfig.fromJson(jsonDecoded); + case _preferencesSettingSpamReportKey: + return SpamReportConfig.fromJson(jsonDecoded); + default: + return DefaultPreferencesConfig.fromJson(jsonDecoded); + } + } + return EmptyPreferencesConfig(); + }).toList(); + + if (listConfigs.isEmpty) { + return PreferencesSetting.initial(); } - return PreferencesRoot.initial(); + return PreferencesSetting(listConfigs); } - Future savePreferences(PreferencesRoot root) async { - await _sharedPreferences.setString( - _preferencesSettingKey, - jsonEncode(root.toJson()), - ); + Future savePreferences(PreferencesConfig config) async { + if (config is ThreadDetailConfig) { + await _sharedPreferences.setString( + _preferencesSettingThreadKey, + jsonEncode(config.toJson()), + ); + } else if (config is SpamReportConfig) { + await _sharedPreferences.setString( + _preferencesSettingSpamReportKey, + jsonEncode(config.toJson()), + ); + } else { + await _sharedPreferences.setString( + _preferencesSettingKey, + jsonEncode(config.toJson()), + ); + } } - Future updateThread(bool enabled) async { - final current = await loadPreferences(); - final updated = current.updateThreadDetail(enabled); - await savePreferences(updated); + Future updateThread(bool isEnabled) async { + final currentConfig = await getThreadConfig(); + final updatedConfig = currentConfig.copyWith(isEnabled: isEnabled); + await savePreferences(updatedConfig); } Future updateSpamReport({ bool? isEnabled, int? lastTimeDismissedMilliseconds, }) async { - final current = await loadPreferences(); - final updated = current.updateSpamReport( + final currentConfig = await getSpamReportConfig(); + final updatedConfig = currentConfig.copyWith( isEnabled: isEnabled, lastTimeDismissedMilliseconds: lastTimeDismissedMilliseconds, ); - await savePreferences(updated); + await savePreferences(updatedConfig); } Future getSpamReportConfig() async { - final preferences = await loadPreferences(); - return preferences.setting.spamReport; + await _sharedPreferences.reload(); + + final jsonString = _sharedPreferences.getString( + _preferencesSettingSpamReportKey, + ); + + return jsonString == null + ? SpamReportConfig.initial() + : SpamReportConfig.fromJson(jsonDecode(jsonString)); + } + + Future getThreadConfig() async { + await _sharedPreferences.reload(); + + final jsonString = _sharedPreferences.getString( + _preferencesSettingThreadKey, + ); + + return jsonString == null + ? ThreadDetailConfig.initial() + : ThreadDetailConfig.fromJson(jsonDecode(jsonString)); } } diff --git a/lib/features/manage_account/data/repository/manage_account_repository_impl.dart b/lib/features/manage_account/data/repository/manage_account_repository_impl.dart index d52bce62c..bb5fbd0b3 100644 --- a/lib/features/manage_account/data/repository/manage_account_repository_impl.dart +++ b/lib/features/manage_account/data/repository/manage_account_repository_impl.dart @@ -1,8 +1,9 @@ import 'dart:ui'; import 'package:tmail_ui_user/features/manage_account/data/datasource/manage_account_datasource.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; class ManageAccountRepositoryImpl extends ManageAccountRepository { @@ -16,12 +17,12 @@ class ManageAccountRepositoryImpl extends ManageAccountRepository { } @override - Future updateLocalSettings(PreferencesRoot preferencesRoot) { - return dataSource.updateLocalSettings(preferencesRoot); + Future toggleLocalSettingsState(PreferencesConfig preferencesConfig) { + return dataSource.toggleLocalSettingsState(preferencesConfig); } @override - Future getLocalSettings() { + Future getLocalSettings() { return dataSource.getLocalSettings(); } } \ No newline at end of file diff --git a/lib/features/manage_account/domain/model/preferences/default_preferences_config.dart b/lib/features/manage_account/domain/model/preferences/default_preferences_config.dart new file mode 100644 index 000000000..f862749a2 --- /dev/null +++ b/lib/features/manage_account/domain/model/preferences/default_preferences_config.dart @@ -0,0 +1,18 @@ +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/converters/default_preferences_config_converter.dart'; + +class DefaultPreferencesConfig extends PreferencesConfig { + final dynamic data; + + DefaultPreferencesConfig(this.data); + + factory DefaultPreferencesConfig.fromJson(Map json) => + const DefaultPreferencesConfigConverter().fromJson(json); + + @override + Map toJson() => + const DefaultPreferencesConfigConverter().toJson(this); + + @override + List get props => [data]; +} diff --git a/lib/features/manage_account/domain/model/preferences/empty_preferences_config.dart b/lib/features/manage_account/domain/model/preferences/empty_preferences_config.dart new file mode 100644 index 000000000..d9b2b7970 --- /dev/null +++ b/lib/features/manage_account/domain/model/preferences/empty_preferences_config.dart @@ -0,0 +1,9 @@ +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; + +class EmptyPreferencesConfig extends PreferencesConfig { + @override + List get props => []; + + @override + Map toJson() => {}; +} diff --git a/lib/features/manage_account/domain/model/preferences/preferences_config.dart b/lib/features/manage_account/domain/model/preferences/preferences_config.dart new file mode 100644 index 000000000..d1b80d319 --- /dev/null +++ b/lib/features/manage_account/domain/model/preferences/preferences_config.dart @@ -0,0 +1,9 @@ +import 'package:equatable/equatable.dart'; + +abstract class PreferencesConfig with EquatableMixin { + + Map toJson(); + + @override + List get props => []; +} \ No newline at end of file diff --git a/lib/features/manage_account/domain/model/preferences/preferences_setting.dart b/lib/features/manage_account/domain/model/preferences/preferences_setting.dart new file mode 100644 index 000000000..a97b59d26 --- /dev/null +++ b/lib/features/manage_account/domain/model/preferences/preferences_setting.dart @@ -0,0 +1,41 @@ +import 'package:collection/collection.dart'; +import 'package:equatable/equatable.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/spam_report_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/thread_detail_config.dart'; + +class PreferencesSetting with EquatableMixin { + final List configs; + + PreferencesSetting(this.configs); + + factory PreferencesSetting.initial() { + return PreferencesSetting([ + ThreadDetailConfig.initial(), + SpamReportConfig.initial(), + ]); + } + + ThreadDetailConfig get threadConfig { + final threadConfig = + configs.firstWhereOrNull((config) => config is ThreadDetailConfig); + if (threadConfig != null) { + return threadConfig as ThreadDetailConfig; + } else { + return ThreadDetailConfig.initial(); + } + } + + SpamReportConfig get spamReportConfig { + final spamConfig = + configs.firstWhereOrNull((config) => config is SpamReportConfig); + if (spamConfig != null) { + return spamConfig as SpamReportConfig; + } else { + return SpamReportConfig.initial(); + } + } + + @override + List get props => [configs]; +} diff --git a/lib/features/manage_account/presentation/model/preferences/spam_report_config.dart b/lib/features/manage_account/domain/model/preferences/spam_report_config.dart similarity index 88% rename from lib/features/manage_account/presentation/model/preferences/spam_report_config.dart rename to lib/features/manage_account/domain/model/preferences/spam_report_config.dart index 5dcc49e17..bb1829397 100644 --- a/lib/features/manage_account/presentation/model/preferences/spam_report_config.dart +++ b/lib/features/manage_account/domain/model/preferences/spam_report_config.dart @@ -1,11 +1,11 @@ -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'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; part 'spam_report_config.g.dart'; @JsonSerializable() -class SpamReportConfig with EquatableMixin { +class SpamReportConfig extends PreferencesConfig { final bool isEnabled; final int lastTimeDismissedMilliseconds; @@ -24,6 +24,7 @@ class SpamReportConfig with EquatableMixin { factory SpamReportConfig.fromJson(Map json) => _$SpamReportConfigFromJson(json); + @override Map toJson() => _$SpamReportConfigToJson(this); @override diff --git a/lib/features/manage_account/presentation/model/preferences/thread_detail_config.dart b/lib/features/manage_account/domain/model/preferences/thread_detail_config.dart similarity index 81% rename from lib/features/manage_account/presentation/model/preferences/thread_detail_config.dart rename to lib/features/manage_account/domain/model/preferences/thread_detail_config.dart index db8c63c17..ec12f091f 100644 --- a/lib/features/manage_account/presentation/model/preferences/thread_detail_config.dart +++ b/lib/features/manage_account/domain/model/preferences/thread_detail_config.dart @@ -1,10 +1,10 @@ -import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; part 'thread_detail_config.g.dart'; @JsonSerializable() -class ThreadDetailConfig with EquatableMixin { +class ThreadDetailConfig extends PreferencesConfig { final bool isEnabled; ThreadDetailConfig({this.isEnabled = false}); @@ -18,6 +18,7 @@ class ThreadDetailConfig with EquatableMixin { factory ThreadDetailConfig.fromJson(Map json) => _$ThreadDetailConfigFromJson(json); + @override Map toJson() => _$ThreadDetailConfigToJson(this); @override diff --git a/lib/features/manage_account/domain/repository/manage_account_repository.dart b/lib/features/manage_account/domain/repository/manage_account_repository.dart index 341f5923a..f96ed179f 100644 --- a/lib/features/manage_account/domain/repository/manage_account_repository.dart +++ b/lib/features/manage_account/domain/repository/manage_account_repository.dart @@ -1,11 +1,12 @@ import 'dart:ui'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; abstract class ManageAccountRepository { Future persistLanguage(Locale localeCurrent); - Future updateLocalSettings(PreferencesRoot preferencesRoot); + Future toggleLocalSettingsState(PreferencesConfig preferencesConfig); - Future getLocalSettings(); + Future getLocalSettings(); } diff --git a/lib/features/manage_account/domain/state/get_local_settings_state.dart b/lib/features/manage_account/domain/state/get_local_settings_state.dart index 5c6c572ad..d232c1aa7 100644 --- a/lib/features/manage_account/domain/state/get_local_settings_state.dart +++ b/lib/features/manage_account/domain/state/get_local_settings_state.dart @@ -1,16 +1,16 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; class GettingLocalSettingsState extends LoadingState {} class GetLocalSettingsSuccess extends UIState { - GetLocalSettingsSuccess(this.preferencesRoot); + GetLocalSettingsSuccess(this.preferencesSetting); - final PreferencesRoot preferencesRoot; + final PreferencesSetting preferencesSetting; @override - List get props => [preferencesRoot]; + List get props => [preferencesSetting]; } class GetLocalSettingsFailure extends FeatureFailure { diff --git a/lib/features/manage_account/domain/state/update_local_settings_state.dart b/lib/features/manage_account/domain/state/update_local_settings_state.dart index 0c33ed1ee..7a1d698af 100644 --- a/lib/features/manage_account/domain/state/update_local_settings_state.dart +++ b/lib/features/manage_account/domain/state/update_local_settings_state.dart @@ -1,16 +1,16 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; class UpdatingLocalSettingsState extends LoadingState {} class UpdateLocalSettingsSuccess extends UIState { - final PreferencesRoot preferencesRoot; + final PreferencesSetting preferencesSetting; - UpdateLocalSettingsSuccess(this.preferencesRoot); + UpdateLocalSettingsSuccess(this.preferencesSetting); @override - List get props => [preferencesRoot]; + List get props => [preferencesSetting]; } class UpdateLocalSettingsFailure extends FeatureFailure { diff --git a/lib/features/manage_account/domain/usecases/get_local_settings_interactor.dart b/lib/features/manage_account/domain/usecases/get_local_settings_interactor.dart index 8a534cbfe..cebe675d1 100644 --- a/lib/features/manage_account/domain/usecases/get_local_settings_interactor.dart +++ b/lib/features/manage_account/domain/usecases/get_local_settings_interactor.dart @@ -1,6 +1,5 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; -import 'package:core/utils/app_logger.dart'; import 'package:dartz/dartz.dart'; import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/get_local_settings_state.dart'; @@ -16,7 +15,6 @@ class GetLocalSettingsInteractor { final result = await _manageAccountRepository.getLocalSettings(); yield Right(GetLocalSettingsSuccess(result)); } catch (e) { - logError('$runtimeType::execute(): exception: $e'); yield Left(GetLocalSettingsFailure(exception: e)); } } diff --git a/lib/features/manage_account/domain/usecases/update_local_settings_interactor.dart b/lib/features/manage_account/domain/usecases/update_local_settings_interactor.dart index e479344d7..5169f3f93 100644 --- a/lib/features/manage_account/domain/usecases/update_local_settings_interactor.dart +++ b/lib/features/manage_account/domain/usecases/update_local_settings_interactor.dart @@ -1,25 +1,23 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; -import 'package:core/utils/app_logger.dart'; import 'package:dartz/dartz.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/update_local_settings_state.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; class UpdateLocalSettingsInteractor { const UpdateLocalSettingsInteractor(this._manageAccountRepository); final ManageAccountRepository _manageAccountRepository; - Stream> execute( - PreferencesRoot preferencesRoot, - ) async* { + Stream> execute(PreferencesConfig preferencesConfig) async* { try { yield Right(UpdatingLocalSettingsState()); - await _manageAccountRepository.updateLocalSettings(preferencesRoot); - yield Right(UpdateLocalSettingsSuccess(preferencesRoot)); + final preferencesSetting = await _manageAccountRepository.toggleLocalSettingsState( + preferencesConfig, + ); + yield Right(UpdateLocalSettingsSuccess(preferencesSetting)); } catch (e) { - logError('$runtimeType::execute(): exception: $e'); yield Left(UpdateLocalSettingsFailure(exception: e)); } } diff --git a/lib/features/manage_account/presentation/converters/default_preferences_config_converter.dart b/lib/features/manage_account/presentation/converters/default_preferences_config_converter.dart new file mode 100644 index 000000000..c22a34602 --- /dev/null +++ b/lib/features/manage_account/presentation/converters/default_preferences_config_converter.dart @@ -0,0 +1,14 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/default_preferences_config.dart'; + +class DefaultPreferencesConfigConverter + implements JsonConverter> { + const DefaultPreferencesConfigConverter(); + + @override + DefaultPreferencesConfig fromJson(Map json) => + DefaultPreferencesConfig(json); + + @override + Map toJson(DefaultPreferencesConfig config) => config.data; +} diff --git a/lib/features/manage_account/presentation/model/preferences/preferences_root.dart b/lib/features/manage_account/presentation/model/preferences/preferences_root.dart deleted file mode 100644 index 58fb9d23f..000000000 --- a/lib/features/manage_account/presentation/model/preferences/preferences_root.dart +++ /dev/null @@ -1,50 +0,0 @@ -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 json) => - _$PreferencesRootFromJson(json); - - Map toJson() => _$PreferencesRootToJson(this); - - @override - List 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, - ), - ); - } -} diff --git a/lib/features/manage_account/presentation/model/preferences/preferences_setting.dart b/lib/features/manage_account/presentation/model/preferences/preferences_setting.dart deleted file mode 100644 index eef33f8b9..000000000 --- a/lib/features/manage_account/presentation/model/preferences/preferences_setting.dart +++ /dev/null @@ -1,61 +0,0 @@ -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 json) => - _$PreferencesSettingFromJson(json); - - Map toJson() => _$PreferencesSettingToJson(this); - - @override - List 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, - ), - ); - } -} diff --git a/lib/features/manage_account/presentation/model/preferences_option_type.dart b/lib/features/manage_account/presentation/model/preferences_option_type.dart index 24b9d2197..836952fff 100644 --- a/lib/features/manage_account/presentation/model/preferences_option_type.dart +++ b/lib/features/manage_account/presentation/model/preferences_option_type.dart @@ -1,7 +1,7 @@ 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/model/preferences/preferences_setting.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; enum PreferencesOptionType { @@ -63,9 +63,9 @@ enum PreferencesOptionType { case PreferencesOptionType.senderPriority: return settingOption?.isDisplaySenderPriority ?? false; case PreferencesOptionType.thread: - return preferencesSetting.threadDetail.isEnabled; + return preferencesSetting.threadConfig.isEnabled; case PreferencesOptionType.spamReport: - return preferencesSetting.spamReport.isEnabled; + return preferencesSetting.spamReportConfig.isEnabled; } } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/preferences/preferences_controller.dart b/lib/features/manage_account/presentation/preferences/preferences_controller.dart index dd8af8e1a..6376c467d 100644 --- a/lib/features/manage_account/presentation/preferences/preferences_controller.dart +++ b/lib/features/manage_account/presentation/preferences/preferences_controller.dart @@ -1,16 +1,21 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:dartz/dartz.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:server_settings/server_settings/tmail_server_settings.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/loader_status.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/spam_report_config.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/thread_detail_config.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/get_local_settings_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/update_local_settings_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_local_settings_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/update_local_settings_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_root.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences_option_type.dart'; import 'package:tmail_ui_user/features/server_settings/domain/state/get_server_setting_state.dart'; import 'package:tmail_ui_user/features/server_settings/domain/state/update_server_setting_state.dart'; @@ -33,7 +38,10 @@ class PreferencesController extends BaseController { final UpdateLocalSettingsInteractor _updateLocalSettingsInteractor; final settingOption = Rxn(); - final localSettings = Rxn(); + final localSettings = Rx(PreferencesSetting.initial()); + + AppLifecycleListener? _appLifecycleListener; + LoaderStatus _localSettingLoaderStatus = LoaderStatus.idle; bool get isLoading => viewState.value.fold( (failure) => false, @@ -45,6 +53,15 @@ class PreferencesController extends BaseController { void onInit() { super.onInit(); _getSettingOption(); + + _appLifecycleListener ??= AppLifecycleListener( + onResume: () { + if (_localSettingLoaderStatus == LoaderStatus.loading) { + return; + } + consumeState(_getLocalSettingInteractor.execute()); + }, + ); } @override @@ -54,9 +71,12 @@ class PreferencesController extends BaseController { } else if (success is UpdateServerSettingSuccess) { _updateSettingOptionValue(newSettingOption: success.settingOption); } else if (success is GetLocalSettingsSuccess) { - _updateLocalSettingOptionValue(success.preferencesRoot); + _localSettingLoaderStatus = LoaderStatus.completed; + _updateLocalSettingOptionValue(success.preferencesSetting); } else if (success is UpdateLocalSettingsSuccess) { - _updateLocalSettingOptionValue(success.preferencesRoot); + _updateLocalSettingOptionValue(success.preferencesSetting); + } else if (success is GettingLocalSettingsState) { + _localSettingLoaderStatus = LoaderStatus.loading; } else { super.handleSuccessViewState(success); } @@ -66,6 +86,8 @@ class PreferencesController extends BaseController { void handleFailureViewState(Failure failure) { if (failure is GetServerSettingFailure) { _updateSettingOptionValue(newSettingOption: null); + } else if (failure is GetLocalSettingsFailure) { + _localSettingLoaderStatus = LoaderStatus.completed; } else if (failure is UpdateServerSettingFailure) { _handleUpdateServerSettingFailure(); } else { @@ -73,6 +95,12 @@ class PreferencesController extends BaseController { } } + @override + void handleErrorViewState(Object error, StackTrace stackTrace) { + super.handleErrorViewState(error, stackTrace); + _localSettingLoaderStatus = LoaderStatus.completed; + } + void _handleUpdateServerSettingFailure() { if (currentOverlayContext != null && currentContext != null) { appToast.showToastErrorMessage( @@ -85,8 +113,8 @@ class PreferencesController extends BaseController { settingOption.value = newSettingOption; } - void _updateLocalSettingOptionValue(PreferencesRoot preferencesRoot) { - localSettings.value = preferencesRoot; + void _updateLocalSettingOptionValue(PreferencesSetting preferencesSetting) { + localSettings.value = preferencesSetting; } void _getSettingOption() { @@ -114,24 +142,20 @@ class PreferencesController extends BaseController { PreferencesOptionType optionType, bool isEnabled, ) { - PreferencesRoot? preferencesRoot; + PreferencesConfig? config; switch(optionType) { case PreferencesOptionType.thread: - preferencesRoot = localSettings.value?.updateThreadDetail( - !isEnabled, - ); + config = ThreadDetailConfig(isEnabled: !isEnabled); break; case PreferencesOptionType.spamReport: - preferencesRoot = localSettings.value?.updateSpamReport( - isEnabled: !isEnabled, - ); + config = SpamReportConfig(isEnabled: !isEnabled); break; default: break; } - if (preferencesRoot != null) { - consumeState(_updateLocalSettingsInteractor.execute(preferencesRoot)); + if (config != null) { + consumeState(_updateLocalSettingsInteractor.execute(config)); } } @@ -171,4 +195,11 @@ class PreferencesController extends BaseController { ); } } + + + @override + void onClose() { + _appLifecycleListener?.dispose(); + super.onClose(); + } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/preferences/preferences_view.dart b/lib/features/manage_account/presentation/preferences/preferences_view.dart index 948fbf1d9..dc51ab5b5 100644 --- a/lib/features/manage_account/presentation/preferences/preferences_view.dart +++ b/lib/features/manage_account/presentation/preferences/preferences_view.dart @@ -59,7 +59,8 @@ class PreferencesView extends GetWidget with AppLoaderMix final settingOption = controller.settingOption.value; final localSettingOption = controller.localSettings.value; - if (settingOption == null && localSettingOption == null) { + if (settingOption == null && + localSettingOption.configs.isEmpty) { return const SizedBox.shrink(); } @@ -68,7 +69,7 @@ class PreferencesView extends GetWidget with AppLoaderMix ...PreferencesOptionType.values.where( (optionType) => !optionType.isLocal, ), - if (localSettingOption != null) + if (localSettingOption.configs.isNotEmpty) ...PreferencesOptionType.values.where( (optionType) => optionType.isLocal, ), @@ -81,7 +82,7 @@ class PreferencesView extends GetWidget with AppLoaderMix return PreferencesOptionItem( imagePaths: controller.imagePaths, settingOption: settingOption, - preferencesSetting: localSettingOption!.setting, + preferencesSetting: localSettingOption, optionType: availableSettingOptions[index], onTapPreferencesOptionAction: controller.updateStateSettingOption, ); diff --git a/lib/features/manage_account/presentation/preferences/widgets/preferences_option_item.dart b/lib/features/manage_account/presentation/preferences/widgets/preferences_option_item.dart index ec3dc9f62..698255f88 100644 --- a/lib/features/manage_account/presentation/preferences/widgets/preferences_option_item.dart +++ b/lib/features/manage_account/presentation/preferences/widgets/preferences_option_item.dart @@ -4,9 +4,7 @@ import 'package:core/presentation/utils/theme_utils.dart'; import 'package:flutter/material.dart'; import 'package:server_settings/server_settings/tmail_server_settings.dart'; import 'package:tmail_ui_user/features/base/widget/default_switch_icon_widget.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/setting_option_type.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences/preferences_setting.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/preferences/preferences_setting.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/preferences_option_type.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; diff --git a/lib/features/thread_detail/data/data_source/thread_detail_local_data_source_impl.dart b/lib/features/thread_detail/data/data_source/thread_detail_local_data_source_impl.dart index 6a2dc2303..861552371 100644 --- a/lib/features/thread_detail/data/data_source/thread_detail_local_data_source_impl.dart +++ b/lib/features/thread_detail/data/data_source/thread_detail_local_data_source_impl.dart @@ -28,8 +28,8 @@ class ThreadDetailLocalDataSourceImpl implements ThreadDetailDataSource { @override Future getThreadDetailStatus() { return Future.sync(() async { - final preferencesRoot = await _preferencesSettingManager.loadPreferences(); - return preferencesRoot.setting.threadDetail.isEnabled; + final threadConfig = await _preferencesSettingManager.getThreadConfig(); + return threadConfig.isEnabled; }).catchError(_exceptionThrower.throwException); } } \ No newline at end of file