TF-3007 [SEARCH] Support drag and drop between From & To field (#3154)

This commit is contained in:
Dat Vu
2024-10-08 16:31:43 +07:00
committed by Dat H. Pham
parent 7cdd6d8790
commit e584e61521
6 changed files with 203 additions and 122 deletions
@@ -9,6 +9,7 @@ import 'package:super_tag_editor/tag_editor.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
@@ -477,6 +478,24 @@ class AdvancedFilterController extends BaseController {
} }
} }
void removeDraggableEmailAddress(DraggableEmailAddress draggableEmailAddress) {
log('AdvancedFilterController::removeDraggableEmailAddress:removeDraggableEmailAddress: $draggableEmailAddress');
switch(draggableEmailAddress.prefix) {
case PrefixEmailAddress.to:
listToEmailAddress.remove(draggableEmailAddress.emailAddress);
toAddressExpandMode.value = ExpandMode.EXPAND;
toAddressExpandMode.refresh();
break;
case PrefixEmailAddress.from:
listFromEmailAddress.remove(draggableEmailAddress.emailAddress);
fromAddressExpandMode.value = ExpandMode.EXPAND;
fromAddressExpandMode.refresh();
break;
default:
break;
}
}
@override @override
void onClose() { void onClose() {
_removeFocusListener(); _removeFocusListener();
@@ -1,5 +1,6 @@
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:model/email/prefix_email_address.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
enum AdvancedSearchFilterField { enum AdvancedSearchFilterField {
@@ -64,6 +65,17 @@ enum AdvancedSearchFilterField {
color: AppColor.colorContentEmail); color: AppColor.colorContentEmail);
} }
PrefixEmailAddress getPrefixEmailAddress() {
switch (this) {
case AdvancedSearchFilterField.from:
return PrefixEmailAddress.from;
case AdvancedSearchFilterField.to:
return PrefixEmailAddress.to;
default:
return PrefixEmailAddress.cc;
}
}
TextStyle getHintTextStyle() { TextStyle getHintTextStyle() {
return const TextStyle( return const TextStyle(
fontSize: 16, fontSize: 16,
@@ -1,9 +0,0 @@
import 'package:flutter/material.dart';
class TextFieldAutocompleteEmailAddressStyle {
static const TextStyle inputTextStyle = TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w400,
);
}
@@ -39,6 +39,7 @@ class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController>
onUpdateListEmailAddressAction: controller.updateListEmailAddress, onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onSearchAction: controller.onSearchAction, onSearchAction: controller.onSearchAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
)), )),
Obx(() => TextFieldAutocompleteEmailAddressWeb( Obx(() => TextFieldAutocompleteEmailAddressWeb(
field: AdvancedSearchFilterField.to, field: AdvancedSearchFilterField.to,
@@ -52,6 +53,7 @@ class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController>
onUpdateListEmailAddressAction: controller.updateListEmailAddress, onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion, onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onSearchAction: controller.onSearchAction, onSearchAction: controller.onSearchAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
)), )),
_buildFilterField( _buildFilterField(
textEditingController: controller.subjectFilterInputController, textEditingController: controller.subjectFilterInputController,
@@ -6,6 +6,8 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:model/extensions/email_address_extension.dart'; import 'package:model/extensions/email_address_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/draggable_recipient_tag_widget.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/advanced_search_filter.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/advanced_search_filter.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/autocomplete_tag_item_web_style.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/autocomplete_tag_item_web_style.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/avatar_tag_item_widget.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/advanced_search/avatar_tag_item_widget.dart';
@@ -48,6 +50,13 @@ class AutoCompleteTagItemWidgetWeb extends StatelessWidget {
top: AutoCompleteTagItemWebStyle.paddingTop, top: AutoCompleteTagItemWebStyle.paddingTop,
end: isCollapsed ? AutoCompleteTagItemWebStyle.paddingEnd : 0, end: isCollapsed ? AutoCompleteTagItemWebStyle.paddingEnd : 0,
), ),
child: Draggable<DraggableEmailAddress>(
data: DraggableEmailAddress(
emailAddress: currentEmailAddress,
prefix: field.getPrefixEmailAddress()
),
feedback: DraggableRecipientTagWidget(emailAddress: currentEmailAddress),
childWhenDragging: DraggableRecipientTagWidget(emailAddress: currentEmailAddress),
child: TextFieldTapRegion( child: TextFieldTapRegion(
child: InkWell( child: InkWell(
onTap: () => isCollapsed onTap: () => isCollapsed
@@ -86,6 +95,7 @@ class AutoCompleteTagItemWidgetWeb extends StatelessWidget {
), ),
), ),
), ),
),
if (isCollapsed) if (isCollapsed)
TMailButtonWidget.fromText( TMailButtonWidget.fromText(
margin: AutoCompleteTagItemWebStyle.marginCollapsed, margin: AutoCompleteTagItemWebStyle.marginCollapsed,
@@ -11,6 +11,8 @@ import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:model/extensions/email_address_extension.dart'; import 'package:model/extensions/email_address_extension.dart';
import 'package:model/mailbox/expand_mode.dart'; import 'package:model/mailbox/expand_mode.dart';
import 'package:super_tag_editor/tag_editor.dart'; import 'package:super_tag_editor/tag_editor.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/recipient_composer_widget.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/advanced_search_filter.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/advanced_search_filter.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/suggesstion_email_address.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/suggesstion_email_address.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/advanced_search_input_form_style.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/advanced_search_input_form_style.dart';
@@ -40,6 +42,7 @@ class TextFieldAutocompleteEmailAddressWeb extends StatefulWidget {
final OnUpdateListEmailAddressAction? onUpdateListEmailAddressAction; final OnUpdateListEmailAddressAction? onUpdateListEmailAddressAction;
final OnDeleteEmailAddressTypeAction? onDeleteEmailAddressTypeAction; final OnDeleteEmailAddressTypeAction? onDeleteEmailAddressTypeAction;
final OnShowFullListEmailAddressAction? onShowFullListEmailAddressAction; final OnShowFullListEmailAddressAction? onShowFullListEmailAddressAction;
final OnRemoveDraggableEmailAddressAction? onRemoveDraggableEmailAddressAction;
final TextEditingController? controller; final TextEditingController? controller;
final VoidCallback? onSearchAction; final VoidCallback? onSearchAction;
@@ -58,6 +61,7 @@ class TextFieldAutocompleteEmailAddressWeb extends StatefulWidget {
this.onUpdateListEmailAddressAction, this.onUpdateListEmailAddressAction,
this.onDeleteEmailAddressTypeAction, this.onDeleteEmailAddressTypeAction,
this.onShowFullListEmailAddressAction, this.onShowFullListEmailAddressAction,
this.onRemoveDraggableEmailAddressAction,
this.controller, this.controller,
this.onSearchAction, this.onSearchAction,
}) : super(key: key); }) : super(key: key);
@@ -68,6 +72,7 @@ class TextFieldAutocompleteEmailAddressWeb extends StatefulWidget {
class _TextFieldAutocompleteEmailAddressWebState extends State<TextFieldAutocompleteEmailAddressWeb> { class _TextFieldAutocompleteEmailAddressWebState extends State<TextFieldAutocompleteEmailAddressWeb> {
bool _lastTagFocused = false; bool _lastTagFocused = false;
bool _isDragging = false;
late List<EmailAddress> _currentListEmailAddress; late List<EmailAddress> _currentListEmailAddress;
Timer? _gapBetweenTagChangedAndFindSuggestion; Timer? _gapBetweenTagChangedAndFindSuggestion;
@@ -105,6 +110,23 @@ class _TextFieldAutocompleteEmailAddressWebState extends State<TextFieldAutocomp
Expanded( Expanded(
child: StatefulBuilder( child: StatefulBuilder(
builder: ((context, setState) { builder: ((context, setState) {
return DragTarget<DraggableEmailAddress>(
onAcceptWithDetails: (draggableEmailAddress) =>
_handleAcceptDraggableEmailAddressAction(
draggableEmailAddress.data,
setState
),
onLeave: (draggableEmailAddress) {
if (_isDragging) {
setState(() => _isDragging = false);
}
},
onMove: (details) {
if (!_isDragging) {
setState(() => _isDragging = true);
}
},
builder: (_, __, ___) {
return TagEditor<SuggestionEmailAddress>( return TagEditor<SuggestionEmailAddress>(
key: widget.keyTagEditor, key: widget.keyTagEditor,
length: _collapsedListEmailAddress.length, length: _collapsedListEmailAddress.length,
@@ -132,7 +154,9 @@ class _TextFieldAutocompleteEmailAddressWebState extends State<TextFieldAutocomp
borderSize: TextFieldAutoCompleteEmailAddressWebStyles.borderWidth, borderSize: TextFieldAutoCompleteEmailAddressWebStyles.borderWidth,
focusedBorderColor: TextFieldAutoCompleteEmailAddressWebStyles.focusedBorderColor, focusedBorderColor: TextFieldAutoCompleteEmailAddressWebStyles.focusedBorderColor,
enableBorder: true, enableBorder: true,
enableBorderColor: AppColor.colorInputBorderCreateMailbox, enableBorderColor: _isDragging
? AppColor.primaryColor
: AppColor.colorInputBorderCreateMailbox,
minTextFieldWidth: TextFieldAutoCompleteEmailAddressWebStyles.minTextFieldWidth, minTextFieldWidth: TextFieldAutoCompleteEmailAddressWebStyles.minTextFieldWidth,
resetTextOnSubmitted: true, resetTextOnSubmitted: true,
autoScrollToInput: false, autoScrollToInput: false,
@@ -189,6 +213,8 @@ class _TextFieldAutocompleteEmailAddressWebState extends State<TextFieldAutocomp
} }
}, },
); );
}
);
}) })
), ),
), ),
@@ -340,4 +366,25 @@ class _TextFieldAutocompleteEmailAddressWebState extends State<TextFieldAutocomp
return null; return null;
} }
} }
void _handleAcceptDraggableEmailAddressAction(
DraggableEmailAddress draggableEmailAddress,
StateSetter stateSetter
) {
log('_TextFieldAutocompleteEmailAddressWebState::_handleAcceptDraggableEmailAddressAction:draggableEmailAddress = $draggableEmailAddress');
if (draggableEmailAddress.prefix != widget.field.getPrefixEmailAddress()) {
if (!_currentListEmailAddress.contains(draggableEmailAddress.emailAddress)) {
stateSetter(() {
_currentListEmailAddress.add(draggableEmailAddress.emailAddress);
_isDragging = false;
});
_updateListEmailAddressAction();
} else if (_isDragging) {
stateSetter(() => _isDragging = false);
}
widget.onRemoveDraggableEmailAddressAction?.call(draggableEmailAddress);
} else if (_isDragging) {
stateSetter(() => _isDragging = false);
}
}
} }