Fix cannot scroll editor when disable code view in composer

This commit is contained in:
dab246
2025-09-19 13:41:55 +07:00
committed by Dat H. Pham
parent 69c9476379
commit 64f4096340
6 changed files with 400 additions and 381 deletions
+9
View File
@@ -46,6 +46,15 @@ class HtmlUtils {
editor.parentNode.replaceChild(newEditor, editor);''', editor.parentNode.replaceChild(newEditor, editor);''',
name: 'unregisterDropListener'); name: 'unregisterDropListener');
static recalculateEditorHeight({double? maxHeight}) => (
script: '''
const editable = document.querySelector('.note-editable');
if (editable) {
editable.style.height = $maxHeight + 'px';
}
''',
name: 'recalculateEditorHeight');
static String customInlineBodyCssStyleHtmlEditor({ static String customInlineBodyCssStyleHtmlEditor({
TextDirection direction = TextDirection.ltr, TextDirection direction = TextDirection.ltr,
double? horizontalPadding, double? horizontalPadding,
@@ -65,7 +65,7 @@ class ComposerView extends GetWidget<ComposerController> {
return ResponsiveWidget( return ResponsiveWidget(
responsiveUtils: controller.responsiveUtils, responsiveUtils: controller.responsiveUtils,
mobile: MobileResponsiveContainerView( mobile: MobileResponsiveContainerView(
childBuilder: (context, constraints) { childBuilder: (_, constraints) {
return GestureDetector( return GestureDetector(
onTap: () => controller.clickOutsideComposer(context), onTap: () => controller.clickOutsideComposer(context),
child: Column( child: Column(
@@ -239,14 +239,14 @@ class ComposerView extends GetWidget<ComposerController> {
margin: ComposerStyle.mobileSubjectMargin, margin: ComposerStyle.mobileSubjectMargin,
), ),
Expanded( Expanded(
child: LayoutBuilder( child: Stack(
builder: (_, constraintsEditor) { children: [
return Stack( Column(
children: [ children: [
Column( Expanded(
children: [ child: LayoutBuilder(
Expanded( builder: (_, constraintsEditor) {
child: Obx(() => WebEditorView( return Obx(() => WebEditorView(
key: controller.responsiveContainerKey, key: controller.responsiveContainerKey,
editorController: controller.richTextWebController!.editorController, editorController: controller.richTextWebController!.editorController,
arguments: controller.composerArguments.value, arguments: controller.composerArguments.value,
@@ -258,7 +258,7 @@ class ComposerView extends GetWidget<ComposerController> {
onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, onMouseDown: controller.handleOnMouseDownHtmlEditorWeb,
onEditorSettings: controller.richTextWebController!.onEditorSettingsChange, onEditorSettings: controller.richTextWebController!.onEditorSettingsChange,
onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged, onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged,
height: constraints.maxHeight, height: constraintsEditor.maxHeight,
horizontalPadding: ComposerStyle.mobileEditorHorizontalPadding, horizontalPadding: ComposerStyle.mobileEditorHorizontalPadding,
onDragEnter: controller.handleOnDragEnterHtmlEditorWeb, onDragEnter: controller.handleOnDragEnterHtmlEditorWeb,
onDragOver: controller.handleOnDragOverHtmlEditorWeb, onDragOver: controller.handleOnDragOverHtmlEditorWeb,
@@ -275,87 +275,83 @@ class ComposerView extends GetWidget<ComposerController> {
uploadError: uploadError uploadError: uploadError
), ),
onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb, onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb,
)), ));
), }
Obx(() { ),
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
return AttachmentComposerWidget(
listFileUploaded: controller.uploadController.listUploadAttachments,
isCollapsed: controller.isAttachmentCollapsed,
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.richTextWebController!.isFormattingOptionsEnabled) {
return ToolbarRichTextWidget(
richTextController: controller.richTextWebController!,
imagePaths: controller.imagePaths,
padding: ComposerStyle.richToolbarPadding,
decoration: const BoxDecoration(
color: ComposerStyle.richToolbarColor,
boxShadow: ComposerStyle.richToolbarShadow,
),
isMobile: controller.responsiveUtils.isMobile(context),
);
} else {
return const SizedBox.shrink();
}
})
],
), ),
Align(
alignment: AlignmentDirectional.topCenter,
child: Obx(() => InsertImageLoadingBarWidget(
uploadInlineViewState: controller.uploadController.uploadInlineViewState.value,
viewState: controller.viewState.value,
margin: ComposerStyle.insertImageLoadingBarMargin,
)),
),
iframeOverlay,
Obx(() { Obx(() {
if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive) { if (controller.uploadController.listUploadAttachments.isNotEmpty) {
return Positioned.fill( return AttachmentComposerWidget(
child: PointerInterceptor( listFileUploaded: controller.uploadController.listUploadAttachments,
child: AttachmentDropZoneWidget( isCollapsed: controller.isAttachmentCollapsed,
imagePaths: controller.imagePaths, onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
width: constraintsEditor.maxWidth, onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
height: constraintsEditor.maxHeight,
onAttachmentDropZoneListener: controller.onAttachmentDropZoneListener,
)
),
); );
} else { } else {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}), }),
Obx(() { Obx(() {
if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive) { if (controller.richTextWebController!.isFormattingOptionsEnabled) {
return Positioned.fill( return ToolbarRichTextWidget(
child: PointerInterceptor( richTextController: controller.richTextWebController!,
child: LocalFileDropZoneWidget( imagePaths: controller.imagePaths,
imagePaths: controller.imagePaths, padding: ComposerStyle.richToolbarPadding,
width: constraintsEditor.maxWidth, decoration: const BoxDecoration(
height: constraintsEditor.maxHeight, color: ComposerStyle.richToolbarColor,
onLocalFileDropZoneListener: (details) => boxShadow: ComposerStyle.richToolbarShadow,
controller.onLocalFileDropZoneListener(
context: context,
details: details,
maxWidth: constraintsEditor.maxWidth,
),
)
), ),
isMobile: controller.responsiveUtils.isMobile(context),
); );
} else { } else {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
}), })
], ],
); ),
} Align(
alignment: AlignmentDirectional.topCenter,
child: Obx(() => InsertImageLoadingBarWidget(
uploadInlineViewState: controller.uploadController.uploadInlineViewState.value,
viewState: controller.viewState.value,
margin: ComposerStyle.insertImageLoadingBarMargin,
)),
),
iframeOverlay,
Obx(() {
if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive) {
return Positioned.fill(
child: PointerInterceptor(
child: AttachmentDropZoneWidget(
imagePaths: controller.imagePaths,
onAttachmentDropZoneListener: controller.onAttachmentDropZoneListener,
)
),
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive) {
return Positioned.fill(
child: PointerInterceptor(
child: LocalFileDropZoneWidget(
imagePaths: controller.imagePaths,
onLocalFileDropZoneListener: (details) =>
controller.onLocalFileDropZoneListener(
context: context,
details: details,
maxWidth: constraints.maxWidth,
),
)
),
);
} else {
return const SizedBox.shrink();
}
}),
],
), ),
), ),
] ]
@@ -519,27 +515,27 @@ class ComposerView extends GetWidget<ComposerController> {
margin: ComposerStyle.desktopSubjectMargin, margin: ComposerStyle.desktopSubjectMargin,
), ),
Expanded( Expanded(
child: LayoutBuilder( child: Stack(
builder: (_, constraintsEditor) { children: [
return Stack( Column(
children: [ children: [
Column( Expanded(
children: [ child: Container(
Expanded( decoration: const BoxDecoration(
child: Container( border: Border(
decoration: const BoxDecoration( bottom: BorderSide(
border: Border( color: ComposerStyle.borderColor,
bottom: BorderSide( width: 1
color: ComposerStyle.borderColor, )
width: 1 ),
) color: ComposerStyle.backgroundEditorColor
), ),
color: ComposerStyle.backgroundEditorColor child: Column(
), children: [
child: Column( Expanded(
children: [ child: LayoutBuilder(
Expanded( builder: (_, constraintsEditor) {
child: Obx(() { return Obx(() {
return WebEditorView( return WebEditorView(
key: controller.responsiveContainerKey, key: controller.responsiveContainerKey,
editorController: controller.richTextWebController!.editorController, editorController: controller.richTextWebController!.editorController,
@@ -552,7 +548,7 @@ class ComposerView extends GetWidget<ComposerController> {
onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, onMouseDown: controller.handleOnMouseDownHtmlEditorWeb,
onEditorSettings: controller.richTextWebController?.onEditorSettingsChange, onEditorSettings: controller.richTextWebController?.onEditorSettingsChange,
onEditorTextSizeChanged: controller.richTextWebController?.onEditorTextSizeChanged, onEditorTextSizeChanged: controller.richTextWebController?.onEditorTextSizeChanged,
height: constraints.maxHeight, height: constraintsEditor.maxHeight,
horizontalPadding: ComposerStyle.desktopEditorHorizontalPadding, horizontalPadding: ComposerStyle.desktopEditorHorizontalPadding,
onDragEnter: controller.handleOnDragEnterHtmlEditorWeb, onDragEnter: controller.handleOnDragEnterHtmlEditorWeb,
onDragOver: controller.handleOnDragOverHtmlEditorWeb, onDragOver: controller.handleOnDragOverHtmlEditorWeb,
@@ -570,112 +566,109 @@ class ComposerView extends GetWidget<ComposerController> {
), ),
onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb, onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb,
); );
}), });
), }
Obx(() { ),
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
return AttachmentComposerWidget(
listFileUploaded: controller.uploadController.listUploadAttachments,
isCollapsed: controller.isAttachmentCollapsed,
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.richTextWebController!.isFormattingOptionsEnabled) {
return ToolbarRichTextWidget(
richTextController: controller.richTextWebController!,
imagePaths: controller.imagePaths,
padding: ComposerStyle.richToolbarPadding,
decoration: const BoxDecoration(
color: ComposerStyle.richToolbarColor,
boxShadow: ComposerStyle.richToolbarShadow,
),
isMobile: controller.responsiveUtils.isMobile(context),
);
} else {
return const SizedBox.shrink();
}
})
],
), ),
), Obx(() {
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
return AttachmentComposerWidget(
listFileUploaded: controller.uploadController.listUploadAttachments,
isCollapsed: controller.isAttachmentCollapsed,
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.richTextWebController!.isFormattingOptionsEnabled) {
return ToolbarRichTextWidget(
richTextController: controller.richTextWebController!,
imagePaths: controller.imagePaths,
padding: ComposerStyle.richToolbarPadding,
decoration: const BoxDecoration(
color: ComposerStyle.richToolbarColor,
boxShadow: ComposerStyle.richToolbarShadow,
),
isMobile: controller.responsiveUtils.isMobile(context),
);
} else {
return const SizedBox.shrink();
}
})
],
), ),
Obx(() => BottomBarComposerWidget( ),
imagePaths: controller.imagePaths,
isCodeViewEnabled: controller.richTextWebController!.codeViewEnabled,
isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled,
hasReadReceipt: controller.hasRequestReadReceipt.value,
isMarkAsImportant: controller.isMarkAsImportant.value,
openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
deleteComposerAction: () => controller.handleClickDeleteComposer(context),
saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
sendMessageAction: () => controller.handleClickSendButton(context),
isEmailChanged: controller.isEmailChanged.isTrue,
toggleCodeViewAction: controller.richTextWebController!.toggleCodeView,
menuMoreOptionController: controller.menuMoreOptionController!,
onPopupMenuChanged: controller.onPopupMenuChanged,
printDraftAction: () => controller.printDraft(context),
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
saveAsTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
)),
],
), ),
Align( Obx(() => BottomBarComposerWidget(
alignment: AlignmentDirectional.topCenter, imagePaths: controller.imagePaths,
child: Obx(() => InsertImageLoadingBarWidget( isCodeViewEnabled: controller.richTextWebController!.codeViewEnabled,
uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled,
viewState: controller.viewState.value, hasReadReceipt: controller.hasRequestReadReceipt.value,
margin: ComposerStyle.insertImageLoadingBarMargin, isMarkAsImportant: controller.isMarkAsImportant.value,
)), openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
), attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
iframeOverlay, insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
Obx(() { deleteComposerAction: () => controller.handleClickDeleteComposer(context),
if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive) { saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
return Positioned.fill( sendMessageAction: () => controller.handleClickSendButton(context),
child: PointerInterceptor( isEmailChanged: controller.isEmailChanged.isTrue,
child: AttachmentDropZoneWidget( toggleCodeViewAction: controller.richTextWebController!.toggleCodeView,
imagePaths: controller.imagePaths, menuMoreOptionController: controller.menuMoreOptionController!,
width: constraintsEditor.maxWidth, onPopupMenuChanged: controller.onPopupMenuChanged,
height: constraintsEditor.maxHeight, printDraftAction: () => controller.printDraft(context),
onAttachmentDropZoneListener: controller.onAttachmentDropZoneListener, toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
) toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
), saveAsTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
); )),
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive) {
return Positioned.fill(
child: PointerInterceptor(
child: LocalFileDropZoneWidget(
imagePaths: controller.imagePaths,
width: constraintsEditor.maxWidth,
height: constraintsEditor.maxHeight,
onLocalFileDropZoneListener: (details) =>
controller.onLocalFileDropZoneListener(
context: context,
details: details,
maxWidth: constraintsEditor.maxWidth,
),
)
),
);
} else {
return const SizedBox.shrink();
}
}),
], ],
); ),
} Align(
alignment: AlignmentDirectional.topCenter,
child: Obx(() => InsertImageLoadingBarWidget(
uploadInlineViewState: controller.uploadController.uploadInlineViewState.value,
viewState: controller.viewState.value,
margin: ComposerStyle.insertImageLoadingBarMargin,
)),
),
iframeOverlay,
Obx(() {
if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive) {
return Positioned.fill(
child: PointerInterceptor(
child: AttachmentDropZoneWidget(
imagePaths: controller.imagePaths,
onAttachmentDropZoneListener:
controller.onAttachmentDropZoneListener,
)
),
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive) {
return Positioned.fill(
child: PointerInterceptor(
child: LocalFileDropZoneWidget(
imagePaths: controller.imagePaths,
onLocalFileDropZoneListener: (details) =>
controller.onLocalFileDropZoneListener(
context: context,
details: details,
maxWidth: constraints.maxWidth,
),
)
),
);
} else {
return const SizedBox.shrink();
}
}),
],
), ),
), ),
]), ]),
@@ -843,27 +836,27 @@ class ComposerView extends GetWidget<ComposerController> {
margin: ComposerStyle.tabletSubjectMargin, margin: ComposerStyle.tabletSubjectMargin,
), ),
Expanded( Expanded(
child: LayoutBuilder( child: Stack(
builder: (_, constraintsBody) { children: [
return Stack( Column(
children: [ children: [
Column( Expanded(
children: [ child: Container(
Expanded( decoration: const BoxDecoration(
child: Container( border: Border(
decoration: const BoxDecoration( bottom: BorderSide(
border: Border( color: ComposerStyle.borderColor,
bottom: BorderSide( width: 1
color: ComposerStyle.borderColor, )
width: 1 ),
) color: ComposerStyle.backgroundEditorColor
), ),
color: ComposerStyle.backgroundEditorColor child: Column(
), children: [
child: Column( Expanded(
children: [ child: LayoutBuilder(
Expanded( builder: (_, constraintsBody) {
child: Obx(() => WebEditorView( return Obx(() => WebEditorView(
key: controller.responsiveContainerKey, key: controller.responsiveContainerKey,
editorController: controller.richTextWebController!.editorController, editorController: controller.richTextWebController!.editorController,
arguments: controller.composerArguments.value, arguments: controller.composerArguments.value,
@@ -875,7 +868,7 @@ class ComposerView extends GetWidget<ComposerController> {
onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, onMouseDown: controller.handleOnMouseDownHtmlEditorWeb,
onEditorSettings: controller.richTextWebController!.onEditorSettingsChange, onEditorSettings: controller.richTextWebController!.onEditorSettingsChange,
onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged, onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged,
height: constraints.maxHeight, height: constraintsBody.maxHeight,
horizontalPadding: ComposerStyle.desktopEditorHorizontalPadding, horizontalPadding: ComposerStyle.desktopEditorHorizontalPadding,
onDragEnter: controller.handleOnDragEnterHtmlEditorWeb, onDragEnter: controller.handleOnDragEnterHtmlEditorWeb,
onDragOver: controller.handleOnDragOverHtmlEditorWeb, onDragOver: controller.handleOnDragOverHtmlEditorWeb,
@@ -892,112 +885,108 @@ class ComposerView extends GetWidget<ComposerController> {
uploadError: uploadError uploadError: uploadError
), ),
onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb, onInitialContentLoadComplete: controller.onInitialContentLoadCompleteWeb,
)), ));
), }
Obx(() { ),
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
return AttachmentComposerWidget(
listFileUploaded: controller.uploadController.listUploadAttachments,
isCollapsed: controller.isAttachmentCollapsed,
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.richTextWebController!.isFormattingOptionsEnabled) {
return ToolbarRichTextWidget(
richTextController: controller.richTextWebController!,
imagePaths: controller.imagePaths,
padding: ComposerStyle.richToolbarPadding,
decoration: const BoxDecoration(
color: ComposerStyle.richToolbarColor,
boxShadow: ComposerStyle.richToolbarShadow,
),
isMobile: controller.responsiveUtils.isMobile(context),
);
} else {
return const SizedBox.shrink();
}
})
],
), ),
), Obx(() {
if (controller.uploadController.listUploadAttachments.isNotEmpty) {
return AttachmentComposerWidget(
listFileUploaded: controller.uploadController.listUploadAttachments,
isCollapsed: controller.isAttachmentCollapsed,
onDeleteAttachmentAction: controller.deleteAttachmentUploaded,
onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed,
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.richTextWebController!.isFormattingOptionsEnabled) {
return ToolbarRichTextWidget(
richTextController: controller.richTextWebController!,
imagePaths: controller.imagePaths,
padding: ComposerStyle.richToolbarPadding,
decoration: const BoxDecoration(
color: ComposerStyle.richToolbarColor,
boxShadow: ComposerStyle.richToolbarShadow,
),
isMobile: controller.responsiveUtils.isMobile(context),
);
} else {
return const SizedBox.shrink();
}
})
],
), ),
Obx(() => BottomBarComposerWidget( ),
imagePaths: controller.imagePaths,
isCodeViewEnabled: controller.richTextWebController!.codeViewEnabled,
isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled,
hasReadReceipt: controller.hasRequestReadReceipt.value,
isMarkAsImportant: controller.isMarkAsImportant.value,
openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
deleteComposerAction: () => controller.handleClickDeleteComposer(context),
saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
sendMessageAction: () => controller.handleClickSendButton(context),
isEmailChanged: controller.isEmailChanged.isTrue,
toggleCodeViewAction: controller.richTextWebController!.toggleCodeView,
menuMoreOptionController: controller.menuMoreOptionController!,
onPopupMenuChanged: controller.onPopupMenuChanged,
printDraftAction: () => controller.printDraft(context),
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
saveAsTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
)),
],
), ),
Align( Obx(() => BottomBarComposerWidget(
alignment: AlignmentDirectional.topCenter, imagePaths: controller.imagePaths,
child: Obx(() => InsertImageLoadingBarWidget( isCodeViewEnabled: controller.richTextWebController!.codeViewEnabled,
uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, isFormattingOptionsEnabled: controller.richTextWebController!.isFormattingOptionsEnabled,
viewState: controller.viewState.value, hasReadReceipt: controller.hasRequestReadReceipt.value,
margin: ComposerStyle.insertImageLoadingBarMargin, isMarkAsImportant: controller.isMarkAsImportant.value,
)), openRichToolbarAction: controller.richTextWebController!.toggleFormattingOptions,
), attachFileAction: () => controller.openFilePickerByType(context, FileType.any),
iframeOverlay, insertImageAction: () => controller.insertImage(context, constraints.maxWidth),
Obx(() { deleteComposerAction: () => controller.handleClickDeleteComposer(context),
if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive) { saveToDraftAction: () => controller.handleClickSaveAsDraftsButton(context),
return Positioned.fill( sendMessageAction: () => controller.handleClickSendButton(context),
child: PointerInterceptor( isEmailChanged: controller.isEmailChanged.isTrue,
child: AttachmentDropZoneWidget( toggleCodeViewAction: controller.richTextWebController!.toggleCodeView,
imagePaths: controller.imagePaths, menuMoreOptionController: controller.menuMoreOptionController!,
width: constraintsBody.maxWidth, onPopupMenuChanged: controller.onPopupMenuChanged,
height: constraintsBody.maxHeight, printDraftAction: () => controller.printDraft(context),
onAttachmentDropZoneListener: controller.onAttachmentDropZoneListener, toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
) toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
), saveAsTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
); )),
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive) {
return Positioned.fill(
child: PointerInterceptor(
child: LocalFileDropZoneWidget(
imagePaths: controller.imagePaths,
width: constraintsBody.maxWidth,
height: constraintsBody.maxHeight,
onLocalFileDropZoneListener: (details) =>
controller.onLocalFileDropZoneListener(
context: context,
details: details,
maxWidth: constraintsBody.maxWidth,
),
)
),
);
} else {
return const SizedBox.shrink();
}
}),
], ],
); ),
}, Align(
alignment: AlignmentDirectional.topCenter,
child: Obx(() => InsertImageLoadingBarWidget(
uploadInlineViewState: controller.uploadController.uploadInlineViewState.value,
viewState: controller.viewState.value,
margin: ComposerStyle.insertImageLoadingBarMargin,
)),
),
iframeOverlay,
Obx(() {
if (controller.mailboxDashBoardController.isAttachmentDraggableAppActive) {
return Positioned.fill(
child: PointerInterceptor(
child: AttachmentDropZoneWidget(
imagePaths: controller.imagePaths,
onAttachmentDropZoneListener: controller.onAttachmentDropZoneListener,
)
),
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
if (controller.mailboxDashBoardController.isLocalFileDraggableAppActive) {
return Positioned.fill(
child: PointerInterceptor(
child: LocalFileDropZoneWidget(
imagePaths: controller.imagePaths,
onLocalFileDropZoneListener: (details) =>
controller.onLocalFileDropZoneListener(
context: context,
details: details,
maxWidth: constraints.maxWidth,
),
)
),
);
} else {
return const SizedBox.shrink();
}
}),
],
), ),
) )
]), ]),
@@ -246,6 +246,10 @@ class RichTextWebController extends GetxController {
if (codeViewEnabled) { if (codeViewEnabled) {
formattingOptionsState.value = FormattingOptionsState.disabled; formattingOptionsState.value = FormattingOptionsState.disabled;
} else {
editorController.evaluateJavascriptWeb(
HtmlUtils.recalculateEditorHeight().name,
);
} }
} }
@@ -28,28 +28,25 @@ class AttachmentDropZoneWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DragTarget<Attachment>( return DragTarget<Attachment>(
builder: (context, _, __) { builder: (context, _, __) {
return SizedBox( final childWidget = Padding(
width: width, padding: DropZoneWidgetStyle.margin,
height: height, child: DottedBorder(
child: Padding( borderType: BorderType.RRect,
padding: DropZoneWidgetStyle.margin, radius: const Radius.circular(DropZoneWidgetStyle.radius),
child: DottedBorder( color: DropZoneWidgetStyle.borderColor,
borderType: BorderType.RRect, strokeWidth: DropZoneWidgetStyle.borderWidth,
radius: const Radius.circular(DropZoneWidgetStyle.radius), dashPattern: DropZoneWidgetStyle.dashSize,
color: DropZoneWidgetStyle.borderColor, child: Container(
strokeWidth: DropZoneWidgetStyle.borderWidth, clipBehavior: Clip.antiAlias,
dashPattern: DropZoneWidgetStyle.dashSize, decoration: ShapeDecoration(
child: Container( color: DropZoneWidgetStyle.backgroundColor,
clipBehavior: Clip.antiAlias, shape: const RoundedRectangleBorder(
decoration: ShapeDecoration( borderRadius: BorderRadius.all(Radius.circular(DropZoneWidgetStyle.radius)),
color: DropZoneWidgetStyle.backgroundColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(DropZoneWidgetStyle.radius)),
),
), ),
padding: DropZoneWidgetStyle.padding, ),
alignment: AlignmentDirectional.center, padding: DropZoneWidgetStyle.padding,
child: Column( alignment: AlignmentDirectional.center,
child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
SvgPicture.asset(imagePaths.icDropZoneIcon), SvgPicture.asset(imagePaths.icDropZoneIcon),
@@ -59,11 +56,20 @@ class AttachmentDropZoneWidget extends StatelessWidget {
style: DropZoneWidgetStyle.labelTextStyle, style: DropZoneWidgetStyle.labelTextStyle,
) )
] ]
),
), ),
), ),
), ),
); );
if (width == null && height == null) {
return SizedBox.expand(child: childWidget);
}
return SizedBox(
width: width,
height: height,
child: childWidget,
);
}, },
onAcceptWithDetails: (details) => onAttachmentDropZoneListener?.call(details.data), onAcceptWithDetails: (details) => onAttachmentDropZoneListener?.call(details.data),
); );
@@ -28,44 +28,52 @@ class LocalFileDropZoneWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DropTarget( Widget childWidget = Padding(
onDragDone: onLocalFileDropZoneListener, padding: margin,
child: SizedBox( child: DottedBorder(
width: width, borderType: BorderType.RRect,
height: height, radius: const Radius.circular(DropZoneWidgetStyle.radius),
child: Padding( color: DropZoneWidgetStyle.borderColor,
padding: margin, strokeWidth: DropZoneWidgetStyle.borderWidth,
child: DottedBorder( dashPattern: DropZoneWidgetStyle.dashSize,
borderType: BorderType.RRect, child: Container(
radius: const Radius.circular(DropZoneWidgetStyle.radius), clipBehavior: Clip.antiAlias,
color: DropZoneWidgetStyle.borderColor, decoration: ShapeDecoration(
strokeWidth: DropZoneWidgetStyle.borderWidth, color: DropZoneWidgetStyle.backgroundColor,
dashPattern: DropZoneWidgetStyle.dashSize, shape: const RoundedRectangleBorder(
child: Container( borderRadius: BorderRadius.all(
clipBehavior: Clip.antiAlias, Radius.circular(DropZoneWidgetStyle.radius),
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: [
Flexible(child: SvgPicture.asset(imagePaths.icDropZoneIcon)),
const SizedBox(height: DropZoneWidgetStyle.space),
Text(
AppLocalizations.of(context).dropFileHereToAttachThem,
style: DropZoneWidgetStyle.labelTextStyle,
)
]
), ),
), ),
), ),
padding: DropZoneWidgetStyle.padding,
alignment: AlignmentDirectional.center,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(child: SvgPicture.asset(imagePaths.icDropZoneIcon)),
const SizedBox(height: DropZoneWidgetStyle.space),
Text(
AppLocalizations
.of(context)
.dropFileHereToAttachThem,
style: DropZoneWidgetStyle.labelTextStyle,
),
],
),
), ),
), ),
); );
if (width == null && height == null) {
childWidget = SizedBox.expand(child: childWidget);
} else {
childWidget = SizedBox(width: width, height: height, child: childWidget);
}
return DropTarget(
onDragDone: onLocalFileDropZoneListener,
child: childWidget,
);
} }
} }
@@ -121,6 +121,7 @@ class _WebEditorState extends State<WebEditorWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final maxHeight = widget.height ?? _defaultHtmlEditorHeight;
return HtmlEditor( return HtmlEditor(
controller: _editorController, controller: _editorController,
htmlEditorOptions: HtmlEditorOptions( htmlEditorOptions: HtmlEditorOptions(
@@ -153,16 +154,18 @@ class _WebEditorState extends State<WebEditorWidget> {
WebScript( WebScript(
name: HtmlUtils.unregisterDropListener.name, name: HtmlUtils.unregisterDropListener.name,
script: HtmlUtils.unregisterDropListener.script, script: HtmlUtils.unregisterDropListener.script,
) ),
WebScript(
name: HtmlUtils.recalculateEditorHeight(maxHeight: maxHeight).name,
script: HtmlUtils.recalculateEditorHeight(maxHeight: maxHeight).script,
),
]) ])
), ),
htmlToolbarOptions: const HtmlToolbarOptions( htmlToolbarOptions: const HtmlToolbarOptions(
toolbarType: ToolbarType.hide, toolbarType: ToolbarType.hide,
defaultToolbarButtons: [], defaultToolbarButtons: [],
), ),
otherOptions: OtherOptions( otherOptions: OtherOptions(height: maxHeight),
height: widget.height ?? _defaultHtmlEditorHeight,
),
callbacks: Callbacks( callbacks: Callbacks(
onBeforeCommand: widget.onChangeContent, onBeforeCommand: widget.onChangeContent,
onChangeContent: widget.onChangeContent, onChangeContent: widget.onChangeContent,