diff --git a/.github/workflows/legacy_version_analyze.yml b/.github/workflows/legacy_version_analyze.yml index 89c195df..4b462c52 100644 --- a/.github/workflows/legacy_version_analyze.yml +++ b/.github/workflows/legacy_version_analyze.yml @@ -3,7 +3,7 @@ name: legacy_version_analyze env: # Note: The versions below should be manually updated after a new stable # version comes out. - flutter_version: "3.7.12" + flutter_version: "3.10.6" on: push: diff --git a/.github/workflows/stream_flutter_workflow.yml b/.github/workflows/stream_flutter_workflow.yml index 99312316..231e68da 100644 --- a/.github/workflows/stream_flutter_workflow.yml +++ b/.github/workflows/stream_flutter_workflow.yml @@ -2,7 +2,7 @@ name: stream_flutter_workflow env: ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' - flutter_version: "3.10.4" + flutter_channel: "stable" on: pull_request: @@ -37,7 +37,7 @@ jobs: uses: subosito/flutter-action@v2 with: cache: true - flutter-version: ${{ env.flutter_version }} + channel: ${{ env.flutter_channel }} - name: "Install Tools" run: | flutter pub global activate melos @@ -64,7 +64,7 @@ jobs: uses: subosito/flutter-action@v2 with: cache: true - flutter-version: ${{ env.flutter_version }} + channel: ${{ env.flutter_channel }} - name: "Install Tools" run: | flutter pub global activate melos @@ -89,7 +89,7 @@ jobs: uses: subosito/flutter-action@v2 with: cache: true - flutter-version: ${{ env.flutter_version }} + channel: ${{ env.flutter_channel }} - name: "Install Tools" run: | flutter pub global activate melos diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index 2e554c7c..b7734678 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,3 +1,18 @@ +## 6.8.0 + +🐞 Fixed + +- Fixed `Channel.query` not initializing `ChannelState`. + +✅ Added + +- Added support for `channel.countUnreadMentions()` to get the count of unread messages mentioning the current user on a + channel. [#1692](https://github.com/GetStream/stream-chat-flutter/issues/1692) + +🔄 Changed + +- Updated minimum supported `SDK` version to Dart 3.0 + ## 7.0.0-beta.2 - Included the changes from version [6.7.0](#670). diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 838f267c..f588205d 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1339,26 +1339,6 @@ class Channel { return _client.markChannelRead(id!, type, messageId: messageId); } - /// Loads the initial channel state and watches for changes. - Future watch({bool presence = false}) async { - ChannelState response; - - try { - response = await query(watch: true, presence: presence); - } catch (error, stackTrace) { - if (!_initializedCompleter.isCompleted) { - _initializedCompleter.completeError(error, stackTrace); - } - rethrow; - } - - if (state == null) { - _initState(response); - } - - return response; - } - void _initState(ChannelState channelState) { state = ChannelClientState(this, channelState); @@ -1370,6 +1350,22 @@ class Channel { } } + /// Loads the initial channel state and watches for changes. + Future watch({ + bool presence = false, + PaginationParams? messagesPagination, + PaginationParams? membersPagination, + PaginationParams? watchersPagination, + }) { + return query( + watch: true, + presence: presence, + messagesPagination: messagesPagination, + membersPagination: membersPagination, + watchersPagination: watchersPagination, + ); + } + /// Stop watching the channel. Future stopWatching() async { _checkInitialized(); @@ -1435,7 +1431,7 @@ class Channel { ); /// Creates a new channel. - Future create() async => query(state: false); + Future create() => query(state: false); /// Query the API, get messages, members or other channel fields. /// @@ -1450,23 +1446,28 @@ class Channel { PaginationParams? watchersPagination, bool preferOffline = false, }) async { - if (preferOffline && cid != null) { - final updatedState = await _client.chatPersistenceClient - ?.getChannelStateByCid(cid!, messagePagination: messagesPagination); - if (updatedState != null && - updatedState.messages != null && - updatedState.messages!.isNotEmpty) { - if (this.state == null) { - _initState(updatedState); - } else { - this.state?.updateChannelState(updatedState); - } - return updatedState; - } - } + ChannelState? channelState; try { - final updatedState = await _client.queryChannel( + // If we prefer offline, we first try to get the channel state from the + // offline storage. + if (preferOffline && !watch && cid != null) { + final persistenceClient = _client.chatPersistenceClient; + if (persistenceClient != null) { + final cachedState = await persistenceClient.getChannelStateByCid( + cid!, + messagePagination: messagesPagination, + ); + + // If the cached state contains messages, we can use it. + if (cachedState.messages?.isNotEmpty == true) { + channelState = cachedState; + } + } + } + + // If we still don't have the channelState, we try to get it from the API. + channelState ??= await _client.queryChannel( type, channelId: id, channelData: _extraData, @@ -1479,18 +1480,35 @@ class Channel { ); if (_id == null) { - _id = updatedState.channel!.id; - _cid = updatedState.channel!.cid; + _id = channelState.channel!.id; + _cid = channelState.channel!.cid; } - this.state?.updateChannelState(updatedState); - return updatedState; - } catch (e) { - if (_client.persistenceEnabled) { - return _client.chatPersistenceClient!.getChannelStateByCid( - cid!, - messagePagination: messagesPagination, - ); + // Initialize the channel state if it's not initialized yet. + if (this.state == null) { + _initState(channelState); + } else { + // Otherwise, update the channel state. + this.state?.updateChannelState(channelState); + } + + return channelState; + } catch (e, stk) { + // If we failed to get the channel state from the API and we were not + // supposed to watch the channel, we will try to get the channel state + // from the offline storage. + if (watch == false) { + if (_client.persistenceEnabled) { + return _client.chatPersistenceClient!.getChannelStateByCid( + cid!, + messagePagination: messagesPagination, + ); + } + } + + // Otherwise, we will just rethrow the error. + if (!_initializedCompleter.isCompleted) { + _initializedCompleter.completeError(e, stk); } rethrow; @@ -2334,6 +2352,26 @@ class ChannelClientState { !isThreadMessage; } + /// Counts the number of unread messages mentioning the current user. + /// + /// **NOTE**: The method relies on the [Channel.messages] list and doesn't do + /// any API call. Therefore, the count might be not reliable as it relies on + /// the local data. + int countUnreadMentions() { + final lastRead = currentUserRead?.lastRead; + final userId = _channel.client.state.currentUser?.id; + + var count = 0; + for (final message in messages) { + if (_countMessageAsUnread(message) && + (lastRead == null || message.createdAt.isAfter(lastRead)) && + message.mentionedUsers.any((user) => user.id == userId) == true) { + count++; + } + } + return count; + } + /// Update threads with updated information about messages. void updateThreadInfo(String parentId, List messages) { final newThreads = Map>.from(threads); diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index 41054163..849d387d 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -1685,7 +1685,7 @@ class ClientState { void updateUsers(List userList) { final newUsers = { ...users, - for (var user in userList) + for (final user in userList) if (user != null) user.id: user, }; _usersController.add(newUsers); diff --git a/packages/stream_chat/pubspec.yaml b/packages/stream_chat/pubspec.yaml index a94e3524..9a220619 100644 --- a/packages/stream_chat/pubspec.yaml +++ b/packages/stream_chat/pubspec.yaml @@ -11,11 +11,11 @@ environment: dependencies: async: ^2.11.0 collection: ^1.17.1 - dio: ^5.2.1+1 + dio: ^5.3.2 equatable: ^2.0.5 freezed_annotation: ^2.4.1 http_parser: ^4.0.2 - jose: ^0.3.3 + jose: ^0.3.4 json_annotation: ^4.8.1 logging: ^1.2.0 meta: ^1.9.1 @@ -28,7 +28,7 @@ dependencies: dev_dependencies: build_runner: ^2.4.6 - freezed: ^2.4.1 + freezed: ^2.4.2 json_serializable: ^6.7.1 - mocktail: ^0.3.0 - test: ^1.24.4 + mocktail: ^1.0.0 + test: ^1.24.6 diff --git a/packages/stream_chat/test/src/client/client_test.dart b/packages/stream_chat/test/src/client/client_test.dart index df167b23..87053d9b 100644 --- a/packages/stream_chat/test/src/client/client_test.dart +++ b/packages/stream_chat/test/src/client/client_test.dart @@ -975,7 +975,7 @@ void main() { // skipping initial seed event -> {} users client.state.usersStream.skip(1), emitsInOrder([ - {for (var user in users) user.id: user}, + {for (final user in users) user.id: user}, ]), ); diff --git a/packages/stream_chat/test/src/core/http/interceptor/additional_headers_interceptor_test.dart b/packages/stream_chat/test/src/core/http/interceptor/additional_headers_interceptor_test.dart index 88cf42ae..5a30bd5b 100644 --- a/packages/stream_chat/test/src/core/http/interceptor/additional_headers_interceptor_test.dart +++ b/packages/stream_chat/test/src/core/http/interceptor/additional_headers_interceptor_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: invalid_use_of_protected_member + import 'package:dio/dio.dart'; import 'package:stream_chat/src/core/http/interceptor/additional_headers_interceptor.dart'; import 'package:stream_chat/stream_chat.dart'; diff --git a/packages/stream_chat/test/src/core/http/interceptor/auth_interceptor_test.dart b/packages/stream_chat/test/src/core/http/interceptor/auth_interceptor_test.dart index e5d06600..be982d47 100644 --- a/packages/stream_chat/test/src/core/http/interceptor/auth_interceptor_test.dart +++ b/packages/stream_chat/test/src/core/http/interceptor/auth_interceptor_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: invalid_use_of_protected_member + import 'package:dio/dio.dart'; import 'package:mocktail/mocktail.dart'; import 'package:stream_chat/src/core/http/interceptor/auth_interceptor.dart'; diff --git a/packages/stream_chat/test/src/core/http/interceptor/connection_id_interceptor_test.dart b/packages/stream_chat/test/src/core/http/interceptor/connection_id_interceptor_test.dart index 9acabccf..92d39185 100644 --- a/packages/stream_chat/test/src/core/http/interceptor/connection_id_interceptor_test.dart +++ b/packages/stream_chat/test/src/core/http/interceptor/connection_id_interceptor_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: invalid_use_of_protected_member + import 'package:dio/dio.dart'; import 'package:mocktail/mocktail.dart'; import 'package:stream_chat/src/core/http/connection_id_manager.dart'; diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 7eea2885..87c00c8b 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,3 +1,38 @@ +## 6.9.0 + +🐞 Fixed + +- [[#1702]](https://github.com/GetStream/stream-chat-flutter/issues/1702) + Fixed `Message.replaceMentions` not treating `@usernames` as mentions. +- [[#1694]](https://github.com/GetStream/stream-chat-flutter/issues/1694) Fixed Video player buttons + getting covered by bottom toolbar. + +✅ Added + +- Added support for listening error events in AttachmentPickerBottomSheet. +- Added support for overriding the `MessageWidget.onReactionTap` callback. +- Added support for `StreamMessageInput.contentInsertionConfiguration` to specify the content insertion configuration. + [#1613](https://github.com/GetStream/stream-chat-flutter/issues/1613) + + ```dart + StreamMessageInput( + ..., + contentInsertionConfiguration: ContentInsertionConfiguration( + onContentInserted: (content) { + // Do something with the content. + controller.addAttachment(...); + }, + ), + ) + ``` + +🔄 Changed + +- Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0 +- Updated `stream_chat_flutter_core` dependency + to [`6.8.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog). +- Updated jiffy dependency to ^6.2.1. + ## 7.0.0-beta.3 - Included the changes from version [6.8.1](#681). @@ -85,43 +120,57 @@ 🐞 Fixed -- [[#1620]](https://github.com/GetStream/stream-chat-flutter/issues/1620) Fixed messages Are Not Hard Deleting even +- [[#1620]](https://github.com/GetStream/stream-chat-flutter/issues/1620) Fixed messages Are Not + Hard Deleting even after overriding the `onConfirmDeleteTap` callback. -- [[#1621]](https://github.com/GetStream/stream-chat-flutter/issues/1621) Fixed `createdAtStyle` null check error +- [[#1621]](https://github.com/GetStream/stream-chat-flutter/issues/1621) Fixed `createdAtStyle` + null check error in `SendingIndicatorBuilder`. -- [[#1069]](https://github.com/GetStream/stream-chat-flutter/issues/1069) Fixed message swipe to reply using same - direction for both current user and other users. It now uses `SwipeDirection.startToEnd` for current user +- [[#1069]](https://github.com/GetStream/stream-chat-flutter/issues/1069) Fixed message swipe to + reply using same + direction for both current user and other users. It now uses `SwipeDirection.startToEnd` for + current user and `SwipeDirection.endToStart` for other users. - [[#1590]](https://github.com/GetStream/stream-chat-flutter/issues/1590) - Fixed `StreamMessageWidget.showReactionPickerIndicator` not toggling the reaction picker indicator visibility. -- [[#1639]](https://github.com/GetStream/stream-chat-flutter/issues/1639) Fixed attachments not showing in gallery view + Fixed `StreamMessageWidget.showReactionPickerIndicator` not toggling the reaction picker indicator + visibility. +- [[#1639]](https://github.com/GetStream/stream-chat-flutter/issues/1639) Fixed attachments not + showing in gallery view even after saving them to the device. > **Note** - > This fix depends on the [image_gallery_saver](https://pub.dev/packages/image_gallery_saver) plugin. Make sure to add + > This fix depends on the [image_gallery_saver](https://pub.dev/packages/image_gallery_saver) + plugin. Make sure to add necessary permissions in your App as per the plugin documentation. -- [[#1642]](https://github.com/GetStream/stream-chat-flutter/issues/1642) Fixed `StreamMessageWidget.widthFactor` not +- [[#1642]](https://github.com/GetStream/stream-chat-flutter/issues/1642) + Fixed `StreamMessageWidget.widthFactor` not working on web and desktop platforms. ✅ Added -- Added support for customizing attachments in `StreamMessageInput`. Use various properties mentioned +- Added support for customizing attachments in `StreamMessageInput`. Use various properties + mentioned below. [#1511](https://github.com/GetStream/stream-chat-flutter/issues/1511) * `StreamMessageInput.attachmentListBuilder` to customize the attachment list. * `StreamMessageInput.fileAttachmentListBuilder` to customize the file attachment list. - * `StreamMessageInput.mediaAttachmentListBuilder` to customize the media attachment list. Includes images, videos + * `StreamMessageInput.mediaAttachmentListBuilder` to customize the media attachment list. + Includes images, videos and gifs. - * `StreamMessageInput.fileAttachmentBuilder` to customize the file attachment item shown in `FileAttachmentList`. + * `StreamMessageInput.fileAttachmentBuilder` to customize the file attachment item shown + in `FileAttachmentList`. * `StreamMessageInput.mediaAttachmentBuilder` to customize the media attachment item shown in `MediaAttachmentList`. -- Added `StreamMessageInput.quotedMessageAttachmentThumbnailBuilders` to customize the thumbnail builders for quoted +- Added `StreamMessageInput.quotedMessageAttachmentThumbnailBuilders` to customize the thumbnail + builders for quoted message attachments. 🔄 Changed -- Deprecated `StreamMessageInput.attachmentThumbnailBuilders` in favor of `StreamMessageInput.mediaAttachmentBuilder`. -- Deprecated `StreamMessageListView.onMessageSwiped`. Try wrapping the `MessageWidget` with a `Swipeable`, `Dismissible` +- Deprecated `StreamMessageInput.attachmentThumbnailBuilders` in favor + of `StreamMessageInput.mediaAttachmentBuilder`. +- Deprecated `StreamMessageListView.onMessageSwiped`. Try wrapping the `MessageWidget` with + a `Swipeable`, `Dismissible` or a custom widget to achieve the swipe to reply behaviour. ```dart @@ -169,7 +218,8 @@ }, ) ``` -- Deprecated `StreamMessageWidget.showReactionPickerIndicator` in favor of `StreamMessageWidget.showReactionPicker`. +- Deprecated `StreamMessageWidget.showReactionPickerIndicator` in favor + of `StreamMessageWidget.showReactionPicker`. ```diff StreamMessageWidget( @@ -186,16 +236,20 @@ 🐞 Fixed -- [[#1600]](https://github.com/GetStream/stream-chat-flutter/issues/1600) Fixed type `ImageDecoderCallback` not found +- [[#1600]](https://github.com/GetStream/stream-chat-flutter/issues/1600) Fixed + type `ImageDecoderCallback` not found error on pre-Flutter 3.10.0 versions. -- [[#1605]](https://github.com/GetStream/stream-chat-flutter/issues/1605) Fixed Null exception is thrown on message list +- [[#1605]](https://github.com/GetStream/stream-chat-flutter/issues/1605) Fixed Null exception is + thrown on message list for unread messages when `ScrollToBottomButton` is pressed. -- [[#1615]](https://github.com/GetStream/stream-chat-flutter/issues/1615) Fixed `StreamAttachmentPickerBottomSheet` not +- [[#1615]](https://github.com/GetStream/stream-chat-flutter/issues/1615) + Fixed `StreamAttachmentPickerBottomSheet` not able to find the `StreamChatTheme` when used in nested MaterialApp. ✅ Added -- Added support for `StreamMessageInput.allowedAttachmentPickerTypes` to specify the allowed attachment picker types. +- Added support for `StreamMessageInput.allowedAttachmentPickerTypes` to specify the allowed + attachment picker types. [#1601](https://github.com/GetStream/stream-chat-flutter/issues/1376) ```dart @@ -208,7 +262,8 @@ ) ``` -- Added support for `StreamMessageWidget.onConfirmDeleteTap` to override the default action on delete confirmation. +- Added support for `StreamMessageWidget.onConfirmDeleteTap` to override the default action on + delete confirmation. [#1604](https://github.com/GetStream/stream-chat-flutter/issues/1604) ```dart @@ -221,8 +276,10 @@ ) ``` -- Added support for `StreamMessageWidget.quotedMessageBuilder` and `StreamMessageInput.quotedMessageBuilder` to override - the default quoted message widget. [#1547](https://github.com/GetStream/stream-chat-flutter/issues/1547) +- Added support for `StreamMessageWidget.quotedMessageBuilder` + and `StreamMessageInput.quotedMessageBuilder` to override + the default quoted message + widget. [#1547](https://github.com/GetStream/stream-chat-flutter/issues/1547) ```dart StreamMessageWidget( @@ -236,7 +293,8 @@ ) ``` -- Added support for `StreamChannelAvatar.ownSpaceAvatarBuilder`, `StreamChannelAvatar.oneToOneAvatarBuilder` and +- Added support + for `StreamChannelAvatar.ownSpaceAvatarBuilder`, `StreamChannelAvatar.oneToOneAvatarBuilder` and `StreamChannelAvatar.groupAvatarBuilder` to override the default avatar widget.[#1614](https://github.com/GetStream/stream-chat-flutter/issues/1614) @@ -268,10 +326,13 @@ 🐞 Fixed -- [[#1592]](https://github.com/GetStream/stream-chat-flutter/issues/1592) Fixed broken attachment download on web. -- [[#1591]](https://github.com/GetStream/stream-chat-flutter/issues/1591) Fixed `StreamChannelInfoBottomSheet` not +- [[#1592]](https://github.com/GetStream/stream-chat-flutter/issues/1592) Fixed broken attachment + download on web. +- [[#1591]](https://github.com/GetStream/stream-chat-flutter/issues/1591) + Fixed `StreamChannelInfoBottomSheet` not rendering member list properly. -- [[#1427]](https://github.com/GetStream/stream-chat-flutter/issues/1427) Fixed unable to load asset error for +- [[#1427]](https://github.com/GetStream/stream-chat-flutter/issues/1427) Fixed unable to load asset + error for `packages/stream_chat_flutter/lib/svgs/video_call_icon.svg`. 🔄 Changed @@ -284,30 +345,40 @@ - [[#1546]](https://github.com/GetStream/stream-chat-flutter/issues/1546) Fixed `StreamMessageInputTheme.linkHighlightColor` returning null for default theme. -- [[#1548]](https://github.com/GetStream/stream-chat-flutter/issues/1548) Fixed `StreamMessageInput` urlRegex only +- [[#1548]](https://github.com/GetStream/stream-chat-flutter/issues/1548) Fixed `StreamMessageInput` + urlRegex only matching the lowercase `http(s)|ftp`. -- [[#1542]](https://github.com/GetStream/stream-chat-flutter/issues/1542) Handle error thrown in `StreamMessageInput` +- [[#1542]](https://github.com/GetStream/stream-chat-flutter/issues/1542) Handle error thrown + in `StreamMessageInput` when unable to fetch a link preview. -- [[#1540]](https://github.com/GetStream/stream-chat-flutter/issues/1540) Use `CircularProgressIndicator.adaptive` +- [[#1540]](https://github.com/GetStream/stream-chat-flutter/issues/1540) + Use `CircularProgressIndicator.adaptive` instead of material indicator. -- [[#1490]](https://github.com/GetStream/stream-chat-flutter/issues/1490) Fixed `editMessageInputBuilder` property not +- [[#1490]](https://github.com/GetStream/stream-chat-flutter/issues/1490) + Fixed `editMessageInputBuilder` property not used in `MessageActionsModal.editMessage` option. -- [[#1544]](https://github.com/GetStream/stream-chat-flutter/issues/1544) Fixed error thrown when unable to fetch +- [[#1544]](https://github.com/GetStream/stream-chat-flutter/issues/1544) Fixed error thrown when + unable to fetch image/data in Message link preview. -- [[#1482]](https://github.com/GetStream/stream-chat-flutter/issues/1482) Fixed `StreaChannelListTile` not showing +- [[#1482]](https://github.com/GetStream/stream-chat-flutter/issues/1482) + Fixed `StreaChannelListTile` not showing unread indicator when `currentUser` is not present in the initial member list. - [[#1487]](https://github.com/GetStream/stream-chat-flutter/issues/1487) Use localized title for `WebOrDesktopAttachmentPickerOption` in `StreamMessageInput`. -- [[#1250]](https://github.com/GetStream/stream-chat-flutter/issues/1250) Fixed bottomRow widgetSpans getting resized +- [[#1250]](https://github.com/GetStream/stream-chat-flutter/issues/1250) Fixed bottomRow + widgetSpans getting resized twice when `textScaling` is enabled. -- [[#1498]](https://github.com/GetStream/stream-chat-flutter/issues/1498) Fixed `MessageInput` autocomplete not working +- [[#1498]](https://github.com/GetStream/stream-chat-flutter/issues/1498) Fixed `MessageInput` + autocomplete not working on non-mobile platforms. -- [[#1576]](https://github.com/GetStream/stream-chat-flutter/issues/1576) Temporary fix for `StreamMessageListView` +- [[#1576]](https://github.com/GetStream/stream-chat-flutter/issues/1576) Temporary fix + for `StreamMessageListView` getting broken when loaded at a particular message and a new message is added. ✅ Added -- Added support for `StreamMessageThemeData.urlAttachmentTextMaxLine` to specify the `.maxLines` for the url attachment +- Added support for `StreamMessageThemeData.urlAttachmentTextMaxLine` to specify the `.maxLines` for + the url attachment text. [#1543](https://github.com/GetStream/stream-chat-flutter/issues/1543) 🔄 Changed @@ -322,24 +393,33 @@ 🐞 Fixed -- [[#1502]](https://github.com/GetStream/stream-chat-flutter/issues/1502) Fixed `isOnlyEmoji` method Detects Single +- [[#1502]](https://github.com/GetStream/stream-chat-flutter/issues/1502) Fixed `isOnlyEmoji` method + Detects Single Hangul Consonants as Emoji. -- [[#1505]](https://github.com/GetStream/stream-chat-flutter/issues/1505) Fixed Message bubble disappears for Hangul +- [[#1505]](https://github.com/GetStream/stream-chat-flutter/issues/1505) Fixed Message bubble + disappears for Hangul Consonants. -- [[#1476]](https://github.com/GetStream/stream-chat-flutter/issues/1476) Fixed `UserAvatarTransform.userAvatarBuilder` +- [[#1476]](https://github.com/GetStream/stream-chat-flutter/issues/1476) + Fixed `UserAvatarTransform.userAvatarBuilder` works only for otherUser. -- [[#1490]](https://github.com/GetStream/stream-chat-flutter/issues/1490) Fixed `editMessageInputBuilder` property not +- [[#1490]](https://github.com/GetStream/stream-chat-flutter/issues/1490) + Fixed `editMessageInputBuilder` property not used in message edit widget. -- [[#1523]](https://github.com/GetStream/stream-chat-flutter/issues/1523) Fixed `StreamMessageThemeData` not being +- [[#1523]](https://github.com/GetStream/stream-chat-flutter/issues/1523) + Fixed `StreamMessageThemeData` not being applied correctly. -- [[#1525]](https://github.com/GetStream/stream-chat-flutter/issues/1525) Fixed `StreamQuotedMessageWidget` message for +- [[#1525]](https://github.com/GetStream/stream-chat-flutter/issues/1525) + Fixed `StreamQuotedMessageWidget` message for deleted messages not being shown correctly. -- [[#1529]](https://github.com/GetStream/stream-chat-flutter/issues/1529) Fixed `ClipboardData` requires non-nullable +- [[#1529]](https://github.com/GetStream/stream-chat-flutter/issues/1529) Fixed `ClipboardData` + requires non-nullable string as text on Flutter 3.10. -- [[#1533]](https://github.com/GetStream/stream-chat-flutter/issues/1533) Fixed `StreamMessageListView` messages grouped +- [[#1533]](https://github.com/GetStream/stream-chat-flutter/issues/1533) + Fixed `StreamMessageListView` messages grouped incorrectly w.r.t. timestamp. -- [[#1532]](https://github.com/GetStream/stream-chat-flutter/issues/1532) Fixed `StreamMessageWidget` actions dialog +- [[#1532]](https://github.com/GetStream/stream-chat-flutter/issues/1532) + Fixed `StreamMessageWidget` actions dialog backdrop filter is cut off by safe area. ✅ Added @@ -387,7 +467,8 @@ 🔄 Changed - Updated `dart` sdk environment range to support `3.0.0`. -- Deprecated `MessageTheme.linkBackgroundColor` in favor of `MessageTheme.urlAttachmentBackgroundColor`. +- Deprecated `MessageTheme.linkBackgroundColor` in favor + of `MessageTheme.urlAttachmentBackgroundColor`. - Updated `stream_chat_flutter_core` dependency to [`6.1.0`](https://pub.dev/packages/stream_chat_flutter_core/changelog). @@ -395,18 +476,23 @@ 🐞 Fixed -- [[#1456]](https://github.com/GetStream/stream-chat-flutter/issues/1456) Fixed logic for showing that a message was +- [[#1456]](https://github.com/GetStream/stream-chat-flutter/issues/1456) Fixed logic for showing + that a message was read using sending indicator. -- [[#1462]](https://github.com/GetStream/stream-chat-flutter/issues/1462) Fixed support for iPad in the share button for +- [[#1462]](https://github.com/GetStream/stream-chat-flutter/issues/1462) Fixed support for iPad in + the share button for images. -- [[#1475]](https://github.com/GetStream/stream-chat-flutter/issues/1475) Fixed typo to fix compilation. +- [[#1475]](https://github.com/GetStream/stream-chat-flutter/issues/1475) Fixed typo to fix + compilation. ✅ Added -- Now it is possible to customize the max lines of the title of a url attachment. Before it was always 1 line. +- Now it is possible to customize the max lines of the title of a url attachment. Before it was + always 1 line. - Added `attachmentActionsModalBuilder` parameter to `StreamMessageWidget` that allows to customize `AttachmentActionsModal`. -- Added `StreamMessageInput.sendMessageKeyPredicate` and `StreamMessageInput.clearQuotedMessageKeyPredicate` to +- Added `StreamMessageInput.sendMessageKeyPredicate` + and `StreamMessageInput.clearQuotedMessageKeyPredicate` to customize the keys used to send and clear the quoted message. 🔄 Changed @@ -415,7 +501,8 @@ 🚀 Improved -- Improved draw of reaction options. [#1455](https://github.com/GetStream/stream-chat-flutter/pull/1455) +- Improved draw of reaction + options. [#1455](https://github.com/GetStream/stream-chat-flutter/pull/1455) ## 5.3.0 @@ -425,7 +512,8 @@ 🐞 Fixed -- [[#1424]](https://github.com/GetStream/stream-chat-flutter/issues/1424) Fixed a render issue when showing messages +- [[#1424]](https://github.com/GetStream/stream-chat-flutter/issues/1424) Fixed a render issue when + showing messages starting with 4 whitespaces. - Fixed a bug where the `AttachmentPickerBottomSheet` was not able to identify the mobile browser. - Fixed uploading files on Windows - fixed temp file path. @@ -438,7 +526,8 @@ ✅ Added -- Added a new `bottomRowBuilderWithDefaultWidget` parameter to `StreamMessageWidget` which contains a third parameter ( +- Added a new `bottomRowBuilderWithDefaultWidget` parameter to `StreamMessageWidget` which contains + a third parameter ( default `BottomRow` widget with `copyWith` method available) to allow easier customization. 🔄 Changed @@ -448,18 +537,23 @@ - Updated `connectivity_plus` dependency to `^3.0.2` - Updated `dart_vlc` dependency to `^0.4.0` - Updated `file_picker` dependency to `^5.2.4` -- Deprecated `StreamMessageWidget.bottomRowBuilder` in favor of `StreamMessageWidget.bottomRowBuilderWithDefaultWidget`. +- Deprecated `StreamMessageWidget.bottomRowBuilder` in favor + of `StreamMessageWidget.bottomRowBuilderWithDefaultWidget`. - Deprecated `StreamMessageWidget.deletedBottomRowBuilder` in favor of `StreamMessageWidget.bottomRowBuilderWithDefaultWidget`. -- Deprecated `StreamMessageWidget.usernameBuilder` in favor of `StreamMessageWidget.bottomRowBuilderWithDefaultWidget`. +- Deprecated `StreamMessageWidget.usernameBuilder` in favor + of `StreamMessageWidget.bottomRowBuilderWithDefaultWidget`. 🐞 Fixed -- [[#1379]](https://github.com/GetStream/stream-chat-flutter/issues/1379) Fixed "Issues with photo attachments on web", +- [[#1379]](https://github.com/GetStream/stream-chat-flutter/issues/1379) Fixed "Issues with photo + attachments on web", where the cached image attachment would not render while uploading. -- Fix render overflow issue with `MessageSearchListTileTitle`. It now uses `Text.rich` instead of `Row`. Better default +- Fix render overflow issue with `MessageSearchListTileTitle`. It now uses `Text.rich` instead + of `Row`. Better default behaviour and allows `TextOverflow`. -- [[1346]](https://github.com/GetStream/stream-chat-flutter/issues/1346) Fixed a render issue while uploading video on +- [[1346]](https://github.com/GetStream/stream-chat-flutter/issues/1346) Fixed a render issue while + uploading video on web. - [[#1347]](https://github.com/GetStream/stream-chat-flutter/issues/1347) `onReply` not working in `AttachmentActionsModal` which is used by `StreamImageAttachment` and `StreamImageGroup`. @@ -502,7 +596,8 @@ * `textInputAction` * `keyboardType` * `textCapitalization` -- Added `showStreamAttachmentPickerModalBottomSheet` to show the attachment picker modal bottom sheet. +- Added `showStreamAttachmentPickerModalBottomSheet` to show the attachment picker modal bottom + sheet. 🔄 Changed diff --git a/packages/stream_chat_flutter/lib/src/avatars/group_avatar.dart b/packages/stream_chat_flutter/lib/src/avatars/group_avatar.dart index be70bdbf..146a6643 100644 --- a/packages/stream_chat_flutter/lib/src/avatars/group_avatar.dart +++ b/packages/stream_chat_flutter/lib/src/avatars/group_avatar.dart @@ -66,7 +66,8 @@ class StreamGroupAvatar extends StatelessWidget { Widget avatar = GestureDetector( onTap: onTap, child: ClipRRect( - borderRadius: borderRadius ?? previewTheme?.borderRadius, + borderRadius: + borderRadius ?? previewTheme?.borderRadius ?? BorderRadius.zero, child: Container( constraints: constraints ?? previewTheme?.constraints, decoration: BoxDecoration(color: colorTheme.accentPrimary), diff --git a/packages/stream_chat_flutter/lib/src/avatars/user_avatar.dart b/packages/stream_chat_flutter/lib/src/avatars/user_avatar.dart index 72ec020b..aae50f48 100644 --- a/packages/stream_chat_flutter/lib/src/avatars/user_avatar.dart +++ b/packages/stream_chat_flutter/lib/src/avatars/user_avatar.dart @@ -86,7 +86,8 @@ class StreamUserAvatar extends StatelessWidget { final backupGradientAvatar = ClipRRect( borderRadius: borderRadius ?? - streamChatTheme.ownMessageTheme.avatarTheme?.borderRadius, + streamChatTheme.ownMessageTheme.avatarTheme?.borderRadius ?? + BorderRadius.zero, child: streamChatConfig.defaultUserImage(context, user), ); diff --git a/packages/stream_chat_flutter/lib/src/channel/stream_channel_avatar.dart b/packages/stream_chat_flutter/lib/src/channel/stream_channel_avatar.dart index 9090c33a..8f148a37 100644 --- a/packages/stream_chat_flutter/lib/src/channel/stream_channel_avatar.dart +++ b/packages/stream_chat_flutter/lib/src/channel/stream_channel_avatar.dart @@ -111,7 +111,8 @@ class StreamChannelAvatar extends StatelessWidget { initialData: channel.image, builder: (context, channelImage) { Widget child = ClipRRect( - borderRadius: borderRadius ?? previewTheme?.borderRadius, + borderRadius: + borderRadius ?? previewTheme?.borderRadius ?? BorderRadius.zero, child: Container( constraints: constraints ?? previewTheme?.constraints, decoration: BoxDecoration(color: colorTheme.accentPrimary), diff --git a/packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media.dart b/packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media.dart index 2a791954..a1708e17 100644 --- a/packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media.dart +++ b/packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media.dart @@ -3,13 +3,11 @@ import 'dart:io'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:chewie/chewie.dart'; -import 'package:contextmenu/contextmenu.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:photo_view/photo_view.dart'; import 'package:shimmer/shimmer.dart'; import 'package:stream_chat_flutter/platform_widget_builder/platform_widget_builder.dart'; -import 'package:stream_chat_flutter/src/context_menu_items/download_menu_item.dart'; import 'package:stream_chat_flutter/src/fullscreen_media/full_screen_media_widget.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; @@ -281,84 +279,83 @@ class _FullScreenMediaState extends State { final currentAttachmentPackage = widget.mediaAttachmentPackages[index]; final attachment = currentAttachmentPackage.attachment; - if (attachment.type == 'image' || attachment.type == 'giphy') { - final imageUrl = attachment.imageUrl ?? - attachment.assetUrl ?? - attachment.thumbUrl; - return ValueListenableBuilder( - valueListenable: _isDisplayingDetail, - builder: (context, isDisplayingDetail, _) => - AnimatedContainer( + return ValueListenableBuilder( + valueListenable: _isDisplayingDetail, + builder: (context, isDisplayingDetail, child) { + return AnimatedContainer( + duration: kThemeChangeDuration, color: isDisplayingDetail ? StreamChannelHeaderTheme.of(context).color : Colors.black, - duration: kThemeAnimationDuration, - child: ContextMenuArea( - verticalPadding: 0, - builder: (_) => [ - DownloadMenuItem( - attachment: attachment, - ), - ], - child: PhotoView( - imageProvider: (imageUrl == null && - attachment.localUri != null && - attachment.file?.bytes != null) - ? Image.memory(attachment.file!.bytes!).image - : CachedNetworkImageProvider(imageUrl!), - errorBuilder: (_, __, ___) => const AttachmentError(), - loadingBuilder: (context, _) { - final image = Image.asset( - 'images/placeholder.png', - fit: BoxFit.cover, - package: 'stream_chat_flutter', + child: Builder( + builder: (context) { + if (attachment.type == 'image' || + attachment.type == 'giphy') { + final imageUrl = attachment.imageUrl ?? + attachment.assetUrl ?? + attachment.thumbUrl; + + return PhotoView( + imageProvider: (imageUrl == null && + attachment.localUri != null && + attachment.file?.bytes != null) + ? Image.memory(attachment.file!.bytes!).image + : CachedNetworkImageProvider(imageUrl!), + errorBuilder: (_, __, ___) => + const AttachmentError(), + loadingBuilder: (context, _) { + final image = Image.asset( + 'images/placeholder.png', + fit: BoxFit.cover, + package: 'stream_chat_flutter', + ); + final colorTheme = + StreamChatTheme.of(context).colorTheme; + return Shimmer.fromColors( + baseColor: colorTheme.disabled, + highlightColor: colorTheme.inputBg, + child: image, + ); + }, + maxScale: PhotoViewComputedScale.covered, + minScale: PhotoViewComputedScale.contained, + heroAttributes: PhotoViewHeroAttributes( + tag: widget.mediaAttachmentPackages, + ), + backgroundDecoration: const BoxDecoration( + color: Colors.transparent, + ), ); - final colorTheme = - StreamChatTheme.of(context).colorTheme; - return Shimmer.fromColors( - baseColor: colorTheme.disabled, - highlightColor: colorTheme.inputBg, - child: image, + } else if (attachment.type == 'video') { + final controller = videoPackages[attachment.id]!; + if (!controller.initialized) { + return const Center( + child: CircularProgressIndicator.adaptive(), + ); + } + + final mediaQuery = MediaQuery.of(context); + final bottomPadding = mediaQuery.padding.bottom; + + return AnimatedPadding( + duration: kThemeChangeDuration, + padding: EdgeInsets.symmetric( + vertical: isDisplayingDetail + ? kToolbarHeight + bottomPadding + : 0, + ), + child: Chewie( + controller: controller.chewieController!, + ), ); - }, - maxScale: PhotoViewComputedScale.covered, - minScale: PhotoViewComputedScale.contained, - heroAttributes: PhotoViewHeroAttributes( - tag: widget.mediaAttachmentPackages, - ), - backgroundDecoration: const BoxDecoration( - color: Colors.transparent, - ), - ), + } + + return const SizedBox(); + }, ), - ), - ); - } else if (attachment.type == 'video') { - final controller = videoPackages[attachment.id]!; - if (!controller.initialized) { - return const Center( - child: CircularProgressIndicator.adaptive(), ); - } - return InkWell( - onTap: switchDisplayingDetail, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 50), - child: ContextMenuArea( - verticalPadding: 0, - builder: (_) => [ - DownloadMenuItem( - attachment: attachment, - ), - ], - child: Chewie( - controller: controller.chewieController!, - ), - ), - ), - ); - } - return const SizedBox(); + }, + ); }, ), ), @@ -475,6 +472,7 @@ class VideoPackage { videoPlayerController: _videoPlayerController, autoInitialize: _autoInitialize, showControls: _showControls, + showOptions: false, aspectRatio: _videoPlayerController.value.aspectRatio, ); }); diff --git a/packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart b/packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart index 13185a79..0b870f77 100644 --- a/packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart +++ b/packages/stream_chat_flutter/lib/src/fullscreen_media/full_screen_media_desktop.dart @@ -307,88 +307,95 @@ class _FullScreenMediaDesktopState extends State { final currentAttachmentPackage = widget.mediaAttachmentPackages[index]; final attachment = currentAttachmentPackage.attachment; - if (attachment.type == 'image' || attachment.type == 'giphy') { - final imageUrl = attachment.imageUrl ?? - attachment.assetUrl ?? - attachment.thumbUrl; - return ValueListenableBuilder( - valueListenable: _isDisplayingDetail, - builder: (context, isDisplayingDetail, _) => - AnimatedContainer( + + return ValueListenableBuilder( + valueListenable: _isDisplayingDetail, + builder: (context, isDisplayingDetail, child) { + return AnimatedContainer( + duration: kThemeChangeDuration, color: isDisplayingDetail ? StreamChannelHeaderTheme.of(context).color : Colors.black, - duration: kThemeAnimationDuration, - child: ContextMenuArea( - verticalPadding: 0, - builder: (_) => [ - DownloadMenuItem( - attachment: attachment, - ), - ], - child: PhotoView( - imageProvider: (imageUrl == null && - attachment.localUri != null && - attachment.file?.bytes != null) - ? Image.memory(attachment.file!.bytes!).image - : CachedNetworkImageProvider(imageUrl!), - errorBuilder: (_, __, ___) => const AttachmentError(), - loadingBuilder: (context, _) { - final image = Image.asset( - 'images/placeholder.png', - fit: BoxFit.cover, - package: 'stream_chat_flutter', - ); - final colorTheme = - StreamChatTheme.of(context).colorTheme; - return Shimmer.fromColors( - baseColor: colorTheme.disabled, - highlightColor: colorTheme.inputBg, - child: image, - ); - }, - maxScale: PhotoViewComputedScale.covered, - minScale: PhotoViewComputedScale.contained, - heroAttributes: PhotoViewHeroAttributes( - tag: widget.mediaAttachmentPackages, - ), - backgroundDecoration: const BoxDecoration( - color: Colors.transparent, - ), - ), - ), - ), - ); - } else if (attachment.type == 'video') { - final package = videoPackages[attachment.id]!; - package.player.open( - Playlist( - medias: [ - Media.network(package.attachment.assetUrl), - ], - ), - autoStart: widget.autoplayVideos, - ); + child: Builder( + builder: (context) { + if (attachment.type == 'image' || + attachment.type == 'giphy') { + final imageUrl = attachment.imageUrl ?? + attachment.assetUrl ?? + attachment.thumbUrl; - return InkWell( - onTap: switchDisplayingDetail, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 50), - child: ContextMenuArea( - verticalPadding: 0, - builder: (_) => [ - DownloadMenuItem( - attachment: attachment, - ), - ], - child: Video( - player: package.player, - ), + return PhotoView( + imageProvider: (imageUrl == null && + attachment.localUri != null && + attachment.file?.bytes != null) + ? Image.memory(attachment.file!.bytes!).image + : CachedNetworkImageProvider(imageUrl!), + errorBuilder: (_, __, ___) => + const AttachmentError(), + loadingBuilder: (context, _) { + final image = Image.asset( + 'images/placeholder.png', + fit: BoxFit.cover, + package: 'stream_chat_flutter', + ); + final colorTheme = + StreamChatTheme.of(context).colorTheme; + return Shimmer.fromColors( + baseColor: colorTheme.disabled, + highlightColor: colorTheme.inputBg, + child: image, + ); + }, + maxScale: PhotoViewComputedScale.covered, + minScale: PhotoViewComputedScale.contained, + heroAttributes: PhotoViewHeroAttributes( + tag: widget.mediaAttachmentPackages, + ), + backgroundDecoration: const BoxDecoration( + color: Colors.transparent, + ), + ); + } else if (attachment.type == 'video') { + final package = videoPackages[attachment.id]!; + package.player.open( + Playlist( + medias: [ + Media.network(package.attachment.assetUrl), + ], + ), + autoStart: widget.autoplayVideos, + ); + + final mediaQuery = MediaQuery.of(context); + final bottomPadding = mediaQuery.padding.bottom; + + return AnimatedPadding( + duration: kThemeChangeDuration, + padding: EdgeInsets.symmetric( + vertical: isDisplayingDetail + ? kToolbarHeight + bottomPadding + : 0, + ), + child: ContextMenuArea( + verticalPadding: 0, + builder: (_) => [ + DownloadMenuItem( + attachment: attachment, + ), + ], + child: Video( + player: package.player, + ), + ), + ); + } + + return const SizedBox(); + }, ), - ), - ); - } - return const SizedBox(); + ); + }, + ); }, ), ), diff --git a/packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker.dart b/packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker.dart index 6c8f1f59..94a81412 100644 --- a/packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker.dart +++ b/packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker.dart @@ -698,6 +698,7 @@ Widget mobileAttachmentPickerBuilder({ ThumbnailFormat attachmentThumbnailFormat = ThumbnailFormat.jpeg, int attachmentThumbnailQuality = 100, double attachmentThumbnailScale = 1, + ErrorListener? onError, }) { return StreamMobileAttachmentPickerBottomSheet( controller: controller, @@ -721,10 +722,15 @@ Widget mobileAttachmentPickerBuilder({ mediaThumbnailQuality: attachmentThumbnailQuality, mediaThumbnailScale: attachmentThumbnailScale, onMediaItemSelected: (media) async { - if (selectedIds.contains(media.id)) { - return controller.removeAssetAttachment(media); + try { + if (selectedIds.contains(media.id)) { + return await controller.removeAssetAttachment(media); + } + return await controller.addAssetAttachment(media); + } catch (e, stk) { + if (onError != null) return onError.call(e, stk); + rethrow; } - return controller.addAssetAttachment(media); }, ); }, @@ -736,8 +742,15 @@ Widget mobileAttachmentPickerBuilder({ optionViewBuilder: (context, controller) { return StreamFilePicker( onFilePicked: (file) async { - if (file != null) await controller.addAttachment(file); - return Navigator.pop(context, controller.value); + try { + if (file != null) await controller.addAttachment(file); + return Navigator.pop(context, controller.value); + } catch (e, stk) { + Navigator.pop(context, controller.value); + if (onError != null) return onError.call(e, stk); + + rethrow; + } }, ); }, @@ -749,10 +762,17 @@ Widget mobileAttachmentPickerBuilder({ optionViewBuilder: (context, controller) { return StreamImagePicker( onImagePicked: (image) async { - if (image != null) { - await controller.addAttachment(image); + try { + if (image != null) { + await controller.addAttachment(image); + } + return Navigator.pop(context, controller.value); + } catch (e, stk) { + Navigator.pop(context, controller.value); + if (onError != null) return onError.call(e, stk); + + rethrow; } - return Navigator.pop(context, controller.value); }, ); }, @@ -764,10 +784,17 @@ Widget mobileAttachmentPickerBuilder({ optionViewBuilder: (context, controller) { return StreamVideoPicker( onVideoPicked: (video) async { - if (video != null) { - await controller.addAttachment(video); + try { + if (video != null) { + await controller.addAttachment(video); + } + return Navigator.pop(context, controller.value); + } catch (e, stk) { + Navigator.pop(context, controller.value); + if (onError != null) return onError.call(e, stk); + + rethrow; } - return Navigator.pop(context, controller.value); }, ); }, @@ -787,6 +814,7 @@ Widget webOrDesktopAttachmentPickerBuilder({ ThumbnailFormat attachmentThumbnailFormat = ThumbnailFormat.jpeg, int attachmentThumbnailQuality = 100, double attachmentThumbnailScale = 1, + ErrorListener? onError, }) { return StreamWebOrDesktopAttachmentPickerBottomSheet( controller: controller, @@ -814,13 +842,20 @@ Widget webOrDesktopAttachmentPickerBuilder({ }.where((option) => option.supportedTypes.every(allowedTypes.contains)), }, onOptionTap: (context, controller, option) async { - final attachment = await StreamAttachmentHandler.instance.pickFile( - type: option.type.fileType, - ); - if (attachment != null) { - await controller.addAttachment(attachment); + try { + final attachment = await StreamAttachmentHandler.instance.pickFile( + type: option.type.fileType, + ); + if (attachment != null) { + await controller.addAttachment(attachment); + } + return Navigator.pop(context, controller.value); + } catch (e, stk) { + Navigator.pop(context, controller.value); + if (onError != null) return onError.call(e, stk); + + rethrow; } - return Navigator.pop(context, controller.value); }, ); } diff --git a/packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_bottom_sheet.dart b/packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_bottom_sheet.dart index bc53e4db..4546bce6 100644 --- a/packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_bottom_sheet.dart +++ b/packages/stream_chat_flutter/lib/src/message_input/attachment_picker/stream_attachment_picker_bottom_sheet.dart @@ -69,6 +69,7 @@ Future showStreamAttachmentPickerModalBottomSheet({ List allowedTypes = AttachmentPickerType.values, List? initialAttachments, StreamAttachmentPickerController? controller, + ErrorListener? onError, Color? backgroundColor, double? elevation, BoxConstraints? constraints, @@ -117,6 +118,7 @@ Future showStreamAttachmentPickerModalBottomSheet({ if (isWebOrDesktop) { return webOrDesktopAttachmentPickerBuilder.call( context: context, + onError: onError, controller: controller, allowedTypes: allowedTypes, customOptions: customOptions?.map( @@ -131,6 +133,7 @@ Future showStreamAttachmentPickerModalBottomSheet({ return mobileAttachmentPickerBuilder.call( context: context, + onError: onError, controller: controller, allowedTypes: allowedTypes, customOptions: customOptions, diff --git a/packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart b/packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart index 8bdbfd99..549809d3 100644 --- a/packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart +++ b/packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart @@ -811,6 +811,7 @@ class StreamMessageInputState extends State Future _onAttachmentButtonPressed() async { final attachments = await showStreamAttachmentPickerModalBottomSheet( context: context, + onError: widget.onError, allowedTypes: widget.allowedAttachmentPickerTypes, initialAttachments: _effectiveController.attachments, ); diff --git a/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart b/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart index d0ac97a9..6185c04a 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart @@ -55,6 +55,7 @@ class StreamMessageWidget extends StatefulWidget { this.attachmentBorderRadiusGeometry, this.onMentionTap, this.onMessageTap, + this.onReactionsTap, this.showReactionPicker = true, @internal this.showReactionPickerTail = false, this.showUserAvatar = DisplayWidget.show, @@ -524,6 +525,9 @@ class StreamMessageWidget extends StatefulWidget { /// {@macro onMessageTap} final void Function(Message)? onMessageTap; + /// {@macro onReactionsTap} + final OnReactionsTap? onReactionsTap; + /// {@template customActions} /// List of custom actions shown on message long tap /// {@endtemplate} @@ -604,6 +608,7 @@ class StreamMessageWidget extends StatefulWidget { bool? translateUserAvatar, OnQuotedMessageTap? onQuotedMessageTap, void Function(Message)? onMessageTap, + OnReactionsTap? onReactionsTap, List? customActions, void Function(Message message, Attachment attachment)? onAttachmentTap, Widget Function(BuildContext, User)? userAvatarBuilder, @@ -669,6 +674,7 @@ class StreamMessageWidget extends StatefulWidget { translateUserAvatar: translateUserAvatar ?? this.translateUserAvatar, onQuotedMessageTap: onQuotedMessageTap ?? this.onQuotedMessageTap, onMessageTap: onMessageTap ?? this.onMessageTap, + onReactionsTap: onReactionsTap ?? this.onReactionsTap, customActions: customActions ?? this.customActions, onAttachmentTap: onAttachmentTap ?? this.onAttachmentTap, userAvatarBuilder: userAvatarBuilder ?? this.userAvatarBuilder, @@ -892,7 +898,11 @@ class _StreamMessageWidgetState extends State showPinHighlight: widget.showPinHighlight, showReactionPickerTail: widget.showReactionPickerTail, showReactions: showReactions, - onReactionsTap: () => _showMessageReactionsModal(context), + onReactionsTap: () { + widget.onReactionsTap != null + ? widget.onReactionsTap!(widget.message) + : _showMessageReactionsModal(context); + }, showUserAvatar: widget.showUserAvatar, streamChat: _streamChat, translateUserAvatar: widget.translateUserAvatar, diff --git a/packages/stream_chat_flutter/lib/src/utils/extensions.dart b/packages/stream_chat_flutter/lib/src/utils/extensions.dart index 06b02aae..94a1bd83 100644 --- a/packages/stream_chat_flutter/lib/src/utils/extensions.dart +++ b/packages/stream_chat_flutter/lib/src/utils/extensions.dart @@ -352,12 +352,12 @@ extension MessageX on Message { final userName = user.name; if (linkify) { messageTextToRender = messageTextToRender?.replaceAll( - '@$userId', - '[@$userName](@${userName.replaceAll(' ', '')})', + RegExp('@($userId|$userName)'), + '[@$userName]($userId)', ); } else { messageTextToRender = messageTextToRender?.replaceAll( - '@$userId', + RegExp('@($userId|$userName)'), '@$userName', ); } diff --git a/packages/stream_chat_flutter/lib/src/utils/typedefs.dart b/packages/stream_chat_flutter/lib/src/utils/typedefs.dart index a0551544..d0c8b99a 100644 --- a/packages/stream_chat_flutter/lib/src/utils/typedefs.dart +++ b/packages/stream_chat_flutter/lib/src/utils/typedefs.dart @@ -221,6 +221,11 @@ typedef OnQuotedMessageTap = void Function(String?); /// {@endtemplate} typedef OnMessageTap = void Function(Message); +/// {@template onReactionsTap} +/// The action to perform when a message's reactions are tapped. +/// {@endtemplate} +typedef OnReactionsTap = void Function(Message); + /// {@template messageSearchItemTapCallback} /// The action to perform when tapping or clicking on a user in a /// [MessageSearchListView]. diff --git a/packages/stream_chat_flutter/pubspec.yaml b/packages/stream_chat_flutter/pubspec.yaml index 5aaa9f85..c6031f89 100644 --- a/packages/stream_chat_flutter/pubspec.yaml +++ b/packages/stream_chat_flutter/pubspec.yaml @@ -17,26 +17,26 @@ dependencies: dart_vlc: ^0.4.0 desktop_drop: ^0.4.1 diacritic: ^0.1.4 - dio: ^5.2.1+1 + dio: ^5.3.2 ezanimation: ^0.6.0 - file_picker: ^5.3.2 + file_picker: ^5.3.3 file_selector: ^1.0.0 flutter: sdk: flutter - flutter_markdown: ^0.6.17 + flutter_markdown: ^0.6.17+1 flutter_portal: ^1.1.4 flutter_svg: ^2.0.7 http_parser: ^4.0.2 image_gallery_saver: ^2.0.3 - image_picker: ^1.0.1 + image_picker: ^1.0.2 jiffy: ^6.2.1 - lottie: ^2.4.0 + lottie: ^2.6.0 meta: ^1.9.1 - path_provider: ^2.0.15 - photo_manager: ^2.6.0 + path_provider: ^2.1.0 + photo_manager: ^2.7.1 photo_view: ^0.14.0 rxdart: ^0.27.7 - share_plus: ^7.0.2 + share_plus: ^7.1.0 shimmer: ^3.0.0 stream_chat_flutter_core: ^7.0.0-beta.2 synchronized: ^3.1.0 @@ -73,5 +73,5 @@ dev_dependencies: flutter_test: sdk: flutter golden_toolkit: ^0.15.0 - mocktail: ^0.3.0 - path: ^1.8.2 \ No newline at end of file + mocktail: ^1.0.0 + path: ^1.8.3 \ No newline at end of file diff --git a/packages/stream_chat_flutter/test/src/utils/extension_test.dart b/packages/stream_chat_flutter/test/src/utils/extension_test.dart index eef7677e..52a6cc5f 100644 --- a/packages/stream_chat_flutter/test/src/utils/extension_test.dart +++ b/packages/stream_chat_flutter/test/src/utils/extension_test.dart @@ -148,4 +148,126 @@ void main() { expect('ㅎㅎㅎㅎ'.isOnlyEmoji, false); }); }); + + group('Message Extension Tests', () { + test('replaceMentions should replace user mentions with names and IDs', () { + final user1 = User(id: 'user1', name: 'Alice'); + final user2 = User(id: 'user2', name: 'Bob'); + + final message = Message( + text: 'Hello, @user1 and @user2!', + mentionedUsers: [user1, user2], + ); + + final modifiedMessage = message.replaceMentions(); + + expect(modifiedMessage.text, contains('[@Alice](user1)')); + expect(modifiedMessage.text, contains('[@Bob](user2)')); + }); + + test('replaceMentions without linkify should not add links', () { + final user = User(id: 'user1', name: 'Alice'); + + final message = Message( + text: 'Hello, @user1!', + mentionedUsers: [user], + ); + + final modifiedMessage = message.replaceMentions(linkify: false); + + expect(modifiedMessage.text, contains('@Alice')); + }); + + test('replaceMentions should handle mentions with usernames', () { + final user = User(id: 'user1', name: 'Alice'); + + final message = Message( + text: 'Hello, @Alice!', + mentionedUsers: [user], + ); + + final modifiedMessage = message.replaceMentions(); + + expect(modifiedMessage.text, contains('[@Alice](user1)')); + }); + + test( + '''replaceMentions without linkify should not change mentions with usernames''', + () { + final user = User(id: 'user1', name: 'Alice'); + + final message = Message( + text: 'Hello, @Alice!', + mentionedUsers: [user], + ); + + final modifiedMessage = message.replaceMentions(linkify: false); + + expect(modifiedMessage.text, contains('@Alice')); + }, + ); + + test( + 'replaceMentions should replace mixed user mentions with names and IDs', + () { + final user1 = User(id: 'user1', name: 'Alice'); + final user2 = User(id: 'user2', name: 'Bob'); + + final message = Message( + text: 'Hello, @user1 and @Bob!', + mentionedUsers: [user1, user2], + ); + + final modifiedMessage = message.replaceMentions(); + + expect(modifiedMessage.text, contains('[@Alice](user1)')); + expect(modifiedMessage.text, contains('[@Bob](user2)')); + }, + ); + + test('replaceMentionsWithId should replace user names with IDs', () { + final user1 = User(id: 'user1', name: 'Alice'); + final user2 = User(id: 'user2', name: 'Bob'); + + final message = Message( + text: 'Hello, @Alice and @Bob!', + mentionedUsers: [user1, user2], + ); + + final modifiedMessage = message.replaceMentionsWithId(); + + expect(modifiedMessage.text, contains('@user1')); + expect(modifiedMessage.text, contains('@user2')); + expect(modifiedMessage.text, isNot(contains('@Alice'))); + expect(modifiedMessage.text, isNot(contains('@Bob'))); + }); + + test( + 'replaceMentionsWithId should not change message without mentions', + () { + final message = Message( + text: 'Hello, @Alice!', + ); + + final modifiedMessage = message.replaceMentionsWithId(); + + expect(modifiedMessage.text, equals('Hello, @Alice!')); + expect(modifiedMessage.text, isNot(contains('@user1'))); + }, + ); + + test('replaceMentionsWithId should handle message with only mention', () { + final user = User(id: 'user1', name: 'Alice'); + + final message = Message( + text: '@Alice', + mentionedUsers: [user], + ); + + final modifiedMessage = message.replaceMentionsWithId(); + + expect(modifiedMessage.text, contains('@user1')); + expect(modifiedMessage.text, isNot(contains('@Alice'))); + }); + }); } diff --git a/packages/stream_chat_flutter_core/CHANGELOG.md b/packages/stream_chat_flutter_core/CHANGELOG.md index da0ccb6f..c316534f 100644 --- a/packages/stream_chat_flutter_core/CHANGELOG.md +++ b/packages/stream_chat_flutter_core/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.8.0 + +- Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0 +- Updated `stream_chat` dependency to [`6.8.0`](https://pub.dev/packages/stream_chat/changelog). + ## 7.0.0-beta.2 - Updated `stream_chat` dependency to [`7.0.0-beta.2`](https://pub.dev/packages/stream_chat/changelog). diff --git a/packages/stream_chat_flutter_core/pubspec.yaml b/packages/stream_chat_flutter_core/pubspec.yaml index e7f4fffc..dd45751f 100644 --- a/packages/stream_chat_flutter_core/pubspec.yaml +++ b/packages/stream_chat_flutter_core/pubspec.yaml @@ -11,7 +11,7 @@ environment: dependencies: collection: ^1.17.1 - connectivity_plus: ^4.0.1 + connectivity_plus: ^4.0.2 flutter: sdk: flutter freezed_annotation: ^2.4.1 @@ -25,5 +25,5 @@ dev_dependencies: flutter_test: sdk: flutter freezed: ^2.4.1 - mocktail: ^0.3.0 + mocktail: ^1.0.0 diff --git a/packages/stream_chat_localizations/CHANGELOG.md b/packages/stream_chat_localizations/CHANGELOG.md index d25054a2..8aa4c997 100644 --- a/packages/stream_chat_localizations/CHANGELOG.md +++ b/packages/stream_chat_localizations/CHANGELOG.md @@ -1,3 +1,8 @@ +## 5.9.0 + +* Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0 +* Updated `stream_chat_flutter` dependency to [`6.9.0`](https://pub.dev/packages/stream_chat_flutter/changelog). + ## 6.0.0-beta.2 * Updated `stream_chat_flutter` dependency to [`7.0.0-beta.2`](https://pub.dev/packages/stream_chat_flutter/changelog). diff --git a/packages/stream_chat_persistence/CHANGELOG.md b/packages/stream_chat_persistence/CHANGELOG.md index 74c845a9..b5dd941d 100644 --- a/packages/stream_chat_persistence/CHANGELOG.md +++ b/packages/stream_chat_persistence/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.8.0 + +- Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0 +- Updated `stream_chat` dependency to [`6.8.0`](https://pub.dev/packages/stream_chat/changelog). + ## 7.0.0-beta.2 - Included the changes from version [6.7.0](#670). diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart index 0ee57dd0..4a266910 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart @@ -41,16 +41,13 @@ class $ChannelsTable extends Channels .withConverter>($ChannelsTable.$converterconfig); static const VerificationMeta _frozenMeta = const VerificationMeta('frozen'); @override - late final GeneratedColumn frozen = - GeneratedColumn('frozen', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("frozen" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn frozen = GeneratedColumn( + 'frozen', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("frozen" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _lastMessageAtMeta = const VerificationMeta('lastMessageAt'); @override @@ -726,28 +723,22 @@ class $MessagesTable extends Messages static const VerificationMeta _showInChannelMeta = const VerificationMeta('showInChannel'); @override - late final GeneratedColumn showInChannel = - GeneratedColumn('show_in_channel', aliasedName, true, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("show_in_channel" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - })); + late final GeneratedColumn showInChannel = GeneratedColumn( + 'show_in_channel', aliasedName, true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("show_in_channel" IN (0, 1))')); static const VerificationMeta _shadowedMeta = const VerificationMeta('shadowed'); @override - late final GeneratedColumn shadowed = - GeneratedColumn('shadowed', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("shadowed" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn shadowed = GeneratedColumn( + 'shadowed', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("shadowed" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _commandMeta = const VerificationMeta('command'); @override @@ -797,16 +788,13 @@ class $MessagesTable extends Messages type: DriftSqlType.string, requiredDuringInsert: false); static const VerificationMeta _pinnedMeta = const VerificationMeta('pinned'); @override - late final GeneratedColumn pinned = - GeneratedColumn('pinned', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("pinned" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn pinned = GeneratedColumn( + 'pinned', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("pinned" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _pinnedAtMeta = const VerificationMeta('pinnedAt'); @override @@ -2004,28 +1992,22 @@ class $PinnedMessagesTable extends PinnedMessages static const VerificationMeta _showInChannelMeta = const VerificationMeta('showInChannel'); @override - late final GeneratedColumn showInChannel = - GeneratedColumn('show_in_channel', aliasedName, true, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("show_in_channel" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - })); + late final GeneratedColumn showInChannel = GeneratedColumn( + 'show_in_channel', aliasedName, true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("show_in_channel" IN (0, 1))')); static const VerificationMeta _shadowedMeta = const VerificationMeta('shadowed'); @override - late final GeneratedColumn shadowed = - GeneratedColumn('shadowed', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("shadowed" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn shadowed = GeneratedColumn( + 'shadowed', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("shadowed" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _commandMeta = const VerificationMeta('command'); @override @@ -2075,16 +2057,13 @@ class $PinnedMessagesTable extends PinnedMessages type: DriftSqlType.string, requiredDuringInsert: false); static const VerificationMeta _pinnedMeta = const VerificationMeta('pinned'); @override - late final GeneratedColumn pinned = - GeneratedColumn('pinned', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("pinned" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn pinned = GeneratedColumn( + 'pinned', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("pinned" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _pinnedAtMeta = const VerificationMeta('pinnedAt'); @override @@ -3928,28 +3907,22 @@ class $UsersTable extends Users with TableInfo<$UsersTable, UserEntity> { type: DriftSqlType.dateTime, requiredDuringInsert: false); static const VerificationMeta _onlineMeta = const VerificationMeta('online'); @override - late final GeneratedColumn online = - GeneratedColumn('online', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("online" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn online = GeneratedColumn( + 'online', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("online" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _bannedMeta = const VerificationMeta('banned'); @override - late final GeneratedColumn banned = - GeneratedColumn('banned', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("banned" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn banned = GeneratedColumn( + 'banned', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("banned" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); @override @@ -4388,54 +4361,42 @@ class $MembersTable extends Members static const VerificationMeta _invitedMeta = const VerificationMeta('invited'); @override - late final GeneratedColumn invited = - GeneratedColumn('invited', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("invited" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn invited = GeneratedColumn( + 'invited', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("invited" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _bannedMeta = const VerificationMeta('banned'); @override - late final GeneratedColumn banned = - GeneratedColumn('banned', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("banned" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn banned = GeneratedColumn( + 'banned', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("banned" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _shadowBannedMeta = const VerificationMeta('shadowBanned'); @override - late final GeneratedColumn shadowBanned = - GeneratedColumn('shadow_banned', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("shadow_banned" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn shadowBanned = GeneratedColumn( + 'shadow_banned', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("shadow_banned" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _isModeratorMeta = const VerificationMeta('isModerator'); @override - late final GeneratedColumn isModerator = - GeneratedColumn('is_moderator', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintsDependsOnDialect({ - SqlDialect.sqlite: 'CHECK ("is_moderator" IN (0, 1))', - SqlDialect.mysql: '', - SqlDialect.postgres: '', - }), - defaultValue: const Constant(false)); + late final GeneratedColumn isModerator = GeneratedColumn( + 'is_moderator', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_moderator" IN (0, 1))'), + defaultValue: const Constant(false)); static const VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); @override diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index b67dac7c..eed66f74 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -10,20 +10,20 @@ environment: flutter: ">=3.10.0" dependencies: - drift: ^2.9.0 + drift: ^2.11.0 flutter: sdk: flutter logging: ^1.2.0 meta: ^1.9.1 path: ^1.8.3 - path_provider: ^2.0.15 + path_provider: ^2.1.0 sqlite3_flutter_libs: ^0.5.15 stream_chat: ^7.0.0-beta.2 dev_dependencies: build_runner: ^2.4.6 - drift_dev: ^2.9.0 + drift_dev: ^2.11.0 flutter_test: sdk: flutter - mocktail: ^0.3.0 + mocktail: ^1.0.0 \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index cf418d76..8c61d28a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter_workspace environment: - sdk: '>=2.19.0 <4.0.0' + sdk: '>=3.0.0 <4.0.0' dev_dependencies: melos: ^3.1.0