From 3c4edf1b185b512fba56830b3cc9636fee6b7444 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 25 Feb 2020 13:52:15 +0100 Subject: [PATCH] add threads example --- example/lib/threads.dart | 91 ++++++++++++++++++++++++++++++++++ lib/src/channel_list_view.dart | 3 +- lib/src/message_list_view.dart | 45 ++++++++++++++--- lib/src/message_widget.dart | 9 ++-- 4 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 example/lib/threads.dart diff --git a/example/lib/threads.dart b/example/lib/threads.dart new file mode 100644 index 00000000..100e5ee6 --- /dev/null +++ b/example/lib/threads.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +void main() async { + final client = Client('qk4nn7rpcn75'); + + await client.setUser( + User(id: 'wild-breeze-7'), + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo', + ); + + runApp( + StreamChat( + client: client, + child: MaterialApp( + home: ChannelListPage(), + ), + ), + ); +} + +class ChannelListPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: ChannelListView( + filter: { + 'members': { + '\$in': [StreamChat.of(context).user.id], + } + }, + 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( + threadBuilder: (_, message) { + return ThreadPage( + parent: message, + ); + }, + ), + ), + MessageInput(), + ], + ), + ); + } +} + +class ThreadPage extends StatelessWidget { + final Message parent; + + ThreadPage({ + Key key, + this.parent, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Expanded( + child: MessageListView( + parentMessage: parent, + ), + ), + MessageInput(), + ], + ), + ); + } +} diff --git a/lib/src/channel_list_view.dart b/lib/src/channel_list_view.dart index f75666fa..5be4dfb1 100644 --- a/lib/src/channel_list_view.dart +++ b/lib/src/channel_list_view.dart @@ -18,8 +18,7 @@ class ChannelListView extends StatefulWidget { this.onChannelTap, this.channelWidget, this.channelPreviewBuilder, - }) : assert(channelWidget != null || onChannelTap != null), - super(key: key); + }) : super(key: key); final Map filter; final Map options; diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index af8608d6..c5b3eab1 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -9,7 +9,8 @@ import 'stream_channel.dart'; typedef MessageBuilder = Widget Function(BuildContext, Message, int index); typedef ParentMessageBuilder = Widget Function(BuildContext, Message); -typedef OnThreadSelectCallback = void Function(Message parent); +typedef ThreadBuilder = Widget Function(BuildContext context, Message parent); +typedef ThreadTapCallback = void Function(Message, Widget); class MessageListView extends StatefulWidget { MessageListView({ @@ -17,13 +18,15 @@ class MessageListView extends StatefulWidget { MessageBuilder messageBuilder, this.parentMessageBuilder, this.parentMessage, - this.onThreadSelect, + this.threadBuilder, + this.onThreadTap, }) : _messageBuilder = messageBuilder, super(key: key); final MessageBuilder _messageBuilder; final ParentMessageBuilder parentMessageBuilder; - final OnThreadSelectCallback onThreadSelect; + final ThreadBuilder threadBuilder; + final ThreadTapCallback onThreadTap; final Message parentMessage; @override @@ -38,6 +41,8 @@ class _MessageListViewState extends State { List _messages = []; List _newMessageList = []; + Function _onThreadTap; + @override Widget build(BuildContext context) { final streamChannel = StreamChannel.of(context); @@ -74,7 +79,7 @@ class _MessageListViewState extends State { previousMessage: null, message: widget.parentMessage.copyWith(replyCount: 0), nextMessage: null, - onThreadSelect: widget.onThreadSelect, + onThreadTap: _onThreadTap, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 32), @@ -131,7 +136,7 @@ class _MessageListViewState extends State { previousMessage: previousMessage, message: message, nextMessage: nextMessage, - onThreadSelect: widget.onThreadSelect, + onThreadTap: _onThreadTap, ); }, childCount: _messages.length + 2, @@ -185,7 +190,7 @@ class _MessageListViewState extends State { previousMessage: null, message: message, nextMessage: nextMessage, - onThreadSelect: widget.onThreadSelect, + onThreadTap: _onThreadTap, ), onVisibilityChanged: (visibility) { final topIsVisible = visibility.visibleBounds != Rect.zero; @@ -218,7 +223,7 @@ class _MessageListViewState extends State { previousMessage: previousMessage, message: message, nextMessage: null, - onThreadSelect: widget.onThreadSelect, + onThreadTap: _onThreadTap, ), ); } @@ -270,6 +275,32 @@ class _MessageListViewState extends State { }); } }); + + _getOnThreadTap(); + } + + void _getOnThreadTap() { + if (widget.onThreadTap != null) { + _onThreadTap = (message) { + widget.onThreadTap( + message, + widget.threadBuilder != null + ? widget.threadBuilder(context, message) + : null); + }; + } else { + _onThreadTap = (message) { + Navigator.push( + context, + MaterialPageRoute(builder: (_) { + return StreamChannel( + channelClient: StreamChannel.of(context).channelClient, + child: widget.threadBuilder(context, message), + ); + }), + ); + }; + } } @override diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index f5278567..8a26984b 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -9,7 +9,6 @@ import 'package:stream_chat_flutter/src/user_avatar.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:video_player/video_player.dart'; -import 'message_list_view.dart'; import 'stream_chat.dart'; class MessageWidget extends StatefulWidget { @@ -18,13 +17,13 @@ class MessageWidget extends StatefulWidget { @required this.previousMessage, @required this.message, @required this.nextMessage, - this.onThreadSelect, + this.onThreadTap, }) : super(key: key); final Message previousMessage; final Message message; final Message nextMessage; - final OnThreadSelectCallback onThreadSelect; + final void Function(Message) onThreadTap; @override _MessageWidgetState createState() => _MessageWidgetState(); @@ -59,8 +58,8 @@ class _MessageWidgetState extends State widget.message.replyCount > 0 ? GestureDetector( onTap: () { - if (widget.onThreadSelect != null) { - widget.onThreadSelect(widget.message); + if (widget.onThreadTap != null) { + widget.onThreadTap(widget.message); } }, child: Padding(