diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index 3edd8c88..7609e0c3 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,10 +1,22 @@ +## 4.1.0 + +✅ Added + +- Added support for extra data in attachment file uploader. Thanks, [@rlee1990](https://github.com/rlee1990). + +🔄 Changed + +- Deprecated `role` in `Member` in favor of `channelRole` +- Deprecated `currentUserRole` getter in `Channel` in favor of `currentUserChannelRole` + ## 4.0.1 - Minor fixes ## 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 @@ -19,8 +31,10 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream. 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. +- [[#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. - Send only `user_id` while reconnecting. ✅ Added @@ -53,8 +67,10 @@ For upgrading to V4, please refer to the [V4 Migration Guide](https://getstream. 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. +- [[#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. - Send only `user_id` while reconnecting. ✅ Added diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 29a2d5ad..a27b672f 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -448,12 +448,14 @@ class Channel { it.file!, onSendProgress: onSendProgress, cancelToken: cancelToken, + extraData: it.extraData, ).then((it) => it.file); } else { future = sendFile( it.file!, onSendProgress: onSendProgress, cancelToken: cancelToken, + extraData: it.extraData, ).then((it) => it.file); } _cancelableAttachmentUploadRequest[it.id] = cancelToken; @@ -757,6 +759,7 @@ class Channel { AttachmentFile file, { ProgressCallback? onSendProgress, CancelToken? cancelToken, + Map? extraData, }) { _checkInitialized(); return _client.sendFile( @@ -765,6 +768,7 @@ class Channel { type, onSendProgress: onSendProgress, cancelToken: cancelToken, + extraData: extraData, ); } @@ -773,6 +777,7 @@ class Channel { AttachmentFile file, { ProgressCallback? onSendProgress, CancelToken? cancelToken, + Map? extraData, }) { _checkInitialized(); return _client.sendImage( @@ -781,6 +786,7 @@ class Channel { type, onSendProgress: onSendProgress, cancelToken: cancelToken, + extraData: extraData, ); } @@ -805,6 +811,7 @@ class Channel { Future deleteFile( String url, { CancelToken? cancelToken, + Map? extraData, }) { _checkInitialized(); return _client.deleteFile( @@ -812,6 +819,7 @@ class Channel { id!, type, cancelToken: cancelToken, + extraData: extraData, ); } @@ -819,6 +827,7 @@ class Channel { Future deleteImage( String url, { CancelToken? cancelToken, + Map? extraData, }) { _checkInitialized(); return _client.deleteImage( @@ -826,6 +835,7 @@ class Channel { id!, type, cancelToken: cancelToken, + extraData: extraData, ); } @@ -2007,8 +2017,12 @@ class ChannelClientState { ); /// User role for the current user. + @Deprecated('Please use currentUserChannelRole') String? get currentUserRole => currentUserMember?.role; + /// Channel role for the current user + String? get currentUserChannelRole => currentUserMember?.channelRole; + /// Channel read list. List get read => _channelState.read ?? []; diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index d16f56c5..0f2781c1 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -728,6 +728,7 @@ class StreamChatClient { String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, + Map? extraData, }) => _chatApi.fileUploader.sendFile( file, @@ -735,6 +736,7 @@ class StreamChatClient { channelType, onSendProgress: onSendProgress, cancelToken: cancelToken, + extraData: extraData, ); /// Send a [image] to the [channelId] of type [channelType] @@ -744,6 +746,7 @@ class StreamChatClient { String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, + Map? extraData, }) => _chatApi.fileUploader.sendImage( image, @@ -751,6 +754,7 @@ class StreamChatClient { channelType, onSendProgress: onSendProgress, cancelToken: cancelToken, + extraData: extraData, ); /// Delete a file from this channel @@ -759,12 +763,14 @@ class StreamChatClient { String channelId, String channelType, { CancelToken? cancelToken, + Map? extraData, }) => _chatApi.fileUploader.deleteFile( url, channelId, channelType, cancelToken: cancelToken, + extraData: extraData, ); /// Delete an image from this channel @@ -773,12 +779,14 @@ class StreamChatClient { String channelId, String channelType, { CancelToken? cancelToken, + Map? extraData, }) => _chatApi.fileUploader.deleteImage( url, channelId, channelType, cancelToken: cancelToken, + extraData: extraData, ); /// Replaces the [channelId] of type [ChannelType] data with [data]. diff --git a/packages/stream_chat/lib/src/core/api/attachment_file_uploader.dart b/packages/stream_chat/lib/src/core/api/attachment_file_uploader.dart index d6dc249f..096b2c2d 100644 --- a/packages/stream_chat/lib/src/core/api/attachment_file_uploader.dart +++ b/packages/stream_chat/lib/src/core/api/attachment_file_uploader.dart @@ -16,6 +16,7 @@ abstract class AttachmentFileUploader { String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, + Map? extraData, }); /// Uploads a [file] to the given channel. @@ -29,6 +30,7 @@ abstract class AttachmentFileUploader { String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, + Map? extraData, }); /// Deletes a image using its [url] from the given channel. @@ -40,6 +42,7 @@ abstract class AttachmentFileUploader { String channelId, String channelType, { CancelToken? cancelToken, + Map? extraData, }); /// Deletes a file using its [url] from the given channel. @@ -51,6 +54,7 @@ abstract class AttachmentFileUploader { String channelId, String channelType, { CancelToken? cancelToken, + Map? extraData, }); } @@ -68,6 +72,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader { String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, + Map? extraData, }) async { final multiPartFile = await file.toMultipartFile(); final response = await _client.postFile( @@ -86,6 +91,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader { String channelType, { ProgressCallback? onSendProgress, CancelToken? cancelToken, + Map? extraData, }) async { final multiPartFile = await file.toMultipartFile(); final response = await _client.postFile( @@ -103,6 +109,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader { String channelId, String channelType, { CancelToken? cancelToken, + Map? extraData, }) async { final response = await _client.delete( '/channels/$channelType/$channelId/image', @@ -118,6 +125,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader { String channelId, String channelType, { CancelToken? cancelToken, + Map? extraData, }) async { final response = await _client.delete( '/channels/$channelType/$channelId/file', diff --git a/packages/stream_chat/lib/src/core/models/member.dart b/packages/stream_chat/lib/src/core/models/member.dart index e8b0ecff..c2dc9eb1 100644 --- a/packages/stream_chat/lib/src/core/models/member.dart +++ b/packages/stream_chat/lib/src/core/models/member.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:stream_chat/src/core/models/user.dart'; @@ -15,6 +17,7 @@ class Member extends Equatable { this.inviteRejectedAt, this.invited = false, this.role, + this.channelRole, this.userId, this.isModerator = false, DateTime? createdAt, @@ -46,8 +49,12 @@ class Member extends Equatable { final bool invited; /// The role of the user in the channel + @Deprecated('Please use channelRole') final String? role; + /// The role of this member in the channel + final String? channelRole; + /// The id of the interested user final String? userId; @@ -76,6 +83,7 @@ class Member extends Equatable { DateTime? inviteRejectedAt, bool? invited, String? role, + String? channelRole, String? userId, bool? isModerator, DateTime? createdAt, @@ -93,6 +101,7 @@ class Member extends Equatable { banExpires: banExpires ?? this.banExpires, shadowBanned: shadowBanned ?? this.shadowBanned, role: role ?? this.role, + channelRole: channelRole ?? this.channelRole, userId: userId ?? this.userId, isModerator: isModerator ?? this.isModerator, createdAt: createdAt ?? this.createdAt, @@ -109,6 +118,7 @@ class Member extends Equatable { inviteRejectedAt, invited, role, + channelRole, userId, isModerator, banned, diff --git a/packages/stream_chat/lib/src/core/models/member.g.dart b/packages/stream_chat/lib/src/core/models/member.g.dart index 4da3cfd2..1bcde74d 100644 --- a/packages/stream_chat/lib/src/core/models/member.g.dart +++ b/packages/stream_chat/lib/src/core/models/member.g.dart @@ -18,6 +18,7 @@ Member _$MemberFromJson(Map json) => Member( : DateTime.parse(json['invite_rejected_at'] as String), invited: json['invited'] as bool? ?? false, role: json['role'] as String?, + channelRole: json['channel_role'] as String?, userId: json['user_id'] as String?, isModerator: json['is_moderator'] as bool? ?? false, createdAt: json['created_at'] == null @@ -39,6 +40,7 @@ Map _$MemberToJson(Member instance) => { 'invite_rejected_at': instance.inviteRejectedAt?.toIso8601String(), 'invited': instance.invited, 'role': instance.role, + 'channel_role': instance.channelRole, 'user_id': instance.userId, 'is_moderator': instance.isModerator, 'banned': instance.banned, diff --git a/packages/stream_chat/lib/version.dart b/packages/stream_chat/lib/version.dart index 5ea92b4d..360c57e9 100644 --- a/packages/stream_chat/lib/version.dart +++ b/packages/stream_chat/lib/version.dart @@ -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.0.1'; +const PACKAGE_VERSION = '4.1.0'; diff --git a/packages/stream_chat/pubspec.yaml b/packages/stream_chat/pubspec.yaml index acce67b7..1689550a 100644 --- a/packages/stream_chat/pubspec.yaml +++ b/packages/stream_chat/pubspec.yaml @@ -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.0.1 +version: 4.1.0 repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues diff --git a/packages/stream_chat/test/fixtures/member.json b/packages/stream_chat/test/fixtures/member.json index a33acf13..163878a3 100644 --- a/packages/stream_chat/test/fixtures/member.json +++ b/packages/stream_chat/test/fixtures/member.json @@ -9,7 +9,7 @@ "name": "Robin Papa", "image": "https://pbs.twimg.com/profile_images/669512187778498560/L7wQctBt.jpg" }, - "role": "member", + "channel_role": "channel_member", "created_at": "2020-01-28T22:17:30.95443Z", "updated_at": "2020-01-28T22:17:30.95443Z" } \ No newline at end of file diff --git a/packages/stream_chat/test/src/client/channel_test.dart b/packages/stream_chat/test/src/client/channel_test.dart index 9452a433..f90430f2 100644 --- a/packages/stream_chat/test/src/client/channel_test.dart +++ b/packages/stream_chat/test/src/client/channel_test.dart @@ -313,6 +313,7 @@ void main() { channelType, onSendProgress: any(named: 'onSendProgress'), cancelToken: any(named: 'cancelToken'), + extraData: any(named: 'extraData'), )).thenAnswer((_) async => sendImageResponse); when(() => client.sendFile( @@ -321,6 +322,7 @@ void main() { channelType, onSendProgress: any(named: 'onSendProgress'), cancelToken: any(named: 'cancelToken'), + extraData: any(named: 'extraData'), )).thenAnswer((_) async => sendFileResponse); when(() => client.sendMessage( @@ -440,6 +442,7 @@ void main() { channelType, onSendProgress: any(named: 'onSendProgress'), cancelToken: any(named: 'cancelToken'), + extraData: any(named: 'extraData'), )).called(2); verify(() => client.sendFile( @@ -448,6 +451,7 @@ void main() { channelType, onSendProgress: any(named: 'onSendProgress'), cancelToken: any(named: 'cancelToken'), + extraData: any(named: 'extraData'), )).called(1); verify(() => client.sendMessage( @@ -524,6 +528,7 @@ void main() { channelType, onSendProgress: any(named: 'onSendProgress'), cancelToken: any(named: 'cancelToken'), + extraData: any(named: 'extraData'), )).thenAnswer((_) async => sendImageResponse); when(() => client.sendFile( @@ -532,6 +537,7 @@ void main() { channelType, onSendProgress: any(named: 'onSendProgress'), cancelToken: any(named: 'cancelToken'), + extraData: any(named: 'extraData'), )).thenAnswer((_) async => sendFileResponse); when(() => client.updateMessage( @@ -649,6 +655,7 @@ void main() { channelType, onSendProgress: any(named: 'onSendProgress'), cancelToken: any(named: 'cancelToken'), + extraData: any(named: 'extraData'), )).called(2); verify(() => client.sendFile( @@ -657,6 +664,7 @@ void main() { channelType, onSendProgress: any(named: 'onSendProgress'), cancelToken: any(named: 'cancelToken'), + extraData: any(named: 'extraData'), )).called(1); verify(() => client.updateMessage( diff --git a/packages/stream_chat/test/src/core/models/member_test.dart b/packages/stream_chat/test/src/core/models/member_test.dart index 4cd8efda..98d42743 100644 --- a/packages/stream_chat/test/src/core/models/member_test.dart +++ b/packages/stream_chat/test/src/core/models/member_test.dart @@ -9,7 +9,7 @@ void main() { test('should parse json correctly', () { final member = Member.fromJson(jsonFixture('member.json')); expect(member.user, isA()); - expect(member.role, 'member'); + expect(member.channelRole, 'channel_member'); expect(member.createdAt, DateTime.parse('2020-01-28T22:17:30.95443Z')); expect(member.updatedAt, DateTime.parse('2020-01-28T22:17:30.95443Z')); }); diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 7d171f92..f41d94f6 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,3 +1,19 @@ +## 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` + +🐞 Fixed + +- Fixed attachment picker ui. +- Fixed message widget thread indicator in reverse mode. + +🔄 Changed + +- Removed `isOwner` condition from `ChannelBottomSheet` and `StreamChannelInfoBottomSheet` for delete option tile. + ## 4.0.1 - Minor fixes diff --git a/packages/stream_chat_flutter/README.md b/packages/stream_chat_flutter/README.md index bcc9e982..25310c5b 100644 --- a/packages/stream_chat_flutter/README.md +++ b/packages/stream_chat_flutter/README.md @@ -46,7 +46,8 @@ You should then run `flutter packages get` ### Android -All set ✅ +The package uses [photo_manager](https://pub.dev/packages/photo_manager) to access the device's photo library. +Follow [this wiki](https://pub.dev/packages/photo_manager#android-10-q-29) to fulfil the Android requirements. ### iOS diff --git a/packages/stream_chat_flutter/example/lib/tutorial_part_6.dart b/packages/stream_chat_flutter/example/lib/tutorial_part_6.dart index e9c0168f..a3d02a1d 100644 --- a/packages/stream_chat_flutter/example/lib/tutorial_part_6.dart +++ b/packages/stream_chat_flutter/example/lib/tutorial_part_6.dart @@ -56,10 +56,14 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - final themeData = ThemeData(primarySwatch: Colors.green); + final themeData = ThemeData( + colorScheme: ColorScheme.fromSwatch( + accentColor: Colors.green, + ), + ); final defaultTheme = StreamChatThemeData.fromTheme(themeData); final colorTheme = defaultTheme.colorTheme; - final customTheme = defaultTheme.merge(StreamChatThemeData( + final customTheme = StreamChatThemeData( channelPreviewTheme: StreamChannelPreviewThemeData( avatarTheme: StreamAvatarThemeData( borderRadius: BorderRadius.circular(8), @@ -81,7 +85,7 @@ class MyApp extends StatelessWidget { borderRadius: BorderRadius.circular(8), ), ), - )); + ).merge(defaultTheme); return MaterialApp( theme: themeData, diff --git a/packages/stream_chat_flutter/lib/src/channel_bottom_sheet.dart b/packages/stream_chat_flutter/lib/src/channel_bottom_sheet.dart index 66438479..8b273fe2 100644 --- a/packages/stream_chat_flutter/lib/src/channel_bottom_sheet.dart +++ b/packages/stream_chat_flutter/lib/src/channel_bottom_sheet.dart @@ -33,7 +33,6 @@ class _ChannelBottomSheetState extends State { final userAsMember = members .firstWhere((e) => e.user?.id == _streamChatState.currentUser?.id); - final isOwner = userAsMember.role == 'owner'; return Material( color: _streamChatThemeData.colorTheme.barsBg, @@ -179,9 +178,8 @@ class _ChannelBottomSheetState extends State { }); }, ), - if (isOwner && - channel.ownCapabilities - .contains(PermissionType.deleteChannel)) + if (channel.ownCapabilities + .contains(PermissionType.deleteChannel)) StreamOptionListTile( leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), diff --git a/packages/stream_chat_flutter/lib/src/channel_header.dart b/packages/stream_chat_flutter/lib/src/channel_header.dart index aea899bd..12f84e1f 100644 --- a/packages/stream_chat_flutter/lib/src/channel_header.dart +++ b/packages/stream_chat_flutter/lib/src/channel_header.dart @@ -52,7 +52,8 @@ typedef ChannelHeader = StreamChannelHeader; /// with [onBackPressed]. /// /// The widget components render the ui based on the first ancestor of type -/// [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property. +/// [StreamChatTheme] and on its [StreamChatThemeData.channelHeaderTheme] +/// property. /// Modify it to change the widget appearance. /// {@endtemplate} class StreamChannelHeader extends StatelessWidget diff --git a/packages/stream_chat_flutter/lib/src/message_widget.dart b/packages/stream_chat_flutter/lib/src/message_widget.dart index caf2722e..ae6e652c 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget.dart @@ -909,17 +909,6 @@ class _StreamMessageWidgetState extends State const usernameKey = Key('username'); children.addAll([ - if (showInChannel || showThreadReplyIndicator) ...[ - if (showThreadParticipants) - SizedBox.fromSize( - size: Size((threadParticipants!.length * 8.0) + 8, 16), - child: _buildThreadParticipantsIndicator(threadParticipants), - ), - InkWell( - onTap: widget.onThreadTap != null ? onThreadTap : null, - child: Text(msg, style: widget.messageTheme.repliesStyle), - ), - ], if (showUsername) _buildUsername(usernameKey), if (showTimeStamp) Text( @@ -932,26 +921,41 @@ class _StreamMessageWidgetState extends State final showThreadTail = !(hasUrlAttachments || isGiphy || isOnlyEmoji) && (showThreadReplyIndicator || showInChannel); + final threadIndicatorWidgets = [ + if (showThreadTail) + Container( + margin: EdgeInsets.only( + bottom: context.textScaleFactor * + ((widget.messageTheme.repliesStyle?.fontSize ?? 1) / 2), + ), + child: CustomPaint( + size: const Size(16, 32) * context.textScaleFactor, + painter: _ThreadReplyPainter( + context: context, + color: widget.messageTheme.messageBorderColor, + reverse: widget.reverse, + ), + ), + ), + if (showInChannel || showThreadReplyIndicator) ...[ + if (showThreadParticipants) + SizedBox.fromSize( + size: Size((threadParticipants!.length * 8.0) + 8, 16), + child: _buildThreadParticipantsIndicator(threadParticipants), + ), + InkWell( + onTap: widget.onThreadTap != null ? onThreadTap : null, + child: Text(msg, style: widget.messageTheme.repliesStyle), + ), + ], + ]; + return Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: widget.reverse ? MainAxisAlignment.end : MainAxisAlignment.start, children: [ - if (showThreadTail && !widget.reverse) - Container( - margin: EdgeInsets.only( - bottom: context.textScaleFactor * - ((widget.messageTheme.repliesStyle?.fontSize ?? 1) / 2), - ), - child: CustomPaint( - size: const Size(16, 32) * context.textScaleFactor, - painter: _ThreadReplyPainter( - context: context, - color: widget.messageTheme.messageBorderColor, - reverse: widget.reverse, - ), - ), - ), + if (showThreadTail && !widget.reverse) ...threadIndicatorWidgets, ...children.map( (child) { Widget mappedChild = SizedBox( @@ -965,20 +969,7 @@ class _StreamMessageWidgetState extends State }, ), if (showThreadTail && widget.reverse) - Container( - margin: EdgeInsets.only( - bottom: context.textScaleFactor * - ((widget.messageTheme.repliesStyle?.fontSize ?? 1) / 2), - ), - child: CustomPaint( - size: const Size(16, 32) * context.textScaleFactor, - painter: _ThreadReplyPainter( - context: context, - color: widget.messageTheme.messageBorderColor, - reverse: widget.reverse, - ), - ), - ), + ...threadIndicatorWidgets.reversed, ].insertBetween(const SizedBox(width: 8)), ); } diff --git a/packages/stream_chat_flutter/lib/src/v4/message_input/stream_attachment_picker.dart b/packages/stream_chat_flutter/lib/src/v4/message_input/stream_attachment_picker.dart index c6a3581b..98762302 100644 --- a/packages/stream_chat_flutter/lib/src/v4/message_input/stream_attachment_picker.dart +++ b/packages/stream_chat_flutter/lib/src/v4/message_input/stream_attachment_picker.dart @@ -281,27 +281,27 @@ class _StreamAttachmentPickerState extends State { icon: widget.customAttachmentTypes[i] .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, + 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, + ); + }, ); - }, - ); - } + } - return const SizedBox.shrink(); - }, + return const SizedBox.shrink(); + }, + ), + ], ), DecoratedBox( decoration: BoxDecoration( diff --git a/packages/stream_chat_flutter/lib/src/v4/message_input/stream_message_input.dart b/packages/stream_chat_flutter/lib/src/v4/message_input/stream_message_input.dart index 786ba22e..808760c7 100644 --- a/packages/stream_chat_flutter/lib/src/v4/message_input/stream_message_input.dart +++ b/packages/stream_chat_flutter/lib/src/v4/message_input/stream_message_input.dart @@ -207,8 +207,10 @@ class StreamMessageInput extends StatefulWidget { this.enableSafeArea, this.elevation, this.shadow, - this.autoCorrect, - this.disableEmojiSuggestionsOverlay, + this.autoCorrect = true, + this.disableEmojiSuggestionsOverlay = false, + this.enableEmojiSuggestionsOverlay = true, + this.enableMentionsOverlay = true, }) : super(key: key); /// List of options for showing overlays. @@ -327,11 +329,20 @@ class StreamMessageInput extends StatefulWidget { /// Disable autoCorrect by passing false /// autoCorrect is enabled by default - final bool? autoCorrect; + final bool autoCorrect; /// Disable the default emoji suggestions /// Enabled by default - final bool? disableEmojiSuggestionsOverlay; + @Deprecated('Please use enableEmojiSuggestionsOverlay') + final bool disableEmojiSuggestionsOverlay; + + /// Disable the default emoji suggestions by passing `false` + /// Enabled by default + final bool enableEmojiSuggestionsOverlay; + + /// Disable the mentions overlay by passing false + /// Enabled by default + final bool enableMentionsOverlay; static bool _defaultValidator(Message message) => message.text?.isNotEmpty == true || message.attachments.isNotEmpty; @@ -364,11 +375,6 @@ class StreamMessageInputState extends State bool get _isEditing => _effectiveController.value.status != MessageSendingStatus.sending; - bool get _autoCorrect => widget.autoCorrect ?? true; - - bool get _disableEmojiSuggestionsOverlay => - widget.disableEmojiSuggestionsOverlay ?? false; - StreamRestorableMessageInputController? _controller; StreamMessageInputController get _effectiveController => @@ -598,7 +604,8 @@ class StreamMessageInputState extends State visible: _showCommandsOverlay, widget: _buildCommandsOverlayEntry(), ), - if (!_disableEmojiSuggestionsOverlay) + if (widget.enableEmojiSuggestionsOverlay && + !widget.disableEmojiSuggestionsOverlay) OverlayOptions( visible: _focusNode.hasFocus && _effectiveController.text.isNotEmpty && @@ -611,10 +618,11 @@ class StreamMessageInputState extends State .contains(':'), widget: _buildEmojiOverlay(), ), - OverlayOptions( - visible: _showMentionsOverlay, - widget: _buildMentionsOverlayEntry(), - ), + if (widget.enableMentionsOverlay) + OverlayOptions( + visible: _showMentionsOverlay, + widget: _buildMentionsOverlayEntry(), + ), ...widget.customOverlays, ], child: child, @@ -813,7 +821,7 @@ class StreamMessageInputState extends State textAlignVertical: TextAlignVertical.center, decoration: _getInputDecoration(context), textCapitalization: TextCapitalization.sentences, - autocorrect: _autoCorrect, + autocorrect: widget.autoCorrect, ), ), ], diff --git a/packages/stream_chat_flutter/lib/src/v4/stream_channel_info_bottom_sheet.dart b/packages/stream_chat_flutter/lib/src/v4/stream_channel_info_bottom_sheet.dart index 986a9cb3..19c2349b 100644 --- a/packages/stream_chat_flutter/lib/src/v4/stream_channel_info_bottom_sheet.dart +++ b/packages/stream_chat_flutter/lib/src/v4/stream_channel_info_bottom_sheet.dart @@ -59,10 +59,6 @@ class StreamChannelInfoBottomSheet extends StatelessWidget { final members = channel.state?.members ?? []; - final isOwner = members.any( - (it) => it.user?.id == currentUser?.id && it.role == 'owner', - ); - // remove current user in case it's 1-1 conversation if (isOneToOneChannel) { members.removeWhere((it) => it.user?.id == currentUser?.id); @@ -153,7 +149,7 @@ class StreamChannelInfoBottomSheet extends StatelessWidget { ), onTap: onLeaveChannelTap, ), - if (isOwner) + if (channel.ownCapabilities.contains(PermissionType.deleteChannel)) StreamOptionListTile( leading: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), diff --git a/packages/stream_chat_flutter/pubspec.yaml b/packages/stream_chat_flutter/pubspec.yaml index 69e7c42c..7df5cc83 100644 --- a/packages/stream_chat_flutter/pubspec.yaml +++ b/packages/stream_chat_flutter/pubspec.yaml @@ -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.0.1 +version: 4.1.0 repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues @@ -36,7 +36,7 @@ dependencies: rxdart: ^0.27.0 share_plus: ^4.0.1 shimmer: ^2.0.0 - stream_chat_flutter_core: ^4.0.1 + stream_chat_flutter_core: ^4.1.0 substring_highlight: ^1.0.26 url_launcher: ^6.1.0 video_player: ^2.1.0 diff --git a/packages/stream_chat_flutter_core/CHANGELOG.md b/packages/stream_chat_flutter_core/CHANGELOG.md index 9927e734..7eb8845a 100644 --- a/packages/stream_chat_flutter_core/CHANGELOG.md +++ b/packages/stream_chat_flutter_core/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.1.0 + +- Updated `stream_chat` dependency to [`4.1.0`](https://pub.dev/packages/stream_chat/changelog). + ## 4.0.1 - Minor fixes diff --git a/packages/stream_chat_flutter_core/pubspec.yaml b/packages/stream_chat_flutter_core/pubspec.yaml index d7b1cfc2..07d5f842 100644 --- a/packages/stream_chat_flutter_core/pubspec.yaml +++ b/packages/stream_chat_flutter_core/pubspec.yaml @@ -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.0.1 +version: 4.1.0 repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues @@ -17,7 +17,7 @@ dependencies: freezed_annotation: ^1.0.0 meta: ^1.3.0 rxdart: ^0.27.0 - stream_chat: ^4.0.1 + stream_chat: ^4.1.0 dev_dependencies: build_runner: ^2.0.1 diff --git a/packages/stream_chat_localizations/CHANGELOG.md b/packages/stream_chat_localizations/CHANGELOG.md index a23bf1a1..0d3f0a7a 100644 --- a/packages/stream_chat_localizations/CHANGELOG.md +++ b/packages/stream_chat_localizations/CHANGELOG.md @@ -1,3 +1,7 @@ +## 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. + ## 3.0.0 * Added translations for viewLibrary. diff --git a/packages/stream_chat_localizations/README.md b/packages/stream_chat_localizations/README.md index 34680d35..24805d6e 100644 --- a/packages/stream_chat_localizations/README.md +++ b/packages/stream_chat_localizations/README.md @@ -38,6 +38,7 @@ At the moment we support the following languages: - [Japanese](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ja.dart) - [Korean](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ko.dart) - [Portuguese](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_pt.dart) +- [German](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_de.dart) More languages will be added in the future. Feel free to [contribute](https://github.com/GetStream/stream-chat-flutter/blob/master/CONTRIBUTING.md) to add more languages. diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart index 16838cf5..3087e900 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart @@ -19,6 +19,8 @@ part 'stream_chat_localizations_hi.dart'; part 'stream_chat_localizations_pt.dart'; +part 'stream_chat_localizations_de.dart'; + /// The set of supported languages, as language code strings. /// /// The [GlobalStreamChatLocalizations.delegate] can generate localizations for @@ -36,6 +38,7 @@ const kStreamChatSupportedLanguages = { 'ja', 'ko', 'pt', + 'de', }; /// Creates a [GlobalStreamChatLocalizations] instance for the given `locale`. @@ -74,6 +77,8 @@ GlobalStreamChatLocalizations? getStreamChatTranslation(Locale locale) { return const StreamChatLocalizationsKo(); case 'pt': return const StreamChatLocalizationsPt(); + case 'de': + return const StreamChatLocalizationsDe(); default: return null; } diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_de.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_de.dart new file mode 100644 index 00000000..35b283ec --- /dev/null +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_de.dart @@ -0,0 +1,385 @@ +part of 'stream_chat_localizations.dart'; + +/// The translations for German (`de`). +class StreamChatLocalizationsDe extends GlobalStreamChatLocalizations { + /// Create an instance of the translation bundle for German. + const StreamChatLocalizationsDe({String localeName = 'de'}) + : super(localeName: localeName); + + @override + String get launchUrlError => 'Die Url kann nicht geöffnet werden'; + + @override + String get loadingUsersError => 'Fehler beim Laden von Usern'; + + @override + String get noUsersLabel => 'Derzeit gibt es keine User'; + + @override + String get retryLabel => 'Erneut versuchen'; + + @override + String get userLastOnlineText => 'Zuletzt online'; + + @override + String get userOnlineText => 'Online'; + + @override + String userTypingText(Iterable users) { + if (users.isEmpty) return ''; + final first = users.first; + if (users.length == 1) { + return '${first.name} tippt'; + } + return '${first.name} und ${users.length - 1} weitere tippen'; + } + + @override + String get threadReplyLabel => 'Thread-Antwort'; + + @override + String get onlyVisibleToYouText => 'Nur für dich sichtbar'; + + @override + String threadReplyCountText(int count) => '$count Thread-Antworten'; + + @override + String attachmentsUploadProgressText({ + required int remaining, + required int total, + }) => + 'Hochladen $remaining/$total ...'; + + @override + String pinnedByUserText({ + required User pinnedBy, + required User currentUser, + }) { + final pinnedByCurrentUser = currentUser.id == pinnedBy.id; + if (pinnedByCurrentUser) return 'Angeheftet von Dir'; + return 'Angeheftet von ${pinnedBy.name}'; + } + + @override + String get emptyMessagesText => 'Derzeit sind keine Nachrichten vorhanden'; + + @override + String get genericErrorText => 'Etwas ist schief gelaufen'; + + @override + String get loadingMessagesError => 'Fehler beim Laden der Nachrichten'; + + @override + String resultCountText(int count) => '$count Ergebnisse'; + + @override + String get messageDeletedText => 'Diese Nachricht ist gelöscht.'; + + @override + String get messageDeletedLabel => 'Nachricht gelöscht'; + + @override + String get messageReactionsLabel => 'Nachricht-Reaktionen'; + + @override + String get emptyChatMessagesText => 'Noch keine Nachrichten hier...'; + + @override + String threadSeparatorText(int replyCount) { + if (replyCount == 1) return '1 Antwort'; + return '$replyCount Antworten'; + } + + @override + String get connectedLabel => 'Verbunden'; + + @override + String get disconnectedLabel => 'Getrennt'; + + @override + String get reconnectingLabel => 'Verbindung wird wiederhergestellt...'; + + @override + String get alsoSendAsDirectMessageLabel => 'Auch als Direktnachricht senden'; + + @override + String get addACommentOrSendLabel => 'Kommentar hinzufügen oder senden'; + + @override + String get searchGifLabel => 'GIFs suchen'; + + @override + String get writeAMessageLabel => 'Nachricht schreiben'; + + @override + String get instantCommandsLabel => 'Sofort-Befehle'; + + @override + String fileTooLargeAfterCompressionError(double limitInMB) => + 'Die Datei ist zu groß zum Hochladen. ' + 'Die maximale Dateigröße beträgt $limitInMB MB. ' + 'Wir haben versucht, sie zu komprimieren, aber das war nicht genug.'; + + @override + String fileTooLargeError(double limitInMB) => + 'Die Datei ist zu groß zum Hochladen. ' + 'Die Dateigröße ist begrenzt auf $limitInMB MB.'; + + @override + String emojiMatchingQueryText(String query) => 'Emoji-Abgleich "$query"'; + + @override + String get addAFileLabel => 'Datei hinzufügen'; + + @override + String get photoFromCameraLabel => 'Foto von der Kamera'; + + @override + String get uploadAFileLabel => 'Datei hochladen'; + + @override + String get uploadAPhotoLabel => 'Foto hochladen'; + + @override + String get uploadAVideoLabel => 'Video hochladen'; + + @override + String get videoFromCameraLabel => 'Video von der Kamera'; + + @override + String get okLabel => 'OK'; + + @override + String get somethingWentWrongError => 'Etwas ist schief gelaufen'; + + @override + String get addMoreFilesLabel => 'Weitere Dateien hinzufügen'; + + @override + String get enablePhotoAndVideoAccessMessage => + 'Bitte aktivieren Sie den Zugriff auf Ihre Fotos' + '\nund Videos, damit Sie sie mit Freunden teilen können.'; + + @override + String get allowGalleryAccessMessage => 'Zugang zu Ihrer Galerie gewähren'; + + @override + String get flagMessageLabel => 'Markierte Nachricht'; + + @override + String get flagMessageQuestion => + 'Möchten Sie eine Kopie dieser Nachricht an einen' + '\nModerator für weitere Untersuchungen senden?'; + + @override + String get flagLabel => 'MARKIEREN'; + + @override + String get cancelLabel => 'ABBRECHEN'; + + @override + String get flagMessageSuccessfulLabel => 'Nachricht markiert'; + + @override + String get flagMessageSuccessfulText => + 'Die Nachricht wurde an einen Moderator weitergeleitet.'; + + @override + String get deleteLabel => 'LÖSCHEN'; + + @override + String get deleteMessageLabel => 'Nachricht löschen'; + + @override + String get deleteMessageQuestion => + 'Sind Sie sicher, dass Sie diese Nachricht endgültig löschen wollen?'; + + @override + String get operationCouldNotBeCompletedText => + 'Die Operation konnte nicht abgeschlossen werden.'; + + @override + String get replyLabel => 'Antwort'; + + @override + String togglePinUnpinText({required bool pinned}) { + if (pinned) return 'Aus der Unterhaltung lösen'; + return 'Anheften an die Unterhaltung'; + } + + @override + String toggleDeleteRetryDeleteMessageText({required bool isDeleteFailed}) { + if (isDeleteFailed) return 'Löschen der Nachricht wiederholen'; + return 'Nachricht löschen'; + } + + @override + String get copyMessageLabel => 'Nachricht kopieren'; + + @override + String get editMessageLabel => 'Nachricht bearbeiten'; + + @override + String toggleResendOrResendEditedMessage({required bool isUpdateFailed}) { + if (isUpdateFailed) return 'Bearbeitete Nachricht erneut senden'; + return 'Erneut senden'; + } + + @override + String get photosLabel => 'Fotos'; + + String _getDay(DateTime dateTime) { + final now = DateTime.now(); + final today = DateTime(now.year, now.month, now.day); + final yesterday = DateTime(now.year, now.month, now.day - 1); + + final date = DateTime(dateTime.year, dateTime.month, dateTime.day); + + if (date == today) { + return 'Heute'; + } else if (date == yesterday) { + return 'Gestern'; + } else { + return 'am ${Jiffy(date).MMMd}'; + } + } + + @override + String sentAtText({required DateTime date, required DateTime time}) => + 'Gesendet ${_getDay(date)} am ${Jiffy(time.toLocal()).format('HH:mm')}'; + + @override + String get todayLabel => 'Heute'; + + @override + String get yesterdayLabel => 'Gestern'; + + @override + String get channelIsMutedText => 'Kanal ist stummgeschaltet'; + + @override + String get noTitleText => 'Kein Titel'; + + @override + String get letsStartChattingLabel => 'Lass uns anfangen zu chatten!'; + + @override + String get sendingFirstMessageLabel => 'Wie wäre es, wenn Sie Ihre erste ' + 'Nachricht an einen Freund senden würden?'; + + @override + String get startAChatLabel => 'Chat beginnen'; + + @override + String get loadingChannelsError => 'Fehler beim Laden der Kanäle'; + + @override + String get deleteConversationLabel => 'Unterhaltung löschen'; + + @override + String get deleteConversationQuestion => + 'Sind Sie sicher, dass Sie diese Unterhaltung löschen wollen?'; + + @override + String get streamChatLabel => 'Stream Chat'; + + @override + String get searchingForNetworkText => 'Searching for Network'; + + @override + String get offlineLabel => 'Offline...'; + + @override + String get tryAgainLabel => 'Erneut versuchen'; + + @override + String membersCountText(int count) { + if (count == 1) return '1 Mitglied'; + return '$count Mitglieder'; + } + + @override + String watchersCountText(int count) { + return '$count Online'; + } + + @override + String get viewInfoLabel => 'Infos anzeigen'; + + @override + String get leaveGroupLabel => 'Gruppe verlassen'; + + @override + String get leaveLabel => 'VERLASSEN'; + + @override + String get leaveConversationLabel => 'Unterhaltung verlassen'; + + @override + String get leaveConversationQuestion => + 'Sind Sie sicher, dass Sie diese Unterhaltung verlassen wollen?'; + + @override + String get showInChatLabel => 'Im Chat anzeigen'; + + @override + String get saveImageLabel => 'Bild speichern'; + + @override + String get saveVideoLabel => 'Video speichern'; + + @override + String get uploadErrorLabel => 'UPLOAD-FEHLER'; + + @override + String get giphyLabel => 'Giphy'; + + @override + String get shuffleLabel => 'Mischen'; + + @override + String get sendLabel => 'Senden'; + + @override + String get withText => 'mit'; + + @override + String get inText => 'in'; + + @override + String get youText => 'Du'; + + @override + String galleryPaginationText({ + required int currentPage, + required int totalPages, + }) => + '${currentPage + 1} von $totalPages'; + + @override + String get fileText => 'Datei'; + + @override + String get replyToMessageLabel => 'Auf Nachricht antworten'; + + @override + String attachmentLimitExceedError(int limit) => + 'Dateigröße überschritten, Grenze: $limit'; + + @override + String get slowModeOnLabel => 'Langsamer Modus: EIN'; + + @override + String get linkDisabledDetails => + 'Das Senden von Links ist in dieser Konversation nicht erlaubt.'; + + @override + String get linkDisabledError => 'Verknüpfungen sind deaktiviert'; + + @override + String get sendMessagePermissionError => + 'Sie sind nicht berechtigt Nachrichten zu senden'; + + @override + String get viewLibrary => 'Bibliothek ansehen'; +} diff --git a/packages/stream_chat_localizations/pubspec.yaml b/packages/stream_chat_localizations/pubspec.yaml index d3007663..e9ffb1c8 100644 --- a/packages/stream_chat_localizations/pubspec.yaml +++ b/packages/stream_chat_localizations/pubspec.yaml @@ -1,6 +1,6 @@ name: stream_chat_localizations description: The Official localizations for Stream Chat Flutter, a service for building chat applications -version: 3.0.0 +version: 3.1.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,7 +14,7 @@ dependencies: sdk: flutter flutter_localizations: sdk: flutter - stream_chat_flutter: ^4.0.0 + stream_chat_flutter: ^4.1.0 dev_dependencies: dart_code_metrics: ^4.4.0 diff --git a/packages/stream_chat_localizations/test/override_test.dart b/packages/stream_chat_localizations/test/override_test.dart index a30bb09a..6b775de1 100644 --- a/packages/stream_chat_localizations/test/override_test.dart +++ b/packages/stream_chat_localizations/test/override_test.dart @@ -173,8 +173,8 @@ void main() { launchUrlError: "Impossible de lancer l'url", ), const FooStreamChatLocalizationsDelegate( - supportedLanguage: 'de', - launchUrlError: 'Kann die URL nicht starten', + supportedLanguage: 'uz', + launchUrlError: 'test', ), ], supportedLocales: const [ @@ -182,6 +182,7 @@ void main() { Locale('hi'), Locale('fr'), Locale('de'), + Locale('uz'), ], buildContent: (BuildContext context) => Text( StreamChatLocalizations.of(context)!.launchUrlError, @@ -202,9 +203,9 @@ void main() { await tester.pump(); expect(find.text("Impossible de lancer l'url"), findsOneWidget); - await tester.binding.setLocale('de', 'DE'); + await tester.binding.setLocale('uz', 'UZ'); await tester.pump(); - expect(find.text('Kann die URL nicht starten'), findsOneWidget); + expect(find.text('test'), findsOneWidget); }, ); diff --git a/packages/stream_chat_persistence/CHANGELOG.md b/packages/stream_chat_persistence/CHANGELOG.md index 6dd74f8b..fc409305 100644 --- a/packages/stream_chat_persistence/CHANGELOG.md +++ b/packages/stream_chat_persistence/CHANGELOG.md @@ -1,3 +1,9 @@ +## 4.1.0 + +🔄 Changed + +- Deprecated `role` field in `Member` table in favor of `channelRole` + ## 4.0.1 - Updated `stream_chat` dependency to [`4.0.1`](https://pub.dev/packages/stream_chat/changelog). diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart index 9b73312d..1de78245 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart @@ -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 => 7; + int get schemaVersion => 8; @override MigrationStrategy get migration => MigrationStrategy( 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 e5382861..9c44cb2f 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 @@ -3888,6 +3888,9 @@ class MemberEntity extends DataClass implements Insertable { /// The role of the user in the channel final String? role; + /// The role of the user in the channel + final String? channelRole; + /// The date on which the user accepted the invite to the channel final DateTime? inviteAcceptedAt; @@ -3915,6 +3918,7 @@ class MemberEntity extends DataClass implements Insertable { {required this.userId, required this.channelCid, this.role, + this.channelRole, this.inviteAcceptedAt, this.inviteRejectedAt, required this.invited, @@ -3932,6 +3936,8 @@ class MemberEntity extends DataClass implements Insertable { .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid'])!, role: const StringType() .mapFromDatabaseResponse(data['${effectivePrefix}role']), + channelRole: const StringType() + .mapFromDatabaseResponse(data['${effectivePrefix}channel_role']), inviteAcceptedAt: const DateTimeType().mapFromDatabaseResponse( data['${effectivePrefix}invite_accepted_at']), inviteRejectedAt: const DateTimeType().mapFromDatabaseResponse( @@ -3958,6 +3964,9 @@ class MemberEntity extends DataClass implements Insertable { if (!nullToAbsent || role != null) { map['role'] = Variable(role); } + if (!nullToAbsent || channelRole != null) { + map['channel_role'] = Variable(channelRole); + } if (!nullToAbsent || inviteAcceptedAt != null) { map['invite_accepted_at'] = Variable(inviteAcceptedAt); } @@ -3980,6 +3989,7 @@ class MemberEntity extends DataClass implements Insertable { userId: serializer.fromJson(json['userId']), channelCid: serializer.fromJson(json['channelCid']), role: serializer.fromJson(json['role']), + channelRole: serializer.fromJson(json['channelRole']), inviteAcceptedAt: serializer.fromJson(json['inviteAcceptedAt']), inviteRejectedAt: @@ -3999,6 +4009,7 @@ class MemberEntity extends DataClass implements Insertable { 'userId': serializer.toJson(userId), 'channelCid': serializer.toJson(channelCid), 'role': serializer.toJson(role), + 'channelRole': serializer.toJson(channelRole), 'inviteAcceptedAt': serializer.toJson(inviteAcceptedAt), 'inviteRejectedAt': serializer.toJson(inviteRejectedAt), 'invited': serializer.toJson(invited), @@ -4014,6 +4025,7 @@ class MemberEntity extends DataClass implements Insertable { {String? userId, String? channelCid, Value role = const Value.absent(), + Value channelRole = const Value.absent(), Value inviteAcceptedAt = const Value.absent(), Value inviteRejectedAt = const Value.absent(), bool? invited, @@ -4026,6 +4038,7 @@ class MemberEntity extends DataClass implements Insertable { userId: userId ?? this.userId, channelCid: channelCid ?? this.channelCid, role: role.present ? role.value : this.role, + channelRole: channelRole.present ? channelRole.value : this.channelRole, inviteAcceptedAt: inviteAcceptedAt.present ? inviteAcceptedAt.value : this.inviteAcceptedAt, @@ -4045,6 +4058,7 @@ class MemberEntity extends DataClass implements Insertable { ..write('userId: $userId, ') ..write('channelCid: $channelCid, ') ..write('role: $role, ') + ..write('channelRole: $channelRole, ') ..write('inviteAcceptedAt: $inviteAcceptedAt, ') ..write('inviteRejectedAt: $inviteRejectedAt, ') ..write('invited: $invited, ') @@ -4062,6 +4076,7 @@ class MemberEntity extends DataClass implements Insertable { userId, channelCid, role, + channelRole, inviteAcceptedAt, inviteRejectedAt, invited, @@ -4077,6 +4092,7 @@ class MemberEntity extends DataClass implements Insertable { other.userId == this.userId && other.channelCid == this.channelCid && other.role == this.role && + other.channelRole == this.channelRole && other.inviteAcceptedAt == this.inviteAcceptedAt && other.inviteRejectedAt == this.inviteRejectedAt && other.invited == this.invited && @@ -4091,6 +4107,7 @@ class MembersCompanion extends UpdateCompanion { final Value userId; final Value channelCid; final Value role; + final Value channelRole; final Value inviteAcceptedAt; final Value inviteRejectedAt; final Value invited; @@ -4103,6 +4120,7 @@ class MembersCompanion extends UpdateCompanion { this.userId = const Value.absent(), this.channelCid = const Value.absent(), this.role = const Value.absent(), + this.channelRole = const Value.absent(), this.inviteAcceptedAt = const Value.absent(), this.inviteRejectedAt = const Value.absent(), this.invited = const Value.absent(), @@ -4116,6 +4134,7 @@ class MembersCompanion extends UpdateCompanion { required String userId, required String channelCid, this.role = const Value.absent(), + this.channelRole = const Value.absent(), this.inviteAcceptedAt = const Value.absent(), this.inviteRejectedAt = const Value.absent(), this.invited = const Value.absent(), @@ -4130,6 +4149,7 @@ class MembersCompanion extends UpdateCompanion { Expression? userId, Expression? channelCid, Expression? role, + Expression? channelRole, Expression? inviteAcceptedAt, Expression? inviteRejectedAt, Expression? invited, @@ -4143,6 +4163,7 @@ class MembersCompanion extends UpdateCompanion { if (userId != null) 'user_id': userId, if (channelCid != null) 'channel_cid': channelCid, if (role != null) 'role': role, + if (channelRole != null) 'channel_role': channelRole, if (inviteAcceptedAt != null) 'invite_accepted_at': inviteAcceptedAt, if (inviteRejectedAt != null) 'invite_rejected_at': inviteRejectedAt, if (invited != null) 'invited': invited, @@ -4158,6 +4179,7 @@ class MembersCompanion extends UpdateCompanion { {Value? userId, Value? channelCid, Value? role, + Value? channelRole, Value? inviteAcceptedAt, Value? inviteRejectedAt, Value? invited, @@ -4170,6 +4192,7 @@ class MembersCompanion extends UpdateCompanion { userId: userId ?? this.userId, channelCid: channelCid ?? this.channelCid, role: role ?? this.role, + channelRole: channelRole ?? this.channelRole, inviteAcceptedAt: inviteAcceptedAt ?? this.inviteAcceptedAt, inviteRejectedAt: inviteRejectedAt ?? this.inviteRejectedAt, invited: invited ?? this.invited, @@ -4193,6 +4216,9 @@ class MembersCompanion extends UpdateCompanion { if (role.present) { map['role'] = Variable(role.value); } + if (channelRole.present) { + map['channel_role'] = Variable(channelRole.value); + } if (inviteAcceptedAt.present) { map['invite_accepted_at'] = Variable(inviteAcceptedAt.value); } @@ -4226,6 +4252,7 @@ class MembersCompanion extends UpdateCompanion { ..write('userId: $userId, ') ..write('channelCid: $channelCid, ') ..write('role: $role, ') + ..write('channelRole: $channelRole, ') ..write('inviteAcceptedAt: $inviteAcceptedAt, ') ..write('inviteRejectedAt: $inviteRejectedAt, ') ..write('invited: $invited, ') @@ -4262,6 +4289,12 @@ class $MembersTable extends Members late final GeneratedColumn role = GeneratedColumn( 'role', aliasedName, true, type: const StringType(), requiredDuringInsert: false); + final VerificationMeta _channelRoleMeta = + const VerificationMeta('channelRole'); + @override + late final GeneratedColumn channelRole = GeneratedColumn( + 'channel_role', aliasedName, true, + type: const StringType(), requiredDuringInsert: false); final VerificationMeta _inviteAcceptedAtMeta = const VerificationMeta('inviteAcceptedAt'); @override @@ -4327,6 +4360,7 @@ class $MembersTable extends Members userId, channelCid, role, + channelRole, inviteAcceptedAt, inviteRejectedAt, invited, @@ -4363,6 +4397,12 @@ class $MembersTable extends Members context.handle( _roleMeta, role.isAcceptableOrUnknown(data['role']!, _roleMeta)); } + if (data.containsKey('channel_role')) { + context.handle( + _channelRoleMeta, + channelRole.isAcceptableOrUnknown( + data['channel_role']!, _channelRoleMeta)); + } if (data.containsKey('invite_accepted_at')) { context.handle( _inviteAcceptedAtMeta, diff --git a/packages/stream_chat_persistence/lib/src/entity/members.dart b/packages/stream_chat_persistence/lib/src/entity/members.dart index c1709981..371cb2be 100644 --- a/packages/stream_chat_persistence/lib/src/entity/members.dart +++ b/packages/stream_chat_persistence/lib/src/entity/members.dart @@ -12,8 +12,12 @@ class Members extends Table { text().customConstraint('REFERENCES channels(cid) ON DELETE CASCADE')(); /// The role of the user in the channel + @Deprecated('Please use channelRole') TextColumn get role => text().nullable()(); + /// The role of the user in the channel + TextColumn get channelRole => text().nullable()(); + /// The date on which the user accepted the invite to the channel DateTimeColumn get inviteAcceptedAt => dateTime().nullable()(); diff --git a/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart index 925abe16..05975ea4 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart @@ -12,6 +12,7 @@ extension MemberEntityX on MemberEntity { updatedAt: updatedAt, createdAt: createdAt, role: role, + channelRole: channelRole, inviteAcceptedAt: inviteAcceptedAt, invited: invited, inviteRejectedAt: inviteRejectedAt, @@ -32,7 +33,9 @@ extension MemberX on Member { inviteRejectedAt: inviteRejectedAt, invited: invited, inviteAcceptedAt: inviteAcceptedAt, + // ignore: deprecated_member_use role: role, + channelRole: channelRole, updatedAt: updatedAt, ); } diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index de73c91c..4d3ed908 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -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.0.1 +version: 4.1.0 repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues @@ -19,7 +19,7 @@ dependencies: path: ^1.8.0 path_provider: ^2.0.1 sqlite3_flutter_libs: ^0.5.0 - stream_chat: ^4.0.1 + stream_chat: ^4.1.0 dev_dependencies: build_runner: ^2.0.1 diff --git a/packages/stream_chat_persistence/test/src/dao/member_dao_test.dart b/packages/stream_chat_persistence/test/src/dao/member_dao_test.dart index 4a3a31da..1082967e 100644 --- a/packages/stream_chat_persistence/test/src/dao/member_dao_test.dart +++ b/packages/stream_chat_persistence/test/src/dao/member_dao_test.dart @@ -62,7 +62,7 @@ void main() { expect(fetchedMember.createdAt, isSameDateAs(member.createdAt)); expect(fetchedMember.isModerator, member.isModerator); expect(fetchedMember.invited, member.invited); - expect(fetchedMember.role, member.role); + expect(fetchedMember.channelRole, member.channelRole); expect(fetchedMember.updatedAt, isSameDateAs(member.updatedAt)); expect( fetchedMember.inviteAcceptedAt, @@ -89,7 +89,7 @@ void main() { expect(fetchedMember.createdAt, isSameDateAs(member.createdAt)); expect(fetchedMember.isModerator, member.isModerator); expect(fetchedMember.invited, member.invited); - expect(fetchedMember.role, member.role); + expect(fetchedMember.channelRole, member.channelRole); expect(fetchedMember.updatedAt, isSameDateAs(member.updatedAt)); expect( fetchedMember.inviteAcceptedAt, diff --git a/packages/stream_chat_persistence/test/src/mapper/member_mapper_test.dart b/packages/stream_chat_persistence/test/src/mapper/member_mapper_test.dart index a3878409..e327e752 100644 --- a/packages/stream_chat_persistence/test/src/mapper/member_mapper_test.dart +++ b/packages/stream_chat_persistence/test/src/mapper/member_mapper_test.dart @@ -28,7 +28,7 @@ void main() { expect(member.user!.id, entity.userId); expect(member.createdAt, isSameDateAs(entity.createdAt)); expect(member.updatedAt, isSameDateAs(entity.updatedAt)); - expect(member.role, entity.role); + expect(member.channelRole, entity.channelRole); expect(member.inviteAcceptedAt, isSameDateAs(entity.inviteAcceptedAt!)); expect(member.inviteRejectedAt, isSameDateAs(entity.inviteRejectedAt!)); expect(member.invited, entity.invited); @@ -58,7 +58,7 @@ void main() { expect(entity.userId, member.user!.id); expect(entity.createdAt, isSameDateAs(member.createdAt)); expect(entity.updatedAt, isSameDateAs(member.updatedAt)); - expect(entity.role, member.role); + expect(entity.channelRole, member.channelRole); expect(entity.inviteAcceptedAt, isSameDateAs(member.inviteAcceptedAt!)); expect(entity.inviteRejectedAt, isSameDateAs(member.inviteRejectedAt!)); expect(entity.invited, member.invited);