diff --git a/CHANGELOG.md b/CHANGELOG.md index 327807a8..fe2e26db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,17 @@ -## 0.2.18 +## 0.2.20 - Implement shadowban +## 0.2.19 + +- Updated llc dependency +- Added loading builder in channellistview +- Added sendButtonLocation and animationduration to messageinput + +## 0.2.18 + +- Updated llc dependency + ## 0.2.17+2 - Expose ChannelsBloc.channelsComparator to sort channels on message.new event diff --git a/lib/src/channel_list_view.dart b/lib/src/channel_list_view.dart index 33988b92..51c02611 100644 --- a/lib/src/channel_list_view.dart +++ b/lib/src/channel_list_view.dart @@ -65,6 +65,7 @@ class ChannelListView extends StatefulWidget { this.errorBuilder, this.emptyBuilder, this.onImageTap, + this.loadingBuilder, this.pullToRefresh = true, }) : super(key: key); @@ -79,6 +80,9 @@ class ChannelListView extends StatefulWidget { /// You can also filter other built-in channel fields. final Map filter; + /// The builder used while loading. + final WidgetBuilder loadingBuilder; + /// Query channels options. /// /// state: if true returns the Channel state @@ -224,9 +228,11 @@ class _ChannelListViewState extends State constraints: BoxConstraints( minHeight: viewportConstraints.maxHeight, ), - child: Center( - child: CircularProgressIndicator(), - ), + child: widget.loadingBuilder != null + ? widget.loadingBuilder(context) + : Center( + child: CircularProgressIndicator(), + ), ), ); }, @@ -339,6 +345,9 @@ class _ChannelListViewState extends State ), ); } else { + if (widget.loadingBuilder != null) { + return widget.loadingBuilder(context); + } return _buildQueryProgressIndicator(context, channelsProvider); } } diff --git a/lib/src/channels_bloc.dart b/lib/src/channels_bloc.dart index 59dd6335..0784cb30 100644 --- a/lib/src/channels_bloc.dart +++ b/lib/src/channels_bloc.dart @@ -89,29 +89,24 @@ class ChannelsBlocState extends State paginationParams.offset == null || paginationParams.offset == 0; final oldChannels = List.from(channels ?? []); - client - .queryChannels( + final _channels = await client.queryChannels( filter: filter, sort: sortOptions, options: options, paginationParams: paginationParams, onlyOffline: onlyOffline, - ) - .listen((channels) { - if (clear) { - _channelsController.add(channels); - } else { - final l = oldChannels + channels; - _channelsController.add(l); - } - }, onDone: () { - _queryChannelsLoadingController.sink.add(false); - }, onError: (err, stackTrace) { - print(err); - print(stackTrace); - _queryChannelsLoadingController.addError(err, stackTrace); - }); + ); + + if (clear) { + _channelsController.add(_channels); + } else { + final l = oldChannels + _channels; + _channelsController.add(l); + } + _queryChannelsLoadingController.sink.add(false); } catch (err, stackTrace) { + print(err); + print(stackTrace); _queryChannelsLoadingController.addError(err, stackTrace); } } diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index b30028e8..c8d089f1 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -27,6 +27,11 @@ enum ActionsLocation { right, } +enum SendButtonLocation { + inside, + outside, +} + enum DefaultAttachmentTypes { image, video, @@ -96,6 +101,8 @@ class MessageInput extends StatefulWidget { this.inputTextStyle, this.attachmentIconColor, this.autofocus = false, + this.sendButtonLocation = SendButtonLocation.inside, + this.animationDuration = const Duration(milliseconds: 300), }) : super(key: key); /// Message to edit @@ -141,6 +148,9 @@ class MessageInput extends StatefulWidget { /// The location of the custom actions final ActionsLocation actionsLocation; + /// The location of the send button + final SendButtonLocation sendButtonLocation; + /// Map that defines a thumbnail builder for an attachment type final Map attachmentThumbnailBuilders; @@ -148,6 +158,9 @@ class MessageInput extends StatefulWidget { /// `Theme.of(context).textTheme.bodyText2`. final TextStyle inputTextStyle; + /// The duration of the send button animation + final Duration animationDuration; + /// Color used for attachment icon. final Color attachmentIconColor; @@ -194,17 +207,26 @@ class MessageInputState extends State { }, child: Padding( padding: const EdgeInsets.all(8.0), - child: Stack( - clipBehavior: Clip.none, - children: [ - _buildBorder(context), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildAttachments(), - _buildTextField(context), - ], + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Stack( + clipBehavior: Clip.none, + children: [ + _buildBorder(context), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildAttachments(), + _buildTextField(context), + ], + ), + ], + ), ), + if (widget.sendButtonLocation == SendButtonLocation.outside) + _animateSendButton(context), ], ), ), @@ -221,14 +243,18 @@ class MessageInputState extends State { if (widget.actionsLocation == ActionsLocation.left) ...widget.actions ?? [], _buildTextInput(context), - _animateSendButton(context), if (widget.actionsLocation == ActionsLocation.right) ...widget.actions ?? [], + if (widget.sendButtonLocation == SendButtonLocation.inside) + _animateSendButton(context), ], ); } - AnimatedCrossFade _animateSendButton(BuildContext context) { + Widget _animateSendButton(BuildContext context) { + if (widget.animationDuration == Duration.zero) { + return _buildSendButton(context); + } return AnimatedCrossFade( crossFadeState: ((_messageIsPresent || _attachments.isNotEmpty) && _attachments.every((a) => a.uploaded == true)) @@ -236,7 +262,7 @@ class MessageInputState extends State { : CrossFadeState.showSecond, firstChild: _buildSendButton(context), secondChild: SizedBox(), - duration: Duration(milliseconds: 300), + duration: widget.animationDuration, alignment: Alignment.center, ); } @@ -851,12 +877,14 @@ class MessageInputState extends State { color: Colors.transparent, child: IconButton( key: Key('sendButton'), - onPressed: () { - sendMessage(); - }, + onPressed: (textEditingController.text.trim().isEmpty && + _attachments.isEmpty) + ? null + : () { + sendMessage(); + }, icon: Icon( Icons.send, - color: StreamChatTheme.of(context).accentColor, ), ), ), diff --git a/pubspec.yaml b/pubspec.yaml index a50abbf3..40053962 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. -version: 0.2.18 +version: 0.2.20 repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues @@ -23,7 +23,7 @@ dependencies: file_picker: ^2.0.12 image_picker: ^0.6.7+2 flutter_keyboard_visibility: ^4.0.1 - stream_chat: ^0.2.19 + stream_chat: ^0.2.21 mime: ^0.9.6+3 visibility_detector: ^0.1.5 http_parser: ^3.1.4