diff --git a/lib/features/base/base_mailbox_controller.dart b/lib/features/base/base_mailbox_controller.dart index 3abc95226..a430aaecf 100644 --- a/lib/features/base/base_mailbox_controller.dart +++ b/lib/features/base/base_mailbox_controller.dart @@ -17,13 +17,19 @@ abstract class BaseMailboxController extends BaseController { List allMailboxes = []; - Future buildTree(List allMailbox) async { + Future buildTree( + List allMailbox, + {MailboxId? mailboxIdSelected} + ) async { allMailboxes = allMailbox; - final tupleTree = await _treeBuilder.generateMailboxTreeInUI(allMailbox); + final tupleTree = await _treeBuilder.generateMailboxTreeInUI( + allMailbox, + mailboxIdSelected: mailboxIdSelected); defaultMailboxTree.firstRebuild = true; folderMailboxTree.firstRebuild = true; defaultMailboxTree.value = tupleTree.value1; folderMailboxTree.value = tupleTree.value2; + allMailboxes = tupleTree.value3; } Future refreshTree(List allMailbox) async { diff --git a/lib/features/destination_picker/presentation/destination_picker_controller.dart b/lib/features/destination_picker/presentation/destination_picker_controller.dart index e28ce32bf..d6be31835 100644 --- a/lib/features/destination_picker/presentation/destination_picker_controller.dart +++ b/lib/features/destination_picker/presentation/destination_picker_controller.dart @@ -60,10 +60,7 @@ class DestinationPickerController extends BaseMailboxController { newState.map((success) { if (success is GetAllMailboxSuccess) { if (mailboxAction.value == MailboxActions.move && mailboxIdSelected != null) { - final newMailboxList = success.mailboxList - .where((mailbox) => mailbox.id != mailboxIdSelected) - .toList(); - buildTree(newMailboxList); + buildTree(success.mailboxList, mailboxIdSelected: mailboxIdSelected); } else { buildTree(success.mailboxList); } diff --git a/lib/features/mailbox/presentation/model/mailbox_node.dart b/lib/features/mailbox/presentation/model/mailbox_node.dart index cc31ccbc9..d3e3ed00d 100644 --- a/lib/features/mailbox/presentation/model/mailbox_node.dart +++ b/lib/features/mailbox/presentation/model/mailbox_node.dart @@ -2,6 +2,7 @@ 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/mailbox_state.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/select_mode.dart'; @@ -12,6 +13,7 @@ class MailboxNode with EquatableMixin{ List? childrenItems; ExpandMode expandMode; SelectMode selectMode; + MailboxState nodeState; factory MailboxNode.root() => MailboxNode(_root); @@ -19,12 +21,15 @@ class MailboxNode with EquatableMixin{ bool hasChildren() => childrenItems?.isNotEmpty ?? false; + bool get isActivated => nodeState == MailboxState.activated; + MailboxNode( this.item, { this.childrenItems, this.expandMode = ExpandMode.COLLAPSE, - this.selectMode = SelectMode.INACTIVE + this.selectMode = SelectMode.INACTIVE, + this.nodeState = MailboxState.activated, } ); @@ -33,6 +38,14 @@ class MailboxNode with EquatableMixin{ childrenItems?.add(node); } + void updateNodeState(MailboxState state) { + nodeState = state; + } + + void updateItem(PresentationMailbox newItem) { + item = newItem; + } + List? updateNode(MailboxId mailboxId, MailboxNode newNode, {MailboxNode? parent}) { List? _children = parent == null ? childrenItems : parent.childrenItems; return _children?.map((MailboxNode child) { @@ -106,13 +119,16 @@ extension MailboxNodeExtension on MailboxNode { MailboxNode copyWith({ SelectMode? newSelectMode, ExpandMode? newExpandMode, + MailboxState? newNodeState, + PresentationMailbox? newItem, List? children }) { return MailboxNode( - item, + newItem ?? item, childrenItems: children ?? childrenItems, expandMode: newExpandMode ?? expandMode, selectMode: newSelectMode ?? selectMode, + nodeState: newNodeState ?? nodeState, ); } @@ -122,6 +138,7 @@ extension MailboxNodeExtension on MailboxNode { childrenItems: childrenItems, expandMode: expandMode, selectMode: selectMode == SelectMode.INACTIVE ? SelectMode.ACTIVE : SelectMode.INACTIVE, + nodeState: nodeState, ); } @@ -131,6 +148,7 @@ extension MailboxNodeExtension on MailboxNode { childrenItems: childrenItems, expandMode: newExpandMode ?? expandMode, selectMode: selectMode, + nodeState: nodeState, ); } diff --git a/lib/features/mailbox/presentation/model/mailbox_tree_builder.dart b/lib/features/mailbox/presentation/model/mailbox_tree_builder.dart index baf5af765..568a8647a 100644 --- a/lib/features/mailbox/presentation/model/mailbox_tree_builder.dart +++ b/lib/features/mailbox/presentation/model/mailbox_tree_builder.dart @@ -39,14 +39,24 @@ class TreeBuilder { return tree; } - Future> generateMailboxTreeInUI(List allMailboxes) async { + Future>> generateMailboxTreeInUI( + List allMailboxes, + {MailboxId? mailboxIdSelected} + ) async { final Map mailboxDictionary = HashMap(); final defaultTree = MailboxTree(MailboxNode.root()); final folderTree = MailboxTree(MailboxNode.root()); + List listAllMailboxes = []; for (var mailbox in allMailboxes) { - mailboxDictionary[mailbox.id] = MailboxNode(mailbox); + if (mailbox.id == mailboxIdSelected) { + mailboxDictionary[mailbox.id] = MailboxNode( + mailbox.withMailboxSate(MailboxState.deactivated), + nodeState: MailboxState.deactivated); + } else { + mailboxDictionary[mailbox.id] = MailboxNode(mailbox); + } } for (var mailbox in allMailboxes) { @@ -55,12 +65,22 @@ class TreeBuilder { final node = mailboxDictionary[mailbox.id]; if (node != null) { if (parentNode != null) { - parentNode.addChildNode(node); + if (parentNode.nodeState == MailboxState.deactivated) { + node.updateItem(mailbox.withMailboxSate(MailboxState.deactivated)); + node.updateNodeState(MailboxState.deactivated); + parentNode.addChildNode(node); + listAllMailboxes.add(node.item); + } else { + parentNode.addChildNode(node); + listAllMailboxes.add(node.item); + } parentNode.childrenItems?.sortByCompare( (node) => node.item.name, (name, other) => name?.compareAlphabetically(other) ?? -1 ); } else { + listAllMailboxes.add(node.item); + var tree = mailbox.hasRole() ? defaultTree : folderTree; tree.root.addChildNode(node); @@ -73,7 +93,7 @@ class TreeBuilder { } defaultTree.root.childrenItems?.sort((thisMailbox, thatMailbox) => thisMailbox.compareTo(thatMailbox)); - return Tuple2(defaultTree, folderTree); + return Tuple3(defaultTree, folderTree, listAllMailboxes); } Future> generateMailboxTreeInUIAfterRefreshChanges( diff --git a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart index 5a453f396..8d062ce4a 100644 --- a/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart +++ b/lib/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart @@ -100,54 +100,66 @@ class MailBoxFolderTileBuilder { ); }); } else { - return InkWell( - onTap: () => _onOpenMailboxFolderClick?.call(_mailboxNode), - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(14)), - child: Container( - color: Colors.white, - padding: const EdgeInsets.only(left: 16, top: 10, bottom: 10), - child: Row(children: [ - _buildLeadingMailboxItem(), - const SizedBox(width: 8), - Expanded(child: _buildTitleFolderItem()), - _buildSelectedIcon(), - const SizedBox(width: 8), - _buildTrailingMailboxItem() - ]) + return AbsorbPointer( + absorbing: !_mailboxNode.isActivated, + child: Opacity( + opacity: _mailboxNode.isActivated ? 1.0 : 0.3, + child: InkWell( + onTap: () => _onOpenMailboxFolderClick?.call(_mailboxNode), + radius: 14, + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(14)), + child: Container( + padding: const EdgeInsets.only(left: 16, top: 10, bottom: 10), + child: Row(children: [ + _buildLeadingMailboxItem(), + const SizedBox(width: 8), + Expanded(child: _buildTitleFolderItem()), + _buildSelectedIcon(), + const SizedBox(width: 8), + _buildTrailingMailboxItem() + ]) + ), + ), ), ), ); } } else { - return InkWell( - onTap: () => allSelectMode == SelectMode.ACTIVE - ? _onSelectMailboxFolderClick?.call(_mailboxNode) - : _onOpenMailboxFolderClick?.call(_mailboxNode), - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(14)), - child: Container( - color: Colors.white, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.symmetric( - vertical: _mailboxNode.hasChildren() ? 8 : 15), - child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - _buildLeadingMailboxItem(), - const SizedBox(width: 8), - Expanded(child: _buildTitleFolderItem()), - _buildSelectedIcon(), - const SizedBox(width: 8), - _buildTrailingMailboxItem() - ]), - ), - _buildDivider(), - ] + return AbsorbPointer( + absorbing: !_mailboxNode.isActivated, + child: Opacity( + opacity: _mailboxNode.isActivated ? 1.0 : 0.3, + child: InkWell( + onTap: () => allSelectMode == SelectMode.ACTIVE + ? _onSelectMailboxFolderClick?.call(_mailboxNode) + : _onOpenMailboxFolderClick?.call(_mailboxNode), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(14)), + child: Container( + color: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: _mailboxNode.hasChildren() ? 8 : 15), + child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + _buildLeadingMailboxItem(), + const SizedBox(width: 8), + Expanded(child: _buildTitleFolderItem()), + _buildSelectedIcon(), + const SizedBox(width: 8), + _buildTrailingMailboxItem() + ]), + ), + _buildDivider(), + ] + ) ) - ) + ), + ), ), ); } diff --git a/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart b/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart index b98dcdef3..fb7df704b 100644 --- a/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart +++ b/lib/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart @@ -68,35 +68,47 @@ class MailboxSearchTileBuilder { if (BuildUtils.isWeb) { return StatefulBuilder( builder: (BuildContext context, StateSetter setState) { - return InkWell( - onTap: () {}, - onHover: (value) => setState(() => isHoverItem = value), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: backgroundColorItem), - child: ListTile( - contentPadding: const EdgeInsets.only(left: 8), - onTap: () => _onOpenMailboxActionClick?.call(_presentationMailbox), - leading: _buildLeadingIcon(), - title: _buildTitleItem(), - subtitle: _buildSubtitleItem(), - trailing: _buildMenuIcon(), - ), - ) + return AbsorbPointer( + absorbing: !_presentationMailbox.isActivated, + child: Opacity( + opacity: _presentationMailbox.isActivated ? 1.0 : 0.3, + child: InkWell( + onTap: () {}, + onHover: (value) => setState(() => isHoverItem = value), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: backgroundColorItem), + child: ListTile( + contentPadding: const EdgeInsets.only(left: 8), + onTap: () => _onOpenMailboxActionClick?.call(_presentationMailbox), + leading: _buildLeadingIcon(), + title: _buildTitleItem(), + subtitle: _buildSubtitleItem(), + trailing: _buildMenuIcon(), + ), + ) + ), + ), ); }); } else { return Column(children: [ - ListTile( - contentPadding: EdgeInsets.zero, - onTap: () => allSelectMode == SelectMode.ACTIVE - ? _onSelectMailboxActionClick?.call(_presentationMailbox) - : _onOpenMailboxActionClick?.call(_presentationMailbox), - leading: _buildLeadingIcon(), - title: _buildTitleItem(), - subtitle: _buildSubtitleItem(), - trailing: _buildSelectedIcon(), + AbsorbPointer( + 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(), + ), + ), ), if (lastMailbox?.id != _presentationMailbox.id) Padding( diff --git a/model/lib/extensions/presentation_mailbox_extension.dart b/model/lib/extensions/presentation_mailbox_extension.dart index 2b06e95f1..8b9c768a1 100644 --- a/model/lib/extensions/presentation_mailbox_extension.dart +++ b/model/lib/extensions/presentation_mailbox_extension.dart @@ -17,7 +17,27 @@ extension PresentationMailboxExtension on PresentationMailbox { myRights: myRights, isSubscribed: isSubscribed, selectMode: selectMode, - mailboxPath: mailboxPath + mailboxPath: mailboxPath, + state: state + ); + } + + PresentationMailbox withMailboxSate(MailboxState newMailboxState) { + return PresentationMailbox( + id, + name: name, + parentId: parentId, + role: role, + sortOrder: sortOrder, + totalEmails: totalEmails, + unreadEmails: unreadEmails, + totalThreads: totalThreads, + unreadThreads: unreadThreads, + myRights: myRights, + isSubscribed: isSubscribed, + selectMode: selectMode, + mailboxPath: mailboxPath, + state: newMailboxState ); } @@ -52,6 +72,7 @@ extension PresentationMailboxExtension on PresentationMailbox { isSubscribed: isSubscribed, mailboxPath: mailboxPath, selectMode: selectMode == SelectMode.INACTIVE ? SelectMode.ACTIVE : SelectMode.INACTIVE, + state: state ); } @@ -70,6 +91,7 @@ extension PresentationMailboxExtension on PresentationMailbox { isSubscribed: isSubscribed, mailboxPath: mailboxPath, selectMode: selectMode, + state: state ); } } \ No newline at end of file diff --git a/model/lib/mailbox/mailbox_state.dart b/model/lib/mailbox/mailbox_state.dart new file mode 100644 index 000000000..76ef68cb8 --- /dev/null +++ b/model/lib/mailbox/mailbox_state.dart @@ -0,0 +1,5 @@ + +enum MailboxState { + activated, + deactivated +} \ No newline at end of file diff --git a/model/lib/mailbox/presentation_mailbox.dart b/model/lib/mailbox/presentation_mailbox.dart index 29c1d8d22..13b3c8b32 100644 --- a/model/lib/mailbox/presentation_mailbox.dart +++ b/model/lib/mailbox/presentation_mailbox.dart @@ -2,6 +2,7 @@ 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:jmap_dart_client/jmap/mail/mailbox/mailbox_rights.dart'; +import 'package:model/mailbox/mailbox_state.dart'; import 'package:model/mailbox/select_mode.dart'; class PresentationMailbox with EquatableMixin { @@ -32,6 +33,7 @@ class PresentationMailbox with EquatableMixin { final IsSubscribed? isSubscribed; final SelectMode selectMode; final String? mailboxPath; + final MailboxState? state; PresentationMailbox( this.id, @@ -48,9 +50,12 @@ class PresentationMailbox with EquatableMixin { this.isSubscribed, this.selectMode = SelectMode.INACTIVE, this.mailboxPath, + this.state = MailboxState.activated, } ); + bool get isActivated => state == MailboxState.activated; + bool hasParentId() => parentId != null && parentId!.id.value.isNotEmpty; bool hasRole() => role != null && role!.value.isNotEmpty; diff --git a/model/lib/model.dart b/model/lib/model.dart index 72ba2ea20..500367399 100644 --- a/model/lib/model.dart +++ b/model/lib/model.dart @@ -58,6 +58,7 @@ export 'mailbox/expand_mode.dart'; export 'mailbox/mailbox_property.dart'; // Mailbox export 'mailbox/presentation_mailbox.dart'; +export 'mailbox/mailbox_state.dart'; export 'mailbox/select_mode.dart'; export 'oidc/oidc_configuration.dart'; export 'oidc/request/oidc_request.dart';