TF-934 Select mailbox, email when change route on browser

This commit is contained in:
dab246
2022-11-10 20:14:47 +07:00
committed by Dat H. Pham
parent aa8b80975e
commit 6050ee5386
21 changed files with 491 additions and 287 deletions
@@ -1,6 +1,6 @@
import 'dart:collection';
import 'package:core/utils/build_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
@@ -25,8 +25,15 @@ class EmailSupervisorController extends BaseController {
Session? get sessionCurrent => mailboxDashBoardController.sessionCurrent;
AccountId? get accountId => mailboxDashBoardController.accountId.value;
RxList<PresentationEmail> get listEmail => mailboxDashBoardController.searchController.isSearchEmailRunning && !kIsWeb ?
mailboxDashBoardController.listResultSearch : mailboxDashBoardController.emailsInCurrentMailbox;
RxList<PresentationEmail> get listEmail {
if (mailboxDashBoardController.searchController.isSearchEmailRunning && !BuildUtils.isWeb) {
return mailboxDashBoardController.listResultSearch;
} else {
return mailboxDashBoardController.emailsInCurrentMailbox;
}
}
bool get supportedPageView => listEmail.isNotEmpty;
@override
void onClose() {
@@ -52,6 +52,7 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_dialog_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.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';
@@ -66,7 +67,9 @@ import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.
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/route_utils.dart';
import 'package:uuid/uuid.dart';
class SingleEmailController extends BaseController with AppLoaderMixin {
@@ -129,7 +132,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
@override
void onInit() {
_initializeDebounceTimeIndexPageViewChange();
_initWorker();
_registerListenerWorker();
_listenDownloadAttachmentProgressState();
injectRuleFilterBindings(
emailSupervisorController.sessionCurrent,
@@ -160,7 +163,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
void onClose() {
_downloadProgressStateController.close();
_getEmailDeBouncer.cancel();
_clearWorker();
_unregisterListenerWorker();
super.onClose();
}
@@ -172,14 +175,18 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
});
}
void _initWorker() {
void _registerListenerWorker() {
emailWorker = ever(emailSupervisorController.selectedEmail, (presentationEmail) {
log('SingleEmailController::_initWorker(): $presentationEmail');
if (presentationEmail is PresentationEmail) {
if (_currentEmailId != presentationEmail.id) {
_currentEmailId = presentationEmail.id;
emailSupervisorController.setCurrentPositionEmailInListEmail(_currentEmailId);
_getEmailDeBouncer.value = emailSupervisorController.currentIndexPageView;
if (emailSupervisorController.supportedPageView) {
emailSupervisorController.setCurrentPositionEmailInListEmail(_currentEmailId);
_getEmailDeBouncer.value = emailSupervisorController.currentIndexPageView;
} else {
_getEmailContentAction(presentationEmail.id);
}
_resetToOriginalValue();
if (!presentationEmail.hasRead) {
markAsEmailRead(presentationEmail, ReadActions.markAsRead);
@@ -192,8 +199,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
});
}
void _clearWorker() {
emailWorker.call();
void _unregisterListenerWorker() {
emailWorker.dispose();
}
void _listenDownloadAttachmentProgressState() {
@@ -984,12 +991,16 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
}
void closeEmailView(BuildContext context) {
emailSupervisorController.presentationEmailsLoaded.removeWhere((e) => e.emailCurrent?.id == currentEmail?.id);
emailSupervisorController.currentIndexPageView = -1;
_getEmailDeBouncer.value = null;
log('SingleEmailController::closeEmailView(): ');
if (emailSupervisorController.supportedPageView) {
emailSupervisorController.presentationEmailsLoaded.removeWhere((e) => e.emailCurrent?.id == currentEmail?.id);
emailSupervisorController.currentIndexPageView = -1;
_getEmailDeBouncer.value = null;
}
mailboxDashBoardController.clearSelectedEmail();
_currentEmailId = null;
_resetToOriginalValue();
_updateRouteOnBrowser();
if (mailboxDashBoardController.searchController.isSearchEmailRunning) {
if (responsiveUtils.isWebDesktop(context)) {
mailboxDashBoardController.dispatchRoute(DashboardRoutes.thread);
@@ -998,6 +1009,28 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
}
} else {
mailboxDashBoardController.dispatchRoute(DashboardRoutes.thread);
if (isOpenEmailNotMailboxFromRoute) {
mailboxDashBoardController.dispatchAction(SelectMailboxDefaultAction());
}
}
}
bool get isOpenEmailNotMailboxFromRoute => !emailSupervisorController.supportedPageView
&& mailboxDashBoardController.selectedMailbox.value == null;
void _updateRouteOnBrowser() {
if (BuildUtils.isWeb) {
final selectedMailboxId = mailboxDashBoardController.selectedMailbox.value?.id;
final route = RouteUtils.generateRouteBrowser(
AppRoutes.dashboard,
NavigationRouter(
mailboxId: selectedMailboxId,
dashboardType: mailboxDashBoardController.searchController.isSearchEmailRunning
? DashboardType.search
: DashboardType.normal
)
);
RouteUtils.updateRouteOnBrowser('Mailbox-${selectedMailboxId?.id.value}', route);
}
}
+19 -13
View File
@@ -1,7 +1,6 @@
import 'package:core/core.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
@@ -55,7 +54,6 @@ class EmailView extends GetWidget<SingleEmailController> {
: const BoxDecoration(color: Colors.white),
margin: _getMarginEmailView(context),
child: Obx(() {
log('EmailView::_buildLoadingView(): ${controller.currentEmail}');
if (controller.currentEmail != null) {
return _buildEmailView(context, controller.currentEmail!);
} else {
@@ -90,21 +88,28 @@ class EmailView extends GetWidget<SingleEmailController> {
_buildAppBar(context, email),
_buildVacationNotificationMessage(context),
const Divider(color: AppColor.colorDividerHorizontal, height: 1),
Expanded(
child: PageView.builder(
physics: kIsWeb ? const NeverScrollableScrollPhysics() : null,
itemCount: controller.emailSupervisorController.listEmail.length,
controller: controller.emailSupervisorController.pageController,
onPageChanged: controller.emailSupervisorController.onPageChanged,
itemBuilder: (context, index) {
return _buildEmailBody(context, controller.emailSupervisorController.listEmail[index]);
}),
Expanded(child: controller.emailSupervisorController.supportedPageView
? _buildMultipleEmailView(controller.emailSupervisorController.listEmail)
: _buildSingleEmailView(context, email),
),
const Divider(color: AppColor.colorDividerHorizontal, height: 1),
_buildBottomBar(context, email),
]);
}
Widget _buildMultipleEmailView(List<PresentationEmail> listEmails) {
return PageView.builder(
physics: BuildUtils.isWeb ? const NeverScrollableScrollPhysics() : null,
itemCount: listEmails.length,
controller: controller.emailSupervisorController.pageController,
onPageChanged: controller.emailSupervisorController.onPageChanged,
itemBuilder: (context, index) => _buildSingleEmailView(context, listEmails[index])
);
}
Widget _buildSingleEmailView(BuildContext context, PresentationEmail email) {
return _buildEmailBody(context, email);
}
bool _supportVerticalDivider(BuildContext context) {
if (BuildUtils.isWeb) {
@@ -156,7 +161,9 @@ class EmailView extends GetWidget<SingleEmailController> {
_popupMenuEmailActionTile(context, email));
}
},
optionsWidget: kIsWeb ? _buildNavigatorPageViewWidgets(context) : null,
optionsWidget: BuildUtils.isWeb && controller.emailSupervisorController.supportedPageView
? _buildNavigatorPageViewWidgets(context)
: null,
));
}
@@ -323,7 +330,6 @@ class EmailView extends GetWidget<SingleEmailController> {
return controller.viewState.value.fold(
(failure) => const SizedBox.shrink(),
(success) {
log('EmailView::_buildLoadingView(): $success');
if (success is LoadingState) {
return const Align(alignment: Alignment.topCenter, child: Padding(
padding: EdgeInsets.all(16),
@@ -194,7 +194,7 @@ class LoginController extends ReloadableController {
@override
void handleReloaded(Session session) {
pushAndPop(
RouteUtils.generateRoutePathMobile(AppRoutes.dashboard, NavigationRouter()),
RouteUtils.generateRouteMobile(AppRoutes.dashboard, NavigationRouter()),
arguments: session);
}
@@ -10,6 +10,7 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/error/method/error_method_response.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
@@ -46,7 +47,6 @@ import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_action
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories_expand_mode.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/open_mailbox_view_event.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_utils.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/duplicate_name_validator.dart';
@@ -68,6 +68,7 @@ import 'package:tmail_ui_user/features/thread/presentation/model/search_state.da
import 'package:tmail_ui_user/features/thread/presentation/model/search_status.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';
import 'package:uuid/uuid.dart';
@@ -108,6 +109,8 @@ class MailboxController extends BaseMailboxController {
dashboardActionWorker,
routerParametersWorker;
PresentationMailbox? get selectedMailbox => mailboxDashBoardController.selectedMailbox.value;
MailboxController(
this._getAllMailboxInteractor,
this._refreshAllMailboxInteractor,
@@ -154,12 +157,9 @@ class MailboxController extends BaseMailboxController {
if (success is GetAllMailboxSuccess) {
_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);
_setUpMapMailbox(success.mailboxList, defaultMailboxTree.value, folderMailboxTree.value);
}
});
}
@@ -167,32 +167,34 @@ class MailboxController extends BaseMailboxController {
@override
void onDone() {
viewState.value.fold(
(failure) {
if (failure is CreateNewMailboxFailure) {
_createNewMailboxFailure(failure);
} else if (failure is SearchMailboxFailure) {
_searchMailboxFailure(failure);
} else if (failure is DeleteMultipleMailboxFailure) {
_deleteMailboxFailure(failure);
}
},
(success) {
if (success is CreateNewMailboxSuccess) {
_createNewMailboxSuccess(success);
} else if (success is SearchMailboxSuccess) {
_searchMailboxSuccess(success);
} else if (success is DeleteMultipleMailboxAllSuccess) {
_deleteMultipleMailboxSuccess(success.listMailboxIdDeleted, success.currentMailboxState);
} else if (success is DeleteMultipleMailboxHasSomeSuccess) {
_deleteMultipleMailboxSuccess(success.listMailboxIdDeleted, success.currentMailboxState);
} else if ((success is GetAllMailboxSuccess || success is RefreshChangesAllMailboxSuccess) && isSearchActive()) {
_searchMailboxAction(allMailboxes, searchQuery.value);
} else if (success is RenameMailboxSuccess) {
refreshMailboxChanges(currentMailboxState: success.currentMailboxState);
} else if (success is MoveMailboxSuccess) {
_moveMailboxSuccess(success);
}
(failure) {
if (failure is CreateNewMailboxFailure) {
_createNewMailboxFailure(failure);
} else if (failure is SearchMailboxFailure) {
_searchMailboxFailure(failure);
} else if (failure is DeleteMultipleMailboxFailure) {
_deleteMailboxFailure(failure);
}
},
(success) async {
if (success is GetAllMailboxSuccess || success is RefreshChangesAllMailboxSuccess) {
_initialMailboxVariableStorage();
} else if (success is CreateNewMailboxSuccess) {
_createNewMailboxSuccess(success);
} else if (success is SearchMailboxSuccess) {
_searchMailboxSuccess(success);
} else if (success is DeleteMultipleMailboxAllSuccess) {
_deleteMultipleMailboxSuccess(success.listMailboxIdDeleted, success.currentMailboxState);
} else if (success is DeleteMultipleMailboxHasSomeSuccess) {
_deleteMultipleMailboxSuccess(success.listMailboxIdDeleted, success.currentMailboxState);
} else if ((success is GetAllMailboxSuccess || success is RefreshChangesAllMailboxSuccess) && isSearchActive()) {
_searchMailboxAction(allMailboxes, searchQuery.value);
} else if (success is RenameMailboxSuccess) {
refreshMailboxChanges(currentMailboxState: success.currentMailboxState);
} else if (success is MoveMailboxSuccess) {
_moveMailboxSuccess(success);
}
}
);
}
@@ -313,64 +315,128 @@ class MailboxController extends BaseMailboxController {
}
}
void _setUpMapMailbox(List<PresentationMailbox> allMailbox, MailboxTree defaultTree, MailboxTree folderTree) {
void _initialMailboxVariableStorage() {
_setMapMailbox();
_setOutboxMailbox();
_selectMailboxDefault();
}
void _setMapMailbox() {
final mapDefaultMailboxIdByRole = {
for (var mailboxNode
in defaultTree.root.childrenItems ?? List<MailboxNode>.empty())
for (var mailboxNode in defaultMailboxTree.value.root.childrenItems ?? List<MailboxNode>.empty())
mailboxNode.item.role!: mailboxNode.item.id
};
final mapDefaultMailbox = {
for (var mailboxNode
in defaultTree.root.childrenItems ?? List<MailboxNode>.empty())
mailboxNode.item.role!: mailboxNode.item
};
final mapMailboxById = {
for (var presentationMailbox in allMailbox)
for (var presentationMailbox in allMailboxes)
presentationMailbox.id: presentationMailbox
};
mailboxDashBoardController.setMapDefaultMailboxIdByRole(mapDefaultMailboxIdByRole);
mailboxDashBoardController.setMapMailboxById(mapMailboxById);
}
void _setOutboxMailbox() {
try {
final outboxMailboxIdByRole = mapDefaultMailboxIdByRole[PresentationMailbox.roleOutbox];
final outboxMailboxIdByRole = mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleOutbox];
if (outboxMailboxIdByRole == null) {
final outboxMailboxByName = allMailbox
final outboxMailboxByName = allMailboxes
.firstWhere((mailbox) => mailbox.name?.toLowerCase() == PresentationMailbox.lowerCaseOutboxMailboxName);
mailboxDashBoardController.setOutboxMailbox(outboxMailboxByName);
} else {
mailboxDashBoardController.setOutboxMailbox(mapMailboxById[outboxMailboxIdByRole]!);
mailboxDashBoardController.setOutboxMailbox(mailboxDashBoardController.mapMailboxById[outboxMailboxIdByRole]!);
}
} catch (e) {
logError('MailboxController::_setUpMapMailboxIdDefault: Not found outbox mailbox');
logError('MailboxController::_setOutboxMailbox: Not found outbox mailbox');
mailboxDashBoardController.setOutboxMailbox(null);
}
}
var mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
void _selectMailboxDefault() {
final mapDefaultMailbox = {
for (var mailboxNode in defaultMailboxTree.value.root.childrenItems ?? List<MailboxNode>.empty())
mailboxNode.item.role!: mailboxNode.item
};
final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
final mapMailboxById = mailboxDashBoardController.mapMailboxById;
final isSearchEmailRunning = mailboxDashBoardController.searchController.isSearchEmailRunning;
PresentationMailbox? mailboxSelected;
if (mailboxCurrent != null) {
if (mailboxCurrent.hasRole()) {
mailboxDashBoardController.setNewFirstSelectedMailbox(mapDefaultMailbox.containsKey(mailboxCurrent.role)
mailboxSelected = mapDefaultMailbox.containsKey(mailboxCurrent.role)
? mapDefaultMailbox[mailboxCurrent.role]
: mailboxCurrent);
: mailboxCurrent;
} else {
mailboxDashBoardController.setNewFirstSelectedMailbox(mapMailboxById.containsKey(mailboxCurrent.id)
mailboxSelected = mapMailboxById.containsKey(mailboxCurrent.id)
? mapMailboxById[mailboxCurrent.id]
: mailboxCurrent);
: mailboxCurrent;
}
} else {
if (!mailboxDashBoardController.searchController.isSearchEmailRunning) {
if (!isSearchEmailRunning) {
if (mapDefaultMailbox.containsKey(PresentationMailbox.roleInbox)) {
mailboxDashBoardController.setNewFirstSelectedMailbox(mapDefaultMailbox[PresentationMailbox.roleInbox]);
mailboxSelected = mapDefaultMailbox[PresentationMailbox.roleInbox];
} else {
if (allMailbox.isNotEmpty) {
mailboxDashBoardController.setNewFirstSelectedMailbox(allMailbox.first);
if (allMailboxes.isNotEmpty) {
mailboxSelected = allMailboxes.first;
}
}
}
}
if (isHasDataFromRoute) {
if (mailboxIdFromNavigationRouter != null) {
_selectMailboxFromRouter();
} else if (emailIdFromNavigationRouter != null) {
mailboxDashBoardController.dispatchAction(
SelectEmailByIdAction(
emailIdFromNavigationRouter!,
mailboxIdFromNavigationRouter,
navigationRouter!.dashboardType
)
);
} else {
mailboxDashBoardController.setSelectedMailbox(mailboxSelected);
_updateSelectedMailboxRouteOnBrowser();
}
} else {
mailboxDashBoardController.setSelectedMailbox(mailboxSelected);
_updateSelectedMailboxRouteOnBrowser();
}
}
NavigationRouter? get navigationRouter => mailboxDashBoardController.navigationRouter;
bool get isHasDataFromRoute => BuildUtils.isWeb && navigationRouter != null;
MailboxId? get mailboxIdFromNavigationRouter => navigationRouter?.mailboxId;
EmailId? get emailIdFromNavigationRouter => navigationRouter?.emailId;
void _clearNavigationRouter() {
mailboxDashBoardController.navigationRouter = null;
}
void _selectMailboxFromRouter() {
final matchedMailboxNode = findMailboxNodeById(mailboxIdFromNavigationRouter!);
if (matchedMailboxNode != null) {
mailboxDashBoardController.setSelectedMailbox(matchedMailboxNode.item);
if (emailIdFromNavigationRouter != null) {
mailboxDashBoardController.dispatchAction(
SelectEmailByIdAction(
emailIdFromNavigationRouter!,
mailboxIdFromNavigationRouter,
navigationRouter!.dashboardType
)
);
} else {
_updateSelectedMailboxRouteOnBrowser();
}
_clearNavigationRouter();
} else {
_clearNavigationRouter();
}
}
void _handleOpenMailbox(
@@ -386,6 +452,7 @@ class MailboxController extends BaseMailboxController {
_disableAllSearchEmail();
mailboxDashBoardController.setSelectedMailbox(presentationMailboxSelected);
_updateSelectedMailboxRouteOnBrowser();
if (mailboxDashBoardController.isDrawerOpen) {
mailboxDashBoardController.closeMailboxMenuDrawer();
@@ -748,7 +815,11 @@ class MailboxController extends BaseMailboxController {
void _switchBackToMailboxDefault() {
final inboxMailbox = findMailboxNodeByRole(PresentationMailbox.roleInbox);
mailboxDashBoardController.setSelectedMailbox(inboxMailbox?.item);
mailboxListScrollController.animateTo(0, duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
_updateSelectedMailboxRouteOnBrowser();
mailboxListScrollController.animateTo(
0,
duration: const Duration(milliseconds: 500),
curve: Curves.fastOutSlowIn);
}
void _deleteMailboxFailure(DeleteMultipleMailboxFailure failure) {
@@ -996,30 +1067,11 @@ 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');
log('MailboxController::_handleNavigationRouteParameters(): parameters: $parameters');
if (parameters != null) {
final navigationRouter = RouteUtils.parsingRouteParametersToNavigationRouter(parameters);
log('ThreadController::_handleNavigationRouteParameters():navigationRouter: $navigationRouter');
log('MailboxController::_handleNavigationRouteParameters():navigationRouter: $navigationRouter');
mailboxDashBoardController.navigationRouter = navigationRouter;
}
}
@@ -1053,6 +1105,20 @@ class MailboxController extends BaseMailboxController {
}
}
void _updateSelectedMailboxRouteOnBrowser() {
if (BuildUtils.isWeb) {
final selectedMailboxId = selectedMailbox?.id;
final route = RouteUtils.generateRouteBrowser(
AppRoutes.dashboard,
NavigationRouter(
mailboxId: selectedMailboxId,
dashboardType: DashboardType.normal
)
);
RouteUtils.updateRouteOnBrowser('Mailbox-${selectedMailboxId?.id.value}', route);
}
}
void closeMailboxScreen(BuildContext context) {
_cancelSelectMailbox();
mailboxDashBoardController.closeMailboxMenuDrawer();
@@ -1,10 +1,12 @@
import 'package:flutter/cupertino.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.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';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/main/routes/navigation_router.dart';
class DashBoardAction extends UIAction {
static final idle = DashBoardAction();
@@ -115,9 +117,11 @@ class SelectMailboxDefaultAction extends DashBoardAction {
class SelectEmailByIdAction extends DashBoardAction {
final EmailId emailId;
final MailboxId? mailboxId;
final DashboardType dashboardType;
SelectEmailByIdAction(this.emailId);
SelectEmailByIdAction(this.emailId, this.mailboxId, this.dashboardType);
@override
List<Object?> get props => [emailId];
List<Object?> get props => [emailId, mailboxId, dashboardType];
}
@@ -326,7 +326,7 @@ class MailboxDashBoardController extends ReloadableController {
void _getSessionCurrent() {
final arguments = Get.arguments;
log('MailboxDashBoardController::_setSessionCurrent(): arguments = $arguments');
log('MailboxDashBoardController::_getSessionCurrent(): arguments = $arguments');
if (arguments is Session) {
sessionCurrent = arguments;
accountId.value = sessionCurrent?.accounts.keys.first;
@@ -381,12 +381,13 @@ class MailboxDashBoardController extends ReloadableController {
}
void setSelectedMailbox(PresentationMailbox? newPresentationMailbox) {
selectedMailbox.value = newPresentationMailbox;
}
void setNewFirstSelectedMailbox(PresentationMailbox? newPresentationMailbox) {
selectedMailbox.firstRebuild = true;
selectedMailbox.value = newPresentationMailbox;
final previousMailbox = selectedMailbox.value;
if (previousMailbox == newPresentationMailbox) {
selectedMailbox.value = newPresentationMailbox;
selectedMailbox.refresh();
} else {
selectedMailbox.value = newPresentationMailbox;
}
}
void setSelectedEmail(PresentationEmail? newPresentationEmail) {
@@ -885,7 +886,7 @@ class MailboxDashBoardController extends ReloadableController {
Function? onCancelSelectionEmail,
}
) {
if (_responsiveUtils.isMobile(context)) {
if (_responsiveUtils.isScreenWithShortestSide(context)) {
(ConfirmationDialogActionSheetBuilder(context)
..messageText(actionType.getContentDialog(
context,
@@ -1020,6 +1021,8 @@ class MailboxDashBoardController extends ReloadableController {
@override
void handleReloaded(Session session) {
log('MailboxDashBoardController::handleReloaded():');
_getRouteParameters();
sessionCurrent = session;
accountId.value = sessionCurrent?.accounts.keys.first;
_getUserProfile();
@@ -1028,7 +1031,6 @@ class MailboxDashBoardController extends ReloadableController {
injectRuleFilterBindings(sessionCurrent, accountId.value);
injectVacationBindings(sessionCurrent, accountId.value);
_getVacationResponse();
_getRouteParameters();
}
void _getRouteParameters() {
@@ -227,7 +227,7 @@ class ManageAccountDashBoardController extends ReloadableController {
} else {
log('ManageAccountDashBoardController::backToMailboxDashBoard(): canBack: FALSE');
pushAndPopAll(
RouteUtils.generateRoutePathMobile(AppRoutes.dashboard, NavigationRouter()),
RouteUtils.generateRouteMobile(AppRoutes.dashboard, NavigationRouter()),
arguments: sessionCurrent);
}
}
@@ -53,7 +53,9 @@ import 'package:tmail_ui_user/features/thread/domain/usecases/search_more_email_
import 'package:tmail_ui_user/features/thread/presentation/mixin/email_action_controller.dart';
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/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 {
@@ -727,6 +729,22 @@ class SearchEmailController extends BaseController
}
}
PresentationEmail generateEmailByPlatform(PresentationEmail currentEmail) {
if (BuildUtils.isWeb) {
final route = RouteUtils.generateRouteBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: currentEmail.id,
dashboardType: DashboardType.search
)
);
final emailOnWeb = currentEmail.withRouteWeb(route);
return emailOnWeb;
} else {
return currentEmail;
}
}
@override
void onClose() {
textInputSearchController.dispose();
@@ -420,31 +420,33 @@ class SearchEmailView extends GetWidget<SearchEmailController>
key: const PageStorageKey('list_presentation_email_in_search_view'),
itemExtent: _getItemExtent(context),
itemCount: listPresentationEmail.length,
itemBuilder: (context, index) => Obx(() => (EmailTileBuilder(
context,
listPresentationEmail[index],
controller.selectionMode.value,
controller.searchQuery,
controller.mailboxDashBoardController.selectedEmail.value?.id == listPresentationEmail[index].id,
isSearchEmailRunning: true,
padding: SearchEmailUtils.getPaddingSearchResultList(context, _responsiveUtils),
paddingDivider: SearchEmailUtils.getPaddingDividerSearchResultList(context, _responsiveUtils),
mailboxCurrent: listPresentationEmail[index].findMailboxContain(
controller.mailboxDashBoardController.mapMailboxById))
..addOnPressEmailActionClick((action, email) =>
controller.pressEmailAction(
context,
action,
email,
mailboxContain: email.findMailboxContain(
controller.mailboxDashBoardController.mapMailboxById)))
..addOnMoreActionClick((email, position) => _responsiveUtils.isMobile(context)
? controller.openContextMenuAction(context, _contextMenuActionTile(context, email))
: controller.openPopupMenuAction(context, position, _popupMenuActionTile(context, email))))
.build()))
itemBuilder: (context, index) {
final mailboxContain = _getMailboxContain(listPresentationEmail[index]);
final newPresentationEmail = controller.generateEmailByPlatform(listPresentationEmail[index]);
return Obx(() => (EmailTileBuilder(
context,
newPresentationEmail,
controller.selectionMode.value,
controller.searchQuery,
controller.mailboxDashBoardController.selectedEmail.value?.id == newPresentationEmail.id,
isSearchEmailRunning: true,
padding: SearchEmailUtils.getPaddingSearchResultList(context, _responsiveUtils),
paddingDivider: SearchEmailUtils.getPaddingDividerSearchResultList(context, _responsiveUtils),
mailboxContain: mailboxContain)
..addOnPressEmailActionClick((action, email) =>
controller.pressEmailAction(context, action, email, mailboxContain: mailboxContain))
..addOnMoreActionClick((email, position) => _responsiveUtils.isScreenWithShortestSide(context)
? controller.openContextMenuAction(context, _contextMenuActionTile(context, email))
: controller.openPopupMenuAction(context, position, _popupMenuActionTile(context, email)))
).build());
})
);
}
PresentationMailbox? _getMailboxContain(PresentationEmail currentEmail) {
return currentEmail.findMailboxContain(controller.mailboxDashBoardController.mapMailboxById);
}
double? _getItemExtent(BuildContext context) {
if (BuildUtils.isWeb) {
return _responsiveUtils.isDesktop(context) ? 52 : 95;
@@ -470,7 +472,7 @@ class SearchEmailView extends GetWidget<SearchEmailController>
}
Widget _markAsEmailSpamOrUnSpamAction(BuildContext context, PresentationEmail email) {
final mailboxContain = email.findMailboxContain(controller.mailboxDashBoardController.mapMailboxById);
final mailboxContain = _getMailboxContain(email);
return (EmailActionCupertinoActionSheetActionBuilder(
const Key('mark_as_spam_or_un_spam_action'),
@@ -58,7 +58,7 @@ class SessionController extends ReloadableController {
@override
void handleReloaded(Session session) {
pushAndPop(
RouteUtils.generateRoutePathMobile(AppRoutes.dashboard, NavigationRouter()),
RouteUtils.generateRouteMobile(AppRoutes.dashboard, NavigationRouter()),
arguments: session);
}
@@ -108,7 +108,7 @@ class SessionController extends ReloadableController {
if (apiUrl.isNotEmpty) {
_dynamicUrlInterceptors.changeBaseUrl(apiUrl);
pushAndPop(
RouteUtils.generateRoutePathMobile(AppRoutes.dashboard, NavigationRouter()),
RouteUtils.generateRouteMobile(AppRoutes.dashboard, NavigationRouter()),
arguments: success.session);
} else {
_goToLogin();
@@ -1,16 +1,20 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:model/model.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/email/presentation_email.dart';
import 'package:tmail_ui_user/main/routes/navigation_router.dart';
class GetEmailByIdLoading extends LoadingState {}
class GetEmailByIdSuccess extends UIState {
final PresentationEmail email;
final MailboxId? mailboxId;
final DashboardType dashboardType;
GetEmailByIdSuccess(this.email);
GetEmailByIdSuccess(this.email, this.mailboxId, this.dashboardType);
@override
List<Object?> get props => [email];
List<Object?> get props => [email, mailboxId, dashboardType];
}
class GetEmailByIdFailure extends FeatureFailure {
@@ -4,8 +4,10 @@ import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.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/thread/domain/repository/thread_repository.dart';
import 'package:tmail_ui_user/features/thread/domain/state/get_email_by_id_state.dart';
import 'package:tmail_ui_user/main/routes/navigation_router.dart';
class GetEmailByIdInteractor {
final ThreadRepository _threadRepository;
@@ -16,13 +18,15 @@ class GetEmailByIdInteractor {
AccountId accountId,
EmailId emailId,
{
MailboxId? mailboxId,
DashboardType dashboardType = DashboardType.normal,
Properties? properties,
}
) async* {
try {
yield Right<Failure, Success>(GetEmailByIdLoading());
final email = await _threadRepository.getEmailById(accountId, emailId, properties: properties);
yield Right<Failure, Success>(GetEmailByIdSuccess(email));
yield Right<Failure, Success>(GetEmailByIdSuccess(email, mailboxId, dashboardType));
} catch (e) {
yield Left<Failure, Success>(GetEmailByIdFailure(e));
}
@@ -28,6 +28,7 @@ import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_t
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';
mixin EmailActionController on ViewAsDialogActionMixin {
@@ -47,6 +48,11 @@ mixin EmailActionController on ViewAsDialogActionMixin {
void previewEmail(BuildContext context, PresentationEmail presentationEmail) {
mailboxDashBoardController.setSelectedEmail(presentationEmail);
mailboxDashBoardController.dispatchRoute(DashboardRoutes.emailDetailed);
if (BuildUtils.isWeb && presentationEmail.routeWeb != null) {
RouteUtils.updateRouteOnBrowser(
'Email-${presentationEmail.id.id.value}',
presentationEmail.routeWeb!);
}
}
void moveToTrash(PresentationEmail email) async {
@@ -3,10 +3,10 @@ import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/presentation/utils/app_toast.dart';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/build_utils.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
@@ -85,6 +85,8 @@ class ThreadController extends BaseController with EmailActionController {
final listEmailDrag = <PresentationEmail>[].obs;
bool _rangeSelectionMode = false;
final openingEmail = RxBool(false);
bool canLoadMore = true;
bool canSearchMore = true;
bool _isLoadingMore = false;
@@ -153,6 +155,8 @@ class ThreadController extends BaseController with EmailActionController {
emailList.clear();
} else if (failure is SearchMoreEmailFailure || failure is LoadMoreEmailsFailure) {
_isLoadingMore = false;
} else if (failure is GetEmailByIdFailure) {
openingEmail.value = false;
}
},
(success) {
@@ -168,26 +172,11 @@ class ThreadController extends BaseController with EmailActionController {
_searchMoreEmailsSuccess(success);
} else if (success is SearchingMoreState || success is LoadingMoreState) {
_isLoadingMore = true;
} else if (success is GetEmailByIdLoading) {
openingEmail.value = true;
} else if (success is GetEmailByIdSuccess) {
if (currentContext != null) {
final mailboxContain = success.email
.findMailboxContain(mailboxDashBoardController.mapMailboxById);
final route = RouteUtils.generateRouteBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: success.email.id,
mailboxId: mailboxContain?.id,
dashboardType: searchController.isSearchEmailRunning
? DashboardType.search
: DashboardType.normal
)
);
pressEmailAction(
currentContext!,
EmailActionType.preview,
success.email.withRouteWeb(route),
mailboxContain: mailboxContain);
}
openingEmail.value = false;
_openEmailDetailView(success.email, success.mailboxId, success.dashboardType);
}
}
);
@@ -246,23 +235,14 @@ class ThreadController extends BaseController with EmailActionController {
pressEmailSelectionAction(action.context, action.emailAction, action.listEmailSelected);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is OpenEmailDetailedFromSuggestionQuickSearchAction) {
final mailboxContain = action.presentationEmail
.findMailboxContain(mailboxDashBoardController.mapMailboxById);
final route = RouteUtils.generateRouteBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: action.presentationEmail.id,
mailboxId: mailboxContain?.id,
dashboardType: searchController.isSearchEmailRunning
? DashboardType.search
: DashboardType.normal
)
);
final mailboxContain = action.presentationEmail.findMailboxContain(mailboxDashBoardController.mapMailboxById);
final newEmail = generateEmailByPlatform(action.presentationEmail);
pressEmailAction(
action.context,
EmailActionType.preview,
action.presentationEmail.withRouteWeb(route),
mailboxContain: mailboxContain);
action.context,
EmailActionType.preview,
newEmail,
mailboxContain: mailboxContain
);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is StartSearchEmailAction) {
cancelSelectEmail();
@@ -272,7 +252,7 @@ class ThreadController extends BaseController with EmailActionController {
deleteSelectionEmailsPermanently(action.context, DeleteActionType.all);
mailboxDashBoardController.clearDashBoardAction();
} else if (action is SelectEmailByIdAction) {
_openEmailDetailedView(action.emailId);
_getEmailByIdAction(action.emailId, action.mailboxId, action.dashboardType);
mailboxDashBoardController.clearDashBoardAction();
}
});
@@ -503,11 +483,6 @@ class ThreadController extends BaseController with EmailActionController {
: SelectMode.INACTIVE;
}
void previewEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
mailboxDashBoardController.setSelectedEmail(presentationEmailSelected);
mailboxDashBoardController.dispatchRoute(DashboardRoutes.emailDetailed);
}
Tuple2<StartRangeSelection,EndRangeSelection> _getSelectionEmailsRange(PresentationEmail presentationEmailSelected) {
final emailSelectedIndex = emailList.indexWhere((e) => e.id == presentationEmailSelected.id);
final latestEmailSelectedOrUnselectedIndex = emailList.indexWhere((e) => e.id == latestEmailSelectedOrUnselected.value?.id);
@@ -833,12 +808,57 @@ class ThreadController extends BaseController with EmailActionController {
: KeyEventResult.ignored;
}
void _openEmailDetailedView(EmailId emailId) {
PresentationEmail generateEmailByPlatform(PresentationEmail currentEmail) {
if (BuildUtils.isWeb) {
final route = RouteUtils.generateRouteBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: currentEmail.id,
mailboxId: currentMailbox?.id,
dashboardType: searchController.isSearchEmailRunning
? DashboardType.search
: DashboardType.normal
)
);
final emailOnWeb = currentEmail.withRouteWeb(route);
return emailOnWeb;
} else {
return currentEmail;
}
}
void _getEmailByIdAction(EmailId emailId, MailboxId? mailboxId, DashboardType dashboardType) {
if (_accountId != null) {
consumeState(_getEmailByIdInteractor.execute(
_accountId!,
emailId,
mailboxId: mailboxId,
dashboardType: dashboardType,
properties: ThreadConstants.propertiesDefault));
}
}
void _openEmailDetailView(
PresentationEmail email,
MailboxId? mailboxId,
DashboardType dashboardType
) {
if (currentContext != null) {
final mailboxContain = email.findMailboxContain(mailboxDashBoardController.mapMailboxById);
final route = RouteUtils.generateRouteBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: email.id,
mailboxId: mailboxId,
dashboardType: dashboardType
)
);
pressEmailAction(
currentContext!,
EmailActionType.preview,
email.withRouteWeb(route),
mailboxContain: mailboxContain
);
}
}
}
@@ -251,7 +251,7 @@ class ThreadView extends GetWidget<ThreadController> with AppLoaderMixin,
? Padding(padding: const EdgeInsets.symmetric(vertical: 16), child: loadingWidget)
: const SizedBox.shrink();
} else {
return success is LoadingState
return success is LoadingState || controller.openingEmail.isTrue
? Padding(padding: const EdgeInsets.symmetric(vertical: 16), child: loadingWidget)
: const SizedBox.shrink();
}
@@ -283,7 +283,9 @@ class ThreadView extends GetWidget<ThreadController> with AppLoaderMixin,
padding: EdgeInsets.zero,
color: Colors.white,
child: Obx(() {
return _buildResultListEmail(context, controller.emailList);
return Visibility(
visible: controller.openingEmail.isFalse,
child: _buildResultListEmail(context, controller.emailList));
})
);
}
@@ -333,48 +335,39 @@ class ThreadView extends GetWidget<ThreadController> with AppLoaderMixin,
itemExtent: _getItemExtent(context),
itemCount: listPresentationEmail.length,
itemBuilder: (context, index) {
final mailboxContain = _getMailboxContain(listPresentationEmail[index]);
final newPresentationEmail = controller.generateEmailByPlatform(listPresentationEmail[index]);
return Obx(() => Draggable<List<PresentationEmail>>(
maxSimultaneousDrags: kIsWeb ? null : 0,
data: controller.listEmailDrag,
child: (EmailTileBuilder(
context,
listPresentationEmail[index],
controller.mailboxDashBoardController.currentSelectMode.value,
controller.searchQuery,
controller.mailboxDashBoardController.selectedEmail.value?.id == listPresentationEmail[index].id,
mailboxCurrent: controller.searchController.isSearchEmailRunning
? listPresentationEmail[index].findMailboxContain(controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox,
isSearchEmailRunning: controller.searchController.isSearchEmailRunning)
..addOnPressEmailActionClick((action, email) =>
controller.pressEmailAction(
context,
action,
email,
mailboxContain: controller.searchController.isSearchEmailRunning
? email.findMailboxContain(controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox))
..addOnMoreActionClick((email, position) => _responsiveUtils.isMobile(context)
? controller.openContextMenuAction(context, _contextMenuActionTile(context, email))
: controller.openPopupMenuAction(context, position, _popupMenuActionTile(context, email)))
newPresentationEmail,
controller.mailboxDashBoardController.currentSelectMode.value,
controller.searchQuery,
controller.mailboxDashBoardController.selectedEmail.value?.id == newPresentationEmail.id,
mailboxContain: mailboxContain,
isSearchEmailRunning: controller.searchController.isSearchEmailRunning)
..addOnPressEmailActionClick((action, email) =>
controller.pressEmailAction(context, action, email, mailboxContain: mailboxContain))
..addOnMoreActionClick((email, position) => _responsiveUtils.isScreenWithShortestSide(context)
? controller.openContextMenuAction(context, _contextMenuActionTile(context, email))
: controller.openPopupMenuAction(context, position, _popupMenuActionTile(context, email)))
).build(),
feedback: _buildFeedBackWidget(context),
childWhenDragging: (EmailTileBuilder(
context,
listPresentationEmail[index],
newPresentationEmail,
controller.mailboxDashBoardController.currentSelectMode.value,
controller.searchQuery,
controller.mailboxDashBoardController.selectedEmail.value?.id == listPresentationEmail[index].id,
mailboxCurrent: controller.searchController.isSearchEmailRunning
? listPresentationEmail[index].findMailboxContain(
controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox,
controller.mailboxDashBoardController.selectedEmail.value?.id == newPresentationEmail.id,
mailboxContain: mailboxContain,
isSearchEmailRunning: controller.searchController.isSearchEmailRunning,
isDrag: true)
).build(),
dragAnchorStrategy: pointerDragAnchorStrategy,
onDragStarted: () {
controller.calculateDragValue(listPresentationEmail[index]);
controller.calculateDragValue(newPresentationEmail);
},
));
}),
@@ -382,6 +375,12 @@ class ThreadView extends GetWidget<ThreadController> with AppLoaderMixin,
);
}
PresentationMailbox? _getMailboxContain(PresentationEmail currentEmail) {
return controller.searchController.isSearchEmailRunning
? currentEmail.findMailboxContain(controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox;
}
Widget _buildFeedBackWidget(BuildContext context) {
return SizedBox(
height: 60,
@@ -509,9 +508,7 @@ class ThreadView extends GetWidget<ThreadController> with AppLoaderMixin,
}
Widget _markAsEmailSpamOrUnSpamAction(BuildContext context, PresentationEmail email) {
final mailboxContain = controller.searchController.isSearchEmailRunning
? email.findMailboxContain(controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox;
final mailboxContain = _getMailboxContain(email);
return (EmailActionCupertinoActionSheetActionBuilder(
const Key('mark_as_spam_or_un_spam_action'),
SvgPicture.asset(
@@ -13,7 +13,7 @@ class EmailTileBuilder with BaseEmailItemTile {
final PresentationEmail _presentationEmail;
final BuildContext _context;
final SelectMode _selectModeAll;
final PresentationMailbox? mailboxCurrent;
final PresentationMailbox? mailboxContain;
final SearchQuery? _searchQuery;
final bool isSearchEmailRunning;
final EdgeInsets? padding;
@@ -31,7 +31,7 @@ class EmailTileBuilder with BaseEmailItemTile {
this._isShowingEmailContent,
{
this.isSearchEmailRunning = false,
this.mailboxCurrent,
this.mailboxContain,
this.padding,
this.paddingDivider,
this.isDrag = false,
@@ -83,7 +83,7 @@ class EmailTileBuilder with BaseEmailItemTile {
fit: BoxFit.fill)),
Expanded(child: buildInformationSender(
_presentationEmail,
mailboxCurrent,
mailboxContain,
isSearchEmailRunning,
_searchQuery)),
if (_presentationEmail.hasAttachment == true)
@@ -11,9 +11,6 @@ import 'package:model/mailbox/select_mode.dart';
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/navigation_router.dart';
import 'package:tmail_ui_user/main/routes/route_utils.dart';
import 'package:url_launcher/link.dart';
class EmailTileBuilder with BaseEmailItemTile {
@@ -21,7 +18,7 @@ class EmailTileBuilder with BaseEmailItemTile {
final PresentationEmail _presentationEmail;
final BuildContext _context;
final SelectMode _selectModeAll;
final PresentationMailbox? mailboxCurrent;
final PresentationMailbox? mailboxContain;
final SearchQuery? _searchQuery;
final bool isSearchEmailRunning;
final EdgeInsets? padding;
@@ -43,7 +40,7 @@ class EmailTileBuilder with BaseEmailItemTile {
this._isShowingEmailContent,
{
this.isSearchEmailRunning = false,
this.mailboxCurrent,
this.mailboxContain,
this.padding,
this.paddingDivider,
this.isDrag = false,
@@ -80,56 +77,43 @@ class EmailTileBuilder with BaseEmailItemTile {
}
Widget _wrapContainerForTile(Widget tile) {
return Container(
margin: _getMarginItem(),
padding: _getPaddingItem(),
decoration: _getDecorationItem(),
alignment: Alignment.center,
child: Link(
uri: _presentationEmail.routeWeb,
builder: (_, __) => tile
)
);
}
EdgeInsets _getMarginItem() {
if (responsiveUtils.isDesktop(_context)) {
return Container(
margin: const EdgeInsets.only(top: 3),
padding: const EdgeInsets.symmetric(vertical: 8),
decoration: (_selectModeAll == SelectMode.ACTIVE &&
_presentationEmail.selectMode == SelectMode.ACTIVE) || isDrag || _isShowingEmailContent
? BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColor.colorItemEmailSelectedDesktop)
: null,
child: Link(
uri: RouteUtils.generateRoutePathBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: _presentationEmail.id,
mailboxId: mailboxCurrent?.id,
dashboardType: isSearchEmailRunning
? DashboardType.search
: DashboardType.normal
)
),
builder: (_, __) => tile
)
);
return const EdgeInsets.only(top: 3);
} else {
return Container(
margin: const EdgeInsets.only(top: 3, left: 16, right: 16),
padding: const EdgeInsets.only(bottom: 8, right: 8, top: 8),
decoration: (_selectModeAll == SelectMode.ACTIVE &&
_presentationEmail.selectMode == SelectMode.ACTIVE) || isDrag || _isShowingEmailContent
? BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColor.colorItemEmailSelectedDesktop)
: BoxDecoration(
borderRadius: BorderRadius.circular(0),
color: Colors.white),
alignment: Alignment.center,
child: Link(
uri: RouteUtils.generateRoutePathBrowser(
AppRoutes.dashboard,
NavigationRouter(
emailId: _presentationEmail.id,
mailboxId: mailboxCurrent?.id,
dashboardType: isSearchEmailRunning
? DashboardType.search
: DashboardType.normal
)
),
builder: (_, __) => tile
));
return const EdgeInsets.only(top: 3, left: 16, right: 16);
}
}
EdgeInsets _getPaddingItem() {
if (responsiveUtils.isDesktop(_context)) {
return const EdgeInsets.symmetric(vertical: 8);
} else {
return const EdgeInsets.only(bottom: 8, right: 8, top: 8);
}
}
BoxDecoration _getDecorationItem() {
if ((_selectModeAll == SelectMode.ACTIVE && _presentationEmail.selectMode == SelectMode.ACTIVE) || isDrag || _isShowingEmailContent) {
return BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: AppColor.colorItemEmailSelectedDesktop);
} else {
return BoxDecoration(
borderRadius: BorderRadius.circular(0),
color: Colors.white);
}
}
@@ -168,7 +152,7 @@ class EmailTileBuilder with BaseEmailItemTile {
fit: BoxFit.fill)),
Expanded(child: buildInformationSender(
_presentationEmail,
mailboxCurrent,
mailboxContain,
isSearchEmailRunning,
_searchQuery
)),
@@ -264,7 +248,7 @@ class EmailTileBuilder with BaseEmailItemTile {
fit: BoxFit.fill)),
Expanded(child: buildInformationSender(
_presentationEmail,
mailboxCurrent,
mailboxContain,
isSearchEmailRunning,
_searchQuery
)),
@@ -385,7 +369,7 @@ class EmailTileBuilder with BaseEmailItemTile {
width: 160,
child: buildInformationSender(
_presentationEmail,
mailboxCurrent,
mailboxContain,
isSearchEmailRunning,
_searchQuery
)),
@@ -437,7 +421,7 @@ class EmailTileBuilder with BaseEmailItemTile {
: EmailActionType.markAsRead,
_presentationEmail)),
const SizedBox(width: 5),
if (mailboxCurrent?.isDrafts == false)
if (mailboxContain?.isDrafts == false)
... [
buildIconWeb(
minSize: 18,
@@ -476,7 +460,7 @@ class EmailTileBuilder with BaseEmailItemTile {
: EmailActionType.moveToTrash,
_presentationEmail)),
const SizedBox(width: 5),
if (mailboxCurrent?.isDrafts == false)
if (mailboxContain?.isDrafts == false)
buildIconWebHasPosition(
_context,
icon: SvgPicture.asset(
@@ -501,7 +485,7 @@ class EmailTileBuilder with BaseEmailItemTile {
}
bool get canDeletePermanently {
return mailboxCurrent?.isTrash == true || mailboxCurrent?.isDrafts == true;
return mailboxContain?.isTrash == true || mailboxContain?.isDrafts == true;
}
Widget _buildDateTimeForDesktopScreen() {
+13 -3
View File
@@ -1,17 +1,21 @@
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';
import 'package:universal_html/html.dart' as html;
class RouteUtils {
abstract class RouteUtils {
static String get baseOriginUrl => Uri.base.origin;
static String generateRoutePathMobile(String route, NavigationRouter router) {
static String get baseUrl => Uri.base.path;
static String generateRouteMobile(String route, NavigationRouter router) {
ServicePath servicePath = ServicePath(route);
if (router.emailId != null) {
servicePath = servicePath.withPathParameter(router.emailId!.id.value);
@@ -25,7 +29,7 @@ class RouteUtils {
return servicePath.path;
}
static Uri generateRoutePathBrowser(String route, NavigationRouter router) {
static Uri generateRouteBrowser(String route, NavigationRouter router) {
final baseRoutePath = '$baseOriginUrl/#$route';
ServicePath servicePath = ServicePath(baseRoutePath);
if (router.emailId != null) {
@@ -57,4 +61,10 @@ class RouteUtils {
dashboardType: dashboardType,
);
}
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());
}
}
+12 -3
View File
@@ -1,5 +1,5 @@
import 'package:core/core.dart';
import 'package:core/presentation/extensions/string_extension.dart';
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
@@ -7,7 +7,8 @@ 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/keyword_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart';
import 'package:model/extensions/email_address_extension.dart';
import 'package:model/mailbox/select_mode.dart';
class PresentationEmail with EquatableMixin {
@@ -27,6 +28,7 @@ class PresentationEmail with EquatableMixin {
final Map<MailboxId, bool>? mailboxIds;
final List<MailboxName?>? mailboxNames;
final SelectMode selectMode;
final Uri? routeWeb;
PresentationEmail(
this.id,
@@ -46,6 +48,7 @@ class PresentationEmail with EquatableMixin {
this.mailboxIds,
this.mailboxNames,
this.selectMode = SelectMode.INACTIVE,
this.routeWeb
}
);
@@ -72,6 +75,8 @@ class PresentationEmail with EquatableMixin {
String get mailboxName => mailboxNames?.first?.name ?? '';
String get routeWebAsString => routeWeb.toString();
@override
List<Object?> get props => [
id,
@@ -86,6 +91,10 @@ class PresentationEmail with EquatableMixin {
sentAt,
replyTo,
preview,
hasAttachment
hasAttachment,
mailboxIds,
mailboxNames,
selectMode,
routeWeb
];
}
@@ -1,11 +1,18 @@
import 'dart:ui';
import 'package:core/core.dart';
import 'package:core/domain/extensions/datetime_extension.dart';
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart';
import 'package:model/email/email_action_type.dart';
import 'package:model/email/presentation_email.dart';
import 'package:model/extensions/email_address_extension.dart';
import 'package:model/extensions/list_email_address_extension.dart';
import 'package:model/extensions/utc_date_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:model/mailbox/select_mode.dart';
extension PresentationEmailExtension on PresentationEmail {
@@ -43,6 +50,7 @@ extension PresentationEmailExtension on PresentationEmail {
mailboxIds: mailboxIds,
mailboxNames: mailboxNames,
selectMode: selectMode == SelectMode.INACTIVE ? SelectMode.ACTIVE : SelectMode.INACTIVE,
routeWeb: routeWeb
);
}
@@ -64,6 +72,7 @@ extension PresentationEmailExtension on PresentationEmail {
mailboxIds: mailboxIds,
mailboxNames: mailboxNames,
selectMode: selectMode,
routeWeb: routeWeb
);
}
@@ -111,7 +120,7 @@ extension PresentationEmailExtension on PresentationEmail {
case EmailActionType.edit:
return Tuple3(to.asList(), cc.asList(), bcc.asList());
default:
return Tuple3([], [], []);
return const Tuple3([], [], []);
}
}
@@ -145,6 +154,7 @@ extension PresentationEmailExtension on PresentationEmail {
mailboxIds: mailboxIds,
mailboxNames: listMailboxName,
selectMode: selectMode,
routeWeb: routeWeb
);
}
@@ -160,4 +170,26 @@ extension PresentationEmailExtension on PresentationEmail {
}
return null;
}
PresentationEmail withRouteWeb(Uri routeWeb) {
return PresentationEmail(
this.id,
keywords: keywords,
size: size,
receivedAt: receivedAt,
hasAttachment: hasAttachment,
preview: preview,
subject: subject,
sentAt: sentAt,
from: from,
to: to,
cc: cc,
bcc: bcc,
replyTo: replyTo,
mailboxIds: mailboxIds,
mailboxNames: mailboxNames,
selectMode: selectMode,
routeWeb: routeWeb
);
}
}