add threads example
This commit is contained in:
@@ -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: <Widget>[
|
||||||
|
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: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: MessageListView(
|
||||||
|
parentMessage: parent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
MessageInput(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,8 +18,7 @@ class ChannelListView extends StatefulWidget {
|
|||||||
this.onChannelTap,
|
this.onChannelTap,
|
||||||
this.channelWidget,
|
this.channelWidget,
|
||||||
this.channelPreviewBuilder,
|
this.channelPreviewBuilder,
|
||||||
}) : assert(channelWidget != null || onChannelTap != null),
|
}) : super(key: key);
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
final Map<String, dynamic> filter;
|
final Map<String, dynamic> filter;
|
||||||
final Map<String, dynamic> options;
|
final Map<String, dynamic> options;
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import 'stream_channel.dart';
|
|||||||
|
|
||||||
typedef MessageBuilder = Widget Function(BuildContext, Message, int index);
|
typedef MessageBuilder = Widget Function(BuildContext, Message, int index);
|
||||||
typedef ParentMessageBuilder = Widget Function(BuildContext, Message);
|
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 {
|
class MessageListView extends StatefulWidget {
|
||||||
MessageListView({
|
MessageListView({
|
||||||
@@ -17,13 +18,15 @@ class MessageListView extends StatefulWidget {
|
|||||||
MessageBuilder messageBuilder,
|
MessageBuilder messageBuilder,
|
||||||
this.parentMessageBuilder,
|
this.parentMessageBuilder,
|
||||||
this.parentMessage,
|
this.parentMessage,
|
||||||
this.onThreadSelect,
|
this.threadBuilder,
|
||||||
|
this.onThreadTap,
|
||||||
}) : _messageBuilder = messageBuilder,
|
}) : _messageBuilder = messageBuilder,
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
final MessageBuilder _messageBuilder;
|
final MessageBuilder _messageBuilder;
|
||||||
final ParentMessageBuilder parentMessageBuilder;
|
final ParentMessageBuilder parentMessageBuilder;
|
||||||
final OnThreadSelectCallback onThreadSelect;
|
final ThreadBuilder threadBuilder;
|
||||||
|
final ThreadTapCallback onThreadTap;
|
||||||
final Message parentMessage;
|
final Message parentMessage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -38,6 +41,8 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
List<Message> _messages = [];
|
List<Message> _messages = [];
|
||||||
List<Message> _newMessageList = [];
|
List<Message> _newMessageList = [];
|
||||||
|
|
||||||
|
Function _onThreadTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final streamChannel = StreamChannel.of(context);
|
final streamChannel = StreamChannel.of(context);
|
||||||
@@ -74,7 +79,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
previousMessage: null,
|
previousMessage: null,
|
||||||
message: widget.parentMessage.copyWith(replyCount: 0),
|
message: widget.parentMessage.copyWith(replyCount: 0),
|
||||||
nextMessage: null,
|
nextMessage: null,
|
||||||
onThreadSelect: widget.onThreadSelect,
|
onThreadTap: _onThreadTap,
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||||
@@ -131,7 +136,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
previousMessage: previousMessage,
|
previousMessage: previousMessage,
|
||||||
message: message,
|
message: message,
|
||||||
nextMessage: nextMessage,
|
nextMessage: nextMessage,
|
||||||
onThreadSelect: widget.onThreadSelect,
|
onThreadTap: _onThreadTap,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
childCount: _messages.length + 2,
|
childCount: _messages.length + 2,
|
||||||
@@ -185,7 +190,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
previousMessage: null,
|
previousMessage: null,
|
||||||
message: message,
|
message: message,
|
||||||
nextMessage: nextMessage,
|
nextMessage: nextMessage,
|
||||||
onThreadSelect: widget.onThreadSelect,
|
onThreadTap: _onThreadTap,
|
||||||
),
|
),
|
||||||
onVisibilityChanged: (visibility) {
|
onVisibilityChanged: (visibility) {
|
||||||
final topIsVisible = visibility.visibleBounds != Rect.zero;
|
final topIsVisible = visibility.visibleBounds != Rect.zero;
|
||||||
@@ -218,7 +223,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
previousMessage: previousMessage,
|
previousMessage: previousMessage,
|
||||||
message: message,
|
message: message,
|
||||||
nextMessage: null,
|
nextMessage: null,
|
||||||
onThreadSelect: widget.onThreadSelect,
|
onThreadTap: _onThreadTap,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -270,6 +275,32 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_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
|
@override
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import 'package:stream_chat_flutter/src/user_avatar.dart';
|
|||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:video_player/video_player.dart';
|
import 'package:video_player/video_player.dart';
|
||||||
|
|
||||||
import 'message_list_view.dart';
|
|
||||||
import 'stream_chat.dart';
|
import 'stream_chat.dart';
|
||||||
|
|
||||||
class MessageWidget extends StatefulWidget {
|
class MessageWidget extends StatefulWidget {
|
||||||
@@ -18,13 +17,13 @@ class MessageWidget extends StatefulWidget {
|
|||||||
@required this.previousMessage,
|
@required this.previousMessage,
|
||||||
@required this.message,
|
@required this.message,
|
||||||
@required this.nextMessage,
|
@required this.nextMessage,
|
||||||
this.onThreadSelect,
|
this.onThreadTap,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final Message previousMessage;
|
final Message previousMessage;
|
||||||
final Message message;
|
final Message message;
|
||||||
final Message nextMessage;
|
final Message nextMessage;
|
||||||
final OnThreadSelectCallback onThreadSelect;
|
final void Function(Message) onThreadTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MessageWidgetState createState() => _MessageWidgetState();
|
_MessageWidgetState createState() => _MessageWidgetState();
|
||||||
@@ -59,8 +58,8 @@ class _MessageWidgetState extends State<MessageWidget>
|
|||||||
widget.message.replyCount > 0
|
widget.message.replyCount > 0
|
||||||
? GestureDetector(
|
? GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (widget.onThreadSelect != null) {
|
if (widget.onThreadTap != null) {
|
||||||
widget.onThreadSelect(widget.message);
|
widget.onThreadTap(widget.message);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|||||||
Reference in New Issue
Block a user