Add HTML render

This commit is contained in:
Sorunome 2020-05-09 11:36:41 +00:00 committed by Christian Pauly
parent eb72198048
commit 3ee1018eb5
12 changed files with 167 additions and 21 deletions

View File

@ -0,0 +1,41 @@
import 'package:famedlysdk/famedlysdk.dart';
import 'package:flutter_matrix_html/flutter_html.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'matrix.dart';
class HtmlMessage extends StatelessWidget {
final String html;
final Color textColor;
final int maxLines;
const HtmlMessage({this.html, this.textColor, this.maxLines});
@override
Widget build(BuildContext context) {
// there is no need to pre-validate the html, as we validate it while rendering
return Html(
data: html,
defaultTextStyle: TextStyle(color: textColor),
shrinkToFit: true,
maxLines: maxLines,
onLinkTap: (String url) {
if (url == null || url.isEmpty) {
return;
}
launch(url);
},
getMxcUrl: (String mxc, double width, double height) {
final ratio = MediaQuery.of(context).devicePixelRatio;
return Uri.parse(mxc)?.getThumbnail(
Matrix.of(context).client,
width: (width ?? 800) * ratio,
height: (height ?? 800) * ratio,
method: ThumbnailMethod.scale,
);
},
);
}
}

View File

@ -55,6 +55,7 @@ class MatrixState extends State<Matrix> {
String activeRoomId;
File wallpaper;
bool renderHtml = false;
String jitsiInstance = 'https://meet.jit.si/';
@ -189,6 +190,9 @@ class MatrixState extends State<Matrix> {
wallpaper = file;
}
});
client.storeAPI.getItem("chat.fluffy.renderHtml").then((final render) async {
renderHtml = render == "1";
});
}
super.initState();
}

View File

@ -8,6 +8,7 @@ import 'package:link_text/link_text.dart';
import 'package:url_launcher/url_launcher.dart';
import 'matrix.dart';
import 'message_download_content.dart';
import 'html_message.dart';
class MessageContent extends StatelessWidget {
final Event event;
@ -36,13 +37,30 @@ class MessageContent extends StatelessWidget {
case MessageTypes.Video:
case MessageTypes.File:
return MessageDownloadContent(event, textColor);
case MessageTypes.BadEncrypted:
case MessageTypes.Text:
case MessageTypes.Notice:
case MessageTypes.Emote:
if (
Matrix.of(context).renderHtml && !event.redacted &&
event.content['format'] == 'org.matrix.custom.html' &&
event.content['formatted_body'] is String
) {
String html = event.content['formatted_body'];
if (event.messageType == MessageTypes.Emote) {
html = "* $html";
}
return HtmlMessage(
html: html,
textColor: textColor,
);
}
// else we fall through to the normal message rendering
continue textmessage;
case MessageTypes.BadEncrypted:
case MessageTypes.Reply:
case MessageTypes.Location:
case MessageTypes.None:
case MessageTypes.Notice:
case MessageTypes.Emote:
textmessage:
default:
if (event.content['msgtype'] == Matrix.callNamespace) {
return RaisedButton(
@ -76,5 +94,6 @@ class MessageContent extends StatelessWidget {
),
);
}
return Container(); // else flutter analyze complains
}
}

View File

@ -2,6 +2,9 @@ import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:flutter/material.dart';
import 'html_message.dart';
import 'matrix.dart';
class ReplyContent extends StatelessWidget {
final Event replyEvent;
final bool lightText;
@ -11,6 +14,40 @@ class ReplyContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
Widget replyBody;
if (
replyEvent != null && Matrix.of(context).renderHtml &&
[EventTypes.Message, EventTypes.Encrypted].contains(replyEvent.type) &&
[MessageTypes.Text, MessageTypes.Notice, MessageTypes.Emote].contains(replyEvent.messageType) &&
!replyEvent.redacted && replyEvent.content['format'] == 'org.matrix.custom.html' && replyEvent.content['formatted_body'] is String
) {
String html = replyEvent.content['formatted_body'];
if (replyEvent.messageType == MessageTypes.Emote) {
html = "* $html";
}
replyBody = HtmlMessage(
html: html,
textColor: lightText
? Colors.white
: Theme.of(context).textTheme.bodyText2.color,
maxLines: 1,
);
} else {
replyBody = Text(
replyEvent?.getLocalizedBody(
L10n.of(context),
withSenderNamePrefix: false,
hideReply: true,
) ??
"",
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: lightText
? Colors.white
: Theme.of(context).textTheme.bodyText2.color),
);
}
return Row(
children: <Widget>[
Container(
@ -34,20 +71,7 @@ class ReplyContent extends StatelessWidget {
lightText ? Colors.white : Theme.of(context).primaryColor,
),
),
Text(
replyEvent?.getLocalizedBody(
L10n.of(context),
withSenderNamePrefix: false,
hideReply: true,
) ??
"",
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: lightText
? Colors.white
: Theme.of(context).textTheme.bodyText2.color),
),
replyBody,
],
),
),

View File

@ -248,6 +248,11 @@
"type": "text",
"placeholders": {}
},
"Chat": "Chat",
"@Chat": {
"type": "text",
"placeholders": {}
},
"Chat details": "Gruppeninfo",
"@Chat details": {
"type": "text",
@ -847,6 +852,11 @@
"type": "text",
"placeholders": {}
},
"Render rich message content": "Zeige Nachrichtenformatierungen an",
"@Render rich message content": {
"type": "text",
"placeholders": {}
},
"redactedAnEvent": "{username} hat ein Event enternt",
"@redactedAnEvent": {
"type": "text",
@ -1317,4 +1327,4 @@
"type": "text",
"placeholders": {}
}
}
}

View File

@ -1,5 +1,5 @@
{
"@@last_modified": "2020-05-09T12:56:54.540935",
"@@last_modified": "2020-05-09T13:02:58.452942",
"About": "About",
"@About": {
"type": "text",
@ -248,6 +248,11 @@
"type": "text",
"placeholders": {}
},
"Chat": "Chat",
"@Chat": {
"type": "text",
"placeholders": {}
},
"Chat details": "Chat details",
"@Chat details": {
"type": "text",
@ -852,6 +857,11 @@
"type": "text",
"placeholders": {}
},
"Render rich message content": "Render rich message content",
"@Render rich message content": {
"type": "text",
"placeholders": {}
},
"Recording": "Recording",
"@Recording": {
"type": "text",
@ -1327,4 +1337,4 @@
"type": "text",
"placeholders": {}
}
}
}

View File

@ -206,6 +206,8 @@ class L10n extends MatrixLocalizations {
String get channelCorruptedDecryptError =>
Intl.message("The encryption has been corrupted");
String get chat => Intl.message('Chat');
String get chatDetails => Intl.message('Chat details');
String get chooseAStrongPassword => Intl.message("Choose a strong password");
@ -524,6 +526,8 @@ class L10n extends MatrixLocalizations {
String get rejoin => Intl.message("Rejoin");
String get renderRichContent => Intl.message("Render rich message content");
String get recording => Intl.message("Recording");
String redactedAnEvent(String username) => Intl.message(

View File

@ -164,6 +164,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Change wallpaper" : MessageLookupByLibrary.simpleMessage("Hintergrund ändern"),
"Change your style" : MessageLookupByLibrary.simpleMessage("Ändere Deinen Style"),
"Changelog" : MessageLookupByLibrary.simpleMessage("Changelog"),
"Chat" : MessageLookupByLibrary.simpleMessage("Chat"),
"Chat details" : MessageLookupByLibrary.simpleMessage("Gruppeninfo"),
"Choose a strong password" : MessageLookupByLibrary.simpleMessage("Wähle ein sicheres Passwort"),
"Choose a username" : MessageLookupByLibrary.simpleMessage("Wähle einen Benutzernamen"),
@ -261,6 +262,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Remove device" : MessageLookupByLibrary.simpleMessage("Gerät entfernen"),
"Remove exile" : MessageLookupByLibrary.simpleMessage("Verbannung aufheben"),
"Remove message" : MessageLookupByLibrary.simpleMessage("Nachricht entfernen"),
"Render rich message content" : MessageLookupByLibrary.simpleMessage("Zeige Nachrichtenformatierungen an"),
"Reply" : MessageLookupByLibrary.simpleMessage("Antworten"),
"Request permission" : MessageLookupByLibrary.simpleMessage("Berechtigung anfragen"),
"Request to read older messages" : MessageLookupByLibrary.simpleMessage("Anfrage um ältere Nachrichten zu lesen"),

View File

@ -164,6 +164,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Change wallpaper" : MessageLookupByLibrary.simpleMessage("Change wallpaper"),
"Change your style" : MessageLookupByLibrary.simpleMessage("Change your style"),
"Changelog" : MessageLookupByLibrary.simpleMessage("Changelog"),
"Chat" : MessageLookupByLibrary.simpleMessage("Chat"),
"Chat details" : MessageLookupByLibrary.simpleMessage("Chat details"),
"Choose a strong password" : MessageLookupByLibrary.simpleMessage("Choose a strong password"),
"Choose a username" : MessageLookupByLibrary.simpleMessage("Choose a username"),
@ -263,6 +264,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Remove device" : MessageLookupByLibrary.simpleMessage("Remove device"),
"Remove exile" : MessageLookupByLibrary.simpleMessage("Remove exile"),
"Remove message" : MessageLookupByLibrary.simpleMessage("Remove message"),
"Render rich message content" : MessageLookupByLibrary.simpleMessage("Render rich message content"),
"Reply" : MessageLookupByLibrary.simpleMessage("Reply"),
"Request permission" : MessageLookupByLibrary.simpleMessage("Request permission"),
"Request to read older messages" : MessageLookupByLibrary.simpleMessage("Request to read older messages"),

View File

@ -210,6 +210,28 @@ class _SettingsState extends State<Settings> {
);
}),
Divider(thickness: 1),
ListTile(
title: Text(
L10n.of(context).chat,
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
),
),
),
ListTile(
title: Text(L10n.of(context).renderRichContent),
trailing: Switch(
value: Matrix.of(context).renderHtml,
activeColor: Theme.of(context).primaryColor,
onChanged: (bool newValue) async {
Matrix.of(context).renderHtml = newValue;
await client.storeAPI.setItem("chat.fluffy.renderHtml", newValue ? "1" : "0");
setState(() => null);
},
),
),
Divider(thickness: 1),
ListTile(
title: Text(
L10n.of(context).account,

View File

@ -181,6 +181,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_matrix_html:
dependency: "direct main"
description:
name: flutter_matrix_html
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.5"
flutter_secure_storage:
dependency: "direct main"
description:
@ -738,7 +745,7 @@ packages:
name: webkit_inspection_protocol
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.2"
version: "0.5.3"
webview_flutter:
dependency: "direct main"
description:

View File

@ -54,6 +54,7 @@ dependencies:
open_file: ^3.0.1
mime_type: ^0.3.0
flutter_styled_toast: ^1.2.1
flutter_matrix_html: ^0.0.5
intl: ^0.16.0
intl_translation: ^0.17.9