From 1f226f33c84b12d0bf5ceb31fa52aad06c0ec0a8 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 8 Jul 2020 14:52:39 +0200 Subject: [PATCH] add online indicator to useravatar --- lib/src/channel_image.dart | 27 ++++++++- lib/src/message_widget.dart | 2 + lib/src/user_avatar.dart | 107 +++++++++++++++++++++++------------- 3 files changed, 96 insertions(+), 40 deletions(-) diff --git a/lib/src/channel_image.dart b/lib/src/channel_image.dart index bef666db..d8401bdf 100644 --- a/lib/src/channel_image.dart +++ b/lib/src/channel_image.dart @@ -49,6 +49,7 @@ class ChannelImage extends StatelessWidget { this.channel, this.constraints, this.onTap, + this.showOnlineStatus = true, }) : super(key: key); /// The channel to show the image of @@ -60,9 +61,11 @@ class ChannelImage extends StatelessWidget { /// The function called when the image is tapped final VoidCallback onTap; + final bool showOnlineStatus; + @override Widget build(BuildContext context) { - final client = StreamChat.of(context); + final streamChat = StreamChat.of(context); final channel = this.channel ?? StreamChannel.of(context).channel; return StreamBuilder>( stream: channel.extraDataStream, @@ -73,8 +76,26 @@ class ChannelImage extends StatelessWidget { image = snapshot.data['image']; } else if (channel.state.members.length == 2) { final otherMember = channel.state.members - .firstWhere((member) => member.user.id != client.user.id); - image = otherMember.user.extraData['image']; + .firstWhere((member) => member.user.id != streamChat.user.id); + return StreamBuilder( + stream: streamChat.client.state.usersStream + .map((users) => users[otherMember.userId]), + initialData: otherMember.user, + builder: (context, snapshot) { + return UserAvatar( + user: snapshot.data ?? otherMember.user, + constraints: constraints ?? + StreamChatTheme.of(context) + .channelPreviewTheme + .avatarTheme + .constraints, + onTap: onTap != null + ? (_) { + onTap(); + } + : null, + ); + }); } return ClipRRect( diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 07760235..3103d079 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -426,6 +426,7 @@ class _MessageWidgetState extends State { child: UserAvatar( user: e.user, constraints: BoxConstraints.loose(Size.fromRadius(16)), + showOnlineStatus: false, ), ), ), @@ -648,6 +649,7 @@ class _MessageWidgetState extends State { user: widget.message.user, onTap: widget.onUserAvatarTap, constraints: widget.messageTheme.avatarTheme.constraints, + showOnlineStatus: false, ), ), ), diff --git a/lib/src/user_avatar.dart b/lib/src/user_avatar.dart index 8ea9a525..33e8ab90 100644 --- a/lib/src/user_avatar.dart +++ b/lib/src/user_avatar.dart @@ -9,55 +9,88 @@ class UserAvatar extends StatelessWidget { Key key, @required this.user, this.constraints, + this.onlineIndicatorConstraints, this.onTap, + this.showOnlineStatus = true, }) : super(key: key); final User user; final BoxConstraints constraints; + final BoxConstraints onlineIndicatorConstraints; final void Function(User) onTap; + final bool showOnlineStatus; @override Widget build(BuildContext context) { return GestureDetector( - onTap: () { - if (onTap != null) { - onTap(user); - } - }, - child: ClipRRect( - borderRadius: StreamChatTheme.of(context) - .ownMessageTheme - .avatarTheme - .borderRadius, - child: Container( - constraints: constraints ?? - StreamChatTheme.of(context) - .ownMessageTheme - .avatarTheme - .constraints, - decoration: BoxDecoration( - color: StreamChatTheme.of(context).accentColor, + onTap: onTap != null + ? () { + if (onTap != null) { + onTap(user); + } + } + : null, + child: Stack( + children: [ + ClipRRect( + borderRadius: StreamChatTheme.of(context) + .ownMessageTheme + .avatarTheme + .borderRadius, + child: Container( + constraints: constraints ?? + StreamChatTheme.of(context) + .ownMessageTheme + .avatarTheme + .constraints, + decoration: BoxDecoration( + color: StreamChatTheme.of(context).accentColor, + ), + child: user.extraData?.containsKey('image') ?? false + ? CachedNetworkImage( + imageUrl: user.extraData['image'], + errorWidget: (_, __, ___) { + return Center( + child: Text( + user.extraData?.containsKey('name') ?? false + ? user.extraData['name'][0] + : '', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ); + }, + fit: BoxFit.cover, + ) + : StreamChatTheme.of(context).defaultUserImage(context, user), + ), ), - child: user.extraData?.containsKey('image') ?? false - ? CachedNetworkImage( - imageUrl: user.extraData['image'], - errorWidget: (_, __, ___) { - return Center( - child: Text( - user.extraData?.containsKey('name') ?? false - ? user.extraData['name'][0] - : '', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, + if (showOnlineStatus && user.online) + Positioned( + top: 0, + right: 0, + child: Material( + child: Center( + child: Container( + padding: const EdgeInsets.all(2.0), + constraints: onlineIndicatorConstraints ?? + BoxConstraints.tightFor( + width: 12, + height: 12, ), - ), - ); - }, - fit: BoxFit.cover, - ) - : StreamChatTheme.of(context).defaultUserImage(context, user), - ), + child: Material( + shape: CircleBorder(), + color: Color(0xff20E070), + ), + ), + ), + shape: CircleBorder(), + color: Colors.white, + ), + ), + ], ), ); }