diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index e05599e1..430b0c36 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,3 +1,9 @@ +## Upcoming + +🐞 Fixed + +- [#563](https://github.com/GetStream/stream-chat-flutter/issues/563): `Channel.stopWatching()` not working + ## 2.0.0 🛑️ Breaking Changes from `1.5.3` @@ -619,4 +625,4 @@ ## 0.0.2 -- first beta version \ No newline at end of file +- first beta version diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 89e4ac44..16e65fa7 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,9 +1,14 @@ ## Upcoming -✅ Added +✅ Added +- Added `MessageListView.paginationLimit` - Allow the various ListView widgets to be themed via ThemeData classes +🐞 Fixed + +- Fix floating date divider not having a fixed size + ## 2.0.0 🛑️ Breaking Changes from `1.5.4` diff --git a/packages/stream_chat_flutter/example/android/app/build.gradle b/packages/stream_chat_flutter/example/android/app/build.gradle index 9bb36eac..fbd6268e 100644 --- a/packages/stream_chat_flutter/example/android/app/build.gradle +++ b/packages/stream_chat_flutter/example/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 29 + compileSdkVersion 30 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -41,7 +41,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" minSdkVersion 21 - targetSdkVersion 29 + targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/packages/stream_chat_flutter/example/android/build.gradle b/packages/stream_chat_flutter/example/android/build.gradle index 9afae7f8..3e0873de 100644 --- a/packages/stream_chat_flutter/example/android/build.gradle +++ b/packages/stream_chat_flutter/example/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.5.20' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.2' + classpath 'com.android.tools.build:gradle:4.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/packages/stream_chat_flutter/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/stream_chat_flutter/example/android/gradle/wrapper/gradle-wrapper.properties index 493072b3..3df6b338 100644 --- a/packages/stream_chat_flutter/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/stream_chat_flutter/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip diff --git a/packages/stream_chat_flutter/lib/src/message_list_view.dart b/packages/stream_chat_flutter/lib/src/message_list_view.dart index 55421a2e..11d651b8 100644 --- a/packages/stream_chat_flutter/lib/src/message_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/message_list_view.dart @@ -166,11 +166,23 @@ class MessageListView extends StatefulWidget { this.showFloatingDateDivider = true, this.threadSeparatorBuilder, this.messageListController, + this.reverse = true, + this.paginationLimit = 20, }) : super(key: key); /// Function used to build a custom message widget final MessageBuilder? messageBuilder; + /// Whether the view scrolls in the reading direction. + /// + /// Defaults to true. + /// + /// See [ScrollView.reverse]. + final bool reverse; + + /// Limit used during pagination + final int paginationLimit; + /// Function used to build a custom system message widget final SystemMessageBuilder? systemMessageBuilder; @@ -329,6 +341,7 @@ class _MessageListViewState extends State { @override Widget build(BuildContext context) => MessageListCore( + paginationLimit: widget.paginationLimit, messageFilter: widget.messageFilter, loadingBuilder: widget.loadingBuilder ?? (context) => const Center( @@ -446,7 +459,7 @@ class _MessageListViewState extends State { initialAlignment: initialAlignment ?? 0, physics: widget.scrollPhysics, itemScrollController: _scrollController, - reverse: true, + reverse: widget.reverse, addAutomaticKeepAlives: false, itemCount: itemCount, @@ -622,7 +635,8 @@ class _MessageListViewState extends State { } Positioned _buildFloatingDateDivider(int itemCount) => Positioned( - top: 20, + top: widget.reverse ? 20 : null, + bottom: widget.reverse ? null : 20, left: 0, right: 0, child: BetterStreamBuilder>( @@ -656,7 +670,9 @@ class _MessageListViewState extends State { ); Future _paginateData( - StreamChannelState? channel, QueryDirection direction) => + StreamChannelState? channel, + QueryDirection direction, + ) => _messageListController.paginateData!(direction: direction); int? _getTopElementIndex(Iterable values) { @@ -716,9 +732,13 @@ class _MessageListViewState extends State { ); } }, - child: StreamSvgIcon.down( - color: _streamTheme.colorTheme.textHighEmphasis, - ), + child: widget.reverse + ? StreamSvgIcon.down( + color: _streamTheme.colorTheme.textHighEmphasis, + ) + : StreamSvgIcon.up( + color: _streamTheme.colorTheme.textHighEmphasis, + ), ), if (showUnreadCount) Positioned( diff --git a/packages/stream_chat_flutter/lib/src/stream_svg_icon.dart b/packages/stream_chat_flutter/lib/src/stream_svg_icon.dart index fb5017e1..73c33131 100644 --- a/packages/stream_chat_flutter/lib/src/stream_svg_icon.dart +++ b/packages/stream_chat_flutter/lib/src/stream_svg_icon.dart @@ -37,6 +37,18 @@ class StreamSvgIcon extends StatelessWidget { height: size, ); + /// [StreamSvgIcon] type + factory StreamSvgIcon.up({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'Icon_up.svg', + color: color, + width: size, + height: size, + ); + /// [StreamSvgIcon] type factory StreamSvgIcon.attach({ double? size, diff --git a/packages/stream_chat_flutter/lib/svgs/Icon_up.svg b/packages/stream_chat_flutter/lib/svgs/Icon_up.svg new file mode 100644 index 00000000..60e6888f --- /dev/null +++ b/packages/stream_chat_flutter/lib/svgs/Icon_up.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/stream_chat_flutter/pubspec.yaml b/packages/stream_chat_flutter/pubspec.yaml index 6b9aeedc..391ddfdd 100644 --- a/packages/stream_chat_flutter/pubspec.yaml +++ b/packages/stream_chat_flutter/pubspec.yaml @@ -31,7 +31,7 @@ dependencies: lottie: ^1.0.1 meta: ^1.3.0 path_provider: ^2.0.1 - photo_manager: ^1.1.6 + photo_manager: ^1.2.6+1 photo_view: ^0.12.0 rxdart: ^0.27.0 scrollable_positioned_list: ^0.2.0-nullsafety.0 diff --git a/packages/stream_chat_flutter_core/CHANGELOG.md b/packages/stream_chat_flutter_core/CHANGELOG.md index 2f7abfe2..a823a0db 100644 --- a/packages/stream_chat_flutter_core/CHANGELOG.md +++ b/packages/stream_chat_flutter_core/CHANGELOG.md @@ -1,3 +1,8 @@ +## Upcoming + +✅ Added +- Added `MessageListCore.paginationLimit` + ## 2.0.0 🛑️ Breaking Changes from `1.5.3` diff --git a/packages/stream_chat_flutter_core/lib/src/message_list_core.dart b/packages/stream_chat_flutter_core/lib/src/message_list_core.dart index dc90cc91..4acf0ba7 100644 --- a/packages/stream_chat_flutter_core/lib/src/message_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/message_list_core.dart @@ -71,6 +71,7 @@ class MessageListCore extends StatefulWidget { this.parentMessage, this.messageListController, this.messageFilter, + this.paginationLimit = 20, }) : super(key: key); /// A [MessageListController] allows pagination. @@ -86,6 +87,9 @@ class MessageListCore extends StatefulWidget { /// Function used to build an empty widget final WidgetBuilder emptyBuilder; + /// Limit used to paginate messages + final int paginationLimit; + /// Callback triggered when an error occurs while performing the given /// request. /// @@ -163,13 +167,20 @@ class MessageListCoreState extends State { /// Fetches more messages with updated pagination and updates the widget. /// /// Optionally pass the fetch direction, defaults to [QueryDirection.top] + /// Optionally pass a limit, defaults to 20 Future paginateData({ QueryDirection direction = QueryDirection.top, }) { if (!_isThreadConversation) { - return _streamChannel!.queryMessages(direction: direction); + return _streamChannel!.queryMessages( + direction: direction, + limit: widget.paginationLimit, + ); } else { - return _streamChannel!.getReplies(widget.parentMessage!.id); + return _streamChannel!.getReplies( + widget.parentMessage!.id, + limit: widget.paginationLimit, + ); } } @@ -179,7 +190,10 @@ class MessageListCoreState extends State { if (newStreamChannel != _streamChannel) { if (_streamChannel == null /*only first time*/ && _isThreadConversation) { - newStreamChannel.getReplies(widget.parentMessage!.id); + newStreamChannel.getReplies( + widget.parentMessage!.id, + limit: widget.paginationLimit, + ); } _streamChannel = newStreamChannel; } @@ -197,7 +211,10 @@ class MessageListCoreState extends State { if (widget.parentMessage?.id != widget.parentMessage?.id) { if (_isThreadConversation) { - _streamChannel!.getReplies(widget.parentMessage!.id); + _streamChannel!.getReplies( + widget.parentMessage!.id, + limit: widget.paginationLimit, + ); } } } diff --git a/packages/stream_chat_flutter_core/lib/src/stream_channel.dart b/packages/stream_chat_flutter_core/lib/src/stream_channel.dart index 1dcf9c3c..fb7b79f2 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_channel.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_channel.dart @@ -147,9 +147,18 @@ class StreamChannelState extends State { } /// Calls [channel.query] updating [queryMessage] stream - Future queryMessages({QueryDirection? direction = QueryDirection.top}) { - if (direction == QueryDirection.top) return _queryTopMessages(); - return _queryBottomMessages(); + Future queryMessages({ + QueryDirection? direction = QueryDirection.top, + int limit = 20, + }) { + if (direction == QueryDirection.top) { + return _queryTopMessages( + limit: limit, + ); + } + return _queryBottomMessages( + limit: limit, + ); } /// Calls [channel.getReplies] updating [queryMessage] stream diff --git a/packages/stream_chat_flutter_core/test/message_list_core_test.dart b/packages/stream_chat_flutter_core/test/message_list_core_test.dart index b038411b..e61d0abb 100644 --- a/packages/stream_chat_flutter_core/test/message_list_core_test.dart +++ b/packages/stream_chat_flutter_core/test/message_list_core_test.dart @@ -151,7 +151,9 @@ void main() { (tester) async { const messageListCoreKey = Key('messageListCore'); final controller = MessageListController(); + const paginationLimit = 10; final messageListCore = MessageListCore( + paginationLimit: paginationLimit, key: messageListCoreKey, messageListBuilder: (_, __) => const Offstage(), loadingBuilder: (BuildContext context) => const Offstage(), @@ -165,10 +167,6 @@ void main() { final mockChannel = MockChannel(); when(() => mockChannel.state.isUpToDate).thenReturn(true); - // when(() => mockChannel.query( - // messagesPagination: any(named: 'messagesPagination'), - // preferOffline: any(named: 'preferOffline'), - // )).thenAnswer((_) => mockChannel.state); final messages = _generateMessages(); when(() => mockChannel.state.messages).thenReturn(messages); when(() => mockChannel.state.messagesStream) @@ -191,7 +189,10 @@ void main() { await coreState.paginateData(); verify(() => mockChannel.query( - messagesPagination: any(named: 'messagesPagination'), + messagesPagination: any( + named: 'messagesPagination', + that: wrapMatcher((it) => it.limit == paginationLimit), + ), preferOffline: any(named: 'preferOffline'), )).called(1); }, diff --git a/packages/stream_chat_persistence/test/src/dao/channel_query_dao_test.dart b/packages/stream_chat_persistence/test/src/dao/channel_query_dao_test.dart index 62a3df15..81e629b6 100644 --- a/packages/stream_chat_persistence/test/src/dao/channel_query_dao_test.dart +++ b/packages/stream_chat_persistence/test/src/dao/channel_query_dao_test.dart @@ -1,5 +1,3 @@ -import 'dart:math' as math; - import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_persistence/src/dao/channel_query_dao.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; @@ -84,9 +82,9 @@ void main() { cid: cids[index], createdBy: users[index], config: ChannelConfig(), - extraData: {'test_custom_field': math.Random().nextInt(100)}, + extraData: {'test_custom_field': 3 + index}, createdAt: now, - memberCount: math.Random().nextInt(100), + memberCount: 3 + index, lastMessageAt: now.add(Duration(hours: index)), ), ).reversed.toList(growable: false); @@ -99,6 +97,8 @@ void main() { } group('getChannels', () { + tearDown(() async => database.flush()); + final filter = Filter.in_('members', const ['testUserId']); test('should return empty list of channels', () async {