diff --git a/lib/src/widgets/link.dart b/lib/src/widgets/link.dart index dce921fb..34cfe419 100644 --- a/lib/src/widgets/link.dart +++ b/lib/src/widgets/link.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import '../models/documents/attribute.dart'; import '../models/documents/nodes/node.dart'; import '../translations/toolbar.i18n.dart'; @@ -42,6 +43,33 @@ Future defaultLinkActionPickerDelegate( } } +TextRange getLinkRange(Node node) { + var start = node.documentOffset; + var length = node.length; + var prev = node.previous; + final linkAttr = node.style.attributes[Attribute.link.key]!; + while (prev != null) { + if (prev.style.attributes[Attribute.link.key] == linkAttr) { + start = prev.documentOffset; + length += prev.length; + prev = prev.previous; + } else { + break; + } + } + + var next = node.next; + while (next != null) { + if (next.style.attributes[Attribute.link.key] == linkAttr) { + length += next.length; + next = next.next; + } else { + break; + } + } + return TextRange(start: start, end: start + length); +} + Future _showCupertinoLinkMenu( BuildContext context, String link) async { final result = await showCupertinoModalPopup( diff --git a/lib/src/widgets/text_line.dart b/lib/src/widgets/text_line.dart index 089db489..8fa53e57 100644 --- a/lib/src/widgets/text_line.dart +++ b/lib/src/widgets/text_line.dart @@ -423,7 +423,7 @@ class _TextLineState extends State { Clipboard.setData(ClipboardData(text: link)); break; case LinkMenuAction.remove: - final range = _getLinkRange(node); + final range = getLinkRange(node); widget.controller .formatText(range.start, range.end - range.start, Attribute.link); break; @@ -432,33 +432,6 @@ class _TextLineState extends State { } } - TextRange _getLinkRange(Node node) { - var start = node.documentOffset; - var length = node.length; - var prev = node.previous; - final linkAttr = node.style.attributes[Attribute.link.key]!; - while (prev != null) { - if (prev.style.attributes[Attribute.link.key] == linkAttr) { - start = prev.documentOffset; - length += prev.length; - prev = prev.previous; - } else { - break; - } - } - - var next = node.next; - while (next != null) { - if (next.style.attributes[Attribute.link.key] == linkAttr) { - length += next.length; - next = next.next; - } else { - break; - } - } - return TextRange(start: start, end: start + length); - } - TextStyle _merge(TextStyle a, TextStyle b) { final decorations = []; if (a.decoration != null) { diff --git a/lib/src/widgets/toolbar/link_style_button.dart b/lib/src/widgets/toolbar/link_style_button.dart index a7c1c0eb..8b75601d 100644 --- a/lib/src/widgets/toolbar/link_style_button.dart +++ b/lib/src/widgets/toolbar/link_style_button.dart @@ -7,6 +7,7 @@ import '../../models/themes/quill_dialog_theme.dart'; import '../../models/themes/quill_icon_theme.dart'; import '../../translations/toolbar.i18n.dart'; import '../controller.dart'; +import '../link.dart'; import '../toolbar.dart'; class LinkStyleButton extends StatefulWidget { @@ -134,10 +135,19 @@ class _LinkStyleButtonState extends State { final String text = (value as Tuple2).item1; final String link = value.item2; - final index = widget.controller.selection.baseOffset; - final length = widget.controller.selection.extentOffset - index; + var index = widget.controller.selection.baseOffset; + var length = widget.controller.selection.extentOffset - index; + if (_getLinkAttributeValue() != null) { + // text should be the link's corresponding text, not selection + final leaf = widget.controller.document.querySegmentLeafNode(index).item2; + if (leaf != null) { + final range = getLinkRange(leaf); + index = range.start; + length = range.end - range.start; + } + } widget.controller.replaceText(index, length, text, null); - widget.controller.formatSelection(LinkAttribute(link)); + widget.controller.formatText(index, text.length, LinkAttribute(link)); } }