Skip to content

Commit c9f0f82

Browse files
TF-3308 Implement super_drag_and_drop
1 parent 1bb66f3 commit c9f0f82

File tree

8 files changed

+162
-166
lines changed

8 files changed

+162
-166
lines changed

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

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:core/presentation/extensions/color_extension.dart';
2+
import 'package:core/presentation/views/text/text_drop_zone_web.dart';
23
import 'package:core/utils/direction_utils.dart';
34
import 'package:flutter/material.dart';
45
import 'package:languagetool_textfield/languagetool_textfield.dart';
@@ -27,6 +28,7 @@ class TextFieldBuilder extends StatefulWidget {
2728
final bool readOnly;
2829
final MouseCursor? mouseCursor;
2930
final LanguageToolController? languageToolController;
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
@@ -85,8 +88,10 @@ class _TextFieldBuilderState extends State<TextFieldBuilder> {
8588

8689
@override
8790
Widget build(BuildContext context) {
91+
Widget child;
92+
8893
if (_languageToolController != null) {
89-
return LanguageToolTextField(
94+
child = LanguageToolTextField(
9095
key: widget.key,
9196
controller: _languageToolController!,
9297
cursorColor: widget.cursorColor,
@@ -104,55 +109,46 @@ class _TextFieldBuilderState extends State<TextFieldBuilder> {
104109
textDirection: _textDirection,
105110
readOnly: widget.readOnly,
106111
mouseCursor: widget.mouseCursor,
107-
onTextChange: (value) {
108-
widget.onTextChange?.call(value);
109-
if (value.isNotEmpty) {
110-
final directionByText = DirectionUtils.getDirectionByEndsText(value);
111-
if (directionByText != _textDirection) {
112-
setState(() {
113-
_textDirection = directionByText;
114-
});
115-
}
116-
}
117-
},
112+
onTextChange: _onChanged,
118113
onTextSubmitted: widget.onTextSubmitted,
119114
onTap: widget.onTap,
120115
onTapOutside: widget.onTapOutside,
121116
);
117+
} else {
118+
child = TextField(
119+
key: widget.key,
120+
controller: _controller,
121+
cursorColor: widget.cursorColor,
122+
autocorrect: widget.autocorrect,
123+
textInputAction: widget.textInputAction,
124+
decoration: widget.decoration,
125+
maxLines: widget.maxLines,
126+
minLines: widget.minLines,
127+
keyboardAppearance: widget.keyboardAppearance,
128+
style: widget.textStyle,
129+
obscureText: widget.obscureText,
130+
keyboardType: widget.keyboardType,
131+
autofocus: widget.autoFocus,
132+
focusNode: widget.focusNode,
133+
textDirection: _textDirection,
134+
readOnly: widget.readOnly,
135+
mouseCursor: widget.mouseCursor,
136+
onChanged: _onChanged,
137+
onSubmitted: widget.onTextSubmitted,
138+
onTap: widget.onTap,
139+
onTapOutside: widget.onTapOutside,
140+
);
122141
}
123142

124-
return TextField(
125-
key: widget.key,
126-
controller: _controller,
127-
cursorColor: widget.cursorColor,
128-
autocorrect: widget.autocorrect,
129-
textInputAction: widget.textInputAction,
130-
decoration: widget.decoration,
131-
maxLines: widget.maxLines,
132-
minLines: widget.minLines,
133-
keyboardAppearance: widget.keyboardAppearance,
134-
style: widget.textStyle,
135-
obscureText: widget.obscureText,
136-
keyboardType: widget.keyboardType,
137-
autofocus: widget.autoFocus,
138-
focusNode: widget.focusNode,
139-
textDirection: _textDirection,
140-
readOnly: widget.readOnly,
141-
mouseCursor: widget.mouseCursor,
142-
onChanged: (value) {
143-
widget.onTextChange?.call(value);
144-
if (value.isNotEmpty) {
145-
final directionByText = DirectionUtils.getDirectionByEndsText(value);
146-
if (directionByText != _textDirection) {
147-
setState(() {
148-
_textDirection = directionByText;
149-
});
150-
}
151-
}
143+
if (!widget.dropTextEnabled) return child;
144+
145+
return TextDropZoneWeb(
146+
onDrop: (value) {
147+
(_languageToolController ?? _controller)?.text += value;
148+
widget.focusNode?.requestFocus();
149+
_onChanged(value);
152150
},
153-
onSubmitted: widget.onTextSubmitted,
154-
onTap: widget.onTap,
155-
onTapOutside: widget.onTapOutside,
151+
child: child,
156152
);
157153
}
158154

@@ -166,4 +162,16 @@ class _TextFieldBuilderState extends State<TextFieldBuilder> {
166162
}
167163
super.dispose();
168164
}
165+
166+
void _onChanged(String value) {
167+
widget.onTextChange?.call(value);
168+
if (value.isNotEmpty) {
169+
final directionByText = DirectionUtils.getDirectionByEndsText(value);
170+
if (directionByText != _textDirection) {
171+
setState(() {
172+
_textDirection = directionByText;
173+
});
174+
}
175+
}
176+
}
169177
}

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:collection/collection.dart';
66
import 'package:core/core.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';
@@ -2295,15 +2294,13 @@ class ComposerController extends BaseController
22952294
}
22962295
}
22972296

2298-
void onLocalFileDropZoneListener({
2297+
Future<void> onSuperDropListener({
22992298
required BuildContext context,
2300-
required DropDoneDetails details,
2299+
required List<FileInfo> listFileInfo,
23012300
required double maxWidth
23022301
}) async {
23032302
_setUpMaxWidthInlineImage(context: context, maxWidth: maxWidth);
23042303

2305-
final listFileInfo = await onDragDone(context: context, details: details);
2306-
23072304
if (listFileInfo.isEmpty && context.mounted) {
23082305
appToast.showToastErrorMessage(
23092306
context,

lib/features/composer/presentation/composer_view_web.dart

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ class ComposerView extends GetWidget<ComposerController> {
198198
onTextChange: controller.setSubjectEmail,
199199
padding: ComposerStyle.mobileSubjectPadding,
200200
margin: ComposerStyle.mobileSubjectMargin,
201+
dropTextEnabled: true,
201202
),
202203
Expanded(
203204
child: LayoutBuilder(
@@ -301,10 +302,10 @@ class ComposerView extends GetWidget<ComposerController> {
301302
imagePaths: controller.imagePaths,
302303
width: constraintsEditor.maxWidth,
303304
height: constraintsEditor.maxHeight,
304-
onLocalFileDropZoneListener: (details) =>
305-
controller.onLocalFileDropZoneListener(
305+
onSuperDrop: (listFileInfo) =>
306+
controller.onSuperDropListener(
306307
context: context,
307-
details: details,
308+
listFileInfo: listFileInfo,
308309
maxWidth: constraintsEditor.maxWidth,
309310
),
310311
)
@@ -472,6 +473,7 @@ class ComposerView extends GetWidget<ComposerController> {
472473
onTextChange: controller.setSubjectEmail,
473474
padding: ComposerStyle.desktopSubjectPadding,
474475
margin: ComposerStyle.desktopSubjectMargin,
476+
dropTextEnabled: true,
475477
),
476478
Expanded(
477479
child: LayoutBuilder(
@@ -607,10 +609,10 @@ class ComposerView extends GetWidget<ComposerController> {
607609
imagePaths: controller.imagePaths,
608610
width: constraintsEditor.maxWidth,
609611
height: constraintsEditor.maxHeight,
610-
onLocalFileDropZoneListener: (details) =>
611-
controller.onLocalFileDropZoneListener(
612+
onSuperDrop: (listFileInfo) =>
613+
controller.onSuperDropListener(
612614
context: context,
613-
details: details,
615+
listFileInfo: listFileInfo,
614616
maxWidth: constraintsEditor.maxWidth,
615617
),
616618
)
@@ -779,6 +781,7 @@ class ComposerView extends GetWidget<ComposerController> {
779781
onTextChange: controller.setSubjectEmail,
780782
padding: ComposerStyle.tabletSubjectPadding,
781783
margin: ComposerStyle.tabletSubjectMargin,
784+
dropTextEnabled: true,
782785
),
783786
Expanded(
784787
child: LayoutBuilder(
@@ -912,10 +915,10 @@ class ComposerView extends GetWidget<ComposerController> {
912915
imagePaths: controller.imagePaths,
913916
width: constraintsBody.maxWidth,
914917
height: constraintsBody.maxHeight,
915-
onLocalFileDropZoneListener: (details) =>
916-
controller.onLocalFileDropZoneListener(
918+
onSuperDrop: (listFileInfo) =>
919+
controller.onSuperDropListener(
917920
context: context,
918-
details: details,
921+
listFileInfo: listFileInfo,
919922
maxWidth: constraintsBody.maxWidth,
920923
),
921924
)
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
}

0 commit comments

Comments
 (0)