diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 1b4ade9..0448d50 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -262,11 +262,11 @@ Future getPreviewData( } /// Regex to check if text is email. -const regexEmail = r'([a-zA-Z0-9+._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)'; +const regexEmail = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'; /// Regex to check if content type is an image. const regexImageContentType = r'image\/*'; /// Regex to find all links in the text. const regexLink = - r'((http|ftp|https):\/\/)?([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?'; + r'((http|ftp|https):\/\/)?([\w_-]+(?:(?:\.[\w_-]*[a-zA-Z_][\w_-]*)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?[^\.\s]'; diff --git a/lib/src/widgets/link_preview.dart b/lib/src/widgets/link_preview.dart index c71d670..a79790c 100644 --- a/lib/src/widgets/link_preview.dart +++ b/lib/src/widgets/link_preview.dart @@ -29,6 +29,7 @@ class LinkPreview extends StatefulWidget { this.openOnPreviewImageTap = false, this.openOnPreviewTitleTap = false, this.padding, + this.previewBuilder, required this.previewData, this.requestTimeout, required this.text, @@ -86,6 +87,9 @@ class LinkPreview extends StatefulWidget { /// Padding around initial text widget. final EdgeInsets? padding; + /// Function that allows you to build a custom link preview. + final Widget Function(BuildContext, PreviewData)? previewBuilder; + /// Pass saved [PreviewData] here so [LinkPreview] would not fetch preview /// data again. final PreviewData? previewData; @@ -422,20 +426,24 @@ class _LinkPreviewState extends State final previewData = widget.previewData; if (previewData != null && _hasData(previewData)) { - final aspectRatio = widget.previewData!.image == null - ? null - : widget.previewData!.image!.width / - widget.previewData!.image!.height; - - final width = aspectRatio == 1 ? widget.width : widget.width - 32; - - return _containerWidget( - animate: shouldAnimate, - child: aspectRatio == 1 - ? _minimizedBodyWidget(previewData) - : _bodyWidget(previewData, width), - withPadding: aspectRatio == 1, - ); + if (widget.previewBuilder != null) { + return widget.previewBuilder!(context, previewData); + } else { + final aspectRatio = widget.previewData!.image == null + ? null + : widget.previewData!.image!.width / + widget.previewData!.image!.height; + + final width = aspectRatio == 1 ? widget.width : widget.width - 32; + + return _containerWidget( + animate: shouldAnimate, + child: aspectRatio == 1 + ? _minimizedBodyWidget(previewData) + : _bodyWidget(previewData, width), + withPadding: aspectRatio == 1, + ); + } } else { return _containerWidget(animate: false); }