Merge remote-tracking branch 'origin/develop' into feat/localization
This commit is contained in:
@@ -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
|
||||
- first beta version
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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<MessageListView> {
|
||||
|
||||
@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<MessageListView> {
|
||||
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<MessageListView> {
|
||||
}
|
||||
|
||||
Positioned _buildFloatingDateDivider(int itemCount) => Positioned(
|
||||
top: 20,
|
||||
top: widget.reverse ? 20 : null,
|
||||
bottom: widget.reverse ? null : 20,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: BetterStreamBuilder<Iterable<ItemPosition>>(
|
||||
@@ -656,7 +670,9 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
);
|
||||
|
||||
Future<void> _paginateData(
|
||||
StreamChannelState? channel, QueryDirection direction) =>
|
||||
StreamChannelState? channel,
|
||||
QueryDirection direction,
|
||||
) =>
|
||||
_messageListController.paginateData!(direction: direction);
|
||||
|
||||
int? _getTopElementIndex(Iterable<ItemPosition> values) {
|
||||
@@ -716,9 +732,13 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
);
|
||||
}
|
||||
},
|
||||
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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path transform="translate(24, 24) rotate(-180)" d="M5.30605 8.30597C5.11052 8.50222 5.00073 8.76795 5.00073 9.04498C5.00073 9.322 5.11052 9.58774 5.30605 9.78398L11.2061 15.697C11.4321 15.923 11.7351 16.024 12.0291 16C12.17 16.0032 12.3102 15.9778 12.441 15.9252C12.5718 15.8726 12.6906 15.7939 12.7901 15.694L18.6941 9.78398C18.8898 9.58786 18.9998 9.32208 18.9998 9.04498C18.9998 8.76787 18.8898 8.50209 18.6941 8.30597C18.5972 8.20898 18.4821 8.13203 18.3555 8.07952C18.2289 8.02702 18.0931 8 17.9561 8C17.819 8 17.6832 8.02702 17.5566 8.07952C17.43 8.13203 17.3149 8.20898 17.2181 8.30597L11.9981 13.533L6.78005 8.30597C6.68327 8.20901 6.56831 8.13208 6.44176 8.07959C6.31521 8.0271 6.17956 8.00008 6.04255 8.00008C5.90555 8.00008 5.76989 8.0271 5.64334 8.07959C5.51679 8.13208 5.40184 8.20901 5.30505 8.30597H5.30605Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 943 B |
@@ -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
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
## Upcoming
|
||||
|
||||
✅ Added
|
||||
- Added `MessageListCore.paginationLimit`
|
||||
|
||||
## 2.0.0
|
||||
|
||||
🛑️ Breaking Changes from `1.5.3`
|
||||
|
||||
@@ -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<MessageListCore> {
|
||||
/// 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<void> 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<MessageListCore> {
|
||||
|
||||
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<MessageListCore> {
|
||||
|
||||
if (widget.parentMessage?.id != widget.parentMessage?.id) {
|
||||
if (_isThreadConversation) {
|
||||
_streamChannel!.getReplies(widget.parentMessage!.id);
|
||||
_streamChannel!.getReplies(
|
||||
widget.parentMessage!.id,
|
||||
limit: widget.paginationLimit,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,9 +147,18 @@ class StreamChannelState extends State<StreamChannel> {
|
||||
}
|
||||
|
||||
/// Calls [channel.query] updating [queryMessage] stream
|
||||
Future<void> queryMessages({QueryDirection? direction = QueryDirection.top}) {
|
||||
if (direction == QueryDirection.top) return _queryTopMessages();
|
||||
return _queryBottomMessages();
|
||||
Future<void> 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
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user