Skip to content
This repository was archived by the owner on Jul 19, 2025. It is now read-only.

Commit db4a5a5

Browse files
Merge pull request #39 from felixgabler/fg/open_from_title_and_image
Open link on text and image tap too
2 parents eface02 + f20b2c9 commit db4a5a5

File tree

1 file changed

+72
-48
lines changed

1 file changed

+72
-48
lines changed

lib/src/widgets/link_preview.dart

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_chat_types/flutter_chat_types.dart' show PreviewData;
33
import 'package:flutter_linkify/flutter_linkify.dart' hide UrlLinkifier;
44
import 'package:url_launcher/url_launcher.dart';
5+
56
import '../url_linkifier.dart' show UrlLinkifier;
67
import '../utils.dart' show getPreviewData;
78

@@ -25,6 +26,8 @@ class LinkPreview extends StatefulWidget {
2526
this.metadataTitleStyle,
2627
this.onLinkPressed,
2728
required this.onPreviewDataFetched,
29+
this.openOnPreviewImageClick = false,
30+
this.openOnPreviewTitleClick = false,
2831
this.padding,
2932
required this.previewData,
3033
required this.text,
@@ -72,6 +75,12 @@ class LinkPreview extends StatefulWidget {
7275
/// preview data again.
7376
final void Function(PreviewData) onPreviewDataFetched;
7477

78+
/// Open the link when the link preview image is clicked. Defaults to false.
79+
final bool openOnPreviewImageClick;
80+
81+
/// Open the link when the link preview title is clicked. Defaults to false.
82+
final bool openOnPreviewTitleClick;
83+
7584
/// Padding around initial text widget
7685
final EdgeInsets? padding;
7786

@@ -182,9 +191,11 @@ class _LinkPreviewState extends State<LinkPreview>
182191
widget.previewData?.image?.url != null;
183192
}
184193

185-
Future<void> _onOpen(LinkableElement link) async {
186-
if (await canLaunch(link.url)) {
187-
await launch(link.url);
194+
Future<void> _onOpen(String url) async {
195+
if (widget.onLinkPressed != null) {
196+
widget.onLinkPressed!(url);
197+
} else if (await canLaunch(url)) {
198+
await launch(url);
188199
}
189200
}
190201

@@ -208,23 +219,27 @@ class _LinkPreviewState extends State<LinkPreview>
208219
return Column(
209220
crossAxisAlignment: CrossAxisAlignment.start,
210221
children: <Widget>[
211-
Container(
212-
padding: EdgeInsets.only(
213-
bottom: _padding.bottom,
214-
left: _padding.left,
215-
right: _padding.right,
216-
),
217-
child: Column(
218-
crossAxisAlignment: CrossAxisAlignment.start,
219-
children: <Widget>[
220-
if (data.title != null) _titleWidget(data.title!),
221-
if (data.description != null)
222-
_descriptionWidget(data.description!),
223-
],
222+
GestureDetector(
223+
onTap:
224+
widget.openOnPreviewTitleClick ? () => _onOpen(data.link!) : null,
225+
child: Container(
226+
padding: EdgeInsets.only(
227+
bottom: _padding.bottom,
228+
left: _padding.left,
229+
right: _padding.right,
230+
),
231+
child: Column(
232+
crossAxisAlignment: CrossAxisAlignment.start,
233+
children: <Widget>[
234+
if (data.title != null) _titleWidget(data.title!),
235+
if (data.description != null)
236+
_descriptionWidget(data.description!),
237+
],
238+
),
224239
),
225240
),
226241
if (data.image?.url != null && widget.hideImage != true)
227-
_imageWidget(data.image!.url, width),
242+
_imageWidget(data.image!.url, data.link!, width),
228243
],
229244
);
230245
}
@@ -295,18 +310,21 @@ class _LinkPreviewState extends State<LinkPreview>
295310
);
296311
}
297312

298-
Widget _imageWidget(String url, double width) {
299-
return Container(
300-
constraints: BoxConstraints(
301-
maxHeight: width,
313+
Widget _imageWidget(String imageUrl, String linkUrl, double width) {
314+
return GestureDetector(
315+
onTap: widget.openOnPreviewImageClick ? () => _onOpen(linkUrl) : null,
316+
child: Container(
317+
constraints: BoxConstraints(
318+
maxHeight: width,
319+
),
320+
width: width,
321+
child: widget.imageBuilder != null
322+
? widget.imageBuilder!(imageUrl)
323+
: Image.network(
324+
imageUrl,
325+
fit: BoxFit.contain,
326+
),
302327
),
303-
width: width,
304-
child: widget.imageBuilder != null
305-
? widget.imageBuilder!(url)
306-
: Image.network(
307-
url,
308-
fit: BoxFit.contain,
309-
),
310328
);
311329
}
312330

@@ -316,9 +334,7 @@ class _LinkPreviewState extends State<LinkPreview>
316334
linkStyle: widget.linkStyle,
317335
maxLines: 100,
318336
minLines: 1,
319-
onOpen: widget.onLinkPressed != null
320-
? (element) => widget.onLinkPressed!(element.url)
321-
: _onOpen,
337+
onOpen: (link) => _onOpen(link.url),
322338
options: const LinkifyOptions(
323339
defaultToHttps: true,
324340
humanize: false,
@@ -340,38 +356,46 @@ class _LinkPreviewState extends State<LinkPreview>
340356
crossAxisAlignment: CrossAxisAlignment.start,
341357
children: <Widget>[
342358
Expanded(
343-
child: Container(
344-
margin: const EdgeInsets.only(right: 4),
345-
child: Column(
346-
crossAxisAlignment: CrossAxisAlignment.start,
347-
children: <Widget>[
348-
if (data.title != null) _titleWidget(data.title!),
349-
if (data.description != null)
350-
_descriptionWidget(data.description!),
351-
],
359+
child: GestureDetector(
360+
onTap: widget.openOnPreviewTitleClick
361+
? () => _onOpen(data.link!)
362+
: null,
363+
child: Container(
364+
margin: const EdgeInsets.only(right: 4),
365+
child: Column(
366+
crossAxisAlignment: CrossAxisAlignment.start,
367+
children: <Widget>[
368+
if (data.title != null) _titleWidget(data.title!),
369+
if (data.description != null)
370+
_descriptionWidget(data.description!),
371+
],
372+
),
352373
),
353374
),
354375
),
355376
if (data.image?.url != null && widget.hideImage != true)
356-
_minimizedImageWidget(data.image!.url),
377+
_minimizedImageWidget(data.image!.url, data.link!),
357378
],
358379
),
359380
),
360381
],
361382
);
362383
}
363384

364-
Widget _minimizedImageWidget(String url) {
385+
Widget _minimizedImageWidget(String imageUrl, String linkUrl) {
365386
return ClipRRect(
366387
borderRadius: const BorderRadius.all(
367388
Radius.circular(12),
368389
),
369-
child: SizedBox(
370-
height: 48,
371-
width: 48,
372-
child: widget.imageBuilder != null
373-
? widget.imageBuilder!(url)
374-
: Image.network(url),
390+
child: GestureDetector(
391+
onTap: widget.openOnPreviewImageClick ? () => _onOpen(linkUrl) : null,
392+
child: SizedBox(
393+
height: 48,
394+
width: 48,
395+
child: widget.imageBuilder != null
396+
? widget.imageBuilder!(imageUrl)
397+
: Image.network(imageUrl),
398+
),
375399
),
376400
);
377401
}

0 commit comments

Comments
 (0)