TF-80 Move multiple email to mailbox from thread view
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
|
||||
|
||||
extension ListMailboxNodeExtensions on List<MailboxNode> {
|
||||
List<MailboxNode>? updateNode(MailboxId currentMailboxId, MailboxNode newNode) {
|
||||
return map((MailboxNode child) {
|
||||
if (child.item.id == currentMailboxId) {
|
||||
return newNode;
|
||||
} else {
|
||||
if (child.hasChildren()) {
|
||||
return child.copyWith(mailboxNodes: child.updateNode(currentMailboxId, newNode));
|
||||
}
|
||||
return child;
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,11 @@ import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_i
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart';
|
||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
@@ -26,8 +27,8 @@ class MailboxController extends BaseController {
|
||||
final TreeBuilder _treeBuilder;
|
||||
final ResponsiveUtils responsiveUtils;
|
||||
|
||||
final folderMailboxTree = MailboxTree(MailboxNode.root()).obs;
|
||||
final defaultMailboxList = <PresentationMailbox>[].obs;
|
||||
final folderMailboxNodeList = <MailboxNode>[].obs;
|
||||
|
||||
MailboxController(
|
||||
this._getAllMailboxInteractor,
|
||||
@@ -51,6 +52,10 @@ class MailboxController extends BaseController {
|
||||
success is MarkAsMultipleEmailReadAllSuccess ||
|
||||
success is MarkAsMultipleEmailReadHasSomeEmailFailure) {
|
||||
refreshGetAllMailboxAction();
|
||||
} else if (success is MoveMultipleEmailToMailboxAllSuccess
|
||||
|| success is MoveMultipleEmailToMailboxHasSomeEmailFailure) {
|
||||
mailboxDashBoardController.clearState();
|
||||
refreshGetAllMailboxAction();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -97,7 +102,20 @@ class MailboxController extends BaseController {
|
||||
void onError(error) {}
|
||||
|
||||
void _buildTree(List<PresentationMailbox> folderMailboxList) async {
|
||||
folderMailboxTree.value = await _treeBuilder.generateMailboxTree(folderMailboxList);
|
||||
final _folderMailboxTree = await _treeBuilder.generateMailboxTree(folderMailboxList);
|
||||
folderMailboxNodeList.value = _folderMailboxTree.root.childrenItems ?? [];
|
||||
}
|
||||
|
||||
void toggleMailboxFolder(MailboxNode mailboxNode) {
|
||||
final newExpandMode = mailboxNode.expandMode == ExpandMode.COLLAPSE
|
||||
? ExpandMode.EXPAND
|
||||
: ExpandMode.COLLAPSE;
|
||||
|
||||
final newMailboxNodeList = folderMailboxNodeList.updateNode(
|
||||
mailboxNode.item.id,
|
||||
mailboxNode.copyWith(newExpandMode: newExpandMode)) ?? [];
|
||||
|
||||
folderMailboxNodeList.value = newMailboxNodeList;
|
||||
}
|
||||
|
||||
void _setUpMapMailboxIdDefault(List<PresentationMailbox> defaultMailboxList) {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
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/utils/responsive_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -174,7 +171,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
}
|
||||
|
||||
Widget _buildFolderMailbox(BuildContext context) {
|
||||
return Obx(() => controller.folderMailboxTree.value.root.hasChildren()
|
||||
return Obx(() => controller.folderMailboxNodeList.isNotEmpty
|
||||
? Transform(
|
||||
transform: Matrix4.translationValues(responsiveUtils.isMobile(context) ? 0.0 : -15.0, 0.0, 0.0),
|
||||
child: Padding(
|
||||
@@ -182,7 +179,7 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
child: TreeView(
|
||||
startExpanded: false,
|
||||
key: Key('folder_mailbox_list'),
|
||||
children: _buildListChildTileWidget(context, controller.folderMailboxTree.value.root.childrenItems!)))
|
||||
children: _buildListChildTileWidget(context, controller.folderMailboxNodeList)))
|
||||
)
|
||||
: SizedBox.shrink()
|
||||
);
|
||||
@@ -192,24 +189,27 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
return listMailboxNode
|
||||
.map((mailboxNode) => mailboxNode.hasChildren()
|
||||
? Padding(
|
||||
padding: EdgeInsets.only(left: 16),
|
||||
padding: EdgeInsets.only(left: 20),
|
||||
child: TreeViewChild(
|
||||
key: Key('children_tree_mailbox_child'),
|
||||
parent: Obx(() => MailBoxFolderTileBuilder(
|
||||
context,
|
||||
imagePaths,
|
||||
responsiveUtils,
|
||||
mailboxNode,
|
||||
selectMode: controller.getSelectMode(
|
||||
mailboxNode.item,
|
||||
controller.mailboxDashBoardController.selectedMailbox.value))
|
||||
.build()),
|
||||
children: _buildListChildTileWidget(context, mailboxNode.childrenItems!)))
|
||||
context,
|
||||
key: Key('children_tree_mailbox_child'),
|
||||
isExpanded: mailboxNode.expandMode == ExpandMode.EXPAND,
|
||||
parent: Obx(() => (MailBoxFolderTileBuilder(
|
||||
context,
|
||||
imagePaths,
|
||||
responsiveUtils,
|
||||
mailboxNode,
|
||||
selectMode: controller.getSelectMode(
|
||||
mailboxNode.item,
|
||||
controller.mailboxDashBoardController.selectedMailbox.value))
|
||||
..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailbox(context, mailboxNode.item))
|
||||
..addOnExpandFolderActionClick((mailboxNode) => controller.toggleMailboxFolder(mailboxNode)))
|
||||
.build()),
|
||||
children: _buildListChildTileWidget(context, mailboxNode.childrenItems!)
|
||||
).build())
|
||||
: Padding(
|
||||
padding: EdgeInsets.only(left: 16),
|
||||
child: Obx(() => GestureDetector(
|
||||
onTap: () => controller.selectMailbox(context, mailboxNode.item),
|
||||
child: MailBoxFolderTileBuilder(
|
||||
padding: EdgeInsets.only(left: 20),
|
||||
child: Obx(() => (MailBoxFolderTileBuilder(
|
||||
context,
|
||||
imagePaths,
|
||||
responsiveUtils,
|
||||
@@ -217,8 +217,9 @@ class MailboxView extends GetWidget<MailboxController> {
|
||||
selectMode: controller.getSelectMode(
|
||||
mailboxNode.item,
|
||||
controller.mailboxDashBoardController.selectedMailbox.value))
|
||||
.build(),
|
||||
))))
|
||||
..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailbox(context, mailboxNode.item)))
|
||||
.build(),
|
||||
)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/mailbox/expand_mode.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart';
|
||||
|
||||
class MailboxNode with EquatableMixin{
|
||||
static PresentationMailbox _root = PresentationMailbox(MailboxId(Id('root')));
|
||||
|
||||
PresentationMailbox item;
|
||||
List<MailboxNode>? childrenItems;
|
||||
ExpandMode expandMode;
|
||||
|
||||
factory MailboxNode.root() => MailboxNode(_root);
|
||||
|
||||
static PresentationMailbox rootItem() => _root;
|
||||
|
||||
bool hasChildren() => childrenItems?.isNotEmpty ?? false;
|
||||
|
||||
MailboxNode(this.item, {this.childrenItems});
|
||||
MailboxNode(this.item, {this.childrenItems, this.expandMode = ExpandMode.COLLAPSE});
|
||||
|
||||
void addChildNode(MailboxNode node) {
|
||||
if (childrenItems == null) {
|
||||
@@ -22,6 +27,60 @@ class MailboxNode with EquatableMixin{
|
||||
childrenItems?.add(node);
|
||||
}
|
||||
|
||||
String getPathMailboxNode(MailboxTree mailboxTree, List<PresentationMailbox> defaultMailboxList) {
|
||||
String path = '${item.name?.name}';
|
||||
|
||||
var parentId = item.parentId;
|
||||
|
||||
while(parentId != null) {
|
||||
var parent = mailboxTree.findNode(parentId);
|
||||
if (parent == null) {
|
||||
try {
|
||||
final parentItem = defaultMailboxList.firstWhere((mailbox) => mailbox.id == parentId);
|
||||
parent = MailboxNode(parentItem);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
if (parent != null) {
|
||||
path = '${parent.item.name?.name}/$path';
|
||||
parentId = parent.item.parentId;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
List<MailboxNode>? updateNode(MailboxId mailboxId, MailboxNode newNode, {MailboxNode? parent}) {
|
||||
List<MailboxNode>? _children = parent == null ? this.childrenItems : parent.childrenItems;
|
||||
return _children?.map((MailboxNode child) {
|
||||
if (child.item.id == mailboxId) {
|
||||
return newNode;
|
||||
} else {
|
||||
if (child.hasChildren()) {
|
||||
return child.copyWith(
|
||||
mailboxNodes: updateNode(
|
||||
mailboxId,
|
||||
newNode,
|
||||
parent: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [item, childrenItems];
|
||||
}
|
||||
}
|
||||
|
||||
extension MailboxNodeExtension on MailboxNode {
|
||||
MailboxNode copyWith({ExpandMode? newExpandMode, List<MailboxNode>? mailboxNodes}) {
|
||||
return MailboxNode(
|
||||
item,
|
||||
childrenItems: mailboxNodes ?? childrenItems,
|
||||
expandMode: newExpandMode ?? expandMode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
|
||||
import 'mailbox_node.dart';
|
||||
|
||||
@@ -7,6 +10,23 @@ class MailboxTree with EquatableMixin {
|
||||
MailboxNode root;
|
||||
MailboxTree(this.root);
|
||||
|
||||
MailboxNode? findNode(MailboxId? mailboxId) {
|
||||
var result;
|
||||
final queue = ListQueue<MailboxNode>();
|
||||
queue.addLast(root);
|
||||
while (queue.isNotEmpty && mailboxId != null) {
|
||||
final currentNode = queue.removeFirst();
|
||||
if (mailboxId == currentNode.item.id) {
|
||||
result = currentNode;
|
||||
break;
|
||||
}
|
||||
currentNode.childrenItems?.forEach((child) {
|
||||
queue.addLast(child);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [root];
|
||||
}
|
||||
@@ -3,9 +3,13 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:model/mailbox/select_mode.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_displayed.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
|
||||
|
||||
typedef OnExpandFolderActionClick = void Function(MailboxNode mailboxNode);
|
||||
typedef OnSelectMailboxFolderClick = void Function(MailboxNode mailboxNode);
|
||||
|
||||
class MailBoxFolderTileBuilder {
|
||||
|
||||
final MailboxNode _mailboxNode;
|
||||
@@ -15,6 +19,9 @@ class MailBoxFolderTileBuilder {
|
||||
final SelectMode selectMode;
|
||||
final MailboxDisplayed mailboxDisplayed;
|
||||
|
||||
OnExpandFolderActionClick? _onExpandFolderActionClick;
|
||||
OnSelectMailboxFolderClick? _onSelectMailboxFolderClick;
|
||||
|
||||
MailBoxFolderTileBuilder(
|
||||
this._context,
|
||||
this._imagePaths,
|
||||
@@ -26,6 +33,14 @@ class MailBoxFolderTileBuilder {
|
||||
}
|
||||
);
|
||||
|
||||
void addOnExpandFolderActionClick(OnExpandFolderActionClick onExpandFolderActionClick) {
|
||||
this._onExpandFolderActionClick = onExpandFolderActionClick;
|
||||
}
|
||||
|
||||
void addOnSelectMailboxFolderClick(OnSelectMailboxFolderClick onSelectMailboxFolderClick) {
|
||||
this._onSelectMailboxFolderClick = onSelectMailboxFolderClick;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return Container(
|
||||
key: Key('mailbox_folder_tile'),
|
||||
@@ -39,6 +54,11 @@ class MailBoxFolderTileBuilder {
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(padding: EdgeInsets.zero),
|
||||
child: ListTile(
|
||||
onTap: () {
|
||||
if (_onSelectMailboxFolderClick != null) {
|
||||
_onSelectMailboxFolderClick!(_mailboxNode);
|
||||
}
|
||||
},
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: Padding(
|
||||
padding: EdgeInsets.only(left: mailboxDisplayed == MailboxDisplayed.mailbox
|
||||
@@ -72,14 +92,21 @@ class MailBoxFolderTileBuilder {
|
||||
: 36,
|
||||
left: mailboxDisplayed == MailboxDisplayed.mailbox ? 16 : 16),
|
||||
child: _mailboxNode.hasChildren()
|
||||
? SvgPicture.asset(
|
||||
_imagePaths.icFolderArrow,
|
||||
width: 12,
|
||||
height: 12,
|
||||
color: selectMode == SelectMode.ACTIVE
|
||||
? AppColor.mailboxSelectedIconColor
|
||||
: AppColor.mailboxIconColor,
|
||||
fit: BoxFit.fill)
|
||||
? GestureDetector(
|
||||
onTap: () {
|
||||
if (_onExpandFolderActionClick != null) {
|
||||
_onExpandFolderActionClick!(_mailboxNode);
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
_mailboxNode.expandMode == ExpandMode.EXPAND ? _imagePaths.icExpandFolder : _imagePaths.icFolderArrow,
|
||||
width: _mailboxNode.expandMode == ExpandMode.EXPAND ? 8 : 12,
|
||||
height: _mailboxNode.expandMode == ExpandMode.EXPAND ? 8 : 12,
|
||||
color: selectMode == SelectMode.ACTIVE
|
||||
? AppColor.mailboxSelectedIconColor
|
||||
: AppColor.mailboxIconColor,
|
||||
fit: BoxFit.fill),
|
||||
)
|
||||
: SizedBox.shrink())
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user