add html support
This commit is contained in:
parent
ec48e3ae96
commit
8d3c657ff6
6 changed files with 58 additions and 55 deletions
|
|
@ -1,12 +1,10 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter/widgets.dart";
|
|
||||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:matrix/matrix.dart";
|
import "package:matrix/matrix.dart";
|
||||||
import "package:nexus/models/full_room.dart";
|
import "package:nexus/models/full_room.dart";
|
||||||
import "package:nexus/widgets/error_dialog.dart";
|
import "package:nexus/widgets/error_dialog.dart";
|
||||||
import "package:nexus/widgets/loading.dart";
|
import "package:nexus/widgets/loading.dart";
|
||||||
import "package:html2md/html2md.dart";
|
|
||||||
|
|
||||||
extension BetterWhen<T> on AsyncValue<T> {
|
extension BetterWhen<T> on AsyncValue<T> {
|
||||||
Widget betterWhen({
|
Widget betterWhen({
|
||||||
|
|
@ -39,6 +37,7 @@ extension ToMessage on Event {
|
||||||
? relationshipEventId
|
? relationshipEventId
|
||||||
: null;
|
: null;
|
||||||
final metadata = {
|
final metadata = {
|
||||||
|
"formatted": formattedText.isEmpty ? body : formattedText,
|
||||||
"eventType": type,
|
"eventType": type,
|
||||||
"displayName": senderFromMemoryOrFallback.displayName,
|
"displayName": senderFromMemoryOrFallback.displayName,
|
||||||
"txnId": transactionId,
|
"txnId": transactionId,
|
||||||
|
|
@ -49,34 +48,34 @@ extension ToMessage on Event {
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
id: eventId,
|
id: eventId,
|
||||||
authorId: senderId,
|
authorId: senderId,
|
||||||
text: "~~This message has been redacted.~~",
|
text: "<s>This message has been redacted.</s>",
|
||||||
deletedAt: redactedBecause?.originServerTs,
|
deletedAt: redactedBecause?.originServerTs,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final formatted = convert(
|
final asText =
|
||||||
formattedText.isEmpty ? body : formattedText,
|
Message.text(
|
||||||
ignore: replyId == null ? null : ["mx-reply"],
|
metadata: metadata,
|
||||||
);
|
id: eventId,
|
||||||
|
authorId: senderId,
|
||||||
final asText = Message.text(
|
text: body,
|
||||||
metadata: metadata,
|
replyToMessageId: replyId,
|
||||||
id: eventId,
|
deliveredAt: originServerTs,
|
||||||
authorId: senderId,
|
)
|
||||||
text: formatted,
|
as TextMessage;
|
||||||
replyToMessageId: replyId,
|
|
||||||
deliveredAt: originServerTs,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (mustBeText) return asText;
|
if (mustBeText) return asText;
|
||||||
|
|
||||||
return switch (type) {
|
return switch (type) {
|
||||||
|
EventTypes.Encrypted => asText.copyWith(
|
||||||
|
text: "Unable to decrypt message.",
|
||||||
|
),
|
||||||
EventTypes.Message => switch (messageType) {
|
EventTypes.Message => switch (messageType) {
|
||||||
MessageTypes.Image => Message.image(
|
MessageTypes.Image => Message.image(
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
id: eventId,
|
id: eventId,
|
||||||
authorId: senderId,
|
authorId: senderId,
|
||||||
text: formatted,
|
text: text,
|
||||||
source: (await getAttachmentUri()).toString(),
|
source: (await getAttachmentUri()).toString(),
|
||||||
replyToMessageId: replyId,
|
replyToMessageId: replyId,
|
||||||
deliveredAt: originServerTs,
|
deliveredAt: originServerTs,
|
||||||
|
|
@ -85,7 +84,7 @@ extension ToMessage on Event {
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
id: eventId,
|
id: eventId,
|
||||||
authorId: senderId,
|
authorId: senderId,
|
||||||
text: formatted,
|
text: text,
|
||||||
replyToMessageId: replyId,
|
replyToMessageId: replyId,
|
||||||
source: (await getAttachmentUri()).toString(),
|
source: (await getAttachmentUri()).toString(),
|
||||||
deliveredAt: originServerTs,
|
deliveredAt: originServerTs,
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@ class LaunchHelper {
|
||||||
final Ref ref;
|
final Ref ref;
|
||||||
LaunchHelper(this.ref);
|
LaunchHelper(this.ref);
|
||||||
|
|
||||||
Future<void> launchUrl(Uri url, {bool useWebview = false}) async {
|
Future<bool> launchUrl(Uri url, {bool useWebview = false}) async {
|
||||||
try {
|
try {
|
||||||
await ul.launchUrl(
|
return await ul.launchUrl(
|
||||||
url,
|
url,
|
||||||
mode: useWebview
|
mode: useWebview
|
||||||
? ul.LaunchMode.inAppBrowserView
|
? ul.LaunchMode.inAppBrowserView
|
||||||
: ul.LaunchMode.externalApplication,
|
: ul.LaunchMode.externalApplication,
|
||||||
);
|
);
|
||||||
} on PlatformException catch (_) {
|
} on PlatformException catch (_) {
|
||||||
// Ignore missing intent handler error
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,15 @@ class RoomAppbar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(room.title, overflow: TextOverflow.ellipsis),
|
Text(room.title, overflow: TextOverflow.ellipsis),
|
||||||
Text(
|
if (room.roomData.topic.isNotEmpty)
|
||||||
room.roomData.topic,
|
Text(
|
||||||
maxLines: 1,
|
room.roomData.topic,
|
||||||
overflow: TextOverflow.ellipsis,
|
maxLines: 1,
|
||||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
overflow: TextOverflow.ellipsis,
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import "package:nexus/widgets/chat_box.dart";
|
||||||
import "package:nexus/widgets/member_list.dart";
|
import "package:nexus/widgets/member_list.dart";
|
||||||
import "package:nexus/widgets/room_appbar.dart";
|
import "package:nexus/widgets/room_appbar.dart";
|
||||||
import "package:nexus/widgets/top_widget.dart";
|
import "package:nexus/widgets/top_widget.dart";
|
||||||
|
import "package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart";
|
||||||
|
|
||||||
class RoomChat extends HookConsumerWidget {
|
class RoomChat extends HookConsumerWidget {
|
||||||
final bool isDesktop;
|
final bool isDesktop;
|
||||||
|
|
@ -122,26 +123,24 @@ class RoomChat extends HookConsumerWidget {
|
||||||
required bool isSentByMe,
|
required bool isSentByMe,
|
||||||
MessageGroupStatus? groupStatus,
|
MessageGroupStatus? groupStatus,
|
||||||
}) => FlyerChatTextMessage(
|
}) => FlyerChatTextMessage(
|
||||||
|
customWidget: HtmlWidget(
|
||||||
|
message.metadata?["formatted"],
|
||||||
|
customWidgetBuilder: (element) =>
|
||||||
|
element.localName == "mx-reply"
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: null,
|
||||||
|
onTapUrl: (url) => ref
|
||||||
|
.watch(LaunchHelper.provider)
|
||||||
|
.launchUrl(Uri.parse(url)),
|
||||||
|
),
|
||||||
topWidget: TopWidget(
|
topWidget: TopWidget(
|
||||||
message,
|
message,
|
||||||
headers: room.roomData.client.headers,
|
headers: room.roomData.client.headers,
|
||||||
groupStatus: groupStatus,
|
groupStatus: groupStatus,
|
||||||
),
|
),
|
||||||
message: message.copyWith(
|
message: message,
|
||||||
text: message.text.replaceAllMapped(
|
|
||||||
urlRegex,
|
|
||||||
(match) =>
|
|
||||||
"[${match.group(0)}](${match.group(0)})",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
showTime: true,
|
showTime: true,
|
||||||
index: index,
|
index: index,
|
||||||
onLinkTap: (url, _) => ref
|
|
||||||
.watch(LaunchHelper.provider)
|
|
||||||
.launchUrl(Uri.parse(url)),
|
|
||||||
linksDecoration: TextDecoration.underline,
|
|
||||||
sentLinksColor: Colors.blue,
|
|
||||||
receivedLinksColor: Colors.blue,
|
|
||||||
),
|
),
|
||||||
linkPreviewBuilder: (_, message, isSentByMe) =>
|
linkPreviewBuilder: (_, message, isSentByMe) =>
|
||||||
LinkPreview(
|
LinkPreview(
|
||||||
|
|
|
||||||
25
pubspec.lock
25
pubspec.lock
|
|
@ -590,6 +590,14 @@ packages:
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_widget_from_html_core:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_widget_from_html_core
|
||||||
|
sha256: "1120ee6ed3509ceff2d55aa6c6cbc7b6b1291434422de2411b5a59364dd6ff03"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.17.0"
|
||||||
flyer_chat_file_message:
|
flyer_chat_file_message:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -617,10 +625,11 @@ packages:
|
||||||
flyer_chat_text_message:
|
flyer_chat_text_message:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flyer_chat_text_message
|
path: "packages/flyer_chat_text_message"
|
||||||
sha256: dad7a0c29803233ca55cf8318ed9962c657864dc0a464d8cb76469b9e4da07e7
|
ref: HEAD
|
||||||
url: "https://pub.dev"
|
resolved-ref: dd1b93e6dd4194b3bd934e0d9c27438ba25322cb
|
||||||
source: hosted
|
url: "https://github.com/Henry-Hiles/flutter_chat_ui"
|
||||||
|
source: git
|
||||||
version: "2.5.2"
|
version: "2.5.2"
|
||||||
freezed:
|
freezed:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
|
|
@ -702,14 +711,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.15.6"
|
version: "0.15.6"
|
||||||
html2md:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: html2md
|
|
||||||
sha256: "465cf8ffa1b510fe0e97941579bf5b22e2d575f2cecb500a9c0254efe33a8036"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.2"
|
|
||||||
html_unescape:
|
html_unescape:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,11 @@ dependencies:
|
||||||
flutter_chat_core: ^2.0.0
|
flutter_chat_core: ^2.0.0
|
||||||
flyer_chat_image_message: ^2.2.2
|
flyer_chat_image_message: ^2.2.2
|
||||||
flyer_chat_system_message: ^2.1.13
|
flyer_chat_system_message: ^2.1.13
|
||||||
flyer_chat_text_message: ^2.5.2
|
|
||||||
flyer_chat_file_message: ^2.3.1
|
flyer_chat_file_message: ^2.3.1
|
||||||
|
flyer_chat_text_message:
|
||||||
|
git:
|
||||||
|
url: https://github.com/Henry-Hiles/flutter_chat_ui
|
||||||
|
path: packages/flyer_chat_text_message
|
||||||
flutter_chat_ui:
|
flutter_chat_ui:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Henry-Hiles/flutter_chat_ui
|
url: https://github.com/Henry-Hiles/flutter_chat_ui
|
||||||
|
|
@ -53,8 +56,8 @@ dependencies:
|
||||||
sqflite_common_ffi: ^2.3.6
|
sqflite_common_ffi: ^2.3.6
|
||||||
color_hash: ^1.0.1
|
color_hash: ^1.0.1
|
||||||
scaled_app: ^2.3.0
|
scaled_app: ^2.3.0
|
||||||
html2md: ^1.3.2
|
|
||||||
flutter_vodozemac: ^0.4.1
|
flutter_vodozemac: ^0.4.1
|
||||||
|
flutter_widget_from_html_core: ^0.17.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.4.11
|
build_runner: ^2.4.11
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue