Merge branch 'develop'
This commit is contained in:
@@ -7,6 +7,7 @@ env:
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
+1
-1
@@ -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);
|
||||
});
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,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);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+2
-2
@@ -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)),
|
||||
|
||||
+19
-18
@@ -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,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user