diff --git a/lib/features/mailbox/presentation/model/mailbox_node.dart b/lib/features/mailbox/presentation/model/mailbox_node.dart index b92af2f20..790218ada 100644 --- a/lib/features/mailbox/presentation/model/mailbox_node.dart +++ b/lib/features/mailbox/presentation/model/mailbox_node.dart @@ -1,4 +1,3 @@ -import 'package:built_collection/built_collection.dart'; import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; @@ -8,39 +7,19 @@ class MailboxNode with EquatableMixin{ static PresentationMailbox _root = PresentationMailbox(MailboxId(Id('root'))); PresentationMailbox item; - late BuiltList childrenItems; + List? childrenItems; factory MailboxNode.root() => MailboxNode(_root); - bool hasChildren() => childrenItems.isNotEmpty; + bool hasChildren() => childrenItems?.isNotEmpty ?? false; - MailboxNode(this.item, {List child = const []}) { - this.childrenItems = BuiltList(child); - } + MailboxNode(this.item, {this.childrenItems}); - MailboxNode? addChild(PresentationMailbox mailbox) { - if (_validateChild(mailbox)) { - final node = MailboxNode(mailbox); - _addChildNode(node); - return node; + void addChildNode(MailboxNode node) { + if (childrenItems == null) { + childrenItems = []; } - return null; - } - - void _addChildNode(MailboxNode node) { - childrenItems = (ListBuilder(childrenItems) - ..add(node)) - .build(); - } - - bool _validateChild(PresentationMailbox mailbox) { - if (mailbox.parentId == item.id) { - return true; - } - if (item == _root) { - return true; - } - return false; + childrenItems?.add(node); } @override diff --git a/lib/features/mailbox/presentation/model/mailbox_tree.dart b/lib/features/mailbox/presentation/model/mailbox_tree.dart index 78e4f2b95..32461a07f 100644 --- a/lib/features/mailbox/presentation/model/mailbox_tree.dart +++ b/lib/features/mailbox/presentation/model/mailbox_tree.dart @@ -1,8 +1,5 @@ -import 'dart:collection'; import 'package:equatable/equatable.dart'; -import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; -import 'package:model/mailbox/presentation_mailbox.dart'; import 'mailbox_node.dart'; @@ -10,34 +7,6 @@ class MailboxTree with EquatableMixin { MailboxNode root; MailboxTree(this.root); - MailboxNode? findNode(MailboxId? mailboxId) { - var result; - final queue = ListQueue(); - 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; - } - - MailboxNode? insertNode(PresentationMailbox mailbox) { - if (mailbox.parentId == null) { - return root.addChild(mailbox); - } - - final foundParent = findNode(mailbox.parentId); - return foundParent != null - ? foundParent.addChild(mailbox) - : root.addChild(mailbox); - } - @override List get props => [root]; } \ No newline at end of file diff --git a/lib/features/mailbox/presentation/model/mailbox_tree_builder.dart b/lib/features/mailbox/presentation/model/mailbox_tree_builder.dart index f169ab4ee..5b75f61f7 100644 --- a/lib/features/mailbox/presentation/model/mailbox_tree_builder.dart +++ b/lib/features/mailbox/presentation/model/mailbox_tree_builder.dart @@ -1,6 +1,5 @@ import 'dart:collection'; -import 'package:built_collection/built_collection.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; @@ -9,50 +8,24 @@ import 'mailbox_tree.dart'; class TreeBuilder { Future generateMailboxTree(List mailboxesList) async { - final Map> mapNotFoundParentMailbox = HashMap(); + final Map mailboxDictionary = HashMap(); final tree = MailboxTree(MailboxNode.root()); mailboxesList.forEach((mailbox) { - if (mailbox.hasParentId()) { - final parentId = mailbox.parentId!; - final foundParent = tree.findNode(parentId); - if (foundParent != null) { - _addDescendant(tree, mailbox, maybeDescendant: mapNotFoundParentMailbox); - } else { - final siblingTrees = mapNotFoundParentMailbox[mailbox.parentId]; - if (siblingTrees != null) { - mapNotFoundParentMailbox.addAll({ - parentId: (ListBuilder(siblingTrees)..add(mailbox)).build() - }); - } else { - mapNotFoundParentMailbox.addAll({parentId: (ListBuilder()..add(mailbox)).build()}); - } - } - } else { - _addDescendant(tree, mailbox, maybeDescendant: mapNotFoundParentMailbox); - } + mailboxDictionary[mailbox.id] = MailboxNode(mailbox); }); - mapNotFoundParentMailbox.forEach((_, listMailbox) { - listMailbox.forEach((mailbox) { - _addDescendant(tree, mailbox); - }); + mailboxesList.forEach((mailbox) { + final parentId = mailbox.parentId; + final parentNode = mailboxDictionary[parentId]; + final node = mailboxDictionary[mailbox.id]; + if (node != null) { + if (parentNode != null) { + parentNode.addChildNode(node); + } else { + tree.root.addChildNode(node); + } + } }); return tree; } - - MailboxNode? _addDescendant( - MailboxTree tree, - PresentationMailbox mailboxChild, - {Map>? maybeDescendant} - ) { - final queue = ListQueue(); - queue.addLast(mailboxChild); - while (queue.isNotEmpty) { - final current = queue.removeFirst(); - tree.insertNode(current); - maybeDescendant?.remove(current.id)?.forEach((child) { - queue.addLast(child); - }); - } - } } \ No newline at end of file diff --git a/test/features/mailbox/presentation/model/mailbox_node_test.dart b/test/features/mailbox/presentation/model/mailbox_node_test.dart index ddf22baa3..b4d72f31f 100644 --- a/test/features/mailbox/presentation/model/mailbox_node_test.dart +++ b/test/features/mailbox/presentation/model/mailbox_node_test.dart @@ -11,38 +11,20 @@ void main() { final parentMailbox = PresentationMailbox(MailboxId(Id('1'))); final node = MailboxNode(parentMailbox); final childMailbox = PresentationMailbox(MailboxId(Id('11')), parentId: MailboxId(Id('1'))); - final childNode = node.addChild(childMailbox); + node.addChildNode(MailboxNode(childMailbox)); - expect(node.childrenItems.length, equals(1)); - expect(node.childrenItems[0], equals(childNode)); + expect(node.childrenItems?.length, equals(1)); }); - test('addChild should add new mailbox to a node', () async { + test('addChildNode should add other new mailbox to a node', () async { final parentMailbox = PresentationMailbox(MailboxId(Id('1'))); final node = MailboxNode(parentMailbox); final childMailbox = PresentationMailbox(MailboxId(Id('11')), parentId: MailboxId(Id('1'))); - final childNode = node.addChild(childMailbox); + node.addChildNode(MailboxNode(childMailbox)); final childMailbox2 = PresentationMailbox(MailboxId(Id('12')), parentId: MailboxId(Id('1'))); - final childNode2 = node.addChild(childMailbox2); + node.addChildNode(MailboxNode(childMailbox2)); - expect(node.childrenItems.length, equals(2)); - expect(node.childrenItems, containsAll({childNode, childNode2})); - }); - - test('addChild add new mailbox without parentId to a node should return null', () async { - final parentMailbox = PresentationMailbox(MailboxId(Id('1'))); - final node = MailboxNode(parentMailbox); - final orphanMailbox = PresentationMailbox(MailboxId(Id('22'))); - - expect(node.addChild(orphanMailbox), null); - }); - - test('addChild add new mailbox with other parentId to a node should return null', () async { - final parentMailbox = PresentationMailbox(MailboxId(Id('1'))); - final node = MailboxNode(parentMailbox); - final orphanMailbox = PresentationMailbox(MailboxId(Id('21')), parentId: MailboxId(Id('2'))); - - expect(node.addChild(orphanMailbox), null); + expect(node.childrenItems!.length, equals(2)); }); }); } \ No newline at end of file diff --git a/test/features/mailbox/presentation/model/mailbox_tree_builder_test.dart b/test/features/mailbox/presentation/model/mailbox_tree_builder_test.dart index d85627985..40364837a 100644 --- a/test/features/mailbox/presentation/model/mailbox_tree_builder_test.dart +++ b/test/features/mailbox/presentation/model/mailbox_tree_builder_test.dart @@ -11,14 +11,14 @@ void main() { final expectedTree = MailboxTree( MailboxNode( PresentationMailbox(MailboxId(Id('root'))), - child: [ + childrenItems: [ MailboxNode( PresentationMailbox(MailboxId(Id("1")), parentId: null), - child: [ + childrenItems: [ MailboxNode(PresentationMailbox(MailboxId(Id("1_1")), parentId: MailboxId(Id('1')))), MailboxNode( PresentationMailbox(MailboxId(Id("1_2")), parentId: MailboxId(Id('1'))), - child: [ + childrenItems: [ MailboxNode(PresentationMailbox(MailboxId(Id("1_2_1")), parentId: MailboxId(Id('1_2')))) ] ), @@ -26,12 +26,12 @@ void main() { ), MailboxNode( PresentationMailbox(MailboxId(Id("2")), parentId: null), - child: [ + childrenItems: [ MailboxNode(PresentationMailbox(MailboxId(Id("2_1")), parentId: MailboxId(Id('2'))), - child: [ + childrenItems: [ MailboxNode( PresentationMailbox(MailboxId(Id("2_1_1")), parentId: MailboxId(Id('2_1'))), - child: [MailboxNode(PresentationMailbox(MailboxId(Id("2_1_1_1")), parentId: MailboxId(Id('2_1_1'))))] + childrenItems: [MailboxNode(PresentationMailbox(MailboxId(Id("2_1_1_1")), parentId: MailboxId(Id('2_1_1'))))] ), MailboxNode(PresentationMailbox(MailboxId(Id("2_1_2")), parentId: MailboxId(Id('2_1')))) ] @@ -41,16 +41,16 @@ void main() { ), MailboxNode( PresentationMailbox(MailboxId(Id("3")), parentId: null), - child: [ + childrenItems: [ MailboxNode( PresentationMailbox(MailboxId(Id("3_1")), parentId: MailboxId(Id('3'))), - child: [ + childrenItems: [ MailboxNode(PresentationMailbox(MailboxId(Id("3_1_1")), parentId: MailboxId(Id('3_1')))) ] ), MailboxNode( PresentationMailbox(MailboxId(Id("3_2")), parentId: MailboxId(Id('3'))), - child: [MailboxNode(PresentationMailbox(MailboxId(Id("3_2_1")), parentId: MailboxId(Id('3_2'))))] + childrenItems: [MailboxNode(PresentationMailbox(MailboxId(Id("3_2_1")), parentId: MailboxId(Id('3_2'))))] ) ] ), @@ -103,8 +103,8 @@ void main() { final generatedTree = await TreeBuilder().generateMailboxTree(testCase); - expect(generatedTree.root.childrenItems, containsAll(expectedTree.root.childrenItems)); - expect(generatedTree.root.childrenItems[2], equals(expectedTree.root.childrenItems[0])); + expect(generatedTree.root.childrenItems, containsAll(expectedTree.root.childrenItems!)); + expect(generatedTree.root.childrenItems![2], equals(expectedTree.root.childrenItems![0])); }); test('list mailbox is not in ordered, parent come first, then grandpa, then children', () async { @@ -128,8 +128,8 @@ void main() { final generatedTree = await TreeBuilder().generateMailboxTree(testCase); - expect(generatedTree.root.childrenItems, containsAll(expectedTree.root.childrenItems)); - expect(generatedTree.root.childrenItems[2], equals(expectedTree.root.childrenItems[0])); + expect(generatedTree.root.childrenItems, containsAll(expectedTree.root.childrenItems!)); + expect(generatedTree.root.childrenItems![2], equals(expectedTree.root.childrenItems![0])); }); test('list mailbox is not in ordered, children come first, then grandpa, then parent', () async { @@ -153,8 +153,8 @@ void main() { final generatedTree = await TreeBuilder().generateMailboxTree(testCase); - expect(generatedTree.root.childrenItems, containsAll(expectedTree.root.childrenItems)); - expect(generatedTree.root.childrenItems[2], equals(expectedTree.root.childrenItems[0])); + expect(generatedTree.root.childrenItems, containsAll(expectedTree.root.childrenItems!)); + expect(generatedTree.root.childrenItems![2], equals(expectedTree.root.childrenItems![0])); }); test('list mailbox is not in ordered, children come first, then parent, then grandpa', () async { @@ -178,8 +178,8 @@ void main() { final generatedTree = await TreeBuilder().generateMailboxTree(testCase); - expect(generatedTree.root.childrenItems, containsAll(expectedTree.root.childrenItems)); - expect(generatedTree.root.childrenItems[2], equals(expectedTree.root.childrenItems[0])); + expect(generatedTree.root.childrenItems, containsAll(expectedTree.root.childrenItems!)); + expect(generatedTree.root.childrenItems![2], equals(expectedTree.root.childrenItems![0])); }); test('item have parent but not found in tree will become root child', () async { @@ -204,7 +204,7 @@ void main() { final generatedTree = await TreeBuilder().generateMailboxTree(testCase); - expect(generatedTree.root.childrenItems.length, equals(4)); + expect(generatedTree.root.childrenItems?.length, equals(4)); expect(generatedTree.root.childrenItems, contains(MailboxNode(PresentationMailbox(MailboxId(Id("e3_2_1")), parentId: MailboxId(Id('id42')))))); }); diff --git a/test/features/mailbox/presentation/model/mailbox_tree_test.dart b/test/features/mailbox/presentation/model/mailbox_tree_test.dart deleted file mode 100644 index 7cbb22d91..000000000 --- a/test/features/mailbox/presentation/model/mailbox_tree_test.dart +++ /dev/null @@ -1,101 +0,0 @@ -import 'dart:io'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:jmap_dart_client/jmap/core/id.dart'; -import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; -import 'package:model/mailbox/presentation_mailbox.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'; - -void main() { - group('test findNode in mailbox tree', () { - late MailboxTree? tree; - final level1Node = PresentationMailbox(MailboxId(Id('1'))); - final level1Node1 = PresentationMailbox(MailboxId(Id('1_1'))); - final level1Node2 = PresentationMailbox(MailboxId(Id('1_2'))); - final level2Node1 = PresentationMailbox(MailboxId(Id('2_1')), parentId: MailboxId(Id('1'))); - final level3Node1 = PresentationMailbox(MailboxId(Id('3_1')), parentId: MailboxId(Id('2_1'))); - - setUp(() { - tree = MailboxTree(MailboxNode.root()); - tree!.insertNode(level1Node); - tree!.insertNode(level1Node1); - tree!.insertNode(level1Node2); - tree!.insertNode(level2Node1); - tree!.insertNode(level3Node1); - }); - - test('findNode should find a node in tree at level 1', () { - final node1 = tree!.findNode(MailboxId(Id('1'))); - expect(node1!.item, equals(level1Node)); - }); - - test('findNode should find a node in tree at level 2', () { - final node1 = tree!.findNode(MailboxId(Id('1_2'))); - expect(node1!.item, equals(level1Node2)); - }); - - test('findNode should find a leaf in tree', () { - final node1 = tree!.findNode(MailboxId(Id('3_1'))); - expect(node1!.item, equals(level3Node1)); - }); - - test('findNode should find a node which have children in tree', () { - final node1 = tree!.findNode(MailboxId(Id('2_1'))); - expect(node1!.item, equals(level2Node1)); - expect(node1.childrenItems.length, equals(1)); - expect(node1.childrenItems[0].item, equals(level3Node1)); - }); - - test('findNode should not find a node not in tree', () { - expect(tree!.findNode(MailboxId(Id('4_1'))), null); - }); - - tearDown(() { - tree = null; - }); - }); - - group('test insertNode in mailbox tree', () { - - test('insertNode should insert a node without parent at level 1', () { - final tree = MailboxTree(MailboxNode.root()); - final mailbox = PresentationMailbox(MailboxId(Id("1"))); - final insertedNode = tree.insertNode(mailbox); - - expect(tree.root.childrenItems, contains(insertedNode)); - }); - - test('insertNode should insert a node to correctly parent', () { - final tree = MailboxTree(MailboxNode.root()); - final level1Node = PresentationMailbox(MailboxId(Id('1'))); - final level1Node1 = PresentationMailbox(MailboxId(Id('1_1'))); - final level1Node2 = PresentationMailbox(MailboxId(Id('1_2'))); - tree.insertNode(level1Node); - tree.insertNode(level1Node1); - tree.insertNode(level1Node2); - - final insertedNode = tree.insertNode(PresentationMailbox(MailboxId(Id('2_1_2')), parentId: MailboxId(Id('1_2')))); - - final foundLevel1Node2 = tree.findNode(MailboxId(Id('1_2'))); - expect(foundLevel1Node2?.childrenItems.length, equals(1)); - expect(foundLevel1Node2?.childrenItems, contains(insertedNode)); - }); - - test('insertNode should insert a node to root if parent not found', () { - final tree = MailboxTree(MailboxNode.root()); - final level1Node = PresentationMailbox(MailboxId(Id('1'))); - final level1Node1 = PresentationMailbox(MailboxId(Id('1_1'))); - final level1Node2 = PresentationMailbox(MailboxId(Id('1_2'))); - tree.insertNode(level1Node); - tree.insertNode(level1Node1); - tree.insertNode(level1Node2); - - final insertedNode = tree.insertNode(PresentationMailbox(MailboxId(Id('1_1_1_exp')), parentId: MailboxId(Id('e1_2')))); - - expect(tree.root.childrenItems.length, equals(4)); - expect(tree.root.childrenItems.map((childNode) => childNode.item).toList(), - containsAll({level1Node, level1Node2, level1Node1, insertedNode!.item})); - }); - }); -} \ No newline at end of file