[MessageWidget] Refactor

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