Merge remote-tracking branch 'origin/develop' into v7.0.0
# Conflicts: # packages/stream_chat/CHANGELOG.md # packages/stream_chat/lib/version.dart # packages/stream_chat/pubspec.yaml # packages/stream_chat_flutter/CHANGELOG.md # packages/stream_chat_flutter/lib/src/channel/channel_preview.dart # packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart # packages/stream_chat_flutter/lib/src/user/user_item.dart # packages/stream_chat_flutter/pubspec.yaml # packages/stream_chat_flutter_core/CHANGELOG.md # packages/stream_chat_flutter_core/pubspec.yaml # packages/stream_chat_localizations/CHANGELOG.md # packages/stream_chat_localizations/pubspec.yaml # packages/stream_chat_persistence/CHANGELOG.md # packages/stream_chat_persistence/pubspec.yaml
This commit is contained in:
@@ -1,3 +1,18 @@
|
||||
## 6.8.0
|
||||
|
||||
🐞 Fixed
|
||||
|
||||
- Fixed `Channel.query` not initializing `ChannelState`.
|
||||
|
||||
✅ Added
|
||||
|
||||
- Added support for `channel.countUnreadMentions()` to get the count of unread messages mentioning the current user on a
|
||||
channel. [#1692](https://github.com/GetStream/stream-chat-flutter/issues/1692)
|
||||
|
||||
🔄 Changed
|
||||
|
||||
- Updated minimum supported `SDK` version to Dart 3.0
|
||||
|
||||
## 7.0.0-beta.2
|
||||
|
||||
- Included the changes from version [6.7.0](#670).
|
||||
|
||||
@@ -1339,26 +1339,6 @@ class Channel {
|
||||
return _client.markChannelRead(id!, type, messageId: messageId);
|
||||
}
|
||||
|
||||
/// Loads the initial channel state and watches for changes.
|
||||
Future<ChannelState> watch({bool presence = false}) async {
|
||||
ChannelState response;
|
||||
|
||||
try {
|
||||
response = await query(watch: true, presence: presence);
|
||||
} catch (error, stackTrace) {
|
||||
if (!_initializedCompleter.isCompleted) {
|
||||
_initializedCompleter.completeError(error, stackTrace);
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
|
||||
if (state == null) {
|
||||
_initState(response);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void _initState(ChannelState channelState) {
|
||||
state = ChannelClientState(this, channelState);
|
||||
|
||||
@@ -1370,6 +1350,22 @@ class Channel {
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads the initial channel state and watches for changes.
|
||||
Future<ChannelState> watch({
|
||||
bool presence = false,
|
||||
PaginationParams? messagesPagination,
|
||||
PaginationParams? membersPagination,
|
||||
PaginationParams? watchersPagination,
|
||||
}) {
|
||||
return query(
|
||||
watch: true,
|
||||
presence: presence,
|
||||
messagesPagination: messagesPagination,
|
||||
membersPagination: membersPagination,
|
||||
watchersPagination: watchersPagination,
|
||||
);
|
||||
}
|
||||
|
||||
/// Stop watching the channel.
|
||||
Future<EmptyResponse> stopWatching() async {
|
||||
_checkInitialized();
|
||||
@@ -1435,7 +1431,7 @@ class Channel {
|
||||
);
|
||||
|
||||
/// Creates a new channel.
|
||||
Future<ChannelState> create() async => query(state: false);
|
||||
Future<ChannelState> create() => query(state: false);
|
||||
|
||||
/// Query the API, get messages, members or other channel fields.
|
||||
///
|
||||
@@ -1450,23 +1446,28 @@ class Channel {
|
||||
PaginationParams? watchersPagination,
|
||||
bool preferOffline = false,
|
||||
}) async {
|
||||
if (preferOffline && cid != null) {
|
||||
final updatedState = await _client.chatPersistenceClient
|
||||
?.getChannelStateByCid(cid!, messagePagination: messagesPagination);
|
||||
if (updatedState != null &&
|
||||
updatedState.messages != null &&
|
||||
updatedState.messages!.isNotEmpty) {
|
||||
if (this.state == null) {
|
||||
_initState(updatedState);
|
||||
} else {
|
||||
this.state?.updateChannelState(updatedState);
|
||||
}
|
||||
return updatedState;
|
||||
}
|
||||
}
|
||||
ChannelState? channelState;
|
||||
|
||||
try {
|
||||
final updatedState = await _client.queryChannel(
|
||||
// If we prefer offline, we first try to get the channel state from the
|
||||
// offline storage.
|
||||
if (preferOffline && !watch && cid != null) {
|
||||
final persistenceClient = _client.chatPersistenceClient;
|
||||
if (persistenceClient != null) {
|
||||
final cachedState = await persistenceClient.getChannelStateByCid(
|
||||
cid!,
|
||||
messagePagination: messagesPagination,
|
||||
);
|
||||
|
||||
// If the cached state contains messages, we can use it.
|
||||
if (cachedState.messages?.isNotEmpty == true) {
|
||||
channelState = cachedState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we still don't have the channelState, we try to get it from the API.
|
||||
channelState ??= await _client.queryChannel(
|
||||
type,
|
||||
channelId: id,
|
||||
channelData: _extraData,
|
||||
@@ -1479,18 +1480,35 @@ class Channel {
|
||||
);
|
||||
|
||||
if (_id == null) {
|
||||
_id = updatedState.channel!.id;
|
||||
_cid = updatedState.channel!.cid;
|
||||
_id = channelState.channel!.id;
|
||||
_cid = channelState.channel!.cid;
|
||||
}
|
||||
|
||||
this.state?.updateChannelState(updatedState);
|
||||
return updatedState;
|
||||
} catch (e) {
|
||||
if (_client.persistenceEnabled) {
|
||||
return _client.chatPersistenceClient!.getChannelStateByCid(
|
||||
cid!,
|
||||
messagePagination: messagesPagination,
|
||||
);
|
||||
// Initialize the channel state if it's not initialized yet.
|
||||
if (this.state == null) {
|
||||
_initState(channelState);
|
||||
} else {
|
||||
// Otherwise, update the channel state.
|
||||
this.state?.updateChannelState(channelState);
|
||||
}
|
||||
|
||||
return channelState;
|
||||
} catch (e, stk) {
|
||||
// If we failed to get the channel state from the API and we were not
|
||||
// supposed to watch the channel, we will try to get the channel state
|
||||
// from the offline storage.
|
||||
if (watch == false) {
|
||||
if (_client.persistenceEnabled) {
|
||||
return _client.chatPersistenceClient!.getChannelStateByCid(
|
||||
cid!,
|
||||
messagePagination: messagesPagination,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we will just rethrow the error.
|
||||
if (!_initializedCompleter.isCompleted) {
|
||||
_initializedCompleter.completeError(e, stk);
|
||||
}
|
||||
|
||||
rethrow;
|
||||
@@ -2334,6 +2352,26 @@ class ChannelClientState {
|
||||
!isThreadMessage;
|
||||
}
|
||||
|
||||
/// Counts the number of unread messages mentioning the current user.
|
||||
///
|
||||
/// **NOTE**: The method relies on the [Channel.messages] list and doesn't do
|
||||
/// any API call. Therefore, the count might be not reliable as it relies on
|
||||
/// the local data.
|
||||
int countUnreadMentions() {
|
||||
final lastRead = currentUserRead?.lastRead;
|
||||
final userId = _channel.client.state.currentUser?.id;
|
||||
|
||||
var count = 0;
|
||||
for (final message in messages) {
|
||||
if (_countMessageAsUnread(message) &&
|
||||
(lastRead == null || message.createdAt.isAfter(lastRead)) &&
|
||||
message.mentionedUsers.any((user) => user.id == userId) == true) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Update threads with updated information about messages.
|
||||
void updateThreadInfo(String parentId, List<Message> messages) {
|
||||
final newThreads = Map<String, List<Message>>.from(threads);
|
||||
|
||||
@@ -1685,7 +1685,7 @@ class ClientState {
|
||||
void updateUsers(List<User?> userList) {
|
||||
final newUsers = {
|
||||
...users,
|
||||
for (var user in userList)
|
||||
for (final user in userList)
|
||||
if (user != null) user.id: user,
|
||||
};
|
||||
_usersController.add(newUsers);
|
||||
|
||||
@@ -11,11 +11,11 @@ environment:
|
||||
dependencies:
|
||||
async: ^2.11.0
|
||||
collection: ^1.17.1
|
||||
dio: ^5.2.1+1
|
||||
dio: ^5.3.2
|
||||
equatable: ^2.0.5
|
||||
freezed_annotation: ^2.4.1
|
||||
http_parser: ^4.0.2
|
||||
jose: ^0.3.3
|
||||
jose: ^0.3.4
|
||||
json_annotation: ^4.8.1
|
||||
logging: ^1.2.0
|
||||
meta: ^1.9.1
|
||||
@@ -28,7 +28,7 @@ dependencies:
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.6
|
||||
freezed: ^2.4.1
|
||||
freezed: ^2.4.2
|
||||
json_serializable: ^6.7.1
|
||||
mocktail: ^0.3.0
|
||||
test: ^1.24.4
|
||||
mocktail: ^1.0.0
|
||||
test: ^1.24.6
|
||||
|
||||
@@ -975,7 +975,7 @@ void main() {
|
||||
// skipping initial seed event -> {} users
|
||||
client.state.usersStream.skip(1),
|
||||
emitsInOrder([
|
||||
{for (var user in users) user.id: user},
|
||||
{for (final user in users) user.id: user},
|
||||
]),
|
||||
);
|
||||
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
// ignore_for_file: invalid_use_of_protected_member
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:stream_chat/src/core/http/interceptor/additional_headers_interceptor.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// ignore_for_file: invalid_use_of_protected_member
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:stream_chat/src/core/http/interceptor/auth_interceptor.dart';
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
// ignore_for_file: invalid_use_of_protected_member
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:stream_chat/src/core/http/connection_id_manager.dart';
|
||||
|
||||
Reference in New Issue
Block a user