TF-2384 Handle open email detailed when click notification on background mode

Signed-off-by: dab246 <tdvu@linagora.com>
(cherry picked from commit 72db39c87dbd8f06bfbb417e4fed4d384da356ea)
This commit is contained in:
dab246
2023-12-25 00:03:48 +07:00
committed by Dat H. Pham
parent aac12f5731
commit 84b7239ad0
8 changed files with 98 additions and 12 deletions
+19
View File
@@ -7,12 +7,16 @@ import flutter_local_notifications
@UIApplicationMain @UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate {
var notificationInteractionChannel: FlutterMethodChannel?
override func application( override func application(
_ application: UIApplication, _ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool { ) -> Bool {
GeneratedPluginRegistrant.register(with: self) GeneratedPluginRegistrant.register(with: self)
createNotificationInteractionChannel()
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
} }
@@ -94,7 +98,13 @@ import flutter_local_notifications
} }
override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
TwakeLogger.shared.log(message: "AppDelegate::userNotificationCenter::didReceive::response: \(response)")
updateAppBadger(currentBadgeCount: UIApplication.shared.applicationIconBadgeNumber) updateAppBadger(currentBadgeCount: UIApplication.shared.applicationIconBadgeNumber)
if let emailId = response.notification.request.content.userInfo[JmapConstants.EMAIL_ID] as? String {
self.notificationInteractionChannel?.invokeMethod("openEmail", arguments: emailId)
}
completionHandler() completionHandler()
} }
} }
@@ -124,4 +134,13 @@ extension AppDelegate {
private func isAppForegroundActive() -> Bool { private func isAppForegroundActive() -> Bool {
return UIApplication.shared.applicationState == .active return UIApplication.shared.applicationState == .active
} }
private func createNotificationInteractionChannel() {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
self.notificationInteractionChannel = FlutterMethodChannel(
name: "notification_interaction_channel",
binaryMessenger: controller.binaryMessenger
)
}
} }
@@ -3,6 +3,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/core/session/session.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:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:model/account/personal_account.dart'; import 'package:model/account/personal_account.dart';
import 'package:model/email/email_content.dart'; import 'package:model/email/email_content.dart';
@@ -19,6 +20,7 @@ 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_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_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/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/main/routes/app_routes.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_navigation.dart';
import 'package:tmail_ui_user/main/routes/route_utils.dart'; import 'package:tmail_ui_user/main/routes/route_utils.dart';
@@ -40,6 +42,7 @@ class HomeController extends ReloadableController {
); );
PersonalAccount? currentAccount; PersonalAccount? currentAccount;
EmailId? _emailIdPreview;
@override @override
void onInit() { void onInit() {
@@ -47,6 +50,9 @@ class HomeController extends ReloadableController {
_initFlutterDownloader(); _initFlutterDownloader();
_registerReceivingSharingIntent(); _registerReceivingSharingIntent();
} }
if (PlatformInfo.isIOS && Get.arguments is EmailId) {
_emailIdPreview = Get.arguments;
}
super.onInit(); super.onInit();
} }
@@ -58,10 +64,20 @@ class HomeController extends ReloadableController {
@override @override
void handleReloaded(Session session) { void handleReloaded(Session session) {
popAndPush( if (_emailIdPreview != null) {
RouteUtils.generateNavigationRoute(AppRoutes.dashboard), popAndPush(
arguments: session RouteUtils.generateNavigationRoute(AppRoutes.dashboard),
); arguments: PreviewEmailArguments(
session: session,
emailId: _emailIdPreview!
)
);
} else {
popAndPush(
RouteUtils.generateNavigationRoute(AppRoutes.dashboard),
arguments: session
);
}
} }
void _initFlutterDownloader() { void _initFlutterDownloader() {
@@ -84,6 +84,7 @@ 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/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/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/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/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_receive_time_type.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_sort_order_type.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_sort_order_type.dart';
@@ -112,6 +113,7 @@ import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_ema
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_mailbox_state_to_refresh_interactor.dart'; import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_mailbox_state_to_refresh_interactor.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_manager.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/notification/local_notification_manager.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/services/fcm_service.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/services/fcm_service.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/utils/fcm_utils.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/model/sending_email.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/state/get_all_sending_email_state.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/state/get_all_sending_email_state.dart';
import 'package:tmail_ui_user/features/sending_queue/domain/state/update_sending_email_state.dart'; import 'package:tmail_ui_user/features/sending_queue/domain/state/update_sending_email_state.dart';
@@ -438,7 +440,7 @@ class MailboxDashBoardController extends ReloadableController {
}); });
_refreshActionEventController.stream _refreshActionEventController.stream
.debounceTime(const Duration(milliseconds: FcmService.durationMessageComing)) .debounceTime(const Duration(milliseconds: FcmUtils.durationMessageComing))
.listen(_handleRefreshActionWhenBackToApp); .listen(_handleRefreshActionWhenBackToApp);
_registerLocalNotificationStreamListener(); _registerLocalNotificationStreamListener();
@@ -462,6 +464,8 @@ class MailboxDashBoardController extends ReloadableController {
_handleSession(arguments); _handleSession(arguments);
} else if (arguments is MailtoArguments) { } else if (arguments is MailtoArguments) {
_handleMailtoURL(arguments); _handleMailtoURL(arguments);
} else if (arguments is PreviewEmailArguments) {
_handleOpenEmailAction(arguments);
} else { } else {
dispatchRoute(DashboardRoutes.thread); dispatchRoute(DashboardRoutes.thread);
reload(); reload();
@@ -532,6 +536,13 @@ class MailboxDashBoardController extends ReloadableController {
_handleSession(arguments.session); _handleSession(arguments.session);
} }
void _handleOpenEmailAction(PreviewEmailArguments arguments) {
log('MailboxDashBoardController::_handleOpenEmailAction:arguments: $arguments');
dispatchRoute(DashboardRoutes.waiting);
_handleSession(arguments.session);
_handleNotificationMessageFromEmailId(arguments.emailId);
}
Future<void> _getAppVersion() async { Future<void> _getAppVersion() async {
final info = await PackageInfo.fromPlatform(); final info = await PackageInfo.fromPlatform();
log('MailboxDashBoardController::_getAppVersion(): ${info.version}'); log('MailboxDashBoardController::_getAppVersion(): ${info.version}');
@@ -1718,7 +1729,7 @@ class MailboxDashBoardController extends ReloadableController {
void _showWaitingView() { void _showWaitingView() {
popAllRouteIfHave(); popAllRouteIfHave();
dispatchRoute( DashboardRoutes.waiting); dispatchRoute(DashboardRoutes.waiting);
} }
void _openInboxMailboxFromNotification() { void _openInboxMailboxFromNotification() {
@@ -0,0 +1,15 @@
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];
}
@@ -73,21 +73,21 @@ class FcmMessageController extends FcmBaseController {
void _listenForegroundMessageStream() { void _listenForegroundMessageStream() {
FcmService.instance.foregroundMessageStreamController FcmService.instance.foregroundMessageStreamController
?.stream ?.stream
.throttleTime(const Duration(milliseconds: FcmService.durationMessageComing)) .throttleTime(const Duration(milliseconds: FcmUtils.durationMessageComing))
.listen(_handleForegroundMessageAction); .listen(_handleForegroundMessageAction);
} }
void _listenBackgroundMessageStream() { void _listenBackgroundMessageStream() {
FcmService.instance.backgroundMessageStreamController FcmService.instance.backgroundMessageStreamController
?.stream ?.stream
.throttleTime(const Duration(milliseconds: FcmService.durationMessageComing)) .throttleTime(const Duration(milliseconds: FcmUtils.durationMessageComing))
.listen(_handleBackgroundMessageAction); .listen(_handleBackgroundMessageAction);
} }
void _listenTokenStream() { void _listenTokenStream() {
FcmService.instance.fcmTokenStreamController FcmService.instance.fcmTokenStreamController
?.stream ?.stream
.throttleTime(const Duration(milliseconds: FcmService.durationRefreshToken)) .throttleTime(const Duration(milliseconds: FcmUtils.durationRefreshToken))
.listen(FcmTokenController.instance.onFcmTokenChanged); .listen(FcmTokenController.instance.onFcmTokenChanged);
} }
@@ -2,6 +2,7 @@
import 'package:core/utils/app_logger.dart'; import 'package:core/utils/app_logger.dart';
import 'package:core/utils/platform_info.dart'; import 'package:core/utils/platform_info.dart';
import 'package:firebase_messaging/firebase_messaging.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/controller/fcm_message_controller.dart';
import 'package:tmail_ui_user/features/push_notification/presentation/services/fcm_service.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/services/fcm_service.dart';
import 'package:tmail_ui_user/main/utils/app_config.dart'; import 'package:tmail_ui_user/main/utils/app_config.dart';
@@ -20,12 +21,24 @@ class FcmReceiver {
static FcmReceiver get instance => _instance; static FcmReceiver get instance => _instance;
static const notificationInteractionChannel = MethodChannel('notification_interaction_channel');
Future onInitialFcmListener() async { Future onInitialFcmListener() async {
log('FcmReceiver::onInitialFcmListener:'); log('FcmReceiver::onInitialFcmListener:');
await _onHandleFcmToken(); await _onHandleFcmToken();
_onForegroundMessage(); _onForegroundMessage();
_onBackgroundMessage(); _onBackgroundMessage();
if (PlatformInfo.isIOS) {
notificationInteractionChannel.setMethodCallHandler((call) async {
log('FcmReceiver::onInitialFcmListener:notificationInteractionChannel: $call');
if (call.method == 'openEmail') {
log('FcmReceiver::onInitialFcmListener:openEmail with id = ${call.arguments}');
FcmService.instance.handleOpenEmailFromNotification(call.arguments);
}
});
}
} }
void _onForegroundMessage() { void _onForegroundMessage() {
@@ -3,12 +3,14 @@ import 'dart:async';
import 'package:core/utils/app_logger.dart'; import 'package:core/utils/app_logger.dart';
import 'package:firebase_messaging/firebase_messaging.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/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';
class FcmService { class FcmService {
static const int durationMessageComing = 2000;
static const int durationRefreshToken = 2000;
StreamController<Map<String, dynamic>>? foregroundMessageStreamController; StreamController<Map<String, dynamic>>? foregroundMessageStreamController;
StreamController<Map<String, dynamic>>? backgroundMessageStreamController; StreamController<Map<String, dynamic>>? backgroundMessageStreamController;
StreamController<String?>? fcmTokenStreamController; StreamController<String?>? fcmTokenStreamController;
@@ -45,6 +47,14 @@ class FcmService {
fcmTokenStreamController = StreamController<String?>.broadcast(); fcmTokenStreamController = StreamController<String?>.broadcast();
} }
void handleOpenEmailFromNotification(String emailId) {
log('FcmService::handleOpenEmailFromNotification:emailId: $emailId');
popAndPush(
RouteUtils.generateNavigationRoute(AppRoutes.home),
arguments: EmailId(Id(emailId))
);
}
void closeStream() { void closeStream() {
foregroundMessageStreamController?.close(); foregroundMessageStreamController?.close();
backgroundMessageStreamController?.close(); backgroundMessageStreamController?.close();
@@ -31,6 +31,8 @@ class FcmUtils {
TypeName.mailboxType, TypeName.mailboxType,
TypeName.emailDelivery TypeName.emailDelivery
]; ];
static const int durationMessageComing = 2000;
static const int durationRefreshToken = 2000;
StateChange? convertFirebaseDataMessageToStateChange(Map<String, dynamic> dataMessage) { StateChange? convertFirebaseDataMessageToStateChange(Map<String, dynamic> dataMessage) {
log('FcmUtils::convertFirebaseDataMessageToStateChange():dataMessage: $dataMessage'); log('FcmUtils::convertFirebaseDataMessageToStateChange():dataMessage: $dataMessage');