Skip to content

Commit c2bd882

Browse files
TF-3308 Implement super_drag_and_drop
1 parent e619d6c commit c2bd882

File tree

8 files changed

+60
-56
lines changed

8 files changed

+60
-56
lines changed

core/lib/presentation/views/text/text_field_builder.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:core/presentation/extensions/color_extension.dart';
22
import 'package:core/presentation/views/semantics/text_field_semantics.dart';
3+
import 'package:core/presentation/views/text/text_drop_zone_web.dart';
34
import 'package:core/utils/direction_utils.dart';
45
import 'package:flutter/material.dart';
56

@@ -27,6 +28,7 @@ class TextFieldBuilder extends StatefulWidget {
2728
final bool readOnly;
2829
final MouseCursor? mouseCursor;
2930
final String? semanticLabel;
31+
final bool dropTextEnabled;
3032

3133
const TextFieldBuilder({
3234
super.key,
@@ -52,6 +54,7 @@ class TextFieldBuilder extends StatefulWidget {
5254
this.onTapOutside,
5355
this.onTextChange,
5456
this.onTextSubmitted,
57+
this.dropTextEnabled = false,
5558
});
5659

5760
@override
@@ -79,7 +82,7 @@ class _TextFieldBuilderState extends State<TextFieldBuilder> {
7982

8083
@override
8184
Widget build(BuildContext context) {
82-
final textField = TextField(
85+
Widget textField = TextField(
8386
key: widget.key,
8487
controller: _controller,
8588
cursorColor: widget.cursorColor,
@@ -103,6 +106,17 @@ class _TextFieldBuilderState extends State<TextFieldBuilder> {
103106
onTapOutside: widget.onTapOutside,
104107
);
105108

109+
if (widget.dropTextEnabled) {
110+
textField = TextDropZoneWeb(
111+
child: textField,
112+
onDrop: (value) {
113+
_controller?.text += value;
114+
widget.focusNode?.requestFocus();
115+
_onTextChanged(value);
116+
},
117+
);
118+
}
119+
106120
if (widget.semanticLabel != null) {
107121
return TextFieldSemantics(
108122
label: widget.semanticLabel!,

lib/features/composer/presentation/composer_controller.dart

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import 'dart:math';
55
import 'package:core/core.dart';
66
import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
77
import 'package:dartz/dartz.dart';
8-
import 'package:desktop_drop/desktop_drop.dart';
98
import 'package:dio/dio.dart';
109
import 'package:dropdown_button2/dropdown_button2.dart';
1110
import 'package:file_picker/file_picker.dart';
@@ -1969,15 +1968,13 @@ class ComposerController extends BaseController
19691968
}
19701969
}
19711970

1972-
void onLocalFileDropZoneListener({
1971+
Future<void> onSuperDropListener({
19731972
required BuildContext context,
1974-
required DropDoneDetails details,
1973+
required List<FileInfo> listFileInfo,
19751974
required double maxWidth
19761975
}) async {
19771976
_setUpMaxWidthInlineImage(context: context, maxWidth: maxWidth);
19781977

1979-
final listFileInfo = await onDragDone(context: context, details: details);
1980-
19811978
if (listFileInfo.isEmpty && context.mounted) {
19821979
appToast.showToastErrorMessage(
19831980
context,

lib/features/composer/presentation/composer_view_web.dart

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class ComposerView extends GetWidget<ComposerController> {
205205
onTextChange: controller.setSubjectEmail,
206206
padding: ComposerStyle.mobileSubjectPadding,
207207
margin: ComposerStyle.mobileSubjectMargin,
208+
dropTextEnabled: true,
208209
),
209210
Expanded(
210211
child: LayoutBuilder(
@@ -305,10 +306,10 @@ class ComposerView extends GetWidget<ComposerController> {
305306
imagePaths: controller.imagePaths,
306307
width: constraintsEditor.maxWidth,
307308
height: constraintsEditor.maxHeight,
308-
onLocalFileDropZoneListener: (details) =>
309-
controller.onLocalFileDropZoneListener(
309+
onSuperDrop: (listFileInfo) =>
310+
controller.onSuperDropListener(
310311
context: context,
311-
details: details,
312+
listFileInfo: listFileInfo,
312313
maxWidth: constraintsEditor.maxWidth,
313314
),
314315
)
@@ -474,6 +475,7 @@ class ComposerView extends GetWidget<ComposerController> {
474475
onTextChange: controller.setSubjectEmail,
475476
padding: ComposerStyle.desktopSubjectPadding,
476477
margin: ComposerStyle.desktopSubjectMargin,
478+
dropTextEnabled: true,
477479
),
478480
Expanded(
479481
child: LayoutBuilder(
@@ -613,10 +615,10 @@ class ComposerView extends GetWidget<ComposerController> {
613615
imagePaths: controller.imagePaths,
614616
width: constraintsEditor.maxWidth,
615617
height: constraintsEditor.maxHeight,
616-
onLocalFileDropZoneListener: (details) =>
617-
controller.onLocalFileDropZoneListener(
618+
onSuperDrop: (listFileInfo) =>
619+
controller.onSuperDropListener(
618620
context: context,
619-
details: details,
621+
listFileInfo: listFileInfo,
620622
maxWidth: constraintsEditor.maxWidth,
621623
),
622624
)
@@ -786,6 +788,7 @@ class ComposerView extends GetWidget<ComposerController> {
786788
onTextChange: controller.setSubjectEmail,
787789
padding: ComposerStyle.tabletSubjectPadding,
788790
margin: ComposerStyle.tabletSubjectMargin,
791+
dropTextEnabled: true,
789792
),
790793
Expanded(
791794
child: LayoutBuilder(
@@ -923,10 +926,10 @@ class ComposerView extends GetWidget<ComposerController> {
923926
imagePaths: controller.imagePaths,
924927
width: constraintsBody.maxWidth,
925928
height: constraintsBody.maxHeight,
926-
onLocalFileDropZoneListener: (details) =>
927-
controller.onLocalFileDropZoneListener(
929+
onSuperDrop: (listFileInfo) =>
930+
controller.onSuperDropListener(
928931
context: context,
929-
details: details,
932+
listFileInfo: listFileInfo,
930933
maxWidth: constraintsBody.maxWidth,
931934
),
932935
)
Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import 'dart:async' as async;
22
import 'package:async/async.dart';
3-
import 'package:core/data/constants/constant.dart';
4-
import 'package:desktop_drop/desktop_drop.dart';
53
import 'package:flutter/material.dart';
64
import 'package:future_loading_dialog/future_loading_dialog.dart';
7-
import 'package:model/upload/file_info.dart';
85
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
96

107
mixin DragDropFileMixin {
@@ -19,34 +16,4 @@ mixin DragDropFileMixin {
1916
future: future,
2017
);
2118
}
22-
23-
async.Future<List<FileInfo>> onDragDone({
24-
required BuildContext context,
25-
required DropDoneDetails details
26-
}) async {
27-
final bytesList = await showFutureLoadingDialogFullScreen(
28-
context: context,
29-
future: () => async.Future.wait(
30-
details.files.map(
31-
(xFile) => xFile.readAsBytes(),
32-
),
33-
),
34-
);
35-
36-
if (bytesList.error != null) return [];
37-
38-
final listFileInfo = <FileInfo>[];
39-
for (var i = 0; i < bytesList.result!.length; i++) {
40-
listFileInfo.add(
41-
FileInfo(
42-
bytes: bytesList.result![i],
43-
fileName: details.files[i].name,
44-
type: details.files[i].mimeType,
45-
fileSize: bytesList.result![i].length,
46-
isInline: details.files[i].mimeType?.startsWith(Constant.imageType) == true
47-
),
48-
);
49-
}
50-
return listFileInfo;
51-
}
5219
}

lib/features/composer/presentation/widgets/recipient_composer_widget.dart

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'package:model/email/prefix_email_address.dart';
1717
import 'package:model/extensions/email_address_extension.dart';
1818
import 'package:model/mailbox/expand_mode.dart';
1919
import 'package:super_tag_editor/tag_editor.dart';
20+
import 'package:core/presentation/views/text/text_drop_zone_web.dart';
2021
import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_email_address_extension.dart';
2122
import 'package:tmail_ui_user/features/composer/presentation/extensions/mail_address_extension.dart';
2223
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
@@ -162,7 +163,7 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
162163
if (PlatformInfo.isWeb || widget.isTestingForWeb) {
163164
return DragTarget<DraggableEmailAddress>(
164165
builder: (context, candidateData, rejectedData) {
165-
return TagEditor<SuggestionEmailAddress>(
166+
final child = TagEditor<SuggestionEmailAddress>(
166167
key: widget.keyTagEditor,
167168
length: _collapsedListEmailAddress.length,
168169
controller: widget.controller,
@@ -244,6 +245,27 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
244245
);
245246
},
246247
);
248+
249+
return TextDropZoneWeb(
250+
onHover: () {
251+
if (!_isDragging) {
252+
stateSetter(() => _isDragging = true);
253+
}
254+
},
255+
onLeave: () {
256+
if (_isDragging) {
257+
stateSetter(() => _isDragging = false);
258+
}
259+
},
260+
onDrop: (value) {
261+
if (_isDragging) {
262+
stateSetter(() => _isDragging = false);
263+
}
264+
widget.controller?.text += value;
265+
widget.focusNode?.requestFocus();
266+
},
267+
child: child,
268+
);
247269
},
248270
onAcceptWithDetails: (draggableEmailAddress) => _handleAcceptDraggableEmailAddressAction(draggableEmailAddress.data, stateSetter),
249271
onLeave: (draggableEmailAddress) {

lib/features/composer/presentation/widgets/subject_composer_widget.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class SubjectComposerWidget extends StatelessWidget {
1111
final ValueChanged<String>? onTextChange;
1212
final EdgeInsetsGeometry? margin;
1313
final EdgeInsetsGeometry? padding;
14+
final bool dropTextEnabled;
1415

1516
const SubjectComposerWidget({
1617
super.key,
@@ -19,6 +20,7 @@ class SubjectComposerWidget extends StatelessWidget {
1920
required this.onTextChange,
2021
this.margin,
2122
this.padding,
23+
this.dropTextEnabled = false,
2224
});
2325

2426
@override
@@ -51,6 +53,7 @@ class SubjectComposerWidget extends StatelessWidget {
5153
textDirection: DirectionUtils.getDirectionByLanguage(context),
5254
textStyle: SubjectComposerWidgetStyle.inputTextStyle,
5355
controller: textController,
56+
dropTextEnabled: dropTextEnabled,
5457
)
5558
)
5659
]

lib/features/identity_creator/presentation/identity_creator_controller.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import 'package:core/presentation/utils/keyboard_utils.dart';
1212
import 'package:core/utils/app_logger.dart';
1313
import 'package:core/utils/file_utils.dart';
1414
import 'package:core/utils/platform_info.dart';
15-
import 'package:desktop_drop/desktop_drop.dart';
1615
import 'package:file_picker/file_picker.dart';
1716
import 'package:flutter/cupertino.dart';
1817
import 'package:flutter/scheduler.dart';
@@ -896,14 +895,13 @@ class IdentityCreatorController extends BaseController with DragDropFileMixin im
896895
AppLocalizations.of(context).thisImageCannotBePastedIntoTheEditor);
897896
}
898897

899-
void onLocalFileDropZoneListener({
898+
Future<void> onSuperDropListener({
900899
required BuildContext context,
901-
required DropDoneDetails details,
900+
required List<FileInfo> listFileInfo,
902901
required double maxWidth
903902
}) async {
904903
clearFocusEditor(context);
905904

906-
final listFileInfo = await onDragDone(context: context, details: details);
907905
if (!context.mounted) return;
908906
await _uploadMultipleFilesToPublicAsset(
909907
context,

lib/features/identity_creator/presentation/identity_creator_view.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,10 @@ class IdentityCreatorView extends GetWidget<IdentityCreatorController>
137137
width: constraintsEditor.maxWidth,
138138
height: constraintsEditor.maxHeight,
139139
margin: EdgeInsets.zero,
140-
onLocalFileDropZoneListener: (details) =>
141-
controller.onLocalFileDropZoneListener(
140+
onSuperDrop: (listFileInfo) =>
141+
controller.onSuperDropListener(
142142
context: context,
143-
details: details,
143+
listFileInfo: listFileInfo,
144144
maxWidth: constraintsEditor.maxWidth,
145145
),
146146
)

0 commit comments

Comments
 (0)