add custom recognizer (#1196)

pull/1198/head
jiangchong 2 years ago committed by GitHub
parent 8fe0e0004b
commit 744d0b6c39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      lib/src/widgets/delegate.dart
  2. 3
      lib/src/widgets/editor.dart
  3. 3
      lib/src/widgets/raw_editor.dart
  4. 43
      lib/src/widgets/text_line.dart

@ -14,6 +14,8 @@ typedef EmbedsBuilder = EmbedBuilder Function(Embed node);
typedef CustomStyleBuilder = TextStyle Function(Attribute attribute);
typedef CustomRecognizerBuilder = GestureRecognizer? Function(Attribute attribute);
/// Delegate interface for the [EditorTextSelectionGestureDetectorBuilder].
///
/// The interface is usually implemented by textfield implementations wrapping

@ -176,6 +176,7 @@ class QuillEditor extends StatefulWidget {
this.unknownEmbedBuilder,
this.linkActionPickerDelegate = defaultLinkActionPickerDelegate,
this.customStyleBuilder,
this.customRecognizerBuilder,
this.locale,
this.floatingCursorDisabled = false,
this.textSelectionControls,
@ -372,6 +373,7 @@ class QuillEditor extends StatefulWidget {
final Iterable<EmbedBuilder>? embedBuilders;
final EmbedBuilder? unknownEmbedBuilder;
final CustomStyleBuilder? customStyleBuilder;
final CustomRecognizerBuilder? customRecognizerBuilder;
/// The locale to use for the editor toolbar, defaults to system locale
/// More https://github.com/singerdmx/flutter-quill#translation
@ -518,6 +520,7 @@ class QuillEditorState extends State<QuillEditor>
embedBuilder: _getEmbedBuilder,
linkActionPickerDelegate: widget.linkActionPickerDelegate,
customStyleBuilder: widget.customStyleBuilder,
customRecognizerBuilder: widget.customRecognizerBuilder,
floatingCursorDisabled: widget.floatingCursorDisabled,
onImagePaste: widget.onImagePaste,
customShortcuts: widget.customShortcuts,

@ -79,6 +79,7 @@ class RawEditor extends StatefulWidget {
this.scrollPhysics,
this.linkActionPickerDelegate = defaultLinkActionPickerDelegate,
this.customStyleBuilder,
this.customRecognizerBuilder,
this.floatingCursorDisabled = false,
this.onImagePaste,
this.customLinkPrefixes = const <String>[],
@ -262,6 +263,7 @@ class RawEditor extends StatefulWidget {
final EmbedsBuilder embedBuilder;
final LinkActionPickerDelegate linkActionPickerDelegate;
final CustomStyleBuilder? customStyleBuilder;
final CustomRecognizerBuilder? customRecognizerBuilder;
final bool floatingCursorDisabled;
final List<String> customLinkPrefixes;
@ -925,6 +927,7 @@ class RawEditorState extends EditorState
textDirection: _textDirection,
embedBuilder: widget.embedBuilder,
customStyleBuilder: widget.customStyleBuilder,
customRecognizerBuilder: widget.customRecognizerBuilder,
styles: _styles!,
readOnly: widget.readOnly,
controller: controller,

@ -41,6 +41,7 @@ class TextLine extends StatefulWidget {
required this.linkActionPicker,
this.textDirection,
this.customStyleBuilder,
this.customRecognizerBuilder,
this.customLinkPrefixes = const <String>[],
Key? key,
}) : super(key: key);
@ -52,6 +53,7 @@ class TextLine extends StatefulWidget {
final bool readOnly;
final QuillController controller;
final CustomStyleBuilder? customStyleBuilder;
final CustomRecognizerBuilder? customRecognizerBuilder;
final ValueChanged<String>? onLaunchUrl;
final LinkActionPicker linkActionPicker;
final List<String> customLinkPrefixes;
@ -313,12 +315,14 @@ class _TextLineState extends State<TextLine> {
final isLink = nodeStyle.containsKey(Attribute.link.key) &&
nodeStyle.attributes[Attribute.link.key]!.value != null;
final recognizer = _getRecognizer(node, isLink);
return TextSpan(
text: textNode.value,
style: _getInlineTextStyle(
textNode, defaultStyles, nodeStyle, lineStyle, isLink),
recognizer: isLink && canLaunchLinks ? _getRecognizer(node) : null,
mouseCursor: isLink && canLaunchLinks ? SystemMouseCursors.click : null,
recognizer: recognizer,
mouseCursor: (recognizer != null) ? SystemMouseCursors.click : null,
);
}
@ -406,19 +410,38 @@ class _TextLineState extends State<TextLine> {
return res;
}
GestureRecognizer _getRecognizer(Node segment) {
GestureRecognizer? _getRecognizer(Node segment, bool isLink) {
if (_linkRecognizers.containsKey(segment)) {
return _linkRecognizers[segment]!;
}
if (isDesktop() || widget.readOnly) {
_linkRecognizers[segment] = TapGestureRecognizer()
..onTap = () => _tapNodeLink(segment);
} else {
_linkRecognizers[segment] = LongPressGestureRecognizer()
..onLongPress = () => _longPressLink(segment);
if (widget.customRecognizerBuilder != null) {
final textNode = segment as leaf.Text;
final nodeStyle = textNode.style;
nodeStyle.attributes.forEach((key, value) {
final recognizer = widget.customRecognizerBuilder!.call(value);
if (recognizer != null) {
_linkRecognizers[segment] = recognizer;
return;
}
});
}
if (_linkRecognizers.containsKey(segment)) {
return _linkRecognizers[segment]!;
}
if (isLink && canLaunchLinks) {
if (isDesktop() || widget.readOnly) {
_linkRecognizers[segment] = TapGestureRecognizer()
..onTap = () => _tapNodeLink(segment);
} else {
_linkRecognizers[segment] = LongPressGestureRecognizer()
..onLongPress = () => _longPressLink(segment);
}
}
return _linkRecognizers[segment]!;
return _linkRecognizers[segment];
}
Future<void> _launchUrl(String url) async {

Loading…
Cancel
Save