Merge remote-tracking branch 'origin/refactor/deprecate-v3' into refactor/deprecate-v3
This commit is contained in:
@@ -591,7 +591,7 @@ class _ChannelListViewState extends State<ChannelListView> {
|
||||
decoration: BoxDecoration(
|
||||
color: chatThemeData.channelListViewTheme.backgroundColor,
|
||||
),
|
||||
child: StreamChannelPreview(
|
||||
child: ChannelPreview(
|
||||
onLongPress: widget.onChannelLongPress,
|
||||
channel: channel,
|
||||
onImageTap: widget.onImageTap != null
|
||||
|
||||
@@ -4,10 +4,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat_flutter/src/extension.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
/// {@macro channel_preview}
|
||||
@Deprecated("Use 'StreamChannelPreview' instead")
|
||||
typedef ChannelPreview = StreamChannelPreview;
|
||||
|
||||
/// {@template channel_preview}
|
||||
/// 
|
||||
/// 
|
||||
@@ -24,9 +20,10 @@ typedef ChannelPreview = StreamChannelPreview;
|
||||
/// [StreamChatTheme].
|
||||
/// Modify it to change the widget appearance.
|
||||
/// {@endtemplate}
|
||||
class StreamChannelPreview extends StatelessWidget {
|
||||
/// Constructor for creating [StreamChannelPreview]
|
||||
const StreamChannelPreview({
|
||||
@Deprecated("Use 'StreamChannelListTile' instead")
|
||||
class ChannelPreview extends StatelessWidget {
|
||||
/// Constructor for creating [ChannelPreview]
|
||||
const ChannelPreview({
|
||||
required this.channel,
|
||||
Key? key,
|
||||
this.onTap,
|
||||
@@ -71,7 +68,7 @@ class StreamChannelPreview extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
|
||||
final channelPreviewTheme = ChannelPreviewTheme.of(context);
|
||||
final streamChatState = StreamChat.of(context);
|
||||
return BetterStreamBuilder<bool>(
|
||||
stream: channel.isMutedStream,
|
||||
@@ -194,13 +191,13 @@ class StreamChannelPreview extends StatelessWidget {
|
||||
|
||||
return Text(
|
||||
stringDate,
|
||||
style: StreamChannelPreviewTheme.of(context).lastMessageAtStyle,
|
||||
style: ChannelPreviewTheme.of(context).lastMessageAtStyle,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Widget _buildSubtitle(BuildContext context) {
|
||||
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
|
||||
final channelPreviewTheme = ChannelPreviewTheme.of(context);
|
||||
if (channel.isMuted) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
@@ -253,7 +250,7 @@ class StreamChannelPreview extends StatelessWidget {
|
||||
|
||||
text = parts.join(' ');
|
||||
|
||||
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
|
||||
final channelPreviewTheme = ChannelPreviewTheme.of(context);
|
||||
return Text.rich(
|
||||
_getDisplayText(
|
||||
text,
|
||||
|
||||
@@ -225,3 +225,50 @@ extension UserListX on List<User> {
|
||||
return entries.map((e) => e.key).toList(growable: false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Extensions on Message
|
||||
extension MessageX on Message {
|
||||
/// It replaces the user mentions with the actual user names.
|
||||
Message replaceMentions({bool linkify = true}) {
|
||||
var messageTextToRender = text;
|
||||
for (final user in mentionedUsers.toSet()) {
|
||||
final userId = user.id;
|
||||
final userName = user.name;
|
||||
if (linkify) {
|
||||
messageTextToRender = messageTextToRender?.replaceAll(
|
||||
'@$userId',
|
||||
'[@$userName](@${userName.replaceAll(' ', '')})',
|
||||
);
|
||||
} else {
|
||||
messageTextToRender = messageTextToRender?.replaceAll(
|
||||
'@$userId',
|
||||
'@$userName',
|
||||
);
|
||||
}
|
||||
}
|
||||
return copyWith(text: messageTextToRender);
|
||||
}
|
||||
|
||||
/// It returns the message with the translated text if available locally
|
||||
Message translate(String language) =>
|
||||
copyWith(text: i18n?['${language}_text'] ?? text);
|
||||
|
||||
/// It returns the message replacing the mentioned user names with
|
||||
/// the respective user ids
|
||||
Message replaceMentionsWithId() {
|
||||
if (mentionedUsers.isEmpty) return this;
|
||||
|
||||
var messageTextToSend = text;
|
||||
if (messageTextToSend == null) return this;
|
||||
|
||||
for (final user in mentionedUsers.toSet()) {
|
||||
final userName = user.name;
|
||||
messageTextToSend = messageTextToSend!.replaceAll(
|
||||
'@$userName',
|
||||
'@${user.id}',
|
||||
);
|
||||
}
|
||||
|
||||
return copyWith(text: messageTextToSend);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1171,10 +1171,10 @@ class StreamMessageInputState extends State<StreamMessageInput>
|
||||
splits[splits.length - 1] = user.name;
|
||||
final rejoin = splits.join('@');
|
||||
|
||||
_effectiveController.text = rejoin +
|
||||
_effectiveController.text.substring(
|
||||
_effectiveController.selectionStart,
|
||||
);
|
||||
_effectiveController.text =
|
||||
'$rejoin${_effectiveController.text.substring(
|
||||
_effectiveController.selectionStart,
|
||||
)}';
|
||||
|
||||
_onChangedDebounced.cancel();
|
||||
setState(() => _showMentionsOverlay = false);
|
||||
@@ -1679,6 +1679,8 @@ class StreamMessageInputState extends State<StreamMessageInput>
|
||||
await streamChannel.reloadChannel();
|
||||
}
|
||||
|
||||
message = message.replaceMentionsWithId();
|
||||
|
||||
try {
|
||||
Future sendingFuture;
|
||||
if (_isEditing) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:collection/collection.dart' show IterableExtension;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:stream_chat_flutter/src/extension.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
/// {@macro message_text}
|
||||
@@ -40,13 +41,14 @@ class StreamMessageText extends StatelessWidget {
|
||||
stream: streamChat.currentUserStream.map((it) => it!.language ?? 'en'),
|
||||
initialData: streamChat.currentUser!.language ?? 'en',
|
||||
builder: (context, language) {
|
||||
final translatedText =
|
||||
message.i18n?['${language}_text'] ?? message.text;
|
||||
final messageText =
|
||||
_replaceMentions(translatedText ?? '').replaceAll('\n', '\n\n');
|
||||
final messageText = message
|
||||
.translate(language)
|
||||
.replaceMentions()
|
||||
.text
|
||||
?.replaceAll('\n', '\n\n');
|
||||
final themeData = Theme.of(context);
|
||||
return MarkdownBody(
|
||||
data: messageText,
|
||||
data: messageText ?? '',
|
||||
onTapLink: (
|
||||
String link,
|
||||
String? href,
|
||||
@@ -86,17 +88,4 @@ class StreamMessageText extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
String _replaceMentions(String text) {
|
||||
var messageTextToRender = text;
|
||||
for (final user in message.mentionedUsers.toSet()) {
|
||||
final userId = user.id;
|
||||
final userName = user.name;
|
||||
messageTextToRender = messageTextToRender.replaceAll(
|
||||
'@$userId',
|
||||
'[@$userName](@${userName.replaceAll(' ', '')})',
|
||||
);
|
||||
}
|
||||
return messageTextToRender;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -9,6 +9,7 @@ import 'package:stream_chat_flutter/src/typing_indicator.dart';
|
||||
import 'package:stream_chat_flutter/src/unread_indicator.dart';
|
||||
import 'package:stream_chat_flutter/src/v4/stream_channel_avatar.dart';
|
||||
import 'package:stream_chat_flutter/src/v4/stream_channel_name.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||
|
||||
/// A widget that displays a channel preview.
|
||||
@@ -359,7 +360,10 @@ class ChannelLastMessageText extends StatelessWidget {
|
||||
|
||||
if (lastMessage == null) return const Offstage();
|
||||
|
||||
final lastMessageText = lastMessage.text;
|
||||
final lastMessageText = lastMessage
|
||||
.translate(channel.client.state.currentUser?.language ?? 'en')
|
||||
.replaceMentions(linkify: false)
|
||||
.text;
|
||||
final lastMessageAttachments = lastMessage.attachments;
|
||||
final lastMessageMentionedUsers = lastMessage.mentionedUsers;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user