TF-2644 Handle total size exceeded maximum size when drag & drop multiple file to composer
This commit is contained in:
+18
-39
@@ -3,42 +3,35 @@ import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/styles/web/drop_zone_widget_style.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
typedef OnAddAttachmentFromDropZone = Function(Attachment attachment);
|
||||
typedef OnAttachmentDropZoneListener = Function(Attachment attachment);
|
||||
|
||||
class DropZoneWidget extends StatefulWidget {
|
||||
class AttachmentDropZoneWidget extends StatelessWidget {
|
||||
|
||||
final ImagePaths imagePaths;
|
||||
final double? width;
|
||||
final double? height;
|
||||
final OnAddAttachmentFromDropZone? addAttachmentFromDropZone;
|
||||
final OnAttachmentDropZoneListener? onAttachmentDropZoneListener;
|
||||
|
||||
const DropZoneWidget({
|
||||
const AttachmentDropZoneWidget({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
this.width,
|
||||
this.height,
|
||||
this.addAttachmentFromDropZone
|
||||
this.onAttachmentDropZoneListener
|
||||
});
|
||||
|
||||
@override
|
||||
State<DropZoneWidget> createState() => _DropZoneWidgetState();
|
||||
}
|
||||
|
||||
class _DropZoneWidgetState extends State<DropZoneWidget> {
|
||||
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
|
||||
bool _isDragging = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DragTarget<Attachment>(
|
||||
builder: (context, candidateData, rejectedData) {
|
||||
if (_isDragging) {
|
||||
return Padding(
|
||||
builder: (context, _, __) {
|
||||
return SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
child: Padding(
|
||||
padding: DropZoneWidgetStyle.margin,
|
||||
child: DottedBorder(
|
||||
borderType: BorderType.RRect,
|
||||
@@ -48,20 +41,18 @@ class _DropZoneWidgetState extends State<DropZoneWidget> {
|
||||
dashPattern: DropZoneWidgetStyle.dashSize,
|
||||
child: Container(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: const ShapeDecoration(
|
||||
decoration: ShapeDecoration(
|
||||
color: DropZoneWidgetStyle.backgroundColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(DropZoneWidgetStyle.radius)),
|
||||
),
|
||||
),
|
||||
width: widget.width,
|
||||
height: widget.height,
|
||||
padding: DropZoneWidgetStyle.padding,
|
||||
alignment: AlignmentDirectional.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SvgPicture.asset(_imagePaths.icDropZoneIcon),
|
||||
SvgPicture.asset(imagePaths.icDropZoneIcon),
|
||||
const SizedBox(height: DropZoneWidgetStyle.space),
|
||||
Text(
|
||||
AppLocalizations.of(context).dropFileHereToAttachThem,
|
||||
@@ -71,22 +62,10 @@ class _DropZoneWidgetState extends State<DropZoneWidget> {
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return SizedBox(width: widget.width, height: widget.height);
|
||||
}
|
||||
},
|
||||
onAccept: widget.addAttachmentFromDropZone,
|
||||
onLeave: (attachment) {
|
||||
if (_isDragging) {
|
||||
setState(() => _isDragging = false);
|
||||
}
|
||||
},
|
||||
onMove: (details) {
|
||||
if (!_isDragging) {
|
||||
setState(() => _isDragging = true);
|
||||
}
|
||||
),
|
||||
);
|
||||
},
|
||||
onAccept: onAttachmentDropZoneListener
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ class BottomBarComposerWidget extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: BottomBarComposerWidgetStyle.padding,
|
||||
height: BottomBarComposerWidgetStyle.height,
|
||||
color: BottomBarComposerWidgetStyle.backgroundColor,
|
||||
child: Row(
|
||||
children: [
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/styles/web/drop_zone_widget_style.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:desktop_drop/desktop_drop.dart';
|
||||
|
||||
typedef OnLocalFileDropZoneListener = Function(DropDoneDetails details);
|
||||
|
||||
class LocalFileDropZoneWidget extends StatelessWidget {
|
||||
|
||||
final ImagePaths imagePaths;
|
||||
final double? width;
|
||||
final double? height;
|
||||
final OnLocalFileDropZoneListener? onLocalFileDropZoneListener;
|
||||
|
||||
const LocalFileDropZoneWidget({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
this.width,
|
||||
this.height,
|
||||
this.onLocalFileDropZoneListener
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DropTarget(
|
||||
onDragDone: onLocalFileDropZoneListener,
|
||||
child: SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
child: Padding(
|
||||
padding: DropZoneWidgetStyle.margin,
|
||||
child: DottedBorder(
|
||||
borderType: BorderType.RRect,
|
||||
radius: const Radius.circular(DropZoneWidgetStyle.radius),
|
||||
color: DropZoneWidgetStyle.borderColor,
|
||||
strokeWidth: DropZoneWidgetStyle.borderWidth,
|
||||
dashPattern: DropZoneWidgetStyle.dashSize,
|
||||
child: Container(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: ShapeDecoration(
|
||||
color: DropZoneWidgetStyle.backgroundColor,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(DropZoneWidgetStyle.radius)),
|
||||
),
|
||||
),
|
||||
padding: DropZoneWidgetStyle.padding,
|
||||
alignment: AlignmentDirectional.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SvgPicture.asset(imagePaths.icDropZoneIcon),
|
||||
const SizedBox(height: DropZoneWidgetStyle.space),
|
||||
Text(
|
||||
AppLocalizations.of(context).dropFileHereToAttachThem,
|
||||
style: DropZoneWidgetStyle.labelTextStyle,
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,6 @@ typedef OnChangeContentEditorAction = Function(String? text);
|
||||
typedef OnInitialContentEditorAction = Function(String text);
|
||||
typedef OnMouseDownEditorAction = Function(BuildContext context);
|
||||
typedef OnEditorSettingsChange = Function(EditorSettings settings);
|
||||
typedef OnImageUploadSuccessAction = Function(FileUpload fileUpload);
|
||||
typedef OnImageUploadFailureAction = Function(FileUpload? fileUpload, String? base64Str, UploadError error);
|
||||
typedef OnEditorTextSizeChanged = Function(int? size);
|
||||
|
||||
class WebEditorWidget extends StatefulWidget {
|
||||
@@ -26,11 +24,10 @@ class WebEditorWidget extends StatefulWidget {
|
||||
final VoidCallback? onUnFocus;
|
||||
final OnMouseDownEditorAction? onMouseDown;
|
||||
final OnEditorSettingsChange? onEditorSettings;
|
||||
final OnImageUploadSuccessAction? onImageUploadSuccessAction;
|
||||
final OnImageUploadFailureAction? onImageUploadFailureAction;
|
||||
final OnEditorTextSizeChanged? onEditorTextSizeChanged;
|
||||
final double? width;
|
||||
final double? height;
|
||||
final VoidCallback? onDragEnter;
|
||||
|
||||
const WebEditorWidget({
|
||||
super.key,
|
||||
@@ -43,11 +40,10 @@ class WebEditorWidget extends StatefulWidget {
|
||||
this.onUnFocus,
|
||||
this.onMouseDown,
|
||||
this.onEditorSettings,
|
||||
this.onImageUploadSuccessAction,
|
||||
this.onImageUploadFailureAction,
|
||||
this.onEditorTextSizeChanged,
|
||||
this.width,
|
||||
this.height,
|
||||
this.onDragEnter,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -133,6 +129,7 @@ class _WebEditorState extends State<WebEditorWidget> {
|
||||
initialText: widget.content,
|
||||
customBodyCssStyle: HtmlUtils.customCssStyleHtmlEditor(direction: widget.direction),
|
||||
spellCheck: true,
|
||||
disableDragAndDrop: true,
|
||||
webInitialScripts: UnmodifiableListView([
|
||||
WebScript(
|
||||
name: HtmlUtils.lineHeight100Percent.name,
|
||||
@@ -145,7 +142,7 @@ class _WebEditorState extends State<WebEditorWidget> {
|
||||
WebScript(
|
||||
name: HtmlUtils.unregisterDropListener.name,
|
||||
script: HtmlUtils.unregisterDropListener.script,
|
||||
),
|
||||
)
|
||||
])
|
||||
),
|
||||
htmlToolbarOptions: const HtmlToolbarOptions(
|
||||
@@ -154,8 +151,8 @@ class _WebEditorState extends State<WebEditorWidget> {
|
||||
),
|
||||
otherOptions: OtherOptions(
|
||||
height: height,
|
||||
dropZoneWidth: dropZoneWidth,
|
||||
dropZoneHeight: dropZoneHeight,
|
||||
// dropZoneWidth: dropZoneWidth,
|
||||
// dropZoneHeight: dropZoneHeight,
|
||||
),
|
||||
callbacks: Callbacks(
|
||||
onBeforeCommand: widget.onChangeContent,
|
||||
@@ -173,12 +170,12 @@ class _WebEditorState extends State<WebEditorWidget> {
|
||||
onMouseDown: () => widget.onMouseDown?.call(context),
|
||||
onChangeSelection: widget.onEditorSettings,
|
||||
onChangeCodeview: widget.onChangeContent,
|
||||
onImageUpload: widget.onImageUploadSuccessAction,
|
||||
onImageUploadError: widget.onImageUploadFailureAction,
|
||||
onTextFontSizeChanged: widget.onEditorTextSizeChanged,
|
||||
onPaste: () => _editorController.evaluateJavascriptWeb(
|
||||
HtmlUtils.lineHeight100Percent.name
|
||||
),
|
||||
onDragEnter: widget.onDragEnter,
|
||||
onDragLeave: () {},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user