TF-975 Gone all sub folder of folder when move it

This commit is contained in:
dab246
2022-09-28 18:17:35 +07:00
committed by Dat H. Pham
parent dbfaaa2b7c
commit acff7c4c94
10 changed files with 178 additions and 80 deletions
@@ -17,13 +17,19 @@ abstract class BaseMailboxController extends BaseController {
List<PresentationMailbox> allMailboxes = <PresentationMailbox>[]; List<PresentationMailbox> allMailboxes = <PresentationMailbox>[];
Future buildTree(List<PresentationMailbox> allMailbox) async { Future buildTree(
List<PresentationMailbox> allMailbox,
{MailboxId? mailboxIdSelected}
) async {
allMailboxes = allMailbox; allMailboxes = allMailbox;
final tupleTree = await _treeBuilder.generateMailboxTreeInUI(allMailbox); final tupleTree = await _treeBuilder.generateMailboxTreeInUI(
allMailbox,
mailboxIdSelected: mailboxIdSelected);
defaultMailboxTree.firstRebuild = true; defaultMailboxTree.firstRebuild = true;
folderMailboxTree.firstRebuild = true; folderMailboxTree.firstRebuild = true;
defaultMailboxTree.value = tupleTree.value1; defaultMailboxTree.value = tupleTree.value1;
folderMailboxTree.value = tupleTree.value2; folderMailboxTree.value = tupleTree.value2;
allMailboxes = tupleTree.value3;
} }
Future refreshTree(List<PresentationMailbox> allMailbox) async { Future refreshTree(List<PresentationMailbox> allMailbox) async {
@@ -60,10 +60,7 @@ class DestinationPickerController extends BaseMailboxController {
newState.map((success) { newState.map((success) {
if (success is GetAllMailboxSuccess) { if (success is GetAllMailboxSuccess) {
if (mailboxAction.value == MailboxActions.move && mailboxIdSelected != null) { if (mailboxAction.value == MailboxActions.move && mailboxIdSelected != null) {
final newMailboxList = success.mailboxList buildTree(success.mailboxList, mailboxIdSelected: mailboxIdSelected);
.where((mailbox) => mailbox.id != mailboxIdSelected)
.toList();
buildTree(newMailboxList);
} else { } else {
buildTree(success.mailboxList); buildTree(success.mailboxList);
} }
@@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/id.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.dart';
import 'package:model/mailbox/expand_mode.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/presentation_mailbox.dart';
import 'package:model/mailbox/select_mode.dart'; import 'package:model/mailbox/select_mode.dart';
@@ -12,6 +13,7 @@ class MailboxNode with EquatableMixin{
List<MailboxNode>? childrenItems; List<MailboxNode>? childrenItems;
ExpandMode expandMode; ExpandMode expandMode;
SelectMode selectMode; SelectMode selectMode;
MailboxState nodeState;
factory MailboxNode.root() => MailboxNode(_root); factory MailboxNode.root() => MailboxNode(_root);
@@ -19,12 +21,15 @@ class MailboxNode with EquatableMixin{
bool hasChildren() => childrenItems?.isNotEmpty ?? false; bool hasChildren() => childrenItems?.isNotEmpty ?? false;
bool get isActivated => nodeState == MailboxState.activated;
MailboxNode( MailboxNode(
this.item, this.item,
{ {
this.childrenItems, this.childrenItems,
this.expandMode = ExpandMode.COLLAPSE, 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); childrenItems?.add(node);
} }
void updateNodeState(MailboxState state) {
nodeState = state;
}
void updateItem(PresentationMailbox newItem) {
item = newItem;
}
List<MailboxNode>? updateNode(MailboxId mailboxId, MailboxNode newNode, {MailboxNode? parent}) { List<MailboxNode>? updateNode(MailboxId mailboxId, MailboxNode newNode, {MailboxNode? parent}) {
List<MailboxNode>? _children = parent == null ? childrenItems : parent.childrenItems; List<MailboxNode>? _children = parent == null ? childrenItems : parent.childrenItems;
return _children?.map((MailboxNode child) { return _children?.map((MailboxNode child) {
@@ -106,13 +119,16 @@ extension MailboxNodeExtension on MailboxNode {
MailboxNode copyWith({ MailboxNode copyWith({
SelectMode? newSelectMode, SelectMode? newSelectMode,
ExpandMode? newExpandMode, ExpandMode? newExpandMode,
MailboxState? newNodeState,
PresentationMailbox? newItem,
List<MailboxNode>? children List<MailboxNode>? children
}) { }) {
return MailboxNode( return MailboxNode(
item, newItem ?? item,
childrenItems: children ?? childrenItems, childrenItems: children ?? childrenItems,
expandMode: newExpandMode ?? expandMode, expandMode: newExpandMode ?? expandMode,
selectMode: newSelectMode ?? selectMode, selectMode: newSelectMode ?? selectMode,
nodeState: newNodeState ?? nodeState,
); );
} }
@@ -122,6 +138,7 @@ extension MailboxNodeExtension on MailboxNode {
childrenItems: childrenItems, childrenItems: childrenItems,
expandMode: expandMode, expandMode: expandMode,
selectMode: selectMode == SelectMode.INACTIVE ? SelectMode.ACTIVE : SelectMode.INACTIVE, selectMode: selectMode == SelectMode.INACTIVE ? SelectMode.ACTIVE : SelectMode.INACTIVE,
nodeState: nodeState,
); );
} }
@@ -131,6 +148,7 @@ extension MailboxNodeExtension on MailboxNode {
childrenItems: childrenItems, childrenItems: childrenItems,
expandMode: newExpandMode ?? expandMode, expandMode: newExpandMode ?? expandMode,
selectMode: selectMode, selectMode: selectMode,
nodeState: nodeState,
); );
} }
@@ -39,14 +39,24 @@ class TreeBuilder {
return tree; return tree;
} }
Future<Tuple2<MailboxTree, MailboxTree>> generateMailboxTreeInUI(List<PresentationMailbox> allMailboxes) async { Future<Tuple3<MailboxTree, MailboxTree, List<PresentationMailbox>>> generateMailboxTreeInUI(
List<PresentationMailbox> allMailboxes,
{MailboxId? mailboxIdSelected}
) async {
final Map<MailboxId, MailboxNode> mailboxDictionary = HashMap(); final Map<MailboxId, MailboxNode> mailboxDictionary = HashMap();
final defaultTree = MailboxTree(MailboxNode.root()); final defaultTree = MailboxTree(MailboxNode.root());
final folderTree = MailboxTree(MailboxNode.root()); final folderTree = MailboxTree(MailboxNode.root());
List<PresentationMailbox> listAllMailboxes = <PresentationMailbox>[];
for (var mailbox in allMailboxes) { 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) { for (var mailbox in allMailboxes) {
@@ -55,12 +65,22 @@ class TreeBuilder {
final node = mailboxDictionary[mailbox.id]; final node = mailboxDictionary[mailbox.id];
if (node != null) { if (node != null) {
if (parentNode != 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<MailboxName?>( parentNode.childrenItems?.sortByCompare<MailboxName?>(
(node) => node.item.name, (node) => node.item.name,
(name, other) => name?.compareAlphabetically(other) ?? -1 (name, other) => name?.compareAlphabetically(other) ?? -1
); );
} else { } else {
listAllMailboxes.add(node.item);
var tree = mailbox.hasRole() ? defaultTree : folderTree; var tree = mailbox.hasRole() ? defaultTree : folderTree;
tree.root.addChildNode(node); tree.root.addChildNode(node);
@@ -73,7 +93,7 @@ class TreeBuilder {
} }
defaultTree.root.childrenItems?.sort((thisMailbox, thatMailbox) => thisMailbox.compareTo(thatMailbox)); defaultTree.root.childrenItems?.sort((thisMailbox, thatMailbox) => thisMailbox.compareTo(thatMailbox));
return Tuple2(defaultTree, folderTree); return Tuple3(defaultTree, folderTree, listAllMailboxes);
} }
Future<Tuple2<MailboxTree, MailboxTree>> generateMailboxTreeInUIAfterRefreshChanges( Future<Tuple2<MailboxTree, MailboxTree>> generateMailboxTreeInUIAfterRefreshChanges(
@@ -100,54 +100,66 @@ class MailBoxFolderTileBuilder {
); );
}); });
} else { } else {
return InkWell( return AbsorbPointer(
onTap: () => _onOpenMailboxFolderClick?.call(_mailboxNode), absorbing: !_mailboxNode.isActivated,
child: ClipRRect( child: Opacity(
borderRadius: const BorderRadius.all(Radius.circular(14)), opacity: _mailboxNode.isActivated ? 1.0 : 0.3,
child: Container( child: InkWell(
color: Colors.white, onTap: () => _onOpenMailboxFolderClick?.call(_mailboxNode),
padding: const EdgeInsets.only(left: 16, top: 10, bottom: 10), radius: 14,
child: Row(children: [ child: ClipRRect(
_buildLeadingMailboxItem(), borderRadius: const BorderRadius.all(Radius.circular(14)),
const SizedBox(width: 8), child: Container(
Expanded(child: _buildTitleFolderItem()), padding: const EdgeInsets.only(left: 16, top: 10, bottom: 10),
_buildSelectedIcon(), child: Row(children: [
const SizedBox(width: 8), _buildLeadingMailboxItem(),
_buildTrailingMailboxItem() const SizedBox(width: 8),
]) Expanded(child: _buildTitleFolderItem()),
_buildSelectedIcon(),
const SizedBox(width: 8),
_buildTrailingMailboxItem()
])
),
),
), ),
), ),
); );
} }
} else { } else {
return InkWell( return AbsorbPointer(
onTap: () => allSelectMode == SelectMode.ACTIVE absorbing: !_mailboxNode.isActivated,
? _onSelectMailboxFolderClick?.call(_mailboxNode) child: Opacity(
: _onOpenMailboxFolderClick?.call(_mailboxNode), opacity: _mailboxNode.isActivated ? 1.0 : 0.3,
child: ClipRRect( child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(14)), onTap: () => allSelectMode == SelectMode.ACTIVE
child: Container( ? _onSelectMailboxFolderClick?.call(_mailboxNode)
color: Colors.white, : _onOpenMailboxFolderClick?.call(_mailboxNode),
child: Column( child: ClipRRect(
mainAxisSize: MainAxisSize.min, borderRadius: const BorderRadius.all(Radius.circular(14)),
mainAxisAlignment: MainAxisAlignment.center, child: Container(
children: [ color: Colors.white,
Padding( child: Column(
padding: EdgeInsets.symmetric( mainAxisSize: MainAxisSize.min,
vertical: _mailboxNode.hasChildren() ? 8 : 15), mainAxisAlignment: MainAxisAlignment.center,
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ children: [
_buildLeadingMailboxItem(), Padding(
const SizedBox(width: 8), padding: EdgeInsets.symmetric(
Expanded(child: _buildTitleFolderItem()), vertical: _mailboxNode.hasChildren() ? 8 : 15),
_buildSelectedIcon(), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
const SizedBox(width: 8), _buildLeadingMailboxItem(),
_buildTrailingMailboxItem() const SizedBox(width: 8),
]), Expanded(child: _buildTitleFolderItem()),
), _buildSelectedIcon(),
_buildDivider(), const SizedBox(width: 8),
] _buildTrailingMailboxItem()
]),
),
_buildDivider(),
]
)
) )
) ),
),
), ),
); );
} }
@@ -68,35 +68,47 @@ class MailboxSearchTileBuilder {
if (BuildUtils.isWeb) { if (BuildUtils.isWeb) {
return StatefulBuilder( return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) { builder: (BuildContext context, StateSetter setState) {
return InkWell( return AbsorbPointer(
onTap: () {}, absorbing: !_presentationMailbox.isActivated,
onHover: (value) => setState(() => isHoverItem = value), child: Opacity(
child: Container( opacity: _presentationMailbox.isActivated ? 1.0 : 0.3,
decoration: BoxDecoration( child: InkWell(
borderRadius: BorderRadius.circular(10), onTap: () {},
color: backgroundColorItem), onHover: (value) => setState(() => isHoverItem = value),
child: ListTile( child: Container(
contentPadding: const EdgeInsets.only(left: 8), decoration: BoxDecoration(
onTap: () => _onOpenMailboxActionClick?.call(_presentationMailbox), borderRadius: BorderRadius.circular(10),
leading: _buildLeadingIcon(), color: backgroundColorItem),
title: _buildTitleItem(), child: ListTile(
subtitle: _buildSubtitleItem(), contentPadding: const EdgeInsets.only(left: 8),
trailing: _buildMenuIcon(), onTap: () => _onOpenMailboxActionClick?.call(_presentationMailbox),
), leading: _buildLeadingIcon(),
) title: _buildTitleItem(),
subtitle: _buildSubtitleItem(),
trailing: _buildMenuIcon(),
),
)
),
),
); );
}); });
} else { } else {
return Column(children: [ return Column(children: [
ListTile( AbsorbPointer(
contentPadding: EdgeInsets.zero, absorbing: !_presentationMailbox.isActivated,
onTap: () => allSelectMode == SelectMode.ACTIVE child: Opacity(
? _onSelectMailboxActionClick?.call(_presentationMailbox) opacity: _presentationMailbox.isActivated ? 1.0 : 0.3,
: _onOpenMailboxActionClick?.call(_presentationMailbox), child: ListTile(
leading: _buildLeadingIcon(), contentPadding: EdgeInsets.zero,
title: _buildTitleItem(), onTap: () => allSelectMode == SelectMode.ACTIVE
subtitle: _buildSubtitleItem(), ? _onSelectMailboxActionClick?.call(_presentationMailbox)
trailing: _buildSelectedIcon(), : _onOpenMailboxActionClick?.call(_presentationMailbox),
leading: _buildLeadingIcon(),
title: _buildTitleItem(),
subtitle: _buildSubtitleItem(),
trailing: _buildSelectedIcon(),
),
),
), ),
if (lastMailbox?.id != _presentationMailbox.id) if (lastMailbox?.id != _presentationMailbox.id)
Padding( Padding(
@@ -17,7 +17,27 @@ extension PresentationMailboxExtension on PresentationMailbox {
myRights: myRights, myRights: myRights,
isSubscribed: isSubscribed, isSubscribed: isSubscribed,
selectMode: selectMode, 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, isSubscribed: isSubscribed,
mailboxPath: mailboxPath, mailboxPath: mailboxPath,
selectMode: selectMode == SelectMode.INACTIVE ? SelectMode.ACTIVE : SelectMode.INACTIVE, selectMode: selectMode == SelectMode.INACTIVE ? SelectMode.ACTIVE : SelectMode.INACTIVE,
state: state
); );
} }
@@ -70,6 +91,7 @@ extension PresentationMailboxExtension on PresentationMailbox {
isSubscribed: isSubscribed, isSubscribed: isSubscribed,
mailboxPath: mailboxPath, mailboxPath: mailboxPath,
selectMode: selectMode, selectMode: selectMode,
state: state
); );
} }
} }
+5
View File
@@ -0,0 +1,5 @@
enum MailboxState {
activated,
deactivated
}
@@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/id.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.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox_rights.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'; import 'package:model/mailbox/select_mode.dart';
class PresentationMailbox with EquatableMixin { class PresentationMailbox with EquatableMixin {
@@ -32,6 +33,7 @@ class PresentationMailbox with EquatableMixin {
final IsSubscribed? isSubscribed; final IsSubscribed? isSubscribed;
final SelectMode selectMode; final SelectMode selectMode;
final String? mailboxPath; final String? mailboxPath;
final MailboxState? state;
PresentationMailbox( PresentationMailbox(
this.id, this.id,
@@ -48,9 +50,12 @@ class PresentationMailbox with EquatableMixin {
this.isSubscribed, this.isSubscribed,
this.selectMode = SelectMode.INACTIVE, this.selectMode = SelectMode.INACTIVE,
this.mailboxPath, this.mailboxPath,
this.state = MailboxState.activated,
} }
); );
bool get isActivated => state == MailboxState.activated;
bool hasParentId() => parentId != null && parentId!.id.value.isNotEmpty; bool hasParentId() => parentId != null && parentId!.id.value.isNotEmpty;
bool hasRole() => role != null && role!.value.isNotEmpty; bool hasRole() => role != null && role!.value.isNotEmpty;
+1
View File
@@ -58,6 +58,7 @@ export 'mailbox/expand_mode.dart';
export 'mailbox/mailbox_property.dart'; export 'mailbox/mailbox_property.dart';
// Mailbox // Mailbox
export 'mailbox/presentation_mailbox.dart'; export 'mailbox/presentation_mailbox.dart';
export 'mailbox/mailbox_state.dart';
export 'mailbox/select_mode.dart'; export 'mailbox/select_mode.dart';
export 'oidc/oidc_configuration.dart'; export 'oidc/oidc_configuration.dart';
export 'oidc/request/oidc_request.dart'; export 'oidc/request/oidc_request.dart';