TF-4142 Implement hyperlink insertion

This commit is contained in:
dab246
2025-11-10 12:09:19 +07:00
committed by Dat H. Pham
parent db22415a3e
commit 249520b711
14 changed files with 257 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M10.7914 14.4256C10.4572 14.7599 9.90859 14.7599 9.5743 14.4256C7.90287 12.7542 7.90287 10.037 9.5743 8.36561L14.0657 3.87418C15.7372 2.20275 18.4543 2.20275 20.1257 3.87418C21.7972 5.54561 21.7972 8.26275 20.1257 9.93418L18.8949 11.165C18.561 11.4989 18.0197 11.4994 17.6852 11.166C17.3508 10.8327 17.3498 10.2915 17.6828 9.95696L18.9086 8.72561C19.92 7.72275 19.92 6.09418 18.9086 5.09132C17.9057 4.07989 16.2772 4.07989 15.2743 5.09132L10.7914 9.57418C9.78001 10.577 9.78001 12.2056 10.7914 13.2085C11.1429 13.5427 11.1429 14.0913 10.7914 14.4256ZM13.2086 9.57418C13.5429 9.23989 14.0914 9.23989 14.4257 9.57418C16.0972 11.2456 16.0972 13.9627 14.4257 15.6342L9.9343 20.1256C8.26287 21.797 5.54573 21.797 3.8743 20.1256C2.20287 18.4542 2.20287 15.737 3.8743 14.0656L5.10128 12.8386C5.43566 12.5035 5.97837 12.5035 6.31311 12.8383C6.31322 12.8384 6.31334 12.8385 6.31311 12.839L6.31378 12.8397C6.64783 13.1748 6.64767 13.7172 6.31343 14.0522L5.09144 15.2742C4.08001 16.277 4.08001 17.9056 5.09144 18.9085C6.0943 19.9199 7.72287 19.9199 8.72573 18.9085L13.2086 14.4256C14.22 13.4227 14.22 11.7942 13.2086 10.7913C12.8572 10.457 12.8572 9.90846 13.2086 9.57418Z"
fill="#55687D" />
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.47998 14.2174C6.81437 13.8824 7.35719 13.8827 7.69189 14.2174L7.69287 14.2184C8.02678 14.5535 8.02609 15.0964 7.69189 15.4313L6.47021 16.653C5.45879 17.6558 5.45879 19.2849 6.47021 20.2877C7.47297 21.2988 9.1012 21.2987 10.104 20.2877L13.6958 16.6959L14.9087 17.9088L11.313 21.5045C9.64164 23.1759 6.92487 23.1757 5.25342 21.5045C3.58199 19.8331 3.58199 17.1164 5.25342 15.4449L6.47998 14.2174ZM12.4058 15.4059C12.3675 15.5521 12.2897 15.6907 12.1704 15.8043C11.8361 16.1386 11.2869 16.1386 10.9526 15.8043C10.0984 14.9499 9.68155 13.8223 9.70068 12.7008L12.4058 15.4059ZM14.5874 10.9528C14.9216 10.6188 15.47 10.6188 15.8042 10.9528C17.1789 12.3275 17.4213 14.4089 16.5347 16.0348L15.2329 14.733C15.5004 13.8553 15.2864 12.8638 14.5874 12.1705C14.236 11.8362 14.236 11.287 14.5874 10.9528ZM15.4448 5.25354C17.1163 3.58211 19.833 3.58211 21.5044 5.25354C23.1756 6.92499 23.1757 9.64176 21.5044 11.3131L20.2739 12.5436C19.94 12.8775 19.3985 12.8779 19.064 12.5446C18.7297 12.2113 18.7281 11.6701 19.061 11.3356L20.2876 10.1041C21.2986 9.10132 21.2987 7.47309 20.2876 6.47034C19.2847 5.45891 17.6557 5.45891 16.6528 6.47034L12.1704 10.9528C12.0471 11.075 11.9384 11.2068 11.8452 11.3453L10.6196 10.1198C10.7222 9.99002 10.8329 9.86451 10.9526 9.74475L15.4448 5.25354Z" fill="#007AFF"/>
<path d="M5.99902 6L20.999 21" stroke="#007AFF" stroke-width="1.8" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+14
View File
@@ -0,0 +1,14 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M2.57153 5.99997C2.57153 5.52658 2.95529 5.14282 3.42868 5.14282H10.2858C10.7592 5.14282 11.143 5.52658 11.143 5.99997C11.143 6.47335 10.7592 6.85711 10.2858 6.85711L7.71439 6.85711V12.8571C7.71439 13.3305 7.33063 13.7143 6.85725 13.7143C6.38386 13.7143 6.0001 13.3305 6.0001 12.8571V6.85711L3.42868 6.85711C2.95529 6.85711 2.57153 6.47335 2.57153 5.99997Z"
fill="#55687D" />
<path
d="M14.5715 6.85711C14.0981 6.85711 13.7144 7.24086 13.7144 7.71425C13.7144 8.18764 14.0981 8.57139 14.5715 8.57139L20.5715 8.57139C21.0449 8.57139 21.4287 8.18764 21.4287 7.71425C21.4287 7.24086 21.0449 6.85711 20.5715 6.85711L14.5715 6.85711Z"
fill="#55687D" />
<path
d="M10.2858 12.8571C10.2858 12.3837 10.6696 12 11.143 12L20.5715 12C21.0449 12 21.4287 12.3837 21.4287 12.8571C21.4287 13.3305 21.0449 13.7143 20.5715 13.7143L11.143 13.7143C10.6696 13.7143 10.2858 13.3305 10.2858 12.8571Z"
fill="#55687D" />
<path
d="M6.0001 18C6.0001 17.5266 6.38386 17.1428 6.85725 17.1428L20.5715 17.1428C21.0449 17.1428 21.4287 17.5266 21.4287 18C21.4287 18.4734 21.0449 18.8571 20.5715 18.8571L6.85725 18.8571C6.38386 18.8571 6.0001 18.4734 6.0001 18Z"
fill="#55687D" />
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -261,6 +261,8 @@ extension AppColor on Color {
static const gray9AA7B6 = Color(0xFF9AA7B6); static const gray9AA7B6 = Color(0xFF9AA7B6);
static const redFF3347 = Color(0xFFFF3347); static const redFF3347 = Color(0xFFFF3347);
static const gray686E76 = Color(0xFF686E76); static const gray686E76 = Color(0xFF686E76);
static const gray900 = Color(0xFF222222);
static const gray400 = Color(0xFF939393);
static const lightGrayEBEDF0 = Color(0xFFEBEDF0); static const lightGrayEBEDF0 = Color(0xFFEBEDF0);
static const gray99A2AD = Color(0xFF99A2AD); static const gray99A2AD = Color(0xFF99A2AD);
static const textSecondary = Color(0xFF1C1B1F); static const textSecondary = Color(0xFF1C1B1F);
@@ -257,6 +257,9 @@ class ImagePaths {
String get icNavigation => _getImagePath('ic_navigation.svg'); String get icNavigation => _getImagePath('ic_navigation.svg');
String get icReading => _getImagePath('ic_reading.svg'); String get icReading => _getImagePath('ic_reading.svg');
String get icMoveFolderContent => _getImagePath('ic_move_folder_content.svg'); String get icMoveFolderContent => _getImagePath('ic_move_folder_content.svg');
String get icInsertLink => _getImagePath('ic_insert_link.svg');
String get icRemoveLink => _getImagePath('ic_remove_link.svg');
String get icText => _getImagePath('ic_text.svg');
String _getImagePath(String imageName) { String _getImagePath(String imageName) {
return AssetsPaths.images + imageName; return AssetsPaths.images + imageName;
@@ -12,6 +12,7 @@ import 'package:tmail_ui_user/features/base/widget/keyboard/keyboard_handler_wra
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/composer_print_draft_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/composer_print_draft_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_edit_recipient_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_edit_recipient_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_insert_link_composer_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_recipients_collapsed_extensions.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_keyboard_shortcut_actions_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_keyboard_shortcut_actions_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/mark_as_important_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/mark_as_important_extension.dart';
@@ -248,6 +249,7 @@ class ComposerView extends GetWidget<ComposerController> {
onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged, onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged,
height: constraintsEditor.maxHeight, height: constraintsEditor.maxHeight,
horizontalPadding: ComposerStyle.mobileEditorHorizontalPadding, horizontalPadding: ComposerStyle.mobileEditorHorizontalPadding,
linkOverlayOptions: controller.createLinkOverlayOptions(context),
onDragEnter: controller.handleOnDragEnterHtmlEditorWeb, onDragEnter: controller.handleOnDragEnterHtmlEditorWeb,
onDragOver: controller.handleOnDragOverHtmlEditorWeb, onDragOver: controller.handleOnDragOverHtmlEditorWeb,
onPasteImageSuccessAction: (listFileUpload) => controller.handleOnPasteImageSuccessAction( onPasteImageSuccessAction: (listFileUpload) => controller.handleOnPasteImageSuccessAction(
@@ -489,6 +491,7 @@ class ComposerView extends GetWidget<ComposerController> {
onEditorTextSizeChanged: controller.richTextWebController?.onEditorTextSizeChanged, onEditorTextSizeChanged: controller.richTextWebController?.onEditorTextSizeChanged,
height: constraintsEditor.maxHeight, height: constraintsEditor.maxHeight,
horizontalPadding: ComposerStyle.desktopEditorHorizontalPadding, horizontalPadding: ComposerStyle.desktopEditorHorizontalPadding,
linkOverlayOptions: controller.createLinkOverlayOptions(context),
onDragEnter: controller.handleOnDragEnterHtmlEditorWeb, onDragEnter: controller.handleOnDragEnterHtmlEditorWeb,
onDragOver: controller.handleOnDragOverHtmlEditorWeb, onDragOver: controller.handleOnDragOverHtmlEditorWeb,
onPasteImageSuccessAction: (listFileUpload) => controller.handleOnPasteImageSuccessAction( onPasteImageSuccessAction: (listFileUpload) => controller.handleOnPasteImageSuccessAction(
@@ -551,6 +554,7 @@ class ComposerView extends GetWidget<ComposerController> {
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context), toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context), toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
saveAsTemplateAction: () => controller.handleClickSaveAsTemplateButton(context), saveAsTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
onOpenInsertLink: controller.openInsertLink,
)), )),
], ],
), ),
@@ -760,6 +764,7 @@ class ComposerView extends GetWidget<ComposerController> {
onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged, onEditorTextSizeChanged: controller.richTextWebController!.onEditorTextSizeChanged,
height: constraintsBody.maxHeight, height: constraintsBody.maxHeight,
horizontalPadding: ComposerStyle.desktopEditorHorizontalPadding, horizontalPadding: ComposerStyle.desktopEditorHorizontalPadding,
linkOverlayOptions: controller.createLinkOverlayOptions(context),
onDragEnter: controller.handleOnDragEnterHtmlEditorWeb, onDragEnter: controller.handleOnDragEnterHtmlEditorWeb,
onDragOver: controller.handleOnDragOverHtmlEditorWeb, onDragOver: controller.handleOnDragOverHtmlEditorWeb,
onPasteImageSuccessAction: (listFileUpload) => controller.handleOnPasteImageSuccessAction( onPasteImageSuccessAction: (listFileUpload) => controller.handleOnPasteImageSuccessAction(
@@ -821,6 +826,7 @@ class ComposerView extends GetWidget<ComposerController> {
toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context), toggleRequestReadReceiptAction: () => controller.toggleRequestReadReceipt(context),
toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context), toggleMarkAsImportantAction: () => controller.toggleMarkAsImportant(context),
saveAsTemplateAction: () => controller.handleClickSaveAsTemplateButton(context), saveAsTemplateAction: () => controller.handleClickSaveAsTemplateButton(context),
onOpenInsertLink: controller.openInsertLink,
)), )),
], ],
), ),
@@ -0,0 +1,89 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:html_editor_enhanced/html_editor.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
extension HandleInsertLinkComposerExtension on ComposerController {
void openInsertLink() {
richTextWebController?.editorController.openInsertLinkDialog();
}
LinkOverlayOptions createLinkOverlayOptions(BuildContext context) {
final appLocalizations = AppLocalizations.of(context);
return LinkOverlayOptions(
tooltipOptions: LinkTooltipOverlayOptions(
linkPrefixLabel: '${appLocalizations.goTo}:',
editLinkLabel: appLocalizations.change,
removeLinkTooltipMessage: appLocalizations.removeLink,
linkPrefixLabelStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.gray900,
),
linkLabelStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.blue700,
),
editLinkLabelStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.primaryMain,
),
removeLinkButtonBuilder: (_, onTap) => TMailButtonWidget.fromIcon(
icon: imagePaths.icRemoveLink,
iconSize: 20,
iconColor: AppColor.primaryLinShare,
backgroundColor: Colors.transparent,
onTapActionCallback: onTap,
),
),
editDialogOptions: LinkEditDialogOverlayOptions(
hintText: appLocalizations.text,
hintUrl: appLocalizations.typeOrPasteLink,
applyButtonLabel: appLocalizations.apply,
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
inputTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.gray900,
),
applyButtonTextStyle: (isEnabled) => ThemeUtils.textStyleM3LabelLarge(
color: isEnabled ? AppColor.primaryMain : AppColor.gray400,
),
textPrefixIcon: SvgPicture.asset(
imagePaths.icText,
width: 24,
height: 24,
fit: BoxFit.fill,
),
urlPrefixIcon: SvgPicture.asset(
imagePaths.icInsertLink,
width: 24,
height: 24,
fit: BoxFit.fill,
),
backgroundColor: Colors.white,
inputBackgroundColor: Colors.white,
dialogPadding: const EdgeInsetsDirectional.only(
start: 16,
end: 12,
top: 16,
bottom: 16,
),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
width: 1,
color: AppColor.m3Neutral90,
),
),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
width: 1,
color: AppColor.primaryMain,
),
),
),
);
}
}
@@ -29,6 +29,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
final OnEditorTextSizeChanged? onEditorTextSizeChanged; final OnEditorTextSizeChanged? onEditorTextSizeChanged;
final double? height; final double? height;
final double? horizontalPadding; final double? horizontalPadding;
final LinkOverlayOptions? linkOverlayOptions;
final OnDragEnterListener? onDragEnter; final OnDragEnterListener? onDragEnter;
final OnDragOverListener? onDragOver; final OnDragOverListener? onDragOver;
final OnPasteImageSuccessAction? onPasteImageSuccessAction; final OnPasteImageSuccessAction? onPasteImageSuccessAction;
@@ -51,6 +52,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
this.onEditorTextSizeChanged, this.onEditorTextSizeChanged,
this.height, this.height,
this.horizontalPadding, this.horizontalPadding,
this.linkOverlayOptions,
this.onDragEnter, this.onDragEnter,
this.onDragOver, this.onDragOver,
this.onPasteImageSuccessAction, this.onPasteImageSuccessAction,
@@ -82,6 +84,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
onEditorTextSizeChanged: onEditorTextSizeChanged, onEditorTextSizeChanged: onEditorTextSizeChanged,
height: height, height: height,
horizontalPadding: horizontalPadding, horizontalPadding: horizontalPadding,
linkOverlayOptions: linkOverlayOptions,
onDragEnter: onDragEnter, onDragEnter: onDragEnter,
onDragOver: onDragOver, onDragOver: onDragOver,
onPasteImageSuccessAction: onPasteImageSuccessAction, onPasteImageSuccessAction: onPasteImageSuccessAction,
@@ -113,6 +116,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
onEditorTextSizeChanged: onEditorTextSizeChanged, onEditorTextSizeChanged: onEditorTextSizeChanged,
height: height, height: height,
horizontalPadding: horizontalPadding, horizontalPadding: horizontalPadding,
linkOverlayOptions: linkOverlayOptions,
onDragEnter: onDragEnter, onDragEnter: onDragEnter,
onDragOver: onDragOver, onDragOver: onDragOver,
onPasteImageSuccessAction: onPasteImageSuccessAction, onPasteImageSuccessAction: onPasteImageSuccessAction,
@@ -146,6 +150,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
onEditorTextSizeChanged: onEditorTextSizeChanged, onEditorTextSizeChanged: onEditorTextSizeChanged,
height: height, height: height,
horizontalPadding: horizontalPadding, horizontalPadding: horizontalPadding,
linkOverlayOptions: linkOverlayOptions,
onDragEnter: onDragEnter, onDragEnter: onDragEnter,
onDragOver: onDragOver, onDragOver: onDragOver,
onPasteImageSuccessAction: onPasteImageSuccessAction, onPasteImageSuccessAction: onPasteImageSuccessAction,
@@ -185,6 +190,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
onEditorTextSizeChanged: onEditorTextSizeChanged, onEditorTextSizeChanged: onEditorTextSizeChanged,
height: height, height: height,
horizontalPadding: horizontalPadding, horizontalPadding: horizontalPadding,
linkOverlayOptions: linkOverlayOptions,
onDragEnter: onDragEnter, onDragEnter: onDragEnter,
onDragOver: onDragOver, onDragOver: onDragOver,
onPasteImageSuccessAction: onPasteImageSuccessAction, onPasteImageSuccessAction: onPasteImageSuccessAction,
@@ -219,6 +225,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
onEditorTextSizeChanged: onEditorTextSizeChanged, onEditorTextSizeChanged: onEditorTextSizeChanged,
height: height, height: height,
horizontalPadding: horizontalPadding, horizontalPadding: horizontalPadding,
linkOverlayOptions: linkOverlayOptions,
onDragEnter: onDragEnter, onDragEnter: onDragEnter,
onDragOver: onDragOver, onDragOver: onDragOver,
onPasteImageSuccessAction: onPasteImageSuccessAction, onPasteImageSuccessAction: onPasteImageSuccessAction,
@@ -243,6 +250,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
onEditorTextSizeChanged: onEditorTextSizeChanged, onEditorTextSizeChanged: onEditorTextSizeChanged,
height: height, height: height,
horizontalPadding: horizontalPadding, horizontalPadding: horizontalPadding,
linkOverlayOptions: linkOverlayOptions,
onDragEnter: onDragEnter, onDragEnter: onDragEnter,
onDragOver: onDragOver, onDragOver: onDragOver,
onPasteImageSuccessAction: onPasteImageSuccessAction, onPasteImageSuccessAction: onPasteImageSuccessAction,
@@ -30,6 +30,7 @@ class BottomBarComposerWidget extends StatelessWidget {
final VoidCallback printDraftAction; final VoidCallback printDraftAction;
final VoidCallback toggleMarkAsImportantAction; final VoidCallback toggleMarkAsImportantAction;
final VoidCallback saveAsTemplateAction; final VoidCallback saveAsTemplateAction;
final VoidCallback onOpenInsertLink;
final OnMenuChanged? onPopupMenuChanged; final OnMenuChanged? onPopupMenuChanged;
const BottomBarComposerWidget({ const BottomBarComposerWidget({
@@ -52,6 +53,7 @@ class BottomBarComposerWidget extends StatelessWidget {
required this.printDraftAction, required this.printDraftAction,
required this.toggleMarkAsImportantAction, required this.toggleMarkAsImportantAction,
required this.saveAsTemplateAction, required this.saveAsTemplateAction,
required this.onOpenInsertLink,
this.onPopupMenuChanged, this.onPopupMenuChanged,
}); });
@@ -110,6 +112,22 @@ class BottomBarComposerWidget extends StatelessWidget {
), ),
), ),
const SizedBox(width: BottomBarComposerWidgetStyle.space), const SizedBox(width: BottomBarComposerWidgetStyle.space),
AbsorbPointer(
absorbing: isCodeViewEnabled,
child: TMailButtonWidget.fromIcon(
icon: imagePaths.icInsertLink,
iconColor: isCodeViewEnabled
? BottomBarComposerWidgetStyle.disabledIconColor
: BottomBarComposerWidgetStyle.iconColor,
borderRadius: BottomBarComposerWidgetStyle.iconRadius,
backgroundColor: Colors.transparent,
padding: BottomBarComposerWidgetStyle.iconPadding,
iconSize: BottomBarComposerWidgetStyle.iconSize,
tooltipMessage: AppLocalizations.of(context).insertLink,
onTapActionCallback: onOpenInsertLink,
),
),
const SizedBox(width: BottomBarComposerWidgetStyle.space),
PopupMenuOverlayWidget( PopupMenuOverlayWidget(
controller: menuMoreOptionController, controller: menuMoreOptionController,
iconButton: HighlightSVGIconOnHover( iconButton: HighlightSVGIconOnHover(
@@ -39,6 +39,7 @@ class WebEditorWidget extends StatefulWidget {
final OnEditorTextSizeChanged? onEditorTextSizeChanged; final OnEditorTextSizeChanged? onEditorTextSizeChanged;
final double? height; final double? height;
final double? horizontalPadding; final double? horizontalPadding;
final LinkOverlayOptions? linkOverlayOptions;
final OnDragEnterListener? onDragEnter; final OnDragEnterListener? onDragEnter;
final OnDragOverListener? onDragOver; final OnDragOverListener? onDragOver;
final OnPasteImageSuccessAction? onPasteImageSuccessAction; final OnPasteImageSuccessAction? onPasteImageSuccessAction;
@@ -60,6 +61,7 @@ class WebEditorWidget extends StatefulWidget {
this.onEditorTextSizeChanged, this.onEditorTextSizeChanged,
this.height, this.height,
this.horizontalPadding, this.horizontalPadding,
this.linkOverlayOptions,
this.onDragEnter, this.onDragEnter,
this.onDragOver, this.onDragOver,
this.onPasteImageSuccessAction, this.onPasteImageSuccessAction,
@@ -141,6 +143,9 @@ class _WebEditorState extends State<WebEditorWidget> {
useDefaultFontStyle: true, useDefaultFontStyle: true,
customScrollbar: true, customScrollbar: true,
), ),
useLinkTooltipOverlay: true,
linkOverlayOptions: widget.linkOverlayOptions
?? const LinkOverlayOptions(),
spellCheck: true, spellCheck: true,
disableDragAndDrop: true, disableDragAndDrop: true,
normalizeHtmlTextWhenDropping: true, normalizeHtmlTextWhenDropping: true,
+43 -1
View File
@@ -1,5 +1,5 @@
{ {
"@@last_modified": "2025-11-05T13:34:06.612241", "@@last_modified": "2025-11-10T12:07:59.064737",
"initializing_data": "Initializing data...", "initializing_data": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
@@ -5069,5 +5069,47 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"insertLink": "Insert link",
"@insertLink": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"goTo": "Go to",
"@goTo": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"change": "Change",
"@change": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"removeLink": "Remove link",
"@removeLink": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"text": "Text",
"@text": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"typeOrPasteLink": "Type or paste a link",
"@typeOrPasteLink": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"apply": "Apply",
"@apply": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
@@ -5366,4 +5366,53 @@ class AppLocalizations {
name: 'favoriteMailboxDisplayName', name: 'favoriteMailboxDisplayName',
); );
} }
String get insertLink {
return Intl.message(
'Insert link',
name: 'insertLink',
);
}
String get goTo {
return Intl.message(
'Go to',
name: 'goTo',
);
}
String get change {
return Intl.message(
'Change',
name: 'change',
);
}
String get removeLink {
return Intl.message(
'Remove link',
name: 'removeLink',
);
}
String get text {
return Intl.message(
'Text',
name: 'text',
);
}
String get typeOrPasteLink {
return Intl.message(
'Type or paste a link',
name: 'typeOrPasteLink',
);
}
String get apply {
return Intl.message(
'Apply',
name: 'apply',
);
}
} }
+10 -2
View File
@@ -1256,8 +1256,8 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
path: "." path: "."
ref: main ref: "feature/summernote-link-tooltip-overlay"
resolved-ref: "33c6f89b1a2cf47f8c148939268488b2bbc19144" resolved-ref: "6c7ac2828e67158734aa5d6c62d4cc94ed2475dc"
url: "https://github.com/linagora/html-editor-enhanced.git" url: "https://github.com/linagora/html-editor-enhanced.git"
source: git source: git
version: "3.3.0" version: "3.3.0"
@@ -1480,6 +1480,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.16.0" version: "1.16.0"
middle_ellipsis_text:
dependency: transitive
description:
name: middle_ellipsis_text
sha256: "70a628b9a152e6a933e518ca835a86a8dbff7a1db73521aeb36cfd02b04f36c1"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
mime: mime:
dependency: "direct main" dependency: "direct main"
description: description:
+1 -1
View File
@@ -63,7 +63,7 @@ dependencies:
html_editor_enhanced: html_editor_enhanced:
git: git:
url: https://github.com/linagora/html-editor-enhanced.git url: https://github.com/linagora/html-editor-enhanced.git
ref: main ref: feature/summernote-link-tooltip-overlay
jmap_dart_client: jmap_dart_client:
git: git: