TF-2119 Disable drag and drop recipients on mobile

(cherry picked from commit d1760dbdbac30a3af13fd6a7dca97236484dbd9a)
This commit is contained in:
dab246
2023-09-15 00:46:35 +07:00
committed by Dat H. Pham
parent e1dd99c613
commit c3a6d0f4d8
3 changed files with 218 additions and 124 deletions
@@ -118,7 +118,6 @@ class ComposerView extends GetWidget<ComposerController> {
onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
RecipientComposerWidget(
@@ -139,7 +138,6 @@ class ComposerView extends GetWidget<ComposerController> {
onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
RecipientComposerWidget(
@@ -160,7 +158,6 @@ class ComposerView extends GetWidget<ComposerController> {
onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
],
)),
@@ -262,7 +259,6 @@ class ComposerView extends GetWidget<ComposerController> {
onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
RecipientComposerWidget(
@@ -283,7 +279,6 @@ class ComposerView extends GetWidget<ComposerController> {
onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
RecipientComposerWidget(
@@ -304,7 +299,6 @@ class ComposerView extends GetWidget<ComposerController> {
onUpdateListEmailAddressAction: controller.updateListEmailAddress,
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
),
],
)),
@@ -5,6 +5,7 @@ import 'package:collection/collection.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
@@ -146,82 +147,143 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
},
child: StatefulBuilder(
builder: (context, stateSetter) {
return DragTarget<DraggableEmailAddress>(
builder: (context, candidateData, rejectedData) {
return TagEditor<SuggestionEmailAddress>(
key: widget.keyTagEditor,
length: _collapsedListEmailAddress.length,
controller: widget.controller,
focusNode: widget.focusNode,
enableBorder: _isDragging,
borderRadius: RecipientComposerWidgetStyle.enableBorderRadius,
enableBorderColor: RecipientComposerWidgetStyle.enableBorderColor,
autoDisposeFocusNode: widget.autoDisposeFocusNode,
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
debounceDuration: const Duration(milliseconds: 150),
hasAddButton: false,
tagSpacing: 8,
autofocus: widget.prefix != PrefixEmailAddress.to && _currentListEmailAddress.isEmpty,
minTextFieldWidth: 20,
resetTextOnSubmitted: true,
suggestionsBoxElevation: 20.0,
suggestionsBoxBackgroundColor: Colors.white,
suggestionsBoxRadius: 20,
suggestionsBoxMaxHeight: 350,
textStyle: RecipientComposerWidgetStyle.inputTextStyle,
onFocusTagAction: (focused) => _handleFocusTagAction.call(focused, stateSetter),
onDeleteTagAction: () => _handleDeleteLatestTagAction.call(stateSetter),
onSelectOptionAction: (item) => _handleSelectOptionAction.call(item, stateSetter),
onSubmitted: (value) => _handleSubmitTagAction.call(value, stateSetter),
inputDecoration: const InputDecoration(border: InputBorder.none),
tagBuilder: (context, index) {
final currentEmailAddress = _currentListEmailAddress[index];
final isLatestEmail = currentEmailAddress == _currentListEmailAddress.last;
if (PlatformInfo.isWeb) {
return DragTarget<DraggableEmailAddress>(
builder: (context, candidateData, rejectedData) {
return TagEditor<SuggestionEmailAddress>(
key: widget.keyTagEditor,
length: _collapsedListEmailAddress.length,
controller: widget.controller,
focusNode: widget.focusNode,
enableBorder: _isDragging,
borderRadius: RecipientComposerWidgetStyle.enableBorderRadius,
enableBorderColor: RecipientComposerWidgetStyle.enableBorderColor,
autoDisposeFocusNode: widget.autoDisposeFocusNode,
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
debounceDuration: const Duration(milliseconds: 150),
hasAddButton: false,
tagSpacing: 8,
autofocus: widget.prefix != PrefixEmailAddress.to && _currentListEmailAddress.isEmpty,
minTextFieldWidth: 20,
resetTextOnSubmitted: true,
suggestionsBoxElevation: 20.0,
suggestionsBoxBackgroundColor: Colors.white,
suggestionsBoxRadius: 20,
suggestionsBoxMaxHeight: 350,
textStyle: RecipientComposerWidgetStyle.inputTextStyle,
onFocusTagAction: (focused) => _handleFocusTagAction.call(focused, stateSetter),
onDeleteTagAction: () => _handleDeleteLatestTagAction.call(stateSetter),
onSelectOptionAction: (item) => _handleSelectOptionAction.call(item, stateSetter),
onSubmitted: (value) => _handleSubmitTagAction.call(value, stateSetter),
inputDecoration: const InputDecoration(border: InputBorder.none),
tagBuilder: (context, index) {
final currentEmailAddress = _currentListEmailAddress[index];
final isLatestEmail = currentEmailAddress == _currentListEmailAddress.last;
return RecipientTagItemWidget(
prefix: widget.prefix,
currentEmailAddress: currentEmailAddress,
currentListEmailAddress: _currentListEmailAddress,
collapsedListEmailAddress: _collapsedListEmailAddress,
isLatestEmail: isLatestEmail,
isCollapsed: _isCollapse,
isLatestTagFocused: _lastTagFocused,
onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, stateSetter),
onShowFullAction: widget.onShowFullListEmailAddressAction,
);
},
onTagChanged: (value) => _handleOnTagChangeAction.call(value, stateSetter),
findSuggestions: _findSuggestions,
useDefaultHighlight: false,
suggestionBuilder: (context, tagEditorState, suggestionEmailAddress, index, length, highlight, suggestionValid) {
return RecipientSuggestionItemWidget(
suggestionState: suggestionEmailAddress.state,
emailAddress: suggestionEmailAddress.emailAddress,
suggestionValid: suggestionValid,
highlight: highlight,
onSelectedAction: (emailAddress) {
stateSetter(() => _currentListEmailAddress.add(emailAddress));
_updateListEmailAddressAction();
tagEditorState.resetTextField();
tagEditorState.closeSuggestionBox();
},
);
},
);
},
onAccept: (draggableEmailAddress) => _handleAcceptDraggableEmailAddressAction(draggableEmailAddress, stateSetter),
onLeave: (draggableEmailAddress) {
if (_isDragging) {
stateSetter(() => _isDragging = false);
}
},
onMove: (details) {
if (!_isDragging) {
stateSetter(() => _isDragging = true);
}
},
);
return RecipientTagItemWidget(
prefix: widget.prefix,
currentEmailAddress: currentEmailAddress,
currentListEmailAddress: _currentListEmailAddress,
collapsedListEmailAddress: _collapsedListEmailAddress,
isLatestEmail: isLatestEmail,
isCollapsed: _isCollapse,
isLatestTagFocused: _lastTagFocused,
onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, stateSetter),
onShowFullAction: widget.onShowFullListEmailAddressAction,
);
},
onTagChanged: (value) => _handleOnTagChangeAction.call(value, stateSetter),
findSuggestions: _findSuggestions,
useDefaultHighlight: false,
suggestionBuilder: (context, tagEditorState, suggestionEmailAddress, index, length, highlight, suggestionValid) {
return RecipientSuggestionItemWidget(
suggestionState: suggestionEmailAddress.state,
emailAddress: suggestionEmailAddress.emailAddress,
suggestionValid: suggestionValid,
highlight: highlight,
onSelectedAction: (emailAddress) {
stateSetter(() => _currentListEmailAddress.add(emailAddress));
_updateListEmailAddressAction();
tagEditorState.resetTextField();
tagEditorState.closeSuggestionBox();
},
);
},
);
},
onAccept: (draggableEmailAddress) => _handleAcceptDraggableEmailAddressAction(draggableEmailAddress, stateSetter),
onLeave: (draggableEmailAddress) {
if (_isDragging) {
stateSetter(() => _isDragging = false);
}
},
onMove: (details) {
if (!_isDragging) {
stateSetter(() => _isDragging = true);
}
},
);
} else {
return TagEditor<SuggestionEmailAddress>(
key: widget.keyTagEditor,
length: _collapsedListEmailAddress.length,
controller: widget.controller,
focusNode: widget.focusNode,
autoDisposeFocusNode: widget.autoDisposeFocusNode,
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
debounceDuration: const Duration(milliseconds: 150),
hasAddButton: false,
tagSpacing: 8,
autofocus: widget.prefix != PrefixEmailAddress.to && _currentListEmailAddress.isEmpty,
minTextFieldWidth: 20,
resetTextOnSubmitted: true,
suggestionsBoxElevation: 20.0,
suggestionsBoxBackgroundColor: Colors.white,
suggestionsBoxRadius: 20,
suggestionsBoxMaxHeight: 350,
textStyle: RecipientComposerWidgetStyle.inputTextStyle,
onFocusTagAction: (focused) => _handleFocusTagAction.call(focused, stateSetter),
onDeleteTagAction: () => _handleDeleteLatestTagAction.call(stateSetter),
onSelectOptionAction: (item) => _handleSelectOptionAction.call(item, stateSetter),
onSubmitted: (value) => _handleSubmitTagAction.call(value, stateSetter),
inputDecoration: const InputDecoration(border: InputBorder.none),
tagBuilder: (context, index) {
final currentEmailAddress = _currentListEmailAddress[index];
final isLatestEmail = currentEmailAddress == _currentListEmailAddress.last;
return RecipientTagItemWidget(
prefix: widget.prefix,
currentEmailAddress: currentEmailAddress,
currentListEmailAddress: _currentListEmailAddress,
collapsedListEmailAddress: _collapsedListEmailAddress,
isLatestEmail: isLatestEmail,
isCollapsed: _isCollapse,
isLatestTagFocused: _lastTagFocused,
onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, stateSetter),
onShowFullAction: widget.onShowFullListEmailAddressAction,
);
},
onTagChanged: (value) => _handleOnTagChangeAction.call(value, stateSetter),
findSuggestions: _findSuggestions,
useDefaultHighlight: false,
suggestionBuilder: (context, tagEditorState, suggestionEmailAddress, index, length, highlight, suggestionValid) {
return RecipientSuggestionItemWidget(
suggestionState: suggestionEmailAddress.state,
emailAddress: suggestionEmailAddress.emailAddress,
suggestionValid: suggestionValid,
highlight: highlight,
onSelectedAction: (emailAddress) {
stateSetter(() => _currentListEmailAddress.add(emailAddress));
_updateListEmailAddressAction();
tagEditorState.resetTextField();
tagEditorState.closeSuggestionBox();
},
);
},
);
}
},
)
)
@@ -49,52 +49,90 @@ class RecipientTagItemWidget extends StatelessWidget {
return Stack(
alignment: AlignmentDirectional.centerEnd,
children: [
Padding(
padding: EdgeInsetsDirectional.only(
top: PlatformInfo.isWeb ? 8 : 0,
end: isCollapsed ? 40 : 0),
child: InkWell(
onTap: () => isCollapsed
? onShowFullAction?.call(prefix)
: null,
child: Draggable<DraggableEmailAddress>(
data: DraggableEmailAddress(emailAddress: currentEmailAddress, prefix: prefix),
feedback: DraggableRecipientTagWidget(emailAddress: currentEmailAddress),
childWhenDragging: DraggableRecipientTagWidget(emailAddress: currentEmailAddress),
child: MouseRegion(
cursor: SystemMouseCursors.grab,
child: Chip(
labelPadding: EdgeInsetsDirectional.symmetric(
horizontal: 4,
vertical: DirectionUtils.isDirectionRTLByHasAnyRtl(currentEmailAddress.asString()) ? 0 : 2
if (PlatformInfo.isWeb)
Padding(
padding: EdgeInsetsDirectional.only(
top: 8,
end: isCollapsed ? 40 : 0),
child: InkWell(
onTap: () => isCollapsed
? onShowFullAction?.call(prefix)
: null,
child: Draggable<DraggableEmailAddress>(
data: DraggableEmailAddress(emailAddress: currentEmailAddress, prefix: prefix),
feedback: DraggableRecipientTagWidget(emailAddress: currentEmailAddress),
childWhenDragging: DraggableRecipientTagWidget(emailAddress: currentEmailAddress),
child: MouseRegion(
cursor: SystemMouseCursors.grab,
child: Chip(
labelPadding: EdgeInsetsDirectional.symmetric(
horizontal: 4,
vertical: DirectionUtils.isDirectionRTLByHasAnyRtl(currentEmailAddress.asString()) ? 0 : 2
),
label: Text(
currentEmailAddress.asString(),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
),
deleteIcon: SvgPicture.asset(_imagePaths.icClose, fit: BoxFit.fill),
labelStyle: RecipientTagItemWidgetStyle.labelTextStyle,
backgroundColor: _getTagBackgroundColor(),
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(RecipientTagItemWidgetStyle.radius)),
side: _getTagBorderSide(),
),
avatar: currentEmailAddress.displayName.isNotEmpty
? GradientCircleAvatarIcon(
colors: currentEmailAddress.avatarColors,
label: currentEmailAddress.displayName.firstLetterToUpperCase,
labelFontSize: RecipientTagItemWidgetStyle.avatarLabelFontSize,
iconSize: RecipientTagItemWidgetStyle.avatarIconSize,
)
: null,
onDeleted: () => onDeleteTagAction?.call(currentEmailAddress),
),
label: Text(
currentEmailAddress.asString(),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
),
deleteIcon: SvgPicture.asset(_imagePaths.icClose, fit: BoxFit.fill),
labelStyle: RecipientTagItemWidgetStyle.labelTextStyle,
backgroundColor: _getTagBackgroundColor(),
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(RecipientTagItemWidgetStyle.radius)),
side: _getTagBorderSide(),
),
avatar: currentEmailAddress.displayName.isNotEmpty
? GradientCircleAvatarIcon(
colors: currentEmailAddress.avatarColors,
label: currentEmailAddress.displayName.firstLetterToUpperCase,
labelFontSize: RecipientTagItemWidgetStyle.avatarLabelFontSize,
iconSize: RecipientTagItemWidgetStyle.avatarIconSize,
)
: null,
onDeleted: () => onDeleteTagAction?.call(currentEmailAddress),
),
),
)
)
),
)
else
Padding(
padding: EdgeInsetsDirectional.only(end: isCollapsed ? 40 : 0),
child: InkWell(
onTap: () => isCollapsed
? onShowFullAction?.call(prefix)
: null,
child: Chip(
labelPadding: EdgeInsetsDirectional.symmetric(
horizontal: 4,
vertical: DirectionUtils.isDirectionRTLByHasAnyRtl(currentEmailAddress.asString()) ? 0 : 2
),
label: Text(
currentEmailAddress.asString(),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
),
deleteIcon: SvgPicture.asset(_imagePaths.icClose, fit: BoxFit.fill),
labelStyle: RecipientTagItemWidgetStyle.labelTextStyle,
backgroundColor: _getTagBackgroundColor(),
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(RecipientTagItemWidgetStyle.radius)),
side: _getTagBorderSide(),
),
avatar: currentEmailAddress.displayName.isNotEmpty
? GradientCircleAvatarIcon(
colors: currentEmailAddress.avatarColors,
label: currentEmailAddress.displayName.firstLetterToUpperCase,
labelFontSize: RecipientTagItemWidgetStyle.avatarLabelFontSize,
iconSize: RecipientTagItemWidgetStyle.avatarIconSize,
)
: null,
onDeleted: () => onDeleteTagAction?.call(currentEmailAddress),
)
),
),
),
if (isCollapsed)
TMailButtonWidget.fromText(
margin: RecipientTagItemWidgetStyle.counterMargin,