add read indicators
This commit is contained in:
@@ -425,6 +425,16 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
final isNextUser =
|
final isNextUser =
|
||||||
index - 1 >= 0 && message.user.id == messages[index - 1]?.user?.id;
|
index - 1 >= 0 && message.user.id == messages[index - 1]?.user?.id;
|
||||||
|
|
||||||
|
final readList = StreamChannel.of(context)
|
||||||
|
.channel
|
||||||
|
.state
|
||||||
|
.read
|
||||||
|
.where((read) =>
|
||||||
|
read.lastRead.isAfter(message.createdAt) &&
|
||||||
|
(index == 0 ||
|
||||||
|
read.lastRead.isBefore(messages[index - 1].createdAt)))
|
||||||
|
.toList();
|
||||||
|
|
||||||
return MessageWidget(
|
return MessageWidget(
|
||||||
message: message,
|
message: message,
|
||||||
reverse: isMyMessage,
|
reverse: isMyMessage,
|
||||||
@@ -439,7 +449,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
(index == 0 || message.status != MessageSendingStatus.SENT)
|
(index == 0 || message.status != MessageSendingStatus.SENT)
|
||||||
? DisplayWidget.show
|
? DisplayWidget.show
|
||||||
: DisplayWidget.hide,
|
: DisplayWidget.hide,
|
||||||
showTimestamp: !isNextUser,
|
showTimestamp: !isNextUser || readList.isNotEmpty,
|
||||||
showEditMessage: isMyMessage,
|
showEditMessage: isMyMessage,
|
||||||
showDeleteMessage: isMyMessage,
|
showDeleteMessage: isMyMessage,
|
||||||
borderSide: isMyMessage ? BorderSide.none : null,
|
borderSide: isMyMessage ? BorderSide.none : null,
|
||||||
@@ -455,6 +465,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
messageTheme: isMyMessage
|
messageTheme: isMyMessage
|
||||||
? StreamChatTheme.of(context).ownMessageTheme
|
? StreamChatTheme.of(context).ownMessageTheme
|
||||||
: StreamChatTheme.of(context).otherMessageTheme,
|
: StreamChatTheme.of(context).otherMessageTheme,
|
||||||
|
readList: readList,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+69
-22
@@ -97,6 +97,8 @@ class MessageWidget extends StatefulWidget {
|
|||||||
/// The function called when tapping on UserAvatar
|
/// The function called when tapping on UserAvatar
|
||||||
final void Function(User) onUserAvatarTap;
|
final void Function(User) onUserAvatarTap;
|
||||||
|
|
||||||
|
final List<Read> readList;
|
||||||
|
|
||||||
/// If true show the users username next to the timestamp of the message
|
/// If true show the users username next to the timestamp of the message
|
||||||
final bool showUsername;
|
final bool showUsername;
|
||||||
final bool showTimestamp;
|
final bool showTimestamp;
|
||||||
@@ -130,6 +132,7 @@ class MessageWidget extends StatefulWidget {
|
|||||||
this.editMessageInputBuilder,
|
this.editMessageInputBuilder,
|
||||||
this.textBuilder,
|
this.textBuilder,
|
||||||
Map<String, AttachmentBuilder> customAttachmentBuilders,
|
Map<String, AttachmentBuilder> customAttachmentBuilders,
|
||||||
|
this.readList,
|
||||||
this.padding,
|
this.padding,
|
||||||
this.textPadding = const EdgeInsets.all(8.0),
|
this.textPadding = const EdgeInsets.all(8.0),
|
||||||
this.attachmentPadding = EdgeInsets.zero,
|
this.attachmentPadding = EdgeInsets.zero,
|
||||||
@@ -298,8 +301,9 @@ class _MessageWidgetState extends State<MessageWidget> {
|
|||||||
),
|
),
|
||||||
if ((widget.message.createdAt != null &&
|
if ((widget.message.createdAt != null &&
|
||||||
widget.showTimestamp) ||
|
widget.showTimestamp) ||
|
||||||
widget.showUsername)
|
widget.showUsername ||
|
||||||
_buildUsernameAndTimestamp(leftPadding),
|
widget.readList?.isNotEmpty == true)
|
||||||
|
_buildBottomRow(leftPadding),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -360,36 +364,79 @@ class _MessageWidgetState extends State<MessageWidget> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Padding _buildUsernameAndTimestamp(double leftPadding) {
|
Padding _buildBottomRow(double leftPadding) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: leftPadding,
|
left: leftPadding,
|
||||||
top: 2,
|
top: 2,
|
||||||
),
|
),
|
||||||
child: Transform(
|
child: Row(
|
||||||
alignment: Alignment.center,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
transform: Matrix4.rotationY(widget.reverse ? pi : 0),
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: RichText(
|
children: <Widget>[
|
||||||
text: TextSpan(
|
Transform(
|
||||||
style: widget.messageTheme.createdAt,
|
alignment: Alignment.center,
|
||||||
children: <TextSpan>[
|
transform: Matrix4.rotationY(widget.reverse ? pi : 0),
|
||||||
if (widget.showUsername)
|
child: RichText(
|
||||||
TextSpan(
|
text: TextSpan(
|
||||||
text: widget.message.user.name,
|
style: widget.messageTheme.createdAt,
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
children: <TextSpan>[
|
||||||
),
|
if (widget.showUsername)
|
||||||
if (widget.message.createdAt != null && widget.showTimestamp)
|
TextSpan(
|
||||||
TextSpan(
|
text: widget.message.user.name,
|
||||||
text: Jiffy(widget.message.createdAt.toLocal())
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
.format(' HH:mm'),
|
),
|
||||||
),
|
if (widget.message.createdAt != null && widget.showTimestamp)
|
||||||
],
|
TextSpan(
|
||||||
|
text: Jiffy(widget.message.createdAt.toLocal())
|
||||||
|
.format(' HH:mm'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
if (widget.readList?.isNotEmpty == true)
|
||||||
|
SizedBox.fromSize(
|
||||||
|
size: Size(widget.readList.length * 20.0, 17),
|
||||||
|
child: Transform(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
transform: Matrix4.rotationY(widget.reverse ? pi : 0),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 4.0),
|
||||||
|
child: _buildReadIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildReadIndicator() {
|
||||||
|
var padding = 0.0;
|
||||||
|
return Stack(
|
||||||
|
children: widget.readList.map((e) {
|
||||||
|
padding += 10.0;
|
||||||
|
return Positioned(
|
||||||
|
left: padding - 10,
|
||||||
|
bottom: 0,
|
||||||
|
top: 0,
|
||||||
|
child: Material(
|
||||||
|
color: Colors.white,
|
||||||
|
shape: CircleBorder(),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(1.0),
|
||||||
|
child: UserAvatar(
|
||||||
|
user: e.user,
|
||||||
|
constraints: BoxConstraints.loose(Size.fromRadius(16)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildReactionIndicator(BuildContext context) {
|
Widget _buildReactionIndicator(BuildContext context) {
|
||||||
return AnimatedSwitcher(
|
return AnimatedSwitcher(
|
||||||
key: _reactionPickerKey,
|
key: _reactionPickerKey,
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ dependencies:
|
|||||||
file_picker: ^1.9.0+1
|
file_picker: ^1.9.0+1
|
||||||
image_picker: ^0.6.7
|
image_picker: ^0.6.7
|
||||||
flutter_keyboard_visibility: ^3.0.0
|
flutter_keyboard_visibility: ^3.0.0
|
||||||
stream_chat: ^0.2.0-alpha+19
|
stream_chat: ^0.2.0-alpha+20
|
||||||
mime: ^0.9.6+3
|
mime: ^0.9.6+3
|
||||||
visibility_detector: ^0.1.5
|
visibility_detector: ^0.1.5
|
||||||
http_parser: ^3.1.4
|
http_parser: ^3.1.4
|
||||||
|
|||||||
Reference in New Issue
Block a user