diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index 54930c6..697e3f7 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -31,4 +31,18 @@
android:name="flutterEmbedding"
android:value="2" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/assets/messages.json b/example/assets/messages.json
index 3f35b36..5eb574a 100644
--- a/example/assets/messages.json
+++ b/example/assets/messages.json
@@ -1,4 +1,16 @@
[
+ {
+ "author": {
+ "firstName": "John",
+ "id": "b4878b96-efbc-479a-8291-474ef323dec7",
+ "imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4"
+ },
+ "createdAt": 1598438797000,
+ "id": "e7a673e9-86eb-4572-936f-2882b0183cdc",
+ "status": "seen",
+ "text": "**bold** _italic_ ~strikethrough~ `code`\nhttps://link-test.com test@email.com",
+ "type": "text"
+ },
{
"author": {
"firstName": "John",
diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist
index 713fcc1..2e377b3 100644
--- a/example/ios/Runner/Info.plist
+++ b/example/ios/Runner/Info.plist
@@ -22,6 +22,11 @@
????
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
+ LSApplicationQueriesSchemes
+
+ https
+ http
+
LSRequiresIPhoneOS
NSCameraUsageDescription
diff --git a/lib/src/chat_theme.dart b/lib/src/chat_theme.dart
index 083e270..68062f6 100644
--- a/lib/src/chat_theme.dart
+++ b/lib/src/chat_theme.dart
@@ -74,6 +74,8 @@ abstract class ChatTheme {
required this.receivedEmojiMessageTextStyle,
this.receivedMessageBodyLinkTextStyle,
required this.receivedMessageBodyTextStyle,
+ this.receivedMessageBodyBoldTextStyle,
+ this.receivedMessageBodyCodeTextStyle,
required this.receivedMessageCaptionTextStyle,
required this.receivedMessageDocumentIconColor,
required this.receivedMessageLinkDescriptionTextStyle,
@@ -86,6 +88,8 @@ abstract class ChatTheme {
required this.sentEmojiMessageTextStyle,
this.sentMessageBodyLinkTextStyle,
required this.sentMessageBodyTextStyle,
+ this.sentMessageBodyBoldTextStyle,
+ this.sentMessageBodyCodeTextStyle,
required this.sentMessageCaptionTextStyle,
required this.sentMessageDocumentIconColor,
required this.sentMessageLinkDescriptionTextStyle,
@@ -175,6 +179,14 @@ abstract class ChatTheme {
/// of received messages
final TextStyle receivedMessageBodyTextStyle;
+ /// Body text style used for displaying bold text on received text messages.
+ /// Default to a bold version of [receivedMessageBodyTextStyle].
+ final TextStyle? receivedMessageBodyBoldTextStyle;
+
+ /// Body text style used for displaying code text on received text messages.
+ /// Defaults to a mono version of [receivedMessageBodyTextStyle].
+ final TextStyle? receivedMessageBodyCodeTextStyle;
+
/// Caption text style used for displaying secondary info (e.g. file size)
/// on different types of received messages
final TextStyle receivedMessageCaptionTextStyle;
@@ -215,6 +227,14 @@ abstract class ChatTheme {
/// of sent messages
final TextStyle sentMessageBodyTextStyle;
+ /// Body text style used for displaying bold text on sent text messages.
+ /// Defaults to a bold version of [sentMessageBodyTextStyle].
+ final TextStyle? sentMessageBodyBoldTextStyle;
+
+ /// Body text style used for displaying code text on sent text messages.
+ /// Defaults to a mono version of [sentMessageBodyTextStyle].
+ final TextStyle? sentMessageBodyCodeTextStyle;
+
/// Caption text style used for displaying secondary info (e.g. file size)
/// on different types of sent messages
final TextStyle sentMessageCaptionTextStyle;
diff --git a/lib/src/widgets/text_message.dart b/lib/src/widgets/text_message.dart
index 9e4bcbe..75a32db 100644
--- a/lib/src/widgets/text_message.dart
+++ b/lib/src/widgets/text_message.dart
@@ -1,7 +1,12 @@
+import 'dart:io';
+
import 'package:flutter/material.dart';
import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
import 'package:flutter_link_previewer/flutter_link_previewer.dart'
- show LinkPreview, regexLink;
+ show LinkPreview, regexEmail, regexLink;
+import 'package:flutter_parsed_text/flutter_parsed_text.dart';
+import 'package:url_launcher/url_launcher.dart';
+
import '../models/emoji_enlargement_behavior.dart';
import '../util.dart';
import 'inherited_chat_theme.dart';
@@ -50,12 +55,6 @@ class TextMessage extends StatelessWidget {
double width,
BuildContext context,
) {
- final bodyLinkTextStyle = user.id == message.author.id
- ? InheritedChatTheme.of(context).theme.sentMessageBodyLinkTextStyle
- : InheritedChatTheme.of(context).theme.receivedMessageBodyLinkTextStyle;
- final bodyTextStyle = user.id == message.author.id
- ? InheritedChatTheme.of(context).theme.sentMessageBodyTextStyle
- : InheritedChatTheme.of(context).theme.receivedMessageBodyTextStyle;
final linkDescriptionTextStyle = user.id == message.author.id
? InheritedChatTheme.of(context)
.theme
@@ -69,18 +68,9 @@ class TextMessage extends StatelessWidget {
.theme
.receivedMessageLinkTitleTextStyle;
- final color = getUserAvatarNameColor(message.author,
- InheritedChatTheme.of(context).theme.userAvatarNameColors);
- final name = getUserName(message.author);
-
return LinkPreview(
enableAnimation: true,
- header: showName ? name : null,
- headerStyle: InheritedChatTheme.of(context)
- .theme
- .userNameTextStyle
- .copyWith(color: color),
- linkStyle: bodyLinkTextStyle ?? bodyTextStyle,
+ textWidget: _textWidgetBuilder(user, context, false),
metadataTextStyle: linkDescriptionTextStyle,
metadataTitleStyle: linkTitleTextStyle,
onPreviewDataFetched: _onPreviewDataFetched,
@@ -91,7 +81,6 @@ class TextMessage extends StatelessWidget {
),
previewData: message.previewData,
text: message.text,
- textStyle: bodyTextStyle,
width: width,
);
}
@@ -105,6 +94,22 @@ class TextMessage extends StatelessWidget {
final color =
getUserAvatarNameColor(message.author, theme.userAvatarNameColors);
final name = getUserName(message.author);
+ final bodyTextStyle = user.id == message.author.id
+ ? enlargeEmojis
+ ? theme.sentEmojiMessageTextStyle
+ : theme.sentMessageBodyTextStyle
+ : enlargeEmojis
+ ? theme.receivedEmojiMessageTextStyle
+ : theme.receivedMessageBodyTextStyle;
+ final boldTextStyle = user.id == message.author.id
+ ? theme.sentMessageBodyBoldTextStyle
+ : theme.receivedMessageBodyBoldTextStyle;
+ final codeTextStyle = user.id == message.author.id
+ ? theme.sentMessageBodyCodeTextStyle
+ : theme.receivedMessageBodyCodeTextStyle;
+ final bodyLinkTextStyle = user.id == message.author.id
+ ? InheritedChatTheme.of(context).theme.sentMessageBodyLinkTextStyle
+ : InheritedChatTheme.of(context).theme.receivedMessageBodyLinkTextStyle;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -119,16 +124,72 @@ class TextMessage extends StatelessWidget {
style: theme.userNameTextStyle.copyWith(color: color),
),
),
- SelectableText(
- message.text,
- style: user.id == message.author.id
- ? enlargeEmojis
- ? theme.sentEmojiMessageTextStyle
- : theme.sentMessageBodyTextStyle
- : enlargeEmojis
- ? theme.receivedEmojiMessageTextStyle
- : theme.receivedMessageBodyTextStyle,
- textWidthBasis: TextWidthBasis.longestLine,
+ ParsedText(
+ text: message.text,
+ selectable: true,
+ style: bodyTextStyle,
+ regexOptions: const RegexOptions(multiLine: true, dotAll: true),
+ parse: [
+ MatchText(
+ pattern: regexEmail,
+ onTap: (mail) async {
+ final url = 'mailto:$mail';
+ if (await canLaunch(url)) {
+ await launch(url);
+ }
+ },
+ style: bodyLinkTextStyle ??
+ bodyTextStyle.copyWith(decoration: TextDecoration.underline),
+ ),
+ MatchText(
+ pattern: regexLink,
+ onTap: (url) async {
+ if (await canLaunch(url)) {
+ await launch(url);
+ }
+ },
+ style: bodyLinkTextStyle ??
+ bodyTextStyle.copyWith(decoration: TextDecoration.underline),
+ ),
+ MatchText(
+ pattern: '(\\*\\*|\\*)(.*?)(\\*\\*|\\*)',
+ onTap: (_) {},
+ style: boldTextStyle ??
+ bodyTextStyle.copyWith(fontWeight: FontWeight.bold),
+ renderText: ({required String str, required String pattern}) {
+ return {'display': str.replaceAll(RegExp('(\\*\\*|\\*)'), '')};
+ },
+ ),
+ MatchText(
+ pattern: '_(.*?)_',
+ onTap: (_) {},
+ style: bodyTextStyle.copyWith(fontStyle: FontStyle.italic),
+ renderText: ({required String str, required String pattern}) {
+ return {'display': str.replaceAll('_', '')};
+ },
+ ),
+ MatchText(
+ pattern: '~(.*?)~',
+ onTap: (_) {},
+ style: bodyTextStyle.copyWith(
+ decoration: TextDecoration.lineThrough,
+ ),
+ renderText: ({required String str, required String pattern}) {
+ return {'display': str.replaceAll('~', '')};
+ },
+ ),
+ MatchText(
+ pattern: '`(.*?)`',
+ onTap: (_) {},
+ style: codeTextStyle ??
+ bodyTextStyle.copyWith(
+ fontFamily: Platform.isIOS ? 'Courier' : 'monospace',
+ ),
+ renderText: ({required String str, required String pattern}) {
+ return {'display': str.replaceAll('`', '')};
+ },
+ ),
+ ],
),
],
);
diff --git a/pubspec.yaml b/pubspec.yaml
index 231112e..f2fd568 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -17,9 +17,11 @@ dependencies:
equatable: ^2.0.3
flutter_chat_types: ^3.3.2
flutter_link_previewer: ^2.6.4
+ flutter_parsed_text: ^2.2.1
intl: ^0.17.0
meta: ^1.7.0
photo_view: ^0.13.0
+ url_launcher: ^6.0.20
visibility_detector: ^0.2.2
dev_dependencies: