fix(ui): listen for read events in the message widget

This commit is contained in:
Salvatore Giordano
2021-11-24 12:41:25 +01:00
parent 63fb8105d3
commit 44bf613f8d
3 changed files with 70 additions and 35 deletions
@@ -1,3 +1,4 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/user.dart'; import 'package:stream_chat/src/core/models/user.dart';
@@ -5,7 +6,7 @@ part 'read.g.dart';
/// The class that defines a read event /// The class that defines a read event
@JsonSerializable() @JsonSerializable()
class Read { class Read extends Equatable {
/// Constructor used for json serialization /// Constructor used for json serialization
Read({ Read({
required this.lastRead, required this.lastRead,
@@ -39,4 +40,11 @@ class Read {
user: user ?? this.user, user: user ?? this.user,
unreadMessages: unreadMessages ?? this.unreadMessages, unreadMessages: unreadMessages ?? this.unreadMessages,
); );
@override
List<Object?> get props => [
lastRead,
user,
unreadMessages,
];
} }
@@ -126,16 +126,26 @@ class ChannelPreview extends StatelessWidget {
streamChatState.currentUser?.id) { streamChatState.currentUser?.id) {
return Padding( return Padding(
padding: const EdgeInsets.only(right: 4), padding: const EdgeInsets.only(right: 4),
child: SendingIndicator( child: BetterStreamBuilder<List<Read>>(
message: lastMessage!, stream: channel.state?.readStream,
size: channelPreviewTheme.indicatorIconSize, initialData: channel.state?.read,
isMessageRead: channel.state!.read builder: (context, data) {
.where((element) => final readList = data.where((it) =>
element.user.id != it.user.id !=
channel.client.state.currentUser!.id) channel.client.state.currentUser?.id &&
.where((element) => element.lastRead (it.lastRead
.isAfter(lastMessage.createdAt)) .isAfter(lastMessage!.createdAt) ||
.isNotEmpty, it.lastRead.isAtSameMomentAs(
lastMessage.createdAt,
)));
final isMessageRead = readList.length >=
(channel.memberCount ?? 0) - 1;
return SendingIndicator(
message: lastMessage!,
size: channelPreviewTheme.indicatorIconSize,
isMessageRead: isMessageRead,
);
},
), ),
); );
} }
@@ -97,14 +97,20 @@ class MessageWidget extends StatefulWidget {
this.deletedBottomRowBuilder, this.deletedBottomRowBuilder,
this.onReturnAction, this.onReturnAction,
this.customAttachmentBuilders, this.customAttachmentBuilders,
this.readList,
this.padding, this.padding,
this.textPadding = const EdgeInsets.symmetric( this.textPadding = const EdgeInsets.symmetric(
horizontal: 16, horizontal: 16,
vertical: 8, vertical: 8,
), ),
this.attachmentPadding = EdgeInsets.zero, this.attachmentPadding = EdgeInsets.zero,
this.allRead = false, @Deprecated('''
allRead is now deprecated and it will be removed in future releases.
The MessageWidget now listens for read events on its own.
''') this.allRead = false,
@Deprecated('''
readList is now deprecated and it will be removed in future releases.
The MessageWidget now listens for read events on its own.
''') this.readList,
this.onQuotedMessageTap, this.onQuotedMessageTap,
this.customActions = const [], this.customActions = const [],
this.onAttachmentTap, this.onAttachmentTap,
@@ -558,8 +564,6 @@ class _MessageWidgetState extends State<MessageWidget>
bool get showTimeStamp => widget.showTimestamp; bool get showTimeStamp => widget.showTimestamp;
bool get isMessageRead => widget.readList?.isNotEmpty == true;
bool get showInChannel => widget.showInChannelIndicator; bool get showInChannel => widget.showInChannelIndicator;
bool get hasQuotedMessage => widget.message.quotedMessage != null; bool get hasQuotedMessage => widget.message.quotedMessage != null;
@@ -1253,27 +1257,40 @@ class _MessageWidgetState extends State<MessageWidget>
); );
} }
Widget child = SendingIndicator( final channel = StreamChannel.of(context).channel;
message: message,
isMessageRead: isMessageRead, return BetterStreamBuilder<List<Read>>(
size: style!.fontSize, stream: channel.state?.readStream,
initialData: channel.state?.read,
builder: (context, data) {
final readList = data.where((it) =>
it.user.id != _streamChat.currentUser?.id &&
(it.lastRead.isAfter(message.createdAt) ||
it.lastRead.isAtSameMomentAs(message.createdAt)));
final isMessageRead = readList.length >= (channel.memberCount ?? 0) - 1;
Widget child = SendingIndicator(
message: message,
isMessageRead: isMessageRead,
size: style!.fontSize,
);
if (isMessageRead) {
child = Row(
children: [
if (memberCount > 2)
Text(
readList.length.toString(),
style: style.copyWith(
color: _streamChatTheme.colorTheme.accentPrimary,
),
),
const SizedBox(width: 2),
child,
],
);
}
return child;
},
); );
if (isMessageRead) {
child = Row(
children: [
if (memberCount > 2)
Text(
widget.readList!.length.toString(),
style: style.copyWith(
color: _streamChatTheme.colorTheme.accentPrimary,
),
),
const SizedBox(width: 2),
child,
],
);
}
return child;
} }
Widget _buildUserAvatar() => Transform.translate( Widget _buildUserAvatar() => Transform.translate(