diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 3c7d16faf..191b695df 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -15,6 +15,18 @@ import receive_sharing_intent FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!) } } + + let sharingIntent = SwiftReceiveSharingIntentPlugin.instance + if let url = launchOptions?[UIApplication.LaunchOptionsKey.url] as? URL { + if url.scheme == "mailto" { + if let url = handleEmailAndress(open: url) { + let corrected = launchOptions!.map { (key, value) in key != .url ? (key, value) : (key, url) } + + return sharingIntent.application(application, didFinishLaunchingWithOptions: Dictionary(uniqueKeysWithValues: corrected)) + } + } + } + return super.application(application, didFinishLaunchingWithOptions: launchOptions) } @@ -24,6 +36,11 @@ import receive_sharing_intent return sharingIntent.application(app, open: url, options: options) } + if url.scheme == "mailto" { + if let url = handleEmailAndress(open: url) { + return sharingIntent.application(app, open: url, options: options) + } + } // For example load MSALPublicClientApplication // return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[.sourceApplication] as? String) @@ -34,4 +51,18 @@ import receive_sharing_intent return super.application(app, open: url, options:options) } + private func handleEmailAndress(open url: URL) -> URL? { + let appDomain = Bundle.main.bundleIdentifier! + let appGroupId = (Bundle.main.object(forInfoDictionaryKey: "AppGroupId") as? String) ?? "group.\(Bundle.main.bundleIdentifier!)" + let sharedKey = "ShareKey" + var sharedText: [String] = [] + if let email = url.absoluteString.components(separatedBy: ":").last { + sharedText.append(email) + } + let userDefaults = UserDefaults(suiteName: appGroupId) + userDefaults?.set(sharedText, forKey: sharedKey) + userDefaults?.synchronize() + return URL(string: "ShareMedia-\(appDomain)://dataUrl=\(sharedKey)#text") + } + } diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 9c6d330b7..2be79e3ac 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + com.apple.developer.mail-client + AppGroupId ${APP_GROUP_ID} CADisableMinimumFrameDurationOnPhone @@ -33,6 +35,7 @@ ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER) teammail.mobile + mailto diff --git a/lib/features/base/reloadable/reloadable_controller.dart b/lib/features/base/reloadable/reloadable_controller.dart index b05b679c3..adeccf533 100644 --- a/lib/features/base/reloadable/reloadable_controller.dart +++ b/lib/features/base/reloadable/reloadable_controller.dart @@ -11,7 +11,6 @@ import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/caching/config/hive_cache_config.dart'; import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart'; -import 'package:tmail_ui_user/features/login/data/network/config/authorization_isolate_interceptors.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/usecases/delete_authority_oidc_interactor.dart'; @@ -25,13 +24,14 @@ import 'package:tmail_ui_user/features/manage_account/domain/state/log_out_oidc_ import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/features/session/domain/state/get_session_state.dart'; import 'package:tmail_ui_user/features/session/domain/usecases/get_session_interactor.dart'; +import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; abstract class ReloadableController extends BaseController { final DynamicUrlInterceptors _dynamicUrlInterceptors = Get.find(); final AuthorizationInterceptors _authorizationInterceptors = Get.find(); - final AuthorizationIsolateInterceptors _authorizationIsolateInterceptors = Get.find(); + final AuthorizationInterceptors _authorizationIsolateInterceptors = Get.find(tag: BindingTag.isolateTag); final GetSessionInteractor _getSessionInteractor = Get.find(); final DeleteCredentialInteractor _deleteCredentialInteractor = Get.find(); final CachingManager _cachingManager = Get.find(); diff --git a/lib/features/composer/presentation/composer_bindings.dart b/lib/features/composer/presentation/composer_bindings.dart index 89aa524c1..b37da2c8a 100644 --- a/lib/features/composer/presentation/composer_bindings.dart +++ b/lib/features/composer/presentation/composer_bindings.dart @@ -65,7 +65,7 @@ class ComposerBindings extends BaseBindings { } void _bindingsUtils() { - Get.lazyPut(() => FileUploader(Get.find(tag: BindingTag.isoLateTag), Get.find())); + Get.lazyPut(() => FileUploader(Get.find(tag: BindingTag.isolateTag), Get.find())); } @override diff --git a/lib/features/home/presentation/home_bindings.dart b/lib/features/home/presentation/home_bindings.dart index 017473ae0..be27a3abb 100644 --- a/lib/features/home/presentation/home_bindings.dart +++ b/lib/features/home/presentation/home_bindings.dart @@ -19,7 +19,6 @@ import 'package:tmail_ui_user/features/login/data/local/oidc_configuration_cache 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'; -import 'package:tmail_ui_user/features/login/data/network/config/authorization_isolate_interceptors.dart'; import 'package:tmail_ui_user/features/login/data/network/oidc_http_client.dart'; import 'package:tmail_ui_user/features/login/data/repository/account_repository_impl.dart'; import 'package:tmail_ui_user/features/login/data/repository/authentication_oidc_repository_impl.dart'; @@ -33,6 +32,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/get_authenticated_a import 'package:tmail_ui_user/features/login/domain/usecases/get_credential_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_token_oidc_interactor.dart'; import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart'; +import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; class HomeBindings extends BaseBindings { @@ -43,7 +43,7 @@ class HomeBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), + Get.find(tag: BindingTag.isolateTag), Get.find(), Get.find(), Get.find(), diff --git a/lib/features/home/presentation/home_controller.dart b/lib/features/home/presentation/home_controller.dart index 49ba2aa83..c59187eed 100644 --- a/lib/features/home/presentation/home_controller.dart +++ b/lib/features/home/presentation/home_controller.dart @@ -12,7 +12,6 @@ import 'package:tmail_ui_user/features/cleanup/domain/model/recent_search_cleanu import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_email_cache_interactor.dart'; import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_search_cache_interactor.dart'; import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart'; -import 'package:tmail_ui_user/features/login/data/network/config/authorization_isolate_interceptors.dart'; import 'package:tmail_ui_user/features/login/domain/state/check_oidc_is_available_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'; @@ -31,7 +30,7 @@ class HomeController extends BaseController { final GetAuthenticatedAccountInteractor _getAuthenticatedAccountInteractor; final DynamicUrlInterceptors _dynamicUrlInterceptors; final AuthorizationInterceptors _authorizationInterceptors; - final AuthorizationIsolateInterceptors _authorizationIsolateInterceptors; + final AuthorizationInterceptors _authorizationIsolateInterceptors; final CleanupEmailCacheInteractor _cleanupEmailCacheInteractor; final EmailReceiveManager _emailReceiveManager; final CleanupRecentSearchCacheInteractor _cleanupRecentSearchCacheInteractor; diff --git a/lib/features/login/data/network/config/authorization_isolate_interceptors.dart b/lib/features/login/data/network/config/authorization_isolate_interceptors.dart deleted file mode 100644 index ab94dcc5a..000000000 --- a/lib/features/login/data/network/config/authorization_isolate_interceptors.dart +++ /dev/null @@ -1,65 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:dio/dio.dart'; -import 'package:core/core.dart'; -import 'package:model/account/authentication_type.dart'; -import 'package:model/oidc/oidc_configuration.dart'; -import 'package:model/oidc/token.dart'; - -class AuthorizationIsolateInterceptors extends QueuedInterceptorsWrapper { - - AuthenticationType _authenticationType = AuthenticationType.none; - OIDCConfiguration? _configOIDC; - Token? _token; - String? _authorization; - - void setBasicAuthorization(String? userName, String? password) { - _authorization = base64Encode(utf8.encode('$userName:$password')); - _authenticationType = AuthenticationType.basic; - } - - void setTokenAndAuthorityOidc({Token? newToken, OIDCConfiguration? newConfig}) { - _token = newToken; - _configOIDC = newConfig; - _authenticationType = AuthenticationType.oidc; - log('AuthorizationIsolateInterceptors::setToken(): newToken: $newToken'); - log('AuthorizationIsolateInterceptors::setToken(): tokenId: ${newToken?.tokenIdHash}'); - log('AuthorizationIsolateInterceptors::setToken(): EXPIRE_DATE: ${newToken?.expiredTime?.toIso8601String()}'); - } - - OIDCConfiguration? get oidcConfig => _configOIDC; - - AuthenticationType get authenticationType => _authenticationType; - - @override - void onRequest(RequestOptions options, RequestInterceptorHandler handler) { - switch(_authenticationType) { - case AuthenticationType.basic: - if (_authorization != null) { - options.headers[HttpHeaders.authorizationHeader] = _getAuthorizationAsBasicHeader(_authorization); - } - break; - case AuthenticationType.oidc: - if (_token != null && _token?.isTokenValid() == true) { - options.headers[HttpHeaders.authorizationHeader] = _getTokenAsBearerHeader(_token!.token); - } - break; - case AuthenticationType.none: - break; - } - - super.onRequest(options, handler); - } - - String _getAuthorizationAsBasicHeader(String? authorization) => 'Basic $authorization'; - - String _getTokenAsBearerHeader(String token) => 'Bearer $token'; - - void clear() { - _authorization = null; - _token = null; - _configOIDC = null; - _authenticationType = AuthenticationType.none; - } -} diff --git a/lib/features/login/presentation/login_bindings.dart b/lib/features/login/presentation/login_bindings.dart index 21d7213a1..39d569b0d 100644 --- a/lib/features/login/presentation/login_bindings.dart +++ b/lib/features/login/presentation/login_bindings.dart @@ -13,7 +13,6 @@ import 'package:tmail_ui_user/features/login/data/local/oidc_configuration_cache 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'; -import 'package:tmail_ui_user/features/login/data/network/config/authorization_isolate_interceptors.dart'; import 'package:tmail_ui_user/features/login/data/network/oidc_http_client.dart'; import 'package:tmail_ui_user/features/login/data/repository/account_repository_impl.dart'; import 'package:tmail_ui_user/features/login/data/repository/authentication_oidc_repository_impl.dart'; @@ -31,6 +30,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configurat import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_token_oidc_interactor.dart'; import 'package:tmail_ui_user/features/login/presentation/login_controller.dart'; +import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; class LoginBindings extends BaseBindings { @@ -40,7 +40,7 @@ class LoginBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), - Get.find(), + Get.find(tag: BindingTag.isolateTag), Get.find(), Get.find(), Get.find(), diff --git a/lib/features/login/presentation/login_controller.dart b/lib/features/login/presentation/login_controller.dart index 3b217ed62..4304f0d0e 100644 --- a/lib/features/login/presentation/login_controller.dart +++ b/lib/features/login/presentation/login_controller.dart @@ -9,7 +9,6 @@ import 'package:get/get.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart'; -import 'package:tmail_ui_user/features/login/data/network/config/authorization_isolate_interceptors.dart'; import 'package:tmail_ui_user/features/login/domain/state/authenticate_oidc_on_browser_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/authentication_user_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/check_oidc_is_available_state.dart'; @@ -36,7 +35,7 @@ class LoginController extends BaseController { final AuthenticationInteractor _authenticationInteractor; final DynamicUrlInterceptors _dynamicUrlInterceptors; final AuthorizationInterceptors _authorizationInterceptors; - final AuthorizationIsolateInterceptors _authorizationIsolateInterceptors; + final AuthorizationInterceptors _authorizationIsolateInterceptors; final CheckOIDCIsAvailableInteractor _checkOIDCIsAvailableInteractor; final GetOIDCConfigurationInteractor _getOIDCConfigurationInteractor; final GetTokenOIDCInteractor _getTokenOIDCInteractor; 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 d7435741f..8cfbca053 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -59,7 +59,6 @@ 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/router_arguments.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; -import 'package:worker_manager/worker_manager.dart'; class MailboxDashBoardController extends ReloadableController { @@ -644,7 +643,6 @@ class MailboxDashBoardController extends ReloadableController { _fileReceiveManagerStreamSubscription.cancel(); _connectivityStreamSubscription.cancel(); _progressStateController.close(); - Executor().dispose(); Get.delete(); super.onClose(); } diff --git a/lib/main/bindings/main_bindings.dart b/lib/main/bindings/main_bindings.dart index e6462be7f..523a5bedd 100644 --- a/lib/main/bindings/main_bindings.dart +++ b/lib/main/bindings/main_bindings.dart @@ -3,6 +3,7 @@ import 'package:tmail_ui_user/main/bindings/core/core_bindings.dart'; import 'package:tmail_ui_user/main/bindings/credential/credential_bindings.dart'; import 'package:tmail_ui_user/main/bindings/local/local_bindings.dart'; import 'package:tmail_ui_user/main/bindings/network/network_bindings.dart'; +import 'package:tmail_ui_user/main/bindings/network/network_isolate_binding.dart'; import 'package:tmail_ui_user/main/bindings/session/session_bindings.dart'; class MainBindings extends Bindings { @@ -11,6 +12,7 @@ class MainBindings extends Bindings { await CoreBindings().dependencies(); LocalBindings().dependencies(); NetworkBindings().dependencies(); + NetworkIsolateBindings().dependencies(); CredentialBindings().dependencies(); SessionBindings().dependencies(); } diff --git a/lib/main/bindings/network/binding_tag.dart b/lib/main/bindings/network/binding_tag.dart index 1e8abdbaf..660cdef60 100644 --- a/lib/main/bindings/network/binding_tag.dart +++ b/lib/main/bindings/network/binding_tag.dart @@ -1,3 +1,3 @@ class BindingTag { - static const isoLateTag = 'isoLateTag'; + static const isolateTag = 'isolateTag'; } \ 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 d4ee484f4..30b297635 100644 --- a/lib/main/bindings/network/network_bindings.dart +++ b/lib/main/bindings/network/network_bindings.dart @@ -13,17 +13,12 @@ import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.da 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'; -import 'package:tmail_ui_user/features/login/data/network/config/authorization_isolate_interceptors.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/network/mailbox_api.dart'; -import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_isolate_worker.dart'; import 'package:tmail_ui_user/features/manage_account/data/network/manage_account_api.dart'; import 'package:tmail_ui_user/features/session/data/network/session_api.dart'; 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:worker_manager/worker_manager.dart'; class NetworkBindings extends Bindings { @@ -31,7 +26,6 @@ class NetworkBindings extends Bindings { void dependencies() { _bindingDio(); _bindingApi(); - _bindingIsolateWorker(); _bindingConnection(); _bindingException(); } @@ -47,9 +41,7 @@ class NetworkBindings extends Bindings { void _bindingDio() { _bindingBaseOption(); Get.put(Dio(Get.find())); - Get.put(Dio(Get.find()), tag: BindingTag.isoLateTag); Get.put(DioClient(Get.find())); - Get.put(DioClient(Get.find(tag: BindingTag.isoLateTag)), tag: BindingTag.isoLateTag); Get.put(const FlutterAppAuth()); Get.put(AppAuthWebPlugin()); Get.put(OIDCHttpClient(Get.find())); @@ -59,20 +51,16 @@ class NetworkBindings extends Bindings { void _bindingInterceptors() { Get.put(DynamicUrlInterceptors()); - Get.put(AuthorizationIsolateInterceptors()); Get.put(AuthorizationInterceptors( Get.find(), Get.find(), Get.find(), Get.find(), )); - Get.find(tag: BindingTag.isoLateTag).interceptors.add(Get.find()); - Get.find(tag: BindingTag.isoLateTag).interceptors.add(Get.find()); Get.find().interceptors.add(Get.find()); Get.find().interceptors.add(Get.find()); if (kDebugMode) { Get.find().interceptors.add(LogInterceptor(requestBody: true)); - Get.find(tag: BindingTag.isoLateTag).interceptors.add(LogInterceptor(requestBody: true)); } } @@ -98,18 +86,4 @@ class NetworkBindings extends Bindings { void _bindingException() { Get.put(RemoteExceptionThrower()); } - - void _bindingIsolateWorker() { - Get.put(Executor()); - Get.put(ThreadIsolateWorker( - Get.find(), - Get.find(), - Get.find(), - )); - Get.put(MailboxIsolateWorker( - Get.find(), - Get.find(), - Get.find(), - )); - } } \ No newline at end of file diff --git a/lib/main/bindings/network/network_isolate_binding.dart b/lib/main/bindings/network/network_isolate_binding.dart new file mode 100644 index 000000000..2441b530f --- /dev/null +++ b/lib/main/bindings/network/network_isolate_binding.dart @@ -0,0 +1,70 @@ +import 'package:core/core.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/foundation.dart'; +import 'package:get/get.dart'; +import 'package:jmap_dart_client/http/http_client.dart' as JmapHttpClient; +import 'package:tmail_ui_user/features/email/data/network/email_api.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/data/network/config/authorization_interceptors.dart'; +import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_isolate_worker.dart'; +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:worker_manager/worker_manager.dart'; + +class NetworkIsolateBindings extends Bindings { + + @override + void dependencies() { + _bindingDio(); + _bindingApi(); + _bindingIsolateWorker(); + } + + void _bindingDio() { + final dio = Get.put(Dio(Get.find()), tag: BindingTag.isolateTag); + Get.put(DioClient(dio), tag: BindingTag.isolateTag); + _bindingInterceptors(dio); + } + + void _bindingInterceptors(Dio dio) { + Get.put(AuthorizationInterceptors( + dio, + Get.find(), + Get.find(), + Get.find(), + ), tag: BindingTag.isolateTag); + dio.interceptors.add(Get.find()); + dio.interceptors.add(Get.find(tag: BindingTag.isolateTag)); + if (kDebugMode) { + dio.interceptors.add(LogInterceptor(requestBody: true)); + } + } + + void _bindingApi() { + final JmapHttpClient.HttpClient httpClient = Get.put(JmapHttpClient.HttpClient(Get.find(tag: BindingTag.isolateTag)), tag: BindingTag.isolateTag); + Get.put(DownloadClient(Get.find(tag: BindingTag.isolateTag), Get.find()), tag: BindingTag.isolateTag); + Get.put(DownloadManager(Get.find(tag: BindingTag.isolateTag)), tag: BindingTag.isolateTag); + Get.put(ThreadAPI(httpClient), tag: BindingTag.isolateTag); + Get.put(EmailAPI( + httpClient, + Get.find(tag: BindingTag.isolateTag), + Get.find(tag: BindingTag.isolateTag)), tag: BindingTag.isolateTag); + } + + void _bindingIsolateWorker() { + Get.put(Executor()); + Get.put(ThreadIsolateWorker( + Get.find(tag: BindingTag.isolateTag), + Get.find(tag: BindingTag.isolateTag), + Get.find(), + )); + Get.put(MailboxIsolateWorker( + Get.find(tag: BindingTag.isolateTag), + Get.find(tag: BindingTag.isolateTag), + Get.find(), + )); + } +} \ No newline at end of file