From 16a5b8d2e0c6d21037c129a5a4beb437b25d69b6 Mon Sep 17 00:00:00 2001 From: HuyNguyen Date: Tue, 12 Nov 2024 22:48:00 +0700 Subject: [PATCH] Fix lagging when scrolling --- lib/src/matrix_linkify.dart | 171 ++++++------------------------------ 1 file changed, 28 insertions(+), 143 deletions(-) diff --git a/lib/src/matrix_linkify.dart b/lib/src/matrix_linkify.dart index 127fcdc..c823265 100644 --- a/lib/src/matrix_linkify.dart +++ b/lib/src/matrix_linkify.dart @@ -6,160 +6,43 @@ import 'package:linkfy_text/src/utils/matrix_regex.dart'; /// Matrix Linkify [text] containing urls, emails or hashtag class MatrixLinkifyText extends StatelessWidget { - const MatrixLinkifyText( - this.text, { - this.textStyle, - this.linkStyle, - this.linkTypes, - this.onTap, - this.customLinkStyles, - this.strutStyle, - this.textAlign, - this.textDirection, - this.locale, - this.softWrap, - this.overflow, - this.textScaler, - this.maxLines, - this.semanticsLabel, - this.textWidthBasis, - Key? key, - this.onTapDownLink, - this.themeData, - }) : super(key: key); - - /// text to be linkified final String text; - - /// [textStyle] applied the text final TextStyle? textStyle; - - /// [textStyle] added to the formatted links in the text final TextStyle? linkStyle; - - /// called when a formatted link is pressed, it returns the link as a parameter - /// ```dart - /// LinkifyText("#helloWorld", onTap: (link) { - /// // do stuff with link - /// print("${link.value} hashtag was tapped"); - /// }); - /// ``` - final void Function(Link)? onTap; - - /// option to override the links to be formatted in the text, defaults to `[LinkType.url]` - /// so only urls are being linkified in the text - final List? linkTypes; - - /// {@macro flutter.painting.textPainter.strutStyle} - final StrutStyle? strutStyle; - - /// How the text should be aligned horizontally. final TextAlign? textAlign; - - /// The directionality of the text. - /// - /// This decides how [textAlign] values like [TextAlign.start] and - /// [TextAlign.end] are interpreted. - /// - /// This is also used to disambiguate how to render bidirectional text. For - /// example, if the [data] is an English phrase followed by a Hebrew phrase, - /// in a [TextDirection.ltr] context the English phrase will be on the left - /// and the Hebrew phrase to its right, while in a [TextDirection.rtl] - /// context, the English phrase will be on the right and the Hebrew phrase on - /// its left. - /// - /// Defaults to the ambient [Directionality], if any. - final TextDirection? textDirection; - - /// Used to select a font when the same Unicode character can - /// be rendered differently, depending on the locale. - /// - /// It's rarely necessary to set this property. By default its value - /// is inherited from the enclosing app with `Localizations.localeOf(context)`. - /// - /// See [RenderParagraph.locale] for more information. - final Locale? locale; - - /// Whether the text should break at soft line breaks. - /// - /// If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. - final bool? softWrap; - - /// How visual overflow should be handled. - /// - /// Defaults to retrieving the value from the nearest [DefaultTextStyle] ancestor. - final TextOverflow? overflow; - - /// The number of font pixels for each logical pixel. - /// - /// For example, if the text scale factor is 1.5, text will be 50% larger than - /// the specified font size. - /// - /// The value given to the constructor as textScaleFactor. If null, will - /// use the [MediaQueryData.textScaler] obtained from the ambient - /// [MediaQuery], or 1.0 if there is no [MediaQuery] in scope. - final TextScaler? textScaler; - - /// An optional maximum number of lines for the text to span, wrapping if necessary. - /// If the text exceeds the given number of lines, it will be truncated according - /// to [overflow]. - /// - /// If this is 1, text will not wrap. Otherwise, text will be wrapped at the - /// edge of the box. - /// - /// If this is null, but there is an ambient [DefaultTextStyle] that specifies - /// an explicit number for its [DefaultTextStyle.maxLines], then the - /// [DefaultTextStyle] value will take precedence. You can use a [RichText] - /// widget directly to entirely override the [DefaultTextStyle]. + final List? linkTypes; + final ThemeData? themeData; + final Function(Link)? onTapLink; + final Function(TapDownDetails, Link)? onTapDownLink; final int? maxLines; - /// An alternative semantics label for this text. - /// - /// If present, the semantics of this widget will contain this value instead - /// of the actual text. This will overwrite any of the semantics labels applied - /// directly to the [TextSpan]s. - /// - /// This is useful for replacing abbreviations or shorthands with the full - /// text value: - /// - /// ```dart - /// Text(r'$$', semanticsLabel: 'Double dollars') - /// ``` - final String? semanticsLabel; - - /// {@macro flutter.painting.textPainter.textWidthBasis} - final TextWidthBasis? textWidthBasis; - - final Map? customLinkStyles; - - final void Function(TapDownDetails, Link)? onTapDownLink; - - final ThemeData? themeData; + const MatrixLinkifyText({ + Key? key, + required this.text, + this.textStyle, + this.linkStyle, + this.textAlign = TextAlign.start, + this.maxLines, + this.linkTypes, + this.themeData, + this.onTapLink, + this.onTapDownLink, + }) : super(key: key); @override Widget build(BuildContext context) { - return Text.rich( + return CleanRichText( LinkifyTextSpans( text: text, + textStyle: textStyle, linkStyle: linkStyle, - onTapLink: onTap, - onTapDownLink: onTapDownLink, - themeData: themeData, linkTypes: linkTypes, - customLinkStyles: customLinkStyles, + themeData: themeData, + onTapLink: onTapLink, + onTapDownLink: onTapDownLink, ), - key: key, - style: textStyle, - strutStyle: strutStyle, textAlign: textAlign, - textDirection: textDirection, - textScaler: textScaler, - textWidthBasis: textWidthBasis, - semanticsLabel: semanticsLabel, - softWrap: softWrap, - overflow: overflow, maxLines: maxLines, - locale: locale, ); } } @@ -291,25 +174,26 @@ TextSpan LinkifyTextSpans({ decoration: TextDecoration.underline, ); - final _regExp = - constructMatrixRegExpFromLinkType(linkTypes ?? [LinkType.url]); + final regExp = constructMatrixRegExpFromLinkType(linkTypes ?? [LinkType.url]); // return the full text if there's no match or if empty - if (!_regExp.hasMatch(text) || text.isEmpty) { + if (!regExp.hasMatch(text) || text.isEmpty) { return TextSpan( text: text, style: textStyle, + children: const [], ); } - final texts = text.split(_regExp); + final texts = text.split(regExp); final List spans = []; - final highlights = _regExp.allMatches(text).toList(); + final highlights = regExp.allMatches(text).toList(); for (final text in texts) { spans.add(TextSpan( text: text, style: textStyle, + children: const [], )); if (highlights.isNotEmpty) { @@ -319,6 +203,7 @@ TextSpan LinkifyTextSpans({ spans.add(TextSpan( text: link.value, style: textStyle, + children: const [], )); continue; }