fix: Some links not clickable in messages

This commit is contained in:
Krille 2023-12-27 15:26:22 +01:00
commit 6b53d27c4c
No known key found for this signature in database
GPG key ID: E067ECD60F1A0652
3 changed files with 111 additions and 96 deletions

View file

@ -6,6 +6,7 @@ import 'package:flutter_highlighter/themes/shades-of-purple.dart';
import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html_table/flutter_html_table.dart'; import 'package:flutter_html_table/flutter_html_table.dart';
import 'package:flutter_math_fork/flutter_math.dart'; import 'package:flutter_math_fork/flutter_math.dart';
import 'package:html/dom.dart' as dom;
import 'package:linkify/linkify.dart'; import 'package:linkify/linkify.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
@ -26,6 +27,35 @@ class HtmlMessage extends StatelessWidget {
this.textColor = Colors.black, this.textColor = Colors.black,
}); });
dom.Node _linkifyHtml(dom.Node element) {
for (final node in element.nodes) {
if (node is! dom.Text) {
node.replaceWith(_linkifyHtml(node));
continue;
}
final parts = linkify(
node.text,
options: const LinkifyOptions(humanize: false),
);
if (!parts.any((part) => part is UrlElement)) {
continue;
}
final newHtml = parts
.map(
(linkifyElement) => linkifyElement is! UrlElement
? linkifyElement.text
: '<a href="${linkifyElement.text}">${linkifyElement.text}</a>',
)
.join(' ');
node.replaceWith(dom.Element.html(newHtml));
}
return element;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// riot-web is notorious for creating bad reply fallback events from invalid messages which, if // riot-web is notorious for creating bad reply fallback events from invalid messages which, if
@ -46,21 +76,6 @@ class HtmlMessage extends StatelessWidget {
final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor;
final linkifiedRenderHtml = linkify(
renderHtml,
options: const LinkifyOptions(humanize: false),
).map(
(element) {
if (element is! UrlElement ||
element.text.contains('<') ||
element.text.contains('>') ||
element.text.contains('"')) {
return element.text;
}
return '<a href="${element.url}">${element.text}</a>';
},
).join('');
final linkColor = textColor.withAlpha(150); final linkColor = textColor.withAlpha(150);
final blockquoteStyle = Style( final blockquoteStyle = Style(
@ -73,11 +88,11 @@ class HtmlMessage extends StatelessWidget {
padding: HtmlPaddings.only(left: 6, bottom: 0), padding: HtmlPaddings.only(left: 6, bottom: 0),
); );
final element = _linkifyHtml(HtmlParser.parseHTML(renderHtml));
// there is no need to pre-validate the html, as we validate it while rendering // there is no need to pre-validate the html, as we validate it while rendering
return MouseRegion( return Html.fromElement(
cursor: SystemMouseCursors.text, documentElement: element as dom.Element,
child: Html(
data: linkifiedRenderHtml,
style: { style: {
'*': Style( '*': Style(
color: textColor, color: textColor,
@ -153,7 +168,6 @@ class HtmlMessage extends StatelessWidget {
'html', 'html',
}, },
shrinkWrap: true, shrinkWrap: true,
),
); );
} }

View file

@ -872,7 +872,7 @@ packages:
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
html: html:
dependency: transitive dependency: "direct main"
description: description:
name: html name: html
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"

View file

@ -54,6 +54,7 @@ dependencies:
go_router: ^12.1.1 go_router: ^12.1.1
hive: ^2.2.3 hive: ^2.2.3
hive_flutter: ^1.1.0 hive_flutter: ^1.1.0
html: ^0.15.4
http: ^0.13.6 http: ^0.13.6
image_picker: ^1.0.0 image_picker: ^1.0.0
intl: any intl: any