diff --git a/assets/images/ic_rename_mailbox.svg b/assets/images/ic_rename_mailbox.svg new file mode 100644 index 000000000..b27f3cd02 --- /dev/null +++ b/assets/images/ic_rename_mailbox.svg @@ -0,0 +1,4 @@ + + + + diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index 33b64b49b..66f6e5e66 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -81,6 +81,7 @@ class ImagePaths { String get icLogoTMailV2 => _getImagePath('logo_tmail_v2.png'); String get icSendToast => _getImagePath('ic_send_toast.svg'); String get icClearTextSearch => _getImagePath('ic_clear_text_search.svg'); + String get icRenameMailbox => _getImagePath('ic_rename_mailbox.svg'); String _getImagePath(String imageName) { return AssetsPaths.images + imageName; diff --git a/core/lib/presentation/views/button/button_builder.dart b/core/lib/presentation/views/button/button_builder.dart index 11e01ce81..656f88080 100644 --- a/core/lib/presentation/views/button/button_builder.dart +++ b/core/lib/presentation/views/button/button_builder.dart @@ -49,20 +49,13 @@ class ButtonBuilder { } Widget build() { - return GestureDetector( - onTap: () { - if (_onPressActionClick != null) { - _onPressActionClick!(); - } - }, + return InkWell( + onTap: () => _onPressActionClick?.call(), child: Container( key: _key, alignment: Alignment.center, - color: Colors.transparent, - child: MediaQuery( - data: MediaQueryData(padding: EdgeInsets.zero), - child: _buildBody() - ) + color: Colors.white, + child: _buildBody() ) ); } @@ -98,7 +91,7 @@ class ButtonBuilder { '${_text ?? ''}', maxLines: 1, overflow: TextOverflow.ellipsis, - style: _textStyle ?? TextStyle(fontSize: 12, color: AppColor.textButtonColor, fontWeight: FontWeight.w500), + style: _textStyle ?? TextStyle(fontSize: 12, color: AppColor.colorTextButton), ); } } \ No newline at end of file diff --git a/lib/features/destination_picker/presentation/destination_picker_controller.dart b/lib/features/destination_picker/presentation/destination_picker_controller.dart index f74345540..ca50aaf6a 100644 --- a/lib/features/destination_picker/presentation/destination_picker_controller.dart +++ b/lib/features/destination_picker/presentation/destination_picker_controller.dart @@ -82,7 +82,7 @@ class DestinationPickerController extends BaseController { final newMailboxNodeList = folderMailboxNodeList.updateNode( selectedMailboxNode.item.id, - selectedMailboxNode.copyWith(newExpandMode: newExpandMode)) ?? []; + selectedMailboxNode.copyWith(newExpandMode: newExpandMode)); folderMailboxNodeList.value = newMailboxNodeList; } diff --git a/lib/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart b/lib/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart index 42454eb9a..d53ed8e8a 100644 --- a/lib/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart +++ b/lib/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart @@ -5,7 +5,7 @@ import 'package:model/mailbox/select_mode.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; extension ListMailboxNodeExtensions on List { - List? updateNode(MailboxId currentMailboxId, MailboxNode newNode) { + List updateNode(MailboxId currentMailboxId, MailboxNode newNode) { return map((MailboxNode child) { if (child.item.id == currentMailboxId) { return newNode; @@ -18,7 +18,7 @@ extension ListMailboxNodeExtensions on List { }).toList(); } - List? toggleSelectMailboxNode(MailboxNode selectedMailboxMode) { + List toggleSelectMailboxNode(MailboxNode selectedMailboxMode) { return map((MailboxNode child) { if (child.item.id == selectedMailboxMode.item.id) { return child.toggleSelectMailboxNode(); @@ -31,7 +31,7 @@ extension ListMailboxNodeExtensions on List { }).toList(); } - List? toSelectMailboxNode({required SelectMode selectMode, ExpandMode? newExpandMode}) { + List toSelectMailboxNode({required SelectMode selectMode, ExpandMode? newExpandMode}) { return map((MailboxNode child) { if (child.hasChildren()) { return child.copyWith( diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 28e17b603..314c15a17 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -22,6 +22,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_mailbo import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/refresh_all_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/search_mailbox_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.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/mailbox_tree_builder.dart'; @@ -193,10 +194,7 @@ class MailboxController extends BaseController { final newMailboxNodeList = folderMailboxNodeList.updateNode( mailboxNode.item.id, mailboxNode.copyWith(newExpandMode: newExpandMode)); - - if (newMailboxNodeList != null) { - folderMailboxNodeList.value = newMailboxNodeList; - } + folderMailboxNodeList.value = newMailboxNodeList; } void _setUpMapMailboxIdDefault(List defaultMailboxList, List folderMailboxList) { @@ -377,6 +375,8 @@ class MailboxController extends BaseController { _cancelSelectMailbox(); } + bool isSelectionEnabled() => currentSelectMode.value == SelectMode.ACTIVE; + void selectMailbox(BuildContext context, PresentationMailbox mailboxSelected) { if (isSearchActive()) { listMailboxSearched.value = listMailboxSearched @@ -395,9 +395,7 @@ class MailboxController extends BaseController { void selectMailboxNode(BuildContext context, MailboxNode mailboxNodeSelected) { final newMailboxNodeList = folderMailboxNodeList.toggleSelectMailboxNode(mailboxNodeSelected); - if (newMailboxNodeList != null) { - folderMailboxNodeList.value = newMailboxNodeList; - } + folderMailboxNodeList.value = newMailboxNodeList; } void _cancelSelectMailbox() { @@ -413,13 +411,47 @@ class MailboxController extends BaseController { final newMailboxNodeList = folderMailboxNodeList.toSelectMailboxNode( selectMode: SelectMode.INACTIVE, newExpandMode: ExpandMode.COLLAPSE); - if (newMailboxNodeList != null) { - folderMailboxNodeList.value = newMailboxNodeList; - } + folderMailboxNodeList.value = newMailboxNodeList; } currentSelectMode.value = SelectMode.INACTIVE; } + List get listMailboxSelected { + if (isSearchActive()) { + return listMailboxSearched + .where((mailbox) => mailbox.selectMode == SelectMode.ACTIVE) + .toList(); + } else { + final defaultMailboxSelected = defaultMailboxList + .where((mailbox) => mailbox.selectMode == SelectMode.ACTIVE) + .toList(); + + final newFolderMailboxTree = MailboxTree(MailboxNode( + MailboxNode.rootItem(), + childrenItems: folderMailboxNodeList)); + final folderMailboxList = allMailboxes.where((mailbox) => !mailbox.hasRole()).toList(); + + final folderMailboxSelected = folderMailboxList + .where((mailbox) { + final node = newFolderMailboxTree.findNode(mailbox.id); + return node != null && node.selectMode == SelectMode.ACTIVE; + }) + .toList(); + + return defaultMailboxSelected + folderMailboxSelected; + } + } + + void pressMailboxSelectionAction(BuildContext context, MailboxActions actions, + List selectionMailbox) { + switch(actions) { + case MailboxActions.delete: + break; + default: + break; + } + } + void closeMailboxScreen(BuildContext context) { mailboxDashBoardController.closeDrawer(); } diff --git a/lib/features/mailbox/presentation/mailbox_view.dart b/lib/features/mailbox/presentation/mailbox_view.dart index b2ff48f11..7a82ef893 100644 --- a/lib/features/mailbox/presentation/mailbox_view.dart +++ b/lib/features/mailbox/presentation/mailbox_view.dart @@ -5,6 +5,7 @@ import 'package:get/get.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/widgets/bottom_bar_selection_mailbox_widget.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_tile_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget_builder.dart'; @@ -43,7 +44,13 @@ class MailboxView extends GetWidget { child: controller.isSearchActive() ? _buildListMailboxSearched(context, controller.listMailboxSearched) : _buildListMailbox(context)), - ))) + ))), + Obx(() => controller.isSelectionEnabled() + ? Column(children: [ + Divider(color: AppColor.lineItemListColor, height: 1, thickness: 0.2), + _buildOptionSelectionBottomBar(context) + ]) + : SizedBox.shrink()), ] ), ) @@ -151,10 +158,12 @@ class MailboxView extends GetWidget { shrinkWrap: true, padding: EdgeInsets.zero, children: [ - _buildUserInformationWidget(context), - Padding( - padding: EdgeInsets.only(top: 16), - child: Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2)), + Obx(() => (controller.isSelectionEnabled() && responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context)) + ? SizedBox.shrink() + : _buildUserInformationWidget(context)), + Obx(() => (controller.isSelectionEnabled() && responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context)) + ? SizedBox.shrink() + : _buildLineSpaceUserInformation()), _buildSearchBarWidget(context), _buildLoadingView(), Obx(() => controller.defaultMailboxList.isNotEmpty @@ -183,6 +192,12 @@ class MailboxView extends GetWidget { ); } + Widget _buildLineSpaceUserInformation() { + return Padding( + padding: EdgeInsets.only(top: 16), + child: Divider(color: AppColor.colorDividerMailbox, height: 0.5, thickness: 0.2)); + } + Widget _buildDefaultMailbox(BuildContext context, List defaultMailbox) { return ListView.builder( padding: EdgeInsets.all(8), @@ -313,4 +328,17 @@ class MailboxView extends GetWidget { ..addOnOpenMailboxAction((mailbox) => controller.openMailbox(context, mailbox))) .build())); } + + Widget _buildOptionSelectionBottomBar(BuildContext context) { + return Padding( + padding: EdgeInsets.only(bottom: 30, top: 5), + child: (BottomBarSelectionMailboxWidget( + context, + imagePaths, + controller.listMailboxSelected) + ..addOnMailboxActionsClick((actions, listMailboxSelected) => + controller.pressMailboxSelectionAction(context, actions, listMailboxSelected))) + .build() + ); + } } \ No newline at end of file diff --git a/lib/features/mailbox/presentation/model/mailbox_actions.dart b/lib/features/mailbox/presentation/model/mailbox_actions.dart index 228a8b0ac..db7972050 100644 --- a/lib/features/mailbox/presentation/model/mailbox_actions.dart +++ b/lib/features/mailbox/presentation/model/mailbox_actions.dart @@ -5,6 +5,7 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; enum MailboxActions { create, moveEmail, + delete, } extension MailboxActionsExtension on MailboxActions { diff --git a/lib/features/mailbox/presentation/widgets/bottom_bar_selection_mailbox_widget.dart b/lib/features/mailbox/presentation/widgets/bottom_bar_selection_mailbox_widget.dart new file mode 100644 index 000000000..cd83a3f42 --- /dev/null +++ b/lib/features/mailbox/presentation/widgets/bottom_bar_selection_mailbox_widget.dart @@ -0,0 +1,89 @@ +import 'package:core/core.dart'; +import 'package:flutter/material.dart'; +import 'package:model/model.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +typedef OnMailboxActionsClick = void Function(MailboxActions, List); + +class BottomBarSelectionMailboxWidget { + + final BuildContext _context; + final ImagePaths _imagePaths; + final List _listSelectionMailbox; + + OnMailboxActionsClick? _onMailboxActionsClick; + + BottomBarSelectionMailboxWidget( + this._context, + this._imagePaths, + this._listSelectionMailbox, + ); + + void addOnMailboxActionsClick(OnMailboxActionsClick onMailboxActionsClick) { + _onMailboxActionsClick = onMailboxActionsClick; + } + + Widget build() { + return Container( + key: Key('bottom_bar_selection_mailbox_widget'), + alignment: Alignment.center, + color: Colors.white, + child: MediaQuery( + data: MediaQueryData(padding: EdgeInsets.zero), + child: SafeArea(child: _buildListOptionButton()) + ) + ); + } + + Widget _buildListOptionButton() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + (ButtonBuilder(_imagePaths.icMoveV2) + ..key(Key('button_move_all_mailbox')) + ..paddingIcon(EdgeInsets.all(8)) + ..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButton.withOpacity(0.3))) + ..iconColor(AppColor.colorTextButton.withOpacity(0.5)) + ..onPressActionClick(() => {}) + ..text(AppLocalizations.of(_context).move, isVertical: true)) + .build(), + (ButtonBuilder(_imagePaths.icRenameMailbox) + ..key(Key('button_rename_mailbox')) + ..paddingIcon(EdgeInsets.all(8)) + ..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButton.withOpacity(0.3))) + ..iconColor(AppColor.colorTextButton.withOpacity(0.5)) + ..onPressActionClick(() => {}) + ..text(AppLocalizations.of(_context).rename, isVertical: true)) + .build(), + (ButtonBuilder(_imagePaths.icReadV2) + ..key(Key('button_mark_read_all_mailbox')) + ..paddingIcon(EdgeInsets.all(8)) + ..textStyle(TextStyle(fontSize: 12, color: AppColor.colorTextButton.withOpacity(0.3))) + ..iconColor(AppColor.colorTextButton.withOpacity(0.5)) + ..onPressActionClick(() => {}) + ..text(AppLocalizations.of(_context).mark_as_read, isVertical: true)) + .build(), + (ButtonBuilder(_imagePaths.icDeleteV2) + ..key(Key('button_delete_all_mailbox')) + ..paddingIcon(EdgeInsets.all(8)) + ..textStyle(TextStyle( + fontSize: 12, + color: _isDeleteMailboxValid ? AppColor.colorTextButton : AppColor.colorTextButton.withOpacity(0.3))) + ..iconColor(_isDeleteMailboxValid ? AppColor.colorTextButton : AppColor.colorTextButton.withOpacity(0.3)) + ..onPressActionClick(() { + if (_isDeleteMailboxValid) { + _onMailboxActionsClick?.call(MailboxActions.delete, _listSelectionMailbox); + } + }) + ..text(AppLocalizations.of(_context).delete, isVertical: true)) + .build() + ] + ); + } + + bool get _isDeleteMailboxValid => _listSelectionMailbox.length == 1 && _isAllFolderMailbox; + + bool get _isAllFolderMailbox => _listSelectionMailbox.every((mailbox) => !mailbox.hasRole()); +} \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 4be9449b4..5eab4c591 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -670,4 +670,10 @@ class AppLocalizations { name: 'hint_input_create_new_mailbox' ); } + + String get rename { + return Intl.message( + 'Rename', + name: 'rename'); + } } \ No newline at end of file