mirror of
https://github.com/krille-chan/fluffychat
synced 2024-09-17 07:35:13 +00:00
fix: Some links not clickable in messages
This commit is contained in:
parent
6a75d07dea
commit
6b53d27c4c
3 changed files with 111 additions and 96 deletions
|
@ -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,87 +88,86 @@ 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(
|
style: {
|
||||||
data: linkifiedRenderHtml,
|
'*': Style(
|
||||||
style: {
|
color: textColor,
|
||||||
'*': Style(
|
margin: Margins.all(0),
|
||||||
color: textColor,
|
fontSize: FontSize(fontSize),
|
||||||
margin: Margins.all(0),
|
),
|
||||||
fontSize: FontSize(fontSize),
|
'a': Style(color: linkColor, textDecorationColor: linkColor),
|
||||||
),
|
'h1': Style(
|
||||||
'a': Style(color: linkColor, textDecorationColor: linkColor),
|
fontSize: FontSize(fontSize * 2),
|
||||||
'h1': Style(
|
lineHeight: LineHeight.number(1.5),
|
||||||
fontSize: FontSize(fontSize * 2),
|
fontWeight: FontWeight.w600,
|
||||||
lineHeight: LineHeight.number(1.5),
|
),
|
||||||
fontWeight: FontWeight.w600,
|
'h2': Style(
|
||||||
),
|
fontSize: FontSize(fontSize * 1.75),
|
||||||
'h2': Style(
|
lineHeight: LineHeight.number(1.5),
|
||||||
fontSize: FontSize(fontSize * 1.75),
|
fontWeight: FontWeight.w500,
|
||||||
lineHeight: LineHeight.number(1.5),
|
),
|
||||||
fontWeight: FontWeight.w500,
|
'h3': Style(
|
||||||
),
|
fontSize: FontSize(fontSize * 1.5),
|
||||||
'h3': Style(
|
lineHeight: LineHeight.number(1.5),
|
||||||
fontSize: FontSize(fontSize * 1.5),
|
),
|
||||||
lineHeight: LineHeight.number(1.5),
|
'h4': Style(
|
||||||
),
|
fontSize: FontSize(fontSize * 1.25),
|
||||||
'h4': Style(
|
lineHeight: LineHeight.number(1.5),
|
||||||
fontSize: FontSize(fontSize * 1.25),
|
),
|
||||||
lineHeight: LineHeight.number(1.5),
|
'h5': Style(
|
||||||
),
|
fontSize: FontSize(fontSize * 1.25),
|
||||||
'h5': Style(
|
lineHeight: LineHeight.number(1.5),
|
||||||
fontSize: FontSize(fontSize * 1.25),
|
),
|
||||||
lineHeight: LineHeight.number(1.5),
|
'h6': Style(
|
||||||
),
|
fontSize: FontSize(fontSize),
|
||||||
'h6': Style(
|
lineHeight: LineHeight.number(1.5),
|
||||||
fontSize: FontSize(fontSize),
|
),
|
||||||
lineHeight: LineHeight.number(1.5),
|
'blockquote': blockquoteStyle,
|
||||||
),
|
'tg-forward': blockquoteStyle,
|
||||||
'blockquote': blockquoteStyle,
|
'hr': Style(
|
||||||
'tg-forward': blockquoteStyle,
|
border: Border.all(color: textColor, width: 0.5),
|
||||||
'hr': Style(
|
),
|
||||||
border: Border.all(color: textColor, width: 0.5),
|
'table': Style(
|
||||||
),
|
border: Border.all(color: textColor, width: 0.5),
|
||||||
'table': Style(
|
),
|
||||||
border: Border.all(color: textColor, width: 0.5),
|
'tr': Style(
|
||||||
),
|
border: Border.all(color: textColor, width: 0.5),
|
||||||
'tr': Style(
|
),
|
||||||
border: Border.all(color: textColor, width: 0.5),
|
'td': Style(
|
||||||
),
|
border: Border.all(color: textColor, width: 0.5),
|
||||||
'td': Style(
|
padding: HtmlPaddings.all(2),
|
||||||
border: Border.all(color: textColor, width: 0.5),
|
),
|
||||||
padding: HtmlPaddings.all(2),
|
'th': Style(
|
||||||
),
|
border: Border.all(color: textColor, width: 0.5),
|
||||||
'th': Style(
|
),
|
||||||
border: Border.all(color: textColor, width: 0.5),
|
},
|
||||||
),
|
extensions: [
|
||||||
},
|
RoomPillExtension(context, room),
|
||||||
extensions: [
|
CodeExtension(fontSize: fontSize),
|
||||||
RoomPillExtension(context, room),
|
MatrixMathExtension(
|
||||||
CodeExtension(fontSize: fontSize),
|
style: TextStyle(fontSize: fontSize, color: textColor),
|
||||||
MatrixMathExtension(
|
),
|
||||||
style: TextStyle(fontSize: fontSize, color: textColor),
|
const TableHtmlExtension(),
|
||||||
),
|
SpoilerExtension(textColor: textColor),
|
||||||
const TableHtmlExtension(),
|
const ImageExtension(),
|
||||||
SpoilerExtension(textColor: textColor),
|
FontColorExtension(),
|
||||||
const ImageExtension(),
|
],
|
||||||
FontColorExtension(),
|
onLinkTap: (url, _, element) => UrlLauncher(
|
||||||
],
|
context,
|
||||||
onLinkTap: (url, _, element) => UrlLauncher(
|
url,
|
||||||
context,
|
element?.text,
|
||||||
url,
|
).launchUrl(),
|
||||||
element?.text,
|
onlyRenderTheseTags: const {
|
||||||
).launchUrl(),
|
...allowedHtmlTags,
|
||||||
onlyRenderTheseTags: const {
|
// Needed to make it work properly
|
||||||
...allowedHtmlTags,
|
'body',
|
||||||
// Needed to make it work properly
|
'html',
|
||||||
'body',
|
},
|
||||||
'html',
|
shrinkWrap: true,
|
||||||
},
|
|
||||||
shrinkWrap: true,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue