add typing indicator widget

This commit is contained in:
Salvatore Giordano
2020-03-05 10:56:46 +01:00
parent e6328927b1
commit 9e4e2f5a12
5 changed files with 53 additions and 25 deletions
+3 -3
View File
@@ -3,13 +3,13 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
void main() async { void main() async {
final client = Client( final client = Client(
'b67pax5b2wdq', 's2dxdhpxd94g',
logLevel: Level.INFO, logLevel: Level.INFO,
); );
await client.setUser( await client.setUser(
User(id: 'falling-mountain-7'), User(id: 'super-band-9'),
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiZmFsbGluZy1tb3VudGFpbi03In0.AKgRXHMQQMz6vJAKszXdY8zMFfsAgkoUeZHlI-Szz9E', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A',
); );
runApp(MyApp(client)); runApp(MyApp(client));
+14 -15
View File
@@ -5,6 +5,7 @@ import 'package:stream_chat/stream_chat.dart';
import '../stream_chat_flutter.dart'; import '../stream_chat_flutter.dart';
import 'channel_name.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.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_preview_paint.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 typings = snapshot.data;
final opacity = channel.state.unreadCount > 0 ? 1.0 : 0.5; final opacity = channel.state.unreadCount > 0 ? 1.0 : 0.5;
return typings.isNotEmpty 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); : _buildLastMessage(context, opacity);
}); });
} }
@@ -141,18 +154,4 @@ class ChannelPreview extends StatelessWidget {
}, },
); );
} }
Text _buildTypings(List<User> 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),
),
);
}
} }
+9 -7
View File
@@ -62,7 +62,7 @@ class MessageWidget extends StatefulWidget {
} }
class _MessageWidgetState extends State<MessageWidget> class _MessageWidgetState extends State<MessageWidget>
with AutomaticKeepAliveClientMixin { with AutomaticKeepAliveClientMixin, TickerProviderStateMixin {
final Map<String, ChangeNotifier> _videoControllers = {}; final Map<String, ChangeNotifier> _videoControllers = {};
final Map<String, ChangeNotifier> _chuwieControllers = {}; final Map<String, ChangeNotifier> _chuwieControllers = {};
@@ -126,8 +126,7 @@ class _MessageWidgetState extends State<MessageWidget>
row = row.reversed.toList(); row = row.reversed.toList();
} }
child = AnimatedContainer( child = Container(
duration: Duration(milliseconds: 300),
padding: const EdgeInsets.symmetric(horizontal: 10.0), padding: const EdgeInsets.symmetric(horizontal: 10.0),
margin: EdgeInsets.only( margin: EdgeInsets.only(
top: isLastUser ? 5 : 24, top: isLastUser ? 5 : 24,
@@ -674,9 +673,7 @@ class _MessageWidgetState extends State<MessageWidget>
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
vertical: widget.message.reactionCounts?.isNotEmpty == true ? 4.0 : 0, vertical: widget.message.reactionCounts?.isNotEmpty == true ? 4.0 : 0,
), ),
child: AnimatedContainer( child: Container(
duration: Duration(milliseconds: 300),
curve: Curves.decelerate,
padding: widget.message.reactionCounts?.isNotEmpty == true padding: widget.message.reactionCounts?.isNotEmpty == true
? const EdgeInsets.all(8) ? const EdgeInsets.all(8)
: EdgeInsets.zero, : EdgeInsets.zero,
@@ -685,7 +682,12 @@ class _MessageWidgetState extends State<MessageWidget>
borderRadius: BorderRadius.all(Radius.circular(14))), borderRadius: BorderRadius.all(Radius.circular(14))),
child: (widget.message.reactionCounts != null && child: (widget.message.reactionCounts != null &&
widget.message.reactionCounts.isNotEmpty) widget.message.reactionCounts.isNotEmpty)
? _buildReactionRow() ? AnimatedSize(
duration: Duration(milliseconds: 300),
vsync: this,
curve: Curves.easeInQuad,
child: _buildReactionRow(),
)
: SizedBox(), : SizedBox(),
), ),
), ),
+26
View File
@@ -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<User> typings;
@override
Widget build(BuildContext context) {
return Text(
'${typings.map((u) => u.name).join(',')} ${typings.length == 1 ? 'is' : 'are'} typing...',
maxLines: 1,
style: style,
);
}
}
+1
View File
@@ -13,3 +13,4 @@ export 'src/stream_channel.dart';
export 'src/stream_chat.dart'; export 'src/stream_chat.dart';
export 'src/stream_chat_theme.dart'; export 'src/stream_chat_theme.dart';
export 'src/thread_header.dart'; export 'src/thread_header.dart';
export 'src/typing_indicator.dart';