[MessageWidget] Refactor
Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
@@ -120,7 +120,7 @@ class ChannelPage extends StatelessWidget {
|
||||
top: !details.isLastUser ? Radius.circular(16) : Radius.zero,
|
||||
bottom: !details.isNextUser ? Radius.circular(16) : Radius.zero,
|
||||
),
|
||||
showSendingIndicator: DisplayWidget.gone,
|
||||
showSendingIndicator: false,
|
||||
reverse: false,
|
||||
showUserAvatar:
|
||||
details.isNextUser ? DisplayWidget.hide : DisplayWidget.show,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -139,7 +138,7 @@ class MessageActionsModal extends StatelessWidget {
|
||||
MessageSendingStatus.SENT ||
|
||||
message.status == null),
|
||||
showInChannelIndicator: false,
|
||||
showSendingIndicator: DisplayWidget.gone,
|
||||
showSendingIndicator: false,
|
||||
shape: messageShape,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -220,6 +220,8 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
|
||||
bool get _upToDate => streamChannel.channel.state.isUpToDate;
|
||||
|
||||
bool get _isThreadConversation => widget.parentMessage != null;
|
||||
|
||||
bool _topPaginationActive = false;
|
||||
bool _bottomPaginationActive = false;
|
||||
|
||||
@@ -234,7 +236,7 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final messagesStream = widget.parentMessage != null
|
||||
final messagesStream = _isThreadConversation
|
||||
? streamChannel.channel.state.threadsStream
|
||||
.where((threads) => threads.containsKey(widget.parentMessage.id))
|
||||
.map((threads) => threads[widget.parentMessage.id])
|
||||
@@ -333,9 +335,8 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
physics: widget.scrollPhysics,
|
||||
itemScrollController: _scrollController,
|
||||
reverse: true,
|
||||
itemCount: messages.length +
|
||||
2 +
|
||||
(widget.parentMessage != null ? 1 : 0),
|
||||
itemCount:
|
||||
messages.length + 2 + (_isThreadConversation ? 1 : 0),
|
||||
separatorBuilder: (context, i) {
|
||||
if (i == messages.length) return Offstage();
|
||||
if (i == messages.length + 2) return Offstage();
|
||||
@@ -497,7 +498,7 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
|
||||
Future<void> _paginateData(
|
||||
StreamChannelState channel, QueryDirection direction) {
|
||||
if (widget.parentMessage == null) {
|
||||
if (!_isThreadConversation) {
|
||||
return channel.queryMessages(direction: direction);
|
||||
} else {
|
||||
return channel.getReplies(widget.parentMessage.id);
|
||||
@@ -722,7 +723,7 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
right: 8.0,
|
||||
bottom: 16.0,
|
||||
),
|
||||
showSendingIndicator: DisplayWidget.hide,
|
||||
showSendingIndicator: false,
|
||||
onThreadTap: _onThreadTap,
|
||||
showEditMessage: false,
|
||||
showDeleteMessage: false,
|
||||
@@ -768,32 +769,60 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
}
|
||||
|
||||
final channel = streamChannel.channel;
|
||||
final readList = channel.state?.read
|
||||
?.where((element) => element.user.id != userId)
|
||||
?.where((read) =>
|
||||
(read.lastRead.isAfter(message.createdAt) ||
|
||||
read.lastRead.isAtSameMomentAs(message.createdAt)) &&
|
||||
(index == 0 ||
|
||||
read.lastRead.isBefore(messages[index - 1].createdAt)))
|
||||
?.toList() ??
|
||||
final readList = channel.state?.read?.where((read) {
|
||||
if (read.user.id == userId) return false;
|
||||
return (read.lastRead.isAfter(message.createdAt) ||
|
||||
read.lastRead.isAtSameMomentAs(message.createdAt)) &&
|
||||
(index == 0 ||
|
||||
read.lastRead.isBefore(messages[index - 1].createdAt));
|
||||
})?.toList() ??
|
||||
[];
|
||||
|
||||
final allRead = readList.length >= (channel.memberCount ?? 0) - 1;
|
||||
|
||||
final isThreadMessage =
|
||||
widget.parentMessage != null || message?.showInChannel == true;
|
||||
|
||||
final hasFileAttachment =
|
||||
message.attachments.any((it) => it.type == 'file');
|
||||
|
||||
final isThreadMessage =
|
||||
message?.parentId != null && message?.showInChannel == true;
|
||||
|
||||
final hasReplies = message.replyCount > 0;
|
||||
|
||||
final attachmentBorderRadius = hasFileAttachment ? 12.0 : 14.0;
|
||||
|
||||
final showTimeStamp = message.createdAt != null &&
|
||||
(!isThreadMessage || _isThreadConversation) &&
|
||||
!hasReplies &&
|
||||
(timeDiff >= 1 || !isNextUserSame);
|
||||
|
||||
final showUsername = !isMyMessage &&
|
||||
(!isThreadMessage || _isThreadConversation) &&
|
||||
!hasReplies &&
|
||||
(timeDiff >= 1 || !isNextUserSame);
|
||||
|
||||
final showUserAvatar = isMyMessage
|
||||
? DisplayWidget.gone
|
||||
: (timeDiff >= 1 || !isNextUserSame)
|
||||
? DisplayWidget.show
|
||||
: DisplayWidget.hide;
|
||||
|
||||
final showSendingIndicator =
|
||||
isMyMessage && (index == 0 || timeDiff >= 1 || !isNextUserSame);
|
||||
|
||||
bool showInChannelIndicator = !_isThreadConversation && isThreadMessage;
|
||||
bool showThreadReplyIndicator = !_isThreadConversation && hasReplies;
|
||||
|
||||
Widget child = MessageWidget(
|
||||
key: ValueKey<String>('MESSAGE-${message.id}'),
|
||||
message: message,
|
||||
reverse: isMyMessage,
|
||||
showReactions: !message.isDeleted,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
showInChannelIndicator: showInChannelIndicator,
|
||||
showThreadReplyIndicator: showThreadReplyIndicator,
|
||||
showUsername: showUsername,
|
||||
showTimestamp: showTimeStamp,
|
||||
showSendingIndicator: showSendingIndicator,
|
||||
showUserAvatar: showUserAvatar,
|
||||
onQuotedMessageTap: (quotedMessageId) async {
|
||||
final scrollToIndex = () {
|
||||
final index = messages.indexWhere((m) => m.id == quotedMessageId);
|
||||
@@ -814,15 +843,6 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
});
|
||||
}
|
||||
},
|
||||
showInChannelIndicator: widget.parentMessage == null,
|
||||
showThreadReplyIndicator: widget.parentMessage == null,
|
||||
showUsername: !isMyMessage && (timeDiff >= 1 || !isNextUserSame),
|
||||
showSendingIndicator:
|
||||
isMyMessage && (index == 0 || timeDiff >= 1 || !isNextUserSame)
|
||||
? DisplayWidget.show
|
||||
: DisplayWidget.hide,
|
||||
showTimestamp:
|
||||
!isNextUserSame || readList?.isNotEmpty == true || timeDiff >= 1,
|
||||
showEditMessage: isMyMessage,
|
||||
showDeleteMessage: isMyMessage,
|
||||
borderSide: isMyMessage ? BorderSide.none : null,
|
||||
@@ -842,11 +862,6 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
topRight: Radius.circular(16),
|
||||
bottomRight: Radius.circular(16),
|
||||
),
|
||||
showUserAvatar: isMyMessage
|
||||
? DisplayWidget.gone
|
||||
: (timeDiff >= 1 || !isNextUserSame
|
||||
? DisplayWidget.show
|
||||
: DisplayWidget.hide),
|
||||
messageTheme: isMyMessage
|
||||
? StreamChatTheme.of(context).ownMessageTheme
|
||||
: StreamChatTheme.of(context).otherMessageTheme,
|
||||
@@ -918,7 +933,7 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
}
|
||||
});
|
||||
|
||||
if (widget.parentMessage != null) {
|
||||
if (_isThreadConversation) {
|
||||
streamChannel.getReplies(widget.parentMessage.id);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ class MessageReactionsModal extends StatelessWidget {
|
||||
showThreadReplyIndicator: false,
|
||||
showTimestamp: false,
|
||||
translateUserAvatar: false,
|
||||
showSendingIndicator: DisplayWidget.gone,
|
||||
showSendingIndicator: false,
|
||||
shape: messageShape,
|
||||
showInChannelIndicator: false,
|
||||
showReactionPickerIndicator: showReactions &&
|
||||
|
||||
+78
-83
@@ -96,7 +96,7 @@ class MessageWidget extends StatefulWidget {
|
||||
final DisplayWidget showUserAvatar;
|
||||
|
||||
/// It controls the display behaviour of the sending indicator
|
||||
final DisplayWidget showSendingIndicator;
|
||||
final bool showSendingIndicator;
|
||||
|
||||
/// If true the widget will show the reactions
|
||||
final bool showReactions;
|
||||
@@ -157,7 +157,7 @@ class MessageWidget extends StatefulWidget {
|
||||
this.onMentionTap,
|
||||
this.showReactionPickerIndicator = false,
|
||||
this.showUserAvatar = DisplayWidget.show,
|
||||
this.showSendingIndicator = DisplayWidget.show,
|
||||
this.showSendingIndicator = true,
|
||||
this.showThreadReplyIndicator = true,
|
||||
this.showInChannelIndicator = true,
|
||||
this.showReplyIndicator = true,
|
||||
@@ -239,18 +239,17 @@ class MessageWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MessageWidgetState extends State<MessageWidget> {
|
||||
bool get showThreadReplyIndicator =>
|
||||
widget.showThreadReplyIndicator && widget.message.replyCount > 0;
|
||||
bool get showThreadReplyIndicator => widget.showThreadReplyIndicator;
|
||||
|
||||
bool get showSendingIndicator => widget.showSendingIndicator;
|
||||
|
||||
bool get showUsername => widget.showUsername;
|
||||
|
||||
bool get showTimeStamp =>
|
||||
widget.message.createdAt != null && widget.showTimestamp;
|
||||
bool get showTimeStamp => widget.showTimestamp;
|
||||
|
||||
bool get isMessageRead => widget.readList?.isNotEmpty == true;
|
||||
|
||||
bool get showInChannel =>
|
||||
widget.showInChannelIndicator && widget.message?.showInChannel == true;
|
||||
bool get showInChannel => widget.showInChannelIndicator;
|
||||
|
||||
bool get hasQuotedMessage => widget.message?.quotedMessage != null;
|
||||
|
||||
@@ -494,88 +493,84 @@ class _MessageWidgetState extends State<MessageWidget> {
|
||||
}
|
||||
|
||||
Widget _buildBottomRow(double leftPadding) {
|
||||
final deleted = widget.message.isDeleted;
|
||||
var children = <Widget>[];
|
||||
if (deleted) {
|
||||
children.add(
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
StreamSvgIcon.eye(
|
||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||
size: 16.0,
|
||||
),
|
||||
SizedBox(width: 8.0),
|
||||
Text(
|
||||
'Only visible to you',
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.footnote
|
||||
.copyWith(color: StreamChatTheme.of(context).colorTheme.grey),
|
||||
),
|
||||
],
|
||||
if (widget.message.isDeleted) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(left: leftPadding),
|
||||
child: Transform(
|
||||
transform: Matrix4.rotationY(widget.reverse ? pi : 0),
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
StreamSvgIcon.eye(
|
||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||
size: 16.0,
|
||||
),
|
||||
SizedBox(width: 8.0),
|
||||
Text(
|
||||
'Only visible to you',
|
||||
style: StreamChatTheme.of(context).textTheme.footnote.copyWith(
|
||||
color: StreamChatTheme.of(context).colorTheme.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (showInChannel) {
|
||||
final onThreadTap = () async {
|
||||
try {
|
||||
}
|
||||
|
||||
var children = <Widget>[];
|
||||
|
||||
final threadParticipants = widget.message.threadParticipants;
|
||||
final showThreadParticipants = threadParticipants?.isNotEmpty == true;
|
||||
final replyCount = widget.message.replyCount;
|
||||
|
||||
var msg = 'Thread Reply';
|
||||
if (showThreadReplyIndicator && replyCount > 1) {
|
||||
msg = '$replyCount Thread Replies';
|
||||
}
|
||||
|
||||
final onThreadTap = () async {
|
||||
try {
|
||||
var message = widget.message;
|
||||
if (showInChannel) {
|
||||
final channel = StreamChannel.of(context);
|
||||
final message = await channel.getMessage(widget.message.parentId);
|
||||
return widget.onThreadTap(message);
|
||||
} catch (e, stk) {
|
||||
print(e);
|
||||
print(stk);
|
||||
return null;
|
||||
message = await channel.getMessage(widget.message.parentId);
|
||||
}
|
||||
};
|
||||
children.add(
|
||||
return widget.onThreadTap(message);
|
||||
} catch (e, stk) {
|
||||
print(e);
|
||||
print(stk);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
children.addAll([
|
||||
if (showSendingIndicator) _buildSendingIndicator(),
|
||||
if (showInChannel || showThreadReplyIndicator) ...[
|
||||
if (showThreadParticipants)
|
||||
SizedBox.fromSize(
|
||||
size: Size((threadParticipants.length * 8.0) + 10, 16),
|
||||
child: _buildThreadParticipantsIndicator(),
|
||||
),
|
||||
InkWell(
|
||||
onTap: widget.onThreadTap != null ? onThreadTap : null,
|
||||
child: Text('Thread Reply', style: widget.messageTheme?.replies),
|
||||
child: Text(msg, style: widget.messageTheme?.replies),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final showSendingIndicator =
|
||||
widget.showSendingIndicator == DisplayWidget.show;
|
||||
final threadParticipants = widget.message.threadParticipants;
|
||||
final showThreadParticipants = threadParticipants?.isNotEmpty == true;
|
||||
final replyCount = widget.message.replyCount;
|
||||
final msg = replyCount != 0
|
||||
? '$replyCount ${replyCount > 1 ? 'Thread Replies' : 'Thread Reply'}'
|
||||
: 'Thread Reply';
|
||||
],
|
||||
if (showUsername)
|
||||
Text(
|
||||
widget.message.user.name,
|
||||
style: widget.messageTheme.replies.copyWith(
|
||||
color: widget.messageTheme.createdAt.color,
|
||||
),
|
||||
),
|
||||
if (showTimeStamp)
|
||||
Text(
|
||||
Jiffy(widget.message.createdAt.toLocal()).jm,
|
||||
style: widget.messageTheme.createdAt,
|
||||
),
|
||||
]);
|
||||
|
||||
final onThreadTap = () async {
|
||||
var message = widget.message;
|
||||
return widget.onThreadTap(message);
|
||||
};
|
||||
|
||||
children.addAll([
|
||||
if (showSendingIndicator) _buildSendingIndicator(),
|
||||
if (showThreadReplyIndicator) ...[
|
||||
if (showThreadParticipants)
|
||||
SizedBox.fromSize(
|
||||
size: Size((threadParticipants.length * 8.0) + 10, 16),
|
||||
child: _buildThreadParticipantsIndicator(),
|
||||
),
|
||||
InkWell(
|
||||
onTap: widget.onThreadTap != null ? onThreadTap : null,
|
||||
child: Text(msg, style: widget.messageTheme?.replies),
|
||||
),
|
||||
],
|
||||
if (showUsername)
|
||||
Text(
|
||||
widget.message.user.name,
|
||||
style: widget.messageTheme.replies.copyWith(
|
||||
color: widget.messageTheme.createdAt.color,
|
||||
),
|
||||
),
|
||||
if (showTimeStamp)
|
||||
Text(
|
||||
Jiffy(widget.message.createdAt.toLocal()).jm,
|
||||
style: widget.messageTheme.createdAt,
|
||||
),
|
||||
]);
|
||||
}
|
||||
if (widget.reverse) children = children.reversed.toList();
|
||||
|
||||
return Padding(
|
||||
@@ -585,7 +580,7 @@ class _MessageWidgetState extends State<MessageWidget> {
|
||||
clipBehavior: Clip.none,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (!deleted && (showThreadReplyIndicator || showInChannel))
|
||||
if (showThreadReplyIndicator || showInChannel)
|
||||
Container(
|
||||
margin: EdgeInsets.only(
|
||||
bottom: widget.messageTheme.replies.fontSize / 2,
|
||||
|
||||
Reference in New Issue
Block a user