TF-189 Add new utils function in mailbox tree

This commit is contained in:
Dat PHAM HOANG
2022-03-11 14:09:14 +07:00
committed by Dat H. Pham
parent ebb340e99a
commit af22d2ffaf
4 changed files with 132 additions and 94 deletions
@@ -1,45 +0,0 @@
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/mailbox/expand_mode.dart';
import 'package:model/mailbox/select_mode.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();
}
List<MailboxNode> toggleSelectMailboxNode(MailboxNode selectedMailboxMode) {
return map((MailboxNode child) {
if (child.item.id == selectedMailboxMode.item.id) {
return child.toggleSelectMailboxNode();
} else {
if (child.hasChildren()) {
return child.copyWith(mailboxNodes: child.toggleSelectNode(selectedMailboxMode));
}
return child;
}
}).toList();
}
List<MailboxNode> toSelectMailboxNode({required SelectMode selectMode, ExpandMode? newExpandMode}) {
return map((MailboxNode child) {
if (child.hasChildren()) {
return child.copyWith(
mailboxNodes: child.toSelectedNode(selectMode: selectMode, newExpandMode: newExpandMode),
newSelectMode: selectMode,
newExpandMode: newExpandMode);
}
return child.toSelectedMailboxNode(selectMode: selectMode, newExpandMode: newExpandMode);
}).toList();
}
}
@@ -4,7 +4,6 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/mailbox/expand_mode.dart'; import 'package:model/mailbox/expand_mode.dart';
import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:model/mailbox/select_mode.dart'; import 'package:model/mailbox/select_mode.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart';
class MailboxNode with EquatableMixin{ class MailboxNode with EquatableMixin{
static PresentationMailbox _root = PresentationMailbox(MailboxId(Id('root'))); static PresentationMailbox _root = PresentationMailbox(MailboxId(Id('root')));
@@ -36,31 +35,6 @@ class MailboxNode with EquatableMixin{
childrenItems?.add(node); 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>? updateNode(MailboxId mailboxId, MailboxNode newNode, {MailboxNode? parent}) {
List<MailboxNode>? _children = parent == null ? this.childrenItems : parent.childrenItems; List<MailboxNode>? _children = parent == null ? this.childrenItems : parent.childrenItems;
return _children?.map((MailboxNode child) { return _children?.map((MailboxNode child) {
@@ -69,7 +43,7 @@ class MailboxNode with EquatableMixin{
} else { } else {
if (child.hasChildren()) { if (child.hasChildren()) {
return child.copyWith( return child.copyWith(
mailboxNodes: updateNode( children: updateNode(
mailboxId, mailboxId,
newNode, newNode,
parent: child, parent: child,
@@ -81,6 +55,24 @@ class MailboxNode with EquatableMixin{
}).toList(); }).toList();
} }
List<MailboxNode> descendantsAsList(){
List<MailboxNode> listOfNodes = <MailboxNode>[];
_appendDescendants(this, listOfNodes);
return listOfNodes;
}
void _appendDescendants(MailboxNode? node, List<MailboxNode> listOfNodes) {
if (node != null) {
listOfNodes.add(node);
List<MailboxNode>? childrenItems = node.childrenItems;
if (childrenItems != null) {
childrenItems.forEach((child) {
_appendDescendants(child, listOfNodes);
});
}
}
}
List<MailboxNode>? toggleSelectNode(MailboxNode selectedMailboxMode, {MailboxNode? parent}) { List<MailboxNode>? toggleSelectNode(MailboxNode selectedMailboxMode, {MailboxNode? parent}) {
List<MailboxNode>? _children = parent == null ? this.childrenItems : parent.childrenItems; List<MailboxNode>? _children = parent == null ? this.childrenItems : parent.childrenItems;
return _children?.map((MailboxNode child) { return _children?.map((MailboxNode child) {
@@ -88,7 +80,7 @@ class MailboxNode with EquatableMixin{
return child.toggleSelectMailboxNode(); return child.toggleSelectMailboxNode();
} else { } else {
if (child.hasChildren()) { if (child.hasChildren()) {
return child.copyWith(mailboxNodes: toggleSelectNode(selectedMailboxMode, parent: child)); return child.copyWith(children: toggleSelectNode(selectedMailboxMode, parent: child));
} }
return child; return child;
} }
@@ -100,7 +92,7 @@ class MailboxNode with EquatableMixin{
return _children?.map((MailboxNode child) { return _children?.map((MailboxNode child) {
if (child.hasChildren()) { if (child.hasChildren()) {
return child.copyWith( return child.copyWith(
mailboxNodes: toSelectedNode(selectMode: selectMode, newExpandMode: newExpandMode, parent: child), children: toSelectedNode(selectMode: selectMode, newExpandMode: newExpandMode, parent: child),
newSelectMode: selectMode, newSelectMode: selectMode,
newExpandMode: newExpandMode); newExpandMode: newExpandMode);
} }
@@ -109,18 +101,18 @@ class MailboxNode with EquatableMixin{
} }
@override @override
List<Object?> get props => [item, childrenItems]; List<Object?> get props => [item, childrenItems, expandMode, selectMode];
} }
extension MailboxNodeExtension on MailboxNode { extension MailboxNodeExtension on MailboxNode {
MailboxNode copyWith({ MailboxNode copyWith({
SelectMode? newSelectMode, SelectMode? newSelectMode,
ExpandMode? newExpandMode, ExpandMode? newExpandMode,
List<MailboxNode>? mailboxNodes List<MailboxNode>? children
}) { }) {
return MailboxNode( return MailboxNode(
item, item,
childrenItems: mailboxNodes ?? childrenItems, childrenItems: children ?? childrenItems,
expandMode: newExpandMode ?? expandMode, expandMode: newExpandMode ?? expandMode,
selectMode: newSelectMode ?? selectMode, selectMode: newSelectMode ?? selectMode,
); );
@@ -3,20 +3,24 @@ import 'dart:collection';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/mailbox/expand_mode.dart';
import 'package:model/mailbox/select_mode.dart';
import 'mailbox_node.dart'; import 'mailbox_node.dart';
typedef NodeQuery = bool Function(MailboxNode node);
class MailboxTree with EquatableMixin { class MailboxTree with EquatableMixin {
MailboxNode root; MailboxNode root;
MailboxTree(this.root); MailboxTree(this.root);
MailboxNode? findNode(MailboxId? mailboxId) { MailboxNode? findNode(NodeQuery nodeQuery) {
var result; var result;
final queue = ListQueue<MailboxNode>(); final queue = ListQueue<MailboxNode>();
queue.addLast(root); queue.addLast(root);
while (queue.isNotEmpty && mailboxId != null) { while (queue.isNotEmpty) {
final currentNode = queue.removeFirst(); final currentNode = queue.removeFirst();
if (mailboxId == currentNode.item.id) { if (nodeQuery(currentNode)) {
result = currentNode; result = currentNode;
break; break;
} }
@@ -27,22 +31,72 @@ class MailboxTree with EquatableMixin {
return result; return result;
} }
List<MailboxNode> getAllNodes(MailboxNode node){ List<MailboxNode> findNodes(NodeQuery nodeQuery) {
List<MailboxNode> listOfNodes = <MailboxNode>[]; final listResult = List<MailboxNode>.empty(growable: true);
_addAllNodes(node, listOfNodes); final queue = ListQueue<MailboxNode>();
return listOfNodes; queue.addLast(root);
while (queue.isNotEmpty) {
final currentNode = queue.removeFirst();
if (nodeQuery(currentNode)) {
listResult.add(currentNode);
}
currentNode.childrenItems?.forEach((child) {
queue.addLast(child);
});
}
return listResult;
} }
void _addAllNodes(MailboxNode? node, List<MailboxNode> listOfNodes) { MailboxNode? updateExpandedNode(MailboxNode selectedNode, ExpandMode newExpandMode) {
if (node != null) { var matchedNode = findNode((node) => node.item.id == selectedNode.item.id);
listOfNodes.add(node); matchedNode?.expandMode = newExpandMode;
List<MailboxNode>? childrenItems = node.childrenItems; return matchedNode;
if (childrenItems != null) { }
childrenItems.forEach((child) {
_addAllNodes(child, listOfNodes); MailboxNode? updateSelectedNode(MailboxNode selectedNode, SelectMode newSelectMode) {
}); var matchedNode = findNode((node) => node.item.id == selectedNode.item.id);
} matchedNode?.selectMode = newSelectMode;
return matchedNode;
}
void updateNodesUIMode(SelectMode? selectMode, ExpandMode? expandMode) {
if (selectMode == null && expandMode == null) {
return;
} }
final queue = ListQueue<MailboxNode>();
queue.addLast(root);
while (queue.isNotEmpty) {
final currentNode = queue.removeFirst();
if (expandMode != null) {
currentNode.expandMode = expandMode;
}
if (selectMode != null) {
currentNode.selectMode = selectMode;
}
currentNode.childrenItems?.forEach((child) {
queue.addLast(child);
});
}
}
String? getNodePath(MailboxId mailboxId) {
final matchedNode = findNode((node) => node.item.id == mailboxId);
if (matchedNode == null) {
return null;
}
String path = '${matchedNode.item.name?.name}';
var parentId = matchedNode.item.parentId;
while(parentId != null) {
var parentNode = findNode((node) => node.item.id == parentId);
if (parentNode == null) {
break;
}
path = '${parentNode.item.name?.name}/$path';
parentId = parentNode.item.parentId;
}
return path;
} }
@override @override
@@ -1,6 +1,7 @@
import 'dart:collection'; import 'dart:collection';
import 'package:collection/collection.dart';
import 'package:collection/collection.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
@@ -37,4 +38,40 @@ class TreeBuilder {
}); });
return tree; return tree;
} }
Future<Tuple2<MailboxTree, MailboxTree>> generateMailboxTreeInUI(List<PresentationMailbox> allMailboxes) async {
final Map<MailboxId, MailboxNode> mailboxDictionary = HashMap();
final defaultTree = MailboxTree(MailboxNode.root());
final folderTree = MailboxTree(MailboxNode.root());
allMailboxes.forEach((mailbox) {
mailboxDictionary[mailbox.id] = MailboxNode(mailbox);
});
allMailboxes.forEach((mailbox) {
final parentId = mailbox.parentId;
final parentNode = mailboxDictionary[parentId];
final node = mailboxDictionary[mailbox.id];
if (node != null) {
if (parentNode != null) {
parentNode.addChildNode(node);
parentNode.childrenItems?.sortByCompare<MailboxName?>(
(node) => node.item.name,
(name, other) => name?.compareAlphabetically(other) ?? -1
);
} else {
var tree = mailbox.hasRole() ? defaultTree : folderTree;
tree.root.addChildNode(node);
tree.root.childrenItems?.sortByCompare<MailboxName?>(
(node) => node.item.name,
(name, other) => name?.compareAlphabetically(other) ?? -1
);
}
}
});
return Tuple2(defaultTree, folderTree);
}
} }