From 530d1123b938fba219f3eb181ed21fe5cfabc13e Mon Sep 17 00:00:00 2001 From: Felix Gabler Date: Tue, 1 Feb 2022 09:31:42 +0100 Subject: [PATCH 1/2] feat: open link on text and image tap too --- lib/src/widgets/link_preview.dart | 109 +++++++++++++++++------------- 1 file changed, 61 insertions(+), 48 deletions(-) diff --git a/lib/src/widgets/link_preview.dart b/lib/src/widgets/link_preview.dart index 3fc36f8..e06835e 100644 --- a/lib/src/widgets/link_preview.dart +++ b/lib/src/widgets/link_preview.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' show PreviewData; import 'package:flutter_linkify/flutter_linkify.dart' hide UrlLinkifier; import 'package:url_launcher/url_launcher.dart'; + import '../url_linkifier.dart' show UrlLinkifier; import '../utils.dart' show getPreviewData; @@ -175,9 +176,11 @@ class _LinkPreviewState extends State widget.previewData?.image?.url != null; } - Future _onOpen(LinkableElement link) async { - if (await canLaunch(link.url)) { - await launch(link.url); + Future _onOpen(String url) async { + if (widget.onLinkPressed != null) { + widget.onLinkPressed!(url); + } else if (await canLaunch(url)) { + await launch(url); } } @@ -201,23 +204,26 @@ class _LinkPreviewState extends State return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - padding: EdgeInsets.only( - bottom: _padding.bottom, - left: _padding.left, - right: _padding.right, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (data.title != null) _titleWidget(data.title!), - if (data.description != null) - _descriptionWidget(data.description!), - ], + GestureDetector( + onTap: () => _onOpen(data.link!), + child: Container( + padding: EdgeInsets.only( + bottom: _padding.bottom, + left: _padding.left, + right: _padding.right, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (data.title != null) _titleWidget(data.title!), + if (data.description != null) + _descriptionWidget(data.description!), + ], + ), ), ), if (data.image?.url != null && widget.hideImage != true) - _imageWidget(data.image!.url, width), + _imageWidget(data.image!.url, data.link!, width), ], ); } @@ -288,18 +294,21 @@ class _LinkPreviewState extends State ); } - Widget _imageWidget(String url, double width) { - return Container( - constraints: BoxConstraints( - maxHeight: width, + Widget _imageWidget(String imageUrl, String linkUrl, double width) { + return GestureDetector( + onTap: () => _onOpen(linkUrl), + child: Container( + constraints: BoxConstraints( + maxHeight: width, + ), + width: width, + child: widget.imageBuilder != null + ? widget.imageBuilder!(imageUrl) + : Image.network( + imageUrl, + fit: BoxFit.contain, + ), ), - width: width, - child: widget.imageBuilder != null - ? widget.imageBuilder!(url) - : Image.network( - url, - fit: BoxFit.contain, - ), ); } @@ -309,9 +318,7 @@ class _LinkPreviewState extends State linkStyle: widget.linkStyle, maxLines: 100, minLines: 1, - onOpen: widget.onLinkPressed != null - ? (element) => widget.onLinkPressed!(element.url) - : _onOpen, + onOpen: (link) => _onOpen(link.url), options: const LinkifyOptions( defaultToHttps: true, humanize: false, @@ -333,20 +340,23 @@ class _LinkPreviewState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: Container( - margin: const EdgeInsets.only(right: 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (data.title != null) _titleWidget(data.title!), - if (data.description != null) - _descriptionWidget(data.description!), - ], + child: GestureDetector( + onTap: () => _onOpen(data.link!), + child: Container( + margin: const EdgeInsets.only(right: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (data.title != null) _titleWidget(data.title!), + if (data.description != null) + _descriptionWidget(data.description!), + ], + ), ), ), ), if (data.image?.url != null && widget.hideImage != true) - _minimizedImageWidget(data.image!.url), + _minimizedImageWidget(data.image!.url, data.link!), ], ), ), @@ -354,17 +364,20 @@ class _LinkPreviewState extends State ); } - Widget _minimizedImageWidget(String url) { + Widget _minimizedImageWidget(String imageUrl, String linkUrl) { return ClipRRect( borderRadius: const BorderRadius.all( Radius.circular(12), ), - child: SizedBox( - height: 48, - width: 48, - child: widget.imageBuilder != null - ? widget.imageBuilder!(url) - : Image.network(url), + child: GestureDetector( + onTap: () => _onOpen(linkUrl), + child: SizedBox( + height: 48, + width: 48, + child: widget.imageBuilder != null + ? widget.imageBuilder!(imageUrl) + : Image.network(imageUrl), + ), ), ); } From f20b2c9a27791e7221d1f0bb8593dab600d4a83d Mon Sep 17 00:00:00 2001 From: Felix Gabler Date: Sun, 6 Feb 2022 16:54:20 +0100 Subject: [PATCH 2/2] feat: make link opening on title/image tap optional --- lib/src/widgets/link_preview.dart | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/src/widgets/link_preview.dart b/lib/src/widgets/link_preview.dart index e06835e..1bb44e4 100644 --- a/lib/src/widgets/link_preview.dart +++ b/lib/src/widgets/link_preview.dart @@ -26,6 +26,8 @@ class LinkPreview extends StatefulWidget { this.metadataTitleStyle, this.onLinkPressed, required this.onPreviewDataFetched, + this.openOnPreviewImageClick = false, + this.openOnPreviewTitleClick = false, this.padding, required this.previewData, required this.text, @@ -72,6 +74,12 @@ class LinkPreview extends StatefulWidget { /// preview data again. final void Function(PreviewData) onPreviewDataFetched; + /// Open the link when the link preview image is clicked. Defaults to false. + final bool openOnPreviewImageClick; + + /// Open the link when the link preview title is clicked. Defaults to false. + final bool openOnPreviewTitleClick; + /// Padding around initial text widget final EdgeInsets? padding; @@ -205,7 +213,8 @@ class _LinkPreviewState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( - onTap: () => _onOpen(data.link!), + onTap: + widget.openOnPreviewTitleClick ? () => _onOpen(data.link!) : null, child: Container( padding: EdgeInsets.only( bottom: _padding.bottom, @@ -296,7 +305,7 @@ class _LinkPreviewState extends State Widget _imageWidget(String imageUrl, String linkUrl, double width) { return GestureDetector( - onTap: () => _onOpen(linkUrl), + onTap: widget.openOnPreviewImageClick ? () => _onOpen(linkUrl) : null, child: Container( constraints: BoxConstraints( maxHeight: width, @@ -341,7 +350,9 @@ class _LinkPreviewState extends State children: [ Expanded( child: GestureDetector( - onTap: () => _onOpen(data.link!), + onTap: widget.openOnPreviewTitleClick + ? () => _onOpen(data.link!) + : null, child: Container( margin: const EdgeInsets.only(right: 4), child: Column( @@ -370,7 +381,7 @@ class _LinkPreviewState extends State Radius.circular(12), ), child: GestureDetector( - onTap: () => _onOpen(linkUrl), + onTap: widget.openOnPreviewImageClick ? () => _onOpen(linkUrl) : null, child: SizedBox( height: 48, width: 48,