TF-2871 Handle click notification to open detailed email on iOS
This commit is contained in:
@@ -106,7 +106,7 @@ abstract class BaseController extends GetxController
|
||||
(failure) {
|
||||
if (failure is FeatureFailure) {
|
||||
final exception = _performFilterExceptionInError(failure.exception);
|
||||
logError('BaseController::onData:exception: $exception');
|
||||
logError('$runtimeType::onData:exception: $exception');
|
||||
if (exception != null) {
|
||||
handleExceptionAction(failure: failure, exception: exception);
|
||||
} else {
|
||||
@@ -120,7 +120,7 @@ abstract class BaseController extends GetxController
|
||||
}
|
||||
|
||||
void onError(Object error, StackTrace stackTrace) {
|
||||
logError('BaseController::onError():error: $error | stackTrace: $stackTrace');
|
||||
logError('$runtimeType::onError():error: $error | stackTrace: $stackTrace');
|
||||
final exception = _performFilterExceptionInError(error);
|
||||
if (exception != null) {
|
||||
handleExceptionAction(exception: exception);
|
||||
@@ -132,7 +132,7 @@ abstract class BaseController extends GetxController
|
||||
void onDone() {}
|
||||
|
||||
Exception? _performFilterExceptionInError(dynamic error) {
|
||||
logError('BaseController::_performFilterExceptionInError(): $error');
|
||||
logError('$runtimeType::_performFilterExceptionInError(): $error');
|
||||
if (error is NoNetworkError || error is ConnectionTimeout || error is InternalServerError) {
|
||||
if (PlatformInfo.isWeb && currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastMessage(
|
||||
@@ -157,7 +157,7 @@ abstract class BaseController extends GetxController
|
||||
void handleErrorViewState(Object error, StackTrace stackTrace) {}
|
||||
|
||||
void handleExceptionAction({Failure? failure, Exception? exception}) {
|
||||
logError('BaseController::handleExceptionAction():failure: $failure | exception: $exception');
|
||||
logError('$runtimeType::handleExceptionAction():failure: $failure | exception: $exception');
|
||||
if (exception is ConnectionError) {
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
@@ -183,7 +183,7 @@ abstract class BaseController extends GetxController
|
||||
}
|
||||
|
||||
void handleFailureViewState(Failure failure) async {
|
||||
logError('BaseController::handleFailureViewState(): ${failure.runtimeType}');
|
||||
logError('$runtimeType::handleFailureViewState():Failure = $failure');
|
||||
if (failure is LogoutOidcFailure) {
|
||||
if (_isFcmEnabled) {
|
||||
_getStoredFirebaseRegistrationFromCache();
|
||||
@@ -197,7 +197,7 @@ abstract class BaseController extends GetxController
|
||||
}
|
||||
|
||||
void handleSuccessViewState(Success success) async {
|
||||
log('BaseController::handleSuccessViewState(): ${success.runtimeType}');
|
||||
log('$runtimeType::handleSuccessViewState():Success = ${success.runtimeType}');
|
||||
if (success is LogoutOidcSuccess) {
|
||||
if (_isFcmEnabled) {
|
||||
_getStoredFirebaseRegistrationFromCache();
|
||||
@@ -214,7 +214,7 @@ abstract class BaseController extends GetxController
|
||||
void startFpsMeter() {
|
||||
FpsManager().start();
|
||||
fpsCallback = (fpsInfo) {
|
||||
log('BaseController::startFpsMeter(): $fpsInfo');
|
||||
log('$runtimeType::startFpsMeter(): $fpsInfo');
|
||||
};
|
||||
if (fpsCallback != null) {
|
||||
FpsManager().addFpsCallback(fpsCallback!);
|
||||
@@ -234,7 +234,7 @@ abstract class BaseController extends GetxController
|
||||
requireCapability(session!, accountId!, [tmailContactCapabilityIdentifier]);
|
||||
TMailAutoCompleteBindings().dependencies();
|
||||
} catch (e) {
|
||||
logError('BaseController::injectAutoCompleteBindings(): exception: $e');
|
||||
logError('$runtimeType::injectAutoCompleteBindings(): exception: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ abstract class BaseController extends GetxController
|
||||
requireCapability(session!, accountId!, [CapabilityIdentifier.jmapMdn]);
|
||||
MdnInteractorBindings().dependencies();
|
||||
} catch(e) {
|
||||
logError('BaseController::injectMdnBindings(): exception: $e');
|
||||
logError('$runtimeType::injectMdnBindings(): exception: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ abstract class BaseController extends GetxController
|
||||
requireCapability(session!, accountId!, [capabilityForward]);
|
||||
ForwardingInteractorsBindings().dependencies();
|
||||
} catch(e) {
|
||||
logError('BaseController::injectForwardBindings(): exception: $e');
|
||||
logError('$runtimeType::injectForwardBindings(): exception: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,14 +261,14 @@ abstract class BaseController extends GetxController
|
||||
requireCapability(session!, accountId!, [capabilityRuleFilter]);
|
||||
EmailRulesInteractorBindings().dependencies();
|
||||
} catch(e) {
|
||||
logError('BaseController::injectRuleFilterBindings(): exception: $e');
|
||||
logError('$runtimeType::injectRuleFilterBindings(): exception: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> injectFCMBindings(Session? session, AccountId? accountId) async {
|
||||
try {
|
||||
requireCapability(session!, accountId!, [FirebaseCapability.fcmIdentifier]);
|
||||
log('BaseController::injectFCMBindings: fcmAvailable = ${AppConfig.fcmAvailable}');
|
||||
log('$runtimeType::injectFCMBindings: fcmAvailable = ${AppConfig.fcmAvailable}');
|
||||
if (AppConfig.fcmAvailable) {
|
||||
final mapEnvData = Map<String, String>.from(dotenv.env);
|
||||
await AppUtils.loadFcmConfigFileToEnv(currentMapEnvData: mapEnvData);
|
||||
@@ -285,7 +285,7 @@ abstract class BaseController extends GetxController
|
||||
throw NotSupportFCMException();
|
||||
}
|
||||
} catch(e) {
|
||||
logError('BaseController::injectFCMBindings(): exception: $e');
|
||||
logError('$runtimeType::injectFCMBindings(): exception: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ abstract class BaseController extends GetxController
|
||||
}
|
||||
|
||||
Future<void> clearDataAndGoToLoginPage() async {
|
||||
log('BaseController::clearDataAndGoToLoginPage:');
|
||||
log('$runtimeType::clearDataAndGoToLoginPage:');
|
||||
await clearAllData();
|
||||
goToLogin();
|
||||
}
|
||||
|
||||
@@ -6,16 +6,18 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:model/account/password.dart';
|
||||
import 'package:model/oidc/oidc_configuration.dart';
|
||||
import 'package:model/oidc/token_oidc.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/state/get_authenticated_account_state.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/state/get_credential_state.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/state/get_stored_token_oidc_state.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/state/update_authentication_account_state.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/usecases/get_authenticated_account_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/usecases/update_authentication_account_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/usecases/update_account_cache_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_interactors_bindings.dart';
|
||||
import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/remote_exception.dart';
|
||||
@@ -26,16 +28,18 @@ import 'package:tmail_ui_user/main/utils/message_toast_utils.dart';
|
||||
abstract class ReloadableController extends BaseController {
|
||||
final GetSessionInteractor _getSessionInteractor = Get.find<GetSessionInteractor>();
|
||||
final GetAuthenticatedAccountInteractor _getAuthenticatedAccountInteractor = Get.find<GetAuthenticatedAccountInteractor>();
|
||||
final UpdateAuthenticationAccountInteractor _updateAuthenticationAccountInteractor = Get.find<UpdateAuthenticationAccountInteractor>();
|
||||
final UpdateAccountCacheInteractor _updateAccountCacheInteractor = Get.find<UpdateAccountCacheInteractor>();
|
||||
|
||||
@override
|
||||
void handleFailureViewState(Failure failure) {
|
||||
if (failure is GetCredentialFailure ||
|
||||
failure is GetStoredTokenOidcFailure ||
|
||||
failure is GetAuthenticatedAccountFailure) {
|
||||
log('ReloadableController::handleFailureViewState(): failure: $failure');
|
||||
failure is GetAuthenticatedAccountFailure ||
|
||||
failure is UpdateAccountCacheFailure) {
|
||||
logError('$runtimeType::handleFailureViewState():Failure = $failure');
|
||||
goToLogin();
|
||||
} else if (failure is GetSessionFailure) {
|
||||
logError('$runtimeType::handleFailureViewState():Failure = $failure');
|
||||
_handleGetSessionFailure(failure.exception);
|
||||
} else {
|
||||
super.handleFailureViewState(failure);
|
||||
@@ -45,11 +49,26 @@ abstract class ReloadableController extends BaseController {
|
||||
@override
|
||||
void handleSuccessViewState(Success success) {
|
||||
if (success is GetCredentialViewState) {
|
||||
_handleGetCredentialSuccess(success);
|
||||
} else if (success is GetSessionSuccess) {
|
||||
_handleGetSessionSuccess(success);
|
||||
log('$runtimeType::handleSuccessViewState:Success = ${success.runtimeType}');
|
||||
_setDataToInterceptors(
|
||||
baseUrl: success.baseUrl.origin,
|
||||
userName: success.userName,
|
||||
password: success.password);
|
||||
getSessionAction();
|
||||
} else if (success is GetStoredTokenOidcSuccess) {
|
||||
_handleGetStoredTokenOIDCSuccess(success);
|
||||
log('$runtimeType::handleSuccessViewState:Success = ${success.runtimeType}');
|
||||
_setDataToInterceptors(
|
||||
baseUrl: success.baseUrl.toString(),
|
||||
tokenOIDC: success.tokenOidc,
|
||||
oidcConfiguration: success.oidcConfiguration);
|
||||
getSessionAction();
|
||||
} else if (success is GetSessionSuccess) {
|
||||
log('$runtimeType::handleSuccessViewState:Success = ${success.runtimeType}');
|
||||
updateAccountCache(success.session);
|
||||
} else if (success is UpdateAccountCacheSuccess) {
|
||||
log('$runtimeType::handleSuccessViewState:Success = ${success.runtimeType}');
|
||||
dynamicUrlInterceptors.changeBaseUrl(success.apiUrl);
|
||||
handleReloaded(success.session);
|
||||
} else {
|
||||
super.handleSuccessViewState(success);
|
||||
}
|
||||
@@ -66,22 +85,25 @@ abstract class ReloadableController extends BaseController {
|
||||
consumeState(_getAuthenticatedAccountInteractor.execute());
|
||||
}
|
||||
|
||||
void _setUpInterceptors(GetCredentialViewState credentialViewState) {
|
||||
dynamicUrlInterceptors.setJmapUrl(credentialViewState.baseUrl.origin);
|
||||
dynamicUrlInterceptors.changeBaseUrl(credentialViewState.baseUrl.origin);
|
||||
authorizationInterceptors.setBasicAuthorization(
|
||||
credentialViewState.userName,
|
||||
credentialViewState.password,
|
||||
);
|
||||
authorizationIsolateInterceptors.setBasicAuthorization(
|
||||
credentialViewState.userName,
|
||||
credentialViewState.password,
|
||||
);
|
||||
}
|
||||
void _setDataToInterceptors({
|
||||
required String baseUrl,
|
||||
UserName? userName,
|
||||
Password? password,
|
||||
TokenOIDC? tokenOIDC,
|
||||
OIDCConfiguration? oidcConfiguration
|
||||
}) {
|
||||
dynamicUrlInterceptors.setJmapUrl(baseUrl);
|
||||
dynamicUrlInterceptors.changeBaseUrl(baseUrl);
|
||||
|
||||
void _handleGetCredentialSuccess(GetCredentialViewState credentialViewState) {
|
||||
_setUpInterceptors(credentialViewState);
|
||||
getSessionAction();
|
||||
if (userName != null && password != null) {
|
||||
authorizationInterceptors.setBasicAuthorization(userName, password);
|
||||
authorizationIsolateInterceptors.setBasicAuthorization(userName, password);
|
||||
}
|
||||
|
||||
if (tokenOIDC != null && oidcConfiguration != null) {
|
||||
authorizationInterceptors.setTokenAndAuthorityOidc(newToken: tokenOIDC, newConfig: oidcConfiguration);
|
||||
authorizationIsolateInterceptors.setTokenAndAuthorityOidc(newToken: tokenOIDC, newConfig: oidcConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
void getSessionAction() {
|
||||
@@ -98,50 +120,18 @@ abstract class ReloadableController extends BaseController {
|
||||
clearDataAndGoToLoginPage();
|
||||
}
|
||||
|
||||
void _handleGetSessionSuccess(GetSessionSuccess success) {
|
||||
final session = success.session;
|
||||
final personalAccount = session.personalAccount;
|
||||
final apiUrl = session.getQualifiedApiUrl(baseUrl: dynamicUrlInterceptors.jmapUrl);
|
||||
if (apiUrl.isNotEmpty) {
|
||||
dynamicUrlInterceptors.changeBaseUrl(apiUrl);
|
||||
updateAuthenticationAccount(session, personalAccount.accountId, session.username);
|
||||
handleReloaded(session);
|
||||
} else {
|
||||
clearDataAndGoToLoginPage();
|
||||
}
|
||||
}
|
||||
|
||||
void handleReloaded(Session session) {}
|
||||
|
||||
void _handleGetStoredTokenOIDCSuccess(GetStoredTokenOidcSuccess tokenOidcSuccess) {
|
||||
_setUpInterceptorsOidc(tokenOidcSuccess);
|
||||
getSessionAction();
|
||||
}
|
||||
|
||||
void _setUpInterceptorsOidc(GetStoredTokenOidcSuccess tokenOidcSuccess) {
|
||||
dynamicUrlInterceptors.setJmapUrl(tokenOidcSuccess.baseUrl.toString());
|
||||
dynamicUrlInterceptors.changeBaseUrl(tokenOidcSuccess.baseUrl.toString());
|
||||
authorizationInterceptors.setTokenAndAuthorityOidc(
|
||||
newToken: tokenOidcSuccess.tokenOidc,
|
||||
newConfig: tokenOidcSuccess.oidcConfiguration);
|
||||
authorizationIsolateInterceptors.setTokenAndAuthorityOidc(
|
||||
newToken: tokenOidcSuccess.tokenOidc,
|
||||
newConfig: tokenOidcSuccess.oidcConfiguration);
|
||||
}
|
||||
|
||||
void injectVacationBindings(Session? session, AccountId? accountId) {
|
||||
try {
|
||||
requireCapability(session!, accountId!, [CapabilityIdentifier.jmapVacationResponse]);
|
||||
VacationInteractorsBindings().dependencies();
|
||||
} catch(e) {
|
||||
logError('ReloadableController::injectVacationBindings(): exception: $e');
|
||||
logError('$runtimeType::injectVacationBindings(): exception: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void updateAuthenticationAccount(Session session, AccountId accountId, UserName userName) {
|
||||
final apiUrl = session.getQualifiedApiUrl(baseUrl: dynamicUrlInterceptors.jmapUrl);
|
||||
if (apiUrl.isNotEmpty) {
|
||||
consumeState(_updateAuthenticationAccountInteractor.execute(accountId, apiUrl, userName));
|
||||
}
|
||||
void updateAccountCache(Session session) {
|
||||
consumeState(_updateAccountCacheInteractor.execute(session));
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,8 @@ import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_downloader/flutter_downloader.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/account/personal_account.dart';
|
||||
import 'package:model/email/email_content.dart';
|
||||
import 'package:model/email/email_content_type.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
@@ -21,12 +18,11 @@ import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_email_cac
|
||||
import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_login_url_cache_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_login_username_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_search_cache_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/preview_email_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/services/fcm_receiver.dart';
|
||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
import 'package:tmail_ui_user/main/utils/email_receive_manager.dart';
|
||||
import 'package:tmail_ui_user/main/utils/ios_notification_manager.dart';
|
||||
|
||||
class HomeController extends ReloadableController {
|
||||
final CleanupEmailCacheInteractor _cleanupEmailCacheInteractor;
|
||||
@@ -35,6 +31,8 @@ class HomeController extends ReloadableController {
|
||||
final CleanupRecentLoginUrlCacheInteractor _cleanupRecentLoginUrlCacheInteractor;
|
||||
final CleanupRecentLoginUsernameCacheInteractor _cleanupRecentLoginUsernameCacheInteractor;
|
||||
|
||||
IOSNotificationManager? _iosNotificationManager;
|
||||
|
||||
HomeController(
|
||||
this._cleanupEmailCacheInteractor,
|
||||
this._emailReceiveManager,
|
||||
@@ -43,9 +41,6 @@ class HomeController extends ReloadableController {
|
||||
this._cleanupRecentLoginUsernameCacheInteractor,
|
||||
);
|
||||
|
||||
PersonalAccount? currentAccount;
|
||||
EmailId? _emailIdPreview;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
if (PlatformInfo.isMobile) {
|
||||
@@ -53,7 +48,7 @@ class HomeController extends ReloadableController {
|
||||
_registerReceivingSharingIntent();
|
||||
}
|
||||
if (PlatformInfo.isIOS) {
|
||||
_handleIOSDataMessage();
|
||||
_registerNotificationClickOnIOS();
|
||||
}
|
||||
super.onInit();
|
||||
}
|
||||
@@ -66,20 +61,9 @@ class HomeController extends ReloadableController {
|
||||
|
||||
@override
|
||||
void handleReloaded(Session session) {
|
||||
if (_emailIdPreview != null) {
|
||||
popAndPush(
|
||||
RouteUtils.generateNavigationRoute(AppRoutes.dashboard),
|
||||
arguments: PreviewEmailArguments(
|
||||
session: session,
|
||||
emailId: _emailIdPreview!
|
||||
)
|
||||
);
|
||||
} else {
|
||||
popAndPush(
|
||||
RouteUtils.generateNavigationRoute(AppRoutes.dashboard),
|
||||
arguments: session
|
||||
);
|
||||
}
|
||||
pushAndPopAll(
|
||||
RouteUtils.generateNavigationRoute(AppRoutes.dashboard),
|
||||
arguments: session);
|
||||
}
|
||||
|
||||
void _initFlutterDownloader() {
|
||||
@@ -90,7 +74,7 @@ class HomeController extends ReloadableController {
|
||||
|
||||
static void downloadCallback(String id, DownloadTaskStatus status, int progress) {}
|
||||
|
||||
void _cleanupCache() async {
|
||||
Future<void> _cleanupCache() async {
|
||||
await HiveCacheConfig.instance.onUpgradeDatabase(cachingManager);
|
||||
|
||||
await Future.wait([
|
||||
@@ -98,7 +82,7 @@ class HomeController extends ReloadableController {
|
||||
_cleanupRecentSearchCacheInteractor.execute(RecentSearchCleanupRule()),
|
||||
_cleanupRecentLoginUrlCacheInteractor.execute(RecentLoginUrlCleanupRule()),
|
||||
_cleanupRecentLoginUsernameCacheInteractor.execute(RecentLoginUsernameCleanupRule()),
|
||||
]).then((value) => getAuthenticatedAccountAction());
|
||||
], eagerError: true).then((_) => getAuthenticatedAccountAction());
|
||||
}
|
||||
|
||||
void _registerReceivingSharingIntent() {
|
||||
@@ -117,17 +101,8 @@ class HomeController extends ReloadableController {
|
||||
_emailReceiveManager.receivingFileSharingStream.listen(_emailReceiveManager.setPendingFileInfo);
|
||||
}
|
||||
|
||||
Future _handleIOSDataMessage() async {
|
||||
if (Get.arguments is EmailId) {
|
||||
_emailIdPreview = Get.arguments;
|
||||
} else {
|
||||
final notificationInfo = await FcmReceiver.instance.getIOSInitialNotificationInfo();
|
||||
if (notificationInfo != null && notificationInfo.containsKey('email_id')) {
|
||||
final emailId = notificationInfo['email_id'] as String?;
|
||||
if (emailId?.isNotEmpty == true) {
|
||||
_emailIdPreview = EmailId(Id(emailId!));
|
||||
}
|
||||
}
|
||||
}
|
||||
void _registerNotificationClickOnIOS() {
|
||||
_iosNotificationManager = getBinding<IOSNotificationManager>();
|
||||
_iosNotificationManager?.listenClickNotification();
|
||||
}
|
||||
}
|
||||
@@ -48,11 +48,11 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
||||
_token = newToken;
|
||||
_configOIDC = newConfig;
|
||||
_authenticationType = AuthenticationType.oidc;
|
||||
log('AuthorizationInterceptors::setTokenAndAuthorityOidc: INITIAL_TOKEN = ${newToken?.token} | EXPIRED_TIME = ${newToken?.expiredTime}');
|
||||
log('AuthorizationInterceptors::setTokenAndAuthorityOidc: TokenId = ${newToken?.tokenIdHash}');
|
||||
}
|
||||
|
||||
void _updateNewToken(TokenOIDC newToken) {
|
||||
log('AuthorizationInterceptors::_updateNewToken: NEW_TOKEN = ${newToken.token} | EXPIRED_TIME = ${newToken.expiredTime}');
|
||||
log('AuthorizationInterceptors::_updateNewToken: TokenId = ${newToken.tokenIdHash}');
|
||||
_token = newToken;
|
||||
}
|
||||
|
||||
@@ -76,13 +76,13 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
||||
case AuthenticationType.none:
|
||||
break;
|
||||
}
|
||||
log('AuthorizationInterceptors::onRequest(): URL = ${options.uri} | HEADER = ${options.headers} | DATA = ${options.data} | METHOD = ${options.method}');
|
||||
log('AuthorizationInterceptors::onRequest(): URL = ${options.uri} | DATA = ${options.data}');
|
||||
super.onRequest(options, handler);
|
||||
}
|
||||
|
||||
@override
|
||||
void onError(DioError err, ErrorInterceptorHandler handler) async {
|
||||
logError('AuthorizationInterceptors::onError(): TOKEN = ${_token?.expiredTime} | DIO_ERROR = $err | METHOD = ${err.requestOptions.method}');
|
||||
logError('AuthorizationInterceptors::onError(): DIO_ERROR = $err');
|
||||
try {
|
||||
final requestOptions = err.requestOptions;
|
||||
final extraInRequest = requestOptions.extra;
|
||||
@@ -92,24 +92,29 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
||||
responseStatusCode: err.response?.statusCode,
|
||||
tokenOIDC: _token
|
||||
)) {
|
||||
log('AuthorizationInterceptors::onError:_validateToRefreshToken');
|
||||
log('AuthorizationInterceptors::onError: Perform get New Token');
|
||||
final newTokenOidc = PlatformInfo.isIOS
|
||||
? await _handleRefreshTokenOnIOSPlatform()
|
||||
: await _handleRefreshTokenOnOtherPlatform();
|
||||
? await _getNewTokenForIOSPlatform()
|
||||
: await _getNewTokenForOtherPlatform();
|
||||
|
||||
if (newTokenOidc.token == _token?.token) {
|
||||
log('AuthorizationInterceptors::onError: TokenOIDC duplicated');
|
||||
log('AuthorizationInterceptors::onError: Token duplicated');
|
||||
return super.onError(err, handler);
|
||||
}
|
||||
|
||||
_updateNewToken(newTokenOidc);
|
||||
|
||||
final personalAccount = await _updateCurrentAccount(tokenOIDC: newTokenOidc);
|
||||
|
||||
if (PlatformInfo.isIOS) {
|
||||
await _iosSharingManager.saveKeyChainSharingSession(personalAccount);
|
||||
}
|
||||
|
||||
isRetryRequest = true;
|
||||
} else if (validateToRetryTheRequestWithNewToken(
|
||||
authHeader: requestOptions.headers[HttpHeaders.authorizationHeader],
|
||||
tokenOIDC: _token
|
||||
)) {
|
||||
log('AuthorizationInterceptors::onError:validateToRetryTheRequestWithNewToken');
|
||||
log('AuthorizationInterceptors::onError: Request using old token');
|
||||
isRetryRequest = true;
|
||||
} else {
|
||||
return super.onError(err, handler);
|
||||
@@ -117,7 +122,7 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
||||
|
||||
if (isRetryRequest) {
|
||||
if (extraInRequest.containsKey(FileUploader.uploadAttachmentExtraKey)) {
|
||||
log('AuthorizationInterceptors::onError: Perform upload attachment request');
|
||||
log('AuthorizationInterceptors::onError: Retry upload request with TokenId = ${_token?.tokenIdHash}');
|
||||
final uploadExtra = extraInRequest[FileUploader.uploadAttachmentExtraKey];
|
||||
|
||||
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(_token!.token);
|
||||
@@ -136,7 +141,7 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
||||
|
||||
return handler.resolve(response);
|
||||
} else {
|
||||
log('AuthorizationInterceptors::onError: Perform normal request');
|
||||
log('AuthorizationInterceptors::onError: Retry request with TokenId = ${_token?.tokenIdHash}');
|
||||
requestOptions.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(_token!.token);
|
||||
|
||||
final response = await _dio.fetch(requestOptions);
|
||||
@@ -231,13 +236,11 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
||||
|
||||
Future<TokenOIDC?> _getTokenInKeychain(TokenOIDC currentTokenOidc) async {
|
||||
final currentAccount = await _accountCacheManager.getCurrentAccount();
|
||||
log('AuthorizationInterceptors::_getTokenInKeychain:currentAccount: $currentAccount');
|
||||
if (currentAccount.accountId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final keychainSharingSession = await _iosSharingManager.getKeychainSharingSession(currentAccount.accountId!);
|
||||
log('AuthorizationInterceptors::_getTokenInKeychain:keychainSharingSession: $keychainSharingSession');
|
||||
if (keychainSharingSession == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -250,36 +253,29 @@ class AuthorizationInterceptors extends QueuedInterceptorsWrapper {
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<TokenOIDC> _invokeRefreshTokenFromServer() async {
|
||||
final newToken = await _authenticationClient.refreshingTokensOIDC(
|
||||
Future<TokenOIDC> _invokeRefreshTokenFromServer() {
|
||||
log('AuthorizationInterceptors::_invokeRefreshTokenFromServer:');
|
||||
return _authenticationClient.refreshingTokensOIDC(
|
||||
_configOIDC!.clientId,
|
||||
_configOIDC!.redirectUrl,
|
||||
_configOIDC!.discoveryUrl,
|
||||
_configOIDC!.scopes,
|
||||
_token!.refreshToken
|
||||
);
|
||||
log('AuthorizationInterceptors::_invokeRefreshTokenFromServer:newToken: $newToken');
|
||||
return newToken;
|
||||
}
|
||||
|
||||
Future<TokenOIDC> _handleRefreshTokenOnIOSPlatform() async {
|
||||
final keychainToken = await _getTokenInKeychain(_token!);
|
||||
|
||||
if (keychainToken == null) {
|
||||
final newToken = await _invokeRefreshTokenFromServer();
|
||||
final newAccount = await _updateCurrentAccount(tokenOIDC: newToken);
|
||||
await _iosSharingManager.saveKeyChainSharingSession(newAccount);
|
||||
return newToken;
|
||||
Future<TokenOIDC> _getNewTokenForIOSPlatform() async {
|
||||
final tokenInKeychain = await _getTokenInKeychain(_token!);
|
||||
log('AuthorizationInterceptors::_handleRefreshTokenOnIOSPlatform: KeychainTokenId = ${tokenInKeychain?.tokenIdHash} | isTokenExpired = ${_isTokenExpired(tokenInKeychain)}');
|
||||
if (tokenInKeychain == null || _isTokenExpired(tokenInKeychain)) {
|
||||
return _invokeRefreshTokenFromServer();
|
||||
} else {
|
||||
await _updateCurrentAccount(tokenOIDC: keychainToken);
|
||||
return keychainToken;
|
||||
return tokenInKeychain;
|
||||
}
|
||||
}
|
||||
|
||||
Future<TokenOIDC> _handleRefreshTokenOnOtherPlatform() async {
|
||||
final newToken = await _invokeRefreshTokenFromServer();
|
||||
await _updateCurrentAccount(tokenOIDC: newToken);
|
||||
return newToken;
|
||||
Future<TokenOIDC> _getNewTokenForOtherPlatform() {
|
||||
return _invokeRefreshTokenFromServer();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
|
||||
class UpdateAuthenticationAccountLoading extends LoadingState {}
|
||||
class UpdatingAccountCache extends LoadingState {}
|
||||
|
||||
class UpdateAuthenticationAccountSuccess extends UIState {}
|
||||
class UpdateAccountCacheSuccess extends UIState {
|
||||
final Session session;
|
||||
final String apiUrl;
|
||||
|
||||
class UpdateAuthenticationAccountFailure extends FeatureFailure {
|
||||
UpdateAccountCacheSuccess({
|
||||
required this.session,
|
||||
required this.apiUrl});
|
||||
|
||||
UpdateAuthenticationAccountFailure(dynamic exception) : super(exception: exception);
|
||||
@override
|
||||
List<Object?> get props => [session, apiUrl];
|
||||
}
|
||||
|
||||
class UpdateAccountCacheFailure extends FeatureFailure {
|
||||
|
||||
UpdateAccountCacheFailure(dynamic exception) : super(exception: exception);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:model/account/authentication_type.dart';
|
||||
import 'package:model/account/personal_account.dart';
|
||||
import 'package:model/extensions/personal_account_extension.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/state/update_authentication_account_state.dart';
|
||||
|
||||
class UpdateAccountCacheInteractor {
|
||||
final AccountRepository _accountRepository;
|
||||
final CredentialRepository _credentialRepository;
|
||||
|
||||
UpdateAccountCacheInteractor(
|
||||
this._accountRepository,
|
||||
this._credentialRepository);
|
||||
|
||||
Stream<Either<Failure, Success>> execute(Session session) async* {
|
||||
try{
|
||||
yield Right(UpdatingAccountCache());
|
||||
|
||||
final futureValue = await Future.wait([
|
||||
_credentialRepository.getBaseUrl(),
|
||||
_accountRepository.getCurrentAccount(),
|
||||
], eagerError: true);
|
||||
|
||||
final baseUrl = futureValue[0] as Uri;
|
||||
final currentAccount = futureValue[1] as PersonalAccount;
|
||||
final apiUrl = session.getQualifiedApiUrl(
|
||||
baseUrl: currentAccount.authenticationType == AuthenticationType.basic
|
||||
? baseUrl.origin
|
||||
: baseUrl.toString());
|
||||
|
||||
await _accountRepository.setCurrentAccount(
|
||||
currentAccount.fromAccount(
|
||||
accountId: session.accountId,
|
||||
apiUrl: apiUrl,
|
||||
userName: session.username
|
||||
));
|
||||
|
||||
yield Right(UpdateAccountCacheSuccess(
|
||||
session: session,
|
||||
apiUrl: apiUrl));
|
||||
} catch(e) {
|
||||
yield Left(UpdateAccountCacheFailure(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:model/extensions/personal_account_extension.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/state/update_authentication_account_state.dart';
|
||||
|
||||
class UpdateAuthenticationAccountInteractor {
|
||||
final AccountRepository _accountRepository;
|
||||
|
||||
UpdateAuthenticationAccountInteractor(this._accountRepository);
|
||||
|
||||
Stream<Either<Failure, Success>> execute(AccountId accountId, String apiUrl, UserName userName) async* {
|
||||
try{
|
||||
yield Right(UpdateAuthenticationAccountLoading());
|
||||
final currentAccount = await _accountRepository.getCurrentAccount();
|
||||
await _accountRepository.setCurrentAccount(
|
||||
currentAccount.fromAccount(
|
||||
accountId: accountId,
|
||||
apiUrl: apiUrl,
|
||||
userName: userName
|
||||
)
|
||||
);
|
||||
yield Right(UpdateAuthenticationAccountSuccess());
|
||||
} catch(e) {
|
||||
yield Left(UpdateAuthenticationAccountFailure(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
-31
@@ -94,7 +94,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/comp
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_routes.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/download/download_task_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/draggable_app_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/preview_email_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/refresh_action_view_event.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_receive_time_type.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_sort_order_type.dart';
|
||||
@@ -153,6 +152,7 @@ import 'package:tmail_ui_user/main/routes/navigation_router.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
import 'package:tmail_ui_user/main/utils/email_receive_manager.dart';
|
||||
import 'package:tmail_ui_user/main/utils/ios_notification_manager.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class MailboxDashBoardController extends ReloadableController {
|
||||
@@ -197,6 +197,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
GetMailboxStateToRefreshInteractor? _getMailboxStateToRefreshInteractor;
|
||||
DeleteMailboxStateToRefreshInteractor? _deleteMailboxStateToRefreshInteractor;
|
||||
GetAutoCompleteInteractor? _getAutoCompleteInteractor;
|
||||
IOSNotificationManager? _iosNotificationManager;
|
||||
|
||||
final scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final selectedMailbox = Rxn<PresentationMailbox>();
|
||||
@@ -234,6 +235,8 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
late StreamSubscription _emailContentStreamSubscription;
|
||||
late StreamSubscription _fileReceiveManagerStreamSubscription;
|
||||
|
||||
StreamSubscription? _currentEmailIdInNotificationIOSStreamSubscription;
|
||||
|
||||
final StreamController<Either<Failure, Success>> _progressStateController =
|
||||
StreamController<Either<Failure, Success>>.broadcast();
|
||||
Stream<Either<Failure, Success>> get progressState => _progressStateController.stream;
|
||||
@@ -272,7 +275,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
);
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
void onInit() {
|
||||
_registerStreamListener();
|
||||
BackButtonInterceptor.add(_onBackButtonInterceptor, name: AppRoutes.dashboard);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
@@ -286,6 +289,9 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
_registerPendingEmailAddress();
|
||||
_registerPendingEmailContents();
|
||||
_registerPendingFileInfo();
|
||||
if (PlatformInfo.isIOS) {
|
||||
_registerPendingCurrentEmailIdInNotification();
|
||||
}
|
||||
_handleArguments();
|
||||
super.onReady();
|
||||
}
|
||||
@@ -349,7 +355,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
} else if (success is GetAppDashboardConfigurationSuccess) {
|
||||
appGridDashboardController.handleShowAppDashboard(success.linagoraApplications);
|
||||
} else if(success is GetEmailByIdSuccess) {
|
||||
_moveToEmailDetailedView(success);
|
||||
openEmailDetailedView(success.email);
|
||||
} else if (success is StoreSendingEmailSuccess) {
|
||||
_handleStoreSendingEmailSuccess(success);
|
||||
} else if (success is GetAllSendingEmailSuccess) {
|
||||
@@ -392,7 +398,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
} else if (failure is MarkAsMailboxReadFailure) {
|
||||
_markAsReadMailboxFailure(failure);
|
||||
} else if (failure is GetEmailByIdFailure) {
|
||||
_handleGetEmailDetailedFailed(failure);
|
||||
_handleGetEmailByIdFailure(failure);
|
||||
} else if (failure is RestoreDeletedMessageFailure) {
|
||||
_handleRestoreDeletedMessageFailed();
|
||||
} else if (failure is GetRestoredDeletedMessageFailure) {
|
||||
@@ -439,6 +445,18 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
});
|
||||
}
|
||||
|
||||
void _registerPendingCurrentEmailIdInNotification() {
|
||||
_iosNotificationManager = getBinding<IOSNotificationManager>();
|
||||
_currentEmailIdInNotificationIOSStreamSubscription = _iosNotificationManager
|
||||
?.pendingCurrentEmailIdInNotification.stream
|
||||
.listen((emailId) {
|
||||
if (emailId != null) {
|
||||
_iosNotificationManager?.clearPendingCurrentEmailId();
|
||||
_handleNotificationMessageFromEmailId(emailId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _registerStreamListener() {
|
||||
progressState.listen((state) {
|
||||
viewStateMarkAsReadMailbox.value = state;
|
||||
@@ -455,7 +473,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
_notificationManager.localNotificationStream.listen(_handleClickLocalNotificationOnForeground);
|
||||
}
|
||||
|
||||
void _handleClickLocalNotificationOnTerminated() async {
|
||||
Future<void> _handleClickNotificationOnAndroidInTerminated() async {
|
||||
_notificationManager.activatedNotificationClickedOnTerminate = true;
|
||||
final notificationResponse = await _notificationManager.getCurrentNotificationResponse();
|
||||
log('MailboxDashBoardController::_handleClickLocalNotificationOnTerminated():payload: ${notificationResponse?.payload}');
|
||||
@@ -464,13 +482,11 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
|
||||
void _handleArguments() {
|
||||
final arguments = Get.arguments;
|
||||
log('MailboxDashBoardController::_getSessionCurrent(): arguments = $arguments');
|
||||
log('MailboxDashBoardController::_handleArguments():Arguments = ${arguments.runtimeType}');
|
||||
if (arguments is Session) {
|
||||
_handleSessionFromArguments(arguments);
|
||||
} else if (arguments is MailtoArguments) {
|
||||
_handleMailtoURL(arguments);
|
||||
} else if (arguments is PreviewEmailArguments) {
|
||||
_handleOpenEmailAction(arguments);
|
||||
} else {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
reload();
|
||||
@@ -501,11 +517,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
|
||||
void _handleSessionFromArguments(Session session) {
|
||||
log('MailboxDashBoardController::_handleSession:');
|
||||
updateAuthenticationAccount(
|
||||
session,
|
||||
session.personalAccount.accountId,
|
||||
session.username
|
||||
);
|
||||
updateAccountCache(session);
|
||||
|
||||
_setUpComponentsFromSession(session);
|
||||
|
||||
@@ -513,15 +525,15 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
_handleComposerCache();
|
||||
}
|
||||
|
||||
if (PlatformInfo.isMobile && !_notificationManager.isNotificationClickedOnTerminate) {
|
||||
_handleClickLocalNotificationOnTerminated();
|
||||
if (PlatformInfo.isAndroid && !_notificationManager.isNotificationClickedOnTerminate) {
|
||||
_handleClickNotificationOnAndroidInTerminated();
|
||||
} else {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
}
|
||||
|
||||
void _setUpComponentsFromSession(Session session) {
|
||||
final currentAccountId = session.personalAccount.accountId;
|
||||
final currentAccountId = session.accountId;
|
||||
sessionCurrent = session;
|
||||
accountId.value = currentAccountId;
|
||||
|
||||
@@ -546,13 +558,6 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
_handleSessionFromArguments(arguments.session);
|
||||
}
|
||||
|
||||
void _handleOpenEmailAction(PreviewEmailArguments arguments) {
|
||||
log('MailboxDashBoardController::_handleOpenEmailAction:arguments: $arguments');
|
||||
dispatchRoute(DashboardRoutes.waiting);
|
||||
_handleSessionFromArguments(arguments.session);
|
||||
_handleNotificationMessageFromEmailId(arguments.emailId);
|
||||
}
|
||||
|
||||
void _getVacationResponse() {
|
||||
if (accountId.value != null && _getAllVacationInteractor != null) {
|
||||
consumeState(_getAllVacationInteractor!.execute(accountId.value!));
|
||||
@@ -1794,14 +1799,7 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
));
|
||||
}
|
||||
|
||||
void _moveToEmailDetailedView(GetEmailByIdSuccess success) {
|
||||
log('MailboxDashBoardController::_moveToEmailDetailedView(): ${success.email}');
|
||||
setSelectedEmail(success.email);
|
||||
dispatchRoute(DashboardRoutes.emailDetailed);
|
||||
}
|
||||
|
||||
void _handleGetEmailDetailedFailed(GetEmailByIdFailure failure) {
|
||||
logError('MailboxDashBoardController::_handleGetEmailDetailedFailed(): $failure');
|
||||
void _handleGetEmailByIdFailure(GetEmailByIdFailure failure) {
|
||||
dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
|
||||
@@ -2552,6 +2550,10 @@ class MailboxDashBoardController extends ReloadableController {
|
||||
@override
|
||||
void onClose() {
|
||||
_emailReceiveManager.closeEmailReceiveManagerStream();
|
||||
if (PlatformInfo.isIOS) {
|
||||
_iosNotificationManager?.dispose();
|
||||
_currentEmailIdInNotificationIOSStreamSubscription?.cancel();
|
||||
}
|
||||
_emailAddressStreamSubscription.cancel();
|
||||
_emailContentStreamSubscription.cancel();
|
||||
_fileReceiveManagerStreamSubscription.cancel();
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:tmail_ui_user/main/routes/router_arguments.dart';
|
||||
|
||||
class PreviewEmailArguments extends RouterArguments {
|
||||
|
||||
final Session session;
|
||||
final EmailId emailId;
|
||||
|
||||
PreviewEmailArguments({required this.session, required this.emailId});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [session, emailId];
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class ManageAccountDashBoardController extends ReloadableController {
|
||||
void handleReloaded(Session session) {
|
||||
log('ManageAccountDashBoardController::handleReloaded:');
|
||||
sessionCurrent = session;
|
||||
accountId.value = session.personalAccount.accountId;
|
||||
accountId.value = session.accountId;
|
||||
_bindingInteractorForMenuItemView(sessionCurrent, accountId.value);
|
||||
_getVacationResponse();
|
||||
_getParametersRouter();
|
||||
|
||||
@@ -161,7 +161,7 @@ class SendingEmailWorker extends Worker {
|
||||
|
||||
void _handleGetSessionSuccess(GetSessionSuccess success) async {
|
||||
_currentSession = success.session;
|
||||
_currentAccountId = success.session.personalAccount.accountId;
|
||||
_currentAccountId = success.session.accountId;
|
||||
final apiUrl = success.session.getQualifiedApiUrl(baseUrl: _dynamicUrlInterceptors?.jmapUrl);
|
||||
if (apiUrl.isNotEmpty && _currentSession != null && _currentAccountId != null) {
|
||||
_dynamicUrlInterceptors?.changeBaseUrl(apiUrl);
|
||||
|
||||
@@ -270,7 +270,7 @@ class FcmMessageController extends FcmBaseController {
|
||||
_dynamicUrlInterceptors?.changeBaseUrl(apiUrl);
|
||||
|
||||
_pushActionFromRemoteMessageBackground(
|
||||
accountId: success.session.personalAccount.accountId,
|
||||
accountId: success.session.accountId,
|
||||
userName: success.session.username,
|
||||
stateChange: stateChange,
|
||||
session: success.session);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/broadcast_channel/broadcast_channel.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/controller/fcm_message_controller.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/services/fcm_service.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_config.dart';
|
||||
@@ -23,7 +21,6 @@ class FcmReceiver {
|
||||
|
||||
static FcmReceiver get instance => _instance;
|
||||
|
||||
static const notificationInteractionChannel = MethodChannel('notification_interaction_channel');
|
||||
static const int MAX_COUNT_RETRY_TO_GET_FCM_TOKEN = 3;
|
||||
|
||||
int _countRetryToGetFcmToken = 0;
|
||||
@@ -36,24 +33,11 @@ class FcmReceiver {
|
||||
if (PlatformInfo.isWeb) {
|
||||
_onMessageBroadcastChannel();
|
||||
await _requestNotificationPermissionOnWeb();
|
||||
} else if (PlatformInfo.isIOS) {
|
||||
_setUpIOSNotificationInteraction();
|
||||
await _onHandleFcmToken();
|
||||
} else {
|
||||
await _onHandleFcmToken();
|
||||
}
|
||||
}
|
||||
|
||||
void _setUpIOSNotificationInteraction() {
|
||||
notificationInteractionChannel.setMethodCallHandler((call) async {
|
||||
log('FcmReceiver::_setUpIOSNotificationInteraction:notificationInteractionChannel: $call');
|
||||
if (call.method == 'openEmail' && call.arguments is String) {
|
||||
log('FcmReceiver::_setUpIOSNotificationInteraction:openEmail with id = ${call.arguments}');
|
||||
FcmService.instance.handleOpenEmailFromNotification(call.arguments);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _requestNotificationPermissionOnWeb() async {
|
||||
NotificationSettings notificationSetting = await FirebaseMessaging.instance.getNotificationSettings();
|
||||
log('FcmReceiver::_requestNotificationPermissionOnWeb: authorizationStatus = ${notificationSetting.authorizationStatus}');
|
||||
@@ -118,18 +102,4 @@ class FcmReceiver {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>?> getIOSInitialNotificationInfo() async {
|
||||
try {
|
||||
final notificationInfo = await notificationInteractionChannel.invokeMethod('getInitialNotificationInfo');
|
||||
log('FcmReceiver::getIOSInitialNotificationInfo:notificationInfo: $notificationInfo');
|
||||
if (notificationInfo != null && notificationInfo is Map<String, dynamic>) {
|
||||
return notificationInfo;
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
logError('FcmReceiver::getIOSInitialNotificationInfo: Exception: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/presentation/model/broadcast_message_event_data.dart';
|
||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
class FcmService {
|
||||
@@ -63,14 +58,6 @@ class FcmService {
|
||||
fcmTokenStreamController = StreamController<String?>.broadcast();
|
||||
}
|
||||
|
||||
void handleOpenEmailFromNotification(String emailId) {
|
||||
log('FcmService::handleOpenEmailFromNotification:emailId: $emailId');
|
||||
popAndPush(
|
||||
RouteUtils.generateNavigationRoute(AppRoutes.home),
|
||||
arguments: EmailId(Id(emailId))
|
||||
);
|
||||
}
|
||||
|
||||
void closeStream() {
|
||||
foregroundMessageStreamController?.close();
|
||||
backgroundMessageStreamController?.close();
|
||||
|
||||
Reference in New Issue
Block a user