From a2a1f8246f5cb4c9b39c353f8168df3e3a9cfc4d Mon Sep 17 00:00:00 2001 From: dab246 Date: Sun, 24 Dec 2023 19:24:33 +0700 Subject: [PATCH] TF-2384 Store data to keychain when save new Account Signed-off-by: dab246 (cherry picked from commit 4d84a3354927d1c0becaf0e8e6d7cc8c54721f58) --- core/lib/utils/platform_info.dart | 23 +++++ .../widgets/recipient_composer_widget.dart | 4 +- .../hive_account_datasource_impl.dart | 15 ++- .../config/authorization_interceptors.dart | 58 +++++++----- .../authentication_user_interactor.dart | 15 ++- .../usecases/get_token_oidc_interactor.dart | 13 ++- .../mailbox_dashboard_controller.dart | 5 +- ..._field_autocomplete_email_address_web.dart | 4 +- .../bindings/fcm_interactor_bindings.dart | 9 +- .../controller/fcm_message_controller.dart | 49 +++++----- .../listener/email_change_listener.dart | 91 +++---------------- .../local_notification_manager.dart | 43 +++------ .../presentation/services/fcm_receiver.dart | 5 - .../presentation/services/fcm_service.dart | 22 ++--- .../presentation/utils/fcm_utils.dart | 29 +----- lib/main/bindings/core/core_bindings.dart | 12 +++ .../credential/credential_bindings.dart | 2 + lib/main/bindings/local/local_bindings.dart | 14 ++- .../bindings/network/network_bindings.dart | 19 +++- .../network/network_isolate_binding.dart | 2 + lib/main/utils/app_config.dart | 11 ++- lib/main/utils/app_constants.dart | 4 - 22 files changed, 211 insertions(+), 238 deletions(-) delete mode 100644 lib/main/utils/app_constants.dart diff --git a/core/lib/utils/platform_info.dart b/core/lib/utils/platform_info.dart index be125ca08..733f369cf 100644 --- a/core/lib/utils/platform_info.dart +++ b/core/lib/utils/platform_info.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:core/utils/app_logger.dart'; import 'package:flutter/foundation.dart'; abstract class PlatformInfo { @@ -7,8 +8,30 @@ abstract class PlatformInfo { static bool get isLinux => !kIsWeb && Platform.isLinux; static bool get isWindows => !kIsWeb && Platform.isWindows; static bool get isMacOS => !kIsWeb && Platform.isMacOS; + static bool get isFuchsia => !kIsWeb && Platform.isFuchsia; static bool get isIOS => !kIsWeb && Platform.isIOS; static bool get isAndroid => !kIsWeb && Platform.isAndroid; static bool get isMobile => isAndroid || isIOS; static bool get isDesktop => isLinux || isWindows || isMacOS; + + static String get platformNameOS { + var platformName = ''; + if (isWeb) { + platformName = 'Web'; + } else if (isAndroid) { + platformName = 'Android'; + } else if (isIOS) { + platformName = 'IOS'; + } else if (isFuchsia) { + platformName = 'Fuchsia'; + } else if (isLinux) { + platformName = 'Linux'; + } else if (isMacOS) { + platformName = 'MacOS'; + } else if (isWindows) { + platformName = 'Windows'; + } + log('PlatformInfo::platformNameOS(): $platformName'); + return platformName; + } } \ No newline at end of file diff --git a/lib/features/composer/presentation/widgets/recipient_composer_widget.dart b/lib/features/composer/presentation/widgets/recipient_composer_widget.dart index 340c4104a..db4a347b5 100644 --- a/lib/features/composer/presentation/widgets/recipient_composer_widget.dart +++ b/lib/features/composer/presentation/widgets/recipient_composer_widget.dart @@ -24,7 +24,7 @@ import 'package:tmail_ui_user/features/composer/presentation/styles/recipient_co import 'package:tmail_ui_user/features/composer/presentation/widgets/recipient_suggestion_item_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/recipient_tag_item_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -import 'package:tmail_ui_user/main/utils/app_constants.dart'; +import 'package:tmail_ui_user/main/utils/app_config.dart'; typedef OnSuggestionEmailAddress = Future> Function(String word); typedef OnUpdateListEmailAddressAction = void Function(PrefixEmailAddress prefix, List newData); @@ -359,7 +359,7 @@ class _RecipientComposerWidgetState extends State { } final tmailSuggestion = List.empty(growable: true); - if (processedQuery.length >= AppConstants.limitCharToStartSearch && + if (processedQuery.length >= AppConfig.limitCharToStartSearch && widget.onSuggestionEmailAddress != null) { final listEmailAddress = await widget.onSuggestionEmailAddress!(processedQuery); final listSuggestionEmailAddress = listEmailAddress.map((emailAddress) => _toSuggestionEmailAddress(emailAddress, _currentListEmailAddress)); diff --git a/lib/features/login/data/datasource_impl/hive_account_datasource_impl.dart b/lib/features/login/data/datasource_impl/hive_account_datasource_impl.dart index 5350bc49b..d6c160697 100644 --- a/lib/features/login/data/datasource_impl/hive_account_datasource_impl.dart +++ b/lib/features/login/data/datasource_impl/hive_account_datasource_impl.dart @@ -1,14 +1,21 @@ +import 'package:core/utils/platform_info.dart'; import 'package:model/account/personal_account.dart'; import 'package:tmail_ui_user/features/login/data/datasource/account_datasource.dart'; import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart'; import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart'; +import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart'; class HiveAccountDatasourceImpl extends AccountDatasource { final AccountCacheManager _accountCacheManager; + final IOSSharingManager _iosSharingManager; final ExceptionThrower _exceptionThrower; - HiveAccountDatasourceImpl(this._accountCacheManager, this._exceptionThrower); + HiveAccountDatasourceImpl( + this._accountCacheManager, + this._iosSharingManager, + this._exceptionThrower + ); @override Future getCurrentAccount() { @@ -20,7 +27,11 @@ class HiveAccountDatasourceImpl extends AccountDatasource { @override Future setCurrentAccount(PersonalAccount newCurrentAccount) { return Future.sync(() async { - return await _accountCacheManager.setCurrentAccount(newCurrentAccount); + await _accountCacheManager.setCurrentAccount(newCurrentAccount); + if (PlatformInfo.isIOS) { + await _iosSharingManager.saveKeyChainSharingSession(newCurrentAccount); + } + return Future.value(null); }).catchError(_exceptionThrower.throwException); } diff --git a/lib/features/login/data/network/config/authorization_interceptors.dart b/lib/features/login/data/network/config/authorization_interceptors.dart index 97c9c6879..214e240b2 100644 --- a/lib/features/login/data/network/config/authorization_interceptors.dart +++ b/lib/features/login/data/network/config/authorization_interceptors.dart @@ -3,20 +3,21 @@ import 'dart:convert'; import 'dart:io'; import 'package:core/utils/app_logger.dart'; +import 'package:core/utils/platform_info.dart'; import 'package:dio/dio.dart'; import 'package:get/get_connect/http/src/request/request.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'package:model/account/authentication_type.dart'; import 'package:model/account/password.dart'; import 'package:model/account/personal_account.dart'; -import 'package:model/account/authentication_type.dart'; import 'package:model/oidc/oidc_configuration.dart'; -import 'package:model/oidc/token.dart'; import 'package:model/oidc/token_oidc.dart'; -import 'package:tmail_ui_user/features/login/domain/extensions/oidc_configuration_extensions.dart'; import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart'; +import 'package:tmail_ui_user/features/login/domain/extensions/oidc_configuration_extensions.dart'; import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart'; +import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart'; class AuthorizationInterceptors extends QueuedInterceptorsWrapper { @@ -27,17 +28,19 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper { final AuthenticationClientBase _authenticationClient; final TokenOidcCacheManager _tokenOidcCacheManager; final AccountCacheManager _accountCacheManager; + final IOSSharingManager _iosSharingManager; AuthenticationType _authenticationType = AuthenticationType.none; OIDCConfiguration? _configOIDC; - Token? _token; + TokenOIDC? _token; String? _authorization; AuthorizationInterceptors( this._dio, this._authenticationClient, this._tokenOidcCacheManager, - this._accountCacheManager + this._accountCacheManager, + this._iosSharingManager, ); void setBasicAuthorization(UserName userName, Password password) { @@ -45,13 +48,13 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper { _authenticationType = AuthenticationType.basic; } - void setTokenAndAuthorityOidc({Token? newToken, OIDCConfiguration? newConfig}) { + void setTokenAndAuthorityOidc({TokenOIDC? newToken, OIDCConfiguration? newConfig}) { _token = newToken; _configOIDC = newConfig; _authenticationType = AuthenticationType.oidc; } - void _updateNewToken(Token newToken) { + void _updateNewToken(TokenOIDC newToken) { _token = newToken; } @@ -97,24 +100,9 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper { _token!.refreshToken ); - final currentAccount = await _accountCacheManager.getCurrentAccount(); + _updateNewToken(newToken); - await _accountCacheManager.deleteCurrentAccount(currentAccount.id); - - await Future.wait([ - _tokenOidcCacheManager.persistOneTokenOidc(newToken), - _accountCacheManager.setCurrentAccount( - PersonalAccount( - newToken.tokenIdHash, - AuthenticationType.oidc, - isSelected: true, - accountId: currentAccount.accountId, - apiUrl: currentAccount.apiUrl, - userName: currentAccount.userName - ) - ) - ]); - _updateNewToken(newToken.toToken()); + await _updateCurrentAccount(tokenOIDC: newToken); if (extraInRequest.containsKey(FileUploader.uploadAttachmentExtraKey)) { final uploadExtra = extraInRequest[FileUploader.uploadAttachmentExtraKey]; @@ -214,6 +202,28 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper { } } + Future _updateCurrentAccount({required TokenOIDC tokenOIDC}) async { + final currentAccount = await _accountCacheManager.getCurrentAccount(); + + await _accountCacheManager.deleteCurrentAccount(currentAccount.id); + + await _tokenOidcCacheManager.persistOneTokenOidc(tokenOIDC); + + final personalAccount = PersonalAccount( + tokenOIDC.tokenIdHash, + AuthenticationType.oidc, + isSelected: true, + accountId: currentAccount.accountId, + apiUrl: currentAccount.apiUrl, + userName: currentAccount.userName + ); + await _accountCacheManager.setCurrentAccount(personalAccount); + + if (PlatformInfo.isIOS) { + await _iosSharingManager.saveKeyChainSharingSession(personalAccount); + } + } + void clear() { _authorization = null; _token = null; diff --git a/lib/features/login/domain/usecases/authentication_user_interactor.dart b/lib/features/login/domain/usecases/authentication_user_interactor.dart index 5b56a896e..ba1f4f827 100644 --- a/lib/features/login/domain/usecases/authentication_user_interactor.dart +++ b/lib/features/login/domain/usecases/authentication_user_interactor.dart @@ -32,13 +32,20 @@ class AuthenticationInteractor { final user = await authenticationRepository.authenticationUser(baseUrl, userName, password); await Future.wait([ credentialRepository.saveBaseUrl(baseUrl), - credentialRepository.storeAuthenticationInfo(AuthenticationInfoCache(userName.value, password.value)), - _accountRepository.setCurrentAccount(PersonalAccount( + credentialRepository.storeAuthenticationInfo( + AuthenticationInfoCache( + userName.value, + password.value + ) + ), + ]); + await _accountRepository.setCurrentAccount( + PersonalAccount( userName.value, AuthenticationType.basic, isSelected: true - )) - ]); + ) + ); yield Right(AuthenticationUserSuccess(user)); } catch (e) { yield Left(AuthenticationUserFailure(e)); diff --git a/lib/features/login/domain/usecases/get_token_oidc_interactor.dart b/lib/features/login/domain/usecases/get_token_oidc_interactor.dart index 9455aac2f..9d8cdccf8 100644 --- a/lib/features/login/domain/usecases/get_token_oidc_interactor.dart +++ b/lib/features/login/domain/usecases/get_token_oidc_interactor.dart @@ -29,15 +29,20 @@ class GetTokenOIDCInteractor { config.redirectUrl, config.discoveryUrl, config.scopes); + await Future.wait([ _credentialRepository.saveBaseUrl(baseUrl), - _accountRepository.setCurrentAccount(PersonalAccount( - tokenOIDC.tokenIdHash, - AuthenticationType.oidc, - isSelected: true)), authenticationOIDCRepository.persistTokenOIDC(tokenOIDC), authenticationOIDCRepository.persistAuthorityOidc(config.authority), ]); + + await _accountRepository.setCurrentAccount( + PersonalAccount( + tokenOIDC.tokenIdHash, + AuthenticationType.oidc, + isSelected: true + ) + ); yield Right(GetTokenOIDCSuccess(tokenOIDC, config)); } catch (e) { logError('GetTokenOIDCInteractor::execute(): $e'); diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index d7db9a7b6..a3a830e6f 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -480,9 +480,9 @@ class MailboxDashBoardController extends ReloadableController { } @override - void injectFCMBindings(Session? session, AccountId? accountId) async { + Future injectFCMBindings(Session? session, AccountId? accountId) async { try { - super.injectFCMBindings(session, accountId); + await super.injectFCMBindings(session, accountId); await LocalNotificationManager.instance.recreateStreamController(); _registerLocalNotificationStreamListener(); } catch (e) { @@ -1674,7 +1674,6 @@ class MailboxDashBoardController extends ReloadableController { } void _handleMessageFromNotification(String? payload, {bool onForeground = true}) async { - await LocalNotificationManager.instance.removeNotificationBadgeForIOS(); log('MailboxDashBoardController::_handleMessageFromNotification():payload: $payload'); if (payload == null || payload.isEmpty) { dispatchRoute(DashboardRoutes.thread); diff --git a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_autocomplete_email_address_web.dart b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_autocomplete_email_address_web.dart index 17b249584..a063f309d 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_autocomplete_email_address_web.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/text_field_autocomplete_email_address_web.dart @@ -17,7 +17,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/adv import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/text_field_autocomplete_email_address_web_style.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/autocomplete_suggestion_item_widget_web.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/autocomplete_tag_item_widget_web.dart'; -import 'package:tmail_ui_user/main/utils/app_constants.dart'; +import 'package:tmail_ui_user/main/utils/app_config.dart'; typedef OnSuggestionEmailAddress = Future> Function(String word); typedef OnUpdateListEmailAddressAction = void Function(AdvancedSearchFilterField field, List newData); @@ -216,7 +216,7 @@ class _TextFieldAutocompleteEmailAddressWebState extends State.empty(growable: true); - if (processedQuery.length >= AppConstants.limitCharToStartSearch && + if (processedQuery.length >= AppConfig.limitCharToStartSearch && widget.onSuggestionEmailAddress != null) { final listEmailAddress = await widget.onSuggestionEmailAddress!(processedQuery); final listSuggestionEmailAddress = listEmailAddress.map((emailAddress) => _toSuggestionEmailAddress(emailAddress, _currentListEmailAddress)); diff --git a/lib/features/push_notification/presentation/bindings/fcm_interactor_bindings.dart b/lib/features/push_notification/presentation/bindings/fcm_interactor_bindings.dart index d23a8d594..d5eb8a9d0 100644 --- a/lib/features/push_notification/presentation/bindings/fcm_interactor_bindings.dart +++ b/lib/features/push_notification/presentation/bindings/fcm_interactor_bindings.dart @@ -2,7 +2,6 @@ import 'package:core/data/model/source_type/data_source_type.dart'; import 'package:core/utils/file_utils.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/features/base/interactors_bindings.dart'; -import 'package:tmail_ui_user/features/caching/clients/state_cache_client.dart'; import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart'; import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart'; import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart'; @@ -20,6 +19,7 @@ import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_cach import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/state_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.dart'; +import 'package:tmail_ui_user/features/mailbox/data/local/state_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_api.dart'; import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_isolate_worker.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/new_email_cache_manager.dart'; @@ -28,8 +28,8 @@ import 'package:tmail_ui_user/features/offline_mode/manager/opened_email_cache_m import 'package:tmail_ui_user/features/offline_mode/manager/opened_email_cache_worker_queue.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/sending_email_cache_manager.dart'; import 'package:tmail_ui_user/features/push_notification/data/datasource/fcm_datasource.dart'; -import 'package:tmail_ui_user/features/push_notification/data/datasource_impl/fcm_datasource_impl.dart'; import 'package:tmail_ui_user/features/push_notification/data/datasource_impl/cache_fcm_datasource_impl.dart'; +import 'package:tmail_ui_user/features/push_notification/data/datasource_impl/fcm_datasource_impl.dart'; import 'package:tmail_ui_user/features/push_notification/data/local/fcm_cache_manager.dart'; import 'package:tmail_ui_user/features/push_notification/data/network/fcm_api.dart'; import 'package:tmail_ui_user/features/push_notification/data/repository/fcm_repository_impl.dart'; @@ -101,8 +101,9 @@ class FcmInteractorBindings extends InteractorsBindings { Get.find(), Get.find())); Get.lazyPut(() => StateDataSourceImpl( - Get.find(), - Get.find())); + Get.find(), + Get.find() + )); Get.lazyPut(() => EmailHiveCacheDataSourceImpl( Get.find(), Get.find(), diff --git a/lib/features/push_notification/presentation/controller/fcm_message_controller.dart b/lib/features/push_notification/presentation/controller/fcm_message_controller.dart index cb4d11f2a..e12a925fa 100644 --- a/lib/features/push_notification/presentation/controller/fcm_message_controller.dart +++ b/lib/features/push_notification/presentation/controller/fcm_message_controller.dart @@ -6,14 +6,13 @@ import 'package:core/data/network/config/dynamic_url_interceptors.dart'; import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:core/utils/app_logger.dart'; +import 'package:core/utils/platform_info.dart'; import 'package:fcm/model/type_name.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/push/state_change.dart'; -import 'package:model/oidc/token_oidc.dart'; import 'package:rxdart/rxdart.dart'; import 'package:tmail_ui_user/features/base/action/ui_action.dart'; import 'package:tmail_ui_user/features/caching/config/hive_cache_config.dart'; @@ -46,7 +45,7 @@ class FcmMessageController extends FcmBaseController { AccountId? _currentAccountId; Session? _currentSession; UserName? _userName; - RemoteMessage? _remoteMessageBackground; + Map? _payloadData; GetAuthenticatedAccountInteractor? _getAuthenticatedAccountInteractor; DynamicUrlInterceptors? _dynamicUrlInterceptors; @@ -92,24 +91,24 @@ class FcmMessageController extends FcmBaseController { .listen(FcmTokenController.instance.onFcmTokenChanged); } - void _handleForegroundMessageAction(RemoteMessage newRemoteMessage) { - log('FcmMessageController::_handleForegroundMessageAction():remoteMessage: ${newRemoteMessage.data} | _currentAccountId: $_currentAccountId'); + void _handleForegroundMessageAction(Map payloadData) { + log('FcmMessageController::_handleForegroundMessageAction():payloadData: $payloadData | _currentAccountId: $_currentAccountId'); if (_currentAccountId != null && _userName != null) { - final stateChange = _convertRemoteMessageToStateChange(newRemoteMessage); + final stateChange = _parsingPayloadData(payloadData); final mapTypeState = stateChange.getMapTypeState(_currentAccountId!); _mappingTypeStateToAction(mapTypeState, _currentAccountId!, _userName!, session: _currentSession); } } - void _handleBackgroundMessageAction(RemoteMessage newRemoteMessage) async { - log('FcmMessageController::_handleBackgroundMessageAction():remoteMessage: ${newRemoteMessage.data}'); - _remoteMessageBackground = newRemoteMessage; + void _handleBackgroundMessageAction(Map payloadData) async { + log('FcmMessageController::_handleBackgroundMessageAction():payloadData: $payloadData'); + _payloadData = payloadData; await _initialAppConfig(); _getAuthenticatedAccount(); } - StateChange? _convertRemoteMessageToStateChange(RemoteMessage newRemoteMessage) { - return FcmUtils.instance.convertFirebaseDataMessageToStateChange(newRemoteMessage.data); + StateChange? _parsingPayloadData(Map payloadData) { + return FcmUtils.instance.convertFirebaseDataMessageToStateChange(payloadData); } void _mappingTypeStateToAction( @@ -217,7 +216,7 @@ class FcmMessageController extends FcmBaseController { if (_getAuthenticatedAccountInteractor != null) { consumeState(_getAuthenticatedAccountInteractor!.execute()); } else { - _clearRemoteMessageBackground(); + _clearPayloadData(); logError('FcmMessageController::_getAuthenticatedAccount():_getAuthenticatedAccountInteractor is null'); } } @@ -225,7 +224,7 @@ class FcmMessageController extends FcmBaseController { void _handleGetAuthenticatedAccountSuccess(GetAuthenticatedAccountSuccess success) { _currentAccountId = success.account.accountId; _userName = success.account.userName; - if (!FcmUtils.instance.isMobileAndroid) { + if (!PlatformInfo.isAndroid) { _dynamicUrlInterceptors?.changeBaseUrl(success.account.apiUrl); } log('FcmMessageController::_handleGetAuthenticatedAccountSuccess():_currentAccountId: $_currentAccountId | _userName: $_userName'); @@ -235,11 +234,11 @@ class FcmMessageController extends FcmBaseController { log('FcmMessageController::_handleGetAccountByOidcSuccess():'); _dynamicUrlInterceptors?.setJmapUrl(storedTokenOidcSuccess.baseUrl.toString()); _authorizationInterceptors?.setTokenAndAuthorityOidc( - newToken: storedTokenOidcSuccess.tokenOidc.toToken(), + newToken: storedTokenOidcSuccess.tokenOidc, newConfig: storedTokenOidcSuccess.oidcConfiguration ); - if (FcmUtils.instance.isMobileAndroid) { + if (PlatformInfo.isAndroid) { _dynamicUrlInterceptors?.changeBaseUrl(storedTokenOidcSuccess.baseUrl.toString()); _getSessionAction(); } else { @@ -254,7 +253,7 @@ class FcmMessageController extends FcmBaseController { credentialViewState.userName, credentialViewState.password, ); - if (FcmUtils.instance.isMobileAndroid) { + if (PlatformInfo.isAndroid) { _dynamicUrlInterceptors?.changeBaseUrl(credentialViewState.baseUrl.toString()); _getSessionAction(); } else { @@ -266,7 +265,7 @@ class FcmMessageController extends FcmBaseController { if (_getSessionInteractor != null) { consumeState(_getSessionInteractor!.execute()); } else { - _clearRemoteMessageBackground(); + _clearPayloadData(); logError('FcmMessageController::_getSessionAction():_getSessionInteractor is null'); } } @@ -280,29 +279,29 @@ class FcmMessageController extends FcmBaseController { _dynamicUrlInterceptors?.changeBaseUrl(apiUrl); _pushActionFromRemoteMessageBackground(); } else { - _clearRemoteMessageBackground(); + _clearPayloadData(); logError('FcmMessageController::_handleGetSessionSuccess():apiUrl is null'); } } void _pushActionFromRemoteMessageBackground() { - log('FcmMessageController::_pushActionFromRemoteMessageBackground():_remoteMessageBackground: $_remoteMessageBackground | _currentAccountId: $_currentAccountId | _currentSession: $_currentSession'); - if (_remoteMessageBackground != null && _currentAccountId != null && _userName != null) { - final stateChange = _convertRemoteMessageToStateChange(_remoteMessageBackground!); + log('FcmMessageController::_pushActionFromRemoteMessageBackground():_payloadData: $_payloadData | _currentAccountId: $_currentAccountId | _currentSession: $_currentSession'); + if (_payloadData?.isNotEmpty == true && _currentAccountId != null && _userName != null) { + final stateChange = _parsingPayloadData(_payloadData!); final mapTypeState = stateChange.getMapTypeState(_currentAccountId!); _mappingTypeStateToAction(mapTypeState, _currentAccountId!, _userName!, isForeground: false, session: _currentSession); } - _clearRemoteMessageBackground(); + _clearPayloadData(); } - void _clearRemoteMessageBackground() { - _remoteMessageBackground = null; + void _clearPayloadData() { + _payloadData = null; } @override void handleFailureViewState(Failure failure) { log('FcmMessageController::_handleFailureViewState(): $failure'); - _clearRemoteMessageBackground(); + _clearPayloadData(); } @override diff --git a/lib/features/push_notification/presentation/listener/email_change_listener.dart b/lib/features/push_notification/presentation/listener/email_change_listener.dart index de567bc9c..adcc60dad 100644 --- a/lib/features/push_notification/presentation/listener/email_change_listener.dart +++ b/lib/features/push_notification/presentation/listener/email_change_listener.dart @@ -1,6 +1,4 @@ -import 'dart:io'; - import 'package:core/data/network/config/dynamic_url_interceptors.dart'; import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; @@ -46,13 +44,9 @@ import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_e import 'package:tmail_ui_user/features/push_notification/domain/usecases/store_email_state_to_refresh_interactor.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/action/fcm_action.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/listener/change_listener.dart'; -import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_config.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_manager.dart'; -import 'package:tmail_ui_user/features/push_notification/presentation/utils/fcm_utils.dart'; import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; -import 'package:uuid/uuid.dart'; class EmailChangeListener extends ChangeListener { @@ -103,7 +97,7 @@ class EmailChangeListener extends ChangeListener { log('EmailChangeListener::dispatchActions():actions: $actions'); for (var action in actions) { if (action is SynchronizeEmailOnForegroundAction) { - if (FcmUtils.instance.isMobileAndroid) { + if (PlatformInfo.isAndroid) { _handleRemoveNotificationWhenEmailMarkAsRead(action.newState, action.accountId, action.session); } _synchronizeEmailOnForegroundAction(action.newState); @@ -113,11 +107,11 @@ class EmailChangeListener extends ChangeListener { } else if (action is PushNotificationAction) { _pushNotificationAction(action.newState, action.accountId, action.userName, action.session); - if (FcmUtils.instance.isMobileAndroid) { + if (PlatformInfo.isAndroid) { _getNewReceiveEmailFromNotificationAction(action.session, action.accountId, action.newState); } } else if (action is StoreEmailStateToRefreshAction) { - if (FcmUtils.instance.isMobileAndroid) { + if (PlatformInfo.isAndroid) { _handleRemoveNotificationWhenEmailMarkAsRead(action.newState, action.accountId, action.session); } _handleStoreEmailStateToRefreshAction(action.accountId, action.userName, action.newState); @@ -141,32 +135,20 @@ class EmailChangeListener extends ChangeListener { if (PlatformInfo.isWeb) { _storeEmailDeliveryStateAction(accountId, userName, _newStateEmailDelivery!); - } else { - if (Platform.isAndroid) { - _getStoredEmailDeliveryState(accountId, userName); - } else if (Platform.isIOS) { - _storeEmailDeliveryStateAction(accountId, userName, _newStateEmailDelivery!); - _showLocalNotificationForIOS(_newStateEmailDelivery!, accountId); - } else { - logError('EmailChangeListener::_pushNotificationAction(): NOT SUPPORTED PLATFORM'); - } + } else if (PlatformInfo.isAndroid) { + _getStoredEmailDeliveryState(accountId, userName); } } void _getStoredEmailDeliveryState(AccountId accountId, UserName userName) { if (_getStoredEmailDeliveryStateInteractor != null) { consumeState(_getStoredEmailDeliveryStateInteractor!.execute(accountId, userName)); - } else { - _showDefaultLocalNotification(); } } void _getStoredEmailState() { if (_getStoredEmailStateInteractor != null && _session != null && _accountId != null) { consumeState(_getStoredEmailStateInteractor!.execute(_session!, _accountId!)); - } else { - _showDefaultLocalNotification(); - logError('EmailChangeListener::_getStoredEmailState(): _getStoredEmailStateInteractor is null'); } } @@ -183,16 +165,12 @@ class EmailChangeListener extends ChangeListener { propertiesCreated: EmailUtils.getPropertiesForEmailGetMethod(_session!, _accountId!), propertiesUpdated: ThreadConstants.propertiesUpdatedDefault, )); - } else { - _showDefaultLocalNotification(); } } void _storeEmailDeliveryStateAction(AccountId accountId, UserName userName, jmap.State state) { if (_storeEmailDeliveryStateInteractor != null) { consumeState(_storeEmailDeliveryStateInteractor!.execute(accountId, userName, state)); - } else { - _showDefaultLocalNotification(); } } @@ -208,48 +186,12 @@ class EmailChangeListener extends ChangeListener { ); } - void _showLocalNotificationForIOS(jmap.State newState, AccountId accountId) async { - final notificationPayload = NotificationPayload(newState: newState); - log('EmailChangeListener::_showLocalNotificationForIOS():notificationPayload: $notificationPayload'); - LocalNotificationManager.instance.showPushNotification( - id: '${FcmUtils.instance.platformOS}-${accountId.id.value}', - title: currentContext != null - ? AppLocalizations.of(currentContext!).appTitlePushNotification - : LocalNotificationConfig.notificationTitle, - message: currentContext != null - ? AppLocalizations.of(currentContext!).youHaveNewMessages - : LocalNotificationConfig.notificationMessage, - payload: notificationPayload.encodeToString, - ); - await LocalNotificationManager.instance.setNotificationBadgeForIOS(); - } - - void _showDefaultLocalNotification() { - LocalNotificationManager.instance.showPushNotification( - id: '${FcmUtils.instance.platformOS}-${const Uuid().v1()}', - title: currentContext != null - ? AppLocalizations.of(currentContext!).appTitlePushNotification - : LocalNotificationConfig.notificationTitle, - message: currentContext != null - ? AppLocalizations.of(currentContext!).youHaveNewMessages - : LocalNotificationConfig.notificationMessage, - ); - - if (PlatformInfo.isAndroid) { - LocalNotificationManager.instance.groupPushNotification(); - } - } - @override void handleFailureViewState(Failure failure) { log('EmailChangeListener::_handleFailureViewState(): $failure'); if (failure is GetStoredEmailDeliveryStateFailure && failure.exception is NotFoundEmailDeliveryStateException) { _getStoredEmailState(); - } else if (failure is NotFoundEmailState || - failure is GetStoredEmailStateFailure || - failure is GetEmailChangesToPushNotificationFailure) { - _showDefaultLocalNotification(); } else if (failure is GetMailboxesNotPutNotificationsFailure) { final listEmails = _emailsAvailablePushNotification.toEmailsAvailablePushNotification(); _handleLocalPushNotification(listEmails); @@ -259,25 +201,15 @@ class EmailChangeListener extends ChangeListener { @override void handleSuccessViewState(Success success) { log('EmailChangeListener::_handleSuccessViewState(): $success'); - if (success is GetStoredEmailDeliveryStateSuccess) { - if (_newStateEmailDelivery != success.state) { - _getEmailChangesAction(success.state); - } else { - _showDefaultLocalNotification(); - } + if (success is GetStoredEmailDeliveryStateSuccess && _newStateEmailDelivery != success.state) { + _getEmailChangesAction(success.state); } else if (success is GetStoredEmailStateSuccess) { _getEmailChangesAction(success.state); - } else if (success is GetEmailChangesToPushNotificationSuccess) { - if (_newStateEmailDelivery != null) { - _storeEmailDeliveryStateAction(success.accountId, success.userName, _newStateEmailDelivery!); + } else if (success is GetEmailChangesToPushNotificationSuccess && _newStateEmailDelivery != null) { + _storeEmailDeliveryStateAction(success.accountId, success.userName, _newStateEmailDelivery!); - if (FcmUtils.instance.isMobileAndroid) { - _handleListEmailToPushNotification(success.emailList); - } else { - _showDefaultLocalNotification(); - } - } else { - _showDefaultLocalNotification(); + if (PlatformInfo.isAndroid) { + _handleListEmailToPushNotification(success.emailList); } } else if (success is GetMailboxesNotPutNotificationsSuccess) { final listEmails = _emailsAvailablePushNotification.toEmailsAvailablePushNotification( @@ -308,7 +240,6 @@ class EmailChangeListener extends ChangeListener { void _handleLocalPushNotification(List emailList) { log('EmailChangeListener::_handleLocalPushNotification():emailList: $emailList'); if (emailList.isEmpty) { - _showDefaultLocalNotification(); return; } diff --git a/lib/features/push_notification/presentation/notification/local_notification_manager.dart b/lib/features/push_notification/presentation/notification/local_notification_manager.dart index abf2f2c2e..7d0c6bf56 100644 --- a/lib/features/push_notification/presentation/notification/local_notification_manager.dart +++ b/lib/features/push_notification/presentation/notification/local_notification_manager.dart @@ -1,16 +1,13 @@ import 'dart:async'; -import 'dart:io'; import 'package:core/presentation/extensions/html_extension.dart'; import 'package:core/utils/app_logger.dart'; import 'package:core/utils/platform_info.dart'; -import 'package:flutter_app_badger/flutter_app_badger.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/extensions/email_address_extension.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_config.dart'; -import 'package:tmail_ui_user/features/push_notification/presentation/utils/fcm_utils.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; @@ -38,15 +35,14 @@ class LocalNotificationManager { Future setUp() async { try { await _initLocalNotification(); - _checkLocalNotificationPermission(); - if (Platform.isAndroid) { + await _checkLocalNotificationPermission(); + if (PlatformInfo.isAndroid) { await _createAndroidNotificationChannelGroup(); await _createAndroidNotificationChannel(); } } catch (e) { logError('LocalNotificationManager::setUp(): ERROR: ${e.toString()}'); } - return Future.value(); } Future getCurrentNotificationResponse() async { @@ -56,7 +52,7 @@ class LocalNotificationManager { } catch (e) { logError('LocalNotificationManager::getCurrentNotificationResponse(): ERROR: ${e.toString()}'); } - return Future.value(null); + return null; } set activatedNotificationClickedOnTerminate(bool clicked) => _isNotificationClickedOnTerminate = clicked; @@ -82,19 +78,19 @@ class LocalNotificationManager { } } - void _checkLocalNotificationPermission() async { + Future _checkLocalNotificationPermission() async { if (_notificationsEnabled) { - return; + return Future.value(null); } - if (Platform.isAndroid) { + if (PlatformInfo.isAndroid) { final granted = await _isAndroidPermissionGranted(); if (!granted) { _notificationsEnabled = await _requestPermissions(); } else { _notificationsEnabled = granted; } - } else { + } else if (PlatformInfo.isIOS) { _notificationsEnabled = await _requestPermissions(); } } @@ -106,14 +102,16 @@ class LocalNotificationManager { } Future _requestPermissions() async { - if (Platform.isAndroid) { + if (PlatformInfo.isAndroid) { return await _localNotificationsPlugin .resolvePlatformSpecificImplementation() ?.requestPermission() ?? false; - } else { + } else if (PlatformInfo.isIOS) { return await _localNotificationsPlugin .resolvePlatformSpecificImplementation() ?.requestPermissions(alert: true, badge: true, sound: true) ?? false; + } else { + return false; } } @@ -166,14 +164,11 @@ class LocalNotificationManager { } Future removeNotification(String id) async { - if (id.startsWith(FcmUtils.instance.platformOS)) { - await removeNotificationBadgeForIOS(); - } return _localNotificationsPlugin.cancel(id.hashCode); } void groupPushNotification() async { - if (Platform.isIOS) { + if (PlatformInfo.isIOS) { return; } @@ -223,18 +218,4 @@ class LocalNotificationManager { void closeStream() { localNotificationsController.close(); } - - Future setNotificationBadgeForIOS() async { - log("LocalNotificationManager::setNotificationBadgeForIOS:"); - if (PlatformInfo.isIOS) { - await FlutterAppBadger.updateBadgeCount(1); - } - } - - Future removeNotificationBadgeForIOS() async { - log("LocalNotificationManager::removeNotificationBadgeForIOS:"); - if (PlatformInfo.isIOS) { - await FlutterAppBadger.removeBadge(); - } - } } \ No newline at end of file diff --git a/lib/features/push_notification/presentation/services/fcm_receiver.dart b/lib/features/push_notification/presentation/services/fcm_receiver.dart index 9354e72d0..0c35b74ac 100644 --- a/lib/features/push_notification/presentation/services/fcm_receiver.dart +++ b/lib/features/push_notification/presentation/services/fcm_receiver.dart @@ -26,7 +26,6 @@ class FcmReceiver { _onForegroundMessage(); _onBackgroundMessage(); - _onMessageOpenedApp(); } void _onForegroundMessage() { @@ -37,10 +36,6 @@ class FcmReceiver { FirebaseMessaging.onBackgroundMessage(handleFirebaseBackgroundMessage); } - void _onMessageOpenedApp() { - FirebaseMessaging.onMessageOpenedApp.listen(FcmService.instance.handleFirebaseMessageOpenedApp); - } - Future _getInitialToken() async { final token = await FirebaseMessaging.instance.getToken( vapidKey: PlatformInfo.isWeb ? AppConfig.fcmVapidPublicKeyWeb : null diff --git a/lib/features/push_notification/presentation/services/fcm_service.dart b/lib/features/push_notification/presentation/services/fcm_service.dart index a752a6ae4..8fad4b46e 100644 --- a/lib/features/push_notification/presentation/services/fcm_service.dart +++ b/lib/features/push_notification/presentation/services/fcm_service.dart @@ -3,15 +3,14 @@ import 'dart:async'; import 'package:core/utils/app_logger.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_manager.dart'; class FcmService { static const int durationMessageComing = 2000; static const int durationRefreshToken = 2000; - StreamController? foregroundMessageStreamController; - StreamController? backgroundMessageStreamController; + StreamController>? foregroundMessageStreamController; + StreamController>? backgroundMessageStreamController; StreamController? fcmTokenStreamController; FcmService._internal(); @@ -22,17 +21,16 @@ class FcmService { void handleFirebaseForegroundMessage(RemoteMessage newRemoteMessage) { log('FcmService::handleFirebaseForegroundMessage():data: ${newRemoteMessage.data}'); - foregroundMessageStreamController?.add(newRemoteMessage); + if (newRemoteMessage.data.isNotEmpty) { + foregroundMessageStreamController?.add(newRemoteMessage.data); + } } void handleFirebaseBackgroundMessage(RemoteMessage newRemoteMessage) { log('FcmService::handleFirebaseBackgroundMessage():data: ${newRemoteMessage.data}'); - backgroundMessageStreamController?.add(newRemoteMessage); - } - - void handleFirebaseMessageOpenedApp(RemoteMessage newRemoteMessage) async { - log("FcmService::handleFirebaseMessageOpenedApp:"); - await LocalNotificationManager.instance.removeNotificationBadgeForIOS(); + if (newRemoteMessage.data.isNotEmpty) { + backgroundMessageStreamController?.add(newRemoteMessage.data); + } } void handleToken(String? token) { @@ -42,8 +40,8 @@ class FcmService { void initialStreamController() { log('FcmService::initialStreamController:'); - foregroundMessageStreamController = StreamController.broadcast(); - backgroundMessageStreamController = StreamController.broadcast(); + foregroundMessageStreamController = StreamController>.broadcast(); + backgroundMessageStreamController = StreamController>.broadcast(); fcmTokenStreamController = StreamController.broadcast(); } diff --git a/lib/features/push_notification/presentation/utils/fcm_utils.dart b/lib/features/push_notification/presentation/utils/fcm_utils.dart index 92956b7d1..eac695e36 100644 --- a/lib/features/push_notification/presentation/utils/fcm_utils.dart +++ b/lib/features/push_notification/presentation/utils/fcm_utils.dart @@ -1,6 +1,4 @@ -import 'dart:io'; - import 'package:core/domain/extensions/datetime_extension.dart'; import 'package:core/utils/app_logger.dart'; import 'package:core/utils/platform_info.dart'; @@ -94,38 +92,13 @@ class FcmUtils { return object == null || (object is String && object.isEmpty); } - String get platformOS { - var platformName = ''; - if (PlatformInfo.isWeb) { - platformName = 'Web'; - } else { - if (Platform.isAndroid) { - platformName = 'Android'; - } else if (Platform.isIOS) { - platformName = 'IOS'; - } else if (Platform.isFuchsia) { - platformName = 'Fuchsia'; - } else if (Platform.isLinux) { - platformName = 'Linux'; - } else if (Platform.isMacOS) { - platformName = 'MacOS'; - } else if (Platform.isWindows) { - platformName = 'Windows'; - } - } - log('FcmUtils::platformOS():$platformName'); - return platformName; - } - String hashTokenToDeviceId(String token) { final tokenHashCode = token.hashCode.toString(); - final deviceId = '$hashCodeKey-$platformOS-$tokenHashCode'; + final deviceId = '$hashCodeKey-${PlatformInfo.platformNameOS}-$tokenHashCode'; log('FcmUtils::hashCodeTokenToDeviceId():deviceId: $deviceId'); return deviceId; } - bool get isMobileAndroid => PlatformInfo.isMobile && Platform.isAndroid; - bool checkExpirationTimeWithinGivenPeriod({ required DateTime expiredTime, required DateTime currentTime, diff --git a/lib/main/bindings/core/core_bindings.dart b/lib/main/bindings/core/core_bindings.dart index 13be1151c..f0c364914 100644 --- a/lib/main/bindings/core/core_bindings.dart +++ b/lib/main/bindings/core/core_bindings.dart @@ -7,9 +7,11 @@ import 'package:core/utils/config/app_config_loader.dart'; import 'package:core/utils/file_utils.dart'; import 'package:core/utils/platform_info.dart'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tmail_ui_user/features/sending_queue/presentation/utils/sending_queue_isolate_manager.dart'; +import 'package:tmail_ui_user/main/utils/app_config.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; import 'package:uuid/uuid.dart'; @@ -25,6 +27,7 @@ class CoreBindings extends Bindings { _bindingReceivingSharingStream(); _bindingUtils(); _bindingIsolate(); + _bindingStorage(); } void _bindingAppImagePaths() { @@ -64,4 +67,13 @@ class CoreBindings extends Bindings { Get.put(SendingQueueIsolateManager()); } } + + void _bindingStorage() { + Get.put(const FlutterSecureStorage( + iOptions: IOSOptions( + groupId: AppConfig.iOSKeychainSharingGroupId, + accountName: AppConfig.iOSKeychainSharingService, + ) + )); + } } \ No newline at end of file diff --git a/lib/main/bindings/credential/credential_bindings.dart b/lib/main/bindings/credential/credential_bindings.dart index 7f3e6bb5f..15c0f2798 100644 --- a/lib/main/bindings/credential/credential_bindings.dart +++ b/lib/main/bindings/credential/credential_bindings.dart @@ -31,6 +31,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/update_authenticati import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart'; +import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart'; class CredentialBindings extends InteractorsBindings { @@ -67,6 +68,7 @@ class CredentialBindings extends InteractorsBindings { void bindingsDataSourceImpl() { Get.put(HiveAccountDatasourceImpl( Get.find(), + Get.find(), Get.find()) ); Get.put(AuthenticationDataSourceImpl()); diff --git a/lib/main/bindings/local/local_bindings.dart b/lib/main/bindings/local/local_bindings.dart index 38fd8eeb0..1243284e2 100644 --- a/lib/main/bindings/local/local_bindings.dart +++ b/lib/main/bindings/local/local_bindings.dart @@ -1,13 +1,15 @@ import 'package:core/utils/file_utils.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/caching/clients/account_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/authentication_info_cache_client.dart'; -import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/caching/clients/email_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/encryption_key_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/fcm_cache_client.dart'; +import 'package:tmail_ui_user/features/caching/clients/firebase_registration_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/hive_cache_version_client.dart'; import 'package:tmail_ui_user/features/caching/clients/mailbox_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/new_email_hive_cache_client.dart'; @@ -18,7 +20,6 @@ import 'package:tmail_ui_user/features/caching/clients/recent_search_cache_clien import 'package:tmail_ui_user/features/caching/clients/sending_email_hive_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/session_hive_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/state_cache_client.dart'; -import 'package:tmail_ui_user/features/caching/clients/firebase_registration_cache_client.dart'; import 'package:tmail_ui_user/features/caching/clients/token_oidc_cache_client.dart'; import 'package:tmail_ui_user/features/cleanup/data/local/recent_login_url_cache_manager.dart'; import 'package:tmail_ui_user/features/cleanup/data/local/recent_login_username_cache_manager.dart'; @@ -29,6 +30,7 @@ import 'package:tmail_ui_user/features/login/data/local/encryption_key_cache_man import 'package:tmail_ui_user/features/login/data/local/oidc_configuration_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.dart'; +import 'package:tmail_ui_user/features/mailbox/data/local/state_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/local/local_spam_report_manager.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/new_email_cache_manager.dart'; @@ -36,6 +38,7 @@ import 'package:tmail_ui_user/features/offline_mode/manager/new_email_cache_work import 'package:tmail_ui_user/features/offline_mode/manager/opened_email_cache_manager.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/opened_email_cache_worker_queue.dart'; import 'package:tmail_ui_user/features/offline_mode/manager/sending_email_cache_manager.dart'; +import 'package:tmail_ui_user/features/push_notification/data/keychain/keychain_sharing_manager.dart'; import 'package:tmail_ui_user/features/push_notification/data/local/fcm_cache_manager.dart'; import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart'; import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart'; @@ -45,6 +48,7 @@ class LocalBindings extends Bindings { @override void dependencies() { _bindingException(); + _bindingKeychainSharing(); _bindingCaching(); _bindingWorkerQueue(); } @@ -52,6 +56,7 @@ class LocalBindings extends Bindings { void _bindingCaching() { Get.put(MailboxCacheClient()); Get.put(StateCacheClient()); + Get.put(StateCacheManager(Get.find())); Get.put(MailboxCacheManager(Get.find())); Get.put(EmailCacheClient()); Get.put(EmailCacheManager(Get.find())); @@ -98,6 +103,7 @@ class LocalBindings extends Bindings { Get.find(), Get.find(), Get.find(), + Get.find(), )); } @@ -109,4 +115,8 @@ class LocalBindings extends Bindings { Get.put(NewEmailCacheWorkerQueue()); Get.put(OpenedEmailCacheWorkerQueue()); } + + void _bindingKeychainSharing() { + Get.put(KeychainSharingManager(Get.find())); + } } \ No newline at end of file diff --git a/lib/main/bindings/network/network_bindings.dart b/lib/main/bindings/network/network_bindings.dart index 653aa29fb..1e1b3d99a 100644 --- a/lib/main/bindings/network/network_bindings.dart +++ b/lib/main/bindings/network/network_bindings.dart @@ -14,6 +14,7 @@ import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; import 'package:tmail_ui_user/features/email/data/network/mdn_api.dart'; import 'package:tmail_ui_user/features/home/data/network/session_api.dart'; import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart'; +import 'package:tmail_ui_user/features/login/data/local/authentication_info_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart'; import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart'; @@ -21,17 +22,20 @@ import 'package:tmail_ui_user/features/login/data/network/config/time_out_interc import 'package:tmail_ui_user/features/login/data/network/dns_service.dart'; import 'package:tmail_ui_user/features/login/data/network/oidc_http_client.dart'; import 'package:tmail_ui_user/features/login/data/utils/library_platform/app_auth_plugin/app_auth_plugin.dart'; +import 'package:tmail_ui_user/features/mailbox/data/local/state_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_api.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/network/spam_report_api.dart'; import 'package:tmail_ui_user/features/manage_account/data/network/forwarding_api.dart'; import 'package:tmail_ui_user/features/manage_account/data/network/identity_api.dart'; import 'package:tmail_ui_user/features/manage_account/data/network/rule_filter_api.dart'; import 'package:tmail_ui_user/features/manage_account/data/network/vacation_api.dart'; +import 'package:tmail_ui_user/features/push_notification/data/keychain/keychain_sharing_manager.dart'; import 'package:tmail_ui_user/features/push_notification/data/network/fcm_api.dart'; import 'package:tmail_ui_user/features/quotas/data/network/quotas_api.dart'; import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart'; import 'package:tmail_ui_user/main/localizations/locale_interceptor.dart'; +import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart'; import 'package:uuid/uuid.dart'; class NetworkBindings extends Bindings { @@ -39,7 +43,10 @@ class NetworkBindings extends Bindings { @override void dependencies() { _bindingConnection(); + _bindingBaseOption(); _bindingDio(); + _bindingSharing(); + _bindingInterceptors(); _bindingApi(); _bindingTransformer(); _bindingServices(); @@ -55,14 +62,21 @@ class NetworkBindings extends Bindings { } void _bindingDio() { - _bindingBaseOption(); Get.put(Dio(Get.find())); Get.put(DioClient(Get.find())); Get.put(const FlutterAppAuth()); Get.put(AppAuthWebPlugin()); Get.put(OIDCHttpClient(Get.find())); Get.put(AuthenticationClientBase()); - _bindingInterceptors(); + } + + void _bindingSharing() { + Get.put(IOSSharingManager( + Get.find(), + Get.find(), + Get.find(), + Get.find(), + )); } void _bindingInterceptors() { @@ -72,6 +86,7 @@ class NetworkBindings extends Bindings { Get.find(), Get.find(), Get.find(), + Get.find(), )); Get.put(LocaleInterceptor()); Get.put(TimeOutInterceptors()); diff --git a/lib/main/bindings/network/network_isolate_binding.dart b/lib/main/bindings/network/network_isolate_binding.dart index c6e260652..b1f6aa911 100644 --- a/lib/main/bindings/network/network_isolate_binding.dart +++ b/lib/main/bindings/network/network_isolate_binding.dart @@ -16,6 +16,7 @@ import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart'; import 'package:tmail_ui_user/features/thread/data/network/thread_isolate_worker.dart'; import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:tmail_ui_user/main/localizations/locale_interceptor.dart'; +import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart'; import 'package:uuid/uuid.dart'; import 'package:worker_manager/worker_manager.dart'; @@ -43,6 +44,7 @@ class NetworkIsolateBindings extends Bindings { Get.find(tag: BindingTag.isolateTag), Get.find(tag: BindingTag.isolateTag), Get.find(tag: BindingTag.isolateTag), + Get.find(), ), tag: BindingTag.isolateTag); dio.interceptors.add(Get.find()); dio.interceptors.add(Get.find(tag: BindingTag.isolateTag)); diff --git a/lib/main/utils/app_config.dart b/lib/main/utils/app_config.dart index 438716759..a4e21708b 100644 --- a/lib/main/utils/app_config.dart +++ b/lib/main/utils/app_config.dart @@ -5,6 +5,13 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.dart'; class AppConfig { + static const int limitCharToStartSearch = 3; + + static const String appDashboardConfigurationPath = "configurations/app_dashboard.json"; + static const String appFCMConfigurationPath = "configurations/env.fcm"; + static const String iOSKeychainSharingGroupId = 'KUT463DS29.com.linagora.ios.teammail.shared'; + static const String iOSKeychainSharingService = 'com.linagora.ios.teammail.sessions'; + static String get baseUrl => dotenv.get('SERVER_URL', fallback: ''); static String get domainRedirectUrl => dotenv.get('DOMAIN_REDIRECT_URL', fallback: ''); static String get webOidcClientId => dotenv.get('WEB_OIDC_CLIENT_ID', fallback: ''); @@ -15,7 +22,6 @@ class AppConfig { } return false; } - static String appDashboardConfigurationPath = "configurations/app_dashboard.json"; static bool get fcmAvailable { final supportedOtherPlatform = dotenv.get('FCM_AVAILABLE', fallback: 'unsupported'); final supportedIOSPlatform = dotenv.get('IOS_FCM', fallback: 'unsupported'); @@ -26,10 +32,7 @@ class AppConfig { return supportedOtherPlatform == 'supported'; } } - static String appFCMConfigurationPath = "configurations/env.fcm"; - static String get fcmVapidPublicKeyWeb => dotenv.get('FIREBASE_WEB_VAPID_PUBLIC_KEY', fallback: ''); - static List get oidcScopes { try { final envScopes = dotenv.get('OIDC_SCOPES', fallback: ''); diff --git a/lib/main/utils/app_constants.dart b/lib/main/utils/app_constants.dart deleted file mode 100644 index c4b8fc78a..000000000 --- a/lib/main/utils/app_constants.dart +++ /dev/null @@ -1,4 +0,0 @@ - -class AppConstants { - static const int limitCharToStartSearch = 3; -} \ No newline at end of file