From 9e4e2f5a127881bf28bff612300ea3bff1567258 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Mar 2020 10:56:46 +0100 Subject: [PATCH] add typing indicator widget --- example/lib/main.dart | 6 +++--- lib/src/channel_preview.dart | 29 ++++++++++++++--------------- lib/src/message_widget.dart | 16 +++++++++------- lib/src/typing_indicator.dart | 26 ++++++++++++++++++++++++++ lib/stream_chat_flutter.dart | 1 + 5 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 lib/src/typing_indicator.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index a28a4320..3fb47119 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -3,13 +3,13 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; void main() async { final client = Client( - 'b67pax5b2wdq', + 's2dxdhpxd94g', logLevel: Level.INFO, ); await client.setUser( - User(id: 'falling-mountain-7'), - 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiZmFsbGluZy1tb3VudGFpbi03In0.AKgRXHMQQMz6vJAKszXdY8zMFfsAgkoUeZHlI-Szz9E', + User(id: 'super-band-9'), + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A', ); runApp(MyApp(client)); diff --git a/lib/src/channel_preview.dart b/lib/src/channel_preview.dart index 774a72b0..13be1151 100644 --- a/lib/src/channel_preview.dart +++ b/lib/src/channel_preview.dart @@ -5,6 +5,7 @@ import 'package:stream_chat/stream_chat.dart'; import '../stream_chat_flutter.dart'; import 'channel_name.dart'; +import 'typing_indicator.dart'; /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_preview.png) /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_preview_paint.png) @@ -88,7 +89,19 @@ class ChannelPreview extends StatelessWidget { final typings = snapshot.data; final opacity = channel.state.unreadCount > 0 ? 1.0 : 0.5; return typings.isNotEmpty - ? _buildTypings(typings, context, opacity) + ? TypingIndicator( + typings: typings, + style: StreamChatTheme.of(context) + .channelPreviewTheme + .subtitle + .copyWith( + color: StreamChatTheme.of(context) + .channelPreviewTheme + .subtitle + .color + .withOpacity(opacity), + ), + ) : _buildLastMessage(context, opacity); }); } @@ -141,18 +154,4 @@ class ChannelPreview extends StatelessWidget { }, ); } - - Text _buildTypings(List typings, BuildContext context, double opacity) { - return Text( - '${typings.map((u) => u.extraData.containsKey('name') ? u.extraData['name'] : u.id).join(',')} ${typings.length == 1 ? 'is' : 'are'} typing...', - maxLines: 1, - style: StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith( - color: StreamChatTheme.of(context) - .channelPreviewTheme - .subtitle - .color - .withOpacity(opacity), - ), - ); - } } diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 28a859da..c90e8376 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -62,7 +62,7 @@ class MessageWidget extends StatefulWidget { } class _MessageWidgetState extends State - with AutomaticKeepAliveClientMixin { + with AutomaticKeepAliveClientMixin, TickerProviderStateMixin { final Map _videoControllers = {}; final Map _chuwieControllers = {}; @@ -126,8 +126,7 @@ class _MessageWidgetState extends State row = row.reversed.toList(); } - child = AnimatedContainer( - duration: Duration(milliseconds: 300), + child = Container( padding: const EdgeInsets.symmetric(horizontal: 10.0), margin: EdgeInsets.only( top: isLastUser ? 5 : 24, @@ -674,9 +673,7 @@ class _MessageWidgetState extends State padding: EdgeInsets.symmetric( vertical: widget.message.reactionCounts?.isNotEmpty == true ? 4.0 : 0, ), - child: AnimatedContainer( - duration: Duration(milliseconds: 300), - curve: Curves.decelerate, + child: Container( padding: widget.message.reactionCounts?.isNotEmpty == true ? const EdgeInsets.all(8) : EdgeInsets.zero, @@ -685,7 +682,12 @@ class _MessageWidgetState extends State borderRadius: BorderRadius.all(Radius.circular(14))), child: (widget.message.reactionCounts != null && widget.message.reactionCounts.isNotEmpty) - ? _buildReactionRow() + ? AnimatedSize( + duration: Duration(milliseconds: 300), + vsync: this, + curve: Curves.easeInQuad, + child: _buildReactionRow(), + ) : SizedBox(), ), ), diff --git a/lib/src/typing_indicator.dart b/lib/src/typing_indicator.dart new file mode 100644 index 00000000..e63601ba --- /dev/null +++ b/lib/src/typing_indicator.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat/stream_chat.dart'; + +/// Widget to show the current list of typing users +class TypingIndicator extends StatelessWidget { + const TypingIndicator({ + Key key, + @required this.typings, + this.style, + }) : super(key: key); + + /// Style of the text widget + final TextStyle style; + + /// List of typing users + final List typings; + + @override + Widget build(BuildContext context) { + return Text( + '${typings.map((u) => u.name).join(',')} ${typings.length == 1 ? 'is' : 'are'} typing...', + maxLines: 1, + style: style, + ); + } +} diff --git a/lib/stream_chat_flutter.dart b/lib/stream_chat_flutter.dart index 80f4ed38..857336ce 100644 --- a/lib/stream_chat_flutter.dart +++ b/lib/stream_chat_flutter.dart @@ -13,3 +13,4 @@ export 'src/stream_channel.dart'; export 'src/stream_chat.dart'; export 'src/stream_chat_theme.dart'; export 'src/thread_header.dart'; +export 'src/typing_indicator.dart';