diff --git a/assets/images/ic_delete_toast.svg b/assets/images/ic_delete_toast.svg
new file mode 100644
index 000000000..2c82dd270
--- /dev/null
+++ b/assets/images/ic_delete_toast.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/ic_remove_dialog.svg b/assets/images/ic_remove_dialog.svg
new file mode 100644
index 000000000..dcd64a0fb
--- /dev/null
+++ b/assets/images/ic_remove_dialog.svg
@@ -0,0 +1,4 @@
+
diff --git a/core/lib/core.dart b/core/lib/core.dart
index e36944332..087464b18 100644
--- a/core/lib/core.dart
+++ b/core/lib/core.dart
@@ -41,11 +41,13 @@ export 'presentation/views/context_menu/context_menu_header_builder.dart';
export 'presentation/views/context_menu/simple_context_menu_action_builder.dart';
export 'presentation/views/dialog/loading_dialog_builder.dart';
export 'presentation/views/dialog/downloading_file_dialog_builder.dart';
+export 'presentation/views/dialog/confirmation_dialog_builder.dart';
export 'presentation/views/background/background_widget_builder.dart';
export 'presentation/views/html_viewer/html_content_viewer_widget.dart';
export 'presentation/views/floating_button/scrolling_floating_button_animated.dart';
export 'presentation/views/bottom_popup/cupertino_action_sheet_action_builder.dart';
export 'presentation/views/bottom_popup/cupertino_action_sheet_builder.dart';
+export 'presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart';
// Resources
export 'presentation/resources/assets_paths.dart';
diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart
index a33f226d2..36ced66b9 100644
--- a/core/lib/presentation/extensions/color_extension.dart
+++ b/core/lib/presentation/extensions/color_extension.dart
@@ -80,6 +80,11 @@ extension AppColor on Color {
static const colorInputBackgroundErrorVerifyName = Color(0xFFFAEBEB);
static const colorInputBackgroundCreateMailbox = Color(0xFFF2F3F5);
static const colorHintInputCreateMailbox= Color(0xFFA9B4C2);
+ static const colorMessageConfirmDialog= Color(0xFF6D7885);
+ static const colorActionDeleteConfirmDialog= Color(0xFFE64646);
+ static const colorActionCancelDialog= Color(0xFF007AFF);
+ static const colorMessageDialog= Color(0xFF222222);
+ static const colorConfirmActionDialog= Color(0xFFF2F2F2);
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 66f6e5e66..d859b7d2f 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -82,6 +82,8 @@ class ImagePaths {
String get icSendToast => _getImagePath('ic_send_toast.svg');
String get icClearTextSearch => _getImagePath('ic_clear_text_search.svg');
String get icRenameMailbox => _getImagePath('ic_rename_mailbox.svg');
+ String get icDeleteToast => _getImagePath('ic_delete_toast.svg');
+ String get icRemoveDialog => _getImagePath('ic_remove_dialog.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
diff --git a/core/lib/presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart b/core/lib/presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart
new file mode 100644
index 000000000..6359c62b6
--- /dev/null
+++ b/core/lib/presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart
@@ -0,0 +1,71 @@
+
+import 'package:core/core.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+
+typedef OnConfirmActionClick = void Function();
+typedef OnCancelActionClick = void Function();
+
+class ConfirmationDialogActionSheetBuilder {
+
+ final BuildContext _context;
+
+ String? _messageText;
+ String? _confirmText;
+ String? _cancelText;
+ OnConfirmActionClick?_onConfirmActionClick;
+ OnCancelActionClick? _onCancelActionClick;
+
+ ConfirmationDialogActionSheetBuilder(this._context);
+
+ void onConfirmAction(String confirmText, OnConfirmActionClick onConfirmActionClick) {
+ _onConfirmActionClick = onConfirmActionClick;
+ _confirmText = confirmText;
+ }
+
+ void onCancelAction(String cancelText, OnCancelActionClick onCancelActionClick) {
+ _onCancelActionClick = onCancelActionClick;
+ _cancelText = cancelText;
+ }
+
+ void messageText(String message) {
+ _messageText = message;
+ }
+
+ void show() {
+ showCupertinoModalPopup(
+ context: _context,
+ barrierColor: AppColor.colorDefaultCupertinoActionSheet,
+ builder: (context) => CupertinoActionSheet(
+ actions: [
+ Container(
+ padding: EdgeInsets.symmetric(vertical: 8, horizontal: 10),
+ color: Colors.white,
+ child: CupertinoActionSheetAction(
+ child: Text(
+ _messageText ?? '',
+ textAlign: TextAlign.center,
+ style: TextStyle(fontSize: 14, color: AppColor.colorMessageConfirmDialog)),
+ onPressed: () => {},
+ )
+ ),
+ Container(
+ color: Colors.white,
+ child: CupertinoActionSheetAction(
+ child: Text(
+ _confirmText ?? '',
+ style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20, color: AppColor.colorActionDeleteConfirmDialog)),
+ onPressed: () => _onConfirmActionClick?.call(),
+ )
+ ),
+ ],
+ cancelButton: CupertinoActionSheetAction(
+ child: Text(
+ _cancelText ?? '',
+ style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20, color: AppColor.colorActionCancelDialog)),
+ onPressed: () => _onCancelActionClick?.call(),
+ ),
+ )
+ );
+ }
+}
\ No newline at end of file
diff --git a/core/lib/presentation/views/bottom_popup/cupertino_action_sheet_builder.dart b/core/lib/presentation/views/bottom_popup/cupertino_action_sheet_builder.dart
index 83d3c829a..9f3d830b1 100644
--- a/core/lib/presentation/views/bottom_popup/cupertino_action_sheet_builder.dart
+++ b/core/lib/presentation/views/bottom_popup/cupertino_action_sheet_builder.dart
@@ -29,7 +29,7 @@ class CupertinoActionSheetBuilder {
_actionTiles.addAll(tiles);
}
- void build() {
+ void show() {
showCupertinoModalPopup(
context: _context,
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
diff --git a/core/lib/presentation/views/dialog/confirmation_dialog_builder.dart b/core/lib/presentation/views/dialog/confirmation_dialog_builder.dart
new file mode 100644
index 000000000..57705110d
--- /dev/null
+++ b/core/lib/presentation/views/dialog/confirmation_dialog_builder.dart
@@ -0,0 +1,148 @@
+
+import 'package:core/core.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+
+typedef OnConfirmButtonAction = void Function();
+typedef OnCancelButtonAction = void Function();
+typedef OnCloseButtonAction = void Function();
+
+class ConfirmDialogBuilder {
+ final ImagePaths _imagePath;
+
+ Key? _key;
+ String _title = '';
+ String _content = '';
+ String _confirmText = '';
+ String _cancelText = '';
+ Widget? _iconWidget;
+
+ OnConfirmButtonAction? _onConfirmButtonAction;
+ OnCancelButtonAction? _onCancelButtonAction;
+ OnCloseButtonAction? _onCloseButtonAction;
+
+ ConfirmDialogBuilder(this._imagePath);
+
+ void key(Key key) {
+ _key = key;
+ }
+
+ void title(String title) {
+ _title = title;
+ }
+
+ void content(String content) {
+ _content = content;
+ }
+
+ void addIcon(Widget? icon) {
+ _iconWidget = icon;
+ }
+
+ void onConfirmButtonAction(String confirmText, OnConfirmButtonAction? onConfirmButtonAction) {
+ _confirmText = confirmText;
+ _onConfirmButtonAction = onConfirmButtonAction;
+ }
+
+ void onCancelButtonAction(String cancelText, OnCancelButtonAction? onCancelButtonAction) {
+ _cancelText = cancelText;
+ _onCancelButtonAction = onCancelButtonAction;
+ }
+
+ void onCloseButtonAction(OnCloseButtonAction? onCloseButtonAction) {
+ _onCloseButtonAction = onCloseButtonAction;
+ }
+
+ Widget build() {
+ return Dialog(
+ key: _key,
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))),
+ insetPadding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
+ child: Container(
+ margin: EdgeInsets.zero,
+ padding: EdgeInsets.zero,
+ width: 400,
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.all(Radius.circular(16))),
+ child: Wrap(children: [
+ Align(
+ alignment: Alignment.centerRight,
+ child: IconButton(
+ padding: EdgeInsets.only(top: 16, right: 16),
+ onPressed: () => _onCloseButtonAction?.call(),
+ icon: SvgPicture.asset(_imagePath.icCloseMailbox, width: 30, height: 30, fit: BoxFit.fill))),
+ if (_iconWidget != null)
+ Container(
+ margin: EdgeInsets.only(top: 24),
+ alignment: Alignment.center,
+ child: _iconWidget,
+ ),
+ Padding(
+ padding: EdgeInsets.only(top: 12),
+ child: Center(
+ child: Text(
+ _title,
+ textAlign: TextAlign.center,
+ style: TextStyle(fontSize: 20.0, color: AppColor.colorActionDeleteConfirmDialog, fontWeight: FontWeight.w500)
+ )
+ )
+ ),
+ Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16, vertical: 24),
+ child: Center(
+ child: Text(_content,
+ textAlign: TextAlign.center,
+ style: TextStyle(fontSize: 17.0, color: AppColor.colorMessageDialog)
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsets.only(bottom: 16, left: 16, right: 16),
+ child: Row(
+ children: [
+ Expanded(
+ child: _buildButton(name: _cancelText, action: _onCancelButtonAction)
+ ),
+ SizedBox(width: 16),
+ Expanded(
+ child: _buildButton(
+ name: _confirmText,
+ bgColor: AppColor.colorConfirmActionDialog,
+ nameColor: AppColor.colorActionDeleteConfirmDialog,
+ action: _onConfirmButtonAction)
+ )
+ ]
+ ))
+ ])
+ ),
+ );
+ }
+
+ Widget _buildButton({
+ String? name, Color? nameColor, Color? bgColor, Function? action
+ }) {
+ return SizedBox(
+ width: double.infinity,
+ height: 48,
+ child: ElevatedButton(
+ onPressed: () => action?.call(),
+ style: ButtonStyle(
+ foregroundColor: MaterialStateProperty.resolveWith(
+ (Set states) => bgColor ?? AppColor.colorTextButton),
+ backgroundColor: MaterialStateProperty.resolveWith(
+ (Set states) => bgColor ?? AppColor.colorTextButton),
+ shape: MaterialStateProperty.all(RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(8),
+ side: BorderSide(width: 0, color: bgColor ?? AppColor.colorTextButton),
+ )),
+ padding: MaterialStateProperty.resolveWith(
+ (Set states) => EdgeInsets.symmetric(horizontal: 16)),
+ elevation: MaterialStateProperty.resolveWith((Set states) => 0)),
+ child: Text(name ?? '',
+ textAlign: TextAlign.center,
+ style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: nameColor ?? Colors.white)),
+ )
+ );
+ }
+}
diff --git a/lib/features/destination_picker/presentation/destination_picker_view.dart b/lib/features/destination_picker/presentation/destination_picker_view.dart
index cee096a26..85e6c4d7c 100644
--- a/lib/features/destination_picker/presentation/destination_picker_view.dart
+++ b/lib/features/destination_picker/presentation/destination_picker_view.dart
@@ -276,7 +276,7 @@ class DestinationPickerView extends GetWidget {
_imagePaths,
mailboxNode,
mailboxDisplayed: MailboxDisplayed.destinationPicker)
- ..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxAction(mailboxNode.item.toPresentationMailboxWithMailboxPath(
+ ..addOnOpenMailboxFolderClick((mailboxNode) => controller.selectMailboxAction(mailboxNode.item.toPresentationMailboxWithMailboxPath(
mailboxNode.getPathMailboxNode(
controller.folderMailboxTree,
controller.defaultMailboxList,
@@ -292,7 +292,7 @@ class DestinationPickerView extends GetWidget {
_imagePaths,
mailboxNode,
mailboxDisplayed: MailboxDisplayed.destinationPicker)
- ..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxAction(mailboxNode.item.toPresentationMailboxWithMailboxPath(
+ ..addOnOpenMailboxFolderClick((mailboxNode) => controller.selectMailboxAction(mailboxNode.item.toPresentationMailboxWithMailboxPath(
mailboxNode.getPathMailboxNode(
controller.folderMailboxTree,
controller.defaultMailboxList,
diff --git a/lib/features/mailbox/data/datasource/mailbox_datasource.dart b/lib/features/mailbox/data/datasource/mailbox_datasource.dart
index 6322d2e5d..d11cb3799 100644
--- a/lib/features/mailbox/data/datasource/mailbox_datasource.dart
+++ b/lib/features/mailbox/data/datasource/mailbox_datasource.dart
@@ -16,4 +16,6 @@ abstract class MailboxDataSource {
Future update({List? updated, List? created, List? destroyed});
Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest);
+
+ Future deleteMultipleMailbox(AccountId accountId, List mailboxIds);
}
\ No newline at end of file
diff --git a/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart
index 3bbf8e724..fd9fbfbdd 100644
--- a/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart
+++ b/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart
@@ -49,4 +49,9 @@ class MailboxCacheDataSourceImpl extends MailboxDataSource {
Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest) {
throw UnimplementedError();
}
+
+ @override
+ Future deleteMultipleMailbox(AccountId accountId, List mailboxIds) {
+ throw UnimplementedError();
+ }
}
\ No newline at end of file
diff --git a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart
index ef76df489..156d37911 100644
--- a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart
+++ b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart
@@ -50,4 +50,13 @@ class MailboxDataSourceImpl extends MailboxDataSource {
throw error;
});
}
+
+ @override
+ Future deleteMultipleMailbox(AccountId accountId, List mailboxIds) {
+ return Future.sync(() async {
+ return await mailboxAPI.deleteMultipleMailbox(accountId, mailboxIds);
+ }).catchError((error) {
+ throw error;
+ });
+ }
}
\ No newline at end of file
diff --git a/lib/features/mailbox/data/network/mailbox_api.dart b/lib/features/mailbox/data/network/mailbox_api.dart
index 56439886a..780767df3 100644
--- a/lib/features/mailbox/data/network/mailbox_api.dart
+++ b/lib/features/mailbox/data/network/mailbox_api.dart
@@ -128,4 +128,29 @@ class MailboxAPI {
throw error;
});
}
+
+ Future deleteMultipleMailbox(AccountId accountId, List mailboxIds) async {
+ final setMailboxMethod = SetMailboxMethod(accountId)
+ ..addDestroy(mailboxIds.map((mailboxId) => mailboxId.id).toSet())
+ ..addOnDestroyRemoveEmails(true);
+
+ final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation());
+
+ final setMailboxInvocation = requestBuilder.invocation(setMailboxMethod);
+
+ final response = await (requestBuilder
+ ..usings(setMailboxMethod.requiredCapabilities))
+ .build()
+ .execute();
+
+ final setMailboxResponse = response.parse(
+ setMailboxInvocation.methodCallId,
+ SetMailboxResponse.deserialize);
+
+ return Future.sync(() async {
+ return setMailboxResponse?.destroyed?.isNotEmpty == true;
+ }).catchError((error) {
+ throw error;
+ });
+ }
}
\ No newline at end of file
diff --git a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart
index c14ea59d9..1d222f5c5 100644
--- a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart
+++ b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart
@@ -140,4 +140,9 @@ class MailboxRepositoryImpl extends MailboxRepository {
Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest) {
return mapDataSource[DataSourceType.network]!.createNewMailbox(accountId, newMailboxRequest);
}
+
+ @override
+ Future deleteMultipleMailbox(AccountId accountId, List mailboxIds) {
+ return mapDataSource[DataSourceType.network]!.deleteMultipleMailbox(accountId, mailboxIds);
+ }
}
\ No newline at end of file
diff --git a/lib/features/mailbox/domain/repository/mailbox_repository.dart b/lib/features/mailbox/domain/repository/mailbox_repository.dart
index a5b072432..2e3f1885a 100644
--- a/lib/features/mailbox/domain/repository/mailbox_repository.dart
+++ b/lib/features/mailbox/domain/repository/mailbox_repository.dart
@@ -11,4 +11,6 @@ abstract class MailboxRepository {
Stream refresh(AccountId accountId, State currentState);
Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest);
+
+ Future deleteMultipleMailbox(AccountId accountId, List mailboxIds);
}
\ No newline at end of file
diff --git a/lib/features/mailbox/domain/state/delete_multiple_mailbox_state.dart b/lib/features/mailbox/domain/state/delete_multiple_mailbox_state.dart
new file mode 100644
index 000000000..70a20dd36
--- /dev/null
+++ b/lib/features/mailbox/domain/state/delete_multiple_mailbox_state.dart
@@ -0,0 +1,18 @@
+import 'package:core/core.dart';
+
+class DeleteMultipleMailboxSuccess extends UIState {
+
+ DeleteMultipleMailboxSuccess();
+
+ @override
+ List