Merge branch 'develop'

This commit is contained in:
Salvatore Giordano
2022-06-20 16:35:19 +02:00
50 changed files with 923 additions and 605 deletions
@@ -7,6 +7,7 @@ env:
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
push:
branches:
- master
+1 -1
View File
@@ -82,7 +82,7 @@ To run a script, use `melos run <script name>`.
# How can I contribute?
Are you ready to dive into code? It's pretty easy to get up and running with your first Stream contribution. If this is your first time sending a PR to Stream, please read the above section on [local setup](https://www.notion.so/Stream-s-Contribution-Guide-e18e1d57295f4fa8836a115d3fa3d5e7) before continuing.
Are you ready to dive into code? It's pretty easy to get up and running with your first Stream contribution. If this is your first time sending a PR to Stream, please read the above section on [local setup](https://github.com/GetStream/stream-chat-flutter/blob/develop/CONTRIBUTING.md#local-setup) before continuing.
## Filing bugs 🐛
@@ -24,26 +24,22 @@ Make sure to check the [StreamUserListController](./stream_user_list_controller.
```dart
class UserListPage extends StatefulWidget {
const UserListPage({
Key? key,
required this.client,
}) : super(key: key);
final StreamChatClient client;
const UserListPage({Key? key}) : super(key: key);
@override
State<UserListPage> createState() => _UserListPageState();
}
class _UserListPageState extends State<UserListPage> {
late final _controller = StreamUserListController(
client: widget.client,
late final StreamUserListController _userListController =
StreamUserListController(
client: StreamChat.of(context).client,
limit: 25,
filter: Filter.and([
Filter.notEqual('id', StreamChat.of(context).currentUser!.id),
]),
filter: Filter.and(
[Filter.notEqual('id', StreamChat.of(context).currentUser!.id)],
),
sort: [
SortOption(
const SortOption(
'name',
direction: 1,
),
@@ -51,29 +47,14 @@ class _UserListPageState extends State<UserListPage> {
);
@override
void dispose() {
_controller.dispose();
super.dispose();
Widget build(BuildContext context) {
return RefreshIndicator(
onRefresh: () => _userListController.refresh(),
child: StreamUserListView(
controller: _userListController,
),
);
}
@override
Widget build(BuildContext context) => Scaffold(
body: RefreshIndicator(
onRefresh: _controller.refresh,
child: StreamChannelListView(
controller: _controller,
onChannelTap: (channel) => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => StreamChannel(
channel: channel,
child: const ChannelPage(),
),
),
),
),
),
);
}
```
@@ -89,3 +70,25 @@ StreamUsersListView(
},
),
```
### Selecting Users
The `StreamUserListView` widget allows selecting users in a list. The `defaultWidget` returned can be customized to indicate that it has been selected.
```dart
Set<User> _selectedUsers = {};
StreamUserListView(
controller: _userListController,
itemBuilder: (context, users, index, defaultWidget) {
return defaultWidget.copyWith(
selected: _selectedUsers.contains(users[index]),
);
},
onUserTap: (user) {
setState(() {
_selectedUsers.add(user);
});
},
);
```
+99 -66
View File
@@ -1,3 +1,11 @@
## 4.3.0
🐞 Fixed
- [[#1135]](https://github.com/GetStream/stream-chat-flutter/issues/1135) Persistence was not
removing the hidden channels.
- Fix `x-stream-client` header generation.
## 4.2.0
✅ Added
@@ -13,18 +21,20 @@
🔄 Changed
- Deprecated `PaginationParams.before` and `PaginationParams.after`. Use `PaginationParams.limit` instead.
- Deprecated `PaginationParams.before` and `PaginationParams.after`. Use `PaginationParams.limit`
instead.
🐞 Fixed
- [[#1147]](https://github.com/GetStream/stream-chat-flutter/issues/1147) `channel.unset` not updating the extra data
stream.
- [[#1147]](https://github.com/GetStream/stream-chat-flutter/issues/1147) `channel.unset` not
updating the extra data stream.
## 4.1.0
✅ Added
- Added support for extra data in attachment file uploader. Thanks, [@rlee1990](https://github.com/rlee1990).
- Added support for extra data in attachment file uploader.
Thanks, [@rlee1990](https://github.com/rlee1990).
🔄 Changed
@@ -49,14 +59,14 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🐞 Fixed
- Fixed reactions not working for threads in offline mode.
- [[#1046]](https://github.com/GetStream/stream-chat-flutter/issues/1046) After `/mute` command on reload cannot access
any channel.
- [[#1047]](https://github.com/GetStream/stream-chat-flutter/issues/1047) `own_capabilities` extraData missing after
channel update.
- [[#1046]](https://github.com/GetStream/stream-chat-flutter/issues/1046) After `/mute` command on
reload cannot access any channel.
- [[#1047]](https://github.com/GetStream/stream-chat-flutter/issues/1047) `own_capabilities`
extraData missing after channel update.
- [[#1054]](https://github.com/GetStream/stream-chat-flutter/issues/1054)
Fix `Unsupported operation: Cannot remove from an unmodifiable list`.
- [[#1033]](https://github.com/GetStream/stream-chat-flutter/issues/1033) Hard delete from dashboard does not delete
message from client.
- [[#1033]](https://github.com/GetStream/stream-chat-flutter/issues/1033) Hard delete from dashboard
does not delete message from client.
- Send only `user_id` while reconnecting.
✅ Added
@@ -78,21 +88,22 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🐞 Fixed
- [[#1081]](https://github.com/GetStream/stream-chat-flutter/issues/1081) Fixed a bug with user reconnection.
- [[#1081]](https://github.com/GetStream/stream-chat-flutter/issues/1081) Fixed a bug with user
reconnection.
## 3.6.0
🐞 Fixed
- Fixed reactions not working for threads in offline mode.
- [[#1046]](https://github.com/GetStream/stream-chat-flutter/issues/1046) After `/mute` command on reload cannot access
any channel.
- [[#1047]](https://github.com/GetStream/stream-chat-flutter/issues/1047) `own_capabilities` extraData missing after
channel update.
- [[#1046]](https://github.com/GetStream/stream-chat-flutter/issues/1046) After `/mute` command on
reload cannot access any channel.
- [[#1047]](https://github.com/GetStream/stream-chat-flutter/issues/1047) `own_capabilities`
extraData missing after channel update.
- [[#1054]](https://github.com/GetStream/stream-chat-flutter/issues/1054)
Fix `Unsupported operation: Cannot remove from an unmodifiable list`.
- [[#1033]](https://github.com/GetStream/stream-chat-flutter/issues/1033) Hard delete from dashboard does not delete
message from client.
- [[#1033]](https://github.com/GetStream/stream-chat-flutter/issues/1033) Hard delete from dashboard
does not delete message from client.
- Send only `user_id` while reconnecting.
✅ Added
@@ -116,24 +127,26 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🐞 Fixed
- [[#890]](https://github.com/GetStream/stream-chat-flutter/pull/890) Fixed Reactions not updating on thread messages.
Thanks [bstolinski](https://github.com/bstolinski).
- [[#897]](https://github.com/GetStream/stream-chat-flutter/issues/897) Fixed error type mis-match in `AuthInterceptor`.
- [[#891]](https://github.com/GetStream/stream-chat-flutter/pull/891) Fixed reply counter for parent message not
updating correctly after deleting thread message.
- [[#890]](https://github.com/GetStream/stream-chat-flutter/pull/890) Fixed Reactions not updating
on thread messages. Thanks [bstolinski](https://github.com/bstolinski).
- [[#897]](https://github.com/GetStream/stream-chat-flutter/issues/897) Fixed error type mis-match
in `AuthInterceptor`.
- [[#891]](https://github.com/GetStream/stream-chat-flutter/pull/891) Fixed reply counter for parent
message not updating correctly after deleting thread message.
- Fix `channelState.copyWith` with respect to pinnedMessages.
## 3.4.0
🐞 Fixed
- [[#857]](https://github.com/GetStream/stream-chat-flutter/issues/857) Channel now listens for member ban/unban and
updates the channel state with the latest data.
- [[#748]](https://github.com/GetStream/stream-chat-flutter/issues/748) `Message.user` is now also included while saving
users in persistence.
- [[#871]](https://github.com/GetStream/stream-chat-flutter/issues/871) Fixed thread message deletion.
- [[#846]](https://github.com/GetStream/stream-chat-flutter/issues/846) Fixed `message.ownReactions` getting truncated
when receiving a reaction event.
- [[#857]](https://github.com/GetStream/stream-chat-flutter/issues/857) Channel now listens for
member ban/unban and updates the channel state with the latest data.
- [[#748]](https://github.com/GetStream/stream-chat-flutter/issues/748) `Message.user` is now also
included while saving users in persistence.
- [[#871]](https://github.com/GetStream/stream-chat-flutter/issues/871) Fixed thread message
deletion.
- [[#846]](https://github.com/GetStream/stream-chat-flutter/issues/846) Fixed `message.ownReactions`
getting truncated when receiving a reaction event.
- Add check for invalid image URLs
- Fix `channelState.pinnedMessagesStream` getting reset to `0` after a channel update.
- Fixed `unreadCount` after removing user from a channel.
@@ -141,7 +154,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🔄 Changed
- `client.location` is now deprecated in favor of the
new [edge server](https://getstream.io/blog/chat-edge-infrastructure) and will be removed in v4.0.0.
new [edge server](https://getstream.io/blog/chat-edge-infrastructure) and will be removed in
v4.0.0.
- `channel.banUser`, `channel.unbanUser` is now deprecated in favor of the new `channel.banMember`
and `channel.unbanMember`. These deprecated methods will be removed in v4.0.0.
- Added `banExpires` property of type `DateTime` on the `Member`, `OwnUser`, and `User` models.
@@ -155,8 +169,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🐞 Fixed
- [[#799]](https://github.com/GetStream/stream-chat-flutter/issues/799) Fixed `totalUnreadCount` is not updating when
app is resumed from background mode.
- [[#799]](https://github.com/GetStream/stream-chat-flutter/issues/799) Fixed `totalUnreadCount` is
not updating when app is resumed from background mode.
- Fix retry mechanism failing in some cases.
## 3.3.0
@@ -171,7 +185,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
- `closeConnection()` now uses `normalClosure` status when closing websocket.
- Fixed local unread count indicator increasing for thread replies.
- Fixed user presence indicator not updating correctly.
- `ChannelEvent.membersCount` defaults to 0 avoiding parsing errors due to missing `members_count` field.
- `ChannelEvent.membersCount` defaults to 0 avoiding parsing errors due to missing `members_count`
field.
## 3.2.1
@@ -184,7 +199,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🐞 Fixed
- `markAllRead()` now updates local channel states.
- [[#744]](https://github.com/GetStream/stream-chat-flutter/issues/744) Fixed unread count not updating correctly
- [[#744]](https://github.com/GetStream/stream-chat-flutter/issues/744) Fixed unread count not
updating correctly
## 3.1.1
@@ -194,7 +210,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🐞 Fixed
- [[#710]](https://github.com/GetStream/stream-chat-flutter/issues/710) Fixed JWT requiring using `String` as id.
- [[#710]](https://github.com/GetStream/stream-chat-flutter/issues/710) Fixed JWT requiring
using `String` as id.
- Fixed expired CDN attachment links not updating correctly.
## 3.0.0
@@ -214,16 +231,19 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
- Added `Filter.contains` and `Filter.empty`
- Added support for `next`, `previous` value pagination in `client.search`
, [read more.](https://getstream.io/chat/docs/other-rest/search/#pagination)
- `Attachment` class now has a `fileSize` and `mimeType` property. Setting a `file` will also set the `file_size`
- `Attachment` class now has a `fileSize` and `mimeType` property. Setting a `file` will also set
the `file_size`
, `mime_type` key on `extraData`, so `attachment.fileSize`, `attachment.mimetype`
and `attachment.extraData['file_size']`
, `attachment.extraData['mime_type]` is same respectively.
🐞 Fixed
- [[#659]](https://github.com/GetStream/stream-chat-flutter/issues/659) Fixed unread count not updating correctly.
- [[#659]](https://github.com/GetStream/stream-chat-flutter/issues/659) Fixed unread count not
updating correctly.
- Fix `Filter.empty()` json encoding.
- [[#700]](https://github.com/GetStream/stream-chat-flutter/issues/700) Connecting user without providing `name`
- [[#700]](https://github.com/GetStream/stream-chat-flutter/issues/700) Connecting user without
providing `name`
uses `id` instead for setting `user.name`.
## 2.2.1
@@ -241,14 +261,14 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
✅ Added
- `User` and `OwnUser` classes now have an `image` property. Setting an image will also set the 'image' key
on `extraData`, so `user.image` and `user.extraData['image']` is the same.
- `User` and `OwnUser` classes now have a `name` property. Setting a name will also set the 'name' key on `extraData`,
so `user.name` and `user.extraData['name']` is the same.
- `Channel` class now has extra `image` getter and setter. As well as an `updateImage` to do a partial update after a
channel has been initialized.
- `Channel` class now has extra `name` getter and setter. As well as an `updateName` to do a partial update after a
channel has been initialized.
- `User` and `OwnUser` classes now have an `image` property. Setting an image will also set the '
image' key on `extraData`, so `user.image` and `user.extraData['image']` is the same.
- `User` and `OwnUser` classes now have a `name` property. Setting a name will also set the 'name'
key on `extraData`, so `user.name` and `user.extraData['name']` is the same.
- `Channel` class now has extra `image` getter and setter. As well as an `updateImage` to do a
partial update after a channel has been initialized.
- `Channel` class now has extra `name` getter and setter. As well as an `updateName` to do a partial
update after a channel has been initialized.
- Added slow mode which allows a cooldown period after a user sends a message.
## 2.1.1
@@ -261,7 +281,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🛑️ Removed
- The `MessageTranslation` class has been removed. Use the new `i18n` field in the `Message` class instead.
- The `MessageTranslation` class has been removed. Use the new `i18n` field in the `Message` class
instead.
✅ Added
@@ -275,7 +296,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🐞 Fixed
- [#563](https://github.com/GetStream/stream-chat-flutter/issues/563): `Channel.stopWatching()` not working
- [#563](https://github.com/GetStream/stream-chat-flutter/issues/563): `Channel.stopWatching()` not
working
- [#575](https://github.com/GetStream/stream-chat-flutter/issues/575): Wrong `OwnUser.*`
## 2.0.0
@@ -283,7 +305,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🛑️ Breaking Changes from `1.5.3`
- migrate this package to null safety
- `ConnectUserWithProvider` now requires `tokenProvider` as a required param. (Removed from the constructor)
- `ConnectUserWithProvider` now requires `tokenProvider` as a required param. (Removed from the
constructor)
- `client.disconnect()` is now divided into two different functions
- `client.closeConnection()` -> for closing user websocket connection.
- `client.disconnectUser()` -> for disconnecting user and resetting client state.
@@ -303,15 +326,16 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🐞 Fixed
- [#369](https://github.com/GetStream/stream-chat-flutter/issues/369): Client does not return without internet
connection
- [#369](https://github.com/GetStream/stream-chat-flutter/issues/369): Client does not return
without internet connection
- several minor fixes
- performance improvements
✅ Added
- New `Location` enum is introduced for easily changing the client location/baseUrl.
- New `client.openConnection()` and `client.closeConnection()` is introduced to connect/disconnect user ws connection.
- New `client.openConnection()` and `client.closeConnection()` is introduced to connect/disconnect
user ws connection.
- New `client.partialUpdateMessage` and `channel.partialUpdateMessage` methods
- `connectWebSocket` parameter in connect user calls to use the client in "connection-less" mode.
@@ -329,7 +353,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
🛑️ Breaking Changes from `2.0.0-nullsafety.6`
- `ConnectUserWithProvider` now requires `tokenProvider` as a required param. (Removed from the constructor)
- `ConnectUserWithProvider` now requires `tokenProvider` as a required param. (Removed from the
constructor)
- `client.disconnect()` is now divided into two different functions
- `client.closeConnection()` -> for closing user websocket connection.
- `client.disconnectUser()` -> for disconnecting user and resetting client state.
@@ -348,7 +373,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
✅ Added
- New `Location` enum is introduced for easily changing the client location/baseUrl.
- New `client.openConnection()` and `client.closeConnection()` is introduced to connect/disconnect user ws connection.
- New `client.openConnection()` and `client.closeConnection()` is introduced to connect/disconnect
user ws connection.
🔄 Changed
@@ -412,14 +438,16 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
- Save pinned messages in offline storage
- Minor fixes
- `StreamClient.QueryChannels` now returns a Stream and fetches the channels from storage before calling the api
- Added `StreamClient.QueryChannelsOnline` and `StreamClient.QueryChannelsOffline` to fetch channels only from online or
offline
- `StreamClient.QueryChannels` now returns a Stream and fetches the channels from storage before
calling the api
- Added `StreamClient.QueryChannelsOnline` and `StreamClient.QueryChannelsOffline` to fetch channels
only from online or offline
## 1.2.0-beta
- 🛑 **BREAKING** Changed signature of `StreamClient.search` method
- Added `pinMessage` feature [docs here](https://getstream.io/chat/docs/flutter-dart/pinned_messages/?language=dart)
- Added `pinMessage`
feature [docs here](https://getstream.io/chat/docs/flutter-dart/pinned_messages/?language=dart)
- Fixed minor bugs
## 1.1.0-beta
@@ -436,7 +464,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
## 1.0.2-beta
- Deprecated `setUser`, `setGuestUser`, `setUserWithProvider` in favor of `connectUser`, `connectGuestUser`
- Deprecated `setUser`, `setGuestUser`, `setUserWithProvider` in favor of `connectUser`
, `connectGuestUser`
, `connectUserWithProvider`
- Optimised reaction updates - i.e., Update first call Api later.
@@ -449,9 +478,11 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
- 🛑 **BREAKING** Renamed `Client` to less generic `StreamChatClient`
- 🛑 **BREAKING** Segregated the persistence layer into separate
package [stream_chat_persistence](https://pub.dev/packages/stream_chat_persistence)
- 🛑 **BREAKING** Moved `Client.backgroundKeepAlive` to [core package](https://pub.dev/packages/stream_chat_core)
- 🛑 **BREAKING** Moved `Client.showLocalNotification` to [core package](https://pub.dev/packages/stream_chat_core) and
renamed it to `StreamChatCore.onBackgroundEventReceived`
- 🛑 **BREAKING** Moved `Client.backgroundKeepAlive`
to [core package](https://pub.dev/packages/stream_chat_core)
- 🛑 **BREAKING** Moved `Client.showLocalNotification`
to [core package](https://pub.dev/packages/stream_chat_core) and renamed it
to `StreamChatCore.onBackgroundEventReceived`
- Removed `flutter` dependency. This is now a pure Dart package 🥳
- Minor improvements and bugfixes
@@ -475,7 +506,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
## 0.2.23+2
- Do not throw an error when calling queryChannels without an active connection if the offline storage is enabled
- Do not throw an error when calling queryChannels without an active connection if the offline
storage is enabled
## 0.2.23+1
@@ -506,8 +538,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
## 0.2.20
- Return offline data only if the backend is unreachable. This avoids the glitch of the ChannelListView because we
cannot sort by custom properties.
- Return offline data only if the backend is unreachable. This avoids the glitch of the
ChannelListView because we cannot sort by custom properties.
## 0.2.19
@@ -561,7 +593,8 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
## 0.2.12
- Do not save channels in memory if not being watched. This was leading to some bugs in some specific use-cases.
- Do not save channels in memory if not being watched. This was leading to some bugs in some
specific use-cases.
## 0.2.11
+14 -11
View File
@@ -98,7 +98,9 @@ class StreamChatClient {
tokenManager: _tokenManager,
handler: handleEvent,
logger: detachedLogger('🔌'),
queryParameters: {'X-Stream-Client': defaultUserAgent},
queryParameters: {
'X-Stream-Client': '$defaultUserAgent-$packageVersion',
},
);
_retryPolicy = retryPolicy ??
@@ -124,13 +126,15 @@ class StreamChatClient {
}
/// Default user agent for all requests
static String defaultUserAgent = 'stream-chat-dart-client-'
'${CurrentPlatform.name}-'
'${PACKAGE_VERSION.split('+')[0]}';
static String defaultUserAgent =
'stream-chat-dart-client-${CurrentPlatform.name}';
/// Additional headers for all requests
static Map<String, Object?> additionalHeaders = {};
/// The current package version
static const packageVersion = PACKAGE_VERSION;
ChatPersistenceClient? _originalChatPersistenceClient;
/// Chat persistence client
@@ -1489,13 +1493,12 @@ class ClientState {
}
void _listenChannelHidden() {
_subscriptions.add(_client.on(EventType.channelHidden).listen((event) {
final cid = event.cid;
if (cid != null) {
_client.chatPersistenceClient?.deleteChannels([cid]);
}
channels = channels..removeWhere((cid, ch) => cid == event.cid);
_subscriptions
.add(_client.on(EventType.channelHidden).listen((event) async {
final eventChannel = event.channel!;
await _client.chatPersistenceClient?.deleteChannels([eventChannel.cid]);
channels[eventChannel.cid]?.dispose();
channels = channels..remove(eventChannel.cid);
}));
}
@@ -8,7 +8,7 @@ import 'package:stream_chat/src/core/http/token_manager.dart';
/// Authentication interceptor that refreshes the token if
/// an auth error is received
class AuthInterceptor extends Interceptor {
class AuthInterceptor extends QueuedInterceptor {
/// Initialize a new auth interceptor
AuthInterceptor(this._client, this._tokenManager);
@@ -57,35 +57,10 @@ class AuthInterceptor extends Interceptor {
final error = ErrorResponse.fromJson(data);
if (error.code == ChatErrorCode.tokenExpired.code) {
if (_tokenManager.isStatic) return handler.next(err);
_client.lock();
await _tokenManager.loadToken(refresh: true);
_client.unlock();
try {
final options = err.requestOptions;
final response = await _client.request(
options.path,
cancelToken: options.cancelToken,
data: options.data,
onReceiveProgress: options.onReceiveProgress,
onSendProgress: options.onSendProgress,
queryParameters: options.queryParameters,
options: Options(
method: options.method,
sendTimeout: options.sendTimeout,
receiveTimeout: options.receiveTimeout,
extra: options.extra,
headers: options.headers,
responseType: options.responseType,
contentType: options.contentType,
validateStatus: options.validateStatus,
receiveDataWhenStatusError: options.receiveDataWhenStatusError,
followRedirects: options.followRedirects,
maxRedirects: options.maxRedirects,
requestEncoder: options.requestEncoder,
responseDecoder: options.responseDecoder,
listFormat: options.listFormat,
),
);
final response = await _client.fetch(options);
return handler.resolve(response);
} on DioError catch (error) {
return handler.next(error);
@@ -76,20 +76,6 @@ class StreamHttpClient {
@visibleForTesting
final Dio httpClient;
/// Lock the current [StreamHttpClient] instance.
///
/// [StreamHttpClient] will enqueue the incoming request tasks instead
/// send them directly when [interceptor.requestOptions] is locked.
void lock() => httpClient.lock();
/// Unlock the current [StreamHttpClient] instance.
///
/// [StreamHttpClient] instance dequeue the request task。
void unlock() => httpClient.unlock();
/// Clear the current [StreamHttpClient] instance waiting queue.
void clear() => httpClient.clear();
/// Shuts down the [StreamHttpClient].
///
/// If [force] is `false` the [StreamHttpClient] will be kept alive
@@ -280,4 +266,17 @@ class StreamHttpClient {
throw _parseError(error);
}
}
/// Handy method to make http requests from [RequestOptions]
/// with error parsing.
Future<Response<T>> fetch<T>(
RequestOptions requestOptions,
) async {
try {
final response = await httpClient.fetch<T>(requestOptions);
return response;
} on DioError catch (error) {
throw _parseError(error);
}
}
}
@@ -82,7 +82,7 @@ class User extends Equatable {
/// {@macro name}
@JsonKey(ignore: true)
String get name {
if (extraData.containsKey('name')) {
if (extraData.containsKey('name') && extraData['name'] != null) {
final name = extraData['name']! as String;
if (name.isNotEmpty) return name;
}
+1 -1
View File
@@ -3,4 +3,4 @@ import 'package:stream_chat/src/client/client.dart';
/// Current package version
/// Used in [StreamChatClient] to build the `x-stream-client` header
// ignore: constant_identifier_names
const PACKAGE_VERSION = '4.2.0';
const PACKAGE_VERSION = '4.3.0';
+1 -1
View File
@@ -1,7 +1,7 @@
name: stream_chat
homepage: https://getstream.io/
description: The official Dart client for Stream Chat, a service for building chat applications.
version: 4.2.0
version: 4.3.0
repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -2513,7 +2513,7 @@ void main() {
});
test(
'setting the `currentUser` should also compute and update the unreadCounts',
'''setting the `currentUser` should also compute and update the unreadCounts''',
() {
final state = client.state;
final initialUser = OwnUser.fromUser(user);
@@ -93,23 +93,11 @@ void main() {
when(() => tokenManager.isStatic).thenReturn(false);
when(() => client.lock()).thenReturn(() {});
final token = Token.development('test-user-id');
when(() => tokenManager.loadToken(refresh: true))
.thenAnswer((_) async => token);
when(() => client.unlock()).thenReturn(() {});
when(() => client.request(
path,
data: options.data,
onReceiveProgress: options.onReceiveProgress,
onSendProgress: options.onSendProgress,
queryParameters: options.queryParameters,
cancelToken: options.cancelToken,
options: any(named: 'options'),
)).thenAnswer((_) async => Response(
when(() => client.fetch(options)).thenAnswer((_) async => Response(
requestOptions: options,
statusCode: 200,
));
@@ -127,21 +115,10 @@ void main() {
verify(() => tokenManager.isStatic).called(1);
verify(() => client.lock()).called(1);
verify(() => tokenManager.loadToken(refresh: true)).called(1);
verifyNoMoreInteractions(tokenManager);
verify(() => client.unlock()).called(1);
verify(() => client.request(
path,
data: options.data,
onReceiveProgress: options.onReceiveProgress,
onSendProgress: options.onSendProgress,
queryParameters: options.queryParameters,
cancelToken: options.cancelToken,
options: any(named: 'options'),
)).called(1);
verify(() => client.fetch(options)).called(1);
verifyNoMoreInteractions(client);
});
@@ -163,23 +140,11 @@ void main() {
when(() => tokenManager.isStatic).thenReturn(false);
when(() => client.lock()).thenReturn(() {});
final token = Token.development('test-user-id');
when(() => tokenManager.loadToken(refresh: true))
.thenAnswer((_) async => token);
when(() => client.unlock()).thenReturn(() {});
when(() => client.request(
path,
data: options.data,
onReceiveProgress: options.onReceiveProgress,
onSendProgress: options.onSendProgress,
queryParameters: options.queryParameters,
cancelToken: options.cancelToken,
options: any(named: 'options'),
)).thenThrow(err);
when(() => client.fetch(options)).thenThrow(err);
authInterceptor.onError(err, handler);
@@ -193,21 +158,10 @@ void main() {
verify(() => tokenManager.isStatic).called(1);
verify(() => client.lock()).called(1);
verify(() => tokenManager.loadToken(refresh: true)).called(1);
verifyNoMoreInteractions(tokenManager);
verify(() => client.unlock()).called(1);
verify(() => client.request(
path,
data: options.data,
onReceiveProgress: options.onReceiveProgress,
onSendProgress: options.onSendProgress,
queryParameters: options.queryParameters,
cancelToken: options.cancelToken,
options: any(named: 'options'),
)).called(1);
verify(() => client.fetch(options)).called(1);
verifyNoMoreInteractions(client);
},
);
+159 -81
View File
@@ -1,45 +1,77 @@
## 4.3.0
- Updated `photo_view` dependency to [`0.14.0`](https://pub.dev/packages/photo_view/changelog).
🐞 Fixed
- [[#1180]](https://github.com/GetStream/stream-chat-flutter/issues/1180) Fix file download.
- Fix commands resetting the `StreamMessageInputController.value`.
- [[#996]](https://github.com/GetStream/stream-chat-flutter/issues/996) Videos break bottom photo
carousal.
- Fix: URLs with path and/or query params are not enriched.
- [[#1194]](https://github.com/GetStream/stream-chat-flutter/issues/1194) Request permission to access gallery when opening the file picker.
✅ Added
- [[#1011]](https://github.com/GetStream/stream-chat-flutter/issues/1011) Animate the background
color of pinned messages.
- Added unread messages divider in `StreamMessageListView`.
- Added `StreamMessageListView.unreadMessagesSeparatorBuilder`.
- Now `StreamMessageListView` opens to the oldest unread message by default.
## 4.2.0
🐞 Fixed
- [[#1133]](https://github.com/GetStream/stream-chat-flutter/issues/1133) Visibility override flags not being passed to `StreamMessageActionsModal`
- [[#1133]](https://github.com/GetStream/stream-chat-flutter/issues/1133) Visibility override flags
not being passed to `StreamMessageActionsModal`
## 4.1.0
✅ Added
- [[#1119]](https://github.com/GetStream/stream-chat-flutter/issues/1119) Added an option to disable mentions overlay in `StreamMessageInput`
- Deprecated `disableEmojiSuggestionsOverlay` in favor of `enableEmojiSuggestionsOverlay` in `StreamMessageInput`
- [[#1119]](https://github.com/GetStream/stream-chat-flutter/issues/1119) Added an option to disable
mentions overlay in `StreamMessageInput`
- Deprecated `disableEmojiSuggestionsOverlay` in favor of `enableEmojiSuggestionsOverlay`
in `StreamMessageInput`
🐞 Fixed
- Fixed attachment picker ui.
- Fixed StreamChannelHeader and StreamThreadHeader subtitle alignment.
- Fixed message widget thread indicator in reverse mode.
- [[#1044]](https://github.com/GetStream/stream-chat-flutter/issues/1044): Refactor StreamMessageWidget bottom row to use Text.rich.
- [[#1044]](https://github.com/GetStream/stream-chat-flutter/issues/1044): Refactor
StreamMessageWidget bottom row to use Text.rich.
🔄 Changed
- Removed `isOwner` condition from `ChannelBottomSheet` and `StreamChannelInfoBottomSheet` for delete option tile.
- Removed `isOwner` condition from `ChannelBottomSheet` and `StreamChannelInfoBottomSheet` for
delete option tile.
## 4.0.1
- Minor fixes
- Updated `stream_chat_flutter_core` dependency to [`4.0.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `stream_chat_flutter_core` dependency
to [`4.0.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
## 4.0.0
For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migration_guide_4_0/)
For upgrading to V4, please refer to
the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migration_guide_4_0/)
✅ Added
- [[#1087]](https://github.com/GetStream/stream-chat-flutter/issues/1087): Handle limited access to camera on iOS.
- `centerTitle` and `elevation` properties to `ChannelHeader`, `ThreadHeader` and `ChannelListHeader`.
- [[#1087]](https://github.com/GetStream/stream-chat-flutter/issues/1087): Handle limited access to
camera on iOS.
- `centerTitle` and `elevation` properties to `ChannelHeader`, `ThreadHeader`
and `ChannelListHeader`.
🐞 Fixed
- [[#1067]](https://github.com/GetStream/stream-chat-flutter/issues/1067): Fix name text overflow in reaction card.
- [[#842]](https://github.com/GetStream/stream-chat-flutter/issues/842): show date divider for first message.
- [[#1067]](https://github.com/GetStream/stream-chat-flutter/issues/1067): Fix name text overflow in
reaction card.
- [[#842]](https://github.com/GetStream/stream-chat-flutter/issues/842): show date divider for first
message.
- Loosen up url check for attachment download.
- Use `ogScrapeUrl` for LinkAttachments.
@@ -48,16 +80,20 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.
✅ Added
- Added support to pass `autoCorrect` to `StreamMessageInput` for the text input field
- Added support to control the visibility of the default emoji suggestions overlay in `StreamMessageInput`
- Added support to control the visibility of the default emoji suggestions overlay
in `StreamMessageInput`
- Added support to build custom widget for scrollToBottom in `StreamMessageListView`
🐞 Fixed
- Minor fixes and improvements
-[[#892]](https://github.com/GetStream/stream-chat-flutter/issues/892): Fix default `initialAlignment` in `MessageListView`.
- Fix `MessageInputTheme.inputBackgroundColor` color not being used in some widgets of `MessageInput`
-[[#892]](https://github.com/GetStream/stream-chat-flutter/issues/892): Fix
default `initialAlignment` in `MessageListView`.
- Fix `MessageInputTheme.inputBackgroundColor` color not being used in some widgets
of `MessageInput`
- Removed dependency on `visibility_detector`
- [[#1071]](https://github.com/GetStream/stream-chat-flutter/issues/1071): Fixed the way attachment actions were handled in full screen
- [[#1071]](https://github.com/GetStream/stream-chat-flutter/issues/1071): Fixed the way attachment
actions were handled in full screen
## 4.0.0-beta.1
@@ -70,22 +106,27 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.
- Deprecated `ChannelAvatar` in favor of `StreamChannelAvatar`.
- Deprecated `ChannelName` in favor of `StreamChannelName`.
- Deprecated `MessageInput` in favor of `StreamMessageInput`.
- Separated `MessageInput` widget in smaller components. (For example `CountDownButton`, `StreamAttachmentPicker`...)
- Updated `stream_chat_flutter_core` dependency to [`4.0.0-beta.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Separated `MessageInput` widget in smaller components. (For example `CountDownButton`
, `StreamAttachmentPicker`...)
- Updated `stream_chat_flutter_core` dependency
to [`4.0.0-beta.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Added OpenGraph preview support for links in `StreamMessageInput`.
- Removed video compression.
## 3.6.1
- Updated `stream_chat_flutter_core` dependency to [`3.6.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `stream_chat_flutter_core` dependency
to [`3.6.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
## 3.6.0
🐞 Fixed
- Minor fixes and improvements
-[[#892]](https://github.com/GetStream/stream-chat-flutter/issues/892): Fix default `initialAlignment` in `MessageListView`.
- Fix `MessageInputTheme.inputBackgroundColor` color not being used in some widgets of `MessageInput`
-[[#892]](https://github.com/GetStream/stream-chat-flutter/issues/892): Fix
default `initialAlignment` in `MessageListView`.
- Fix `MessageInputTheme.inputBackgroundColor` color not being used in some widgets
of `MessageInput`
- Removed dependency on `visibility_detector`
## 3.5.1
@@ -98,32 +139,35 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.
🐞 Fixed
- Mentions overlay now doesn't overflow when there is not enough height available
- Updated `stream_chat_flutter_core` dependency to [`3.5.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `stream_chat_flutter_core` dependency
to [`3.5.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
✅ Added
- `onLinkTap` for `MessageWidget` can now be passed down to `UrlAttachment`.
## 3.5.0
🐞 Fixed
- [[#888]](https://github.com/GetStream/stream-chat-flutter/issues/888) Fix `unban` command not working in `MessageInput`.
- [[#805]](https://github.com/GetStream/stream-chat-flutter/issues/805) Updated chewie dependency version to 1.3.0
- [[#888]](https://github.com/GetStream/stream-chat-flutter/issues/888) Fix `unban` command not
working in `MessageInput`.
- [[#805]](https://github.com/GetStream/stream-chat-flutter/issues/805) Updated chewie dependency
version to 1.3.0
- Fix `showScrollToBottom` in `MessageListView` not respecting false value.
- Fix default `Channel` route not opening from `ChannelListView` when `ChannelAvatar` is tapped
## 3.4.0
- Updated `stream_chat_flutter_core` dependency to [`3.4.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `stream_chat_flutter_core` dependency
to [`3.4.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
🐞 Fixed
- SVG rendering fixes.
- Use file extension instead of mimeType for downloading files.
- [[#860]](https://github.com/GetStream/stream-chat-flutter/issues/860) CastError while compressing Videos.
- [[#860]](https://github.com/GetStream/stream-chat-flutter/issues/860) CastError while compressing
Videos.
✅ Added
@@ -136,22 +180,26 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.
## 3.3.2
- Updated `stream_chat_flutter_core` dependency to [`3.3.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `stream_chat_flutter_core` dependency
to [`3.3.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
## 3.3.1
✅ Added
- `MessageListView` now allows more better control over spacing after messages using `spacingWidgetBuilder`.
- `MessageListView` now allows more better control over spacing after messages
using `spacingWidgetBuilder`.
- `StreamChannel` can now fetch messages around a message ID with the `queryAroundMessage` call.
- Added `MessageListView.keyboardDismissBehavior` property.
🐞 Fixed
- [[#766]](https://github.com/GetStream/stream-chat-flutter/issues/766) `AttachmentActionsModal` now has customisation options for actions.
- [[#766]](https://github.com/GetStream/stream-chat-flutter/issues/766) `AttachmentActionsModal` now
has customisation options for actions.
- Fixed `MessageWidget` null errors associated with `channel.memberCount`.
- Fixed adding attachments on web.
- [[#767]](https://github.com/GetStream/stream-chat-flutter/issues/767): Fix `MessageInput` focus behaviour when sending messages.
- [[#767]](https://github.com/GetStream/stream-chat-flutter/issues/767): Fix `MessageInput` focus
behaviour when sending messages.
- Fixed user presence indicator not updating correctly.
- Do not use `withData: true` in `FilePicker` calls.
- Fixed read indicator not updating correctly in specific situations.
@@ -159,29 +207,35 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.
## 3.2.0
- Updated Dart SDK constraints to `>=2.14.0 <3.0.0`.
- Updated `stream_chat_flutter_core` dependency to [`3.2.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `stream_chat_flutter_core` dependency
to [`3.2.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
🐞 Fixed
- Fixed message highlight animation alignment in `MessageListView`.
- [[#491]](https://github.com/GetStream/stream-chat-flutter/issues/491): Fix `MediaListView` showing media in wrong order.
- [[#491]](https://github.com/GetStream/stream-chat-flutter/issues/491): Fix `MediaListView` showing
media in wrong order.
- Fixed `MessageListView` initialIndex not working in some cases.
- Improved `MessageListView` rendering in case of reordering.
- Fix image thumbnail generation when using Stream CDN.
✅ Added
- `MessageListViewThemeData` now accepts a `DecorationImage` as a background image for `MessageListView`.
- `MessageListViewThemeData` now accepts a `DecorationImage` as a background image
for `MessageListView`.
## 3.1.1
- Updated `stream_chat_flutter_core` dependency to [`3.1.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `stream_chat_flutter_core` dependency
to [`3.1.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `file_picker`, `image_gallery_saver`, and `video_thumbnail` to the latest versions.
🐞 Fixed
- [[#687]](https://github.com/GetStream/stream-chat-flutter/issues/687): Fix Users losing their place in the conversation after replying in threads.
- Fixed floating date stream subscription causing "Bad state: stream has already been listened.” error.
- [[#687]](https://github.com/GetStream/stream-chat-flutter/issues/687): Fix Users losing their
place in the conversation after replying in threads.
- Fixed floating date stream subscription causing "Bad state: stream has already been listened.”
error.
- Fixed `String` capitalize extension not working on empty strings.
✅ Added
@@ -189,17 +243,21 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.
- Added `MessageInput.customOverlays` property to add custom overlays to the message input.
- Added `MessageInput.mentionAllAppUsers` property to mention all app users in the message input.
- The `MessageInput` now supports local search for channels with less than 100 members.
- Added `MessageListView.paginationLoadingIndicatorBuilder` to override the default loading indicator shown while paginating the message list.
- Added new `linkBackgroundColor` in `MessageTheme` for setting background colors of link attachments.
- Added `MessageListView.paginationLoadingIndicatorBuilder` to override the default loading
indicator shown while paginating the message list.
- Added new `linkBackgroundColor` in `MessageTheme` for setting background colors of link
attachments.
⚠️ Deprecated
- `MessageInput.mentionsTileBuilder` is now deprecated in favor of `MessageInput.userMentionsTileBuilder`.
- `MessageInput.mentionsTileBuilder` is now deprecated in favor
of `MessageInput.userMentionsTileBuilder`.
- `MentionTile` is now deprecated in favor of `UserMentionsTile`.
## 3.0.0
- Updated `stream_chat_flutter_core` dependency to [`3.0.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
- Updated `stream_chat_flutter_core` dependency
to [`3.0.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
🛑️ Breaking Changes from `2.2.1`
@@ -207,16 +265,19 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.
🐞 Fixed
- [[#668]](https://github.com/GetStream/stream-chat-flutter/issues/668): Fix `MessageInput` rendering errors in case
there are no actions available to show.
- [[#349]](https://github.com/GetStream/stream-chat-flutter/issues/349): Fix `MessageInput` attachment render overflow error.
- [[#668]](https://github.com/GetStream/stream-chat-flutter/issues/668): Fix `MessageInput`
rendering errors in case there are no actions available to show.
- [[#349]](https://github.com/GetStream/stream-chat-flutter/issues/349): Fix `MessageInput`
attachment render overflow error.
- `MessageInput` overlays now follow the `MessageInput` focus.
- [[#674]](https://github.com/GetStream/stream-chat-flutter/issues/674): Check scrollController is attached before calling jump in MessageListView.
- [[#674]](https://github.com/GetStream/stream-chat-flutter/issues/674): Check scrollController is
attached before calling jump in MessageListView.
- Fixed `MessageListView` header and footer when `reverse: false`.
🔄 Changed
- Animation curves changed from default `Curves.linear` to `Curves.easeOut` and `Curves.easeIn` for attachment controls.
- Animation curves changed from default `Curves.linear` to `Curves.easeOut` and `Curves.easeIn` for
attachment controls.
- Removed default padding in `DateDivider` in `MessageListView`
✅ Added
@@ -273,17 +334,20 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream.
✅ Added
- [#516](https://github.com/GetStream/stream-chat-flutter/issues/516):
Added `StreamChatThemeData.placeholderUserImage` for building a widget when the `UserAvatar` image is loading
Added `StreamChatThemeData.placeholderUserImage` for building a widget when the `UserAvatar` image
is loading
- Added a `backgroundColor` property to the following widgets:
- `ChannelHeader`
- `ChannelListHeader`
- `GalleryHeader`
- `GalleryFooter`
- `ThreadHeader`
- Added `MessageInput.attachmentLimit` in order to limit the no. of attachments that can be sent with a single message.
- Added `MessageInput.onAttachmentLimitExceed` callback which will be called when the `attachmentLimit` is exceeded.
This will override the default error alert behaviour.
- Added `MessageInput.attachmentButtonBuilder` and `MessageInput.commandButtonBuilder` for more customizations.
- Added `MessageInput.attachmentLimit` in order to limit the no. of attachments that can be sent
with a single message.
- Added `MessageInput.onAttachmentLimitExceed` callback which will be called when
the `attachmentLimit` is exceeded. This will override the default error alert behaviour.
- Added `MessageInput.attachmentButtonBuilder` and `MessageInput.commandButtonBuilder` for more
customizations.
```dart
typedef ActionButtonBuilder = Widget Function(
@@ -299,8 +363,9 @@ You can call `.copyWith` to customize just a subset of properties.
🔄 Changed
Theming has been upgraded! Most theme classes now have `InheritedTheme` classes associated with them, and have been
upgraded with some goodies like `lerp` functions. Here's the full naming breakdown:
Theming has been upgraded! Most theme classes now have `InheritedTheme` classes associated with
them, and have been upgraded with some goodies like `lerp` functions. Here's the full naming
breakdown:
* `AvatarTheme` is now `AvatarThemeData`
* `ChannelHeaderTheme` is now `ChannelHeaderThemeData`
@@ -317,18 +382,20 @@ upgraded with some goodies like `lerp` functions. Here's the full naming breakdo
🐞 Fixed
- Fixed `MessageInput` textField case where `input` is not enabled if the file picked from the camera is null.
- Fixed `MessageInput` textField case where `input` is not enabled if the file picked from the
camera is null.
- Fixed date dividers position/alignment in non reversed `MessageListView`.
- Fixed `MessageListView` not opening to the right initialMessage if `StreamChannel.initialMessageId` is set.
- Fixed null check errors when accessing `message.text` in `MessageWidget` and `MessageListView`; this occurred when
sending a message with no text.
- Fixed `MessageListView` not opening to the right initialMessage
if `StreamChannel.initialMessageId` is set.
- Fixed null check errors when accessing `message.text` in `MessageWidget` and `MessageListView`;
this occurred when sending a message with no text.
## 2.1.2
🐞 Fixed
- [#590](https://github.com/GetStream/stream-chat-flutter/issues/590): livestream use case, no members when sending
message
- [#590](https://github.com/GetStream/stream-chat-flutter/issues/590): livestream use case, no
members when sending message
## 2.1.1
@@ -346,7 +413,8 @@ upgraded with some goodies like `lerp` functions. Here's the full naming breakdo
🔄 Changed
- `StreamChat.of(context).user` is now deprecated in favor of `StreamChat.of(context).currentUser`.
- `StreamChat.of(context).userStream` is now deprecated in favor of `StreamChat.of(context).currentUserStream`.
- `StreamChat.of(context).userStream` is now deprecated in favor
of `StreamChat.of(context).currentUserStream`.
🐞 Fixed
@@ -399,7 +467,8 @@ You can call `.copyWith` to customize just a subset of properties
- Added video compress options (frame and quality) to `MessageInput`
- TypingIndicator now has a property called `parentId` to show typing indicator specific to threads
- [#493](https://github.com/GetStream/stream-chat-flutter/pull/493): add support for messageListView header/footer
- [#493](https://github.com/GetStream/stream-chat-flutter/pull/493): add support for messageListView
header/footer
- `MessageWidget` accepts a `userAvatarBuilder`
- Added pinMessage ui support
- Added `MessageListView.threadSeparatorBuilder` property
@@ -408,10 +477,12 @@ You can call `.copyWith` to customize just a subset of properties
🐞 Fixed
- [#483](https://github.com/GetStream/stream-chat-flutter/issues/483): Keyboard covers input text box when editing
message
- Modals are shown using the nearest `Navigator` to make using the SDK easier in a nested navigator use case
- [#484](https://github.com/GetStream/stream-chat-flutter/issues/484): messages don't update without a reload
- [#483](https://github.com/GetStream/stream-chat-flutter/issues/483): Keyboard covers input text
box when editing message
- Modals are shown using the nearest `Navigator` to make using the SDK easier in a nested navigator
use case
- [#484](https://github.com/GetStream/stream-chat-flutter/issues/484): messages don't update without
a reload
- `MessageListView` not rendering if the user is not a member of the channel
- Fix `MessageInput` overflow when there are no actions
- Minor fixes and improvements
@@ -464,15 +535,18 @@ You can call `.copyWith` to customize just a subset of properties.
✅ Added
- TypingIndicator now has a property called `parentId` to show typing indicator specific to threads
- [#493](https://github.com/GetStream/stream-chat-flutter/pull/493): add support for messageListView header/footer
- [#493](https://github.com/GetStream/stream-chat-flutter/pull/493): add support for messageListView
header/footer
- `MessageWidget` accepts a `userAvatarBuilder`
🐞 Fixed
- [#483](https://github.com/GetStream/stream-chat-flutter/issues/483): Keyboard covers input text box when editing
message
- Modals are shown using the nearest `Navigator` to make using the SDK easier in a nested navigator use case
- [#484](https://github.com/GetStream/stream-chat-flutter/issues/484): messages don't update without a reload
- [#483](https://github.com/GetStream/stream-chat-flutter/issues/483): Keyboard covers input text
box when editing message
- Modals are shown using the nearest `Navigator` to make using the SDK easier in a nested navigator
use case
- [#484](https://github.com/GetStream/stream-chat-flutter/issues/484): messages don't update without
a reload
- `MessageListView` not rendering if the user is not a member of the channel
## 2.0.0-nullsafety.7
@@ -542,7 +616,8 @@ You can call `.copyWith` to customize just a subset of properties.
- Show error messages as system and keep them in the message input
- Remove notification badge logic
- Use shimmer while loading images
- Polished `StreamChatTheme` adding more options and a new `MessageInputTheme` dedicated to `MessageInput`
- Polished `StreamChatTheme` adding more options and a new `MessageInputTheme` dedicated
to `MessageInput`
- Add possibility to specify custom message actions using `MessageWidget.customActions`
- Added `MessageListView.onAttachmentTap` callback
- Fixed message newline issue
@@ -599,7 +674,8 @@ You can call `.copyWith` to customize just a subset of properties.
- Improved api documentation
- Updated `stream_chat` dependency to `^1.0.0-beta`
- Extracted sample app into dedicated [repo](https://github.com/GetStream/flutter-samples)
- Reimplemented existing widgets using [stream_chat_flutter_core](https://pub.dev/packages/stream_chat_flutter_core)
- Reimplemented existing widgets
using [stream_chat_flutter_core](https://pub.dev/packages/stream_chat_flutter_core)
## 0.2.21
@@ -616,8 +692,8 @@ You can call `.copyWith` to customize just a subset of properties.
## 0.2.20+2
- Added `shouldAddChannel` to ChannelsBloc in order to check if a channel has to be added to the list when a new message
arrives
- Added `shouldAddChannel` to ChannelsBloc in order to check if a channel has to be added to the
list when a new message arrives
## 0.2.20+1
@@ -651,7 +727,8 @@ You can call `.copyWith` to customize just a subset of properties.
## 0.2.16
- Do not wrap channel preview builder. Users will have to implement they're custom onTap/onLongPress implementation
- Do not wrap channel preview builder. Users will have to implement they're custom onTap/onLongPress
implementation
- Make public autofocus field of the TextField of message_input
## 0.2.15
@@ -836,10 +913,11 @@ You can call `.copyWith` to customize just a subset of properties.
## 0.2.1-alpha+1
- Removed the additional `Navigator` in `StreamChat` widget. It was added to make the app have the `StreamChat` widget
as ancestor in every route. Now the recommended way to add `StreamChat` to your app is using the `builder` property of
your `MaterialApp` widget. Otherwise you can use it in the usual way, but you need to add a `StreamChat` widget to
every route of your app. Read [this issue](https://github.com/GetStream/stream-chat-flutter/issues/47) for more
- Removed the additional `Navigator` in `StreamChat` widget. It was added to make the app have
the `StreamChat` widget as ancestor in every route. Now the recommended way to add `StreamChat` to
your app is using the `builder` property of your `MaterialApp` widget. Otherwise you can use it in
the usual way, but you need to add a `StreamChat` widget to every route of your app.
Read [this issue](https://github.com/GetStream/stream-chat-flutter/issues/47) for more
information.
```dart
@@ -941,8 +1019,8 @@ Widget build(BuildContext context) {
- Add gesture (vertical drag down) to close the keyboard
- Add keyboard type parameters (set it to TextInputType.text to show the submit button that will even close the
keyboard)
- Add keyboard type parameters (set it to TextInputType.text to show the submit button that will
even close the keyboard)
The property showVideoFullScreen was added mainly because of this issue brianegan/chewie#261
@@ -10,8 +10,8 @@ class Application : FlutterApplication(), PluginRegistrantCallback {
super.onCreate()
}
override fun registerWith(registry: PluginRegistry?) {
PathProviderPlugin.registerWith(registry?.registrarFor(
override fun registerWith(registry: PluginRegistry) {
PathProviderPlugin.registerWith(registry.registrarFor(
"io.flutter.plugins.pathprovider.PathProviderPlugin"))
}
}
@@ -59,5 +59,7 @@
<key>NSMicrophoneUsageDescription</key>
<string>Explain why your app uses the mic</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict>
</plist>
@@ -225,11 +225,12 @@ class _StreamGalleryFooterState extends State<StreamGalleryFooter> {
if (attachment.type == 'video') {
media = InkWell(
onTap: () => widget.mediaSelectedCallBack!(index),
child: FittedBox(
fit: BoxFit.cover,
child: AspectRatio(
aspectRatio: 1,
child: StreamVideoThumbnailImage(
video: (attachment.file?.path ??
attachment.assetUrl)!,
fit: BoxFit.cover,
),
),
);
@@ -77,6 +77,10 @@ abstract class Translations {
/// contains a parent message
String threadSeparatorText(int replyCount);
/// The text for showing the unread messages count
/// in the [StreamMessageListView]
String unreadMessagesSeparatorText(int unreadCount);
/// The label for "connected" in [StreamConnectionStatusBuilder]
String get connectedLabel;
@@ -711,4 +715,12 @@ Attachment limit exceeded: it's not possible to add more than $limit attachments
@override
String get linkDisabledError => 'Links are disabled';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 unread message';
}
return '$unreadCount unread messages';
}
}
@@ -66,7 +66,7 @@ typedef UserMentionTileBuilder = Widget Function(
/// Widget builder for action button.
///
/// [defaultActionButton] is the default [IconButton] configuration,
/// use [defaultActionButton.copyWith] to easily customize it.
/// use .copyWith to easily customize it.
typedef ActionButtonBuilder = Widget Function(
BuildContext context,
IconButton defaultActionButton,
@@ -200,6 +200,7 @@ class StreamMessageListView extends StatefulWidget {
this.onSystemMessageTap,
this.showFloatingDateDivider = true,
this.threadSeparatorBuilder,
this.unreadMessagesSeparatorBuilder,
this.messageListController,
this.reverse = true,
this.paginationLimit = 20,
@@ -337,6 +338,10 @@ class StreamMessageListView extends StatefulWidget {
/// Builder used to build the thread separator in case it's a thread view
final WidgetBuilder? threadSeparatorBuilder;
/// Builder used to build the unread message separator
final Widget Function(BuildContext context, int unreadCount)?
unreadMessagesSeparatorBuilder;
/// A [MessageListController] allows pagination.
/// Use [ChannelListController.paginateData] pagination.
final MessageListController? messageListController;
@@ -363,6 +368,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
StreamChannelState? streamChannel;
late StreamChatThemeData _streamTheme;
late List<String> _userPermissions;
late int unreadCount;
int get _initialIndex {
final initialScrollIndex = widget.initialScrollIndex;
@@ -381,6 +387,11 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
if (index != 0) return index + 1;
return index;
}
if (unreadCount > 0) {
return unreadCount + 1;
}
return 0;
}
@@ -596,9 +607,12 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
return const SizedBox(height: 8);
}
if (i == 1 || i == itemCount - 4) return const Offstage();
if (i == 1 || i == itemCount - 4) {
return const Offstage();
}
late final Message message, nextMessage;
late Widget separator;
if (widget.reverse) {
message = messages[i - 1];
nextMessage = messages[i - 2];
@@ -611,7 +625,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
nextMessage.createdAt.toLocal(),
Units.DAY,
)) {
return _buildDateDivider(nextMessage);
separator = _buildDateDivider(nextMessage);
}
final timeDiff =
Jiffy(nextMessage.createdAt.toLocal()).diff(
@@ -644,13 +658,52 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
}
if (spacingRules.isNotEmpty) {
return widget.spacingWidgetBuilder
separator = widget.spacingWidgetBuilder
?.call(context, spacingRules) ??
const SizedBox(height: 8);
}
return widget.spacingWidgetBuilder
separator = widget.spacingWidgetBuilder
?.call(context, [SpacingType.defaultSpacing]) ??
const SizedBox(height: 2);
if (!isThread && unreadCount > 0 && unreadCount == i - 1) {
final unreadMessagesSeparator = widget
.unreadMessagesSeparatorBuilder
?.call(context, unreadCount);
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
separator,
unreadMessagesSeparator ??
Padding(
padding:
const EdgeInsets.symmetric(vertical: 8),
child: DecoratedBox(
decoration: BoxDecoration(
gradient:
_streamTheme.colorTheme.bgGradient,
),
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
context.translations
.unreadMessagesSeparatorText(
unreadCount,
),
textAlign: TextAlign.center,
style:
StreamChannelHeaderTheme.of(context)
.subtitleStyle,
),
),
),
),
],
);
}
return separator;
},
itemBuilder: (context, i) {
if (i == itemCount - 1) {
@@ -880,9 +933,13 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
}
Future<void> scrollToBottomDefaultTapAction(int unreadCount) async {
this.unreadCount = unreadCount;
if (unreadCount > 0) {
streamChannel!.channel.markRead();
}
final index = unreadCount > 0 ? unreadCount + 1 : 0;
if (!_upToDate) {
_bottomPaginationActive = false;
initialAlignment = 0;
@@ -890,11 +947,11 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
await streamChannel!.reloadChannel();
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollController!.jumpTo(index: 0);
_scrollController!.jumpTo(index: index);
});
} else {
_scrollController!.scrollTo(
index: 0,
index: index,
duration: const Duration(seconds: 1),
curve: Curves.easeInOut,
);
@@ -1317,6 +1374,8 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
if (newStreamChannel != streamChannel) {
streamChannel = newStreamChannel;
_messageNewListener?.cancel();
unreadCount = streamChannel?.channel.state?.unreadCount ?? 0;
initialIndex = _initialIndex;
initialAlignment = _initialAlignment;
@@ -1328,25 +1387,38 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
}
_messageNewListener =
streamChannel!.channel.on(EventType.messageNew).listen((event) {
streamChannel!.channel.on(EventType.messageNew).skip(1)
//skipping the first event because
//the StreamController is a BehaviorSubject
.listen((event) {
if (_upToDate) {
_bottomPaginationActive = false;
}
if (event.message?.parentId == widget.parentMessage?.id &&
event.message!.user!.id ==
streamChannel!.channel.client.state.currentUser!.id) {
setState(() {
unreadCount = 0;
});
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollController?.scrollTo(
index: 0,
duration: const Duration(seconds: 1),
);
});
} else if (streamChannel?.channel.state?.unreadCount != 0) {
setState(() {
unreadCount = unreadCount + 1;
});
}
});
if (_isThreadConversation) {
streamChannel!.getReplies(widget.parentMessage!.id);
}
unreadCount = streamChannel?.channel.state?.unreadCount ?? 0;
}
super.didChangeDependencies();
@@ -596,240 +596,252 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
final showReactions = _shouldShowReactions;
final onMessageTap = widget.onMessageTap;
return Material(
type: widget.message.pinned && widget.showPinHighlight
? MaterialType.card
: MaterialType.transparency,
color: widget.message.pinned && widget.showPinHighlight
? _streamChatTheme.colorTheme.highlight
: null,
child: Portal(
child: InkWell(
onTap: () {
widget.onMessageTap!(widget.message);
},
onLongPress: widget.message.isDeleted && !isFailedState
? null
: () => onLongPress(context),
child: Padding(
padding: widget.padding ?? const EdgeInsets.all(8),
child: FractionallySizedBox(
alignment:
widget.reverse ? Alignment.centerRight : Alignment.centerLeft,
widthFactor: 0.78,
child: Column(
crossAxisAlignment: widget.reverse
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Stack(
clipBehavior: Clip.none,
alignment: widget.reverse
? AlignmentDirectional.bottomEnd
: AlignmentDirectional.bottomStart,
children: [
Padding(
padding: EdgeInsets.only(
bottom:
isPinned && widget.showPinHighlight ? 8.0 : 0.0,
),
child: Column(
crossAxisAlignment: widget.reverse
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
if (widget.message.pinned &&
widget.message.pinnedBy != null &&
widget.showPinHighlight)
_buildPinnedMessage(widget.message),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (!widget.reverse &&
widget.showUserAvatar ==
DisplayWidget.show &&
widget.message.user != null) ...[
_buildUserAvatar(),
const SizedBox(width: 4),
],
if (widget.showUserAvatar == DisplayWidget.hide)
SizedBox(width: avatarWidth + 4),
Flexible(
child: PortalTarget(
visible: showReactions,
portalFollower: showReactions
? Container(
transform:
Matrix4.translationValues(
widget.reverse ? 12 : -12,
0,
0,
),
constraints: const BoxConstraints(
maxWidth: 22 * 6.0,
),
child: _buildReactionIndicator(
context,
),
)
: null,
anchor: Aligned(
follower: Alignment(
widget.reverse ? 1 : -1,
-1,
),
target: Alignment(
widget.reverse ? -1 : 1,
-1,
),
),
child: Stack(
clipBehavior: Clip.none,
children: [
Padding(
padding: widget.showReactions
? EdgeInsets.only(
top: widget
.message
.reactionCounts
?.isNotEmpty ==
true
? 18
: 0,
)
: EdgeInsets.zero,
child: (widget.message.isDeleted &&
!isFailedState)
? Container(
// ignore: lines_longer_than_80_chars
margin: EdgeInsets.symmetric(
horizontal:
// ignore: lines_longer_than_80_chars
widget.showUserAvatar ==
// ignore: lines_longer_than_80_chars
DisplayWidget
.gone
? 0
: 4.0,
),
child: StreamDeletedMessage(
borderRadiusGeometry: widget
.borderRadiusGeometry,
borderSide:
widget.borderSide,
shape: widget.shape,
messageTheme:
widget.messageTheme,
),
)
: Card(
clipBehavior: Clip.hardEdge,
elevation: 0,
margin: EdgeInsets.symmetric(
horizontal: (isFailedState
? 15.0
: 0.0) +
// ignore: lines_longer_than_80_chars
(widget.showUserAvatar ==
DisplayWidget
.gone
? 0
: 4.0),
),
shape: widget.shape ??
RoundedRectangleBorder(
side: widget
.borderSide ??
BorderSide(
color: widget
// ignore: lines_longer_than_80_chars
.messageTheme
// ignore: lines_longer_than_80_chars
.messageBorderColor ??
Colors.grey,
),
borderRadius: widget
// ignore: lines_longer_than_80_chars
.borderRadiusGeometry ??
BorderRadius.zero,
),
color: _getBackgroundColor(),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.end,
mainAxisSize:
MainAxisSize.min,
children: <Widget>[
if (hasQuotedMessage)
_buildQuotedMessage(),
if (hasNonUrlAttachments)
_parseAttachments(),
if (!isGiphy)
_buildTextBubble(),
],
),
),
),
if (widget.showReactionPickerIndicator)
Positioned(
right: widget.reverse ? null : 4,
left: widget.reverse ? 4 : null,
top: -8,
child: CustomPaint(
painter: ReactionBubblePainter(
_streamChatTheme
.colorTheme.barsBg,
Colors.transparent,
Colors.transparent,
tailCirclesSpace: 1,
),
),
),
],
),
),
),
if (widget.reverse &&
widget.showUserAvatar ==
DisplayWidget.show &&
widget.message.user != null) ...[
_buildUserAvatar(),
const SizedBox(width: 4),
],
],
),
if (showBottomRow)
SizedBox(height: context.textScaleFactor * 18.0),
],
),
),
if (showBottomRow)
type: MaterialType.transparency,
child: AnimatedContainer(
duration: const Duration(seconds: 1),
color: widget.message.pinned && widget.showPinHighlight
? _streamChatTheme.colorTheme.highlight
: _streamChatTheme.colorTheme.barsBg.withOpacity(0),
child: Portal(
child: InkWell(
onTap: onMessageTap == null
? null
: () => onMessageTap(widget.message),
onLongPress: widget.message.isDeleted && !isFailedState
? null
: () => onLongPress(context),
child: Padding(
padding: widget.padding ?? const EdgeInsets.all(8),
child: FractionallySizedBox(
alignment: widget.reverse
? Alignment.centerRight
: Alignment.centerLeft,
widthFactor: 0.78,
child: Column(
crossAxisAlignment: widget.reverse
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Stack(
clipBehavior: Clip.none,
alignment: widget.reverse
? AlignmentDirectional.bottomEnd
: AlignmentDirectional.bottomStart,
children: [
Padding(
padding: EdgeInsets.only(
left: !widget.reverse ? bottomRowPadding : 0,
right: widget.reverse ? bottomRowPadding : 0,
bottom:
isPinned && widget.showPinHighlight ? 6.0 : 0.0,
isPinned && widget.showPinHighlight ? 8.0 : 0.0,
),
child: Column(
crossAxisAlignment: widget.reverse
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
if (widget.message.pinned &&
widget.message.pinnedBy != null &&
widget.showPinHighlight)
_buildPinnedMessage(widget.message),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (!widget.reverse &&
widget.showUserAvatar ==
DisplayWidget.show &&
widget.message.user != null) ...[
_buildUserAvatar(),
const SizedBox(width: 4),
],
if (widget.showUserAvatar ==
DisplayWidget.hide)
SizedBox(width: avatarWidth + 4),
Flexible(
child: PortalTarget(
visible: showReactions,
portalFollower: showReactions
? Container(
transform:
Matrix4.translationValues(
widget.reverse ? 12 : -12,
0,
0,
),
constraints: const BoxConstraints(
maxWidth: 22 * 6.0,
),
child: _buildReactionIndicator(
context,
),
)
: null,
anchor: Aligned(
follower: Alignment(
widget.reverse ? 1 : -1,
-1,
),
target: Alignment(
widget.reverse ? -1 : 1,
-1,
),
),
child: Stack(
clipBehavior: Clip.none,
children: [
Padding(
padding: widget.showReactions
? EdgeInsets.only(
top: widget
.message
.reactionCounts
?.isNotEmpty ==
true
? 18
: 0,
)
: EdgeInsets.zero,
child: (widget.message.isDeleted &&
!isFailedState)
? Container(
margin:
EdgeInsets.symmetric(
horizontal:
// ignore: lines_longer_than_80_chars
widget.showUserAvatar ==
// ignore: lines_longer_than_80_chars
DisplayWidget.gone
? 0
: 4.0,
),
child: StreamDeletedMessage(
// ignore: lines_longer_than_80_chars
borderRadiusGeometry: widget
.borderRadiusGeometry,
borderSide:
widget.borderSide,
shape: widget.shape,
messageTheme:
widget.messageTheme,
),
)
: Card(
clipBehavior: Clip.hardEdge,
elevation: 0,
margin:
EdgeInsets.symmetric(
horizontal: (isFailedState
? 15.0
: 0.0) +
// ignore: lines_longer_than_80_chars
(widget.showUserAvatar ==
DisplayWidget
.gone
? 0
: 4.0),
),
shape: widget.shape ??
RoundedRectangleBorder(
side: widget
.borderSide ??
BorderSide(
color: widget
// ignore: lines_longer_than_80_chars
.messageTheme
// ignore: lines_longer_than_80_chars
.messageBorderColor ??
Colors.grey,
),
borderRadius: widget
// ignore: lines_longer_than_80_chars
.borderRadiusGeometry ??
BorderRadius.zero,
),
color: _backgroundColor,
child: Column(
crossAxisAlignment:
CrossAxisAlignment
.end,
mainAxisSize:
MainAxisSize.min,
children: <Widget>[
if (hasQuotedMessage)
_buildQuotedMessage(),
// ignore: lines_longer_than_80_chars
if (hasNonUrlAttachments)
_parseAttachments(),
if (!isGiphy)
_buildTextBubble(),
],
),
),
),
if (widget
.showReactionPickerIndicator)
Positioned(
right: widget.reverse ? null : 4,
left: widget.reverse ? 4 : null,
top: -8,
child: CustomPaint(
painter: ReactionBubblePainter(
_streamChatTheme
.colorTheme.barsBg,
Colors.transparent,
Colors.transparent,
tailCirclesSpace: 1,
),
),
),
],
),
),
),
if (widget.reverse &&
widget.showUserAvatar ==
DisplayWidget.show &&
widget.message.user != null) ...[
_buildUserAvatar(),
const SizedBox(width: 4),
],
],
),
if (showBottomRow)
SizedBox(
height: context.textScaleFactor * 18.0,
),
],
),
child: widget.bottomRowBuilder?.call(
context,
widget.message,
) ??
_bottomRow,
),
if (isFailedState)
Positioned(
right: widget.reverse ? 0 : null,
left: widget.reverse ? null : 0,
bottom: showBottomRow ? 18 : -2,
child: StreamSvgIcon.error(size: 20),
),
],
),
],
if (showBottomRow)
Padding(
padding: EdgeInsets.only(
left: !widget.reverse ? bottomRowPadding : 0,
right: widget.reverse ? bottomRowPadding : 0,
bottom: isPinned && widget.showPinHighlight
? 6.0
: 0.0,
),
child: widget.bottomRowBuilder?.call(
context,
widget.message,
) ??
_bottomRow,
),
if (isFailedState)
Positioned(
right: widget.reverse ? 0 : null,
left: widget.reverse ? null : 0,
bottom: showBottomRow ? 18 : -2,
child: StreamSvgIcon.error(size: 20),
),
],
),
],
),
),
),
),
@@ -1343,12 +1355,8 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
StreamSvgIcon.pin(
size: 16,
),
const SizedBox(
width: 4,
),
StreamSvgIcon.pin(size: 16),
const SizedBox(width: 4),
Text(
context.translations.pinnedByUserText(
pinnedBy: pinnedBy,
@@ -1367,7 +1375,7 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
bool get isPinned => widget.message.pinned;
Color? _getBackgroundColor() {
Color? get _backgroundColor {
if (hasQuotedMessage) {
return widget.messageTheme.messageBackgroundColor;
}
@@ -109,8 +109,8 @@ class StreamChatState extends State<StreamChat> {
child: Builder(
builder: (context) {
StreamChatClient.additionalHeaders = {
'X-Stream-Client':
'${StreamChatClient.defaultUserAgent}-ui',
'X-Stream-Client': '${StreamChatClient.defaultUserAgent}-'
'ui-${StreamChatClient.packageVersion}',
};
return widget.child ?? const Offstage();
},
@@ -9,7 +9,10 @@ import 'package:url_launcher/url_launcher.dart';
/// Launch URL
Future<void> launchURL(BuildContext context, String url) async {
try {
await launchUrl(Uri.parse(url).withScheme);
await launchUrl(
Uri.parse(url).withScheme,
mode: LaunchMode.externalApplication,
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.translations.launchUrlError)),
@@ -282,25 +282,26 @@ class _StreamAttachmentPickerState extends State<StreamAttachmentPicker> {
.iconBuilder(context, _filePickerIndex == i + 1),
),
const Spacer(),
FutureBuilder(
future: PhotoManager.requestPermissionExtend(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.data == PermissionState.limited) {
return TextButton(
child: Text(context.translations.viewLibrary),
onPressed: () async {
await PhotoManager.presentLimited();
_mediaListViewController.updateMedia(
newValue: true,
);
},
);
}
if (widget.isOpen)
FutureBuilder(
future: PhotoManager.requestPermissionExtend(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.data == PermissionState.limited) {
return TextButton(
child: Text(context.translations.viewLibrary),
onPressed: () async {
await PhotoManager.presentLimited();
_mediaListViewController.updateMedia(
newValue: true,
);
},
);
}
return const SizedBox.shrink();
},
),
return const SizedBox.shrink();
},
),
],
),
DecoratedBox(
@@ -70,7 +70,7 @@ typedef UserMentionTileBuilder = Widget Function(
/// Widget builder for action button.
///
/// [defaultActionButton] is the default [IconButton] configuration,
/// use [defaultActionButton.copyWith] to easily customize it.
/// use .copyWith to easily customize it.
typedef ActionButtonBuilder = Widget Function(
BuildContext context,
IconButton defaultActionButton,
@@ -998,7 +998,10 @@ class StreamMessageInputState extends State<StreamMessageInput>
_lastSearchedContainsUrlText = value;
final matchedUrls = _urlRegex.allMatches(value).toList()
..removeWhere((it) => it.group(0)?.split('.').last.isValidTLD() == false);
..removeWhere((it) {
final _parsedMatch = Uri.tryParse(it.group(0) ?? '')?.withScheme;
return _parsedMatch?.host.split('.').last.isValidTLD() == false;
});
// Reset the og attachment if the text doesn't contain any url
if (matchedUrls.isEmpty ||
@@ -1221,7 +1224,7 @@ class StreamMessageInputState extends State<StreamMessageInput>
void _setCommand(Command c) {
_effectiveController
..clear()
..reset()
..command = c;
setState(() {
_showCommandsOverlay = false;
@@ -97,8 +97,9 @@ class _StreamVideoThumbnailImageState extends State<StreamVideoThumbnailImage> {
);
}
if (!snapshot.hasData) {
return Container(
constraints: const BoxConstraints.expand(),
return SizedBox(
height: double.maxFinite,
width: double.maxFinite,
child: widget.placeholderBuilder?.call(context) ??
Shimmer.fromColors(
baseColor: _streamChatTheme.colorTheme.disabled,
@@ -106,16 +107,22 @@ class _StreamVideoThumbnailImageState extends State<StreamVideoThumbnailImage> {
child: Image.asset(
'images/placeholder.png',
fit: BoxFit.cover,
height: widget.height,
width: widget.width,
package: 'stream_chat_flutter',
),
),
);
}
return Image.memory(
snapshot.data!,
fit: widget.fit,
height: widget.height,
width: widget.width,
return SizedBox(
height: double.maxFinite,
width: double.maxFinite,
child: Image.memory(
snapshot.data!,
fit: widget.fit,
height: widget.height,
width: widget.width,
),
);
},
),
+3 -3
View File
@@ -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: 4.2.0
version: 4.3.0
repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -32,11 +32,11 @@ dependencies:
meta: ^1.3.0
path_provider: ^2.0.1
photo_manager: ^2.0.1
photo_view: ^0.13.0
photo_view: ^0.14.0
rxdart: ^0.27.0
share_plus: ^4.0.1
shimmer: ^2.0.0
stream_chat_flutter_core: ^4.2.0
stream_chat_flutter_core: ^4.3.0
substring_highlight: ^1.0.26
url_launcher: ^6.1.0
video_player: ^2.1.0
@@ -1,3 +1,7 @@
## 4.3.0
- Updated `stream_chat` dependency to [`4.3.0`](https://pub.dev/packages/stream_chat/changelog).
## 4.2.0
- Updated `stream_chat` dependency to [`4.2.0`](https://pub.dev/packages/stream_chat/changelog).
@@ -26,8 +26,7 @@ dependencies:
cupertino_icons: ^1.0.3
flutter:
sdk: flutter
stream_chat_flutter_core: ^2.2.1
stream_chat_flutter_core: ^4.3.0
dev_dependencies:
flutter_test:
sdk: flutter
@@ -96,7 +96,8 @@ class StreamChatCoreState extends State<StreamChatCore>
@override
Widget build(BuildContext context) {
StreamChatClient.additionalHeaders = {
'X-Stream-Client': '${StreamChatClient.defaultUserAgent}-core',
'X-Stream-Client': '${StreamChatClient.defaultUserAgent}-'
'core-${StreamChatClient.packageVersion}',
};
return widget.child;
}
@@ -1,7 +1,7 @@
name: stream_chat_flutter_core
homepage: https://github.com/GetStream/stream-chat-flutter
description: Stream Chat official Flutter SDK Core. Build your own chat experience using Dart and Flutter.
version: 4.2.0
version: 4.3.0
repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -17,8 +17,7 @@ dependencies:
freezed_annotation: ^2.0.3
meta: ^1.3.0
rxdart: ^0.27.0
stream_chat: ^4.2.0
stream_chat: ^4.3.0
dev_dependencies:
build_runner: ^2.0.1
dart_code_metrics: ^4.4.0
@@ -1,3 +1,9 @@
## 3.2.0
✅ Added
* Added support for `unreadMessagesSeparatorText` translation.
## 3.1.0
* Added support for [German](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_de.dart) locale.
@@ -405,6 +405,14 @@ class NnStreamChatLocalizations extends GlobalStreamChatLocalizations {
@override
String get viewLibrary => 'View library';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 unread message';
}
return '$unreadCount unread messages';
}
}
void main() async {
@@ -163,7 +163,7 @@ class StreamChatLocalizationsDe extends GlobalStreamChatLocalizations {
String get allowGalleryAccessMessage => 'Zugang zu Ihrer Galerie gewähren';
@override
String get flagMessageLabel => 'Markierte Nachricht';
String get flagMessageLabel => 'Nachricht melden';
@override
String get flagMessageQuestion =>
@@ -171,13 +171,13 @@ class StreamChatLocalizationsDe extends GlobalStreamChatLocalizations {
'\nModerator für weitere Untersuchungen senden?';
@override
String get flagLabel => 'MARKIEREN';
String get flagLabel => 'MELDEN';
@override
String get cancelLabel => 'ABBRECHEN';
@override
String get flagMessageSuccessfulLabel => 'Nachricht markiert';
String get flagMessageSuccessfulLabel => 'Nachricht gemeldet';
@override
String get flagMessageSuccessfulText =>
@@ -283,7 +283,7 @@ class StreamChatLocalizationsDe extends GlobalStreamChatLocalizations {
String get streamChatLabel => 'Stream Chat';
@override
String get searchingForNetworkText => 'Searching for Network';
String get searchingForNetworkText => 'Netzwerk wird gesucht';
@override
String get offlineLabel => 'Offline...';
@@ -380,5 +380,13 @@ class StreamChatLocalizationsDe extends GlobalStreamChatLocalizations {
'Sie sind nicht berechtigt Nachrichten zu senden';
@override
String get viewLibrary => 'Bibliothek ansehen';
String get viewLibrary => 'Bibliothek öffnen';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 ungelesene Nachricht';
}
return '$unreadCount ungelesene Nachrichten';
}
}
@@ -381,4 +381,12 @@ class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations {
@override
String get viewLibrary => 'View library';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 unread message';
}
return '$unreadCount unread messages';
}
}
@@ -387,4 +387,12 @@ No es posible añadir más de $limit archivos adjuntos
@override
String get linkDisabledError => 'Los enlaces están deshabilitados';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 mensaje no leído';
}
return '$unreadCount mensajes no leídos';
}
}
@@ -386,4 +386,12 @@ Limite de pièces jointes dépassée : il n'est pas possible d'ajouter plus de $
@override
String get linkDisabledError => 'Les liens sont désactivés';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 message non lu';
}
return '$unreadCount messages non lus';
}
}
@@ -380,4 +380,12 @@ class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations {
@override
String get linkDisabledError => 'लिंक भेजना प्रतिबंधित';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 अपठित संदेश';
}
return '$unreadCount अपठित संदेश';
}
}
@@ -40,7 +40,12 @@ class StreamChatLocalizationsIt extends GlobalStreamChatLocalizations {
String get onlyVisibleToYouText => 'Visible solo a te';
@override
String threadReplyCountText(int count) => '$count risposte al thread';
String threadReplyCountText(int count) {
if (count == 1) {
return '1 risposta al thread';
}
return '$count risposte al thread';
}
@override
String attachmentsUploadProgressText({
@@ -383,4 +388,12 @@ Attenzione: il limite massimo di $limit file è stato superato.
@override
String get linkDisabledError => 'I links sono disattivati';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 messaggio non letto';
}
return '$unreadCount messaggi non letti';
}
}
@@ -365,4 +365,12 @@ class StreamChatLocalizationsJa extends GlobalStreamChatLocalizations {
@override
String get linkDisabledError => 'リンクが無効になっています';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '未読メッセージ1通';
}
return '$unreadCountつの未読メッセージ';
}
}
@@ -366,4 +366,12 @@ class StreamChatLocalizationsKo extends GlobalStreamChatLocalizations {
@override
String get linkDisabledError => '링크가 비활성화되었습니다.';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '읽지 않은 메시지 1개';
}
return '읽지 않은 메시지 $unreadCount개';
}
}
@@ -384,4 +384,12 @@ Não é possível adicionar mais de $limit arquivos de uma vez
@override
String get viewLibrary => 'Ver biblioteca';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 mensagem não lida';
}
return '$unreadCount mensagens não lidas';
}
}
@@ -1,6 +1,6 @@
name: stream_chat_localizations
description: The Official localizations for Stream Chat Flutter, a service for building chat applications
version: 3.1.0
version: 3.2.0
homepage: https://github.com/GetStream/stream-chat-flutter
repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -14,8 +14,7 @@ dependencies:
sdk: flutter
flutter_localizations:
sdk: flutter
stream_chat_flutter: ^4.1.0
stream_chat_flutter: ^4.3.0
dev_dependencies:
dart_code_metrics: ^4.4.0
flutter_test:
@@ -1,3 +1,7 @@
## 4.2.0
- Added support for `Channel.ownCapabilities`
## 4.1.0
🔄 Changed
@@ -11,9 +11,8 @@ dependencies:
cupertino_icons: ^1.0.3
flutter:
sdk: flutter
stream_chat: ^2.2.1
stream_chat_persistence: ^2.2.0
stream_chat: ^4.3.0
stream_chat_persistence: ^4.2.0
dev_dependencies:
flutter_test:
sdk: flutter
@@ -56,7 +56,7 @@ class DriftChatDatabase extends _$DriftChatDatabase {
// you should bump this number whenever you change or add a table definition.
@override
int get schemaVersion => 8;
int get schemaVersion => 9;
@override
MigrationStrategy get migration => MigrationStrategy(
@@ -6,7 +6,7 @@ part of 'drift_chat_database.dart';
// MoorGenerator
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this
// ignore_for_file: type=lint
class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
/// The id of this channel
final String id;
@@ -17,6 +17,9 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
/// The cid of this channel
final String cid;
/// List of user permissions on this channel
final List<String>? ownCapabilities;
/// The channel configuration data
final Map<String, dynamic> config;
@@ -47,6 +50,7 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
{required this.id,
required this.type,
required this.cid,
this.ownCapabilities,
required this.config,
required this.frozen,
this.lastMessageAt,
@@ -65,7 +69,9 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
.mapFromDatabaseResponse(data['${effectivePrefix}type'])!,
cid: const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}cid'])!,
config: $ChannelsTable.$converter0.mapToDart(const StringType()
ownCapabilities: $ChannelsTable.$converter0.mapToDart(const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}own_capabilities'])),
config: $ChannelsTable.$converter1.mapToDart(const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}config']))!,
frozen: const BoolType()
.mapFromDatabaseResponse(data['${effectivePrefix}frozen'])!,
@@ -81,7 +87,7 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
.mapFromDatabaseResponse(data['${effectivePrefix}member_count'])!,
createdById: const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}created_by_id']),
extraData: $ChannelsTable.$converter1.mapToDart(const StringType()
extraData: $ChannelsTable.$converter2.mapToDart(const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])),
);
}
@@ -91,8 +97,13 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
map['id'] = Variable<String>(id);
map['type'] = Variable<String>(type);
map['cid'] = Variable<String>(cid);
{
if (!nullToAbsent || ownCapabilities != null) {
final converter = $ChannelsTable.$converter0;
map['own_capabilities'] =
Variable<String?>(converter.mapToSql(ownCapabilities));
}
{
final converter = $ChannelsTable.$converter1;
map['config'] = Variable<String>(converter.mapToSql(config)!);
}
map['frozen'] = Variable<bool>(frozen);
@@ -109,7 +120,7 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
map['created_by_id'] = Variable<String?>(createdById);
}
if (!nullToAbsent || extraData != null) {
final converter = $ChannelsTable.$converter1;
final converter = $ChannelsTable.$converter2;
map['extra_data'] = Variable<String?>(converter.mapToSql(extraData));
}
return map;
@@ -122,6 +133,8 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
id: serializer.fromJson<String>(json['id']),
type: serializer.fromJson<String>(json['type']),
cid: serializer.fromJson<String>(json['cid']),
ownCapabilities:
serializer.fromJson<List<String>?>(json['ownCapabilities']),
config: serializer.fromJson<Map<String, dynamic>>(json['config']),
frozen: serializer.fromJson<bool>(json['frozen']),
lastMessageAt: serializer.fromJson<DateTime?>(json['lastMessageAt']),
@@ -140,6 +153,7 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
'id': serializer.toJson<String>(id),
'type': serializer.toJson<String>(type),
'cid': serializer.toJson<String>(cid),
'ownCapabilities': serializer.toJson<List<String>?>(ownCapabilities),
'config': serializer.toJson<Map<String, dynamic>>(config),
'frozen': serializer.toJson<bool>(frozen),
'lastMessageAt': serializer.toJson<DateTime?>(lastMessageAt),
@@ -156,6 +170,7 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
{String? id,
String? type,
String? cid,
Value<List<String>?> ownCapabilities = const Value.absent(),
Map<String, dynamic>? config,
bool? frozen,
Value<DateTime?> lastMessageAt = const Value.absent(),
@@ -169,6 +184,9 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
id: id ?? this.id,
type: type ?? this.type,
cid: cid ?? this.cid,
ownCapabilities: ownCapabilities.present
? ownCapabilities.value
: this.ownCapabilities,
config: config ?? this.config,
frozen: frozen ?? this.frozen,
lastMessageAt:
@@ -186,6 +204,7 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
..write('id: $id, ')
..write('type: $type, ')
..write('cid: $cid, ')
..write('ownCapabilities: $ownCapabilities, ')
..write('config: $config, ')
..write('frozen: $frozen, ')
..write('lastMessageAt: $lastMessageAt, ')
@@ -200,8 +219,20 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
}
@override
int get hashCode => Object.hash(id, type, cid, config, frozen, lastMessageAt,
createdAt, updatedAt, deletedAt, memberCount, createdById, extraData);
int get hashCode => Object.hash(
id,
type,
cid,
ownCapabilities,
config,
frozen,
lastMessageAt,
createdAt,
updatedAt,
deletedAt,
memberCount,
createdById,
extraData);
@override
bool operator ==(Object other) =>
identical(this, other) ||
@@ -209,6 +240,7 @@ class ChannelEntity extends DataClass implements Insertable<ChannelEntity> {
other.id == this.id &&
other.type == this.type &&
other.cid == this.cid &&
other.ownCapabilities == this.ownCapabilities &&
other.config == this.config &&
other.frozen == this.frozen &&
other.lastMessageAt == this.lastMessageAt &&
@@ -224,6 +256,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
final Value<String> id;
final Value<String> type;
final Value<String> cid;
final Value<List<String>?> ownCapabilities;
final Value<Map<String, dynamic>> config;
final Value<bool> frozen;
final Value<DateTime?> lastMessageAt;
@@ -237,6 +270,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
this.id = const Value.absent(),
this.type = const Value.absent(),
this.cid = const Value.absent(),
this.ownCapabilities = const Value.absent(),
this.config = const Value.absent(),
this.frozen = const Value.absent(),
this.lastMessageAt = const Value.absent(),
@@ -251,6 +285,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
required String id,
required String type,
required String cid,
this.ownCapabilities = const Value.absent(),
required Map<String, dynamic> config,
this.frozen = const Value.absent(),
this.lastMessageAt = const Value.absent(),
@@ -268,6 +303,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
Expression<String>? id,
Expression<String>? type,
Expression<String>? cid,
Expression<List<String>?>? ownCapabilities,
Expression<Map<String, dynamic>>? config,
Expression<bool>? frozen,
Expression<DateTime?>? lastMessageAt,
@@ -282,6 +318,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
if (id != null) 'id': id,
if (type != null) 'type': type,
if (cid != null) 'cid': cid,
if (ownCapabilities != null) 'own_capabilities': ownCapabilities,
if (config != null) 'config': config,
if (frozen != null) 'frozen': frozen,
if (lastMessageAt != null) 'last_message_at': lastMessageAt,
@@ -298,6 +335,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
{Value<String>? id,
Value<String>? type,
Value<String>? cid,
Value<List<String>?>? ownCapabilities,
Value<Map<String, dynamic>>? config,
Value<bool>? frozen,
Value<DateTime?>? lastMessageAt,
@@ -311,6 +349,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
id: id ?? this.id,
type: type ?? this.type,
cid: cid ?? this.cid,
ownCapabilities: ownCapabilities ?? this.ownCapabilities,
config: config ?? this.config,
frozen: frozen ?? this.frozen,
lastMessageAt: lastMessageAt ?? this.lastMessageAt,
@@ -335,8 +374,13 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
if (cid.present) {
map['cid'] = Variable<String>(cid.value);
}
if (config.present) {
if (ownCapabilities.present) {
final converter = $ChannelsTable.$converter0;
map['own_capabilities'] =
Variable<String?>(converter.mapToSql(ownCapabilities.value));
}
if (config.present) {
final converter = $ChannelsTable.$converter1;
map['config'] = Variable<String>(converter.mapToSql(config.value)!);
}
if (frozen.present) {
@@ -361,7 +405,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
map['created_by_id'] = Variable<String?>(createdById.value);
}
if (extraData.present) {
final converter = $ChannelsTable.$converter1;
final converter = $ChannelsTable.$converter2;
map['extra_data'] =
Variable<String?>(converter.mapToSql(extraData.value));
}
@@ -374,6 +418,7 @@ class ChannelsCompanion extends UpdateCompanion<ChannelEntity> {
..write('id: $id, ')
..write('type: $type, ')
..write('cid: $cid, ')
..write('ownCapabilities: $ownCapabilities, ')
..write('config: $config, ')
..write('frozen: $frozen, ')
..write('lastMessageAt: $lastMessageAt, ')
@@ -409,12 +454,20 @@ class $ChannelsTable extends Channels
late final GeneratedColumn<String?> cid = GeneratedColumn<String?>(
'cid', aliasedName, false,
type: const StringType(), requiredDuringInsert: true);
final VerificationMeta _ownCapabilitiesMeta =
const VerificationMeta('ownCapabilities');
@override
late final GeneratedColumnWithTypeConverter<List<String>, String?>
ownCapabilities = GeneratedColumn<String?>(
'own_capabilities', aliasedName, true,
type: const StringType(), requiredDuringInsert: false)
.withConverter<List<String>>($ChannelsTable.$converter0);
final VerificationMeta _configMeta = const VerificationMeta('config');
@override
late final GeneratedColumnWithTypeConverter<Map<String, dynamic>, String?>
config = GeneratedColumn<String?>('config', aliasedName, false,
type: const StringType(), requiredDuringInsert: true)
.withConverter<Map<String, dynamic>>($ChannelsTable.$converter0);
.withConverter<Map<String, dynamic>>($ChannelsTable.$converter1);
final VerificationMeta _frozenMeta = const VerificationMeta('frozen');
@override
late final GeneratedColumn<bool?> frozen = GeneratedColumn<bool?>(
@@ -467,12 +520,13 @@ class $ChannelsTable extends Channels
late final GeneratedColumnWithTypeConverter<Map<String, Object?>, String?>
extraData = GeneratedColumn<String?>('extra_data', aliasedName, true,
type: const StringType(), requiredDuringInsert: false)
.withConverter<Map<String, Object?>>($ChannelsTable.$converter1);
.withConverter<Map<String, Object?>>($ChannelsTable.$converter2);
@override
List<GeneratedColumn> get $columns => [
id,
type,
cid,
ownCapabilities,
config,
frozen,
lastMessageAt,
@@ -509,6 +563,7 @@ class $ChannelsTable extends Channels
} else if (isInserting) {
context.missing(_cidMeta);
}
context.handle(_ownCapabilitiesMeta, const VerificationResult.success());
context.handle(_configMeta, const VerificationResult.success());
if (data.containsKey('frozen')) {
context.handle(_frozenMeta,
@@ -561,9 +616,11 @@ class $ChannelsTable extends Channels
return $ChannelsTable(attachedDatabase, alias);
}
static TypeConverter<Map<String, dynamic>, String> $converter0 =
static TypeConverter<List<String>, String> $converter0 =
ListConverter<String>();
static TypeConverter<Map<String, dynamic>, String> $converter1 =
MapConverter();
static TypeConverter<Map<String, Object?>, String> $converter1 =
static TypeConverter<Map<String, Object?>, String> $converter2 =
MapConverter<Object?>();
}
@@ -1,6 +1,6 @@
// coverage:ignore-file
import 'package:drift/drift.dart';
import 'package:stream_chat_persistence/src/converter/map_converter.dart';
import 'package:stream_chat_persistence/src/converter/converter.dart';
/// Represents a [Channels] table in [MoorChatDatabase].
@DataClassName('ChannelEntity')
@@ -14,6 +14,10 @@ class Channels extends Table {
/// The cid of this channel
TextColumn get cid => text()();
/// List of user permissions on this channel
TextColumn get ownCapabilities =>
text().nullable().map(ListConverter<String>())();
/// The channel configuration data
TextColumn get config => text().map(MapConverter())();
@@ -8,6 +8,7 @@ extension ChannelEntityX on ChannelEntity {
final config = ChannelConfig.fromJson(this.config);
return ChannelModel(
id: id,
ownCapabilities: ownCapabilities,
config: config,
type: type,
frozen: frozen,
@@ -46,6 +47,7 @@ extension ChannelModelX on ChannelModel {
id: id,
type: type,
cid: cid,
ownCapabilities: ownCapabilities,
config: config.toJson(),
frozen: frozen,
lastMessageAt: lastMessageAt,
@@ -1,7 +1,7 @@
name: stream_chat_persistence
homepage: https://github.com/GetStream/stream-chat-flutter
description: Official Stream Chat Persistence library. Build your own chat experience using Dart and Flutter.
version: 4.1.0
version: 4.2.0
repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -19,8 +19,7 @@ dependencies:
path: ^1.8.0
path_provider: ^2.0.1
sqlite3_flutter_libs: ^0.5.0
stream_chat: ^4.1.0
stream_chat: ^4.3.0
dev_dependencies:
build_runner: ^2.0.1
dart_code_metrics: ^4.4.0
@@ -14,6 +14,7 @@ void main() {
id: 'testId',
type: 'testType',
cid: 'testCid',
ownCapabilities: ['testCapability'],
config: {'max_message_length': 33},
frozen: math.Random().nextBool(),
lastMessageAt: DateTime.now(),
@@ -29,6 +30,7 @@ void main() {
final channelModel = entity.toChannelModel(createdBy: user);
expect(channelModel, isA<ChannelModel>());
expect(channelModel.id, entity.id);
expect(channelModel.ownCapabilities, entity.ownCapabilities);
expect(channelModel.config.toJson()['max_message_length'], 33);
expect(channelModel.frozen, entity.frozen);
expect(channelModel.createdAt, isSameDateAs(entity.createdAt));
@@ -68,6 +70,7 @@ void main() {
final channelModel = channelState.channel!;
expect(channelModel.id, entity.id);
expect(channelModel.ownCapabilities, entity.ownCapabilities);
expect(channelModel.config.toJson()['max_message_length'], 33);
expect(channelModel.frozen, entity.frozen);
expect(channelModel.createdAt, isSameDateAs(entity.createdAt));
@@ -87,6 +90,7 @@ void main() {
id: 'testId',
type: 'testType',
cid: 'testCid',
ownCapabilities: ['testCapability'],
config: ChannelConfig(maxMessageLength: 33),
frozen: math.Random().nextBool(),
lastMessageAt: DateTime.now(),
@@ -101,6 +105,7 @@ void main() {
final channelEntity = model.toEntity();
expect(channelEntity, isA<ChannelEntity>());
expect(channelEntity.id, model.id);
expect(channelEntity.ownCapabilities, model.ownCapabilities);
expect(
channelEntity.config['max_message_length'],
model.config.maxMessageLength,