TF-899 Implement create mailbox folder in destination picker

This commit is contained in:
dab246
2022-10-26 15:00:48 +07:00
committed by Dat H. Pham
parent 38d403aeed
commit 6554ca5f23
19 changed files with 775 additions and 166 deletions
@@ -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) {
@@ -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<GetAllMailboxInteractor>(),
Get.find<SearchMailboxInteractor>(),
Get.find<CreateNewMailboxInteractor>(),
Get.find<RefreshAllMailboxInteractor>(),
Get.find<VerifyNameInteractor>(),
Get.find<TreeBuilder>(),
));
}
@@ -66,6 +72,9 @@ class DestinationPickerBindings extends BaseBindings {
void bindingsInteractor() {
Get.lazyPut(() => GetAllMailboxInteractor(Get.find<MailboxRepository>()));
Get.lazyPut(() => SearchMailboxInteractor());
Get.lazyPut(() => CreateNewMailboxInteractor(Get.find<MailboxRepository>()));
Get.lazyPut(() => RefreshAllMailboxInteractor(Get.find<MailboxRepository>()));
Get.lazyPut(() => VerifyNameInteractor());
}
@override
@@ -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<Uuid>();
final _appToast = Get.find<AppToast>();
final _imagePaths = Get.find<ImagePaths>();
final _responsiveUtils = Get.find<ResponsiveUtils>();
final GetAllMailboxInteractor _getAllMailboxInteractor;
final SearchMailboxInteractor _searchMailboxInteractor;
final CreateNewMailboxInteractor _createNewMailboxInteractor;
final RefreshAllMailboxInteractor _refreshAllMailboxInteractor;
final VerifyNameInteractor _verifyNameInteractor;
final mailboxAction = Rxn<MailboxActions>();
final listMailboxSearched = <PresentationMailbox>[].obs;
final searchState = SearchState.initial().obs;
final searchQuery = SearchQuery.initial().obs;
final mailboxCategoriesExpandMode = MailboxCategoriesExpandMode.initial().obs;
final destinationScreenType = DestinationScreenType.destinationPicker.obs;
final mailboxDestination = Rxn<PresentationMailbox>();
final newNameMailbox = Rxn<String>();
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<String> listMailboxNameAsStringExist = <String>[];
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 ?? <MailboxNode>[]) +
(folderMailboxTree.value.root.childrenItems ?? <MailboxNode>[]);
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();
@@ -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<DestinationPickerController>
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<DestinationPickerController>
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<DestinationPickerController>
);
}
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<DestinationPickerController>
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<DestinationPickerController>
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<DestinationPickerController>
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<Widget> _buildListChildTileWidget(
@@ -203,34 +268,41 @@ class DestinationPickerView extends GetWidget<DestinationPickerController>
}
) {
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() ?? <Widget>[];
}
@@ -250,7 +322,6 @@ class DestinationPickerView extends GetWidget<DestinationPickerController>
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<DestinationPickerController>
_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<DestinationPickerController>
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<DestinationPickerController>
} 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(
@@ -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;
}
}
}
@@ -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<ImagePaths>();
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<ImagePaths>();
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
)
);
}
}
@@ -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;
}
@@ -361,7 +361,7 @@ class MailboxView extends GetWidget<MailboxController> {
_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())
@@ -361,8 +361,7 @@ class MailboxView extends GetWidget<MailboxController> 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))
@@ -23,6 +23,8 @@ class MailboxNode with EquatableMixin{
bool get isActivated => nodeState == MailboxState.activated;
bool get isSelected => selectMode == SelectMode.ACTIVE;
MailboxNode(
this.item,
{
@@ -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)) {
@@ -15,14 +15,15 @@ typedef OnDragItemAccepted = void Function(List<PresentationEmail>, 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)) {
@@ -30,6 +30,7 @@ class MailboxCreatorController extends BaseController {
final newNameMailbox = Rxn<String>();
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();
@@ -84,6 +84,7 @@ class MailboxCreatorView extends GetWidget<MailboxCreatorController> {
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<MailboxCreatorController> {
..onChange((value) => controller.setNewNameMailbox(value))
..keyboardType(TextInputType.visiblePassword)
..cursorColor(AppColor.colorTextButton)
..addController(controller.nameInputController)
..maxLines(1)
..textStyle(const TextStyle(
color: AppColor.colorNameEmail,