diff --git a/lib/helpers/extension_helper.dart b/lib/helpers/extension_helper.dart index 970e81f..95338ec 100644 --- a/lib/helpers/extension_helper.dart +++ b/lib/helpers/extension_helper.dart @@ -1,12 +1,10 @@ import "package:flutter/material.dart"; -import "package:flutter/widgets.dart"; import "package:flutter_chat_core/flutter_chat_core.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:matrix/matrix.dart"; import "package:nexus/models/full_room.dart"; import "package:nexus/widgets/error_dialog.dart"; import "package:nexus/widgets/loading.dart"; -import "package:html2md/html2md.dart"; extension BetterWhen on AsyncValue { Widget betterWhen({ @@ -39,6 +37,7 @@ extension ToMessage on Event { ? relationshipEventId : null; final metadata = { + "formatted": formattedText.isEmpty ? body : formattedText, "eventType": type, "displayName": senderFromMemoryOrFallback.displayName, "txnId": transactionId, @@ -49,34 +48,34 @@ extension ToMessage on Event { metadata: metadata, id: eventId, authorId: senderId, - text: "~~This message has been redacted.~~", + text: "This message has been redacted.", deletedAt: redactedBecause?.originServerTs, ); } - final formatted = convert( - formattedText.isEmpty ? body : formattedText, - ignore: replyId == null ? null : ["mx-reply"], - ); - - final asText = Message.text( - metadata: metadata, - id: eventId, - authorId: senderId, - text: formatted, - replyToMessageId: replyId, - deliveredAt: originServerTs, - ); + final asText = + Message.text( + metadata: metadata, + id: eventId, + authorId: senderId, + text: body, + replyToMessageId: replyId, + deliveredAt: originServerTs, + ) + as TextMessage; if (mustBeText) return asText; return switch (type) { + EventTypes.Encrypted => asText.copyWith( + text: "Unable to decrypt message.", + ), EventTypes.Message => switch (messageType) { MessageTypes.Image => Message.image( metadata: metadata, id: eventId, authorId: senderId, - text: formatted, + text: text, source: (await getAttachmentUri()).toString(), replyToMessageId: replyId, deliveredAt: originServerTs, @@ -85,7 +84,7 @@ extension ToMessage on Event { metadata: metadata, id: eventId, authorId: senderId, - text: formatted, + text: text, replyToMessageId: replyId, source: (await getAttachmentUri()).toString(), deliveredAt: originServerTs, diff --git a/lib/helpers/launch_helper.dart b/lib/helpers/launch_helper.dart index 215433a..f872ef7 100644 --- a/lib/helpers/launch_helper.dart +++ b/lib/helpers/launch_helper.dart @@ -6,16 +6,16 @@ class LaunchHelper { final Ref ref; LaunchHelper(this.ref); - Future launchUrl(Uri url, {bool useWebview = false}) async { + Future launchUrl(Uri url, {bool useWebview = false}) async { try { - await ul.launchUrl( + return await ul.launchUrl( url, mode: useWebview ? ul.LaunchMode.inAppBrowserView : ul.LaunchMode.externalApplication, ); } on PlatformException catch (_) { - // Ignore missing intent handler error + return false; } } diff --git a/lib/widgets/room_appbar.dart b/lib/widgets/room_appbar.dart index cfc3bf5..289757b 100644 --- a/lib/widgets/room_appbar.dart +++ b/lib/widgets/room_appbar.dart @@ -38,14 +38,15 @@ class RoomAppbar extends StatelessWidget implements PreferredSizeWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(room.title, overflow: TextOverflow.ellipsis), - Text( - room.roomData.topic, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.labelMedium?.copyWith( - color: Theme.of(context).colorScheme.onSurfaceVariant, + if (room.roomData.topic.isNotEmpty) + Text( + room.roomData.topic, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.labelMedium?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), - ), ], ), actions: [ diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index 4744a0b..3ad104c 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -17,6 +17,7 @@ import "package:nexus/widgets/chat_box.dart"; import "package:nexus/widgets/member_list.dart"; import "package:nexus/widgets/room_appbar.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 { final bool isDesktop; @@ -122,26 +123,24 @@ class RoomChat extends HookConsumerWidget { required bool isSentByMe, MessageGroupStatus? groupStatus, }) => 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( message, headers: room.roomData.client.headers, groupStatus: groupStatus, ), - message: message.copyWith( - text: message.text.replaceAllMapped( - urlRegex, - (match) => - "[${match.group(0)}](${match.group(0)})", - ), - ), + message: message, showTime: true, index: index, - onLinkTap: (url, _) => ref - .watch(LaunchHelper.provider) - .launchUrl(Uri.parse(url)), - linksDecoration: TextDecoration.underline, - sentLinksColor: Colors.blue, - receivedLinksColor: Colors.blue, ), linkPreviewBuilder: (_, message, isSentByMe) => LinkPreview( diff --git a/pubspec.lock b/pubspec.lock index 33f5d4a..2b6d548 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -590,6 +590,14 @@ packages: description: flutter source: sdk 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: dependency: "direct main" description: @@ -617,10 +625,11 @@ packages: flyer_chat_text_message: dependency: "direct main" description: - name: flyer_chat_text_message - sha256: dad7a0c29803233ca55cf8318ed9962c657864dc0a464d8cb76469b9e4da07e7 - url: "https://pub.dev" - source: hosted + path: "packages/flyer_chat_text_message" + ref: HEAD + resolved-ref: dd1b93e6dd4194b3bd934e0d9c27438ba25322cb + url: "https://github.com/Henry-Hiles/flutter_chat_ui" + source: git version: "2.5.2" freezed: dependency: "direct dev" @@ -702,14 +711,6 @@ packages: url: "https://pub.dev" source: hosted 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: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 005da31..703708c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,8 +42,11 @@ dependencies: flutter_chat_core: ^2.0.0 flyer_chat_image_message: ^2.2.2 flyer_chat_system_message: ^2.1.13 - flyer_chat_text_message: ^2.5.2 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: git: url: https://github.com/Henry-Hiles/flutter_chat_ui @@ -53,8 +56,8 @@ dependencies: sqflite_common_ffi: ^2.3.6 color_hash: ^1.0.1 scaled_app: ^2.3.0 - html2md: ^1.3.2 flutter_vodozemac: ^0.4.1 + flutter_widget_from_html_core: ^0.17.0 dev_dependencies: build_runner: ^2.4.11