This commit is contained in:
Salvatore Giordano
2020-03-02 15:59:16 +01:00
parent 08d5b21e4e
commit a0a81c90f9
29 changed files with 381 additions and 10 deletions
+5 -2
View File
@@ -14,7 +14,6 @@ import 'stream_channel.dart';
/// It shows the current [Channel] information.
///
/// ```dart
///
/// class MyApp extends StatelessWidget {
/// final Client client;
/// final Channel channel;
@@ -36,7 +35,6 @@ import 'stream_channel.dart';
/// );
/// }
/// }
///
/// ```
///
/// 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.
/// Modify it to change the widget appearance.
class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
/// True if this header shows the leading back button
final bool showBackButton;
/// Callback to call when pressing the back button.
/// By default it calls [Navigator.pop]
final VoidCallback onBackPressed;
/// Creates a channel header
ChannelHeader({
Key key,
this.showBackButton = true,
+42
View File
@@ -3,6 +3,45 @@ import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_image.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_image_paint.png)
///
/// 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 {
const ChannelImage({
Key key,
@@ -10,7 +49,10 @@ class ChannelImage extends StatelessWidget {
this.size = 40,
}) : super(key: key);
/// The channel to show the image of
final Channel channel;
/// The diameter of the image
final double size;
@override
+62
View File
@@ -6,9 +6,45 @@ import 'channel_preview.dart';
import 'stream_channel.dart';
import 'stream_chat.dart';
/// Callback called when tapping on a channel
typedef ChannelTapCallback = void Function(Channel, Widget);
/// Builder used to create a custom [ChannelPreview] from a [Channel]
typedef ChannelPreviewBuilder = Widget Function(BuildContext, Channel);
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_list_view.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_list_view_paint.png)
///
/// 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 {
ChannelListView({
Key key,
@@ -21,12 +57,38 @@ class ChannelListView extends StatefulWidget {
this.channelPreviewBuilder,
}) : 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// Widget used when opening a channel
final Widget channelWidget;
/// Builder used to create a custom channel preview
final ChannelPreviewBuilder channelPreviewBuilder;
@override
+6
View File
@@ -1,6 +1,9 @@
import 'package:flutter/material.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 {
const ChannelName({
Key key,
@@ -8,7 +11,10 @@ class ChannelName extends StatelessWidget {
this.textStyle,
}) : super(key: key);
/// The channel to show the name of
final Channel channel;
/// The style of the text displayed
final TextStyle textStyle;
@override
+14
View File
@@ -6,8 +6,22 @@ import 'package:stream_chat/stream_chat.dart';
import '../stream_chat_flutter.dart';
import 'channel_name.dart';
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_preview.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_preview_paint.png)
///
/// 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 {
/// Function called when tapping this widget
final void Function(Channel) onTap;
/// Channel displayed
final Channel channel;
ChannelPreview({
+44
View File
@@ -5,10 +5,51 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.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 'stream_channel.dart';
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_input.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_input_paint.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_input2.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_input2_paint.png)
///
/// 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 {
MessageInput({
Key key,
@@ -16,7 +57,10 @@ class MessageInput extends StatefulWidget {
this.parentMessage,
}) : super(key: key);
/// Function called after sending the message
final void Function(Message) onMessageSent;
/// Parent message in case of a thread
final Message parentMessage;
@override
+50
View File
@@ -13,6 +13,46 @@ typedef ParentMessageBuilder = Widget Function(BuildContext, Message);
typedef ThreadBuilder = Widget Function(BuildContext context, Message parent);
typedef ThreadTapCallback = void Function(Message, Widget);
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_listview.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_listview_paint.png)
///
/// 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 {
MessageListView({
Key key,
@@ -23,10 +63,20 @@ class MessageListView extends StatefulWidget {
this.onThreadTap,
}) : super(key: key);
/// Function used to build a custom message widget
final MessageBuilder messageBuilder;
/// Function used to build a custom parent message widget
final ParentMessageBuilder parentMessageBuilder;
/// Function used to build a custom thread widget
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;
/// Parent message in case of a thread
final Message parentMessage;
@override
+20 -1
View File
@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_markdown/flutter_markdown.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_chat_theme.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';
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_widget.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_widget_paint.png)
///
/// 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 {
const MessageWidget({
Key key,
@@ -26,10 +36,19 @@ class MessageWidget extends StatefulWidget {
this.isParent = false,
}) : super(key: key);
final Message previousMessage;
/// This message
final Message message;
/// The previous message
final Message previousMessage;
/// The next message
final Message nextMessage;
/// The function called when tapping on replies
final void Function(Message) onThreadTap;
/// True if this is the parent of the thread being showed
final bool isParent;
@override
+9 -2
View File
@@ -4,6 +4,9 @@ import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.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 {
StreamChannel({
Key key,
@@ -16,6 +19,7 @@ class StreamChannel extends StatefulWidget {
final Widget child;
final Channel channel;
/// Use this method to get the current [StreamChannelState] instance
static StreamChannelState of(BuildContext context) {
StreamChannelState streamChannelState;
@@ -34,17 +38,19 @@ class StreamChannel extends StatefulWidget {
}
class StreamChannelState extends State<StreamChannel> {
StreamChannelState();
/// Current channel
Channel get channel => widget.channel;
/// Current channel state stream
Stream<ChannelState> get channelStateStream =>
widget.channel.state.channelStateStream;
final BehaviorSubject<bool> _queryMessageController = BehaviorSubject();
/// The stream notifying the state of queryMessage call
Stream<bool> get queryMessage => _queryMessageController.stream;
/// Calls [channel.query] updating [queryMessage] stream
void queryMessages() {
_queryMessageController.add(true);
@@ -67,6 +73,7 @@ class StreamChannelState extends State<StreamChannel> {
});
}
/// Calls [channel.getReplies] updating [queryMessage] stream
Future<void> getReplies(String parentId) async {
_queryMessageController.add(true);
print('PARENT $parentId');
+31 -2
View File
@@ -6,6 +6,27 @@ import 'package:rxdart/rxdart.dart';
import 'package:stream_chat/stream_chat.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 {
final Client client;
final Widget child;
@@ -23,6 +44,7 @@ class StreamChat extends StatefulWidget {
@override
StreamChatState createState() => StreamChatState();
/// Use this method to get the current [StreamChatState] instance
static StreamChatState of(BuildContext context) {
StreamChatState streamChatState;
@@ -162,22 +184,28 @@ class StreamChatState extends State<StreamChat> {
}));
}
/// The current user
User get user => widget.client.state.user;
/// The current user as a stream
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;
final BehaviorSubject<List<Channel>> _channelsController = BehaviorSubject();
final List<Channel> channels = [];
final BehaviorSubject<bool> _queryChannelsLoadingController =
BehaviorSubject.seeded(false);
/// The stream notifying the state of queryChannel call
Stream<bool> get queryChannelsLoading =>
_queryChannelsLoadingController.stream;
/// Calls [client.queryChannels] updating [queryChannelsLoading] stream
Future<void> queryChannels({
Map<String, dynamic> filter,
List<SortOption> sortOptions,
@@ -204,6 +232,7 @@ class StreamChatState extends State<StreamChat> {
}
}
/// Clear the current channel list
void clearChannels() {
channels.clear();
}
+34
View File
@@ -1,5 +1,9 @@
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 {
final StreamChatThemeData data;
@@ -17,20 +21,36 @@ class StreamChatTheme extends InheritedWidget {
return data != old.data;
}
/// Use this method to get the current [StreamChatThemeData] instance
static StreamChatThemeData of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<StreamChatTheme>().data;
}
}
/// Theme data
class StreamChatThemeData {
/// Primary color of the chat widgets
final Color primaryColor;
/// Secondary color of the chat widgets
final Color secondaryColor;
/// Accent color of the chat widgets
final Color accentColor;
/// Theme of the [ChannelPreview]
final ChannelPreviewTheme channelPreviewTheme;
/// Theme of the chat widgets dedicated to a channel
final ChannelTheme channelTheme;
/// Theme of the current user messages
final MessageTheme ownMessageTheme;
/// Theme of other users messages
final MessageTheme otherMessageTheme;
/// Create a theme from scratch
StreamChatThemeData({
this.primaryColor,
this.secondaryColor,
@@ -41,6 +61,7 @@ class StreamChatThemeData {
this.ownMessageTheme,
});
/// Create a theme from a Material [Theme]
factory StreamChatThemeData.fromTheme(ThemeData theme) {
final defaultTheme = getDefaultTheme(theme);
@@ -67,6 +88,7 @@ class StreamChatThemeData {
);
}
/// Creates a copy of [StreamChatThemeData] with specified attributes overridden.
StreamChatThemeData copyWith({
Color primaryColor,
Color secondaryColor,
@@ -141,6 +163,7 @@ class StreamChatThemeData {
this.otherMessageTheme,
);
/// Get the default Stream Chat theme
static StreamChatThemeData getDefaultTheme(ThemeData theme) {
final accentColor = Color(0xff006cff);
return StreamChatThemeData(
@@ -245,11 +268,21 @@ class StreamChatThemeData {
}
}
/// Channel theme data
class ChannelTheme {
/// Theme of the [ChannelHeader] widget
final ChannelHeaderTheme channelHeaderTheme;
/// IconTheme of the send button in [MessageInput]
final IconThemeData messageInputButtonIconTheme;
/// Theme of the send button in [MessageInput]
final ButtonThemeData messageInputButtonTheme;
/// Gradient of [MessageInput]
final Gradient inputGradient;
/// Background color of [MessageInput]
final Color inputBackground;
ChannelTheme({
@@ -260,6 +293,7 @@ class ChannelTheme {
this.inputGradient,
});
/// Creates a copy of [ChannelTheme] with specified attributes overridden.
ChannelTheme copyWith({
ChannelHeaderTheme channelHeaderTheme,
IconThemeData messageInputButtonIconTheme,
+55
View File
@@ -2,9 +2,64 @@ import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/thread_header.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/thread_header_paint.png)
///
/// 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 {
/// True if this header shows the leading back button
final bool showBackButton;
/// Callback to call when pressing the back button.
/// By default it calls [Navigator.pop]
final VoidCallback onBackPressed;
/// The message parent of this thread
final Message parent;
ThreadHeader({
+9 -3
View File
@@ -30,9 +30,15 @@ class UserAvatar extends StatelessWidget {
imageUrl: user.extraData['image'],
errorWidget: (_, __, ___) {
return Center(
child: Text(user.extraData?.containsKey('name') ?? false
? user.extraData['name'][0]
: ''),
child: Text(
user.extraData?.containsKey('name') ?? false
? user.extraData['name'][0]
: '',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
);
},
fit: BoxFit.cover,
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB