TF-934 Handle route path when open email in new tab

This commit is contained in:
dab246
2022-11-04 22:00:37 +07:00
committed by Dat H. Pham
parent 4c9beb7526
commit 171b791449
12 changed files with 189 additions and 71 deletions
@@ -15,8 +15,17 @@ extension ServicePathExtension on ServicePath {
if (queryParameters.isEmpty) {
return this;
}
return ServicePath('$path?${queryParameters
.map((query) => '${query.queryName}=${query.queryValue}').join('&')}');
if (path.lastIndexOf('/') == path.length - 1) {
final newPath = path.substring(0, path.length - 1);
return ServicePath('$newPath?${queryParameters
.map((query) => '${query.queryName}=${query.queryValue}')
.join('&')}');
} else {
return ServicePath('$path?${queryParameters
.map((query) => '${query.queryName}=${query.queryValue}')
.join('&')}');
}
}
ServicePath withPathParameter(String? pathParameter) {
@@ -49,7 +49,9 @@ import 'package:tmail_ui_user/features/login/presentation/state/login_state.dart
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
import 'package:tmail_ui_user/features/network_status_handle/presentation/network_connnection_controller.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';
class LoginController extends ReloadableController {
@@ -191,7 +193,9 @@ class LoginController extends ReloadableController {
@override
void handleReloaded(Session session) {
pushAndPop(AppRoutes.dashboard, arguments: session);
pushAndPop(
RouteUtils.generateRoutePathMobile(AppRoutes.dashboard, NavigationRouter()),
arguments: session);
}
void _getAuthenticationInfo() {
@@ -69,6 +69,7 @@ import 'package:tmail_ui_user/features/thread/presentation/model/search_status.d
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/route_navigation.dart';
import 'package:tmail_ui_user/main/routes/route_utils.dart';
import 'package:uuid/uuid.dart';
class MailboxController extends BaseMailboxController {
@@ -102,7 +103,10 @@ class MailboxController extends BaseMailboxController {
jmap.State? _currentMailboxState;
List<String> listMailboxNameAsStringExist = <String>[];
late Worker accountIdWorker, viewStateWorker, dashboardActionWorker;
late Worker accountIdWorker,
viewStateWorker,
dashboardActionWorker,
routerParametersWorker;
MailboxController(
this._getAllMailboxInteractor,
@@ -118,7 +122,7 @@ class MailboxController extends BaseMailboxController {
@override
void onInit() {
_initWorker();
_registerListenerWorker();
_registerSearchFocusListener();
super.onInit();
}
@@ -139,7 +143,7 @@ class MailboxController extends BaseMailboxController {
searchFocus.dispose();
_openMailboxEventController.close();
mailboxListScrollController.dispose();
_clearWorker();
_unregisterListenerWorker();
super.onClose();
}
@@ -151,6 +155,7 @@ class MailboxController extends BaseMailboxController {
_currentMailboxState = success.currentMailboxState;
await buildTree(success.mailboxList);
_setUpMapMailbox(success.mailboxList, defaultMailboxTree.value, folderMailboxTree.value);
_selectMailboxById();
} else if (success is RefreshChangesAllMailboxSuccess) {
_currentMailboxState = success.currentMailboxState;
await refreshTree(success.mailboxList);
@@ -191,13 +196,18 @@ class MailboxController extends BaseMailboxController {
);
}
void _initWorker() {
void _registerListenerWorker() {
accountIdWorker = ever(mailboxDashBoardController.accountId, (accountId) {
if (accountId is AccountId) {
getAllMailboxAction(accountId);
}
});
routerParametersWorker = ever<Map<String, String?>?>(
mailboxDashBoardController.routerParameters,
_handleNavigationRouteParameters
);
viewStateWorker = ever(mailboxDashBoardController.viewState, (state) {
if (state is Either) {
state.fold((failure) => null, (success) {
@@ -260,10 +270,11 @@ class MailboxController extends BaseMailboxController {
});
}
void _clearWorker() {
accountIdWorker.call();
viewStateWorker.call();
dashboardActionWorker.call();
void _unregisterListenerWorker() {
accountIdWorker.dispose();
viewStateWorker.dispose();
dashboardActionWorker.dispose();
routerParametersWorker.dispose();
}
void _initCollapseMailboxCategories() {
@@ -985,6 +996,34 @@ class MailboxController extends BaseMailboxController {
}
}
void _selectMailboxById() {
if (mailboxDashBoardController.navigationRouter != null) {
final mailboxId = mailboxDashBoardController.navigationRouter?.mailboxId;
if (mailboxId != null) {
final matchedMailboxNode = findMailboxNodeById(mailboxId);
if (matchedMailboxNode != null && currentContext != null) {
mailboxDashBoardController.setSelectedMailbox(matchedMailboxNode.item);
}
}
final emailId = mailboxDashBoardController.navigationRouter?.emailId;
if (emailId != null) {
mailboxDashBoardController.dispatchAction(SelectEmailByIdAction(emailId));
}
mailboxDashBoardController.navigationRouter = null;
}
}
void _handleNavigationRouteParameters(Map<String, String?>? parameters) {
log('MailboxDashBoardController::_handleNavigationRouteParameters(): parameters: $parameters');
if (parameters != null) {
final navigationRouter = RouteUtils.parsingRouteParametersToNavigationRouter(parameters);
log('ThreadController::_handleNavigationRouteParameters():navigationRouter: $navigationRouter');
mailboxDashBoardController.navigationRouter = navigationRouter;
}
}
void _showAppDashboardAction() {
mailboxDashBoardController.showAppDashboardAction();
}
@@ -1,5 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/email/email_action_type.dart';
import 'package:model/email/presentation_email.dart';
import 'package:tmail_ui_user/features/base/action/ui_action.dart';
@@ -109,4 +110,14 @@ class SelectMailboxDefaultAction extends DashBoardAction {
@override
List<Object?> get props => [];
}
class SelectEmailByIdAction extends DashBoardAction {
final EmailId emailId;
SelectEmailByIdAction(this.emailId);
@override
List<Object?> get props => [emailId];
}
@@ -77,6 +77,7 @@ import 'package:tmail_ui_user/features/thread/domain/usecases/move_multiple_emai
import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.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/router_arguments.dart';
import 'package:tmail_ui_user/main/utils/email_receive_manager.dart';
@@ -122,6 +123,7 @@ class MailboxDashBoardController extends ReloadableController {
final composerOverlayState = ComposerOverlayState.inActive.obs;
final viewStateMarkAsReadMailbox = Rx<Either<Failure, Success>>(Right(UIState.idle));
final vacationResponse = Rxn<VacationResponse>();
final routerParameters = Rxn<Map<String, String?>>();
Session? sessionCurrent;
Map<Role, MailboxId> mapDefaultMailboxIdByRole = {};
@@ -130,6 +132,7 @@ class MailboxDashBoardController extends ReloadableController {
final listResultSearch = RxList<PresentationEmail>();
PresentationMailbox? outboxMailbox;
RouterArguments? routerArguments;
NavigationRouter? navigationRouter;
late StreamSubscription _emailReceiveManagerStreamSubscription;
late StreamSubscription _fileReceiveManagerStreamSubscription;
@@ -1025,6 +1028,13 @@ class MailboxDashBoardController extends ReloadableController {
injectRuleFilterBindings(sessionCurrent, accountId.value);
injectVacationBindings(sessionCurrent, accountId.value);
_getVacationResponse();
_getRouteParameters();
}
void _getRouteParameters() {
final parameters = Get.parameters;
log('MailboxDashBoardController::_getRouteParameters(): parameters: $parameters');
routerParameters.value = parameters;
}
UnsignedInt? get maxSizeAttachmentsPerEmail {
@@ -32,7 +32,9 @@ 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';
class ManageAccountDashBoardController extends ReloadableController {
@@ -224,7 +226,9 @@ class ManageAccountDashBoardController extends ReloadableController {
popBack(result: vacationResponse.value);
} else {
log('ManageAccountDashBoardController::backToMailboxDashBoard(): canBack: FALSE');
pushAndPopAll(AppRoutes.dashboard, arguments: sessionCurrent);
pushAndPopAll(
RouteUtils.generateRoutePathMobile(AppRoutes.dashboard, NavigationRouter()),
arguments: sessionCurrent);
}
}
@@ -16,7 +16,9 @@ import 'package:tmail_ui_user/features/session/domain/usecases/get_session_inter
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/navigation_router.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
import 'package:tmail_ui_user/main/routes/route_utils.dart';
class SessionController extends ReloadableController {
final GetSessionInteractor _getSessionInteractor;
@@ -55,7 +57,9 @@ class SessionController extends ReloadableController {
@override
void handleReloaded(Session session) {
pushAndPop(AppRoutes.dashboard, arguments: session);
pushAndPop(
RouteUtils.generateRoutePathMobile(AppRoutes.dashboard, NavigationRouter()),
arguments: session);
}
void _getSession() async {
@@ -103,7 +107,9 @@ class SessionController extends ReloadableController {
final apiUrl = success.session.apiUrl.toString();
if (apiUrl.isNotEmpty) {
_dynamicUrlInterceptors.changeBaseUrl(apiUrl);
pushAndPop(AppRoutes.dashboard, arguments: success.session);
pushAndPop(
RouteUtils.generateRoutePathMobile(AppRoutes.dashboard, NavigationRouter()),
arguments: success.session);
} else {
_goToLogin();
}
@@ -34,6 +34,7 @@ import 'package:tmail_ui_user/features/thread/data/network/thread_isolate_worker
import 'package:tmail_ui_user/features/thread/data/repository/thread_repository_impl.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/empty_trash_folder_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_email_by_id_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/load_more_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart';
@@ -65,6 +66,7 @@ class ThreadBindings extends BaseBindings {
Get.find<MarkAsEmailReadInteractor>(),
Get.find<MoveToMailboxInteractor>(),
Get.find<CachingManager>(),
Get.find<GetEmailByIdInteractor>(),
));
}
@@ -135,6 +137,7 @@ class ThreadBindings extends BaseBindings {
Get.lazyPut(() => MoveToMailboxInteractor(
Get.find<EmailRepository>(),
Get.find<MailboxRepository>()));
Get.lazyPut(() => GetEmailByIdInteractor(Get.find<ThreadRepository>()));
}
@override
@@ -54,6 +54,7 @@ import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.dar
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/features/thread/domain/state/empty_trash_folder_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/get_email_by_id_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/load_more_emails_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_star_multiple_email_state.dart';
@@ -62,6 +63,7 @@ import 'package:tmail_ui_user/features/thread/domain/state/refresh_changes_all_e
import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/search_more_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/empty_trash_folder_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_email_by_id_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/load_more_emails_in_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart';
@@ -102,6 +104,7 @@ class ThreadController extends BaseController {
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
final MoveToMailboxInteractor _moveToMailboxInteractor;
final CachingManager _cachingManager;
final GetEmailByIdInteractor _getEmailByIdInteractor;
final listEmailDrag = <PresentationEmail>[].obs;
bool _rangeSelectionMode = false;
@@ -149,11 +152,12 @@ class ThreadController extends BaseController {
this._markAsEmailReadInteractor,
this._moveToMailboxInteractor,
this._cachingManager,
this._getEmailByIdInteractor,
);
@override
void onInit() {
_initWorker();
_registerListenerWorker();
super.onInit();
}
@@ -167,7 +171,7 @@ class ThreadController extends BaseController {
void onClose() {
listEmailController.dispose();
focusNodeKeyBoard.dispose();
_clearWorker();
_unregisterListenerWorker();
super.onClose();
}
@@ -195,6 +199,16 @@ class ThreadController extends BaseController {
_searchMoreEmailsSuccess(success);
} else if (success is SearchingMoreState || success is LoadingMoreState) {
_isLoadingMore = true;
} else if (success is GetEmailByIdSuccess) {
if (currentContext != null) {
final mailboxContain = success.email
.findMailboxContain(mailboxDashBoardController.mapMailboxById);
pressEmailAction(
currentContext!,
EmailActionType.preview,
success.email,
mailboxContain: mailboxContain);
}
}
}
);
@@ -243,7 +257,7 @@ class ThreadController extends BaseController {
_handleErrorGetAllOrRefreshChangesEmail(error);
}
void _initWorker() {
void _registerListenerWorker() {
mailboxWorker = ever(mailboxDashBoardController.selectedMailbox, (mailbox) {
if (mailbox is PresentationMailbox) {
if (_currentMailboxId != mailbox.id) {
@@ -272,39 +286,40 @@ class ThreadController extends BaseController {
});
dashboardActionWorker = ever(mailboxDashBoardController.dashBoardAction, (action) {
if (action is DashBoardAction) {
if (action is RefreshAllEmailAction) {
refreshAllEmail();
mailboxDashBoardController.clearDashBoardAction();
} else if (action is SelectionAllEmailAction) {
setSelectAllEmailAction();
mailboxDashBoardController.clearDashBoardAction();
} else if (action is CancelSelectionAllEmailAction) {
cancelSelectEmail();
mailboxDashBoardController.clearDashBoardAction();
} else if (action is FilterMessageAction) {
filterMessagesAction(action.context, action.option);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is HandleEmailActionTypeAction) {
pressEmailSelectionAction(action.context, action.emailAction, action.listEmailSelected);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is OpenEmailDetailedFromSuggestionQuickSearchAction) {
final mailboxContain = action.presentationEmail
.findMailboxContain(mailboxDashBoardController.mapMailboxById);
pressEmailAction(
action.context,
EmailActionType.preview,
action.presentationEmail,
mailboxContain: mailboxContain);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is StartSearchEmailAction) {
cancelSelectEmail();
_searchEmail();
mailboxDashBoardController.clearDashBoardAction();
} else if (action is EmptyTrashAction) {
deleteSelectionEmailsPermanently(action.context, DeleteActionType.all);
mailboxDashBoardController.clearDashBoardAction();
}
if (action is RefreshAllEmailAction) {
refreshAllEmail();
mailboxDashBoardController.clearDashBoardAction();
} else if (action is SelectionAllEmailAction) {
setSelectAllEmailAction();
mailboxDashBoardController.clearDashBoardAction();
} else if (action is CancelSelectionAllEmailAction) {
cancelSelectEmail();
mailboxDashBoardController.clearDashBoardAction();
} else if (action is FilterMessageAction) {
filterMessagesAction(action.context, action.option);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is HandleEmailActionTypeAction) {
pressEmailSelectionAction(action.context, action.emailAction, action.listEmailSelected);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is OpenEmailDetailedFromSuggestionQuickSearchAction) {
final mailboxContain = action.presentationEmail
.findMailboxContain(mailboxDashBoardController.mapMailboxById);
pressEmailAction(
action.context,
EmailActionType.preview,
action.presentationEmail,
mailboxContain: mailboxContain);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is StartSearchEmailAction) {
cancelSelectEmail();
_searchEmail();
mailboxDashBoardController.clearDashBoardAction();
} else if (action is EmptyTrashAction) {
deleteSelectionEmailsPermanently(action.context, DeleteActionType.all);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is SelectEmailByIdAction) {
_openEmailDetailedView(action.emailId);
mailboxDashBoardController.clearDashBoardAction();
}
});
@@ -339,12 +354,12 @@ class ThreadController extends BaseController {
});
}
void _clearWorker() {
mailboxWorker.call();
dashboardActionWorker.call();
searchWorker.call();
advancedSearchFilterWorker.call();
viewStateWorker.call();
void _unregisterListenerWorker() {
mailboxWorker.dispose();
dashboardActionWorker.dispose();
searchWorker.dispose();
advancedSearchFilterWorker.dispose();
viewStateWorker.dispose();
}
void _handleErrorGetAllOrRefreshChangesEmail(dynamic error) async {
@@ -1529,4 +1544,13 @@ class ThreadController extends BaseController {
? KeyEventResult.handled
: KeyEventResult.ignored;
}
void _openEmailDetailedView(EmailId emailId) {
if (_accountId != null) {
consumeState(_getEmailByIdInteractor.execute(
_accountId!,
emailId,
properties: ThreadConstants.propertiesDefault));
}
}
}
@@ -12,8 +12,8 @@ import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/features/thread/presentation/mixin/base_email_item_tile.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/browser_route_utils.dart';
import 'package:tmail_ui_user/main/routes/navigation_router.dart';
import 'package:tmail_ui_user/main/routes/route_utils.dart';
import 'package:url_launcher/link.dart';
class EmailTileBuilder with BaseEmailItemTile {
@@ -91,7 +91,7 @@ class EmailTileBuilder with BaseEmailItemTile {
color: AppColor.colorItemEmailSelectedDesktop)
: null,
child: Link(
uri: BrowserRouteUtils.generateRoutePathBrowser(
uri: RouteUtils.generateRoutePathBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: _presentationEmail.id,
@@ -118,7 +118,7 @@ class EmailTileBuilder with BaseEmailItemTile {
color: Colors.white),
alignment: Alignment.center,
child: Link(
uri: BrowserRouteUtils.generateRoutePathBrowser(
uri: RouteUtils.generateRoutePathBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: _presentationEmail.id,
+5 -5
View File
@@ -43,11 +43,11 @@ class AppPages {
page: () => DeferredWidget(session.loadLibrary, () => session.SessionView()),
binding: SessionPageBindings()),
GetPage(
name: AppRoutes.dashboard,
page: () => DeferredWidget(
mailbox_dashboard.loadLibrary,
() => mailbox_dashboard.MailboxDashBoardView()),
binding: MailboxDashBoardBindings()),
name: AppRoutes.dashboard,
page: () => DeferredWidget(
mailbox_dashboard.loadLibrary,
() => mailbox_dashboard.MailboxDashBoardView()),
binding: MailboxDashBoardBindings()),
GetPage(
name: AppRoutes.dashboardWithParameter,
page: () => DeferredWidget(
@@ -1,17 +1,30 @@
import 'package:core/data/model/query/query_parameter.dart';
import 'package:core/data/network/config/service_path.dart';
import 'package:core/utils/app_logger.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:tmail_ui_user/features/login/data/extensions/service_path_extension.dart';
import 'package:tmail_ui_user/main/routes/navigation_router.dart';
class BrowserRouteUtils {
class RouteUtils {
static String get baseOriginUrl => Uri.base.origin;
static String generateRoutePathMobile(String route, NavigationRouter router) {
ServicePath servicePath = ServicePath(route);
if (router.emailId != null) {
servicePath = servicePath.withPathParameter(router.emailId!.id.value);
}
servicePath = servicePath.withQueryParameters([
StringQueryParameter('type', router.dashboardType.name),
if (router.mailboxId != null)
StringQueryParameter('context', router.mailboxId!.id.value),
]);
return servicePath.path;
}
static Uri generateRoutePathBrowser(String route, NavigationRouter router) {
final baseRoutePath = '$baseOriginUrl/#$route';
ServicePath servicePath = ServicePath(baseRoutePath);
@@ -24,7 +37,6 @@ class BrowserRouteUtils {
StringQueryParameter('context', router.mailboxId!.id.value),
]);
log('BrowserRouteUtils::generateRoutePathForBrowser(): routePath: ${servicePath.path}');
return Uri.parse(servicePath.path);
}
@@ -33,10 +45,6 @@ class BrowserRouteUtils {
final typeParam = parameters['type'];
final contextPram = parameters['context'];
log('BrowserRouteUtils::parsingRouteParametersToNavigationRouter(): idParam: $idParam');
log('BrowserRouteUtils::parsingRouteParametersToNavigationRouter(): typeParam: $typeParam');
log('BrowserRouteUtils::parsingRouteParametersToNavigationRouter(): contextPram: $contextPram');
final emailId = idParam != null ? EmailId(Id(idParam)) : null;
final mailboxId = contextPram != null ? MailboxId(Id(contextPram)) : null;
final dashboardType = typeParam == DashboardType.search.name