TF-987: make email range selection function simple

This commit is contained in:
ManhNTX
2022-11-05 18:25:31 +07:00
committed by Dat H. Pham
parent e4cf4808cb
commit eda6c0271f
6 changed files with 91 additions and 82 deletions
@@ -55,8 +55,8 @@ class TopBarThreadSelection {
buildIconWeb( buildIconWeb(
icon: SvgPicture.asset( icon: SvgPicture.asset(
listEmail.isAllEmailRead listEmail.isAllEmailRead
? imagePaths.icUnread ? imagePaths.icRead
: imagePaths.icRead, : imagePaths.icUnread,
fit: BoxFit.fill), fit: BoxFit.fill),
tooltip: listEmail.isAllEmailRead tooltip: listEmail.isAllEmailRead
? AppLocalizations.of(context).mark_as_unread ? AppLocalizations.of(context).mark_as_unread
@@ -60,8 +60,8 @@ class AppBarSelectionMode extends StatelessWidget {
splashRadius: 15, splashRadius: 15,
icon: SvgPicture.asset( icon: SvgPicture.asset(
listEmail.isAllEmailRead listEmail.isAllEmailRead
? _imagePaths.icUnread ? _imagePaths.icRead
: _imagePaths.icRead, : _imagePaths.icUnread,
fit: BoxFit.fill), fit: BoxFit.fill),
tooltip: listEmail.isAllEmailRead tooltip: listEmail.isAllEmailRead
? AppLocalizations.of(context).unread ? AppLocalizations.of(context).unread
@@ -101,7 +101,7 @@ class ThreadController extends BaseController {
final CachingManager _cachingManager; final CachingManager _cachingManager;
final listEmailDrag = <PresentationEmail>[].obs; final listEmailDrag = <PresentationEmail>[].obs;
bool shiftSelectedMode = false; bool _rangeSelectionMode = false;
bool canLoadMore = true; bool canLoadMore = true;
bool canSearchMore = true; bool canSearchMore = true;
bool _isLoadingMore = false; bool _isLoadingMore = false;
@@ -110,7 +110,7 @@ class ThreadController extends BaseController {
jmap.State? _currentEmailState; jmap.State? _currentEmailState;
final ScrollController listEmailController = ScrollController(); final ScrollController listEmailController = ScrollController();
final FocusNode focusNodeKeyBoard = FocusNode(); final FocusNode focusNodeKeyBoard = FocusNode();
final latestEmailAction = Rxn<PresentationEmail>(); final latestEmailInteracted = Rxn<PresentationEmail>();
late Worker mailboxWorker, searchWorker, dashboardActionWorker, viewStateWorker, advancedSearchFilterWorker; late Worker mailboxWorker, searchWorker, dashboardActionWorker, viewStateWorker, advancedSearchFilterWorker;
Set<Comparator>? get _sortOrder => <Comparator>{} Set<Comparator>? get _sortOrder => <Comparator>{}
@@ -520,44 +520,48 @@ class ThreadController extends BaseController {
mailboxDashBoardController.dispatchRoute(DashboardRoutes.emailDetailed); mailboxDashBoardController.dispatchRoute(DashboardRoutes.emailDetailed);
} }
void _shiftSelectEmail(PresentationEmail presentationEmailSelected) { Tuple2<int,int> _getSelectionEmailsRange(PresentationEmail presentationEmailSelected) {
int startIndexAction = 0; final emailSelectedIndex = emailList.indexWhere((e) => e.id == presentationEmailSelected.id);
int endIndexAction = 0; final latestEmailInteractedIndex = emailList.indexWhere((e) => e.id == latestEmailInteracted.value?.id);
final indexOfPresentationEmailSelected = emailList.indexWhere((e) => e.id == presentationEmailSelected.id); if (emailSelectedIndex > latestEmailInteractedIndex) {
final indexOfLatestEmailAction = emailList.indexWhere((e) => e.id == latestEmailAction.value?.id); return Tuple2(latestEmailInteractedIndex, emailSelectedIndex);
if (indexOfPresentationEmailSelected > indexOfLatestEmailAction) {
startIndexAction = indexOfLatestEmailAction;
endIndexAction = indexOfPresentationEmailSelected;
} else { } else {
startIndexAction = indexOfPresentationEmailSelected; return Tuple2(emailSelectedIndex, latestEmailInteractedIndex);
endIndexAction = indexOfLatestEmailAction;
} }
}
final enableChangeSelectModeOfEmailsToActive = latestEmailAction.value?.selectMode == SelectMode.ACTIVE && bool _checkAllowMakeRangeEmailsSelected(Tuple2<int,int> selectionEmailsRange) {
!emailList.sublist(startIndexAction, endIndexAction).every((e) => e.selectMode == SelectMode.ACTIVE) || return latestEmailInteracted.value?.selectMode == SelectMode.ACTIVE &&
latestEmailAction.value?.selectMode == SelectMode.INACTIVE && !emailList.sublist(selectionEmailsRange.value1, selectionEmailsRange.value2).every((e) => e.selectMode == SelectMode.ACTIVE) ||
emailList.sublist(startIndexAction, endIndexAction).every((e) => e.selectMode == SelectMode.INACTIVE); latestEmailInteracted.value?.selectMode == SelectMode.INACTIVE &&
emailList.sublist(selectionEmailsRange.value1, selectionEmailsRange.value2).every((e) => e.selectMode == SelectMode.INACTIVE);
}
if (enableChangeSelectModeOfEmailsToActive) { void _applySelectModeToRangeEmails(Tuple2<int,int> selectionEmailsRange, SelectMode selectMode) {
emailList.value = emailList.asMap().map((index, email) { emailList.value = emailList.asMap().map((index, email) {
return MapEntry(index, index >= startIndexAction && index <= endIndexAction ? email.toSelectedEmail(selectMode: SelectMode.ACTIVE) : email); return MapEntry(index, index >= selectionEmailsRange.value1 && index <= selectionEmailsRange.value2 ? email.toSelectedEmail(selectMode: selectMode) : email);
}).values.toList(); }).values.toList();
}
void _rangeSelectionEmailsAction(PresentationEmail presentationEmailSelected) {
final selectionEmailsRange = _getSelectionEmailsRange(presentationEmailSelected);
if (_checkAllowMakeRangeEmailsSelected(selectionEmailsRange)) {
_applySelectModeToRangeEmails(selectionEmailsRange, SelectMode.ACTIVE);
} else { } else {
emailList.value = emailList.asMap().map((index, email) { _applySelectModeToRangeEmails(selectionEmailsRange, SelectMode.INACTIVE);
return MapEntry(index, index >= startIndexAction && index <= endIndexAction ? email.toSelectedEmail(selectMode: SelectMode.INACTIVE) : email);
}).values.toList();
} }
} }
void selectEmail(BuildContext context, PresentationEmail presentationEmailSelected) { void selectEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
if (shiftSelectedMode && latestEmailAction.value != null && latestEmailAction.value?.id != presentationEmailSelected.id) { if (_rangeSelectionMode && latestEmailInteracted.value != null && latestEmailInteracted.value?.id != presentationEmailSelected.id) {
_shiftSelectEmail(presentationEmailSelected); _rangeSelectionEmailsAction(presentationEmailSelected);
} else { } else {
emailList.value = emailList emailList.value = emailList
.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email) .map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email)
.toList(); .toList();
} }
latestEmailAction.value = emailList.firstWhere((e) => e.id == presentationEmailSelected.id); latestEmailInteracted.value = emailList.firstWhere((e) => e.id == presentationEmailSelected.id);
focusNodeKeyBoard.requestFocus(); focusNodeKeyBoard.requestFocus();
if (_isUnSelectedAll()) { if (_isUnSelectedAll()) {
mailboxDashBoardController.currentSelectMode.value = SelectMode.INACTIVE; mailboxDashBoardController.currentSelectMode.value = SelectMode.INACTIVE;
@@ -1512,11 +1516,11 @@ class ThreadController extends BaseController {
KeyEventResult handleKeyEvent(FocusNode node, RawKeyEvent event) { KeyEventResult handleKeyEvent(FocusNode node, RawKeyEvent event) {
final shiftEvent = event.logicalKey == LogicalKeyboardKey.shiftLeft || event.logicalKey == LogicalKeyboardKey.shiftRight; final shiftEvent = event.logicalKey == LogicalKeyboardKey.shiftLeft || event.logicalKey == LogicalKeyboardKey.shiftRight;
if (event is RawKeyDownEvent && shiftEvent) { if (event is RawKeyDownEvent && shiftEvent) {
shiftSelectedMode = true; _rangeSelectionMode = true;
} }
if (event is RawKeyUpEvent && shiftEvent) { if (event is RawKeyUpEvent && shiftEvent) {
shiftSelectedMode = false; _rangeSelectionMode = false;
} }
return shiftEvent return shiftEvent
? KeyEventResult.handled ? KeyEventResult.handled
@@ -319,59 +319,64 @@ class ThreadView extends GetWidget<ThreadController> with AppLoaderMixin,
} }
return false; return false;
}, },
child: ListView.builder( child: Focus(
controller: controller.listEmailController, focusNode: controller.focusNodeKeyBoard,
physics: const AlwaysScrollableScrollPhysics(), autofocus: kIsWeb,
padding: EdgeInsets.zero, onKey: kIsWeb ? controller.handleKeyEvent : null,
key: const PageStorageKey('list_presentation_email_in_threads'), child: ListView.builder(
itemExtent: _getItemExtent(context), controller: controller.listEmailController,
itemCount: listPresentationEmail.length, physics: const AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) { padding: EdgeInsets.zero,
return Obx(() => Draggable<List<PresentationEmail>>( key: const PageStorageKey('list_presentation_email_in_threads'),
maxSimultaneousDrags: kIsWeb ? null : 0, itemExtent: _getItemExtent(context),
data: controller.listEmailDrag, itemCount: listPresentationEmail.length,
child: (EmailTileBuilder( itemBuilder: (context, index) {
context, return Obx(() => Draggable<List<PresentationEmail>>(
listPresentationEmail[index], maxSimultaneousDrags: kIsWeb ? null : 0,
controller.mailboxDashBoardController.currentSelectMode.value, data: controller.listEmailDrag,
controller.searchQuery, child: (EmailTileBuilder(
controller.mailboxDashBoardController.selectedEmail.value?.id == listPresentationEmail[index].id,
mailboxCurrent: controller.searchController.isSearchEmailRunning
? listPresentationEmail[index].findMailboxContain(controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox,
isSearchEmailRunning: controller.searchController.isSearchEmailRunning)
..addOnPressEmailActionClick((action, email) =>
controller.pressEmailAction(
context,
action,
email,
mailboxContain: controller.searchController.isSearchEmailRunning
? email.findMailboxContain(controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox))
..addOnMoreActionClick((email, position) => _responsiveUtils.isMobile(context)
? controller.openContextMenuAction(context, _contextMenuActionTile(context, email))
: controller.openPopupMenuAction(context, position, _popupMenuActionTile(context, email)))
).build(),
feedback: _buildFeedBackWidget(context),
childWhenDragging: (EmailTileBuilder(
context, context,
listPresentationEmail[index], listPresentationEmail[index],
controller.mailboxDashBoardController.currentSelectMode.value, controller.mailboxDashBoardController.currentSelectMode.value,
controller.searchQuery, controller.searchQuery,
controller.mailboxDashBoardController.selectedEmail.value?.id == listPresentationEmail[index].id, controller.mailboxDashBoardController.selectedEmail.value?.id == listPresentationEmail[index].id,
mailboxCurrent: controller.searchController.isSearchEmailRunning mailboxCurrent: controller.searchController.isSearchEmailRunning
? listPresentationEmail[index].findMailboxContain( ? listPresentationEmail[index].findMailboxContain(controller.mailboxDashBoardController.mapMailboxById)
controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox, : controller.currentMailbox,
isSearchEmailRunning: controller.searchController.isSearchEmailRunning, isSearchEmailRunning: controller.searchController.isSearchEmailRunning)
isDrag: true) ..addOnPressEmailActionClick((action, email) =>
).build(), controller.pressEmailAction(
dragAnchorStrategy: pointerDragAnchorStrategy, context,
onDragStarted: () { action,
controller.calculateDragValue(listPresentationEmail[index]); email,
}, mailboxContain: controller.searchController.isSearchEmailRunning
)); ? email.findMailboxContain(controller.mailboxDashBoardController.mapMailboxById)
}) : controller.currentMailbox))
..addOnMoreActionClick((email, position) => _responsiveUtils.isMobile(context)
? controller.openContextMenuAction(context, _contextMenuActionTile(context, email))
: controller.openPopupMenuAction(context, position, _popupMenuActionTile(context, email)))
).build(),
feedback: _buildFeedBackWidget(context),
childWhenDragging: (EmailTileBuilder(
context,
listPresentationEmail[index],
controller.mailboxDashBoardController.currentSelectMode.value,
controller.searchQuery,
controller.mailboxDashBoardController.selectedEmail.value?.id == listPresentationEmail[index].id,
mailboxCurrent: controller.searchController.isSearchEmailRunning
? listPresentationEmail[index].findMailboxContain(
controller.mailboxDashBoardController.mapMailboxById)
: controller.currentMailbox,
isSearchEmailRunning: controller.searchController.isSearchEmailRunning,
isDrag: true)
).build(),
dragAnchorStrategy: pointerDragAnchorStrategy,
onDragStarted: () {
controller.calculateDragValue(listPresentationEmail[index]);
},
));
}),
)
); );
} }
@@ -112,8 +112,8 @@ class AppBarThreadWidgetBuilder extends StatelessWidget {
splashRadius: 15, splashRadius: 15,
icon: SvgPicture.asset( icon: SvgPicture.asset(
_listSelectionEmail.isAllEmailRead _listSelectionEmail.isAllEmailRead
? _imagePaths.icUnread ? _imagePaths.icRead
: _imagePaths.icRead, : _imagePaths.icUnread,
fit: BoxFit.fill), fit: BoxFit.fill),
tooltip: _listSelectionEmail.isAllEmailRead tooltip: _listSelectionEmail.isAllEmailRead
? AppLocalizations.of(context).unread ? AppLocalizations.of(context).unread
@@ -393,8 +393,8 @@ class EmailTileBuilder with BaseEmailItemTile {
splashRadius: 10, splashRadius: 10,
icon: SvgPicture.asset( icon: SvgPicture.asset(
_presentationEmail.hasRead _presentationEmail.hasRead
? imagePaths.icUnread ? imagePaths.icRead
: imagePaths.icRead, : imagePaths.icUnread,
color: AppColor.colorActionButtonHover, color: AppColor.colorActionButtonHover,
width: 16, width: 16,
height: 16, height: 16,