add typing indicator widget
This commit is contained in:
@@ -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));
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:stream_chat/stream_chat.dart';
|
||||
|
||||
import '../stream_chat_flutter.dart';
|
||||
import 'channel_name.dart';
|
||||
import 'typing_indicator.dart';
|
||||
|
||||
/// 
|
||||
/// 
|
||||
@@ -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<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),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class MessageWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MessageWidgetState extends State<MessageWidget>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
with AutomaticKeepAliveClientMixin, TickerProviderStateMixin {
|
||||
final Map<String, ChangeNotifier> _videoControllers = {};
|
||||
final Map<String, ChangeNotifier> _chuwieControllers = {};
|
||||
|
||||
@@ -126,8 +126,7 @@ class _MessageWidgetState extends State<MessageWidget>
|
||||
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<MessageWidget>
|
||||
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<MessageWidget>
|
||||
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(),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user