diff --git a/lib/features/email/presentation/action/email_ui_action.dart b/lib/features/email/presentation/action/email_ui_action.dart index 3a2ae4ae5..6e42157df 100644 --- a/lib/features/email/presentation/action/email_ui_action.dart +++ b/lib/features/email/presentation/action/email_ui_action.dart @@ -22,4 +22,6 @@ class RefreshChangeEmailAction extends EmailUIAction { class CloseEmailDetailedViewToRedirectToTheInboxAction extends EmailUIAction {} -class CloseEmailDetailedViewAction extends EmailUIAction {} \ No newline at end of file +class CloseEmailDetailedViewAction extends EmailUIAction {} + +class CloseSearchEmailViewAction extends EmailUIAction {} \ No newline at end of file diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index 525f4b2ae..bc9eb2fd9 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -234,8 +234,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { mailboxDashBoardController.clearSelectedEmail(); mailboxDashBoardController.dispatchRoute(DashboardRoutes.thread); mailboxDashBoardController.clearEmailUIAction(); - } else if (action is CloseEmailDetailedViewAction && currentContext != null) { - closeEmailView(currentContext!); + } else if (action is CloseEmailDetailedViewAction) { + closeEmailView(context: currentContext); mailboxDashBoardController.clearEmailUIAction(); } }); @@ -575,17 +575,15 @@ class SingleEmailController extends BaseController with AppLoaderMixin { mailboxDashBoardController.dispatchState(Right(success)); if (success is MarkAsEmailReadSuccess - && success.readActions == ReadActions.markAsUnread - && currentContext != null) { - closeEmailView(currentContext!); + && success.readActions == ReadActions.markAsUnread) { + closeEmailView(context: currentContext); } } void _markAsEmailReadFailure(Failure failure) { if (failure is MarkAsEmailReadFailure - && failure.readActions == ReadActions.markAsUnread - && currentContext != null) { - closeEmailView(currentContext!); + && failure.readActions == ReadActions.markAsUnread) { + closeEmailView(context: currentContext); } } @@ -844,7 +842,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } void _moveToMailbox(BuildContext context, Session session, AccountId accountId, MoveToMailboxRequest moveRequest) { - closeEmailView(context); + closeEmailView(context: context); consumeState(_moveToMailboxInteractor.execute(session, accountId, moveRequest)); } @@ -905,7 +903,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { AccountId accountId, MoveToMailboxRequest moveRequest ) { - closeEmailView(context); + closeEmailView(context: context); mailboxDashBoardController.moveToMailbox(session, accountId, moveRequest); } @@ -955,7 +953,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { AccountId accountId, MoveToMailboxRequest moveRequest ) { - closeEmailView(context); + closeEmailView(context: context); mailboxDashBoardController.moveToMailbox(session, accountId, moveRequest); } @@ -1082,7 +1080,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { void _deleteEmailPermanentlyAction(BuildContext context, PresentationEmail email) { popBack(); - closeEmailView(context); + closeEmailView(context: context); mailboxDashBoardController.deleteEmailPermanently(email); } @@ -1167,7 +1165,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } } - void closeEmailView(BuildContext context) { + void closeEmailView({BuildContext? context}) { if (emailSupervisorController.supportedPageView.isTrue) { emailSupervisorController.popEmailQueue(_currentEmailId); emailSupervisorController.setCurrentEmailIndex(-1); @@ -1176,9 +1174,9 @@ class SingleEmailController extends BaseController with AppLoaderMixin { mailboxDashBoardController.clearSelectedEmail(); _updateCurrentEmailId(null); _resetToOriginalValue(); - _updateRouteOnBrowser(); + _replaceBrowserHistory(); if (mailboxDashBoardController.searchController.isSearchEmailRunning) { - if (responsiveUtils.isWebDesktop(context)) { + if (context != null && responsiveUtils.isWebDesktop(context)) { mailboxDashBoardController.dispatchRoute(DashboardRoutes.thread); } else { mailboxDashBoardController.dispatchRoute(DashboardRoutes.searchEmail); @@ -1194,20 +1192,29 @@ class SingleEmailController extends BaseController with AppLoaderMixin { bool get isOpenEmailNotMailboxFromRoute => emailSupervisorController.supportedPageView.isFalse && mailboxDashBoardController.selectedMailbox.value == null; - void _updateRouteOnBrowser() { - log('SingleEmailController::_updateRouteOnBrowser(): isSearchEmailRunning: ${mailboxDashBoardController.searchController.isSearchEmailRunning}'); + void _replaceBrowserHistory() { if (PlatformInfo.isWeb) { final selectedMailboxId = mailboxDashBoardController.selectedMailbox.value?.id; - final route = RouteUtils.generateRouteBrowser( - AppRoutes.dashboard, - NavigationRouter( - mailboxId: selectedMailboxId, - dashboardType: mailboxDashBoardController.searchController.isSearchEmailRunning - ? DashboardType.search - : DashboardType.normal + final isSearchRunning = mailboxDashBoardController.searchController.isSearchEmailRunning; + RouteUtils.replaceBrowserHistory( + title: isSearchRunning + ? 'SearchEmail' + : 'Mailbox-${selectedMailboxId?.id.value}', + url: RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter( + mailboxId: isSearchRunning + ? null + : selectedMailboxId, + dashboardType: isSearchRunning + ? DashboardType.search + : DashboardType.normal, + searchQuery: isSearchRunning + ? mailboxDashBoardController.searchController.searchQuery + : null + ) ) ); - RouteUtils.updateRouteOnBrowser('Mailbox-${selectedMailboxId?.id.value}', route); } } @@ -1311,13 +1318,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } } - Future backButtonPressedCallbackAction(BuildContext context) async { - if (PlatformInfo.isMobile) { - closeEmailView(context); - } - return false; - } - void _storeOpenedEmailAction(Session? session, AccountId? accountId, DetailedEmail detailedEmail) async { if (session != null && accountId != null) { consumeState(_storeOpenedEmailInteractor.execute(session, accountId, detailedEmail)); diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index 5ae72894b..fcf0a9243 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -62,7 +62,7 @@ class EmailView extends GetWidget { presentationEmail: controller.currentEmail!, mailboxContain: _getMailboxContain(controller.currentEmail!), isSearchActivated: controller.mailboxDashBoardController.searchController.isSearchEmailRunning, - onBackAction: () => controller.closeEmailView(context), + onBackAction: () => controller.closeEmailView(context: context), onEmailActionClick: (email, action) => controller.handleEmailAction(context, email, action), onMoreActionClick: (presentationEmail, position) => _handleMoreEmailAction(context: context, presentationEmail: presentationEmail, position: position) ), @@ -96,7 +96,7 @@ class EmailView extends GetWidget { presentationEmail: currentEmail, mailboxContain: _getMailboxContain(currentEmail), isSearchActivated: controller.mailboxDashBoardController.searchController.isSearchEmailRunning, - onBackAction: () => controller.closeEmailView(context), + onBackAction: () => controller.closeEmailView(context: context), onEmailActionClick: (email, action) => controller.handleEmailAction(context, email, action), onMoreActionClick: (presentationEmail, position) => _handleMoreEmailAction(context: context, presentationEmail: presentationEmail, position: position), optionsWidget: PlatformInfo.isWeb && controller.emailSupervisorController.supportedPageView.isTrue diff --git a/lib/features/home/presentation/home_controller.dart b/lib/features/home/presentation/home_controller.dart index c2b351bc0..a563ee36c 100644 --- a/lib/features/home/presentation/home_controller.dart +++ b/lib/features/home/presentation/home_controller.dart @@ -20,7 +20,6 @@ import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_lo 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/main/routes/app_routes.dart'; -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'; @@ -60,10 +59,7 @@ class HomeController extends ReloadableController { @override void handleReloaded(Session session) { popAndPush( - RouteUtils.generateNavigationRoute( - AppRoutes.dashboard, - NavigationRouter() - ), + RouteUtils.generateNavigationRoute(AppRoutes.dashboard), arguments: session ); } diff --git a/lib/features/login/presentation/login_controller.dart b/lib/features/login/presentation/login_controller.dart index ff16483e6..c7e286e24 100644 --- a/lib/features/login/presentation/login_controller.dart +++ b/lib/features/login/presentation/login_controller.dart @@ -49,7 +49,6 @@ import 'package:tmail_ui_user/features/login/domain/usecases/save_login_username import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart'; import 'package:tmail_ui_user/features/login/presentation/model/login_arguments.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; -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/app_config.dart'; @@ -195,7 +194,7 @@ class LoginController extends ReloadableController { @override void handleReloaded(Session session) { popAndPush( - RouteUtils.generateNavigationRoute(AppRoutes.dashboard, NavigationRouter()), + RouteUtils.generateNavigationRoute(AppRoutes.dashboard), arguments: session ); } diff --git a/lib/features/mailbox/presentation/action/mailbox_ui_action.dart b/lib/features/mailbox/presentation/action/mailbox_ui_action.dart index 2a0dd928b..3cdf127db 100644 --- a/lib/features/mailbox/presentation/action/mailbox_ui_action.dart +++ b/lib/features/mailbox/presentation/action/mailbox_ui_action.dart @@ -1,7 +1,7 @@ +import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:tmail_ui_user/features/base/action/ui_action.dart'; -import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; class MailboxUIAction extends UIAction { static final idle = MailboxUIAction(); @@ -31,4 +31,6 @@ class OpenMailboxAction extends MailboxUIAction { @override List get props => [presentationMailbox]; -} \ No newline at end of file +} + +class SystemBackToInboxAction extends MailboxUIAction {} \ No newline at end of file diff --git a/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart b/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart index e473b3dcb..353592d09 100644 --- a/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart +++ b/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart @@ -84,5 +84,8 @@ extension PresentationMailboxExtension on PresentationMailbox { } } - Uri get mailboxRouteWeb => RouteUtils.generateRouteBrowser(AppRoutes.dashboard, NavigationRouter(mailboxId: id)); + Uri get mailboxRouteWeb => RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter(mailboxId: id) + ); } \ No newline at end of file diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 58312d340..9467fe2af 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -102,6 +102,7 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM final _activeScrollBottom = RxBool(true); MailboxId? _newFolderId; + NavigationRouter? _navigationRouter; final _openMailboxEventController = StreamController(); final mailboxListScrollController = ScrollController(); @@ -291,6 +292,10 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM } } mailboxDashBoardController.clearMailboxUIAction(); + } else if (action is SystemBackToInboxAction) { + _disableAllSearchEmail(); + _switchBackToMailboxDefault(); + mailboxDashBoardController.clearMailboxUIAction(); } }); } @@ -418,68 +423,122 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM } void _handleDataFromNavigationRouter() { - log('MailboxController::_handleDataFromNavigationRouter():navigationRouter: $navigationRouter'); - - if (isHasDataFromRoute) { - if (isRedirectToMailtoURL) { - mailboxDashBoardController.goToComposer( - ComposerArguments.fromMailtoUri( - emailAddress: navigationRouter?.emailAddress, - subject: navigationRouter?.subject, - body: navigationRouter?.body - ) - ); - } - - if (mailboxIdFromNavigationRouter != null) { - _selectMailboxFromRouter(); - } else if (emailIdFromNavigationRouter != null) { - mailboxDashBoardController.dispatchAction(SelectEmailByIdAction(navigationRouter!)); - _clearNavigationRouter(); - } else if (searchQueryFromNavigationRouter != null && searchQueryFromNavigationRouter?.value.isNotEmpty == true) { - mailboxDashBoardController.dispatchAction(SearchEmailByQueryAction(navigationRouter!)); - _clearNavigationRouter(); - } else { - _clearNavigationRouter(); - _selectSelectedMailboxDefault(); - _updateSelectedMailboxRouteOnBrowser(); - } - } else { + log('MailboxController::_handleDataFromNavigationRouter():navigationRouter: $_navigationRouter'); + if (!PlatformInfo.isWeb || _navigationRouter == null) { _selectSelectedMailboxDefault(); - _updateSelectedMailboxRouteOnBrowser(); + _replaceBrowserHistory(); + return; + } + + if (_navigationRouter?.routeName == AppRoutes.mailtoURL) { + mailboxDashBoardController.goToComposer( + ComposerArguments.fromMailtoUri( + emailAddress: _navigationRouter?.emailAddress, + subject: _navigationRouter?.subject, + body: _navigationRouter?.body + ) + ); + } + + switch(_navigationRouter!.dashboardType) { + case DashboardType.search: + if (_navigationRouter!.emailId != null) { + _openEmailSearchedFromLocationBar( + _navigationRouter!.emailId!, + searchQuery: _navigationRouter!.searchQuery, + ); + } else if (_navigationRouter!.searchQuery?.value.isNotEmpty == true) { + _searchEmailFromLocationBar(_navigationRouter!.searchQuery!); + } else { + _clearNavigationRouter(); + _selectSelectedMailboxDefault(); + _replaceBrowserHistory(); + } + break; + case DashboardType.normal: + if (_navigationRouter!.mailboxId != null) { + final matchedMailboxNode = findMailboxNodeById(_navigationRouter!.mailboxId!); + if (matchedMailboxNode != null) { + if (_navigationRouter!.emailId != null) { + _openEmailInsideMailboxFromLocationBar( + matchedMailboxNode.item, + _navigationRouter!.emailId! + ); + } else { + _openMailboxFromLocationBar(matchedMailboxNode.item); + } + } else { + _clearNavigationRouter(); + popAndPush(AppRoutes.unknownRoutePage); + } + } else if (_navigationRouter!.emailId != null) { + _openEmailWithoutMailboxFromLocationBar(_navigationRouter!.emailId!); + } else { + _clearNavigationRouter(); + _selectSelectedMailboxDefault(); + _replaceBrowserHistory(); + } + break; } } - NavigationRouter? get navigationRouter => mailboxDashBoardController.navigationRouter; + void _openEmailInsideMailboxFromLocationBar( + PresentationMailbox presentationMailbox, + EmailId emailId + ) { + mailboxDashBoardController.setSelectedMailbox(presentationMailbox); + mailboxDashBoardController.dispatchAction(OpenEmailInsideMailboxFromLocationBar(emailId, presentationMailbox)); + _clearNavigationRouter(); + } - bool get isHasDataFromRoute => PlatformInfo.isWeb && navigationRouter != null; + void _openMailboxFromLocationBar(PresentationMailbox presentationMailbox) { + mailboxDashBoardController.setSelectedMailbox(presentationMailbox); + if (PlatformInfo.isWeb) { + RouteUtils.replaceBrowserHistory( + title: 'Mailbox-${presentationMailbox.mailboxId?.id.value}', + url: RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter( + mailboxId: presentationMailbox.mailboxId, + dashboardType: DashboardType.normal + ) + ) + ); + } + _clearNavigationRouter(); + } - MailboxId? get mailboxIdFromNavigationRouter => navigationRouter?.mailboxId; + void _openEmailWithoutMailboxFromLocationBar(EmailId emailId) { + mailboxDashBoardController.dispatchAction( + OpenEmailWithoutMailboxFromLocationBar(emailId) + ); + _clearNavigationRouter(); + } - EmailId? get emailIdFromNavigationRouter => navigationRouter?.emailId; + void _openEmailSearchedFromLocationBar( + EmailId emailId, + { + SearchQuery? searchQuery, + } + ) { + mailboxDashBoardController.dispatchAction( + OpenEmailSearchedFromLocationBar( + emailId, + searchQuery: searchQuery, + ) + ); + _clearNavigationRouter(); + } - SearchQuery? get searchQueryFromNavigationRouter => navigationRouter?.searchQuery; - - bool get isRedirectToMailtoURL => navigationRouter?.routeName == AppRoutes.mailtoURL; + void _searchEmailFromLocationBar(SearchQuery searchQuery) { + mailboxDashBoardController.dispatchAction( + SearchEmailFromLocationBar(searchQuery) + ); + _clearNavigationRouter(); + } void _clearNavigationRouter() { - mailboxDashBoardController.navigationRouter = null; - } - - void _selectMailboxFromRouter() { - final matchedMailboxNode = findMailboxNodeById(mailboxIdFromNavigationRouter!); - if (matchedMailboxNode != null) { - mailboxDashBoardController.setSelectedMailbox(matchedMailboxNode.item); - if (emailIdFromNavigationRouter != null) { - mailboxDashBoardController.dispatchAction(SelectEmailByIdAction(navigationRouter!)); - } else { - _updateSelectedMailboxRouteOnBrowser(); - } - _clearNavigationRouter(); - } else { - _clearNavigationRouter(); - popAndPush(AppRoutes.unknownRoutePage); - } + _navigationRouter = null; } void _handleOpenMailbox( @@ -494,7 +553,7 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM mailboxDashBoardController.clearFilterMessageOption(); } _disableAllSearchEmail(); - _updateSelectedMailboxRouteOnBrowser(); + _replaceBrowserHistory(); mailboxDashBoardController.closeMailboxMenuDrawer(); mailboxDashBoardController.dispatchRoute(DashboardRoutes.thread); } @@ -779,7 +838,7 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM void _switchBackToMailboxDefault() { final inboxMailbox = findMailboxNodeByRole(PresentationMailbox.roleInbox); mailboxDashBoardController.setSelectedMailbox(inboxMailbox?.item); - _updateSelectedMailboxRouteOnBrowser(); + _replaceBrowserHistory(); _autoScrollToTopMailboxList(); } @@ -911,7 +970,7 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM if (parameters != null) { final navigationRouter = RouteUtils.parsingRouteParametersToNavigationRouter(parameters); log('MailboxController::_handleNavigationRouteParameters():navigationRouter: $navigationRouter'); - mailboxDashBoardController.navigationRouter = navigationRouter; + _navigationRouter = navigationRouter; } } @@ -1005,12 +1064,13 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM } } - void _updateSelectedMailboxRouteOnBrowser() { + void _replaceBrowserHistory() { + log('MailboxController::_updateSelectedMailboxRouteOnBrowser:selectedMailbox: ${selectedMailbox?.id}'); if (PlatformInfo.isWeb) { final selectedMailboxId = selectedMailbox?.id; - final route = RouteUtils.generateRouteBrowser( + final route = RouteUtils.createUrlWebLocationBar( AppRoutes.dashboard, - NavigationRouter( + router: NavigationRouter( mailboxId: selectedMailboxId, searchQuery: mailboxDashBoardController.searchController.isSearchEmailRunning ? mailboxDashBoardController.searchController.searchQuery @@ -1020,7 +1080,10 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM : DashboardType.normal ) ); - RouteUtils.updateRouteOnBrowser('Mailbox-${selectedMailboxId?.id.value}', route); + RouteUtils.replaceBrowserHistory( + title: 'Mailbox-${selectedMailboxId?.id.value}', + url: route + ); } } @@ -1060,7 +1123,6 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM } _setMapMailbox(); _setOutboxMailbox(); - _selectSelectedMailboxDefault(); } void _handleRefreshChangesAllMailboxSuccess(RefreshChangesAllMailboxSuccess success) async { diff --git a/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart b/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart index c04c85e1b..0982ec501 100644 --- a/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart +++ b/lib/features/mailbox_dashboard/presentation/action/dashboard_action.dart @@ -1,13 +1,15 @@ import 'package:flutter/cupertino.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/email/email_action_type.dart'; import 'package:model/email/presentation_email.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:tmail_ui_user/features/base/action/ui_action.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/quick_search_filter.dart'; import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart'; -import 'package:tmail_ui_user/main/routes/navigation_router.dart'; +import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; class DashBoardAction extends UIAction { static final idle = DashBoardAction(); @@ -81,24 +83,51 @@ class ClearSearchEmailAction extends DashBoardAction {} class ClearAllFieldOfAdvancedSearchAction extends DashBoardAction {} -class SelectEmailByIdAction extends DashBoardAction { +class OpenEmailInsideMailboxFromLocationBar extends DashBoardAction { - final NavigationRouter navigationRouter; + final EmailId emailId; + final PresentationMailbox presentationMailbox; - SelectEmailByIdAction(this.navigationRouter); + OpenEmailInsideMailboxFromLocationBar(this.emailId, this.presentationMailbox); @override - List get props => [navigationRouter]; + List get props => [emailId, presentationMailbox]; } -class SearchEmailByQueryAction extends DashBoardAction { +class OpenEmailWithoutMailboxFromLocationBar extends DashBoardAction { - final NavigationRouter navigationRouter; + final EmailId emailId; - SearchEmailByQueryAction(this.navigationRouter); + OpenEmailWithoutMailboxFromLocationBar(this.emailId); @override - List get props => [navigationRouter]; + List get props => [emailId]; +} + +class OpenEmailSearchedFromLocationBar extends DashBoardAction { + + final EmailId emailId; + final SearchQuery? searchQuery; + + OpenEmailSearchedFromLocationBar( + this.emailId, + { + this.searchQuery, + } + ); + + @override + List get props => [emailId, searchQuery]; +} + +class SearchEmailFromLocationBar extends DashBoardAction { + + final SearchQuery searchQuery; + + SearchEmailFromLocationBar(this.searchQuery); + + @override + List get props => [searchQuery]; } class SelectDateRangeToAdvancedSearch extends DashBoardAction { 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 a1d8b7035..e7af4fff4 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -140,7 +140,6 @@ import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/dialog_router.dart'; -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'; @@ -217,7 +216,6 @@ class MailboxDashBoardController extends ReloadableController { final listResultSearch = RxList(); PresentationMailbox? outboxMailbox; ComposerArguments? composerArguments; - NavigationRouter? navigationRouter; late StreamSubscription _emailAddressStreamSubscription; late StreamSubscription _emailContentStreamSubscription; @@ -585,9 +583,9 @@ class MailboxDashBoardController extends ReloadableController { setSelectedEmail(presentationEmail); dispatchRoute(DashboardRoutes.emailDetailed); if (PlatformInfo.isWeb && presentationEmail.routeWeb != null) { - RouteUtils.updateRouteOnBrowser( - 'Email-${presentationEmail.id?.id.value ?? ''}', - presentationEmail.routeWeb! + RouteUtils.replaceBrowserHistory( + title: 'Email-${presentationEmail.id?.id.value ?? ''}', + url: presentationEmail.routeWeb! ); } } @@ -2233,12 +2231,18 @@ class MailboxDashBoardController extends ReloadableController { dispatchEmailUIAction(CloseEmailDetailedViewAction()); return true; case DashboardRoutes.thread: + if (PlatformInfo.isMobile) { + return false; + } if (searchController.isSearchEmailRunning) { - dispatchMailboxUIAction(SelectMailboxDefaultAction()); + dispatchMailboxUIAction(SystemBackToInboxAction()); } else { pushAndPopAll(AppRoutes.home); } return true; + case DashboardRoutes.searchEmail: + dispatchAction(CloseSearchEmailViewAction()); + return true; default: break; } diff --git a/lib/features/mailto/presentation/mailto_url_controller.dart b/lib/features/mailto/presentation/mailto_url_controller.dart index dde78b90c..a999b7e19 100644 --- a/lib/features/mailto/presentation/mailto_url_controller.dart +++ b/lib/features/mailto/presentation/mailto_url_controller.dart @@ -4,7 +4,6 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dart'; import 'package:tmail_ui_user/features/mailto/presentation/model/mailto_arguments.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; -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'; @@ -32,10 +31,7 @@ class MailtoUrlController extends ReloadableController { mailtoUri: parameters['uri'] ); popAndPush( - RouteUtils.generateNavigationRoute( - AppRoutes.dashboard, - NavigationRouter.initial() - ), + RouteUtils.generateNavigationRoute(AppRoutes.dashboard), arguments: mailtoArgument ); } else { diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart index 4ea243a37..b53cd03d9 100644 --- a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart +++ b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart @@ -31,7 +31,6 @@ import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vaca import 'package:tmail_ui_user/main/error/capability_validator.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; -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'; @@ -205,7 +204,7 @@ class ManageAccountDashBoardController extends ReloadableController { } else { log('ManageAccountDashBoardController::backToMailboxDashBoard(): canBack: FALSE'); pushAndPopAll( - RouteUtils.generateNavigationRoute(AppRoutes.dashboard, NavigationRouter()), + RouteUtils.generateNavigationRoute(AppRoutes.dashboard), arguments: sessionCurrent); } } diff --git a/lib/features/search/email/presentation/search_email_controller.dart b/lib/features/search/email/presentation/search_email_controller.dart index 9d11a3d25..ced917094 100644 --- a/lib/features/search/email/presentation/search_email_controller.dart +++ b/lib/features/search/email/presentation/search_email_controller.dart @@ -36,8 +36,8 @@ import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_sta import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_state.dart'; +import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart'; import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; -import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_recent_search_latest_state.dart'; @@ -71,7 +71,9 @@ import 'package:tmail_ui_user/features/thread/presentation/mixin/email_action_co import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/dialog_router.dart'; +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'; class SearchEmailController extends BaseController with EmailActionController, @@ -99,6 +101,7 @@ class SearchEmailController extends BaseController late Debouncer _deBouncerTime; late Worker dashBoardViewStateWorker; + late Worker dashBoardActionWorker; late SearchMoreState searchMoreState; late bool canSearchMore; @@ -217,6 +220,16 @@ class SearchEmailController extends BaseController } }); }); + + dashBoardActionWorker = ever( + mailboxDashBoardController.dashBoardAction, + (action) { + if (action is CloseSearchEmailViewAction) { + closeSearchView(context: currentContext); + mailboxDashBoardController.clearDashBoardAction(); + } + } + ); } void _refreshEmailChanges() { @@ -293,7 +306,18 @@ class SearchEmailController extends BaseController canSearchMore = true; searchIsRunning.value = true; cancelSelectionMode(context); - + if (PlatformInfo.isWeb) { + RouteUtils.replaceBrowserHistory( + title: 'SearchEmail', + url: RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter( + searchQuery: searchQuery, + dashboardType: DashboardType.search + ) + ) + ); + } consumeState(_searchEmailInteractor.execute( session!, accountId!, @@ -646,7 +670,6 @@ class SearchEmailController extends BaseController textInputSearchController.clear(); currentSearchText.value = ''; listSuggestionSearch.clear(); - textInputSearchFocus.requestFocus(); } void clearAllResultSearch() { @@ -658,14 +681,26 @@ class SearchEmailController extends BaseController simpleSearchFilter.value = SimpleSearchFilter(); } - void closeSearchView(BuildContext context) { - log('SearchEmailController::closeSearchView(): '); + void closeSearchView({BuildContext? context}) { clearAllTextInputSearchForm(); clearAllResultSearch(); - KeyboardUtils.hideKeyboard(context); + if (context != null) { + KeyboardUtils.hideKeyboard(context); + } mailboxDashBoardController.searchController.disableAllSearchEmail(); - mailboxDashBoardController.dispatchMailboxUIAction(SelectMailboxDefaultAction()); mailboxDashBoardController.dispatchRoute(DashboardRoutes.thread); + if (PlatformInfo.isWeb) { + RouteUtils.replaceBrowserHistory( + title: 'Mailbox-${mailboxDashBoardController.selectedMailbox.value?.id.id.value}', + url: RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter( + mailboxId: mailboxDashBoardController.selectedMailbox.value?.id, + dashboardType: DashboardType.normal + ) + ) + ); + } SearchEmailBindings().disposeBindings(); } @@ -811,6 +846,7 @@ class SearchEmailController extends BaseController resultSearchScrollController.dispose(); _deBouncerTime.cancel(); dashBoardViewStateWorker.dispose(); + dashBoardActionWorker.dispose(); super.onClose(); } } \ No newline at end of file diff --git a/lib/features/search/email/presentation/search_email_view.dart b/lib/features/search/email/presentation/search_email_view.dart index 3c1855d13..85acdd51b 100644 --- a/lib/features/search/email/presentation/search_email_view.dart +++ b/lib/features/search/email/presentation/search_email_view.dart @@ -43,7 +43,7 @@ class SearchEmailView extends GetWidget Widget build(BuildContext context) { if (controller.responsiveUtils.isWebDesktop(context)) { WidgetsBinding.instance.addPostFrameCallback((_) { - controller.closeSearchView(context); + controller.closeSearchView(context: context); }); } @@ -115,7 +115,7 @@ class SearchEmailView extends GetWidget fit: BoxFit.fill ), tooltip: AppLocalizations.of(context).back, - onTap: () => controller.closeSearchView(context) + onTap: () => controller.closeSearchView(context: context) ), Expanded(child: TextFieldBuilder( onTextChange: controller.onTextSearchChange, diff --git a/lib/features/thread/domain/state/get_email_by_id_state.dart b/lib/features/thread/domain/state/get_email_by_id_state.dart index 4d7570b3f..055f0ca6a 100644 --- a/lib/features/thread/domain/state/get_email_by_id_state.dart +++ b/lib/features/thread/domain/state/get_email_by_id_state.dart @@ -1,16 +1,26 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:model/email/presentation_email.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; +import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; class GetEmailByIdLoading extends LoadingState {} class GetEmailByIdSuccess extends UIState { final PresentationEmail email; + final PresentationMailbox? mailboxContain; + final SearchQuery? searchQuery; - GetEmailByIdSuccess(this.email); + GetEmailByIdSuccess( + this.email, + { + this.mailboxContain, + this.searchQuery, + } + ); @override - List get props => [email]; + List get props => [email, mailboxContain, searchQuery]; } class GetEmailByIdFailure extends FeatureFailure { diff --git a/lib/features/thread/domain/usecases/get_email_by_id_interactor.dart b/lib/features/thread/domain/usecases/get_email_by_id_interactor.dart index 65b0ccc47..1a0d44985 100644 --- a/lib/features/thread/domain/usecases/get_email_by_id_interactor.dart +++ b/lib/features/thread/domain/usecases/get_email_by_id_interactor.dart @@ -8,6 +8,7 @@ import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:model/extensions/email_extension.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart'; import 'package:tmail_ui_user/features/thread/domain/state/get_email_by_id_state.dart'; @@ -24,6 +25,7 @@ class GetEmailByIdInteractor { EmailId emailId, { Properties? properties, + PresentationMailbox? mailboxContain, } ) async* { try { @@ -31,7 +33,13 @@ class GetEmailByIdInteractor { if (PlatformInfo.isMobile) { yield* _getStoredEmail(session, accountId, emailId, properties: properties); } else { - yield* _getEmailByIdFromServer(session, accountId, emailId, properties: properties); + yield* _getEmailByIdFromServer( + session, + accountId, + emailId, + properties: properties, + mailboxContain: mailboxContain, + ); } } catch (e) { logError('GetEmailByIdInteractor::execute():EXCEPTION: $e'); @@ -45,11 +53,14 @@ class GetEmailByIdInteractor { EmailId emailId, { Properties? properties, + PresentationMailbox? mailboxContain, } ) async* { try { final email = await _threadRepository.getEmailById(session, accountId, emailId, properties: properties); - yield Right(GetEmailByIdSuccess(email)); + yield Right( + GetEmailByIdSuccess(email, mailboxContain: mailboxContain) + ); } catch (e) { logError('GetEmailByIdInteractor::_getEmailByIdFromServer():EXCEPTION: $e'); yield Left(GetEmailByIdFailure(e)); diff --git a/lib/features/thread/presentation/extensions/list_presentation_email_extensions.dart b/lib/features/thread/presentation/extensions/list_presentation_email_extensions.dart index c88e21449..600cecd74 100644 --- a/lib/features/thread/presentation/extensions/list_presentation_email_extensions.dart +++ b/lib/features/thread/presentation/extensions/list_presentation_email_extensions.dart @@ -42,11 +42,11 @@ extension ListPresentationEmailExtensions on List { SearchQuery? searchQuery, }) { if (PlatformInfo.isWeb) { - final route = RouteUtils.generateRouteBrowser( + final route = RouteUtils.createUrlWebLocationBar( AppRoutes.dashboard, - NavigationRouter( + router: NavigationRouter( emailId: currentEmail.id, - mailboxId: selectedMailbox?.id, + mailboxId: isSearchEmailRunning ? null : selectedMailbox?.id, searchQuery: isSearchEmailRunning ? searchQuery : null, dashboardType: isSearchEmailRunning ? DashboardType.search : DashboardType.normal ) diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index 84c5033da..5b803c446 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -22,6 +22,7 @@ import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart'; +import 'package:tmail_ui_user/features/email/domain/exceptions/email_exceptions.dart'; import 'package:tmail_ui_user/features/email/domain/model/mark_read_action.dart'; import 'package:tmail_ui_user/features/email/domain/state/delete_email_permanently_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/delete_multiple_emails_permanently_state.dart'; @@ -104,7 +105,6 @@ class ThreadController extends BaseController with EmailActionController { LoadingMoreStatus loadingMoreStatus = LoadingMoreStatus.idle; MailboxId? _currentMailboxId; jmap.State? _currentEmailState; - NavigationRouter? _navigationRouter; final ScrollController listEmailController = ScrollController(); final FocusNode focusNodeKeyBoard = FocusNode(); final latestEmailSelectedOrUnselected = Rxn(); @@ -123,9 +123,7 @@ class ThreadController extends BaseController with EmailActionController { SearchEmailFilter get _searchEmailFilter => searchController.searchEmailFilter.value; - String get currentTextSearch => searchController.searchInputController.text; - - SearchQuery? get searchQuery => searchController.searchEmailFilter.value.text; + SearchQuery? get searchQuery => _searchEmailFilter.text; ThreadController( this._getEmailsInMailboxInteractor, @@ -174,7 +172,18 @@ class ThreadController extends BaseController with EmailActionController { openingEmail.value = true; } else if (success is GetEmailByIdSuccess) { openingEmail.value = false; - _openEmailDetailView(success.email); + if (searchController.isSearchEmailRunning) { + _openEmailSearchedFromLocationBar( + email: success.email, + searchQuery: searchQuery + ); + } else { + if (success.mailboxContain != null) { + _openEmailInsideMailboxFromLocationBar(success.email, success.mailboxContain!); + } else { + _openEmailWithoutMailboxFromLocationBar(success.email); + } + } } else if (success is CreateNewRuleFilterSuccess) { _createNewRuleFilterSuccess(success); } @@ -191,7 +200,6 @@ class ThreadController extends BaseController with EmailActionController { loadingMoreStatus = LoadingMoreStatus.completed; } else if (failure is GetEmailByIdFailure) { openingEmail.value = false; - _navigationRouter = null; popAndPush(AppRoutes.unknownRoutePage); } else if (failure is GetAllEmailFailure) { mailboxDashBoardController.refreshingMailboxState.value = Left(failure); @@ -265,32 +273,37 @@ class ThreadController extends BaseController with EmailActionController { } else if (action is OpenEmailDetailedFromSuggestionQuickSearchAction) { final mailboxContain = action.presentationEmail.findMailboxContain(mailboxDashBoardController.mapMailboxById); final newEmail = generateEmailByPlatform(action.presentationEmail); - pressEmailAction( - action.context, + handleEmailActionType( EmailActionType.preview, newEmail, - mailboxContain: mailboxContain + mailboxContain: mailboxContain, + context: action.context, ); mailboxDashBoardController.clearDashBoardAction(); } else if (action is StartSearchEmailAction) { cancelSelectEmail(); - _updateSearchRouteOnBrowser(); + _replaceBrowserHistory(); _searchEmail(); mailboxDashBoardController.clearDashBoardAction(); } else if (action is EmptyTrashAction) { deleteSelectionEmailsPermanently(action.context, DeleteActionType.all); mailboxDashBoardController.clearDashBoardAction(); - } else if (action is SelectEmailByIdAction) { - _navigationRouter = action.navigationRouter; - if (_navigationRouter!.searchQuery != null) { - _activateSearchFromRouter(); - } - _getEmailByIdAction(_navigationRouter!.emailId!); + } else if (action is OpenEmailInsideMailboxFromLocationBar) { + _getEmailByIdFromLocationBar( + action.emailId, + mailboxContain: action.presentationMailbox, + ); mailboxDashBoardController.clearDashBoardAction(); - } else if (action is SearchEmailByQueryAction) { - _navigationRouter = action.navigationRouter; - _activateSearchFromRouter(); + } else if (action is OpenEmailWithoutMailboxFromLocationBar) { + _getEmailByIdFromLocationBar(action.emailId); mailboxDashBoardController.clearDashBoardAction(); + } else if (action is OpenEmailSearchedFromLocationBar) { + _handleOpenEmailSearchedFromLocationBar( + emailId: action.emailId, + searchQuery: action.searchQuery + ); + } else if (action is SearchEmailFromLocationBar) { + _handleSearchEmailFromLocationBar(action.searchQuery); } else if (action is SelectDateRangeToAdvancedSearch || action is ClearDateRangeToAdvancedSearch) { if (listEmailController.hasClients) { listEmailController.jumpTo(0); @@ -356,17 +369,6 @@ class ThreadController extends BaseController with EmailActionController { }); } - void _activateSearchFromRouter() { - searchController.enableSearch(); - searchController.updateTextSearch(_navigationRouter!.searchQuery!.value); - searchController.updateFilterEmail(text: _navigationRouter!.searchQuery!); - if (currentContext != null) { - FocusScope.of(currentContext!).unfocus(); - } - searchController.searchFocus.unfocus(); - _searchEmail(); - } - void _handleErrorGetAllOrRefreshChangesEmail(Object error, StackTrace stackTrace) async { logError('ThreadController::_handleErrorGetAllOrRefreshChangesEmail():Error: $error'); if (error is CannotCalculateChangesMethodResponseException) { @@ -735,18 +737,24 @@ class ThreadController extends BaseController with EmailActionController { filter: _searchEmailFilter.mappingToEmailFilterCondition(moreFilterCondition: _getFilterCondition()), properties: EmailUtils.getPropertiesForEmailGetMethod(_session!, _accountId!), )); + } else { + dispatchState(Left(SearchEmailFailure(NotFoundEmailException()))); } } - void _updateSearchRouteOnBrowser() { + void _replaceBrowserHistory() { if (PlatformInfo.isWeb) { - final route = RouteUtils.generateRouteBrowser( - AppRoutes.dashboard, - NavigationRouter( - searchQuery: searchQuery, - dashboardType: DashboardType.search) + RouteUtils.replaceBrowserHistory( + title: 'SearchEmail', + url: RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter( + mailboxId: _searchEmailFilter.mailbox?.mailboxId, + searchQuery: searchQuery, + dashboardType: DashboardType.search + ) + ) ); - RouteUtils.updateRouteOnBrowser('SearchEmail', route); } } @@ -780,7 +788,7 @@ class ThreadController extends BaseController with EmailActionController { _accountId!, limit: ThreadConstants.defaultLimit, sort: _searchEmailFilter.sortOrder ?? _sortOrder, - filter: searchController.searchEmailFilter.value.mappingToEmailFilterCondition(moreFilterCondition: _getFilterCondition()), + filter: _searchEmailFilter.mappingToEmailFilterCondition(moreFilterCondition: _getFilterCondition()), properties: EmailUtils.getPropertiesForEmailGetMethod(_session!, _accountId!), lastEmailId: oldestEmail?.id )); @@ -877,11 +885,13 @@ class ThreadController extends BaseController with EmailActionController { } } - void pressEmailAction( - BuildContext context, - EmailActionType actionType, - PresentationEmail selectedEmail, - {PresentationMailbox? mailboxContain} + void handleEmailActionType( + EmailActionType actionType, + PresentationEmail selectedEmail, + { + PresentationMailbox? mailboxContain, + BuildContext? context, + } ) { switch(actionType) { case EmailActionType.preview: @@ -892,7 +902,7 @@ class ThreadController extends BaseController with EmailActionController { } break; case EmailActionType.selection: - selectEmail(context, selectedEmail); + selectEmail(context!, selectedEmail); break; case EmailActionType.markAsRead: markAsEmailRead(selectedEmail, ReadActions.markAsRead, MarkReadAction.tap); @@ -907,13 +917,13 @@ class ThreadController extends BaseController with EmailActionController { markAsStarEmail(selectedEmail, MarkStarAction.unMarkStar); break; case EmailActionType.moveToMailbox: - moveToMailbox(context, selectedEmail, mailboxContain: mailboxContain); + moveToMailbox(context!, selectedEmail, mailboxContain: mailboxContain); break; case EmailActionType.moveToTrash: moveToTrash(selectedEmail, mailboxContain: mailboxContain); break; case EmailActionType.deletePermanently: - deleteEmailPermanently(context, selectedEmail); + deleteEmailPermanently(context!, selectedEmail); break; case EmailActionType.moveToSpam: popBack(); @@ -924,7 +934,7 @@ class ThreadController extends BaseController with EmailActionController { unSpam(selectedEmail); break; case EmailActionType.openInNewTab: - openEmailInNewTabAction(context, selectedEmail); + openEmailInNewTabAction(context!, selectedEmail); break; default: break; @@ -939,6 +949,7 @@ class ThreadController extends BaseController with EmailActionController { void goToSearchView() { SearchEmailBindings().dependencies(); + _replaceBrowserHistory(); mailboxDashBoardController.dispatchRoute(DashboardRoutes.searchEmail); } @@ -970,11 +981,13 @@ class ThreadController extends BaseController with EmailActionController { PresentationEmail generateEmailByPlatform(PresentationEmail currentEmail) { if (PlatformInfo.isWeb) { - final route = RouteUtils.generateRouteBrowser( + final route = RouteUtils.createUrlWebLocationBar( AppRoutes.dashboard, - NavigationRouter( + router: NavigationRouter( emailId: currentEmail.id, - mailboxId: currentMailbox?.id, + mailboxId: searchController.isSearchEmailRunning + ? currentEmail.mailboxContain?.mailboxId + : currentMailbox?.id, searchQuery: searchController.isSearchEmailRunning ? searchQuery : null, @@ -990,37 +1003,98 @@ class ThreadController extends BaseController with EmailActionController { } } - void _getEmailByIdAction(EmailId emailId) { + void _getEmailByIdFromLocationBar( + EmailId emailId, + { + PresentationMailbox? mailboxContain, + } + ) { if (_session != null && _accountId != null) { consumeState(_getEmailByIdInteractor.execute( _session!, _accountId!, emailId, - properties: EmailUtils.getPropertiesForEmailGetMethod(_session!, _accountId!) + properties: EmailUtils.getPropertiesForEmailGetMethod(_session!, _accountId!), + mailboxContain: mailboxContain, )); + } else { + logError('ThreadController::_getEmailByIdFromLocationBar: session & accountId is NULL'); + popAndPush(AppRoutes.unknownRoutePage); } } - void _openEmailDetailView(PresentationEmail email) { - if (currentContext != null) { - final mailboxContain = email.findMailboxContain(mailboxDashBoardController.mapMailboxById); - final route = RouteUtils.generateRouteBrowser( + void _openEmailInsideMailboxFromLocationBar( + PresentationEmail email, + PresentationMailbox mailboxContain + ) { + final presentationEmailWithRouter = email.withRouteWeb(RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter( + emailId: email.id, + mailboxId: mailboxContain.mailboxId, + dashboardType: DashboardType.normal + ) + )); + handleEmailActionType( + EmailActionType.preview, + presentationEmailWithRouter, + mailboxContain: mailboxContain + ); + } + + void _openEmailWithoutMailboxFromLocationBar(PresentationEmail email) { + final mailboxContain = email.findMailboxContain(mailboxDashBoardController.mapMailboxById); + if (mailboxContain != null) { + mailboxDashBoardController.setSelectedMailbox(mailboxContain); + final presentationEmailWithRouter = email.withRouteWeb(RouteUtils.createUrlWebLocationBar( AppRoutes.dashboard, - NavigationRouter( + router: NavigationRouter( emailId: email.id, - mailboxId: _navigationRouter?.mailboxId, - searchQuery: _navigationRouter?.searchQuery, - dashboardType: _navigationRouter?.dashboardType ?? DashboardType.normal + mailboxId: mailboxContain.mailboxId, + dashboardType: DashboardType.normal ) - ); - pressEmailAction( - currentContext!, + )); + handleEmailActionType( EmailActionType.preview, - email.withRouteWeb(route), + presentationEmailWithRouter, + mailboxContain: mailboxContain + ); + } else { + searchController.enableSearch(); + _searchEmail(); + + final presentationEmailWithRouter = email.withRouteWeb(RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter( + emailId: email.id, + dashboardType: DashboardType.search + ) + )); + handleEmailActionType( + EmailActionType.preview, + presentationEmailWithRouter, mailboxContain: mailboxContain ); } - _navigationRouter = null; + } + + void _openEmailSearchedFromLocationBar({ + required PresentationEmail email, + SearchQuery? searchQuery, + }) { + final presentationEmailWithRouter = email.withRouteWeb(RouteUtils.createUrlWebLocationBar( + AppRoutes.dashboard, + router: NavigationRouter( + emailId: email.id, + searchQuery: searchQuery, + dashboardType: DashboardType.search + ) + )); + handleEmailActionType( + EmailActionType.preview, + presentationEmailWithRouter, + mailboxContain: email.findMailboxContain(mailboxDashBoardController.mapMailboxById) + ); } void onDragMailBox(bool isDrag) { @@ -1086,7 +1160,7 @@ class ThreadController extends BaseController with EmailActionController { return false; } - DismissDirection getSwipeDirection (bool isWebDesktop, SelectMode selectMode) { + DismissDirection getSwipeDirection(bool isWebDesktop, SelectMode selectMode) { if (isWebDesktop) { return DismissDirection.none; } @@ -1098,19 +1172,40 @@ class ThreadController extends BaseController with EmailActionController { return DismissDirection.startToEnd; } - Future backButtonPressedCallbackAction(BuildContext context) async { - if (PlatformInfo.isMobile && - mailboxDashBoardController.selectedMailbox.value?.isInbox == false) { - mailboxDashBoardController.openDefaultMailbox(); - return false; - } else { - return true; - } - } - void scrollToTop() { if (listEmailController.hasClients) { listEmailController.animateTo(0, duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); } } + + void _handleOpenEmailSearchedFromLocationBar({ + required EmailId emailId, + SearchQuery? searchQuery, + }) { + searchController.enableSearch(); + if (searchQuery != null) { + searchController.updateTextSearch(searchQuery.value); + searchController.updateFilterEmail(text: searchQuery); + if (currentContext != null) { + FocusScope.of(currentContext!).unfocus(); + } + searchController.searchFocus.unfocus(); + } + _searchEmail(); + _getEmailByIdFromLocationBar(emailId); + mailboxDashBoardController.clearDashBoardAction(); + } + + void _handleSearchEmailFromLocationBar(SearchQuery searchQuery) { + dispatchState(Right(SearchingState())); + searchController.enableSearch(); + searchController.updateTextSearch(searchQuery.value); + searchController.updateFilterEmail(text: searchQuery); + if (currentContext != null) { + FocusScope.of(currentContext!).unfocus(); + } + searchController.searchFocus.unfocus(); + _searchEmail(); + mailboxDashBoardController.clearDashBoardAction(); + } } \ No newline at end of file diff --git a/lib/features/thread/presentation/thread_view.dart b/lib/features/thread/presentation/thread_view.dart index 7afc8ebc0..bdeb4790b 100644 --- a/lib/features/thread/presentation/thread_view.dart +++ b/lib/features/thread/presentation/thread_view.dart @@ -482,11 +482,11 @@ class ThreadView extends GetWidget PresentationEmail presentationEmail, EmailActionType actionType ) { - controller.pressEmailAction( - context, + controller.handleEmailActionType( actionType, presentationEmail, - mailboxContain: presentationEmail.mailboxContain + mailboxContain: presentationEmail.mailboxContain, + context: context ); } @@ -629,11 +629,12 @@ class ThreadView extends GetWidget iconRightPadding: controller.responsiveUtils.isMobile(context) ? const EdgeInsets.only(right: 12) : EdgeInsets.zero) - ..onActionClick((email) => controller.pressEmailAction(context, + ..onActionClick((email) => controller.handleEmailActionType( mailboxContain?.isSpam == true ? EmailActionType.unSpam : EmailActionType.moveToSpam, email, - mailboxContain: mailboxContain) - ) + mailboxContain: mailboxContain, + context: context, + )) ).build(); } @@ -689,11 +690,11 @@ class ThreadView extends GetWidget fontSize: 16, color: Colors.black ), - onCallbackAction: () => controller.pressEmailAction( - context, + onCallbackAction: () => controller.handleEmailActionType( mailboxContain?.isSpam == true ? EmailActionType.unSpam : EmailActionType.moveToSpam, email, - mailboxContain: mailboxContain + mailboxContain: mailboxContain, + context: context ) ) ); diff --git a/lib/main/routes/route_utils.dart b/lib/main/routes/route_utils.dart index 758a2b299..86560fe14 100644 --- a/lib/main/routes/route_utils.dart +++ b/lib/main/routes/route_utils.dart @@ -33,9 +33,17 @@ abstract class RouteUtils { static String get baseUrl => Uri.base.path; - static String generateNavigationRoute(String route, NavigationRouter router) { - ServicePath servicePath = ServicePath(route); + static String generateNavigationRoute(String route, {NavigationRouter? router}) { if (PlatformInfo.isWeb) { + return _createServicePath(route, router: router).path; + } else { + return route; + } + } + + static ServicePath _createServicePath(String route, {NavigationRouter? router}) { + ServicePath servicePath = ServicePath(route); + if (router != null) { if (router.emailId != null) { servicePath = servicePath.withPathParameter(router.emailId!.id.value); } @@ -46,26 +54,16 @@ abstract class RouteUtils { if (router.searchQuery != null) StringQueryParameter(paramQuery, router.searchQuery!.value), ]); - return servicePath.path; } else { - return servicePath.path; + servicePath = servicePath.withQueryParameters([ + StringQueryParameter(paramType, DashboardType.normal.name) + ]); } + return servicePath; } - static Uri generateRouteBrowser(String route, NavigationRouter router) { - final baseRoutePath = '$baseOriginUrl$route'; - ServicePath servicePath = ServicePath(baseRoutePath); - if (router.emailId != null) { - servicePath = servicePath.withPathParameter(router.emailId!.id.value); - } - servicePath = servicePath.withQueryParameters([ - StringQueryParameter(paramType, router.dashboardType.name), - if (router.mailboxId != null) - StringQueryParameter(paramContext, router.mailboxId!.id.value), - if (router.searchQuery != null) - StringQueryParameter(paramQuery, router.searchQuery!.value), - ]); - + static Uri createUrlWebLocationBar(String route, {NavigationRouter? router}) { + final servicePath = _createServicePath('$baseOriginUrl$route', router: router); return Uri.parse(servicePath.path); } @@ -101,10 +99,9 @@ abstract class RouteUtils { ); } - static void updateRouteOnBrowser(String title, Uri newRoute) { - log('RouteUtils::updateRouteOnBrowser(): title: $title'); - log('RouteUtils::updateRouteOnBrowser(): newRoute: $newRoute'); - html.window.history.replaceState(null, title, newRoute.toString()); + static void replaceBrowserHistory({required String title, required Uri url}) { + log('RouteUtils::replaceBrowserHistory(): title: $title | url: $url'); + html.window.history.replaceState(null, title, url.toString()); } static Map parseMapMailtoFromUri(String? mailtoUri) {