TF-3758 Update mailbox view on mobile web responsive
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -413,20 +413,15 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
contentPadding: 0,
|
||||
useDefaultFont: true,
|
||||
),
|
||||
if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive)
|
||||
if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive ||
|
||||
controller.mailboxDashBoardController.isLocalFileDraggableAppActive ||
|
||||
controller.mailboxDashBoardController.isAppGridDialogDisplayed.isTrue)
|
||||
PointerInterceptor(
|
||||
child: SizedBox(
|
||||
width: constraints.maxWidth,
|
||||
height: constraints.maxHeight,
|
||||
)
|
||||
),
|
||||
if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive)
|
||||
PointerInterceptor(
|
||||
child: SizedBox(
|
||||
width: constraints.maxWidth,
|
||||
height: constraints.maxHeight,
|
||||
)
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'package:jmap_dart_client/jmap/core/capability/capability_properties.dart
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
|
||||
import 'package:model/download_all/download_all_capability.dart';
|
||||
import 'package:model/mailbox/mailbox_constants.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/home/data/model/session_hive_obj.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/converter/session_account_converter.dart';
|
||||
@@ -115,4 +116,27 @@ extension SessionExtensions on Session {
|
||||
linagoraDownloadAllCapability,
|
||||
);
|
||||
}
|
||||
|
||||
bool isSubAddressingSupported(AccountId? accountId) {
|
||||
try {
|
||||
if (accountId == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CapabilityIdentifier.jmapTeamMailboxes.isSupported(this, accountId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final capability = getCapabilityProperties(
|
||||
accountId,
|
||||
CapabilityIdentifier.jmapTeamMailboxes,
|
||||
);
|
||||
|
||||
final props = capability?.props[0] as Map<String, dynamic>?;
|
||||
return props?[subaddressingSupported] ?? false;
|
||||
} catch (e) {
|
||||
logError('SessionExtensions::isSubAddressingSupported:Exception = $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,31 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/presentation/views/list/tree_view.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/mailbox/expand_mode.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/handle_mailbox_action_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/open_app_grid_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/toggle_expand_folders_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mixin/mailbox_widget_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_item_widget_styles.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folder_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folders_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_app_bar.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_category_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_item_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_loading_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/sending_queue_mailbox_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_routes.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
abstract class BaseMailboxView extends GetWidget<MailboxController>
|
||||
with
|
||||
AppLoaderMixin,
|
||||
MailboxWidgetMixin {
|
||||
with AppLoaderMixin {
|
||||
|
||||
BaseMailboxView({Key? key}) : super(key: key);
|
||||
|
||||
@@ -44,4 +59,327 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildFolders(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Obx(() {
|
||||
if (controller.personalMailboxIsNotEmpty) {
|
||||
return buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.personalFolders,
|
||||
controller.personalRootNode,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.teamMailboxesIsNotEmpty) {
|
||||
return buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.teamMailboxes,
|
||||
controller.teamMailboxesRootNode,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildMailboxCategory(
|
||||
BuildContext context,
|
||||
MailboxCategories categories,
|
||||
MailboxNode mailboxNode,
|
||||
) {
|
||||
final isDesktop = controller.responsiveUtils.isDesktop(context);
|
||||
|
||||
switch (categories) {
|
||||
case MailboxCategories.exchange:
|
||||
return _buildBodyMailboxCategory(
|
||||
context: context,
|
||||
categories: categories,
|
||||
mailboxNode: mailboxNode,
|
||||
padding: isDesktop ? null : const EdgeInsets.symmetric(horizontal: 12),
|
||||
);
|
||||
default:
|
||||
return Column(
|
||||
children: [
|
||||
Obx(() => MailboxCategoryWidget(
|
||||
categories: categories,
|
||||
expandMode: categories.getExpandMode(
|
||||
controller.mailboxCategoriesExpandMode.value,
|
||||
),
|
||||
onToggleMailboxCategories: (categories, itemKey) =>
|
||||
controller.toggleMailboxCategories(
|
||||
categories,
|
||||
controller.mailboxListScrollController,
|
||||
itemKey,
|
||||
),
|
||||
isArrangeLTR: false,
|
||||
showIcon: true,
|
||||
padding: isDesktop
|
||||
? const EdgeInsetsDirectional.only(start: 10)
|
||||
: const EdgeInsets.symmetric(horizontal: 24),
|
||||
height: isDesktop ? 36 : 40,
|
||||
iconSpace: isDesktop
|
||||
? null
|
||||
: MailboxItemWidgetStyles.mobileLabelIconSpace,
|
||||
labelTextStyle: isDesktop ? null : ThemeUtils.textStyleInter500(),
|
||||
)),
|
||||
Obx(() {
|
||||
final categoriesExpandMode = controller
|
||||
.mailboxCategoriesExpandMode
|
||||
.value;
|
||||
|
||||
bool isExpand = categories.getExpandMode(categoriesExpandMode) ==
|
||||
ExpandMode.EXPAND;
|
||||
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
child: isExpand
|
||||
? _buildBodyMailboxCategory(
|
||||
context: context,
|
||||
categories: categories,
|
||||
mailboxNode: mailboxNode,
|
||||
padding: isDesktop
|
||||
? const EdgeInsetsDirectional.only(start: 10)
|
||||
: const EdgeInsetsDirectional.only(start: 24, end: 12),
|
||||
)
|
||||
: const Offstage(),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildBodyMailboxCategory({
|
||||
required BuildContext context,
|
||||
required MailboxCategories categories,
|
||||
required MailboxNode mailboxNode,
|
||||
EdgeInsetsGeometry? padding,
|
||||
}) {
|
||||
final treeView = TreeView(
|
||||
key: Key('${categories.keyValue}_mailbox_list'),
|
||||
children: _buildListChildTileWidget(context, mailboxNode),
|
||||
);
|
||||
|
||||
if (padding != null) {
|
||||
return Padding(padding: padding, child: treeView);
|
||||
} else {
|
||||
return treeView;
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> _buildListChildTileWidget(
|
||||
BuildContext context,
|
||||
MailboxNode parentNode,
|
||||
) {
|
||||
if (parentNode.childrenItems == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return parentNode.childrenItems!.map((mailboxNode) {
|
||||
final mailboxItemWidget = Obx(() => MailboxItemWidget(
|
||||
mailboxNode: mailboxNode,
|
||||
mailboxNodeSelected: controller
|
||||
.mailboxDashBoardController
|
||||
.selectedMailbox
|
||||
.value,
|
||||
onOpenMailboxFolderClick: (mailboxNode) =>
|
||||
controller.openMailbox(context, mailboxNode.item),
|
||||
onExpandFolderActionClick: mailboxNode.hasChildren()
|
||||
? (mailboxNode, itemKey) => controller.toggleMailboxFolder(
|
||||
mailboxNode,
|
||||
controller.mailboxListScrollController,
|
||||
itemKey,
|
||||
)
|
||||
: null,
|
||||
onSelectMailboxFolderClick: controller.selectMailboxNode,
|
||||
onLongPressMailboxNodeAction: PlatformInfo.isMobile
|
||||
? (mailboxNode) => controller.handleLongPressMailboxNodeAction(
|
||||
context,
|
||||
mailboxNode.item,
|
||||
)
|
||||
: null,
|
||||
onDragItemAccepted: PlatformInfo.isMobile
|
||||
? null
|
||||
: controller.handleDragItemAccepted,
|
||||
onMenuActionClick: PlatformInfo.isMobile
|
||||
? null
|
||||
: (position, mailboxNode) {
|
||||
controller.openMailboxContextMenuAction(
|
||||
context,
|
||||
position,
|
||||
mailboxNode.item,
|
||||
);
|
||||
},
|
||||
onEmptyMailboxActionCallback: PlatformInfo.isMobile
|
||||
? null
|
||||
: (mailboxNode) => controller.emptyMailboxAction(
|
||||
context,
|
||||
mailboxNode.item,
|
||||
),
|
||||
));
|
||||
|
||||
if (mailboxNode.hasChildren()) {
|
||||
return TreeViewChild(
|
||||
context,
|
||||
key: const Key('children_tree_mailbox_child'),
|
||||
isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
|
||||
paddingChild: const EdgeInsetsDirectional.only(start: 12),
|
||||
parent: mailboxItemWidget,
|
||||
children: _buildListChildTileWidget(context, mailboxNode),
|
||||
).build();
|
||||
} else {
|
||||
return mailboxItemWidget;
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Widget buildListMailbox(BuildContext context) {
|
||||
final isDesktop = controller.responsiveUtils.isDesktop(context);
|
||||
|
||||
return SingleChildScrollView(
|
||||
controller: controller.mailboxListScrollController,
|
||||
key: const PageStorageKey('mailbox_list'),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: isDesktop
|
||||
? const EdgeInsetsDirectional.only(end: 16)
|
||||
: const EdgeInsets.only(bottom: 16, top: 16),
|
||||
child: Column(children: [
|
||||
Obx(() => MailboxLoadingBarWidget(viewState: controller.viewState.value)),
|
||||
Obx(() {
|
||||
if (controller.defaultMailboxIsNotEmpty) {
|
||||
return buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.exchange,
|
||||
controller.defaultRootNode,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
final sendingEmails = controller
|
||||
.mailboxDashBoardController
|
||||
.listSendingEmails;
|
||||
|
||||
final isSendingQueueSelected =
|
||||
controller.mailboxDashBoardController.dashboardRoute.value == DashboardRoutes.sendingQueue;
|
||||
|
||||
if (sendingEmails.isNotEmpty && PlatformInfo.isMobile) {
|
||||
return SendingQueueMailboxWidget(
|
||||
imagePaths: controller.imagePaths,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
listSendingEmails: sendingEmails,
|
||||
onOpenSendingQueueAction: () =>
|
||||
controller.openSendingQueueViewAction(context),
|
||||
isSelected: isSendingQueueSelected,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
final sendingEmails = controller
|
||||
.mailboxDashBoardController
|
||||
.listSendingEmails;
|
||||
|
||||
if (controller.defaultMailboxIsNotEmpty ||
|
||||
(sendingEmails.isNotEmpty && PlatformInfo.isMobile)) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: Divider(color: AppColor.folderDivider, height: 1),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
return FoldersBarWidget(
|
||||
onOpenSearchFolder: () => controller.openSearchViewAction(context),
|
||||
onAddNewFolder: () => controller.goToCreateNewMailboxView(context),
|
||||
imagePaths: controller.imagePaths,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
height: isDesktop ? 48 : 40,
|
||||
padding: isDesktop
|
||||
? null
|
||||
: const EdgeInsetsDirectional.only(start: 24, end: 12),
|
||||
labelStyle: isDesktop ? null : ThemeUtils.textStyleInter500(),
|
||||
expandMode: controller.foldersExpandMode.value,
|
||||
onToggleExpandFolder: controller.toggleExpandFolders,
|
||||
);
|
||||
}),
|
||||
Obx(() => AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
child: controller.foldersExpandMode.value == ExpandMode.EXPAND
|
||||
? buildFolders(context)
|
||||
: const Offstage(),
|
||||
)),
|
||||
Obx(() {
|
||||
final accountId = controller
|
||||
.mailboxDashBoardController
|
||||
.accountId
|
||||
.value;
|
||||
|
||||
if (accountId == null) return const SizedBox.shrink();
|
||||
|
||||
final contactSupportCapability = controller
|
||||
.mailboxDashBoardController
|
||||
.sessionCurrent
|
||||
?.getContactSupportCapability(accountId);
|
||||
|
||||
if (contactSupportCapability?.isAvailable != true) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final isFoldersExpanded =
|
||||
controller.foldersExpandMode.value == ExpandMode.EXPAND;
|
||||
|
||||
final dividerPadding = EdgeInsets.only(
|
||||
top: isFoldersExpanded ? 8 : 0,
|
||||
bottom: 8,
|
||||
);
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: dividerPadding,
|
||||
child: const Divider(color: AppColor.folderDivider, height: 1),
|
||||
),
|
||||
FolderWidget(
|
||||
icon: controller.imagePaths.icHelp,
|
||||
label: AppLocalizations.of(context).support,
|
||||
onOpenFolderAction: () => controller
|
||||
.mailboxDashBoardController
|
||||
.onGetHelpOrReportBug(contactSupportCapability!),
|
||||
tooltip: AppLocalizations.of(context).getHelpOrReportABug,
|
||||
padding: isDesktop
|
||||
? null
|
||||
: const EdgeInsets.symmetric(horizontal: 12),
|
||||
itemPadding: const EdgeInsets.symmetric(
|
||||
horizontal: MailboxItemWidgetStyles.mobileItemPadding,
|
||||
),
|
||||
borderRadius: isDesktop
|
||||
? null
|
||||
: MailboxItemWidgetStyles.mobileBorderRadius,
|
||||
height: isDesktop
|
||||
? null
|
||||
: MailboxItemWidgetStyles.mobileHeight,
|
||||
labelTextStyle: isDesktop
|
||||
? null
|
||||
: ThemeUtils.textStyleInter500(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/presentation_mailbox_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_utils.dart';
|
||||
|
||||
extension HandleMailboxActionExtension on MailboxController {
|
||||
|
||||
void handleLongPressMailboxNodeAction(
|
||||
BuildContext context,
|
||||
PresentationMailbox mailbox,
|
||||
) {
|
||||
final deletedMessageVaultSupported =
|
||||
MailboxUtils.isDeletedMessageVaultSupported(session, accountId);
|
||||
|
||||
final isSubAddressingSupported =
|
||||
session?.isSubAddressingSupported(accountId) ?? false;
|
||||
|
||||
final contextMenuActions = listContextMenuItemAction(
|
||||
mailbox,
|
||||
mailboxDashBoardController.enableSpamReport,
|
||||
deletedMessageVaultSupported,
|
||||
isSubAddressingSupported,
|
||||
);
|
||||
|
||||
if (contextMenuActions.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
openContextMenuAction(
|
||||
context,
|
||||
contextMenuMailboxActionTiles(
|
||||
context,
|
||||
imagePaths,
|
||||
mailbox,
|
||||
contextMenuActions,
|
||||
handleMailboxAction: handleMailboxAction,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handleDragItemAccepted(
|
||||
List<PresentationEmail> listEmails,
|
||||
PresentationMailbox presentationMailbox,
|
||||
) {
|
||||
final mailboxPath = findNodePath(presentationMailbox.id)
|
||||
?? presentationMailbox.name?.name;
|
||||
log('HandleMailboxActionExtension::handleDragItemAccepted():mailboxPath = $mailboxPath');
|
||||
final newMailbox = mailboxPath != null
|
||||
? presentationMailbox.toPresentationMailboxWithMailboxPath(mailboxPath)
|
||||
: presentationMailbox;
|
||||
|
||||
mailboxDashBoardController.dragSelectedMultipleEmailToMailboxAction(
|
||||
listEmails,
|
||||
newMailbox,
|
||||
);
|
||||
}
|
||||
|
||||
void openMailboxContextMenuAction(
|
||||
BuildContext context,
|
||||
RelativeRect position,
|
||||
PresentationMailbox mailbox,
|
||||
) {
|
||||
final deletedMessageVaultSupported =
|
||||
MailboxUtils.isDeletedMessageVaultSupported(session, accountId);
|
||||
|
||||
final isSubAddressingSupported =
|
||||
session?.isSubAddressingSupported(accountId) ?? false;
|
||||
|
||||
final contextMenuActions = listContextMenuItemAction(
|
||||
mailbox,
|
||||
mailboxDashBoardController.enableSpamReport,
|
||||
deletedMessageVaultSupported,
|
||||
isSubAddressingSupported,
|
||||
);
|
||||
|
||||
if (contextMenuActions.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (responsiveUtils.isScreenWithShortestSide(context)) {
|
||||
openContextMenuAction(
|
||||
context,
|
||||
contextMenuMailboxActionTiles(
|
||||
context,
|
||||
imagePaths,
|
||||
mailbox,
|
||||
contextMenuActions,
|
||||
handleMailboxAction: handleMailboxAction,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
openPopupMenuAction(
|
||||
context,
|
||||
position,
|
||||
popupMenuMailboxActionTiles(
|
||||
context,
|
||||
imagePaths,
|
||||
mailbox,
|
||||
contextMenuActions,
|
||||
handleMailboxAction: handleMailboxAction,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosyst
|
||||
extension OpenAppGridExtension on MailboxController {
|
||||
void openAppGrid(List<AppLinagoraEcosystem> linagoraApps) {
|
||||
log('OpenAppGridExtension::openAppGrid: length of linagoraApps = ${linagoraApps.length}');
|
||||
mailboxDashBoardController.isAppGridDialogDisplayed.value = true;
|
||||
Get.dialog(
|
||||
Center(
|
||||
child: Dialog(
|
||||
@@ -55,7 +56,8 @@ extension OpenAppGridExtension on MailboxController {
|
||||
),
|
||||
),
|
||||
barrierColor: AppColor.blackAlpha20,
|
||||
);
|
||||
).whenComplete(() =>
|
||||
mailboxDashBoardController.isAppGridDialogDisplayed.value = false);
|
||||
}
|
||||
|
||||
Future<void> _handleOpenApp(AppLinagoraEcosystem app) async {
|
||||
|
||||
@@ -71,6 +71,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/usecases/subscribe_mailbox
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/usecases/subscribe_multiple_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mixin/mailbox_widget_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.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';
|
||||
@@ -105,7 +106,8 @@ import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart';
|
||||
class MailboxController extends BaseMailboxController
|
||||
with MailboxActionHandlerMixin,
|
||||
ContactSupportMixin,
|
||||
LauncherApplicationMixin {
|
||||
LauncherApplicationMixin,
|
||||
MailboxWidgetMixin {
|
||||
|
||||
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||
final isMailboxListScrollable = false.obs;
|
||||
|
||||
@@ -1,21 +1,7 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/application_version_widget.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/base_mailbox_view.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/toggle_expand_folders_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/styles/mailbox_item_widget_styles.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folder_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folders_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_category_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_item_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_loading_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/sending_queue_mailbox_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_routes.dart';
|
||||
import 'package:tmail_ui_user/features/quotas/presentation/quotas_view.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
@@ -28,6 +14,7 @@ class MailboxView extends BaseMailboxView {
|
||||
return Drawer(
|
||||
backgroundColor: Colors.white,
|
||||
shape: InputBorder.none,
|
||||
shadowColor: AppColor.blackAlpha20,
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -37,25 +24,19 @@ class MailboxView extends BaseMailboxView {
|
||||
child: RefreshIndicator(
|
||||
color: AppColor.primaryColor,
|
||||
onRefresh: controller.refreshAllMailbox,
|
||||
child: _buildListMailbox(context),
|
||||
),
|
||||
),
|
||||
QuotasView(
|
||||
labelStyle: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: AppColor.steelGray400,
|
||||
),
|
||||
labelMaxLines: 1,
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
start: 24,
|
||||
end: 23,
|
||||
top: 16,
|
||||
child: buildListMailbox(context),
|
||||
),
|
||||
),
|
||||
const QuotasView(),
|
||||
Container(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
bottom: 16,
|
||||
start: 24,
|
||||
end: 24,
|
||||
),
|
||||
child: ApplicationVersionWidget(
|
||||
title: '${AppLocalizations.of(context).version} ',
|
||||
title: '${AppLocalizations.of(context).version.toLowerCase()} ',
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -63,254 +44,4 @@ class MailboxView extends BaseMailboxView {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListMailbox(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
controller: controller.mailboxListScrollController,
|
||||
key: const PageStorageKey('mailbox_list'),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.only(bottom: 16, top: 16),
|
||||
child: Column(children: [
|
||||
Obx(() => MailboxLoadingBarWidget(viewState: controller.viewState.value)),
|
||||
Obx(() {
|
||||
if (controller.defaultMailboxIsNotEmpty) {
|
||||
return _buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.exchange,
|
||||
controller.defaultRootNode
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mailboxDashBoardController.listSendingEmails.isNotEmpty) {
|
||||
return SendingQueueMailboxWidget(
|
||||
imagePaths: controller.imagePaths,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
listSendingEmails: controller.mailboxDashBoardController.listSendingEmails,
|
||||
onOpenSendingQueueAction: () => controller.openSendingQueueViewAction(context),
|
||||
isSelected: controller.mailboxDashBoardController.dashboardRoute.value == DashboardRoutes.sendingQueue,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.defaultMailboxIsNotEmpty ||
|
||||
controller.mailboxDashBoardController.listSendingEmails.isNotEmpty) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: Divider(color: AppColor.folderDivider, height: 1),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
return FoldersBarWidget(
|
||||
onOpenSearchFolder: () => controller.openSearchViewAction(context),
|
||||
onAddNewFolder: () => controller.goToCreateNewMailboxView(context),
|
||||
imagePaths: controller.imagePaths,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
height: 40,
|
||||
padding: const EdgeInsetsDirectional.only(start: 24, end: 12),
|
||||
labelStyle: ThemeUtils.textStyleInter500(),
|
||||
expandMode: controller.foldersExpandMode.value,
|
||||
onToggleExpandFolder: controller.toggleExpandFolders,
|
||||
);
|
||||
}),
|
||||
Obx(() => AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
child: controller.foldersExpandMode.value == ExpandMode.EXPAND
|
||||
? _buildFolders(context)
|
||||
: const Offstage(),
|
||||
)),
|
||||
Obx(() {
|
||||
final accountId = controller
|
||||
.mailboxDashBoardController
|
||||
.accountId
|
||||
.value;
|
||||
|
||||
if (accountId == null) return const SizedBox.shrink();
|
||||
|
||||
final contactSupportCapability = controller
|
||||
.mailboxDashBoardController
|
||||
.sessionCurrent
|
||||
?.getContactSupportCapability(accountId);
|
||||
|
||||
if (contactSupportCapability?.isAvailable != true) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final isFoldersExpanded =
|
||||
controller.foldersExpandMode.value == ExpandMode.EXPAND;
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: isFoldersExpanded
|
||||
? const EdgeInsets.only(top: 8)
|
||||
: EdgeInsets.zero,
|
||||
child: const Divider(color: AppColor.folderDivider, height: 1),
|
||||
),
|
||||
FolderWidget(
|
||||
icon: controller.imagePaths.icHelp,
|
||||
label: AppLocalizations.of(context).support,
|
||||
onOpenFolderAction: () => controller
|
||||
.mailboxDashBoardController
|
||||
.onGetHelpOrReportBug(contactSupportCapability!),
|
||||
tooltip: AppLocalizations.of(context).getHelpOrReportABug,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
itemPadding: const EdgeInsets.symmetric(
|
||||
horizontal: MailboxItemWidgetStyles.mobileItemPadding,
|
||||
),
|
||||
borderRadius: MailboxItemWidgetStyles.mobileBorderRadius,
|
||||
height: MailboxItemWidgetStyles.mobileHeight,
|
||||
labelTextStyle: ThemeUtils.textStyleInter500(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFolders(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Obx(() {
|
||||
if (controller.personalMailboxIsNotEmpty) {
|
||||
return _buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.personalFolders,
|
||||
controller.personalRootNode,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.teamMailboxesIsNotEmpty) {
|
||||
return _buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.teamMailboxes,
|
||||
controller.teamMailboxesRootNode,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBodyMailboxCategory({
|
||||
required BuildContext context,
|
||||
required MailboxCategories categories,
|
||||
required MailboxNode mailboxNode,
|
||||
EdgeInsetsGeometry? padding,
|
||||
}) {
|
||||
final lastNode = mailboxNode.childrenItems?.last;
|
||||
|
||||
final treeView = TreeView(
|
||||
key: Key('${categories.keyValue}_mailbox_list'),
|
||||
children: _buildListChildTileWidget(
|
||||
context,
|
||||
mailboxNode,
|
||||
lastNode: lastNode,
|
||||
),
|
||||
);
|
||||
|
||||
if (padding != null) {
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: treeView,
|
||||
);
|
||||
} else {
|
||||
return treeView;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildMailboxCategory(BuildContext context, MailboxCategories categories, MailboxNode mailboxNode) {
|
||||
if (categories == MailboxCategories.exchange) {
|
||||
return _buildBodyMailboxCategory(
|
||||
context: context,
|
||||
categories: categories,
|
||||
mailboxNode: mailboxNode,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
);
|
||||
}
|
||||
return Column(children: [
|
||||
Obx(() => MailboxCategoryWidget(
|
||||
categories: categories,
|
||||
expandMode: categories.getExpandMode(
|
||||
controller.mailboxCategoriesExpandMode.value,
|
||||
),
|
||||
onToggleMailboxCategories: (categories, itemKey) =>
|
||||
controller.toggleMailboxCategories(
|
||||
categories,
|
||||
controller.mailboxListScrollController,
|
||||
itemKey,
|
||||
),
|
||||
isArrangeLTR: false,
|
||||
showIcon: true,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
height: 40,
|
||||
iconSpace: MailboxItemWidgetStyles.mobileLabelIconSpace,
|
||||
labelTextStyle: ThemeUtils.textStyleInter500(),
|
||||
)),
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
child: categories.getExpandMode(controller.mailboxCategoriesExpandMode.value) == ExpandMode.EXPAND
|
||||
? _buildBodyMailboxCategory(
|
||||
context: context,
|
||||
categories: categories,
|
||||
mailboxNode: mailboxNode,
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
start: 24,
|
||||
end: 12,
|
||||
),
|
||||
)
|
||||
: const Offstage())
|
||||
]);
|
||||
}
|
||||
|
||||
List<Widget> _buildListChildTileWidget(BuildContext context, MailboxNode parentNode, {MailboxNode? lastNode}) {
|
||||
return parentNode.childrenItems
|
||||
?.map((mailboxNode) {
|
||||
if (mailboxNode.hasChildren()) {
|
||||
return TreeViewChild(
|
||||
context,
|
||||
key: const Key('children_tree_mailbox_child'),
|
||||
isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
|
||||
paddingChild: const EdgeInsetsDirectional.only(start: 12),
|
||||
parent: Obx(() => MailboxItemWidget(
|
||||
mailboxNode: mailboxNode,
|
||||
mailboxNodeSelected: controller.mailboxDashBoardController.selectedMailbox.value,
|
||||
onLongPressMailboxNodeAction: (mailboxNode) => openMailboxMenuActionOnMobile(context, controller.imagePaths, mailboxNode.item, controller),
|
||||
onOpenMailboxFolderClick: (mailboxNode) => controller.openMailbox(context, mailboxNode.item),
|
||||
onExpandFolderActionClick: (mailboxNode, itemKey) =>
|
||||
controller.toggleMailboxFolder(
|
||||
mailboxNode,
|
||||
controller.mailboxListScrollController,
|
||||
itemKey,
|
||||
),
|
||||
onSelectMailboxFolderClick: (mailboxNode) => controller.selectMailboxNode(mailboxNode),
|
||||
)),
|
||||
children: _buildListChildTileWidget(context, mailboxNode)
|
||||
).build();
|
||||
} else {
|
||||
return Obx(() => MailboxItemWidget(
|
||||
mailboxNode: mailboxNode,
|
||||
mailboxNodeSelected: controller.mailboxDashBoardController.selectedMailbox.value,
|
||||
onLongPressMailboxNodeAction: (mailboxNode) => openMailboxMenuActionOnMobile(context, controller.imagePaths, mailboxNode.item, controller),
|
||||
onOpenMailboxFolderClick: (mailboxNode) => controller.openMailbox(context, mailboxNode.item),
|
||||
onSelectMailboxFolderClick: (mailboxNode) => controller.selectMailboxNode(mailboxNode)
|
||||
));
|
||||
}
|
||||
}).toList() ?? <Widget>[];
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/application_logo_with_text_widget.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/application_version_widget.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/base_mailbox_view.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/app_grid_view.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folder_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/folders_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_category_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_item_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_loading_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget.dart';
|
||||
import 'package:tmail_ui_user/features/quotas/presentation/quotas_view.dart';
|
||||
import 'package:tmail_ui_user/features/quotas/presentation/styles/quotas_view_styles.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class MailboxView extends BaseMailboxView {
|
||||
@@ -27,182 +16,49 @@ class MailboxView extends BaseMailboxView {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isDesktop = controller.responsiveUtils.isDesktop(context);
|
||||
|
||||
return Drawer(
|
||||
elevation: controller.responsiveUtils.isDesktop(context) ? 0 : 16.0,
|
||||
shape: controller.responsiveUtils.isDesktop(context)
|
||||
? const RoundedRectangleBorder()
|
||||
: null,
|
||||
child: Scaffold(
|
||||
backgroundColor: controller.responsiveUtils.isWebDesktop(context)
|
||||
? AppColor.colorBgDesktop
|
||||
: Colors.white,
|
||||
body: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
if (!controller.responsiveUtils.isDesktop(context))
|
||||
ApplicationLogoWidthTextWidget(
|
||||
margin: const EdgeInsetsDirectional.only(
|
||||
top: 16,
|
||||
bottom: 16,
|
||||
start: 16,
|
||||
),
|
||||
),
|
||||
if (!controller.responsiveUtils.isDesktop(context))
|
||||
const Divider(
|
||||
color: AppColor.colorDividerMailbox,
|
||||
height: 0.5,
|
||||
thickness: 0.2),
|
||||
Expanded(child: Container(
|
||||
padding: EdgeInsetsDirectional.only(start: controller.responsiveUtils.isDesktop(context) ? 16 : 0),
|
||||
color: controller.responsiveUtils.isDesktop(context)
|
||||
? AppColor.colorBgDesktop
|
||||
: Colors.white,
|
||||
child: Container(
|
||||
color: controller.responsiveUtils.isDesktop(context)
|
||||
? AppColor.colorBgDesktop
|
||||
: Colors.white,
|
||||
child: _buildListMailbox(context),
|
||||
),
|
||||
)),
|
||||
const Divider(color: AppColor.colorDividerHorizontal),
|
||||
const QuotasView(
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
start: QuotasViewStyles.padding,
|
||||
top: QuotasViewStyles.padding,
|
||||
),
|
||||
backgroundColor: isDesktop ? AppColor.colorBgDesktop : Colors.white,
|
||||
shape: InputBorder.none,
|
||||
shadowColor: AppColor.blackAlpha20,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (!isDesktop) buildMailboxAppBar(),
|
||||
Expanded(
|
||||
child: isDesktop
|
||||
? Padding(
|
||||
padding: const EdgeInsetsDirectional.only(start: 16),
|
||||
child: _buildListMailbox(context),
|
||||
)
|
||||
: _buildListMailbox(context),
|
||||
),
|
||||
const QuotasView(),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
alignment: controller.responsiveUtils.isDesktop(context)
|
||||
? AlignmentDirectional.centerStart
|
||||
: AlignmentDirectional.center,
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: controller.responsiveUtils.isWebDesktop(context)
|
||||
? AppColor.colorBgDesktop
|
||||
: Colors.white,
|
||||
alignment: isDesktop
|
||||
? AlignmentDirectional.center
|
||||
: AlignmentDirectional.centerStart,
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
bottom: 16,
|
||||
start: 24,
|
||||
end: 24,
|
||||
),
|
||||
child: ApplicationVersionWidget(
|
||||
title: '${AppLocalizations.of(context).version.toLowerCase()} ',
|
||||
textStyle: isDesktop
|
||||
? ThemeUtils.textStyleContentCaption()
|
||||
: null,
|
||||
),
|
||||
),
|
||||
]),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListMailbox(BuildContext context) {
|
||||
final mailboxListWidget = SingleChildScrollView(
|
||||
controller: controller.mailboxListScrollController,
|
||||
key: const PageStorageKey('mailbox_list'),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: EdgeInsetsDirectional.only(end: controller.responsiveUtils.isDesktop(context) ? 16 : 0),
|
||||
child: Column(children: [
|
||||
if (!controller.responsiveUtils.isDesktop(context))
|
||||
Obx(() => UserInformationWidget(
|
||||
userName: controller.mailboxDashBoardController.accountId.value != null
|
||||
? controller.mailboxDashBoardController.getOwnEmailAddress()
|
||||
: '',
|
||||
subtitle: AppLocalizations.of(context).manage_account,
|
||||
onSubtitleClick: controller.mailboxDashBoardController.goToSettings,
|
||||
border: const Border(
|
||||
bottom: BorderSide(
|
||||
color: AppColor.colorDividerHorizontal,
|
||||
width: 0.5,
|
||||
)
|
||||
),
|
||||
)),
|
||||
Obx(() => MailboxLoadingBarWidget(viewState: controller.viewState.value)),
|
||||
Obx(() {
|
||||
final linagoraApps = controller
|
||||
.mailboxDashBoardController
|
||||
.appGridDashboardController
|
||||
.listLinagoraApp;
|
||||
final mailboxListWidget = buildListMailbox(context);
|
||||
|
||||
if (linagoraApps.isNotEmpty && !controller.responsiveUtils.isDesktop(context)) {
|
||||
return AppGridView(linagoraApps: linagoraApps);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
const SizedBox(height: 8),
|
||||
Obx(() {
|
||||
if (controller.defaultMailboxIsNotEmpty) {
|
||||
return _buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.exchange,
|
||||
controller.defaultRootNode
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
const SizedBox(height: 8),
|
||||
const Divider(color: AppColor.colorDividerMailbox, height: 1),
|
||||
FoldersBarWidget(
|
||||
onOpenSearchFolder: () => controller.openSearchViewAction(context),
|
||||
onAddNewFolder: () => controller.goToCreateNewMailboxView(context),
|
||||
imagePaths: controller.imagePaths,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
),
|
||||
Obx(() {
|
||||
if (controller.personalMailboxIsNotEmpty) {
|
||||
return _buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.personalFolders,
|
||||
controller.personalRootNode
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.teamMailboxesIsNotEmpty) {
|
||||
return _buildMailboxCategory(
|
||||
context,
|
||||
MailboxCategories.teamMailboxes,
|
||||
controller.teamMailboxesRootNode
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
final accountId = controller
|
||||
.mailboxDashBoardController
|
||||
.accountId
|
||||
.value;
|
||||
|
||||
if (accountId == null) return const SizedBox.shrink();
|
||||
|
||||
final contactSupportCapability = controller
|
||||
.mailboxDashBoardController
|
||||
.sessionCurrent
|
||||
?.getContactSupportCapability(accountId);
|
||||
|
||||
if (contactSupportCapability?.isAvailable != true) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
const Divider(color: AppColor.colorDividerMailbox, height: 1),
|
||||
const SizedBox(height: 8),
|
||||
FolderWidget(
|
||||
icon: controller.imagePaths.icHelp,
|
||||
label: AppLocalizations.of(context).support,
|
||||
onOpenFolderAction: () => controller
|
||||
.mailboxDashBoardController
|
||||
.onGetHelpOrReportBug(contactSupportCapability!),
|
||||
tooltip: AppLocalizations.of(context).getHelpOrReportABug,
|
||||
padding: !controller.responsiveUtils.isDesktop(context)
|
||||
? const EdgeInsets.symmetric(horizontal: 16)
|
||||
: null,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
);
|
||||
}),
|
||||
])
|
||||
);
|
||||
return Stack(
|
||||
children: [
|
||||
if (!PlatformInfo.isCanvasKit)
|
||||
@@ -249,157 +105,4 @@ class MailboxView extends BaseMailboxView {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBodyMailboxCategory({
|
||||
required BuildContext context,
|
||||
required MailboxCategories categories,
|
||||
required MailboxNode mailboxNode,
|
||||
EdgeInsetsGeometry? padding,
|
||||
}) {
|
||||
final lastNode = mailboxNode.childrenItems?.last;
|
||||
|
||||
final treeView = TreeView(
|
||||
key: Key('${categories.keyValue}_mailbox_list'),
|
||||
children: _buildListChildTileWidget(
|
||||
context,
|
||||
mailboxNode,
|
||||
lastNode: lastNode,
|
||||
),
|
||||
);
|
||||
|
||||
if (padding != null) {
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: treeView,
|
||||
);
|
||||
} else {
|
||||
return treeView;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildMailboxCategory(
|
||||
BuildContext context,
|
||||
MailboxCategories categories,
|
||||
MailboxNode mailboxNode
|
||||
) {
|
||||
if (categories == MailboxCategories.exchange) {
|
||||
return _buildBodyMailboxCategory(
|
||||
context: context,
|
||||
categories: categories,
|
||||
mailboxNode: mailboxNode,
|
||||
padding: !controller.responsiveUtils.isDesktop(context)
|
||||
? const EdgeInsets.symmetric(horizontal: 16)
|
||||
: null,
|
||||
);
|
||||
} else {
|
||||
return Column(
|
||||
children: [
|
||||
Obx(() => MailboxCategoryWidget(
|
||||
categories: categories,
|
||||
expandMode: categories.getExpandMode(
|
||||
controller.mailboxCategoriesExpandMode.value,
|
||||
),
|
||||
onToggleMailboxCategories: (categories, itemKey) =>
|
||||
controller.toggleMailboxCategories(
|
||||
categories,
|
||||
controller.mailboxListScrollController,
|
||||
itemKey,
|
||||
),
|
||||
isArrangeLTR: false,
|
||||
showIcon: true,
|
||||
padding: !controller.responsiveUtils.isDesktop(context)
|
||||
? const EdgeInsetsDirectional.only(start: 26, end: 16)
|
||||
: const EdgeInsetsDirectional.only(start: 10),
|
||||
)),
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
child: categories.getExpandMode(controller.mailboxCategoriesExpandMode.value) == ExpandMode.EXPAND
|
||||
? _buildBodyMailboxCategory(
|
||||
context: context,
|
||||
categories: categories,
|
||||
mailboxNode: mailboxNode,
|
||||
padding: !controller.responsiveUtils.isDesktop(context)
|
||||
? const EdgeInsetsDirectional.only(start: 30, end: 16)
|
||||
: const EdgeInsetsDirectional.only(start: 10),
|
||||
)
|
||||
: const Offstage()
|
||||
),
|
||||
const SizedBox(height: 8)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> _buildListChildTileWidget(
|
||||
BuildContext context,
|
||||
MailboxNode parentNode,
|
||||
{MailboxNode? lastNode}
|
||||
) {
|
||||
return parentNode.childrenItems?.map((mailboxNode) {
|
||||
if (mailboxNode.hasChildren()) {
|
||||
return TreeViewChild(
|
||||
context,
|
||||
key: const Key('children_tree_mailbox_child'),
|
||||
isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
|
||||
paddingChild: const EdgeInsetsDirectional.only(start: 14),
|
||||
parent: Obx(() => MailboxItemWidget(
|
||||
mailboxNode: mailboxNode,
|
||||
mailboxNodeSelected: controller.mailboxDashBoardController.selectedMailbox.value,
|
||||
onOpenMailboxFolderClick: (mailboxNode) => controller.openMailbox(context, mailboxNode.item),
|
||||
onExpandFolderActionClick: (mailboxNode, itemKey) =>
|
||||
controller.toggleMailboxFolder(
|
||||
mailboxNode,
|
||||
controller.mailboxListScrollController,
|
||||
itemKey,
|
||||
),
|
||||
onSelectMailboxFolderClick: controller.selectMailboxNode,
|
||||
onDragItemAccepted: _handleDragItemAccepted,
|
||||
onMenuActionClick: (position, mailboxNode) {
|
||||
openMailboxMenuActionOnWeb(
|
||||
context,
|
||||
controller.imagePaths,
|
||||
controller.responsiveUtils,
|
||||
position,
|
||||
mailboxNode.item,
|
||||
controller
|
||||
);
|
||||
},
|
||||
onEmptyMailboxActionCallback: (mailboxNode) => controller.emptyMailboxAction(context, mailboxNode.item),
|
||||
)),
|
||||
children: _buildListChildTileWidget(context, mailboxNode)
|
||||
).build();
|
||||
} else {
|
||||
return Obx(() => MailboxItemWidget(
|
||||
mailboxNode: mailboxNode,
|
||||
mailboxNodeSelected: controller.mailboxDashBoardController.selectedMailbox.value,
|
||||
onOpenMailboxFolderClick: (mailboxNode) => controller.openMailbox(context, mailboxNode.item),
|
||||
onSelectMailboxFolderClick: controller.selectMailboxNode,
|
||||
onDragItemAccepted: _handleDragItemAccepted,
|
||||
onMenuActionClick: (position, mailboxNode) {
|
||||
openMailboxMenuActionOnWeb(
|
||||
context,
|
||||
controller.imagePaths,
|
||||
controller.responsiveUtils,
|
||||
position,
|
||||
mailboxNode.item,
|
||||
controller
|
||||
);
|
||||
},
|
||||
onEmptyMailboxActionCallback: (mailboxNode) => controller.emptyMailboxAction(context, mailboxNode.item),
|
||||
));
|
||||
}
|
||||
}).toList() ?? <Widget>[];
|
||||
}
|
||||
|
||||
void _handleDragItemAccepted(List<PresentationEmail> listEmails, PresentationMailbox presentationMailbox) {
|
||||
final mailboxPath = controller.findNodePath(presentationMailbox.id)
|
||||
?? presentationMailbox.name?.name;
|
||||
log('MailboxView::_handleDragItemAccepted(): mailboxPath: $mailboxPath');
|
||||
if (mailboxPath != null) {
|
||||
final newMailbox = presentationMailbox.toPresentationMailboxWithMailboxPath(mailboxPath);
|
||||
controller.mailboxDashBoardController.dragSelectedMultipleEmailToMailboxAction(listEmails, newMailbox);
|
||||
} else {
|
||||
controller.mailboxDashBoardController.dragSelectedMultipleEmailToMailboxAction(listEmails, presentationMailbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,11 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:model/mailbox/mailbox_constants.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/context_item_mailbox_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_utils.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_bottom_sheet_action_tile_builder.dart';
|
||||
import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
||||
|
||||
mixin MailboxWidgetMixin {
|
||||
|
||||
@@ -105,43 +98,6 @@ mixin MailboxWidgetMixin {
|
||||
}
|
||||
}
|
||||
|
||||
void openMailboxMenuActionOnMobile(
|
||||
BuildContext context,
|
||||
ImagePaths imagePaths,
|
||||
PresentationMailbox mailbox,
|
||||
MailboxController controller
|
||||
) {
|
||||
final bool deletedMessageVaultSupported = MailboxUtils.isDeletedMessageVaultSupported(
|
||||
controller.mailboxDashBoardController.sessionCurrent,
|
||||
controller.mailboxDashBoardController.accountId.value);
|
||||
|
||||
final bool subaddressingSupported = isSubaddressingSupported(
|
||||
controller.mailboxDashBoardController.sessionCurrent,
|
||||
controller.mailboxDashBoardController.accountId.value);
|
||||
|
||||
final contextMenuActions = listContextMenuItemAction(
|
||||
mailbox,
|
||||
controller.mailboxDashBoardController.enableSpamReport,
|
||||
deletedMessageVaultSupported,
|
||||
subaddressingSupported,
|
||||
);
|
||||
|
||||
if (contextMenuActions.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
controller.openContextMenuAction(
|
||||
context,
|
||||
contextMenuMailboxActionTiles(
|
||||
context,
|
||||
imagePaths,
|
||||
mailbox,
|
||||
contextMenuActions,
|
||||
handleMailboxAction: controller.handleMailboxAction
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> contextMenuMailboxActionTiles(
|
||||
BuildContext context,
|
||||
ImagePaths imagePaths,
|
||||
@@ -207,59 +163,6 @@ mixin MailboxWidgetMixin {
|
||||
return listContextMenuItemAction;
|
||||
}
|
||||
|
||||
void openMailboxMenuActionOnWeb(
|
||||
BuildContext context,
|
||||
ImagePaths imagePaths,
|
||||
ResponsiveUtils responsiveUtils,
|
||||
RelativeRect position,
|
||||
PresentationMailbox mailbox,
|
||||
MailboxController controller
|
||||
) {
|
||||
final bool deletedMessageVaultSupported = MailboxUtils.isDeletedMessageVaultSupported(
|
||||
controller.mailboxDashBoardController.sessionCurrent,
|
||||
controller.mailboxDashBoardController.accountId.value);
|
||||
|
||||
final bool subaddressingSupported = isSubaddressingSupported(
|
||||
controller.mailboxDashBoardController.sessionCurrent,
|
||||
controller.mailboxDashBoardController.accountId.value);
|
||||
|
||||
final contextMenuActions = listContextMenuItemAction(
|
||||
mailbox,
|
||||
controller.mailboxDashBoardController.enableSpamReport,
|
||||
deletedMessageVaultSupported,
|
||||
subaddressingSupported,
|
||||
);
|
||||
|
||||
if (contextMenuActions.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (responsiveUtils.isScreenWithShortestSide(context)) {
|
||||
controller.openContextMenuAction(
|
||||
context,
|
||||
contextMenuMailboxActionTiles(
|
||||
context,
|
||||
imagePaths,
|
||||
mailbox,
|
||||
contextMenuActions,
|
||||
handleMailboxAction: controller.handleMailboxAction
|
||||
)
|
||||
);
|
||||
} else {
|
||||
controller.openPopupMenuAction(
|
||||
context,
|
||||
position,
|
||||
popupMenuMailboxActionTiles(
|
||||
context,
|
||||
imagePaths,
|
||||
mailbox,
|
||||
contextMenuActions,
|
||||
handleMailboxAction: controller.handleMailboxAction
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
List<PopupMenuEntry> popupMenuMailboxActionTiles(
|
||||
BuildContext context,
|
||||
ImagePaths imagePaths,
|
||||
@@ -280,20 +183,6 @@ mixin MailboxWidgetMixin {
|
||||
.toList();
|
||||
}
|
||||
|
||||
static bool isSubaddressingSupported(Session? session, AccountId? accountId) {
|
||||
if (session == null || accountId == null) {
|
||||
return false;
|
||||
}
|
||||
if (!CapabilityIdentifier.jmapTeamMailboxes.isSupported(session, accountId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (session.getCapabilityProperties(accountId, CapabilityIdentifier.jmapTeamMailboxes)
|
||||
?.props[0] as Map<String, dynamic>?)
|
||||
?[subaddressingSupported]
|
||||
?? false;
|
||||
}
|
||||
|
||||
PopupMenuItem _buildPopupMenuItem(
|
||||
BuildContext context,
|
||||
ImagePaths imagePaths,
|
||||
|
||||
@@ -17,7 +17,7 @@ class CountOfEmailsWidget extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: PlatformInfo.isMobile
|
||||
? ThemeUtils.textStyleInter400()
|
||||
: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Colors.black,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -72,7 +72,6 @@ class FolderWidget extends StatelessWidget {
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(borderRadius ?? MailboxItemWidgetStyles.borderRadius),
|
||||
),
|
||||
hoverColor: AppColor.blue100,
|
||||
child: item,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/utils/direction_utils.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:model/mailbox/expand_mode.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/expand_mode_extension.dart';
|
||||
@@ -36,6 +35,8 @@ class FoldersBarWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isDesktop = responsiveUtils.isDesktop(context);
|
||||
|
||||
Widget searchBarIcon = TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icSearchBar,
|
||||
backgroundColor: Colors.transparent,
|
||||
@@ -45,7 +46,7 @@ class FoldersBarWidget extends StatelessWidget {
|
||||
onTapActionCallback: onOpenSearchFolder,
|
||||
);
|
||||
|
||||
if (responsiveUtils.isWebDesktop(context)) {
|
||||
if (isDesktop) {
|
||||
searchBarIcon = Transform(
|
||||
transform: Matrix4.translationValues(8, 0, 0),
|
||||
child: searchBarIcon,
|
||||
@@ -62,7 +63,7 @@ class FoldersBarWidget extends StatelessWidget {
|
||||
onTapActionCallback: onAddNewFolder,
|
||||
);
|
||||
|
||||
if (responsiveUtils.isWebDesktop(context)) {
|
||||
if (isDesktop) {
|
||||
newFolderIcon = Transform(
|
||||
transform: Matrix4.translationValues(8, 0, 0),
|
||||
child: newFolderIcon,
|
||||
@@ -78,8 +79,8 @@ class FoldersBarWidget extends StatelessWidget {
|
||||
|
||||
return Container(
|
||||
padding: padding ?? EdgeInsetsDirectional.only(
|
||||
start: responsiveUtils.isWebDesktop(context) ? 10 : 26,
|
||||
end: responsiveUtils.isWebDesktop(context) ? 0 : 8,
|
||||
start: isDesktop ? 10 : 26,
|
||||
end: isDesktop ? 0 : 8,
|
||||
),
|
||||
height: height ?? 48,
|
||||
child: Row(
|
||||
@@ -94,9 +95,12 @@ class FoldersBarWidget extends StatelessWidget {
|
||||
DirectionUtils.isDirectionRTLByLanguage(context),
|
||||
),
|
||||
iconColor: Colors.black,
|
||||
iconSize: PlatformInfo.isMobile ? 17 : 20,
|
||||
iconSize: 17,
|
||||
margin: isDesktop
|
||||
? const EdgeInsetsDirectional.only(start: 8)
|
||||
: null,
|
||||
backgroundColor: Colors.transparent,
|
||||
padding: EdgeInsets.all(PlatformInfo.isMobile ? 3 : 5),
|
||||
padding: const EdgeInsets.all(3),
|
||||
tooltipMessage: expandMode!.getTooltipMessage(AppLocalizations.of(context)),
|
||||
onTapActionCallback: () => onToggleExpandFolder?.call(),
|
||||
)
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/presentation/views/text/text_overflow_builder.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:model/extensions/presentation_mailbox_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
|
||||
@@ -72,7 +71,8 @@ class _LabelMailboxItemWidgetState extends State<LabelMailboxItemWidget> {
|
||||
itemKey: widget.itemKey,
|
||||
mailboxNode: widget.mailboxNode,
|
||||
imagePaths: widget.imagePaths,
|
||||
onExpandFolderActionClick: widget.onClickExpandMailboxNodeAction,
|
||||
responsiveUtils: widget.responsiveUtils,
|
||||
onExpandFolderActionClick: onClickExpandMailboxNodeAction,
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -163,13 +163,13 @@ class _LabelMailboxItemWidgetState extends State<LabelMailboxItemWidget> {
|
||||
TextStyle get _displayNameTextStyle {
|
||||
if (isSelected) {
|
||||
return ThemeUtils.textStyleInter700(
|
||||
color: PlatformInfo.isMobile ? AppColor.iconFolder : null,
|
||||
color: responsiveUtils.isDesktop(context) ? null : AppColor.iconFolder,
|
||||
fontSize: 14,
|
||||
);
|
||||
} else {
|
||||
return PlatformInfo.isMobile
|
||||
? ThemeUtils.textStyleInter500()
|
||||
: ThemeUtils.textStyleBodyBody3(color: Colors.black);
|
||||
return responsiveUtils.isWebDesktop(context)
|
||||
? ThemeUtils.textStyleBodyBody3(color: Colors.black)
|
||||
: ThemeUtils.textStyleInter500();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/utils/direction_utils.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -79,12 +78,10 @@ class _MailboxCategoryWidgetState extends State<MailboxCategoryWidget> {
|
||||
DirectionUtils.isDirectionRTLByLanguage(context),
|
||||
),
|
||||
iconColor: Colors.black,
|
||||
iconSize: PlatformInfo.isMobile ? 17 : 20,
|
||||
iconSize: 17,
|
||||
backgroundColor: Colors.transparent,
|
||||
margin: PlatformInfo.isMobile
|
||||
? const EdgeInsetsDirectional.only(start: 8)
|
||||
: null,
|
||||
padding: EdgeInsets.all(PlatformInfo.isMobile ? 3 : 5),
|
||||
margin: const EdgeInsetsDirectional.only(start: 8),
|
||||
padding: const EdgeInsets.all(3),
|
||||
tooltipMessage: widget.expandMode.getTooltipMessage(AppLocalizations.of(context)),
|
||||
onTapActionCallback: () =>
|
||||
widget.onToggleMailboxCategories(widget.categories, _key)),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/utils/direction_utils.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:model/extensions/presentation_mailbox_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/expand_mode_extension.dart';
|
||||
@@ -14,6 +14,7 @@ class MailboxExpandButton extends StatelessWidget {
|
||||
final GlobalKey itemKey;
|
||||
final MailboxNode mailboxNode;
|
||||
final ImagePaths imagePaths;
|
||||
final ResponsiveUtils responsiveUtils;
|
||||
final OnClickExpandMailboxNodeAction? onExpandFolderActionClick;
|
||||
|
||||
const MailboxExpandButton({
|
||||
@@ -21,6 +22,7 @@ class MailboxExpandButton extends StatelessWidget {
|
||||
required this.itemKey,
|
||||
required this.mailboxNode,
|
||||
required this.imagePaths,
|
||||
required this.responsiveUtils,
|
||||
required this.onExpandFolderActionClick,
|
||||
});
|
||||
|
||||
@@ -32,11 +34,9 @@ class MailboxExpandButton extends StatelessWidget {
|
||||
DirectionUtils.isDirectionRTLByLanguage(context),
|
||||
),
|
||||
iconColor: _expandIconColor,
|
||||
iconSize: PlatformInfo.isMobile ? 17 : 20,
|
||||
margin: PlatformInfo.isMobile
|
||||
? const EdgeInsetsDirectional.only(start: 8)
|
||||
: null,
|
||||
padding: EdgeInsets.all(PlatformInfo.isMobile ? 3 : 5),
|
||||
iconSize: 17,
|
||||
margin: const EdgeInsetsDirectional.only(start: 8),
|
||||
padding: const EdgeInsets.all(3),
|
||||
backgroundColor: Colors.transparent,
|
||||
tooltipMessage: mailboxNode.expandMode.getTooltipMessage(AppLocalizations.of(context)),
|
||||
onTapActionCallback: () => onExpandFolderActionClick?.call(mailboxNode, itemKey),
|
||||
|
||||
@@ -142,11 +142,17 @@ class _MailboxItemWidgetState extends State<MailboxItemWidget> {
|
||||
),
|
||||
height: widget.mailboxNode.item.isTeamMailboxes
|
||||
? MailboxItemWidgetStyles.teamMailboxHeight
|
||||
: MailboxItemWidgetStyles.height,
|
||||
: MailboxItemWidgetStyles.mobileHeight,
|
||||
child: Row(
|
||||
children: [
|
||||
if (_isIconDisplayed)
|
||||
MailboxIconWidget(icon: _iconMailbox),
|
||||
MailboxIconWidget(
|
||||
icon: _iconMailbox,
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
end: MailboxItemWidgetStyles.mobileLabelIconSpace,
|
||||
),
|
||||
color: AppColor.iconFolder,
|
||||
),
|
||||
Expanded(
|
||||
child: LabelMailboxItemWidget(
|
||||
itemKey: _key,
|
||||
|
||||
@@ -36,8 +36,12 @@ class TrailingMailboxItemWidget extends StatelessWidget {
|
||||
? EdgeInsets.zero
|
||||
: TrailingMailboxItemWidgetStyles.menuIconMargin,
|
||||
icon: imagePaths.icMoreVertical,
|
||||
iconSize: TrailingMailboxItemWidgetStyles.menuIconSize,
|
||||
padding: TrailingMailboxItemWidgetStyles.menuIconPadding,
|
||||
iconSize: mailboxNode.item.isTeamMailboxes
|
||||
? 17
|
||||
: TrailingMailboxItemWidgetStyles.menuIconSize,
|
||||
padding: mailboxNode.item.isTeamMailboxes
|
||||
? const EdgeInsets.all(3)
|
||||
: TrailingMailboxItemWidgetStyles.menuIconPadding,
|
||||
backgroundColor: TrailingMailboxItemWidgetStyles.menuIconBackgroundColor,
|
||||
onTapActionAtPositionCallback: (position) => onMenuActionClick?.call(position, mailboxNode),
|
||||
);
|
||||
|
||||
+1
@@ -258,6 +258,7 @@ class MailboxDashBoardController extends ReloadableController
|
||||
final isRecoveringDeletedMessage = RxBool(false);
|
||||
final localFileDraggableAppState = Rxn<DraggableAppState>();
|
||||
final isSenderImportantFlagEnabled = RxBool(true);
|
||||
final isAppGridDialogDisplayed = RxBool(false);
|
||||
|
||||
Session? sessionCurrent;
|
||||
Map<Role, MailboxId> mapDefaultMailboxIdByRole = {};
|
||||
|
||||
@@ -264,7 +264,10 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
|
||||
key: controller.scaffoldKey,
|
||||
drawer: ResponsiveWidget(
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
mobile: SizedBox(width: ResponsiveUtils.defaultSizeDrawer, child: MailboxView()),
|
||||
mobile: SizedBox(
|
||||
width: ResponsiveUtils.mobileLeftMenuSize,
|
||||
child: MailboxView(),
|
||||
),
|
||||
tabletLarge: SizedBox(width: ResponsiveUtils.defaultSizeLeftMenuMobile, child: MailboxView()),
|
||||
desktop: const SizedBox.shrink()
|
||||
),
|
||||
|
||||
@@ -11,114 +11,96 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class QuotasView extends GetWidget<QuotasController> {
|
||||
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final TextStyle? labelStyle;
|
||||
final int? labelMaxLines;
|
||||
|
||||
const QuotasView({
|
||||
super.key,
|
||||
this.padding,
|
||||
this.labelStyle,
|
||||
this.labelMaxLines,
|
||||
});
|
||||
const QuotasView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() {
|
||||
final octetQuota = controller.octetsQuota.value;
|
||||
if (octetQuota != null && octetQuota.storageAvailable) {
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
return Container(
|
||||
padding: padding ?? const EdgeInsetsDirectional.only(
|
||||
start: QuotasViewStyles.padding,
|
||||
top: QuotasViewStyles.padding,
|
||||
),
|
||||
margin: controller.responsiveUtils.isWebDesktop(context)
|
||||
? const EdgeInsetsDirectional.only(end: QuotasViewStyles.margin)
|
||||
: null,
|
||||
decoration: BoxDecoration(
|
||||
color: controller.responsiveUtils.isWebDesktop(context)
|
||||
? QuotasViewStyles.webBackgroundColor
|
||||
: QuotasViewStyles.mobileBackgroundColor,
|
||||
),
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
controller.imagePaths.icQuotas,
|
||||
width: QuotasViewStyles.iconSize,
|
||||
height: QuotasViewStyles.iconSize,
|
||||
colorFilter: AppColor.steelGray400.asFilter(),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
const SizedBox(width: QuotasViewStyles.iconPadding),
|
||||
Flexible(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).storageQuotas,
|
||||
style: labelStyle ?? const TextStyle(
|
||||
fontSize: QuotasViewStyles.labelTextSize,
|
||||
fontWeight: QuotasViewStyles.labelFontWeight,
|
||||
color: QuotasViewStyles.labelTextColor,
|
||||
),
|
||||
maxLines: labelMaxLines ?? 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: QuotasViewStyles.iconPadding),
|
||||
Obx(() {
|
||||
final isLoading = controller.viewState.value.fold(
|
||||
(failure) => false,
|
||||
(success) => success is GetQuotasLoading,
|
||||
);
|
||||
bool isDesktop = controller.responsiveUtils.isDesktop(context);
|
||||
|
||||
return QuotaReloadButton(
|
||||
icon: controller.imagePaths.icRefresh,
|
||||
isLoading: isLoading,
|
||||
onTap: controller.reloadQuota,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: QuotasViewStyles.space),
|
||||
SizedBox(
|
||||
width: _getProgressBarMaxWith(constraints.maxWidth),
|
||||
child: LinearProgressIndicator(
|
||||
color: octetQuota.getQuotasStateProgressBarColor(),
|
||||
minHeight: QuotasViewStyles.progressBarHeight,
|
||||
backgroundColor: QuotasViewStyles.progressBarBackgroundColor,
|
||||
value: octetQuota.usedStoragePercent,
|
||||
if (octetQuota != null && octetQuota.storageAvailable) {
|
||||
final quotasWidget = Container(
|
||||
padding: isDesktop
|
||||
? const EdgeInsets.all(16)
|
||||
: const EdgeInsets.symmetric(vertical: 16),
|
||||
margin: isDesktop
|
||||
? const EdgeInsetsDirectional.only(start: 8)
|
||||
: const EdgeInsetsDirectional.only(start: 24),
|
||||
width: isDesktop ? 224 : 196,
|
||||
alignment: isDesktop
|
||||
? AlignmentDirectional.center
|
||||
: AlignmentDirectional.centerStart,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
controller.imagePaths.icQuotas,
|
||||
width: QuotasViewStyles.iconSize,
|
||||
height: QuotasViewStyles.iconSize,
|
||||
colorFilter: AppColor.steelGray400.asFilter(),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: QuotasViewStyles.space),
|
||||
Text(
|
||||
octetQuota.getQuotasStateTitle(context),
|
||||
style: labelStyle ?? TextStyle(
|
||||
fontSize: QuotasViewStyles.progressStateTextSize,
|
||||
fontWeight: QuotasViewStyles.progressStateFontWeight,
|
||||
color: octetQuota.getQuotasStateTitleColor(),
|
||||
const SizedBox(width: QuotasViewStyles.iconPadding),
|
||||
Expanded(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).storageQuotas,
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: AppColor.steelGray400,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
maxLines: labelMaxLines ?? 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
const SizedBox(width: QuotasViewStyles.iconPadding),
|
||||
Obx(() {
|
||||
final isLoading = controller.viewState.value.fold(
|
||||
(failure) => false,
|
||||
(success) => success is GetQuotasLoading,
|
||||
);
|
||||
|
||||
return QuotaReloadButton(
|
||||
icon: controller.imagePaths.icRefreshQuotas,
|
||||
isLoading: isLoading,
|
||||
onTap: controller.reloadQuota,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: QuotasViewStyles.space),
|
||||
SizedBox(
|
||||
width: QuotasViewStyles.progressBarMaxWidth,
|
||||
child: LinearProgressIndicator(
|
||||
color: octetQuota.getQuotasStateProgressBarColor(),
|
||||
minHeight: QuotasViewStyles.progressBarHeight,
|
||||
backgroundColor: QuotasViewStyles.progressBarBackgroundColor,
|
||||
value: octetQuota.usedStoragePercent,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: QuotasViewStyles.space),
|
||||
Text(
|
||||
octetQuota.getQuotasStateTitle(context),
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: octetQuota.getQuotasStateTitleColor(),
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (isDesktop) {
|
||||
return Center(child: quotasWidget);
|
||||
} else {
|
||||
return quotasWidget;
|
||||
}
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
return const SizedBox(height: 16);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
double _getProgressBarMaxWith(double maxWith) {
|
||||
if (maxWith > QuotasViewStyles.progressBarMaxWidth) {
|
||||
return QuotasViewStyles.progressBarMaxWidth;
|
||||
} else {
|
||||
return maxWith;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,24 +3,13 @@ import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class QuotasViewStyles {
|
||||
static const double padding = 16;
|
||||
static const double margin = 16;
|
||||
static const double bottomPadding = 24;
|
||||
static const double iconPadding = 12;
|
||||
static const double iconSize = 24;
|
||||
static const double labelTextSize = 13;
|
||||
static const double space = 8;
|
||||
static const double progressBarHeight = 3;
|
||||
static const double progressBarMaxWidth = 168;
|
||||
static const double progressStateTextSize = 13;
|
||||
static const double topLineSize = 1;
|
||||
static const double progressBarMaxWidth = 193;
|
||||
|
||||
static const Color labelTextColor = AppColor.steelGray400;
|
||||
static const Color webBackgroundColor = AppColor.colorBgDesktop;
|
||||
static const Color mobileBackgroundColor = Colors.white;
|
||||
static const Color progressBarBackgroundColor = AppColor.colorDivider;
|
||||
static const Color topLineColor = AppColor.colorDividerHorizontal;
|
||||
|
||||
static const FontWeight labelFontWeight = FontWeight.w400;
|
||||
static const FontWeight progressStateFontWeight = FontWeight.w400;
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import 'package:get/get.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/state/search_mailbox_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/mixin/mailbox_widget_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/context_item_mailbox_action.dart';
|
||||
@@ -196,19 +197,20 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
|
||||
}
|
||||
|
||||
List<FocusedMenuItem> _listPopupMenuItemAction(BuildContext context, PresentationMailbox mailbox) {
|
||||
final bool deletedMessageVaultSupported = MailboxUtils.isDeletedMessageVaultSupported(
|
||||
controller.dashboardController.sessionCurrent,
|
||||
controller.dashboardController.accountId.value);
|
||||
final session = controller.dashboardController.sessionCurrent;
|
||||
final accountId = controller.dashboardController.accountId.value;
|
||||
|
||||
final bool subaddressingSupported = MailboxWidgetMixin.isSubaddressingSupported(
|
||||
controller.dashboardController.sessionCurrent,
|
||||
controller.dashboardController.accountId.value);
|
||||
final deletedMessageVaultSupported =
|
||||
MailboxUtils.isDeletedMessageVaultSupported(session, accountId);
|
||||
|
||||
final isSubAddressingSupported =
|
||||
session?.isSubAddressingSupported(accountId) ?? false;
|
||||
|
||||
final contextMenuActions = listContextMenuItemAction(
|
||||
mailbox,
|
||||
controller.dashboardController.enableSpamReport,
|
||||
deletedMessageVaultSupported,
|
||||
subaddressingSupported,
|
||||
isSubAddressingSupported,
|
||||
);
|
||||
return contextMenuActions
|
||||
.map((action) => _mailboxFocusedMenuItem(context, action, mailbox))
|
||||
@@ -262,19 +264,20 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
|
||||
PresentationMailbox mailbox,
|
||||
{RelativeRect? position}
|
||||
) {
|
||||
final bool deletedMessageVaultSupported = MailboxUtils.isDeletedMessageVaultSupported(
|
||||
controller.dashboardController.sessionCurrent,
|
||||
controller.dashboardController.accountId.value);
|
||||
final session = controller.dashboardController.sessionCurrent;
|
||||
final accountId = controller.dashboardController.accountId.value;
|
||||
|
||||
final bool subaddressingSupported = MailboxWidgetMixin.isSubaddressingSupported(
|
||||
controller.dashboardController.sessionCurrent,
|
||||
controller.dashboardController.accountId.value);
|
||||
final deletedMessageVaultSupported =
|
||||
MailboxUtils.isDeletedMessageVaultSupported(session, accountId);
|
||||
|
||||
final isSubAddressingSupported =
|
||||
session?.isSubAddressingSupported(accountId) ?? false;
|
||||
|
||||
final contextMenuActions = listContextMenuItemAction(
|
||||
mailbox,
|
||||
controller.dashboardController.enableSpamReport,
|
||||
deletedMessageVaultSupported,
|
||||
subaddressingSupported,
|
||||
isSubAddressingSupported,
|
||||
);
|
||||
|
||||
if (contextMenuActions.isEmpty) {
|
||||
|
||||
Reference in New Issue
Block a user