From 65d9d7889dbbe9c22e02aada875f79761d908c49 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 25 Feb 2020 12:09:09 +0100 Subject: [PATCH] add customize_channel_preview example --- .../android/app/src/main/AndroidManifest.xml | 1 + example/lib/customize_channel_preview.dart | 78 ++++++++++++++++ example/lib/multiple_conversation.dart | 4 +- example/lib/single_conversation.dart | 3 +- lib/src/channel_list_view.dart | 69 ++++++++------ lib/src/channel_preview.dart | 89 +++++++------------ pubspec.yaml | 3 +- 7 files changed, 156 insertions(+), 91 deletions(-) create mode 100644 example/lib/customize_channel_preview.dart diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 8bc6007d..1b2ad157 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ In most cases you can leave this as-is, but you if you want to provide additional functionality it is fine to subclass or reimplement FlutterApplication and put your custom class here. --> + 0 + ? CircleAvatar( + radius: 10, + child: Text(channelClient.state.unreadCount.toString()), + ) + : Container(), + ); + }, + sort: [SortOption('last_message_at')], + pagination: PaginationParams( + limit: 20, + ), + channelWidget: ChannelPage(), + ), + ); + } +} + +class ChannelPage extends StatelessWidget { + const ChannelPage({ + Key key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Expanded( + child: MessageListView(), + ), + MessageInput(), + ], + ), + ); + } +} diff --git a/example/lib/multiple_conversation.dart b/example/lib/multiple_conversation.dart index 682f364f..d0cce521 100644 --- a/example/lib/multiple_conversation.dart +++ b/example/lib/multiple_conversation.dart @@ -5,7 +5,7 @@ void main() async { final client = Client('qk4nn7rpcn75'); await client.setUser( - User(id: "wild-breeze-7"), + User(id: 'wild-breeze-7'), 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo', ); @@ -29,7 +29,7 @@ class ChannelListPage extends StatelessWidget { '\$in': [StreamChat.of(context).user.id], } }, - sort: [SortOption("last_message_at")], + sort: [SortOption('last_message_at')], pagination: PaginationParams( limit: 20, ), diff --git a/example/lib/single_conversation.dart b/example/lib/single_conversation.dart index b0008765..6e60f0db 100644 --- a/example/lib/single_conversation.dart +++ b/example/lib/single_conversation.dart @@ -5,12 +5,13 @@ void main() async { final client = Client('qk4nn7rpcn75'); await client.setUser( - User(id: "wild-breeze-7"), + User(id: 'wild-breeze-7'), 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo', ); final channelClient = client.channel('messaging', id: 'godevs'); + // ignore: unawaited_futures channelClient.watch(); runApp( diff --git a/lib/src/channel_list_view.dart b/lib/src/channel_list_view.dart index 94272044..f75666fa 100644 --- a/lib/src/channel_list_view.dart +++ b/lib/src/channel_list_view.dart @@ -6,6 +6,7 @@ import 'stream_channel.dart'; import 'stream_chat.dart'; typedef ChannelTapCallback = void Function(ChannelClient, Widget); +typedef ChannelPreviewBuilder = Widget Function(BuildContext, ChannelClient); class ChannelListView extends StatefulWidget { ChannelListView({ @@ -16,7 +17,7 @@ class ChannelListView extends StatefulWidget { this.pagination, this.onChannelTap, this.channelWidget, - this.channelPreview, + this.channelPreviewBuilder, }) : assert(channelWidget != null || onChannelTap != null), super(key: key); @@ -27,7 +28,7 @@ class ChannelListView extends StatefulWidget { final ScrollController _scrollController = ScrollController(); final ChannelTapCallback onChannelTap; final Widget channelWidget; - final Widget channelPreview; + final ChannelPreviewBuilder channelPreviewBuilder; @override _ChannelListViewState createState() => _ChannelListViewState(); @@ -117,34 +118,46 @@ class _ChannelListViewState extends State { }; } - Widget child; - if (widget.channelPreview != null) { - child = Stack( - children: [ - widget.channelPreview, - Positioned.fill( - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - onTap(channelClient, widget.channelWidget); - }, - ), - ), - ), - ], - ); - } else { - child = ChannelPreview( - onTap: (channelClient) { - onTap(channelClient, widget.channelWidget); - }, - ); - } - return StreamChannel( key: ValueKey('CHANNEL-${channelClient.id}'), - child: child, + child: StreamBuilder( + initialData: channelClient.state.channelState, + stream: channelClient.state.channelStateStream, + builder: (context, snapshot) { + final channelState = snapshot.data; + + Widget child; + if (widget.channelPreviewBuilder != null) { + child = Stack( + children: [ + widget.channelPreviewBuilder( + context, + channelClient, + ), + Positioned.fill( + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + onTap(channelClient, widget.channelWidget); + }, + ), + ), + ), + ], + ); + } else { + child = ChannelPreview( + channelClient: channelClient, + onTap: (channelClient) { + onTap(channelClient, widget.channelWidget); + }, + ); + } + + return child; + }, + ), channelClient: channelClient, ); } else { diff --git a/lib/src/channel_preview.dart b/lib/src/channel_preview.dart index e390a9f6..1372826f 100644 --- a/lib/src/channel_preview.dart +++ b/lib/src/channel_preview.dart @@ -5,62 +5,38 @@ import 'package:stream_chat/stream_chat.dart'; import 'channel_image.dart'; import 'channel_name_text.dart'; -import 'stream_channel.dart'; -import 'stream_chat.dart'; class ChannelPreview extends StatelessWidget { final void Function(ChannelClient) onTap; + final ChannelState channelState; + final ChannelClient channelClient; - const ChannelPreview({ + ChannelPreview({ + @required this.channelClient, Key key, this.onTap, - }) : super(key: key); + }) : channelState = channelClient.state.channelState, + super(key: key); @override Widget build(BuildContext context) { - final streamChannel = StreamChannel.of(context); - return StreamBuilder( - stream: streamChannel.channelClient.state.channelStateStream, - initialData: streamChannel.channelState, - builder: (context, snapshot) { - final channelState = snapshot.data; - return _buildChannelPreview( - context, - channelState, - streamChannel, - ); - }); - } - - StreamChannel _buildChannelPreview( - BuildContext context, - ChannelState channelState, - StreamChannelState streamChannel, - ) { - final channelClient = - StreamChat.of(context).client.channelClients[channelState.channel.id]; - return StreamChannel( - channelClient: channelClient, - child: ListTile( - onTap: () { - onTap(channelClient); - }, - leading: ChannelImage( - channel: channelState.channel, - ), - title: ChannelNameText( - channel: channelState.channel, - ), - subtitle: _buildSubtitle( - streamChannel, - ), - trailing: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - _buildDate(context, channelState.channel.lastMessageAt), - ], - ), + return ListTile( + onTap: () { + onTap(channelClient); + }, + leading: ChannelImage( + channel: channelState.channel, + ), + title: ChannelNameText( + channel: channelState.channel, + ), + subtitle: _buildSubtitle(), + trailing: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + _buildDate(context, channelState.channel.lastMessageAt), + ], ), ); } @@ -86,27 +62,22 @@ class ChannelPreview extends StatelessWidget { ); } - Widget _buildSubtitle( - StreamChannelState streamChannel, - ) { + Widget _buildSubtitle() { return StreamBuilder>( - stream: streamChannel.channelClient.state.typingEventsStream, + stream: channelClient.state.typingEventsStream, initialData: [], builder: (context, snapshot) { final typings = snapshot.data; - final opacity = - streamChannel.channelClient.state.unreadCount > .0 ? 1.0 : 0.5; + final opacity = channelClient.state.unreadCount > .0 ? 1.0 : 0.5; return typings.isNotEmpty ? _buildTypings(typings, context, opacity) - : _buildLastMessage(context, streamChannel, opacity); + : _buildLastMessage(context, opacity); }); } - Widget _buildLastMessage( - BuildContext context, StreamChannelState streamChannel, double opacity) { - final lastMessage = streamChannel.channelState.messages.isNotEmpty - ? streamChannel.channelState.messages.last - : null; + Widget _buildLastMessage(BuildContext context, double opacity) { + final lastMessage = + channelState.messages.isNotEmpty ? channelState.messages.last : null; if (lastMessage == null) { return SizedBox.fromSize( size: Size.zero, diff --git a/pubspec.yaml b/pubspec.yaml index 32cf32e8..00831e3c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,8 @@ dependencies: video_player: ^0.10.7 chewie: ^0.9.8+1 animations: ^1.0.0+3 - stream_chat: ^0.1.6 + stream_chat: + path: ../stream_chat_dart dev_dependencies: pedantic: ^1.8.0+1