add typing indicator widget in example messagelist

This commit is contained in:
Salvatore Giordano
2020-03-06 10:34:38 +01:00
parent 153455ae56
commit 60c2ccfc24
10 changed files with 151 additions and 120 deletions
+3 -2
View File
@@ -78,7 +78,9 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
padding: const EdgeInsets.only(right: 10.0),
child: Stack(
children: <Widget>[
Center(child: ChannelImage(channel: channel)),
Center(
child: ChannelImage(),
),
],
),
),
@@ -88,7 +90,6 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ChannelName(
channel: channel,
textStyle: StreamChatTheme.of(context)
.channelTheme
.channelHeaderTheme
+2 -1
View File
@@ -45,7 +45,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
class ChannelImage extends StatelessWidget {
const ChannelImage({
Key key,
@required this.channel,
this.channel,
this.size = 40,
}) : super(key: key);
@@ -57,6 +57,7 @@ class ChannelImage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final channel = this.channel ?? StreamChannel.of(context).channel;
return StreamBuilder<Map<String, dynamic>>(
stream: channel.extraDataStream,
initialData: channel.extraData,
+4 -1
View File
@@ -1,13 +1,15 @@
import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.dart';
import 'stream_channel.dart';
/// It shows the current [Channel] name using a [Text] widget.
///
/// The widget uses a [StreamBuilder] to render the channel information image as soon as it updates.
class ChannelName extends StatelessWidget {
const ChannelName({
Key key,
@required this.channel,
this.channel,
this.textStyle,
}) : super(key: key);
@@ -19,6 +21,7 @@ class ChannelName extends StatelessWidget {
@override
Widget build(BuildContext context) {
final channel = this.channel ?? StreamChannel.of(context).channel;
return StreamBuilder<Map<String, dynamic>>(
stream: channel.extraDataStream,
initialData: channel.extraData,
+17 -26
View File
@@ -37,14 +37,11 @@ class ChannelPreview extends StatelessWidget {
onTap: () {
onTap(channel);
},
leading: ChannelImage(
channel: channel,
),
leading: ChannelImage(),
title: ChannelName(
textStyle: StreamChatTheme.of(context).channelPreviewTheme.title,
channel: channel,
),
subtitle: _buildSubtitle(),
subtitle: _buildSubtitle(context),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
@@ -81,29 +78,23 @@ class ChannelPreview extends StatelessWidget {
);
}
Widget _buildSubtitle() {
return StreamBuilder<List<User>>(
stream: channel.state.typingEventsStream,
initialData: channel.state.typingEvents,
builder: (context, snapshot) {
final typings = snapshot.data;
final opacity = channel.state.unreadCount > 0 ? 1.0 : 0.5;
return typings.isNotEmpty
? TypingIndicator(
typings: typings,
style: StreamChatTheme.of(context)
Widget _buildSubtitle(BuildContext context) {
final opacity = channel.state.unreadCount > 0 ? 1.0 : 0.5;
return Align(
alignment: Alignment.centerLeft,
child: TypingIndicator(
channel: channel,
alternativeWidget: _buildLastMessage(context, opacity),
style:
StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
color: StreamChatTheme.of(context)
.channelPreviewTheme
.subtitle
.copyWith(
color: StreamChatTheme.of(context)
.channelPreviewTheme
.subtitle
.color
.withOpacity(opacity),
),
)
: _buildLastMessage(context, opacity);
});
.color
.withOpacity(opacity),
),
),
);
}
Widget _buildLastMessage(BuildContext context, double opacity) {
+26 -6
View File
@@ -1,11 +1,13 @@
import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter/src/stream_channel.dart';
/// Widget to show the current list of typing users
class TypingIndicator extends StatelessWidget {
const TypingIndicator({
Key key,
@required this.typings,
this.channel,
this.alternativeWidget = const SizedBox(),
this.style,
}) : super(key: key);
@@ -13,14 +15,32 @@ class TypingIndicator extends StatelessWidget {
final TextStyle style;
/// List of typing users
final List<User> typings;
final Channel channel;
/// Widget built when no typings is happening
final Widget alternativeWidget;
@override
Widget build(BuildContext context) {
return Text(
'${typings.map((u) => u.name).join(',')} ${typings.length == 1 ? 'is' : 'are'} typing...',
maxLines: 1,
style: style,
final channelState =
channel?.state ?? StreamChannel.of(context).channel.state;
return StreamBuilder<List<User>>(
initialData: channelState.typingEvents,
stream: channelState.typingEventsStream,
builder: (context, snapshot) {
return AnimatedSwitcher(
duration: Duration(milliseconds: 300),
child: snapshot.data.isNotEmpty
? Text(
'${snapshot.data.map((u) => u.name).join(',')} ${snapshot.data.length == 1 ? 'is' : 'are'} typing...',
maxLines: 1,
style: style,
)
: Container(
child: alternativeWidget,
),
);
},
);
}
}