add doc
@@ -14,7 +14,6 @@ import 'stream_channel.dart';
|
|||||||
/// It shows the current [Channel] information.
|
/// It shows the current [Channel] information.
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
///
|
|
||||||
/// class MyApp extends StatelessWidget {
|
/// class MyApp extends StatelessWidget {
|
||||||
/// final Client client;
|
/// final Client client;
|
||||||
/// final Channel channel;
|
/// final Channel channel;
|
||||||
@@ -36,7 +35,6 @@ import 'stream_channel.dart';
|
|||||||
/// );
|
/// );
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Usually you would use this widget as an [AppBar] inside a [Scaffold].
|
/// Usually you would use this widget as an [AppBar] inside a [Scaffold].
|
||||||
@@ -52,9 +50,14 @@ import 'stream_channel.dart';
|
|||||||
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property.
|
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property.
|
||||||
/// Modify it to change the widget appearance.
|
/// Modify it to change the widget appearance.
|
||||||
class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
|
class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
|
||||||
|
/// True if this header shows the leading back button
|
||||||
final bool showBackButton;
|
final bool showBackButton;
|
||||||
|
|
||||||
|
/// Callback to call when pressing the back button.
|
||||||
|
/// By default it calls [Navigator.pop]
|
||||||
final VoidCallback onBackPressed;
|
final VoidCallback onBackPressed;
|
||||||
|
|
||||||
|
/// Creates a channel header
|
||||||
ChannelHeader({
|
ChannelHeader({
|
||||||
Key key,
|
Key key,
|
||||||
this.showBackButton = true,
|
this.showBackButton = true,
|
||||||
|
|||||||
@@ -3,6 +3,45 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
|
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
///
|
||||||
|
/// It shows the current [Channel] image.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// class MyApp extends StatelessWidget {
|
||||||
|
/// final Client client;
|
||||||
|
/// final Channel channel;
|
||||||
|
///
|
||||||
|
/// MyApp(this.client, this.channel);
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// Widget build(BuildContext context) {
|
||||||
|
/// return MaterialApp(
|
||||||
|
/// debugShowCheckedModeBanner: false,
|
||||||
|
/// home: StreamChat(
|
||||||
|
/// client: client,
|
||||||
|
/// child: StreamChannel(
|
||||||
|
/// channel: channel,
|
||||||
|
/// child: Center(
|
||||||
|
/// child: ChannelImage(
|
||||||
|
/// channel: channel,
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The widget uses a [StreamBuilder] to render the channel information image as soon as it updates.
|
||||||
|
///
|
||||||
|
/// By default the widget radius size is 40x40 pixels.
|
||||||
|
/// Set the property [size] to set a custom dimension.
|
||||||
|
///
|
||||||
|
/// The widget renders the ui based on the first ancestor of type [StreamChatTheme].
|
||||||
|
/// Modify it to change the widget appearance.
|
||||||
class ChannelImage extends StatelessWidget {
|
class ChannelImage extends StatelessWidget {
|
||||||
const ChannelImage({
|
const ChannelImage({
|
||||||
Key key,
|
Key key,
|
||||||
@@ -10,7 +49,10 @@ class ChannelImage extends StatelessWidget {
|
|||||||
this.size = 40,
|
this.size = 40,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// The channel to show the image of
|
||||||
final Channel channel;
|
final Channel channel;
|
||||||
|
|
||||||
|
/// The diameter of the image
|
||||||
final double size;
|
final double size;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -6,9 +6,45 @@ import 'channel_preview.dart';
|
|||||||
import 'stream_channel.dart';
|
import 'stream_channel.dart';
|
||||||
import 'stream_chat.dart';
|
import 'stream_chat.dart';
|
||||||
|
|
||||||
|
/// Callback called when tapping on a channel
|
||||||
typedef ChannelTapCallback = void Function(Channel, Widget);
|
typedef ChannelTapCallback = void Function(Channel, Widget);
|
||||||
|
|
||||||
|
/// Builder used to create a custom [ChannelPreview] from a [Channel]
|
||||||
typedef ChannelPreviewBuilder = Widget Function(BuildContext, Channel);
|
typedef ChannelPreviewBuilder = Widget Function(BuildContext, Channel);
|
||||||
|
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
///
|
||||||
|
/// It shows the list of current channels.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// 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(),
|
||||||
|
/// ),
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Make sure to have a [StreamChat] ancestor in order to provide the information about the channels.
|
||||||
|
/// The widget uses a [ListView.custom] to render the list of channels.
|
||||||
|
///
|
||||||
|
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme].
|
||||||
|
/// Modify it to change the widget appearance.
|
||||||
class ChannelListView extends StatefulWidget {
|
class ChannelListView extends StatefulWidget {
|
||||||
ChannelListView({
|
ChannelListView({
|
||||||
Key key,
|
Key key,
|
||||||
@@ -21,12 +57,38 @@ class ChannelListView extends StatefulWidget {
|
|||||||
this.channelPreviewBuilder,
|
this.channelPreviewBuilder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// The query filters to use.
|
||||||
|
/// You can query on any of the custom fields you've defined on the [Channel].
|
||||||
|
/// You can also filter other built-in channel fields.
|
||||||
final Map<String, dynamic> filter;
|
final Map<String, dynamic> filter;
|
||||||
|
|
||||||
|
/// Query channels options.
|
||||||
|
///
|
||||||
|
/// state: if true returns the Channel state
|
||||||
|
/// watch: if true listen to changes to this Channel in real time.
|
||||||
final Map<String, dynamic> options;
|
final Map<String, dynamic> options;
|
||||||
|
|
||||||
|
/// The sorting used for the channels matching the filters.
|
||||||
|
/// Sorting is based on field and direction, multiple sorting options can be provided.
|
||||||
|
/// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count.
|
||||||
|
/// Direction can be ascending or descending.
|
||||||
final List<SortOption> sort;
|
final List<SortOption> sort;
|
||||||
|
|
||||||
|
/// Pagination parameters
|
||||||
|
/// limit: the number of channels to return (max is 30)
|
||||||
|
/// offset: the offset (max is 1000)
|
||||||
|
/// message_limit: how many messages should be included to each channel
|
||||||
final PaginationParams pagination;
|
final PaginationParams pagination;
|
||||||
|
|
||||||
|
/// Function called when tapping on a channel
|
||||||
|
/// By default it calls [Navigator.push] building a [MaterialPageRoute]
|
||||||
|
/// with the widget [channelWidget] as child.
|
||||||
final ChannelTapCallback onChannelTap;
|
final ChannelTapCallback onChannelTap;
|
||||||
|
|
||||||
|
/// Widget used when opening a channel
|
||||||
final Widget channelWidget;
|
final Widget channelWidget;
|
||||||
|
|
||||||
|
/// Builder used to create a custom channel preview
|
||||||
final ChannelPreviewBuilder channelPreviewBuilder;
|
final ChannelPreviewBuilder channelPreviewBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.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 {
|
class ChannelName extends StatelessWidget {
|
||||||
const ChannelName({
|
const ChannelName({
|
||||||
Key key,
|
Key key,
|
||||||
@@ -8,7 +11,10 @@ class ChannelName extends StatelessWidget {
|
|||||||
this.textStyle,
|
this.textStyle,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// The channel to show the name of
|
||||||
final Channel channel;
|
final Channel channel;
|
||||||
|
|
||||||
|
/// The style of the text displayed
|
||||||
final TextStyle textStyle;
|
final TextStyle textStyle;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -6,8 +6,22 @@ import 'package:stream_chat/stream_chat.dart';
|
|||||||
import '../stream_chat_flutter.dart';
|
import '../stream_chat_flutter.dart';
|
||||||
import 'channel_name.dart';
|
import 'channel_name.dart';
|
||||||
|
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
///
|
||||||
|
/// It shows the current [Channel] preview.
|
||||||
|
///
|
||||||
|
/// The widget uses a [StreamBuilder] to render the channel information image as soon as it updates.
|
||||||
|
///
|
||||||
|
/// Usually you don't use this widget as it's the default channel preview used by [ChannelListView].
|
||||||
|
///
|
||||||
|
/// The widget renders the ui based on the first ancestor of type [StreamChatTheme].
|
||||||
|
/// Modify it to change the widget appearance.
|
||||||
class ChannelPreview extends StatelessWidget {
|
class ChannelPreview extends StatelessWidget {
|
||||||
|
/// Function called when tapping this widget
|
||||||
final void Function(Channel) onTap;
|
final void Function(Channel) onTap;
|
||||||
|
|
||||||
|
/// Channel displayed
|
||||||
final Channel channel;
|
final Channel channel;
|
||||||
|
|
||||||
ChannelPreview({
|
ChannelPreview({
|
||||||
|
|||||||
@@ -5,10 +5,51 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/message_list_view.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||||
|
|
||||||
import 'stream_channel.dart';
|
import 'stream_channel.dart';
|
||||||
|
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
///
|
||||||
|
/// Widget used to enter the message and add attachments
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// class ChannelPage extends StatelessWidget {
|
||||||
|
/// const ChannelPage({
|
||||||
|
/// Key key,
|
||||||
|
/// }) : super(key: key);
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// Widget build(BuildContext context) {
|
||||||
|
/// return Scaffold(
|
||||||
|
/// appBar: ChannelHeader(),
|
||||||
|
/// body: Column(
|
||||||
|
/// children: <Widget>[
|
||||||
|
/// Expanded(
|
||||||
|
/// child: MessageListView(
|
||||||
|
/// threadBuilder: (_, parentMessage) {
|
||||||
|
/// return ThreadPage(
|
||||||
|
/// parent: parentMessage,
|
||||||
|
/// );
|
||||||
|
/// },
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// MessageInput(),
|
||||||
|
/// ],
|
||||||
|
/// ),
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// You usually put this widget in the same page of a [MessageListView] as the bottom widget.
|
||||||
|
///
|
||||||
|
/// The widget renders the ui based on the first ancestor of type [StreamChatTheme].
|
||||||
|
/// Modify it to change the widget appearance.
|
||||||
class MessageInput extends StatefulWidget {
|
class MessageInput extends StatefulWidget {
|
||||||
MessageInput({
|
MessageInput({
|
||||||
Key key,
|
Key key,
|
||||||
@@ -16,7 +57,10 @@ class MessageInput extends StatefulWidget {
|
|||||||
this.parentMessage,
|
this.parentMessage,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// Function called after sending the message
|
||||||
final void Function(Message) onMessageSent;
|
final void Function(Message) onMessageSent;
|
||||||
|
|
||||||
|
/// Parent message in case of a thread
|
||||||
final Message parentMessage;
|
final Message parentMessage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -13,6 +13,46 @@ typedef ParentMessageBuilder = Widget Function(BuildContext, Message);
|
|||||||
typedef ThreadBuilder = Widget Function(BuildContext context, Message parent);
|
typedef ThreadBuilder = Widget Function(BuildContext context, Message parent);
|
||||||
typedef ThreadTapCallback = void Function(Message, Widget);
|
typedef ThreadTapCallback = void Function(Message, Widget);
|
||||||
|
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
///
|
||||||
|
/// It shows the list of messages of the current channel.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// class ChannelPage extends StatelessWidget {
|
||||||
|
/// const ChannelPage({
|
||||||
|
/// Key key,
|
||||||
|
/// }) : super(key: key);
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// Widget build(BuildContext context) {
|
||||||
|
/// return Scaffold(
|
||||||
|
/// appBar: ChannelHeader(),
|
||||||
|
/// body: Column(
|
||||||
|
/// children: <Widget>[
|
||||||
|
/// Expanded(
|
||||||
|
/// child: MessageListView(
|
||||||
|
/// threadBuilder: (_, parentMessage) {
|
||||||
|
/// return ThreadPage(
|
||||||
|
/// parent: parentMessage,
|
||||||
|
/// );
|
||||||
|
/// },
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// MessageInput(),
|
||||||
|
/// ],
|
||||||
|
/// ),
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Make sure to have a [StreamChannel] ancestor in order to provide the information about the channels.
|
||||||
|
/// The widget uses a [ListView.custom] to render the list of channels.
|
||||||
|
///
|
||||||
|
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme].
|
||||||
|
/// Modify it to change the widget appearance.
|
||||||
class MessageListView extends StatefulWidget {
|
class MessageListView extends StatefulWidget {
|
||||||
MessageListView({
|
MessageListView({
|
||||||
Key key,
|
Key key,
|
||||||
@@ -23,10 +63,20 @@ class MessageListView extends StatefulWidget {
|
|||||||
this.onThreadTap,
|
this.onThreadTap,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// Function used to build a custom message widget
|
||||||
final MessageBuilder messageBuilder;
|
final MessageBuilder messageBuilder;
|
||||||
|
|
||||||
|
/// Function used to build a custom parent message widget
|
||||||
final ParentMessageBuilder parentMessageBuilder;
|
final ParentMessageBuilder parentMessageBuilder;
|
||||||
|
|
||||||
|
/// Function used to build a custom thread widget
|
||||||
final ThreadBuilder threadBuilder;
|
final ThreadBuilder threadBuilder;
|
||||||
|
|
||||||
|
/// Function called when tapping on a thread
|
||||||
|
/// By default it calls [Navigator.push] using the widget built using [threadBuilder]
|
||||||
final ThreadTapCallback onThreadTap;
|
final ThreadTapCallback onThreadTap;
|
||||||
|
|
||||||
|
/// Parent message in case of a thread
|
||||||
final Message parentMessage;
|
final Message parentMessage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/message_list_view.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_channel.dart';
|
import 'package:stream_chat_flutter/src/stream_channel.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||||
import 'package:stream_chat_flutter/src/user_avatar.dart';
|
import 'package:stream_chat_flutter/src/user_avatar.dart';
|
||||||
@@ -16,6 +17,15 @@ import 'package:video_player/video_player.dart';
|
|||||||
|
|
||||||
import 'stream_chat.dart';
|
import 'stream_chat.dart';
|
||||||
|
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
///
|
||||||
|
/// It shows a message with reactions, replies and user avatar.
|
||||||
|
///
|
||||||
|
/// Usually you don't use this widget as it's the default message widget used by [MessageListView].
|
||||||
|
///
|
||||||
|
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme].
|
||||||
|
/// Modify it to change the widget appearance.
|
||||||
class MessageWidget extends StatefulWidget {
|
class MessageWidget extends StatefulWidget {
|
||||||
const MessageWidget({
|
const MessageWidget({
|
||||||
Key key,
|
Key key,
|
||||||
@@ -26,10 +36,19 @@ class MessageWidget extends StatefulWidget {
|
|||||||
this.isParent = false,
|
this.isParent = false,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final Message previousMessage;
|
/// This message
|
||||||
final Message message;
|
final Message message;
|
||||||
|
|
||||||
|
/// The previous message
|
||||||
|
final Message previousMessage;
|
||||||
|
|
||||||
|
/// The next message
|
||||||
final Message nextMessage;
|
final Message nextMessage;
|
||||||
|
|
||||||
|
/// The function called when tapping on replies
|
||||||
final void Function(Message) onThreadTap;
|
final void Function(Message) onThreadTap;
|
||||||
|
|
||||||
|
/// True if this is the parent of the thread being showed
|
||||||
final bool isParent;
|
final bool isParent;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
|
|
||||||
|
/// Widget used to provide information about the channel to the widget tree
|
||||||
|
///
|
||||||
|
/// Use [StreamChannel.of] to get the current [StreamChannelState] instance.
|
||||||
class StreamChannel extends StatefulWidget {
|
class StreamChannel extends StatefulWidget {
|
||||||
StreamChannel({
|
StreamChannel({
|
||||||
Key key,
|
Key key,
|
||||||
@@ -16,6 +19,7 @@ class StreamChannel extends StatefulWidget {
|
|||||||
final Widget child;
|
final Widget child;
|
||||||
final Channel channel;
|
final Channel channel;
|
||||||
|
|
||||||
|
/// Use this method to get the current [StreamChannelState] instance
|
||||||
static StreamChannelState of(BuildContext context) {
|
static StreamChannelState of(BuildContext context) {
|
||||||
StreamChannelState streamChannelState;
|
StreamChannelState streamChannelState;
|
||||||
|
|
||||||
@@ -34,17 +38,19 @@ class StreamChannel extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class StreamChannelState extends State<StreamChannel> {
|
class StreamChannelState extends State<StreamChannel> {
|
||||||
StreamChannelState();
|
/// Current channel
|
||||||
|
|
||||||
Channel get channel => widget.channel;
|
Channel get channel => widget.channel;
|
||||||
|
|
||||||
|
/// Current channel state stream
|
||||||
Stream<ChannelState> get channelStateStream =>
|
Stream<ChannelState> get channelStateStream =>
|
||||||
widget.channel.state.channelStateStream;
|
widget.channel.state.channelStateStream;
|
||||||
|
|
||||||
final BehaviorSubject<bool> _queryMessageController = BehaviorSubject();
|
final BehaviorSubject<bool> _queryMessageController = BehaviorSubject();
|
||||||
|
|
||||||
|
/// The stream notifying the state of queryMessage call
|
||||||
Stream<bool> get queryMessage => _queryMessageController.stream;
|
Stream<bool> get queryMessage => _queryMessageController.stream;
|
||||||
|
|
||||||
|
/// Calls [channel.query] updating [queryMessage] stream
|
||||||
void queryMessages() {
|
void queryMessages() {
|
||||||
_queryMessageController.add(true);
|
_queryMessageController.add(true);
|
||||||
|
|
||||||
@@ -67,6 +73,7 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calls [channel.getReplies] updating [queryMessage] stream
|
||||||
Future<void> getReplies(String parentId) async {
|
Future<void> getReplies(String parentId) async {
|
||||||
_queryMessageController.add(true);
|
_queryMessageController.add(true);
|
||||||
print('PARENT $parentId');
|
print('PARENT $parentId');
|
||||||
|
|||||||
@@ -6,6 +6,27 @@ import 'package:rxdart/rxdart.dart';
|
|||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||||
|
|
||||||
|
/// Widget used to provide information about the chat to the widget tree
|
||||||
|
///
|
||||||
|
/// class MyApp extends StatelessWidget {
|
||||||
|
/// final Client client;
|
||||||
|
///
|
||||||
|
/// MyApp(this.client);
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// Widget build(BuildContext context) {
|
||||||
|
/// return MaterialApp(
|
||||||
|
/// home: Container(
|
||||||
|
/// child: StreamChat(
|
||||||
|
/// client: client,
|
||||||
|
/// child: ChannelListPage(),
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// Use [StreamChat.of] to get the current [StreamChatState] instance.
|
||||||
class StreamChat extends StatefulWidget {
|
class StreamChat extends StatefulWidget {
|
||||||
final Client client;
|
final Client client;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@@ -23,6 +44,7 @@ class StreamChat extends StatefulWidget {
|
|||||||
@override
|
@override
|
||||||
StreamChatState createState() => StreamChatState();
|
StreamChatState createState() => StreamChatState();
|
||||||
|
|
||||||
|
/// Use this method to get the current [StreamChatState] instance
|
||||||
static StreamChatState of(BuildContext context) {
|
static StreamChatState of(BuildContext context) {
|
||||||
StreamChatState streamChatState;
|
StreamChatState streamChatState;
|
||||||
|
|
||||||
@@ -162,22 +184,28 @@ class StreamChatState extends State<StreamChat> {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The current user
|
||||||
User get user => widget.client.state.user;
|
User get user => widget.client.state.user;
|
||||||
|
|
||||||
|
/// The current user as a stream
|
||||||
Stream<User> get userStream => widget.client.state.userStream;
|
Stream<User> get userStream => widget.client.state.userStream;
|
||||||
|
|
||||||
|
/// The current channel list
|
||||||
|
final List<Channel> channels = [];
|
||||||
|
|
||||||
|
/// The current channel list as a stream
|
||||||
Stream<List<Channel>> get channelsStream => _channelsController.stream;
|
Stream<List<Channel>> get channelsStream => _channelsController.stream;
|
||||||
|
|
||||||
final BehaviorSubject<List<Channel>> _channelsController = BehaviorSubject();
|
final BehaviorSubject<List<Channel>> _channelsController = BehaviorSubject();
|
||||||
|
|
||||||
final List<Channel> channels = [];
|
|
||||||
|
|
||||||
final BehaviorSubject<bool> _queryChannelsLoadingController =
|
final BehaviorSubject<bool> _queryChannelsLoadingController =
|
||||||
BehaviorSubject.seeded(false);
|
BehaviorSubject.seeded(false);
|
||||||
|
|
||||||
|
/// The stream notifying the state of queryChannel call
|
||||||
Stream<bool> get queryChannelsLoading =>
|
Stream<bool> get queryChannelsLoading =>
|
||||||
_queryChannelsLoadingController.stream;
|
_queryChannelsLoadingController.stream;
|
||||||
|
|
||||||
|
/// Calls [client.queryChannels] updating [queryChannelsLoading] stream
|
||||||
Future<void> queryChannels({
|
Future<void> queryChannels({
|
||||||
Map<String, dynamic> filter,
|
Map<String, dynamic> filter,
|
||||||
List<SortOption> sortOptions,
|
List<SortOption> sortOptions,
|
||||||
@@ -204,6 +232,7 @@ class StreamChatState extends State<StreamChat> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clear the current channel list
|
||||||
void clearChannels() {
|
void clearChannels() {
|
||||||
channels.clear();
|
channels.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/channel_header.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/channel_preview.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/message_input.dart';
|
||||||
|
|
||||||
|
/// Inherited widget providing the [StreamChatThemeData] to the widget tree
|
||||||
class StreamChatTheme extends InheritedWidget {
|
class StreamChatTheme extends InheritedWidget {
|
||||||
final StreamChatThemeData data;
|
final StreamChatThemeData data;
|
||||||
|
|
||||||
@@ -17,20 +21,36 @@ class StreamChatTheme extends InheritedWidget {
|
|||||||
return data != old.data;
|
return data != old.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use this method to get the current [StreamChatThemeData] instance
|
||||||
static StreamChatThemeData of(BuildContext context) {
|
static StreamChatThemeData of(BuildContext context) {
|
||||||
return context.dependOnInheritedWidgetOfExactType<StreamChatTheme>().data;
|
return context.dependOnInheritedWidgetOfExactType<StreamChatTheme>().data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Theme data
|
||||||
class StreamChatThemeData {
|
class StreamChatThemeData {
|
||||||
|
/// Primary color of the chat widgets
|
||||||
final Color primaryColor;
|
final Color primaryColor;
|
||||||
|
|
||||||
|
/// Secondary color of the chat widgets
|
||||||
final Color secondaryColor;
|
final Color secondaryColor;
|
||||||
|
|
||||||
|
/// Accent color of the chat widgets
|
||||||
final Color accentColor;
|
final Color accentColor;
|
||||||
|
|
||||||
|
/// Theme of the [ChannelPreview]
|
||||||
final ChannelPreviewTheme channelPreviewTheme;
|
final ChannelPreviewTheme channelPreviewTheme;
|
||||||
|
|
||||||
|
/// Theme of the chat widgets dedicated to a channel
|
||||||
final ChannelTheme channelTheme;
|
final ChannelTheme channelTheme;
|
||||||
|
|
||||||
|
/// Theme of the current user messages
|
||||||
final MessageTheme ownMessageTheme;
|
final MessageTheme ownMessageTheme;
|
||||||
|
|
||||||
|
/// Theme of other users messages
|
||||||
final MessageTheme otherMessageTheme;
|
final MessageTheme otherMessageTheme;
|
||||||
|
|
||||||
|
/// Create a theme from scratch
|
||||||
StreamChatThemeData({
|
StreamChatThemeData({
|
||||||
this.primaryColor,
|
this.primaryColor,
|
||||||
this.secondaryColor,
|
this.secondaryColor,
|
||||||
@@ -41,6 +61,7 @@ class StreamChatThemeData {
|
|||||||
this.ownMessageTheme,
|
this.ownMessageTheme,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Create a theme from a Material [Theme]
|
||||||
factory StreamChatThemeData.fromTheme(ThemeData theme) {
|
factory StreamChatThemeData.fromTheme(ThemeData theme) {
|
||||||
final defaultTheme = getDefaultTheme(theme);
|
final defaultTheme = getDefaultTheme(theme);
|
||||||
|
|
||||||
@@ -67,6 +88,7 @@ class StreamChatThemeData {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a copy of [StreamChatThemeData] with specified attributes overridden.
|
||||||
StreamChatThemeData copyWith({
|
StreamChatThemeData copyWith({
|
||||||
Color primaryColor,
|
Color primaryColor,
|
||||||
Color secondaryColor,
|
Color secondaryColor,
|
||||||
@@ -141,6 +163,7 @@ class StreamChatThemeData {
|
|||||||
this.otherMessageTheme,
|
this.otherMessageTheme,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Get the default Stream Chat theme
|
||||||
static StreamChatThemeData getDefaultTheme(ThemeData theme) {
|
static StreamChatThemeData getDefaultTheme(ThemeData theme) {
|
||||||
final accentColor = Color(0xff006cff);
|
final accentColor = Color(0xff006cff);
|
||||||
return StreamChatThemeData(
|
return StreamChatThemeData(
|
||||||
@@ -245,11 +268,21 @@ class StreamChatThemeData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Channel theme data
|
||||||
class ChannelTheme {
|
class ChannelTheme {
|
||||||
|
/// Theme of the [ChannelHeader] widget
|
||||||
final ChannelHeaderTheme channelHeaderTheme;
|
final ChannelHeaderTheme channelHeaderTheme;
|
||||||
|
|
||||||
|
/// IconTheme of the send button in [MessageInput]
|
||||||
final IconThemeData messageInputButtonIconTheme;
|
final IconThemeData messageInputButtonIconTheme;
|
||||||
|
|
||||||
|
/// Theme of the send button in [MessageInput]
|
||||||
final ButtonThemeData messageInputButtonTheme;
|
final ButtonThemeData messageInputButtonTheme;
|
||||||
|
|
||||||
|
/// Gradient of [MessageInput]
|
||||||
final Gradient inputGradient;
|
final Gradient inputGradient;
|
||||||
|
|
||||||
|
/// Background color of [MessageInput]
|
||||||
final Color inputBackground;
|
final Color inputBackground;
|
||||||
|
|
||||||
ChannelTheme({
|
ChannelTheme({
|
||||||
@@ -260,6 +293,7 @@ class ChannelTheme {
|
|||||||
this.inputGradient,
|
this.inputGradient,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Creates a copy of [ChannelTheme] with specified attributes overridden.
|
||||||
ChannelTheme copyWith({
|
ChannelTheme copyWith({
|
||||||
ChannelHeaderTheme channelHeaderTheme,
|
ChannelHeaderTheme channelHeaderTheme,
|
||||||
IconThemeData messageInputButtonIconTheme,
|
IconThemeData messageInputButtonIconTheme,
|
||||||
|
|||||||
@@ -2,9 +2,64 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||||
|
|
||||||
|
/// 
|
||||||
|
/// 
|
||||||
|
///
|
||||||
|
/// It shows the current thread information.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// class ThreadPage extends StatelessWidget {
|
||||||
|
/// final Message parent;
|
||||||
|
///
|
||||||
|
/// ThreadPage({
|
||||||
|
/// Key key,
|
||||||
|
/// this.parent,
|
||||||
|
/// }) : super(key: key);
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// Widget build(BuildContext context) {
|
||||||
|
/// return Scaffold(
|
||||||
|
/// appBar: ThreadHeader(
|
||||||
|
/// parent: parent,
|
||||||
|
/// ),
|
||||||
|
/// body: Column(
|
||||||
|
/// children: <Widget>[
|
||||||
|
/// Expanded(
|
||||||
|
/// child: MessageListView(
|
||||||
|
/// parentMessage: parent,
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// MessageInput(
|
||||||
|
/// parentMessage: parent,
|
||||||
|
/// ),
|
||||||
|
/// ],
|
||||||
|
/// ),
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Usually you would use this widget as an [AppBar] inside a [Scaffold].
|
||||||
|
/// However you can also use it as a normal widget.
|
||||||
|
///
|
||||||
|
/// Make sure to have a [StreamChannel] ancestor in order to provide the information about the channel.
|
||||||
|
/// Every part of the widget uses a [StreamBuilder] to render the channel information as soon as it updates.
|
||||||
|
///
|
||||||
|
/// By default the widget shows a backButton that calls [Navigator.pop].
|
||||||
|
/// You can disable this button using the [showBackButton] property of just override the behaviour
|
||||||
|
/// with [onBackPressed].
|
||||||
|
///
|
||||||
|
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property.
|
||||||
|
/// Modify it to change the widget appearance.
|
||||||
class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
|
class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
|
||||||
|
/// True if this header shows the leading back button
|
||||||
final bool showBackButton;
|
final bool showBackButton;
|
||||||
|
|
||||||
|
/// Callback to call when pressing the back button.
|
||||||
|
/// By default it calls [Navigator.pop]
|
||||||
final VoidCallback onBackPressed;
|
final VoidCallback onBackPressed;
|
||||||
|
|
||||||
|
/// The message parent of this thread
|
||||||
final Message parent;
|
final Message parent;
|
||||||
|
|
||||||
ThreadHeader({
|
ThreadHeader({
|
||||||
|
|||||||
@@ -30,9 +30,15 @@ class UserAvatar extends StatelessWidget {
|
|||||||
imageUrl: user.extraData['image'],
|
imageUrl: user.extraData['image'],
|
||||||
errorWidget: (_, __, ___) {
|
errorWidget: (_, __, ___) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(user.extraData?.containsKey('name') ?? false
|
child: Text(
|
||||||
? user.extraData['name'][0]
|
user.extraData?.containsKey('name') ?? false
|
||||||
: ''),
|
? user.extraData['name'][0]
|
||||||
|
: '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
|
|||||||
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 209 KiB |
|
After Width: | Height: | Size: 294 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 337 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 10 KiB |