diff --git a/assets/images/ic_create_new_folder.svg b/assets/images/ic_create_new_folder.svg
new file mode 100644
index 000000000..65fd73bab
--- /dev/null
+++ b/assets/images/ic_create_new_folder.svg
@@ -0,0 +1,8 @@
+
diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart
index b6c3a3fb4..77d34b6aa 100644
--- a/core/lib/presentation/extensions/color_extension.dart
+++ b/core/lib/presentation/extensions/color_extension.dart
@@ -154,6 +154,9 @@ extension AppColor on Color {
static const colorEmailAddressFull = Color(0xFF818C99);
static const colorTitleHeaderAttachment = Color(0xFF818C99);
static const colorAttachmentIcon = Color(0xFFAEB7C2);
+ static const colorDividerDestinationPicker = Color(0x1F000000);
+ static const colorItemAlreadySelected = Color(0xFF818C99);
+ static const colorItemSelected = Color(0xFFF2F3F5);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index 0c7cd3fc9..7fbbeb054 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -166,6 +166,7 @@ class ImagePaths {
String get icAppDashboard => _getImagePath('ic_app_dashboard.svg');
String get icRequestReadReceipt => _getImagePath('ic_request_read_receipt.svg');
String get icReadReceiptMessage => _getImagePath('ic_read_receipt_message.svg');
+ String get icCreateNewFolder => _getImagePath('ic_create_new_folder.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
diff --git a/lib/features/base/base_mailbox_controller.dart b/lib/features/base/base_mailbox_controller.dart
index a430aaecf..3745a716c 100644
--- a/lib/features/base/base_mailbox_controller.dart
+++ b/lib/features/base/base_mailbox_controller.dart
@@ -74,6 +74,13 @@ abstract class BaseMailboxController extends BaseController {
}
}
+ void unAllSelectedMailboxNode() {
+ defaultMailboxTree.value.updateNodesUIMode(selectMode: SelectMode.INACTIVE);
+ folderMailboxTree.value.updateNodesUIMode(selectMode: SelectMode.INACTIVE);
+ defaultMailboxTree.refresh();
+ folderMailboxTree.refresh();
+ }
+
MailboxNode? findMailboxNodeById(MailboxId mailboxId) {
final mailboxNode = defaultMailboxTree.value.findNode((node) => node.item.id == mailboxId);
if (mailboxNode != null) {
diff --git a/lib/features/destination_picker/presentation/destination_picker_bindings.dart b/lib/features/destination_picker/presentation/destination_picker_bindings.dart
index bccf76b05..8f64400c6 100644
--- a/lib/features/destination_picker/presentation/destination_picker_bindings.dart
+++ b/lib/features/destination_picker/presentation/destination_picker_bindings.dart
@@ -16,9 +16,12 @@ import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.
import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_isolate_worker.dart';
import 'package:tmail_ui_user/features/mailbox/data/repository/mailbox_repository_impl.dart';
import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart';
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_tree_builder.dart';
+import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
import 'package:tmail_ui_user/features/thread/data/datasource_impl/thread_datasource_impl.dart';
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
@@ -41,6 +44,9 @@ class DestinationPickerBindings extends BaseBindings {
Get.lazyPut(() => DestinationPickerController(
Get.find(),
Get.find(),
+ Get.find(),
+ Get.find(),
+ Get.find(),
Get.find(),
));
}
@@ -66,6 +72,9 @@ class DestinationPickerBindings extends BaseBindings {
void bindingsInteractor() {
Get.lazyPut(() => GetAllMailboxInteractor(Get.find()));
Get.lazyPut(() => SearchMailboxInteractor());
+ Get.lazyPut(() => CreateNewMailboxInteractor(Get.find()));
+ Get.lazyPut(() => RefreshAllMailboxInteractor(Get.find()));
+ Get.lazyPut(() => VerifyNameInteractor());
}
@override
diff --git a/lib/features/destination_picker/presentation/destination_picker_controller.dart b/lib/features/destination_picker/presentation/destination_picker_controller.dart
index e1fe0f740..be8b4df03 100644
--- a/lib/features/destination_picker/presentation/destination_picker_controller.dart
+++ b/lib/features/destination_picker/presentation/destination_picker_controller.dart
@@ -1,53 +1,106 @@
-import 'package:core/core.dart';
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+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/presentation/utils/responsive_utils.dart';
+import 'package:core/utils/build_utils.dart';
import 'package:dartz/dartz.dart';
-import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.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/error/method/error_method_response.dart';
+import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
-import 'package:model/model.dart';
+import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
+import 'package:model/mailbox/expand_mode.dart';
+import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/base/base_mailbox_controller.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
+import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_screen_type.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/state/create_new_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/state/refresh_changes_all_mailboxes_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/search_mailbox_state.dart';
+import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart';
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_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_creator/domain/model/verification/duplicate_name_validator.dart';
+import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/empty_name_validator.dart';
+import 'package:tmail_ui_user/features/mailbox_creator/domain/state/verify_name_view_state.dart';
+import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
+import 'package:tmail_ui_user/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/search_state.dart';
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/route_navigation.dart';
+import 'package:uuid/uuid.dart';
typedef OnSelectedMailboxCallback = Function(PresentationMailbox? destinationMailbox);
class DestinationPickerController extends BaseMailboxController {
+ final _uuid = Get.find();
+ final _appToast = Get.find();
+ final _imagePaths = Get.find();
+ final _responsiveUtils = Get.find();
+
final GetAllMailboxInteractor _getAllMailboxInteractor;
final SearchMailboxInteractor _searchMailboxInteractor;
+ final CreateNewMailboxInteractor _createNewMailboxInteractor;
+ final RefreshAllMailboxInteractor _refreshAllMailboxInteractor;
+ final VerifyNameInteractor _verifyNameInteractor;
final mailboxAction = Rxn();
final listMailboxSearched = [].obs;
final searchState = SearchState.initial().obs;
final searchQuery = SearchQuery.initial().obs;
final mailboxCategoriesExpandMode = MailboxCategoriesExpandMode.initial().obs;
+ final destinationScreenType = DestinationScreenType.destinationPicker.obs;
+ final mailboxDestination = Rxn();
+ final newNameMailbox = Rxn();
+ FocusNode? nameInputFocusNode;
+ TextEditingController? nameInputController;
+ TextEditingController? searchInputController;
+ FocusNode? searchFocus;
DestinationPickerArguments? arguments;
AccountId? accountId;
MailboxId? mailboxIdSelected;
OnSelectedMailboxCallback? onSelectedMailboxCallback;
VoidCallback? onDismissDestinationPicker;
- final searchInputController = TextEditingController();
- final searchFocus = FocusNode();
+ List listMailboxNameAsStringExist = [];
DestinationPickerController(
this._getAllMailboxInteractor,
this._searchMailboxInteractor,
+ this._createNewMailboxInteractor,
+ this._refreshAllMailboxInteractor,
+ this._verifyNameInteractor,
treeBuilder,
) : super(treeBuilder);
+ @override
+ void onInit() {
+ super.onInit();
+ nameInputFocusNode = FocusNode();
+ nameInputController = TextEditingController();
+ searchInputController = TextEditingController();
+ searchFocus = FocusNode();
+ searchFocus?.unfocus();
+ nameInputFocusNode?.unfocus();
+ }
+
@override
void onReady() {
super.onReady();
@@ -69,6 +122,8 @@ class DestinationPickerController extends BaseMailboxController {
} else {
buildTree(success.mailboxList);
}
+ } else if (success is RefreshChangesAllMailboxSuccess) {
+ refreshTree(success.mailboxList);
}
});
}
@@ -79,11 +134,15 @@ class DestinationPickerController extends BaseMailboxController {
(failure) {
if (failure is SearchMailboxFailure) {
_searchMailboxFailure(failure);
+ } else if (failure is CreateNewMailboxFailure) {
+ _createNewMailboxFailure(failure);
}
},
(success) {
if (success is SearchMailboxSuccess) {
_searchMailboxSuccess(success);
+ } else if (success is CreateNewMailboxSuccess) {
+ _createNewMailboxSuccess(success);
}
}
);
@@ -94,8 +153,7 @@ class DestinationPickerController extends BaseMailboxController {
@override
void onClose() {
- searchInputController.dispose();
- searchFocus.dispose();
+ _disposeWidget();
super.onClose();
}
@@ -105,6 +163,12 @@ class DestinationPickerController extends BaseMailboxController {
}
}
+ void _refreshMailboxChanges(jmap.State currentMailboxState) {
+ if (accountId != null) {
+ consumeState(_refreshAllMailboxInteractor.execute(accountId!, currentMailboxState));
+ }
+ }
+
void toggleMailboxCategories(MailboxCategories categories) {
switch(categories) {
case MailboxCategories.exchange:
@@ -128,17 +192,84 @@ class DestinationPickerController extends BaseMailboxController {
searchState.value = searchState.value.enableSearchState();
}
+ void setNewNameMailbox(String newName) => newNameMailbox.value = newName;
+
+ String? getErrorInputNameString(BuildContext context) {
+ final nameMailbox = newNameMailbox.value;
+
+ if (nameInputFocusNode?.hasFocus == false && nameMailbox == null) {
+ return null;
+ }
+
+ return _verifyNameInteractor.execute(
+ nameMailbox,
+ [
+ EmptyNameValidator(),
+ DuplicateNameValidator(listMailboxNameAsStringExist),
+ ]
+ ).fold(
+ (failure) {
+ if (failure is VerifyNameFailure) {
+ return failure.getMessage(context);
+ } else {
+ return null;
+ }
+ },
+ (success) => null
+ );
+ }
+
+ bool isCreateMailboxValidated(BuildContext context) {
+ final nameValidated = getErrorInputNameString(context);
+
+ if (nameInputFocusNode?.hasFocus == false && newNameMailbox.value == null) {
+ return false;
+ }
+
+ if (nameValidated?.isNotEmpty == true) {
+ return false;
+ }
+ return true;
+ }
+
+ void _createListMailboxNameAsStringInMailboxLocation() {
+ if (mailboxDestination.value == null ||
+ mailboxDestination.value == PresentationMailbox.unifiedMailbox) {
+ final allChildrenAtMailboxLocation = (defaultMailboxTree.value.root.childrenItems ?? []) +
+ (folderMailboxTree.value.root.childrenItems ?? []);
+ if (allChildrenAtMailboxLocation.isNotEmpty) {
+ listMailboxNameAsStringExist = allChildrenAtMailboxLocation
+ .where((mailboxNode) => mailboxNode.nameNotEmpty)
+ .map((mailboxNode) => mailboxNode.mailboxNameAsString)
+ .toList();
+ } else {
+ listMailboxNameAsStringExist = [];
+ }
+ } else {
+ final mailboxNodeLocation = findMailboxNodeById(mailboxDestination.value!.id);
+ if (mailboxNodeLocation != null && mailboxNodeLocation.childrenItems?.isNotEmpty == true) {
+ final allChildrenAtMailboxLocation = mailboxNodeLocation.childrenItems!;
+ listMailboxNameAsStringExist = allChildrenAtMailboxLocation
+ .where((mailboxNode) => mailboxNode.nameNotEmpty)
+ .map((mailboxNode) => mailboxNode.mailboxNameAsString)
+ .toList();
+ } else {
+ listMailboxNameAsStringExist = [];
+ }
+ }
+ }
+
void disableSearch(BuildContext context) {
listMailboxSearched.clear();
searchState.value = searchState.value.disableSearchState();
searchQuery.value = SearchQuery.initial();
- searchInputController.clear();
+ searchInputController?.clear();
FocusScope.of(context).unfocus();
}
void clearSearchText() {
searchQuery.value = SearchQuery.initial();
- searchFocus.requestFocus();
+ searchFocus?.requestFocus();
listMailboxSearched.clear();
}
@@ -164,16 +295,166 @@ class DestinationPickerController extends BaseMailboxController {
listMailboxSearched.clear();
}
- void selectMailboxAction(PresentationMailbox? destinationMailbox) {
- if (BuildUtils.isWeb) {
- onSelectedMailboxCallback?.call(destinationMailbox);
+ void openCreateNewMailboxView(BuildContext context) async {
+ if (mailboxDestination.value == null) {
+ _appToast.showBottomToast(
+ currentOverlayContext!,
+ AppLocalizations.of(context).toastMessageErrorNotSelectedFolderWhenCreateNewMailbox,
+ leadingIcon: SvgPicture.asset(
+ _imagePaths.icNotConnection,
+ width: 24,
+ height: 24,
+ color: Colors.white,
+ fit: BoxFit.fill),
+ backgroundColor: AppColor.toastErrorBackgroundColor,
+ textColor: Colors.white,
+ textActionColor: Colors.white,
+ maxWidth: _responsiveUtils.getMaxWidthToast(currentContext!));
} else {
- popBack(result: destinationMailbox);
+ destinationScreenType.value = DestinationScreenType.createNewMailbox;
+ _createListMailboxNameAsStringInMailboxLocation();
}
}
- void closeDestinationPicker() {
+ void _dispatchCreateNewMailboxFolder(
+ AccountId accountId,
+ CreateNewMailboxRequest request
+ ) async {
+ consumeState(_createNewMailboxInteractor.execute(accountId, request));
+ }
+
+ void _createNewMailboxSuccess(CreateNewMailboxSuccess success) {
+ if (currentContext != null) {
+ disableSearch(currentContext!);
+ }
+
+ if (success.currentMailboxState != null) {
+ _refreshMailboxChanges(success.currentMailboxState!);
+ } else {
+ getAllMailboxAction();
+ }
+ }
+
+ void _createNewMailboxFailure(CreateNewMailboxFailure failure) {
+ if (currentOverlayContext != null && currentContext != null) {
+ final exception = failure.exception;
+ var messageError = AppLocalizations.of(currentContext!).create_new_mailbox_failure;
+ if (exception is ErrorMethodResponse) {
+ messageError = exception.description ?? AppLocalizations.of(currentContext!).create_new_mailbox_failure;
+ }
+
+ _appToast.showBottomToast(
+ currentOverlayContext!,
+ messageError,
+ leadingIcon: SvgPicture.asset(
+ _imagePaths.icNotConnection,
+ width: 24,
+ height: 24,
+ color: Colors.white,
+ fit: BoxFit.fill),
+ backgroundColor: AppColor.toastErrorBackgroundColor,
+ textColor: Colors.white,
+ textActionColor: Colors.white,
+ maxWidth: _responsiveUtils.getMaxWidthToast(currentContext!));
+ }
+ }
+
+ void selectMailboxAction(
+ PresentationMailbox? presentationMailbox,
+ {MailboxNode? mailboxNode}
+ ) {
+ if (mailboxDestination.value == presentationMailbox) {
+ return;
+ }
+ mailboxDestination.value = presentationMailbox;
+ if (presentationMailbox == null ||
+ presentationMailbox.id == PresentationMailbox.unifiedMailbox.id) {
+ unAllSelectedMailboxNode();
+ } else {
+ if (mailboxNode != null) {
+ unAllSelectedMailboxNode();
+ selectMailboxNode(mailboxNode);
+ } else {
+ final matchedMailboxNode = findMailboxNodeById(presentationMailbox.id);
+ if (matchedMailboxNode != null) {
+ unAllSelectedMailboxNode();
+ selectMailboxNode(matchedMailboxNode);
+ }
+ }
+ }
+ }
+
+ void dispatchSelectMailboxDestination(BuildContext context) {
+ FocusScope.of(context).unfocus();
+
+ if (mailboxDestination.value == null) {
+ _appToast.showBottomToast(
+ currentOverlayContext!,
+ AppLocalizations.of(context).toastMessageErrorNotSelectedFolderWhenCreateNewMailbox,
+ leadingIcon: SvgPicture.asset(
+ _imagePaths.icNotConnection,
+ width: 24,
+ height: 24,
+ color: Colors.white,
+ fit: BoxFit.fill),
+ backgroundColor: AppColor.toastErrorBackgroundColor,
+ textColor: Colors.white,
+ textActionColor: Colors.white,
+ maxWidth: _responsiveUtils.getMaxWidthToast(currentContext!));
+ return;
+ }
+
if (BuildUtils.isWeb) {
+ _disposeWidget();
+ onSelectedMailboxCallback?.call(mailboxDestination.value);
+ } else {
+ popBack(result: mailboxDestination.value);
+ }
+ }
+
+ void createNewMailboxAction(BuildContext context) {
+ FocusScope.of(context).unfocus();
+
+ final nameMailbox = newNameMailbox.value;
+ if (nameMailbox != null && nameMailbox.isNotEmpty) {
+ final generateCreateId = Id(_uuid.v1());
+ final parentId = mailboxDestination.value == PresentationMailbox.unifiedMailbox
+ ? null
+ : mailboxDestination.value?.id;
+
+ _dispatchCreateNewMailboxFolder(
+ accountId!,
+ CreateNewMailboxRequest(
+ generateCreateId,
+ MailboxName(nameMailbox),
+ parentId: parentId));
+ }
+
+ backToDestinationScreen(context);
+ }
+
+ void backToDestinationScreen(BuildContext context) {
+ nameInputController?.clear();
+ FocusScope.of(context).unfocus();
+ destinationScreenType.value = DestinationScreenType.destinationPicker;
+ }
+
+ void _disposeWidget() {
+ nameInputFocusNode?.dispose();
+ nameInputFocusNode = null;
+ nameInputController?.dispose();
+ nameInputController = null;
+ searchFocus?.dispose();
+ searchFocus = null;
+ searchInputController?.dispose();
+ searchInputController = null;
+ }
+
+ void closeDestinationPicker(BuildContext context) {
+ FocusScope.of(context).unfocus();
+
+ if (BuildUtils.isWeb) {
+ _disposeWidget();
onDismissDestinationPicker?.call();
} else {
popBack();
diff --git a/lib/features/destination_picker/presentation/destination_picker_view.dart b/lib/features/destination_picker/presentation/destination_picker_view.dart
index ef0fdcfef..7abca86af 100644
--- a/lib/features/destination_picker/presentation/destination_picker_view.dart
+++ b/lib/features/destination_picker/presentation/destination_picker_view.dart
@@ -6,6 +6,7 @@ import 'package:core/presentation/utils/style_utils.dart';
import 'package:core/presentation/views/button/icon_button_web.dart';
import 'package:core/presentation/views/list/tree_view.dart';
import 'package:core/presentation/views/search/search_bar_view.dart';
+import 'package:core/presentation/views/text/text_field_builder.dart';
import 'package:core/utils/build_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
@@ -18,6 +19,7 @@ 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/destination_picker/presentation/destination_picker_controller.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
+import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_screen_type.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/widgets/top_bar_destination_picker_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_categories.dart';
@@ -25,6 +27,7 @@ import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_displa
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.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_search_tile_builder.dart';
+import 'package:tmail_ui_user/features/mailbox_creator/presentation/widgets/create_mailbox_name_input_decoration_builder.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -60,7 +63,7 @@ class DestinationPickerView extends GetWidget
return PointerInterceptor(
child: GestureDetector(
- onTap: () => controller.closeDestinationPicker(),
+ onTap: () => controller.closeDestinationPicker(context),
child: Card(
margin: EdgeInsets.zero,
borderOnForeground: false,
@@ -101,11 +104,47 @@ class DestinationPickerView extends GetWidget
right: !BuildUtils.isWeb && _responsiveUtils.isLandscapeMobile(context),
child: Column(children: [
Obx(() => TopBarDestinationPickerBuilder(
- controller.mailboxAction.value,
- onCloseAction: () => controller.closeDestinationPicker())),
- Obx(() => controller.isSearchActive()
- ? _buildInputSearchFormWidget(context)
- : const SizedBox.shrink()),
+ controller.mailboxAction.value,
+ controller.destinationScreenType.value,
+ mailboxIdDestination: controller.mailboxDestination.value?.id,
+ isCreateMailboxValidated: controller.isCreateMailboxValidated(context),
+ onCloseAction: () =>
+ controller.closeDestinationPicker(context),
+ onBackToAction: () =>
+ controller.backToDestinationScreen(context),
+ onSelectedMailboxDestinationAction: () =>
+ controller.dispatchSelectMailboxDestination(context),
+ onCreateNewMailboxAction: () =>
+ controller.createNewMailboxAction(context),
+ onOpenCreateNewMailboxScreenAction: () =>
+ controller.openCreateNewMailboxView(context))),
+ const Divider(
+ color: AppColor.colorDividerDestinationPicker,
+ height: 1),
+ Obx(() {
+ if (controller.destinationScreenType.value == DestinationScreenType.destinationPicker) {
+ return controller.isSearchActive()
+ ? _buildInputSearchFormWidget(context)
+ : const SizedBox.shrink();
+ } else {
+ return Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ _buildCreateMailboxNameInput(context),
+ Padding(
+ padding: const EdgeInsets.only(left: 24, right: 24, bottom: 12),
+ child: Text(
+ AppLocalizations.of(context).selectParentFolder,
+ textAlign: TextAlign.left,
+ style: const TextStyle(
+ fontSize: 13,
+ color: AppColor.colorHintSearchBar,
+ fontWeight: FontWeight.normal)),
+ )
+ ]);
+ }
+ }),
Expanded(child: Container(
color: Colors.white,
child: RefreshIndicator(
@@ -126,6 +165,29 @@ class DestinationPickerView extends GetWidget
);
}
+ Widget _buildCreateMailboxNameInput(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
+ child: Obx(() => (TextFieldBuilder()
+ ..key(const Key('create_mailbox_name_input'))
+ ..onChange((value) => controller.setNewNameMailbox(value))
+ ..keyboardType(TextInputType.visiblePassword)
+ ..cursorColor(AppColor.colorTextButton)
+ ..addController(controller.nameInputController)
+ ..maxLines(1)
+ ..textStyle(const TextStyle(
+ color: AppColor.colorNameEmail,
+ fontSize: 16,
+ overflow: CommonTextStyle.defaultTextOverFlow))
+ ..addFocusNode(controller.nameInputFocusNode)
+ ..textDecoration((CreateMailboxNameInputDecorationBuilder()
+ ..setHintText(AppLocalizations.of(context).hint_input_create_new_mailbox)
+ ..setErrorText(controller.getErrorInputNameString(context)))
+ .build()))
+ .build())
+ );
+ }
+
Widget _buildLoadingView() {
return Obx(() => controller.viewState.value.fold(
(failure) => const SizedBox.shrink(),
@@ -144,7 +206,8 @@ class DestinationPickerView extends GetWidget
return SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Column(children: [
- if (actions?.canSearch() == true)
+ if (actions?.canSearch() == true &&
+ controller.destinationScreenType.value == DestinationScreenType.destinationPicker)
SearchBarView(
_imagePaths,
margin: const EdgeInsets.all(12),
@@ -154,21 +217,21 @@ class DestinationPickerView extends GetWidget
if (actions?.hasAllMailboxDefault() == true)
_buildAllMailboxes(context, actions, mailboxIdSelected),
Obx(() => controller.defaultMailboxHasChild
- ? _buildMailboxCategory(
- context,
- MailboxCategories.exchange,
- controller.defaultRootNode,
- actions,
- mailboxIdSelected)
- : const SizedBox.shrink()),
+ ? _buildMailboxCategory(
+ context,
+ MailboxCategories.exchange,
+ controller.defaultRootNode,
+ actions,
+ mailboxIdSelected)
+ : const SizedBox.shrink()),
Obx(() => controller.folderMailboxHasChild
- ? _buildMailboxCategory(
- context,
- MailboxCategories.folders,
- controller.folderRootNode,
- actions,
- mailboxIdSelected)
- : const SizedBox.shrink()),
+ ? _buildMailboxCategory(
+ context,
+ MailboxCategories.folders,
+ controller.folderRootNode,
+ actions,
+ mailboxIdSelected)
+ : const SizedBox.shrink()),
const SizedBox(height: 12),
])
);
@@ -182,15 +245,17 @@ class DestinationPickerView extends GetWidget
MailboxId? mailboxIdSelected
) {
return Container(
- color: Colors.white,
- child: TreeView(
- key: Key('${categories.keyValue}_mailbox_list'),
- children: _buildListChildTileWidget(
- context,
- mailboxNode,
- mailboxIdSelected,
- lastNode: mailboxNode.childrenItems?.last,
- actions: actions)));
+ color: Colors.white,
+ child: TreeView(
+ key: Key('${categories.keyValue}_mailbox_list'),
+ children: _buildListChildTileWidget(
+ context,
+ mailboxNode,
+ mailboxIdSelected,
+ lastNode: mailboxNode.childrenItems?.last,
+ actions: actions)
+ )
+ );
}
List _buildListChildTileWidget(
@@ -203,34 +268,41 @@ class DestinationPickerView extends GetWidget
}
) {
return parentNode.childrenItems
- ?.map((mailboxNode) => mailboxNode.hasChildren()
- ? TreeViewChild(
- context,
- key: const Key('children_tree_mailbox_child'),
- isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
- parent: (MailBoxFolderTileBuilder(
- context,
- _imagePaths,
- mailboxNode,
- lastNode: lastNode,
- mailboxActions: actions,
- mailboxIdSelected: mailboxIdSelected,
- mailboxDisplayed: MailboxDisplayed.destinationPicker)
- ..addOnOpenMailboxFolderClick(_handleOpenMailboxClick)
- ..addOnExpandFolderActionClick((mailboxNode) => controller.toggleMailboxFolder(mailboxNode)))
- .build(),
- children: _buildListChildTileWidget(context, mailboxNode, mailboxIdSelected, actions: actions)
- ).build()
- : (MailBoxFolderTileBuilder(
- context,
- _imagePaths,
- mailboxNode,
- lastNode: lastNode,
- mailboxDisplayed: MailboxDisplayed.destinationPicker,
- mailboxIdSelected: mailboxIdSelected,
- mailboxActions: actions)
- ..addOnOpenMailboxFolderClick(_handleOpenMailboxClick))
- .build())
+ ?.map((mailboxNode) {
+ if (mailboxNode.hasChildren()) {
+ return TreeViewChild(
+ context,
+ key: const Key('children_tree_mailbox_child'),
+ isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
+ parent: (MailBoxFolderTileBuilder(
+ context,
+ _imagePaths,
+ mailboxNode,
+ lastNode: lastNode,
+ mailboxActions: actions,
+ mailboxIdAlreadySelected: mailboxIdSelected,
+ mailboxDisplayed: MailboxDisplayed.destinationPicker)
+ ..addOnOpenMailboxFolderClick(_handleOpenMailboxNodeClick)
+ ..addOnExpandFolderActionClick((mailboxNode) => controller.toggleMailboxFolder(mailboxNode))
+ ).build(),
+ children: _buildListChildTileWidget(
+ context,
+ mailboxNode,
+ mailboxIdSelected,
+ actions: actions)
+ ).build();
+ } else {
+ return (MailBoxFolderTileBuilder(
+ context,
+ _imagePaths,
+ mailboxNode,
+ lastNode: lastNode,
+ mailboxDisplayed: MailboxDisplayed.destinationPicker,
+ mailboxIdAlreadySelected: mailboxIdSelected,
+ mailboxActions: actions)
+ ..addOnOpenMailboxFolderClick(_handleOpenMailboxNodeClick)
+ ).build();
+ }})
.toList() ?? [];
}
@@ -250,7 +322,6 @@ class DestinationPickerView extends GetWidget
color: Colors.white)
: null,
child: ListView.builder(
- padding: const EdgeInsets.only(left: 16, right: 8),
key: const Key('list_mailbox_searched'),
itemCount: controller.listMailboxSearched.length,
shrinkWrap: true,
@@ -262,10 +333,11 @@ class DestinationPickerView extends GetWidget
_responsiveUtils,
controller.listMailboxSearched[index],
mailboxActions: actions,
- mailboxIdSelected: mailboxIdSelected,
+ mailboxIdAlreadySelected: mailboxIdSelected,
mailboxDisplayed: MailboxDisplayed.destinationPicker,
- lastMailbox: controller.listMailboxSearched.last)
- ..addOnOpenMailboxAction((mailbox) => controller.selectMailboxAction(mailbox)))
+ mailboxIdDestination: controller.mailboxDestination.value?.id)
+ ..addOnOpenMailboxAction((mailbox) =>
+ _handleOpenPresentationMailboxClick(context, mailbox)))
.build())
)
));
@@ -276,47 +348,54 @@ class DestinationPickerView extends GetWidget
MailboxActions? actions,
MailboxId? mailboxIdSelected
) {
- return Material(
+ return Obx(() {
+ return Material(
color: Colors.transparent,
child: InkWell(
- onTap: () => controller.selectMailboxAction(PresentationMailbox.unifiedMailbox),
+ onTap: () => _handleOpenPresentationMailboxClick(
+ context,
+ PresentationMailbox.unifiedMailbox),
child: Container(
- padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
- child: Row(children: [
- SvgPicture.asset(
- _imagePaths.icFolderMailbox,
- width: BuildUtils.isWeb ? 20 : 24,
- height: BuildUtils.isWeb ? 20 : 24,
+ padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
+ color: controller.mailboxDestination.value == PresentationMailbox.unifiedMailbox
+ ? AppColor.colorItemSelected
+ : Colors.transparent,
+ child: Row(children: [
+ SvgPicture.asset(
+ _imagePaths.icFolderMailbox,
+ width: BuildUtils.isWeb ? 20 : 24,
+ height: BuildUtils.isWeb ? 20 : 24,
+ fit: BoxFit.fill),
+ const SizedBox(width: 8),
+ Expanded(child: Text(
+ AppLocalizations.of(context).allMailboxes,
+ maxLines: 1,
+ softWrap: CommonTextStyle.defaultSoftWrap,
+ overflow: CommonTextStyle.defaultTextOverFlow,
+ style: const TextStyle(
+ fontSize: 15,
+ color: AppColor.colorNameEmail,
+ fontWeight: FontWeight.normal),
+ )),
+ const SizedBox(width: 8),
+ if (actions == MailboxActions.select && (mailboxIdSelected == null ||
+ mailboxIdSelected == PresentationMailbox.unifiedMailbox.id))
+ Padding(
+ padding: const EdgeInsets.only(right: 30.0),
+ child: SvgPicture.asset(
+ _imagePaths.icFilterSelected,
+ width: 20,
+ height: 20,
fit: BoxFit.fill),
- const SizedBox(width: 8),
- Expanded(child: Text(
- AppLocalizations.of(context).allMailboxes,
- maxLines: 1,
- softWrap: CommonTextStyle.defaultSoftWrap,
- overflow: CommonTextStyle.defaultTextOverFlow,
- style: const TextStyle(
- fontSize: 15,
- color: AppColor.colorNameEmail,
- fontWeight: FontWeight.normal),
- )),
- const SizedBox(width: 8),
- if (actions == MailboxActions.select && (mailboxIdSelected == null ||
- mailboxIdSelected == PresentationMailbox.unifiedMailbox.id))
- Padding(
- padding: const EdgeInsets.only(right: 30.0),
- child: SvgPicture.asset(
- _imagePaths.icFilterSelected,
- width: 20,
- height: 20,
- fit: BoxFit.fill),
- )
- ])
+ )
+ ])
),
),
);
+ });
}
- void _handleOpenMailboxClick(MailboxNode mailboxNode) {
+ void _handleOpenMailboxNodeClick(MailboxNode mailboxNode) {
PresentationMailbox presentationMailbox;
final path = controller.findNodePath(mailboxNode.item.id)
?? mailboxNode.item.name?.name;
@@ -326,13 +405,33 @@ class DestinationPickerView extends GetWidget
} else {
presentationMailbox = mailboxNode.item;
}
- controller.selectMailboxAction(presentationMailbox);
+ controller.selectMailboxAction(presentationMailbox, mailboxNode: mailboxNode);
+ }
+
+ void _handleOpenPresentationMailboxClick(
+ BuildContext context,
+ PresentationMailbox presentationMailbox
+ ) {
+ PresentationMailbox newPresentationMailbox;
+ if (presentationMailbox.id == PresentationMailbox.unifiedMailbox.id) {
+ newPresentationMailbox = presentationMailbox
+ .toPresentationMailboxWithMailboxPath(AppLocalizations.of(context).allMailboxes);
+ } else {
+ final path = controller.findNodePath(presentationMailbox.id)
+ ?? presentationMailbox.name?.name;
+ if (path != null) {
+ newPresentationMailbox = presentationMailbox.toPresentationMailboxWithMailboxPath(path);
+ } else {
+ newPresentationMailbox = presentationMailbox;
+ }
+ }
+
+ controller.selectMailboxAction(newPresentationMailbox);
}
Widget _buildInputSearchFormWidget(BuildContext context) {
return Padding(
- padding: const EdgeInsets.symmetric(
- vertical: BuildUtils.isWeb ? 0 : 16),
+ padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
children: [
Padding(padding: const EdgeInsets.only(left: 5), child: buildIconWeb(
diff --git a/lib/features/destination_picker/presentation/model/destination_screen_type.dart b/lib/features/destination_picker/presentation/model/destination_screen_type.dart
new file mode 100644
index 000000000..066f95f7d
--- /dev/null
+++ b/lib/features/destination_picker/presentation/model/destination_screen_type.dart
@@ -0,0 +1,17 @@
+
+import 'package:flutter/cupertino.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+enum DestinationScreenType {
+ destinationPicker,
+ createNewMailbox;
+
+ String getTitle(BuildContext context, String mailboxActionTitle) {
+ switch(this) {
+ case DestinationScreenType.destinationPicker:
+ return mailboxActionTitle;
+ case DestinationScreenType.createNewMailbox:
+ return AppLocalizations.of(context).createNewMailbox;
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/features/destination_picker/presentation/widgets/top_bar_destination_picker_builder.dart b/lib/features/destination_picker/presentation/widgets/top_bar_destination_picker_builder.dart
index 7c526b39c..1562a214f 100644
--- a/lib/features/destination_picker/presentation/widgets/top_bar_destination_picker_builder.dart
+++ b/lib/features/destination_picker/presentation/widgets/top_bar_destination_picker_builder.dart
@@ -3,26 +3,46 @@ import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
+import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
+import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_screen_type.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+typedef OnCreateNewMailboxAction = Function();
+typedef OnOpenCreateNewMailboxScreenAction = Function();
+typedef OnSelectedMailboxDestinationAction = Function();
+
class TopBarDestinationPickerBuilder extends StatelessWidget {
+ final _imagePaths = Get.find();
+
final MailboxActions? _mailboxAction;
final VoidCallback? onCloseAction;
+ final VoidCallback? onBackToAction;
+ final OnCreateNewMailboxAction? onCreateNewMailboxAction;
+ final OnOpenCreateNewMailboxScreenAction? onOpenCreateNewMailboxScreenAction;
+ final OnSelectedMailboxDestinationAction? onSelectedMailboxDestinationAction;
+ final DestinationScreenType _destinationScreenType;
+ final MailboxId? mailboxIdDestination;
+ final bool isCreateMailboxValidated;
- const TopBarDestinationPickerBuilder(
- this._mailboxAction,
- {
- Key? key,
- this.onCloseAction,
- }
+ TopBarDestinationPickerBuilder(
+ this._mailboxAction,
+ this._destinationScreenType,
+ {
+ Key? key,
+ this.mailboxIdDestination,
+ this.isCreateMailboxValidated = false,
+ this.onCloseAction,
+ this.onBackToAction,
+ this.onCreateNewMailboxAction,
+ this.onOpenCreateNewMailboxScreenAction,
+ this.onSelectedMailboxDestinationAction,
+ }
) : super(key: key);
@override
Widget build(BuildContext context) {
- final _imagePaths = Get.find();
-
return Container(
color: Colors.white,
height: 52,
@@ -30,7 +50,7 @@ class TopBarDestinationPickerBuilder extends StatelessWidget {
children: [
Center(
child: Text(
- _mailboxAction?.getTitle(context) ?? '',
+ _destinationScreenType.getTitle(context, _mailboxAction?.getTitle(context) ?? ''),
maxLines: 1,
softWrap: CommonTextStyle.defaultSoftWrap,
overflow: CommonTextStyle.defaultTextOverFlow,
@@ -39,11 +59,12 @@ class TopBarDestinationPickerBuilder extends StatelessWidget {
fontSize: 20,
color: Colors.black,
fontWeight: FontWeight.w700))),
- Padding(
- padding: const EdgeInsets.only(left: 8.0),
- child: Align(
- alignment: Alignment.centerLeft,
- child: buildIconWeb(
+ if (_destinationScreenType == DestinationScreenType.destinationPicker)
+ Padding(
+ padding: const EdgeInsets.only(left: 8.0),
+ child: Align(
+ alignment: Alignment.centerLeft,
+ child: buildIconWeb(
iconSize: 24,
colorSelected: Colors.white,
splashRadius: 15,
@@ -51,10 +72,125 @@ class TopBarDestinationPickerBuilder extends StatelessWidget {
icon: SvgPicture.asset(_imagePaths.icComposerClose, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () => onCloseAction?.call()),
+ ),
+ )
+ else
+ Padding(
+ padding: const EdgeInsets.only(left: 8.0),
+ child: Align(
+ alignment: Alignment.centerLeft,
+ child: Material(
+ color: Colors.transparent,
+ child: InkWell(
+ onTap: onBackToAction,
+ customBorder: const RoundedRectangleBorder(
+ borderRadius: BorderRadius.all(Radius.circular(8))),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 8,
+ horizontal: 8),
+ child: Row(mainAxisSize: MainAxisSize.min, children: [
+ SvgPicture.asset(
+ _imagePaths.icBack,
+ width: 14,
+ height: 14,
+ color: AppColor.primaryColor,
+ fit: BoxFit.fill),
+ const SizedBox(width: 5),
+ Text(
+ AppLocalizations.of(context).back,
+ maxLines: 1,
+ softWrap: CommonTextStyle.defaultSoftWrap,
+ overflow: CommonTextStyle.defaultTextOverFlow,
+ textAlign: TextAlign.center,
+ style: const TextStyle(
+ fontSize: 15,
+ color: AppColor.colorTextButton,
+ fontWeight: FontWeight.normal))
+ ]),
+ ),
+ ),
+ ),
+ ),
),
- ),
+ Align(
+ alignment: Alignment.centerRight,
+ child: Row(mainAxisSize: MainAxisSize.min, children: [
+ if (_destinationScreenType == DestinationScreenType.destinationPicker &&
+ _mailboxAction != MailboxActions.create)
+ _buildIconCreateButton(context),
+ if (_destinationScreenType == DestinationScreenType.destinationPicker)
+ _buildDoneButton(context)
+ else
+ _buildSaveButton(context),
+ const SizedBox(width: 8)
+ ]),
+ )
]
),
);
}
+
+ Widget _buildIconCreateButton(BuildContext context) {
+ return buildIconWeb(
+ iconSize: 24,
+ colorSelected: Colors.white,
+ splashRadius: 15,
+ iconPadding: const EdgeInsets.all(3),
+ icon: SvgPicture.asset(
+ _imagePaths.icCreateNewFolder,
+ color: mailboxIdDestination != null
+ ? AppColor.colorTextButton
+ : AppColor.colorDisableMailboxCreateButton,
+ fit: BoxFit.fill),
+ tooltip: AppLocalizations.of(context).create,
+ onTap: onOpenCreateNewMailboxScreenAction
+ );
+ }
+
+ Widget _buildDoneButton(BuildContext context) {
+ return Material(
+ color: Colors.transparent,
+ child: InkWell(
+ customBorder: const RoundedRectangleBorder(
+ borderRadius: BorderRadius.all(Radius.circular(8))),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 8,
+ horizontal: 8),
+ child: Text(
+ AppLocalizations.of(context).done,
+ style: TextStyle(
+ fontSize: 15,
+ color: mailboxIdDestination != null
+ ? AppColor.colorTextButton
+ : AppColor.colorDisableMailboxCreateButton))),
+ onTap: onSelectedMailboxDestinationAction
+ )
+ );
+ }
+
+ Widget _buildSaveButton(BuildContext context) {
+ return Material(
+ color: Colors.transparent,
+ child: InkWell(
+ customBorder: const RoundedRectangleBorder(
+ borderRadius: BorderRadius.all(Radius.circular(8))),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 8,
+ horizontal: 8),
+ child: Text(
+ AppLocalizations.of(context).save,
+ style: TextStyle(
+ fontSize: 15,
+ color: isCreateMailboxValidated
+ ? AppColor.colorTextButton
+ : AppColor.colorDisableMailboxCreateButton)
+ )
+ ),
+ onTap: isCreateMailboxValidated ? onCreateNewMailboxAction : null
+ )
+ );
+ }
}
\ No newline at end of file
diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart
index b79e872b3..4b82c2f22 100644
--- a/lib/features/mailbox/presentation/mailbox_controller.dart
+++ b/lib/features/mailbox/presentation/mailbox_controller.dart
@@ -529,8 +529,7 @@ class MailboxController extends BaseMailboxController {
.map((mailbox) => mailbox.toSelectedPresentationMailbox(selectMode: SelectMode.INACTIVE))
.toList();
} else {
- defaultMailboxTree.value.updateNodesUIMode(selectMode: SelectMode.INACTIVE);
- folderMailboxTree.value.updateNodesUIMode(selectMode: SelectMode.INACTIVE);
+ unAllSelectedMailboxNode();
}
currentSelectMode.value = SelectMode.INACTIVE;
}
diff --git a/lib/features/mailbox/presentation/mailbox_view.dart b/lib/features/mailbox/presentation/mailbox_view.dart
index 11f5efbef..a3a52c0e2 100644
--- a/lib/features/mailbox/presentation/mailbox_view.dart
+++ b/lib/features/mailbox/presentation/mailbox_view.dart
@@ -361,7 +361,7 @@ class MailboxView extends GetWidget {
_responsiveUtils,
controller.listMailboxSearched[index],
allSelectMode: controller.currentSelectMode.value,
- lastMailbox: controller.listMailboxSearched.last)
+ lastMailboxIdInSearchedList: controller.listMailboxSearched.last.id)
..addOnOpenMailboxAction((mailbox) => controller.openMailbox(context, mailbox))
..addOnSelectMailboxActionClick((mailbox) => controller.selectMailboxSearched(context, mailbox)))
.build())
diff --git a/lib/features/mailbox/presentation/mailbox_view_web.dart b/lib/features/mailbox/presentation/mailbox_view_web.dart
index f427268bb..f7bd4bd9f 100644
--- a/lib/features/mailbox/presentation/mailbox_view_web.dart
+++ b/lib/features/mailbox/presentation/mailbox_view_web.dart
@@ -361,8 +361,7 @@ class MailboxView extends GetWidget with AppLoaderMixin, Popu
context,
_imagePaths,
_responsiveUtils,
- listMailbox[index],
- lastMailbox: controller.listMailboxSearched.last)
+ listMailbox[index])
..addOnDragItemAccepted(controller.mailboxDashBoardController.dragSelectedMultipleEmailToMailboxAction)
..addOnOpenMailboxAction((mailbox) => controller.openMailbox(context, mailbox))
..addOnMenuActionClick((position, mailbox) => _openMailboxMenuAction(context, position, mailbox))
diff --git a/lib/features/mailbox/presentation/model/mailbox_node.dart b/lib/features/mailbox/presentation/model/mailbox_node.dart
index bbfe686fd..d454e4e24 100644
--- a/lib/features/mailbox/presentation/model/mailbox_node.dart
+++ b/lib/features/mailbox/presentation/model/mailbox_node.dart
@@ -23,6 +23,8 @@ class MailboxNode with EquatableMixin{
bool get isActivated => nodeState == MailboxState.activated;
+ bool get isSelected => selectMode == SelectMode.ACTIVE;
+
MailboxNode(
this.item,
{
diff --git a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart
index be69f2512..9456dcb50 100644
--- a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart
+++ b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart
@@ -28,7 +28,7 @@ class MailBoxFolderTileBuilder {
final MailboxNode? lastNode;
final PresentationMailbox? mailboxNodeSelected;
final MailboxActions? mailboxActions;
- final MailboxId? mailboxIdSelected;
+ final MailboxId? mailboxIdAlreadySelected;
OnExpandFolderActionClick? _onExpandFolderActionClick;
OnOpenMailboxFolderClick? _onOpenMailboxFolderClick;
@@ -48,7 +48,7 @@ class MailBoxFolderTileBuilder {
this.lastNode,
this.mailboxNodeSelected,
this.mailboxActions,
- this.mailboxIdSelected,
+ this.mailboxIdAlreadySelected
}
);
@@ -159,8 +159,10 @@ class MailBoxFolderTileBuilder {
child: InkWell(
onTap: () => _onOpenMailboxFolderClick?.call(_mailboxNode),
child: Container(
- color: Colors.transparent,
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
+ color: mailboxDisplayed == MailboxDisplayed.destinationPicker && _mailboxNode.isSelected
+ ? AppColor.colorItemSelected
+ : Colors.transparent,
child: Row(children: [
_buildLeadingMailboxItem(),
const SizedBox(width: 8),
@@ -399,7 +401,7 @@ class MailBoxFolderTileBuilder {
}
Widget _buildSelectedIcon() {
- if (_mailboxNode.item.id == mailboxIdSelected &&
+ if (_mailboxNode.item.id == mailboxIdAlreadySelected &&
mailboxDisplayed == MailboxDisplayed.destinationPicker &&
(mailboxActions == MailboxActions.select ||
mailboxActions == MailboxActions.create)) {
diff --git a/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart b/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart
index 395151ce6..930d59b68 100644
--- a/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart
+++ b/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart
@@ -15,14 +15,15 @@ typedef OnDragItemAccepted = void Function(List, Presentation
class MailboxSearchTileBuilder {
final PresentationMailbox _presentationMailbox;
- final PresentationMailbox? lastMailbox;
final SelectMode allSelectMode;
final ImagePaths _imagePaths;
final ResponsiveUtils _responsiveUtils;
final BuildContext _context;
final MailboxDisplayed mailboxDisplayed;
final MailboxActions? mailboxActions;
- final MailboxId? mailboxIdSelected;
+ final MailboxId? mailboxIdAlreadySelected;
+ final MailboxId? lastMailboxIdInSearchedList;
+ final MailboxId? mailboxIdDestination;
bool isHoverItem = false;
@@ -38,10 +39,11 @@ class MailboxSearchTileBuilder {
this._presentationMailbox,
{
this.allSelectMode = SelectMode.INACTIVE,
- this.lastMailbox,
+ this.lastMailboxIdInSearchedList,
this.mailboxDisplayed = MailboxDisplayed.mailbox,
this.mailboxActions,
- this.mailboxIdSelected,
+ this.mailboxIdAlreadySelected,
+ this.mailboxIdDestination,
}
);
@@ -111,19 +113,28 @@ class MailboxSearchTileBuilder {
absorbing: !_presentationMailbox.isActivated,
child: Opacity(
opacity: _presentationMailbox.isActivated ? 1.0 : 0.3,
- child: ListTile(
- contentPadding: EdgeInsets.zero,
- onTap: () => allSelectMode == SelectMode.ACTIVE
- ? _onSelectMailboxActionClick?.call(_presentationMailbox)
- : _onOpenMailboxActionClick?.call(_presentationMailbox),
- leading: _buildLeadingIcon(),
- title: _buildTitleItem(),
- subtitle: _buildSubtitleItem(),
- trailing: _buildSelectedIcon(),
+ child: Container(
+ color: _presentationMailbox.id == mailboxIdDestination &&
+ mailboxDisplayed == MailboxDisplayed.destinationPicker
+ ? AppColor.colorItemSelected
+ : Colors.transparent,
+ padding: mailboxDisplayed == MailboxDisplayed.destinationPicker
+ ? const EdgeInsets.only(left: 16, right: 8)
+ : EdgeInsets.zero,
+ child: ListTile(
+ contentPadding: EdgeInsets.zero,
+ onTap: () => allSelectMode == SelectMode.ACTIVE
+ ? _onSelectMailboxActionClick?.call(_presentationMailbox)
+ : _onOpenMailboxActionClick?.call(_presentationMailbox),
+ leading: _buildLeadingIcon(),
+ title: _buildTitleItem(),
+ subtitle: _buildSubtitleItem(),
+ trailing: _buildSelectedIcon(),
+ ),
),
),
),
- if (lastMailbox?.id != _presentationMailbox.id)
+ if (lastMailboxIdInSearchedList != _presentationMailbox.id)
Padding(
padding: EdgeInsets.only(left: allSelectMode == SelectMode.ACTIVE ? 50 : 35),
child: const Divider(color: AppColor.lineItemListColor, height: 0.5, thickness: 0.2)),
@@ -221,21 +232,26 @@ class MailboxSearchTileBuilder {
}
Color get backgroundColorItem {
- if (isHoverItem) {
- return AppColor.colorBgMailboxSelected;
+ if (_presentationMailbox.id == mailboxIdDestination &&
+ mailboxDisplayed == MailboxDisplayed.destinationPicker) {
+ return AppColor.colorItemSelected;
} else {
- if (mailboxDisplayed == MailboxDisplayed.mailbox) {
- return _responsiveUtils.isDesktop(_context)
- ? AppColor.colorBgDesktop
- : Colors.white;
+ if (isHoverItem) {
+ return AppColor.colorBgMailboxSelected;
} else {
- return Colors.white;
+ if (mailboxDisplayed == MailboxDisplayed.mailbox) {
+ return _responsiveUtils.isDesktop(_context)
+ ? AppColor.colorBgDesktop
+ : Colors.white;
+ } else {
+ return Colors.white;
+ }
}
}
}
Widget? _buildSelectedIcon() {
- if (_presentationMailbox.id == mailboxIdSelected &&
+ if (_presentationMailbox.id == mailboxIdAlreadySelected &&
mailboxDisplayed == MailboxDisplayed.destinationPicker &&
(mailboxActions == MailboxActions.select ||
mailboxActions == MailboxActions.create)) {
diff --git a/lib/features/mailbox_creator/presentation/mailbox_creator_controller.dart b/lib/features/mailbox_creator/presentation/mailbox_creator_controller.dart
index c2a324fe5..3508ed4b8 100644
--- a/lib/features/mailbox_creator/presentation/mailbox_creator_controller.dart
+++ b/lib/features/mailbox_creator/presentation/mailbox_creator_controller.dart
@@ -30,6 +30,7 @@ class MailboxCreatorController extends BaseController {
final newNameMailbox = Rxn();
FocusNode? nameInputFocusNode;
+ TextEditingController? nameInputController;
MailboxCreatorArguments? arguments;
AccountId? accountId;
@@ -48,12 +49,12 @@ class MailboxCreatorController extends BaseController {
void onInit() {
super.onInit();
nameInputFocusNode = FocusNode();
+ nameInputController = TextEditingController();
}
@override
void onReady() {
super.onReady();
- log('MailboxCreatorController::onReady(): ');
if (arguments != null) {
folderMailboxTree = arguments!.folderMailboxTree;
defaultMailboxTree = arguments!.defaultMailboxTree;
@@ -71,7 +72,7 @@ class MailboxCreatorController extends BaseController {
@override
void onClose() {
- nameInputFocusNode?.dispose();
+ _disposeWidget();
super.onClose();
}
@@ -184,6 +185,13 @@ class MailboxCreatorController extends BaseController {
}
}
+ void _disposeWidget() {
+ nameInputFocusNode?.dispose();
+ nameInputFocusNode = null;
+ nameInputController?.dispose();
+ nameInputController = null;
+ }
+
void createNewMailbox(BuildContext context) {
FocusScope.of(context).unfocus();
@@ -194,9 +202,7 @@ class MailboxCreatorController extends BaseController {
mailboxLocation: selectedMailbox.value);
if (BuildUtils.isWeb) {
- nameInputFocusNode?.dispose();
- nameInputFocusNode = null;
-
+ _disposeWidget();
onCreatedMailboxCallback?.call(newMailboxArguments);
} else {
popBack(result: newMailboxArguments);
@@ -208,9 +214,7 @@ class MailboxCreatorController extends BaseController {
FocusScope.of(context).unfocus();
if (BuildUtils.isWeb) {
- nameInputFocusNode?.dispose();
- nameInputFocusNode = null;
-
+ _disposeWidget();
onDismissMailboxCreator?.call();
} else {
popBack();
diff --git a/lib/features/mailbox_creator/presentation/mailbox_creator_view.dart b/lib/features/mailbox_creator/presentation/mailbox_creator_view.dart
index e90bbddd8..91f97e035 100644
--- a/lib/features/mailbox_creator/presentation/mailbox_creator_view.dart
+++ b/lib/features/mailbox_creator/presentation/mailbox_creator_view.dart
@@ -84,6 +84,7 @@ class MailboxCreatorView extends GetWidget {
right: !BuildUtils.isWeb && _responsiveUtils.isLandscapeMobile(context),
child: Column(children: [
_buildAppBar(context),
+ const Divider(color: AppColor.colorDividerDestinationPicker, height: 1),
_buildCreateMailboxNameInput(context),
_buildMailboxLocation(context),
]),
@@ -116,6 +117,7 @@ class MailboxCreatorView extends GetWidget {
..onChange((value) => controller.setNewNameMailbox(value))
..keyboardType(TextInputType.visiblePassword)
..cursorColor(AppColor.colorTextButton)
+ ..addController(controller.nameInputController)
..maxLines(1)
..textStyle(const TextStyle(
color: AppColor.colorNameEmail,
diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb
index 72975b0fd..9e5b1a127 100644
--- a/lib/l10n/intl_messages.arb
+++ b/lib/l10n/intl_messages.arb
@@ -1,5 +1,5 @@
{
- "@@last_modified": "2022-10-26T13:43:22.314355",
+ "@@last_modified": "2022-10-27T15:02:38.515955",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -2393,5 +2393,17 @@
"placeholders": {
"numberOfMailbox": {}
}
+ },
+ "toastMessageErrorNotSelectedFolderWhenCreateNewMailbox": "You have not selected a save folder to save",
+ "@toastMessageErrorNotSelectedFolderWhenCreateNewMailbox": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "createNewMailbox": "Create new mailbox",
+ "@createNewMailbox": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
}
}
\ No newline at end of file
diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart
index e78095a74..b0f3602b3 100644
--- a/lib/main/localizations/app_localizations.dart
+++ b/lib/main/localizations/app_localizations.dart
@@ -2463,4 +2463,16 @@ class AppLocalizations {
args: [numberOfMailbox]
);
}
+
+ String get toastMessageErrorNotSelectedFolderWhenCreateNewMailbox {
+ return Intl.message(
+ 'You have not selected a save folder to save',
+ name: 'toastMessageErrorNotSelectedFolderWhenCreateNewMailbox');
+ }
+
+ String get createNewMailbox {
+ return Intl.message(
+ 'Create new mailbox',
+ name: 'createNewMailbox');
+ }
}
\ No newline at end of file