diff --git a/docusaurus/docs/Flutter/guides/adding_chat_to_video_livestreams.mdx b/docusaurus/docs/Flutter/guides/adding_chat_to_video_livestreams.mdx index 9e2afb44..96d24a05 100644 --- a/docusaurus/docs/Flutter/guides/adding_chat_to_video_livestreams.mdx +++ b/docusaurus/docs/Flutter/guides/adding_chat_to_video_livestreams.mdx @@ -64,30 +64,34 @@ The second type looks like this: We can use a `Stack` for achieving this: ```dart -Scaffold( - body: Stack( - children: [ - // Add your video implementation here - ShaderMask( - shaderCallback: (rect) { - return LinearGradient( +Stack( + children: [ + // Add your video implementation here + ShaderMask( + shaderCallback: (rect) { + return const LinearGradient( begin: Alignment.bottomCenter, end: Alignment.topCenter, - colors: [Colors.black, Colors.transparent], - stops: [0.4, 0.65] - ).createShader(Rect.fromLTRB(0, 0, rect.width, rect.height)); - }, - blendMode: BlendMode.dstIn, - child: Column( - children: [ - Expanded( - child: MessageListView(), - ), - MessageInput(), - ], - ), - ), - ], - ), - ) -``` + colors: [Colors.black, Colors.transparent], + stops: [0.4, 0.8]).createShader( + Rect.fromLTRB(0, 0, rect.width, rect.height), + ); + }, + blendMode: BlendMode.dstIn, + child: Column( + children: const [ + Expanded( + child: MessageListViewTheme( + data: MessageListViewThemeData( + backgroundColor: Colors.transparent, + ), + child: MessageListView(), + ), + ), + MessageInput(), + ], + ), + ), + ], +), +``` \ No newline at end of file diff --git a/docusaurus/docs/Flutter/guides/adding_push_notifications_v2.mdx b/docusaurus/docs/Flutter/guides/adding_push_notifications_v2.mdx index 285c2205..917d9216 100644 --- a/docusaurus/docs/Flutter/guides/adding_push_notifications_v2.mdx +++ b/docusaurus/docs/Flutter/guides/adding_push_notifications_v2.mdx @@ -86,6 +86,14 @@ firebaseMessaging.onTokenRefresh.listen((token) { }); ``` +Push Notifications v2 also supports specifying a name to the push device tokens you register. By setting the optional `pushProviderName` param in the `addDevice` call you can support different configurations between the device and the `PushProvider`. + +```dart +firebaseMessaging.onTokenRefresh.listen((token) { + client.addDevice(token, PushProvider.firebase, pushProviderName: 'my-custom-config'); +}); +``` + ### Receiving Notifications Push notifications behave a bit differently depending on whether you are using iOS or Android. diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index a390a823..0965cd2e 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,3 +1,9 @@ +## Upcoming + +✅ Added + +- Added `push_provider_name` to `addDevice` API call + ## 4.0.0-beta.2 🐞 Fixed diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index 6e9ecc33..ee805b56 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -64,7 +64,7 @@ class StreamChatClient { StreamChatClient( String apiKey, { this.logLevel = Level.WARNING, - LogHandlerFunction? logHandlerFunction, + this.logHandlerFunction = StreamChatClient.defaultLogHandler, RetryPolicy? retryPolicy, @Deprecated(''' Location is now deprecated in favor of the new edge server. Will be removed in v4.0.0. @@ -77,7 +77,6 @@ class StreamChatClient { WebSocket? ws, AttachmentFileUploader? attachmentFileUploader, }) { - this.logHandlerFunction = logHandlerFunction ?? _defaultLogHandler; logger.info('Initiating new StreamChatClient'); final options = StreamHttpClientOptions( @@ -134,7 +133,7 @@ class StreamChatClient { '${CurrentPlatform.name}-' '${PACKAGE_VERSION.split('+')[0]}'; - /// Additionals headers for all requests + /// Additional headers for all requests static Map additionalHeaders = {}; ChatPersistenceClient? _originalChatPersistenceClient; @@ -189,7 +188,7 @@ class StreamChatClient { /// final client = StreamChatClient("stream-chat-api-key", /// logHandlerFunction: myLogHandlerFunction); ///``` - late LogHandlerFunction logHandlerFunction; + final LogHandlerFunction logHandlerFunction; StreamSubscription? _connectionStatusSubscription; @@ -214,17 +213,18 @@ class StreamChatClient { Stream get wsConnectionStatusStream => _wsConnectionStatusController.stream.distinct(); - LogHandlerFunction get _defaultLogHandler => (LogRecord record) { - print( - '${record.time} ' - '${_levelEmojiMapper[record.level] ?? record.level.name} ' - '${record.loggerName} ${record.message} ', - ); - if (record.error != null) print(record.error); - if (record.stackTrace != null) print(record.stackTrace); - }; + /// Default log handler function for the [StreamChatClient] logger. + static void defaultLogHandler(LogRecord record) { + print( + '${record.time} ' + '${_levelEmojiMapper[record.level] ?? record.level.name} ' + '${record.loggerName} ${record.message} ', + ); + if (record.error != null) print(record.error); + if (record.stackTrace != null) print(record.stackTrace); + } - /// + /// Default logger for the [StreamChatClient]. Logger detachedLogger(String name) => Logger.detached(name) ..level = logLevel ..onRecord.listen(logHandlerFunction); @@ -820,8 +820,16 @@ class StreamChatClient { ); /// Add a device for Push Notifications. - Future addDevice(String id, PushProvider pushProvider) => - _chatApi.device.addDevice(id, pushProvider); + Future addDevice( + String id, + PushProvider pushProvider, { + String? pushProviderName, + }) => + _chatApi.device.addDevice( + id, + pushProvider, + pushProviderName: pushProviderName, + ); /// Gets a list of user devices. Future getDevices() => _chatApi.device.getDevices(); diff --git a/packages/stream_chat/lib/src/core/api/device_api.dart b/packages/stream_chat/lib/src/core/api/device_api.dart index f4b7f0b1..df137cdc 100644 --- a/packages/stream_chat/lib/src/core/api/device_api.dart +++ b/packages/stream_chat/lib/src/core/api/device_api.dart @@ -29,13 +29,16 @@ class DeviceApi { /// Add a device for Push Notifications. Future addDevice( String deviceId, - PushProvider pushProvider, - ) async { + PushProvider pushProvider, { + String? pushProviderName, + }) async { final response = await _client.post( '/devices', data: { 'id': deviceId, 'push_provider': pushProvider.name, + if (pushProviderName != null && pushProviderName.isNotEmpty) + 'push_provider_name': pushProviderName, }, ); return EmptyResponse.fromJson(response.data); diff --git a/packages/stream_chat/lib/stream_chat.dart b/packages/stream_chat/lib/stream_chat.dart index c0ceab3a..0fce9d63 100644 --- a/packages/stream_chat/lib/stream_chat.dart +++ b/packages/stream_chat/lib/stream_chat.dart @@ -5,7 +5,7 @@ export 'package:dio/src/dio_error.dart'; export 'package:dio/src/multipart_file.dart'; export 'package:dio/src/options.dart'; export 'package:dio/src/options.dart' show ProgressCallback; -export 'package:logging/logging.dart' show Logger, Level; +export 'package:logging/logging.dart' show Logger, Level, LogRecord; export 'package:rate_limiter/rate_limiter.dart'; export 'package:uuid/uuid.dart'; @@ -41,3 +41,31 @@ export './src/permission_type.dart'; export './src/ws/connection_status.dart'; export 'src/client/channel.dart'; export 'src/client/client.dart'; +export 'src/core/api/attachment_file_uploader.dart' show AttachmentFileUploader; +export 'src/core/api/requests.dart'; +export 'src/core/api/requests.dart'; +export 'src/core/api/responses.dart'; +export 'src/core/api/stream_chat_api.dart' show PushProvider; +export 'src/core/error/error.dart'; +export 'src/core/models/action.dart'; +export 'src/core/models/attachment.dart'; +export 'src/core/models/attachment_file.dart'; +export 'src/core/models/channel_config.dart'; +export 'src/core/models/channel_model.dart'; +export 'src/core/models/channel_state.dart'; +export 'src/core/models/command.dart'; +export 'src/core/models/device.dart'; +export 'src/core/models/event.dart'; +export 'src/core/models/filter.dart' show Filter; +export 'src/core/models/member.dart'; +export 'src/core/models/message.dart'; +export 'src/core/models/mute.dart'; +export 'src/core/models/own_user.dart'; +export 'src/core/models/reaction.dart'; +export 'src/core/models/read.dart'; +export 'src/core/models/user.dart'; +export 'src/core/util/extension.dart'; +export 'src/db/chat_persistence_client.dart'; +export 'src/event_type.dart'; +export 'src/location.dart'; +export 'src/ws/connection_status.dart'; diff --git a/packages/stream_chat/test/src/client/client_test.dart b/packages/stream_chat/test/src/client/client_test.dart index 5ec2bfeb..4947bc72 100644 --- a/packages/stream_chat/test/src/client/client_test.dart +++ b/packages/stream_chat/test/src/client/client_test.dart @@ -1171,7 +1171,7 @@ void main() { verifyNoMoreInteractions(api.channel); }); - test('`.addDevice`', () async { + test('`.addDevice should work`', () async { const id = 'test-device-id'; const provider = PushProvider.firebase; @@ -1185,6 +1185,34 @@ void main() { verifyNoMoreInteractions(api.device); }); + test('`.addDevice should work with pushProviderName`', () async { + const id = 'test-device-id'; + const provider = PushProvider.firebase; + const pushProviderName = 'my-custom-config'; + + when( + () => api.device.addDevice( + id, + provider, + pushProviderName: pushProviderName, + ), + ).thenAnswer((_) async => EmptyResponse()); + + final res = await client.addDevice( + id, + provider, + pushProviderName: pushProviderName, + ); + expect(res, isNotNull); + + verify(() => api.device.addDevice( + id, + provider, + pushProviderName: pushProviderName, + )).called(1); + verifyNoMoreInteractions(api.device); + }); + test('`.getDevices`', () async { final devices = List.generate( 3, diff --git a/packages/stream_chat/test/src/core/api/device_api_test.dart b/packages/stream_chat/test/src/core/api/device_api_test.dart index 7d4f59fd..13cfe4dc 100644 --- a/packages/stream_chat/test/src/core/api/device_api_test.dart +++ b/packages/stream_chat/test/src/core/api/device_api_test.dart @@ -20,7 +20,7 @@ void main() { deviceApi = DeviceApi(client); }); - test('addDevice', () async { + test('addDevice should work', () async { const deviceId = 'test-device-id'; const pushProvider = PushProvider.firebase; @@ -44,6 +44,36 @@ void main() { verifyNoMoreInteractions(client); }); + test('addDevice should work with pushProviderName', () async { + const deviceId = 'test-device-id'; + const pushProvider = PushProvider.firebase; + const pushProviderName = 'my-custom-config'; + + const path = '/devices'; + + when(() => client.post( + path, + data: { + 'id': deviceId, + 'push_provider': pushProvider.name, + 'push_provider_name': pushProviderName, + }, + )) + .thenAnswer( + (_) async => successResponse(path, data: {})); + + final res = await deviceApi.addDevice( + deviceId, + pushProvider, + pushProviderName: pushProviderName, + ); + + expect(res, isNotNull); + + verify(() => client.post(path, data: any(named: 'data'))).called(1); + verifyNoMoreInteractions(client); + }); + test('getDevices', () async { const path = '/devices'; diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index ef980e29..cc865b2e 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,3 +1,16 @@ +## Upcoming + +✅ Added + +- [[#1087]](https://github.com/GetStream/stream-chat-flutter/issues/1087): Handle limited access to camera on iOS. +- `centerTitle` and `elevation` properties to `ChannelHeader`, `ThreadHeader` and `ChannelListHeader`. + +🐞 Fixed + +- [[#1067]](https://github.com/GetStream/stream-chat-flutter/issues/1067): Fix name text overflow in reaction card. +- [[#842]](https://github.com/GetStream/stream-chat-flutter/issues/842): show date divider for first message. +- Loosen up url check for attachment download. +- Use `ogScrapeUrl` for LinkAttachments. ## 4.0.0-beta.2 ✅ Added diff --git a/packages/stream_chat_flutter/lib/src/attachment/attachment_title.dart b/packages/stream_chat_flutter/lib/src/attachment/attachment_title.dart index b1aba4a2..6852cdb6 100644 --- a/packages/stream_chat_flutter/lib/src/attachment/attachment_title.dart +++ b/packages/stream_chat_flutter/lib/src/attachment/attachment_title.dart @@ -24,14 +24,11 @@ class StreamAttachmentTitle extends StatelessWidget { @override Widget build(BuildContext context) { - final normalizedTitleLink = attachment.titleLink?.replaceFirst( - RegExp(r'https?://(www\.)?'), - '', - ); + final ogScrapeUrl = attachment.ogScrapeUrl; return GestureDetector( onTap: () { - final titleLink = attachment.titleLink; - if (titleLink != null) launchURL(context, titleLink); + final ogScrapeUrl = attachment.ogScrapeUrl; + if (ogScrapeUrl != null) launchURL(context, ogScrapeUrl); }, child: Padding( padding: const EdgeInsets.all(8), @@ -48,8 +45,8 @@ class StreamAttachmentTitle extends StatelessWidget { fontWeight: FontWeight.bold, ), ), - if (normalizedTitleLink != null) - Text(normalizedTitleLink, style: messageTheme.messageTextStyle), + if (ogScrapeUrl != null) + Text(ogScrapeUrl, style: messageTheme.messageTextStyle), ], ), ), diff --git a/packages/stream_chat_flutter/lib/src/attachment/url_attachment.dart b/packages/stream_chat_flutter/lib/src/attachment/url_attachment.dart index 25cfb5ba..00f29c02 100644 --- a/packages/stream_chat_flutter/lib/src/attachment/url_attachment.dart +++ b/packages/stream_chat_flutter/lib/src/attachment/url_attachment.dart @@ -43,11 +43,11 @@ class StreamUrlAttachment extends StatelessWidget { final chatThemeData = StreamChatTheme.of(context); return GestureDetector( onTap: () { - final titleLink = urlAttachment.titleLink; - if (titleLink != null) { + final ogScrapeUrl = urlAttachment.ogScrapeUrl; + if (ogScrapeUrl != null) { onLinkTap != null - ? onLinkTap!(titleLink) - : launchURL(context, titleLink); + ? onLinkTap!(ogScrapeUrl) + : launchURL(context, ogScrapeUrl); } }, child: Column( diff --git a/packages/stream_chat_flutter/lib/src/channel_header.dart b/packages/stream_chat_flutter/lib/src/channel_header.dart index 9da8b4f8..aea899bd 100644 --- a/packages/stream_chat_flutter/lib/src/channel_header.dart +++ b/packages/stream_chat_flutter/lib/src/channel_header.dart @@ -68,9 +68,11 @@ class StreamChannelHeader extends StatelessWidget this.showConnectionStateTile = false, this.title, this.subtitle, + this.centerTitle, this.leading, this.actions, this.backgroundColor, + this.elevation = 1, }) : preferredSize = const Size.fromHeight(kToolbarHeight), super(key: key); @@ -99,6 +101,9 @@ class StreamChannelHeader extends StatelessWidget /// Subtitle widget final Widget? subtitle; + /// Whether the title should be centered + final bool? centerTitle; + /// Leading widget final Widget? leading; @@ -109,8 +114,16 @@ class StreamChannelHeader extends StatelessWidget /// The background color for this [StreamChannelHeader]. final Color? backgroundColor; + /// The elevation for this [StreamChannelHeader]. + final double elevation; + @override Widget build(BuildContext context) { + final effectiveCenterTitle = getEffectiveCenterTitle( + Theme.of(context), + actions: actions, + centerTitle: centerTitle, + ); final channel = StreamChannel.of(context).channel; final channelHeaderTheme = StreamChannelHeaderTheme.of(context); @@ -151,7 +164,7 @@ class StreamChannelHeader extends StatelessWidget systemOverlayStyle: theme.brightness == Brightness.dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark, - elevation: 1, + elevation: elevation, leading: leadingWidget, backgroundColor: backgroundColor ?? channelHeaderTheme.color, actions: actions ?? @@ -170,14 +183,16 @@ class StreamChannelHeader extends StatelessWidget ), ), ], - centerTitle: true, + centerTitle: centerTitle, title: InkWell( onTap: onTitleTap, child: SizedBox( height: preferredSize.height, - width: preferredSize.width, child: Column( mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: effectiveCenterTitle + ? CrossAxisAlignment.center + : CrossAxisAlignment.stretch, children: [ title ?? StreamChannelName( diff --git a/packages/stream_chat_flutter/lib/src/channel_list_header.dart b/packages/stream_chat_flutter/lib/src/channel_list_header.dart index f814a08e..4835cad0 100644 --- a/packages/stream_chat_flutter/lib/src/channel_list_header.dart +++ b/packages/stream_chat_flutter/lib/src/channel_list_header.dart @@ -62,9 +62,11 @@ class StreamChannelListHeader extends StatelessWidget this.showConnectionStateTile = false, this.preNavigationCallback, this.subtitle, + this.centerTitle, this.leading, this.actions, this.backgroundColor, + this.elevation = 1, }) : super(key: key); /// Pass this if you don't have a [StreamChatClient] in your widget tree. @@ -89,6 +91,9 @@ class StreamChannelListHeader extends StatelessWidget /// Subtitle widget final Widget? subtitle; + /// Whether the title should be centered + final bool? centerTitle; + /// Leading widget /// By default it shows the logged in user avatar final Widget? leading; @@ -100,6 +105,9 @@ class StreamChannelListHeader extends StatelessWidget /// The background color for this [StreamChannelListHeader]. final Color? backgroundColor; + /// The elevation for this [StreamChannelListHeader]. + final double elevation; + @override Widget build(BuildContext context) { final _client = client ?? StreamChat.of(context).client; @@ -135,10 +143,10 @@ class StreamChannelListHeader extends StatelessWidget systemOverlayStyle: theme.brightness == Brightness.dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark, - elevation: 1, + elevation: elevation, backgroundColor: backgroundColor ?? channelListHeaderThemeData.color, - centerTitle: true, + centerTitle: centerTitle, leading: leading ?? Center( child: user != null diff --git a/packages/stream_chat_flutter/lib/src/channel_list_view.dart b/packages/stream_chat_flutter/lib/src/channel_list_view.dart index 819ed40f..f70badc1 100644 --- a/packages/stream_chat_flutter/lib/src/channel_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/channel_list_view.dart @@ -1,3 +1,6 @@ +// ignore: lines_longer_than_80_chars +// ignore_for_file: deprecated_member_use_from_same_package, deprecated_member_use + import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:shimmer/shimmer.dart'; diff --git a/packages/stream_chat_flutter/lib/src/extension.dart b/packages/stream_chat_flutter/lib/src/extension.dart index a0c9d288..5ad30039 100644 --- a/packages/stream_chat_flutter/lib/src/extension.dart +++ b/packages/stream_chat_flutter/lib/src/extension.dart @@ -272,3 +272,12 @@ extension MessageX on Message { return copyWith(text: messageTextToSend); } } + +/// Extensions on [Uri] +extension UriX on Uri { + /// Return the URI adding the http scheme if it is missing + Uri get withScheme { + if (hasScheme) return this; + return Uri.parse('http://${toString()}'); + } +} diff --git a/packages/stream_chat_flutter/lib/src/full_screen_media.dart b/packages/stream_chat_flutter/lib/src/full_screen_media.dart index 37809b40..340392b7 100644 --- a/packages/stream_chat_flutter/lib/src/full_screen_media.dart +++ b/packages/stream_chat_flutter/lib/src/full_screen_media.dart @@ -5,7 +5,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; import 'package:photo_view/photo_view.dart'; -import 'package:stream_chat_flutter/src/stream_attachment_package.dart'; import 'package:stream_chat_flutter/src/extension.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:video_player/video_player.dart'; diff --git a/packages/stream_chat_flutter/lib/src/localization/translations.dart b/packages/stream_chat_flutter/lib/src/localization/translations.dart index 83682c6d..3d12b73b 100644 --- a/packages/stream_chat_flutter/lib/src/localization/translations.dart +++ b/packages/stream_chat_flutter/lib/src/localization/translations.dart @@ -1,7 +1,6 @@ import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter/src/connection_status_builder.dart'; import 'package:stream_chat_flutter/src/message_list_view.dart'; -import 'package:stream_chat_flutter/src/message_search_list_view.dart'; import 'package:stream_chat_flutter/src/v4/message_input/stream_message_input.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' show User; @@ -321,6 +320,9 @@ abstract class Translations { /// The label for "Reply to message" String get replyToMessageLabel; + /// The label for "View library" + String get viewLibrary; + /// Label for "Attachment limit exceeded: /// it's not possible to add more than $limit attachments" String attachmentLimitExceedError(int limit); @@ -696,6 +698,9 @@ class DefaultTranslations implements Translations { @override String get slowModeOnLabel => 'Slow mode ON'; + @override + String get viewLibrary => 'View library'; + @override String attachmentLimitExceedError(int limit) => """ Attachment limit exceeded: it's not possible to add more than $limit attachments"""; diff --git a/packages/stream_chat_flutter/lib/src/media_list_view.dart b/packages/stream_chat_flutter/lib/src/media_list_view.dart index c2404208..72378c1c 100644 --- a/packages/stream_chat_flutter/lib/src/media_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/media_list_view.dart @@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:photo_manager/photo_manager.dart'; +import 'package:stream_chat_flutter/src/media_list_view_controller.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// {@macro media_list_view} @@ -20,6 +21,7 @@ class StreamMediaListView extends StatefulWidget { Key? key, this.selectedIds = const [], this.onSelect, + this.controller, }) : super(key: key); /// Stores the media selected @@ -28,18 +30,28 @@ class StreamMediaListView extends StatefulWidget { /// Callback for on media selected final void Function(AssetEntity media)? onSelect; + /// Controller that handles MediaListView + final MediaListViewController? controller; + @override _StreamMediaListViewState createState() => _StreamMediaListViewState(); } class _StreamMediaListViewState extends State { - final _media = []; - final ScrollController _scrollController = ScrollController(); - int _currentPage = 0; + var _media = []; + var _currentPage = 0; + final _scrollController = ScrollController(); + + /// Controller necessary to verify limited access to photo gallery in iOS and + /// update the media list when listerners are emitted + late final controller = widget.controller ?? MediaListViewController(); @override Widget build(BuildContext context) => LazyLoadScrollView( - onEndOfPage: () async => _getMedia(), + onEndOfPage: () async { + await _getMedia(); + _updatePage(); + }, child: GridView.builder( itemCount: _media.length, controller: _scrollController, @@ -136,9 +148,29 @@ class _StreamMediaListViewState extends State { @override void initState() { super.initState(); + controller.addListener(_updateMediaList); _getMedia(); } + @override + void dispose() { + super.dispose(); + controller.removeListener(_updateMediaList); + if (widget.controller == null) { + controller.dispose(); + } + } + + void _updateMediaList() { + if (controller.shouldUpdateMedia) { + _getMedia(); + } + } + + void _updatePage() { + ++_currentPage; + } + Future _getMedia() async { final assetList = (await PhotoManager.getAssetPathList( filterOption: FilterOptionGroup( @@ -157,13 +189,11 @@ class _StreamMediaListViewState extends State { page: _currentPage, size: 50, ); - if (media?.isNotEmpty == true) { setState(() { - _media.addAll(media!); + _media = media!; }); } - ++_currentPage; } } diff --git a/packages/stream_chat_flutter/lib/src/media_list_view_controller.dart b/packages/stream_chat_flutter/lib/src/media_list_view_controller.dart new file mode 100644 index 00000000..9ec3f594 --- /dev/null +++ b/packages/stream_chat_flutter/lib/src/media_list_view_controller.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +/// Controller for MediaListView Widget +class MediaListViewController extends ChangeNotifier { + var _shouldUpdateMedia = false; + + /// Getter that knows if the media should be updated. + bool get shouldUpdateMedia => _shouldUpdateMedia; + + /// Method that update shouldUpdateMedia and notify all listeners + /// about this update. + void updateMedia({required bool newValue}) { + _shouldUpdateMedia = newValue; + notifyListeners(); + } +} diff --git a/packages/stream_chat_flutter/lib/src/message_input.dart b/packages/stream_chat_flutter/lib/src/message_input.dart index 1dd27661..b830ab37 100644 --- a/packages/stream_chat_flutter/lib/src/message_input.dart +++ b/packages/stream_chat_flutter/lib/src/message_input.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:async'; import 'dart:math'; @@ -15,7 +17,7 @@ import 'package:stream_chat_flutter/src/emoji/emoji.dart'; import 'package:stream_chat_flutter/src/emoji_overlay.dart'; import 'package:stream_chat_flutter/src/extension.dart'; import 'package:stream_chat_flutter/src/media_list_view.dart'; -import 'package:stream_chat_flutter/src/multi_overlay.dart'; +import 'package:stream_chat_flutter/src/media_list_view_controller.dart'; import 'package:stream_chat_flutter/src/quoted_message_widget.dart'; import 'package:stream_chat_flutter/src/user_mentions_overlay.dart'; import 'package:stream_chat_flutter/src/video_thumbnail_image.dart'; @@ -333,6 +335,7 @@ class MessageInputState extends State { final List _mentionedUsers = []; final _imagePicker = ImagePicker(); + final _mediaListViewController = MediaListViewController(); late final _focusNode = widget.focusNode ?? FocusNode(); late final _isInternalFocusNode = widget.focusNode == null; bool _inputEnabled = true; @@ -1046,6 +1049,26 @@ class MessageInputState extends State { ); }, ), + 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(); + }, + ), ], ), DecoratedBox( @@ -1078,6 +1101,7 @@ class MessageInputState extends State { borderRadius: BorderRadius.circular(8), ), child: _PickerWidget( + mediaListViewController: _mediaListViewController, filePickerIndex: _filePickerIndex, streamChatTheme: _streamChatTheme, containsFile: _attachmentContainsFile, @@ -1241,7 +1265,7 @@ class MessageInputState extends State { Widget _buildReplyToMessage() { if (!_hasQuotedMessage) return const Offstage(); final containsUrl = widget.quotedMessage!.attachments - .any((element) => element.titleLink != null); + .any((element) => element.ogScrapeUrl != null); return StreamQuotedMessageWidget( reverse: true, showBorder: !containsUrl, @@ -1909,6 +1933,7 @@ class _PickerWidget extends StatefulWidget { required this.onAddMoreFilesClick, required this.onMediaSelected, required this.streamChatTheme, + required this.mediaListViewController, }) : super(key: key); final int filePickerIndex; @@ -1917,6 +1942,7 @@ class _PickerWidget extends StatefulWidget { final void Function(DefaultAttachmentTypes) onAddMoreFilesClick; final void Function(AssetEntity) onMediaSelected; final StreamChatThemeData streamChatTheme; + final MediaListViewController mediaListViewController; @override _PickerWidgetState createState() => _PickerWidgetState(); @@ -1964,7 +1990,9 @@ class _PickerWidgetState extends State<_PickerWidget> { ), ); } + return StreamMediaListView( + controller: widget.mediaListViewController, selectedIds: widget.selectedMedias, onSelect: widget.onMediaSelected, ); diff --git a/packages/stream_chat_flutter/lib/src/message_list_view.dart b/packages/stream_chat_flutter/lib/src/message_list_view.dart index e6bbba99..7d77b2ea 100644 --- a/packages/stream_chat_flutter/lib/src/message_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/message_list_view.dart @@ -579,6 +579,9 @@ class _StreamMessageListViewState extends State { if (widget.reverse ? widget.headerBuilder == null : widget.footerBuilder == null) { + if (messages.isNotEmpty) { + return _buildDateDivider(messages.last); + } if (_isThreadConversation) return const Offstage(); return const SizedBox(height: 52); } @@ -603,21 +606,12 @@ class _StreamMessageListViewState extends State { message = messages[i - 2]; nextMessage = messages[i - 1]; } + if (!Jiffy(message.createdAt.toLocal()).isSame( nextMessage.createdAt.toLocal(), Units.DAY, )) { - final divider = widget.dateDividerBuilder != null - ? widget.dateDividerBuilder!( - nextMessage.createdAt.toLocal(), - ) - : Padding( - padding: const EdgeInsets.symmetric(vertical: 12), - child: StreamDateDivider( - dateTime: nextMessage.createdAt.toLocal(), - ), - ); - return divider; + return _buildDateDivider(nextMessage); } final timeDiff = Jiffy(nextMessage.createdAt.toLocal()).diff( @@ -769,6 +763,20 @@ class _StreamMessageListViewState extends State { return child; } + Widget _buildDateDivider(Message message) { + final divider = widget.dateDividerBuilder != null + ? widget.dateDividerBuilder!( + message.createdAt.toLocal(), + ) + : Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: StreamDateDivider( + dateTime: message.createdAt.toLocal(), + ), + ); + return divider; + } + Widget _buildThreadSeparator() { if (widget.threadSeparatorBuilder != null) { return widget.threadSeparatorBuilder!.call(context); @@ -825,7 +833,11 @@ class _StreamMessageListViewState extends State { index = _getBottomElementIndex(values); } - if (index == null) return const Offstage(); + if ((index == null) || + (!_isThreadConversation && index == itemCount - 2) || + (_isThreadConversation && index == itemCount - 1)) { + return const Offstage(); + } if (index <= 2 || index >= itemCount - 3) { if (widget.reverse) { @@ -1109,7 +1121,7 @@ class _StreamMessageListViewState extends State { final isOnlyEmoji = message.text?.isOnlyEmoji ?? false; final hasUrlAttachment = - message.attachments.any((it) => it.titleLink != null); + message.attachments.any((it) => it.ogScrapeUrl != null); final borderSide = isOnlyEmoji || hasUrlAttachment || (isMyMessage && !hasFileAttachment) diff --git a/packages/stream_chat_flutter/lib/src/message_reactions_modal.dart b/packages/stream_chat_flutter/lib/src/message_reactions_modal.dart index eceba3f2..f862048b 100644 --- a/packages/stream_chat_flutter/lib/src/message_reactions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_reactions_modal.dart @@ -246,6 +246,8 @@ class StreamMessageReactionsModal extends StatelessWidget { reaction.user!.name.split(' ')[0], style: chatThemeData.textTheme.footnoteBold, textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + maxLines: 1, ), ], ), diff --git a/packages/stream_chat_flutter/lib/src/message_search_list_view.dart b/packages/stream_chat_flutter/lib/src/message_search_list_view.dart index 2554b242..4cc436f4 100644 --- a/packages/stream_chat_flutter/lib/src/message_search_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/message_search_list_view.dart @@ -1,3 +1,6 @@ +// ignore: lines_longer_than_80_chars +// ignore_for_file: deprecated_member_use_from_same_package, deprecated_member_use + import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/extension.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/packages/stream_chat_flutter/lib/src/message_widget.dart b/packages/stream_chat_flutter/lib/src/message_widget.dart index 3108803e..fd710c8e 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget.dart @@ -581,11 +581,11 @@ class _StreamMessageWidgetState extends State bool get isOnlyEmoji => widget.message.text?.isOnlyEmoji == true; bool get hasNonUrlAttachments => widget.message.attachments - .where((it) => it.titleLink == null || it.type == 'giphy') + .where((it) => it.ogScrapeUrl == null || it.type == 'giphy') .isNotEmpty; bool get hasUrlAttachments => widget.message.attachments - .any((it) => it.titleLink != null && it.type != 'giphy'); + .any((it) => it.ogScrapeUrl != null && it.type != 'giphy'); bool get showBottomRow => showThreadReplyIndicator || @@ -1006,9 +1006,9 @@ class _StreamMessageWidgetState extends State Widget _buildUrlAttachment() { final urlAttachment = widget.message.attachments - .firstWhere((element) => element.titleLink != null); + .firstWhere((element) => element.ogScrapeUrl != null); - final host = Uri.parse(urlAttachment.titleLink!).host; + final host = Uri.parse(urlAttachment.ogScrapeUrl!).withScheme.host; final splitList = host.split('.'); final hostName = splitList.length == 3 ? splitList[1] : splitList[0]; final hostDisplayName = urlAttachment.authorName?.capitalize() ?? @@ -1176,7 +1176,7 @@ class _StreamMessageWidgetState extends State widget.message.attachments .where((element) => - (element.titleLink == null && element.type != null) || + (element.ogScrapeUrl == null && element.type != null) || element.type == 'giphy') .forEach((e) { if (attachmentGroups[e.type] == null) { diff --git a/packages/stream_chat_flutter/lib/src/quoted_message_widget.dart b/packages/stream_chat_flutter/lib/src/quoted_message_widget.dart index 81c8b892..1a7bb2d0 100644 --- a/packages/stream_chat_flutter/lib/src/quoted_message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/quoted_message_widget.dart @@ -57,7 +57,7 @@ class StreamQuotedMessageWidget extends StatelessWidget { bool get _hasAttachments => message.attachments.isNotEmpty; bool get _containsLinkAttachment => - message.attachments.any((element) => element.titleLink != null); + message.attachments.any((element) => element.ogScrapeUrl != null); bool get _containsText => message.text?.isNotEmpty == true; @@ -161,7 +161,7 @@ class StreamQuotedMessageWidget extends StatelessWidget { Attachment attachment; if (_containsLinkAttachment) { attachment = message.attachments.firstWhere( - (element) => element.titleLink != null, + (element) => element.ogScrapeUrl != null, ); child = _buildUrlAttachment(attachment); } else { diff --git a/packages/stream_chat_flutter/lib/src/stream_chat_theme.dart b/packages/stream_chat_flutter/lib/src/stream_chat_theme.dart index 4ece0bf2..32b4830f 100644 --- a/packages/stream_chat_flutter/lib/src/stream_chat_theme.dart +++ b/packages/stream_chat_flutter/lib/src/stream_chat_theme.dart @@ -414,7 +414,7 @@ class StreamChatThemeData { /// Theme configuration for the [StreamUserListView] widget. final StreamUserListViewThemeData userListViewTheme; - /// Theme configuration for the [MessageSearchListView] widget. + /// Theme configuration for the [StreamMessageSearchListView] widget. final StreamMessageSearchListViewThemeData messageSearchListViewTheme; /// Creates a copy of [StreamChatThemeData] with specified attributes diff --git a/packages/stream_chat_flutter/lib/src/thread_header.dart b/packages/stream_chat_flutter/lib/src/thread_header.dart index 052e1bcb..f6f77a32 100644 --- a/packages/stream_chat_flutter/lib/src/thread_header.dart +++ b/packages/stream_chat_flutter/lib/src/thread_header.dart @@ -72,11 +72,13 @@ class StreamThreadHeader extends StatelessWidget this.onBackPressed, this.title, this.subtitle, + this.centerTitle, this.leading, this.actions, this.onTitleTap, this.showTypingIndicator = true, this.backgroundColor, + this.elevation = 1, }) : preferredSize = const Size.fromHeight(kToolbarHeight), super(key: key); @@ -99,6 +101,9 @@ class StreamThreadHeader extends StatelessWidget /// Subtitle widget final Widget? subtitle; + /// Whether the title should be centered + final bool? centerTitle; + /// Leading widget final Widget? leading; @@ -112,8 +117,17 @@ class StreamThreadHeader extends StatelessWidget /// The background color of this [StreamThreadHeader]. final Color? backgroundColor; + /// The elevation for this [StreamThreadHeader]. + final double elevation; + @override Widget build(BuildContext context) { + final effectiveCenterTitle = getEffectiveCenterTitle( + Theme.of(context), + actions: actions, + centerTitle: centerTitle, + ); + final channelHeaderTheme = StreamChannelHeaderTheme.of(context); final defaultSubtitle = subtitle ?? @@ -126,7 +140,8 @@ class StreamThreadHeader extends StatelessWidget style: channelHeaderTheme.subtitleStyle, ), Flexible( - child: ChannelName( + child: StreamChannelName( + channel: StreamChannel.of(context).channel, textStyle: channelHeaderTheme.subtitleStyle, ), ), @@ -141,7 +156,7 @@ class StreamThreadHeader extends StatelessWidget systemOverlayStyle: theme.brightness == Brightness.dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark, - elevation: 1, + elevation: elevation, leading: leading ?? (showBackButton ? StreamBackButton( @@ -151,7 +166,7 @@ class StreamThreadHeader extends StatelessWidget ) : const SizedBox()), backgroundColor: backgroundColor ?? channelHeaderTheme.color, - centerTitle: true, + centerTitle: centerTitle, actions: actions, title: InkWell( onTap: onTitleTap, @@ -160,6 +175,9 @@ class StreamThreadHeader extends StatelessWidget width: 250, child: Column( mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: effectiveCenterTitle + ? CrossAxisAlignment.center + : CrossAxisAlignment.stretch, children: [ title ?? Text( diff --git a/packages/stream_chat_flutter/lib/src/typing_indicator.dart b/packages/stream_chat_flutter/lib/src/typing_indicator.dart index 1cb3d8eb..1ac99785 100644 --- a/packages/stream_chat_flutter/lib/src/typing_indicator.dart +++ b/packages/stream_chat_flutter/lib/src/typing_indicator.dart @@ -49,6 +49,12 @@ class StreamTypingIndicator extends StatelessWidget { .where((element) => element.value.parentId == parentId) .map((e) => e.key)), builder: (context, users) => AnimatedSwitcher( + layoutBuilder: (currentChild, previousChildren) => Stack( + children: [ + ...previousChildren, + if (currentChild != null) currentChild, + ], + ), duration: const Duration(milliseconds: 300), child: users.isNotEmpty ? Padding( diff --git a/packages/stream_chat_flutter/lib/src/user_list_view.dart b/packages/stream_chat_flutter/lib/src/user_list_view.dart index 6f1804e7..2b5b868e 100644 --- a/packages/stream_chat_flutter/lib/src/user_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/user_list_view.dart @@ -1,3 +1,6 @@ +// ignore: lines_longer_than_80_chars +// ignore_for_file: deprecated_member_use_from_same_package, deprecated_member_use + import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/extension.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/packages/stream_chat_flutter/lib/src/utils.dart b/packages/stream_chat_flutter/lib/src/utils.dart index 74c721c9..6f68d287 100644 --- a/packages/stream_chat_flutter/lib/src/utils.dart +++ b/packages/stream_chat_flutter/lib/src/utils.dart @@ -2,22 +2,43 @@ import 'dart:async'; import 'dart:math' as math; import 'package:flutter/material.dart'; -import 'package:stream_chat_flutter/src/stream_attachment_package.dart'; import 'package:stream_chat_flutter/src/extension.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; /// Launch URL Future launchURL(BuildContext context, String url) async { - if (await canLaunch(url)) { - await launch(url); - } else { + try { + await launch(Uri.parse(url).withScheme.toString()); + } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(context.translations.launchUrlError)), ); } } +/// Get centerTitle considering a default and platform specific behaviour +bool getEffectiveCenterTitle( + ThemeData theme, { + bool? centerTitle, + List? actions, +}) { + if (centerTitle != null) return centerTitle; + if (theme.appBarTheme.centerTitle != null) { + return theme.appBarTheme.centerTitle!; + } + switch (theme.platform) { + case TargetPlatform.android: + case TargetPlatform.fuchsia: + case TargetPlatform.linux: + case TargetPlatform.windows: + return false; + case TargetPlatform.iOS: + case TargetPlatform.macOS: + return actions == null || actions.length < 2; + } +} + /// Shows confirmation dialog Future showConfirmationDialog( BuildContext context, { @@ -433,8 +454,8 @@ int levenshtein(String s, String t, {bool caseSensitive = true}) { /// An easy way to handle attachment related operations on a message extension AttachmentPackagesX on Message { - /// This extension will return a List of type [StreamAttachmentPackage] from the - /// existing attachments of the message + /// This extension will return a List of type [StreamAttachmentPackage] + /// from the existing attachments of the message List getAttachmentPackageList() { final _attachmentPackages = List.generate( attachments.length, 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 33ba2a25..c6a3581b 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 @@ -5,6 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:photo_manager/photo_manager.dart'; import 'package:stream_chat_flutter/src/extension.dart'; import 'package:stream_chat_flutter/src/media_list_view.dart'; +import 'package:stream_chat_flutter/src/media_list_view_controller.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// Callback for when a file has to be picked. @@ -113,6 +114,7 @@ class StreamAttachmentPicker extends StatefulWidget { class _StreamAttachmentPickerState extends State { int _filePickerIndex = 0; + final _mediaListViewController = MediaListViewController(); @override Widget build(BuildContext context) { @@ -281,6 +283,26 @@ class _StreamAttachmentPickerState extends State { ), ], ), + 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(); + }, + ), DecoratedBox( decoration: BoxDecoration( color: _streamChatTheme.colorTheme.barsBg, @@ -315,6 +337,7 @@ class _StreamAttachmentPickerState extends State { borderRadius: BorderRadius.circular(8), ), child: _PickerWidget( + mediaListViewController: _mediaListViewController, filePickerIndex: _filePickerIndex, streamChatTheme: _streamChatTheme, containsFile: _attachmentContainsFile, @@ -410,6 +433,7 @@ class _PickerWidget extends StatefulWidget { required this.streamChatTheme, required this.allowedAttachmentTypes, required this.customAttachmentTypes, + required this.mediaListViewController, }) : super(key: key); final int filePickerIndex; @@ -420,6 +444,7 @@ class _PickerWidget extends StatefulWidget { final StreamChatThemeData streamChatTheme; final List allowedAttachmentTypes; final List customAttachmentTypes; + final MediaListViewController mediaListViewController; @override _PickerWidgetState createState() => _PickerWidgetState(); @@ -473,6 +498,7 @@ class _PickerWidgetState extends State<_PickerWidget> { return StreamMediaListView( selectedIds: widget.selectedMedias, onSelect: widget.onMediaSelected, + controller: widget.mediaListViewController, ); } 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 a16cd49e..24eec8fa 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 @@ -13,7 +13,6 @@ import 'package:stream_chat_flutter/src/commands_overlay.dart'; import 'package:stream_chat_flutter/src/emoji/emoji.dart'; import 'package:stream_chat_flutter/src/emoji_overlay.dart'; import 'package:stream_chat_flutter/src/extension.dart'; -import 'package:stream_chat_flutter/src/multi_overlay.dart'; import 'package:stream_chat_flutter/src/quoted_message_widget.dart'; import 'package:stream_chat_flutter/src/user_mentions_overlay.dart'; import 'package:stream_chat_flutter/src/v4/message_input/simple_safe_area.dart'; diff --git a/packages/stream_chat_flutter/lib/src/v4/message_input/stream_message_text_field.dart b/packages/stream_chat_flutter/lib/src/v4/message_input/stream_message_text_field.dart index d6a6879a..0aaccd0a 100644 --- a/packages/stream_chat_flutter/lib/src/v4/message_input/stream_message_text_field.dart +++ b/packages/stream_chat_flutter/lib/src/v4/message_input/stream_message_text_field.dart @@ -437,7 +437,7 @@ class StreamMessageTextField extends StatefulWidget { /// This setting is only honored on iOS devices. /// /// If unset, defaults to the brightness of - /// [ThemeData.primaryColorBrightness]. + /// [ThemeData.brightness]. final Brightness? keyboardAppearance; /// {@macro flutter.widgets.editableText.scrollPadding} diff --git a/packages/stream_chat_flutter/lib/src/v4/scroll_view/channel_scroll_view/stream_channel_grid_view.dart b/packages/stream_chat_flutter/lib/src/v4/scroll_view/channel_scroll_view/stream_channel_grid_view.dart index 27b71979..d1969fa4 100644 --- a/packages/stream_chat_flutter/lib/src/v4/scroll_view/channel_scroll_view/stream_channel_grid_view.dart +++ b/packages/stream_chat_flutter/lib/src/v4/scroll_view/channel_scroll_view/stream_channel_grid_view.dart @@ -158,7 +158,8 @@ class StreamChannelGridView extends StatelessWidget { /// only scroll the view if it has sufficient content. See [physics]. /// /// Also when true, the scroll view is used for default [ScrollAction]s. If a - /// ScrollAction is not handled by an otherwise focused part of the application, + /// ScrollAction is not handled by + /// an otherwise focused part of the application, /// the ScrollAction will be evaluated using this scroll view, for example, /// when executing [Shortcuts] key events like page up and down. /// @@ -288,7 +289,8 @@ class StreamChannelGridView extends StatelessWidget { /// /// See also: /// - /// * [SemanticsConfiguration.scrollChildCount], the corresponding semantics property. + /// * [SemanticsConfiguration.scrollChildCount], + /// the corresponding semantics property. final int? semanticChildCount; /// {@macro flutter.widgets.scrollable.dragStartBehavior} diff --git a/packages/stream_chat_flutter/lib/src/v4/scroll_view/message_search_scroll_view/stream_message_search_grid_view.dart b/packages/stream_chat_flutter/lib/src/v4/scroll_view/message_search_scroll_view/stream_message_search_grid_view.dart index 142d4a7a..488148b5 100644 --- a/packages/stream_chat_flutter/lib/src/v4/scroll_view/message_search_scroll_view/stream_message_search_grid_view.dart +++ b/packages/stream_chat_flutter/lib/src/v4/scroll_view/message_search_scroll_view/stream_message_search_grid_view.dart @@ -2,7 +2,6 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/extension.dart'; -import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_empty_widget.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_error_widget.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_load_more_error.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_load_more_indicator.dart'; @@ -75,7 +74,8 @@ class StreamMessageSearchGridView extends StatelessWidget { /// A builder that is called to build items in the [PagedValueGridView]. /// - /// The `value` parameter is the [GetMessageBuilder] at this position in the grid. + /// The `value` parameter is the [GetMessageBuilder] + /// at this position in the grid. final StreamMessageSearchGridViewIndexedWidgetBuilder itemBuilder; /// A builder that is called to build the empty state of the grid. @@ -144,7 +144,8 @@ class StreamMessageSearchGridView extends StatelessWidget { /// only scroll the view if it has sufficient content. See [physics]. /// /// Also when true, the scroll view is used for default [ScrollAction]s. If a - /// ScrollAction is not handled by an otherwise focused part of the application, + /// ScrollAction is not handled by + /// an otherwise focused part of the application, /// the ScrollAction will be evaluated using this scroll view, for example, /// when executing [Shortcuts] key events like page up and down. /// @@ -274,7 +275,8 @@ class StreamMessageSearchGridView extends StatelessWidget { /// /// See also: /// - /// * [SemanticsConfiguration.scrollChildCount], the corresponding semantics property. + /// * [SemanticsConfiguration.scrollChildCount], + /// the corresponding semantics property. final int? semanticChildCount; /// {@macro flutter.widgets.scrollable.dragStartBehavior} diff --git a/packages/stream_chat_flutter/lib/src/v4/scroll_view/message_search_scroll_view/stream_message_search_list_view.dart b/packages/stream_chat_flutter/lib/src/v4/scroll_view/message_search_scroll_view/stream_message_search_list_view.dart index e07bfc32..9c3f165d 100644 --- a/packages/stream_chat_flutter/lib/src/v4/scroll_view/message_search_scroll_view/stream_message_search_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/v4/scroll_view/message_search_scroll_view/stream_message_search_list_view.dart @@ -1,7 +1,8 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/extension.dart'; -import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_empty_widget.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_error_widget.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_load_more_error.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_load_more_indicator.dart'; diff --git a/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_grid_view.dart b/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_grid_view.dart index 3b900971..08cc4a50 100644 --- a/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_grid_view.dart +++ b/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_grid_view.dart @@ -1,7 +1,6 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/extension.dart'; -import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_empty_widget.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_error_widget.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_load_more_error.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_load_more_indicator.dart'; @@ -152,7 +151,8 @@ class StreamUserGridView extends StatelessWidget { /// only scroll the view if it has sufficient content. See [physics]. /// /// Also when true, the scroll view is used for default [ScrollAction]s. If a - /// ScrollAction is not handled by an otherwise focused part of the application, + /// ScrollAction is not handled by + /// an otherwise focused part of the application, /// the ScrollAction will be evaluated using this scroll view, for example, /// when executing [Shortcuts] key events like page up and down. /// @@ -282,7 +282,8 @@ class StreamUserGridView extends StatelessWidget { /// /// See also: /// - /// * [SemanticsConfiguration.scrollChildCount], the corresponding semantics property. + /// * [SemanticsConfiguration.scrollChildCount], + /// the corresponding semantics property. final int? semanticChildCount; /// {@macro flutter.widgets.scrollable.dragStartBehavior} diff --git a/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_list_tile.dart b/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_list_tile.dart index 0d6c79ba..c88862fa 100644 --- a/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_list_tile.dart +++ b/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_list_tile.dart @@ -48,10 +48,11 @@ class StreamUserListTile extends StatelessWidget { /// A widget to display at the end of tile. final Widget? selectedWidget; - /// If this tile is also [enabled] then icons and text are rendered with the same color. + /// If this tile is also [enabled] then icons + /// and text are rendered with the same color. /// - /// By default the selected color is the theme's primary color. The selected color - /// can be overridden with a [ListTileTheme]. + /// By default the selected color is the theme's primary color. + /// The selected color can be overridden with a [ListTileTheme]. /// /// {@tool dartpad} /// Here is an example of using a [StatefulWidget] to keep track of the diff --git a/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_list_view.dart b/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_list_view.dart index 2524f5da..d87f8ab9 100644 --- a/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/v4/scroll_view/user_scroll_view/stream_user_list_view.dart @@ -1,7 +1,8 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/extension.dart'; -import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_empty_widget.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_error_widget.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_load_more_error.dart'; import 'package:stream_chat_flutter/src/v4/scroll_view/stream_scroll_view_load_more_indicator.dart'; diff --git a/packages/stream_chat_flutter/lib/stream_chat_flutter.dart b/packages/stream_chat_flutter/lib/stream_chat_flutter.dart index 7a569711..5052393a 100644 --- a/packages/stream_chat_flutter/lib/stream_chat_flutter.dart +++ b/packages/stream_chat_flutter/lib/stream_chat_flutter.dart @@ -22,6 +22,7 @@ export 'src/info_tile.dart'; export 'src/localization/stream_chat_localizations.dart'; export 'src/localization/translations.dart' show DefaultTranslations; export 'src/message_action.dart'; +// ignore: deprecated_member_use_from_same_package export 'src/message_input.dart' show MessageInput, MessageInputState; export 'src/message_list_view.dart'; export 'src/message_search_item.dart'; diff --git a/packages/stream_chat_flutter/test/src/channel_header_test.dart b/packages/stream_chat_flutter/test/src/channel_header_test.dart index 831809a7..6866eae3 100644 --- a/packages/stream_chat_flutter/test/src/channel_header_test.dart +++ b/packages/stream_chat_flutter/test/src/channel_header_test.dart @@ -280,7 +280,7 @@ void main() { expect(find.text('test'), findsNothing); expect(find.byType(StreamBackButton), findsNothing); - expect(find.byType(ChannelAvatar), findsNothing); + expect(find.byType(StreamChannelAvatar), findsNothing); expect(find.byType(StreamChannelInfo), findsNothing); expect(find.text('leading'), findsOneWidget); expect(find.text('title'), findsOneWidget); diff --git a/packages/stream_chat_flutter/test/src/channel_image_test.dart b/packages/stream_chat_flutter/test/src/channel_image_test.dart index 3fc1e718..1ec1c166 100644 --- a/packages/stream_chat_flutter/test/src/channel_image_test.dart +++ b/packages/stream_chat_flutter/test/src/channel_image_test.dart @@ -31,8 +31,10 @@ void main() { client: client, child: StreamChannel( channel: channel, - child: const Scaffold( - body: ChannelAvatar(), + child: Scaffold( + body: StreamChannelAvatar( + channel: channel, + ), ), ), ), @@ -101,8 +103,10 @@ void main() { client: client, child: StreamChannel( channel: channel, - child: const Scaffold( - body: ChannelAvatar(), + child: Scaffold( + body: StreamChannelAvatar( + channel: channel, + ), ), ), ), @@ -162,8 +166,10 @@ void main() { client: client, child: StreamChannel( channel: channel, - child: const Scaffold( - body: ChannelAvatar(), + child: Scaffold( + body: StreamChannelAvatar( + channel: channel, + ), ), ), ), @@ -202,9 +208,10 @@ void main() { client: client, child: StreamChannel( channel: channel, - child: const Scaffold( - body: ChannelAvatar( + child: Scaffold( + body: StreamChannelAvatar( selected: true, + channel: channel, ), ), ), diff --git a/packages/stream_chat_flutter/test/src/channel_name_test.dart b/packages/stream_chat_flutter/test/src/channel_name_test.dart index dcfda04f..8848207e 100644 --- a/packages/stream_chat_flutter/test/src/channel_name_test.dart +++ b/packages/stream_chat_flutter/test/src/channel_name_test.dart @@ -57,8 +57,10 @@ void main() { client: client, child: StreamChannel( channel: channel, - child: const Scaffold( - body: ChannelName(), + child: Scaffold( + body: StreamChannelName( + channel: channel, + ), ), ), ), diff --git a/packages/stream_chat_flutter/test/src/channel_preview_test.dart b/packages/stream_chat_flutter/test/src/channel_preview_test.dart index 285a5373..a2ab02f1 100644 --- a/packages/stream_chat_flutter/test/src/channel_preview_test.dart +++ b/packages/stream_chat_flutter/test/src/channel_preview_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; diff --git a/packages/stream_chat_flutter/test/src/media_list_view_controller_test.dart b/packages/stream_chat_flutter/test/src/media_list_view_controller_test.dart new file mode 100644 index 00000000..3500d30b --- /dev/null +++ b/packages/stream_chat_flutter/test/src/media_list_view_controller_test.dart @@ -0,0 +1,37 @@ +import 'package:stream_chat_flutter/src/media_list_view_controller.dart'; +import 'package:test/test.dart'; + +void main() { + test('should update media', () { + final controller = MediaListViewController(); + + expect(controller.shouldUpdateMedia, false); + + controller.updateMedia(newValue: true); + expect(controller.shouldUpdateMedia, true); + + controller.dispose(); + }); + + test('should notify listeners on update media', () { + final controller = MediaListViewController(); + + var callCount = 0; + void updateCallsSpy() => callCount++; + + controller.addListener(updateCallsSpy); + + expect(callCount, 0); + controller.updateMedia(newValue: false); + expect(controller.shouldUpdateMedia, false); + expect(callCount, 1); + + controller.updateMedia(newValue: true); + expect(controller.shouldUpdateMedia, true); + expect(callCount, 2); + + controller + ..removeListener(updateCallsSpy) + ..dispose(); + }); +} diff --git a/packages/stream_chat_flutter/test/src/theme/channel_list_view_theme_test.dart b/packages/stream_chat_flutter/test/src/theme/channel_list_view_theme_test.dart index 37de3140..71193da4 100644 --- a/packages/stream_chat_flutter/test/src/theme/channel_list_view_theme_test.dart +++ b/packages/stream_chat_flutter/test/src/theme/channel_list_view_theme_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/packages/stream_chat_flutter/test/src/theme/message_search_list_view_theme_test.dart b/packages/stream_chat_flutter/test/src/theme/message_search_list_view_theme_test.dart index 556f8109..a12b52f4 100644 --- a/packages/stream_chat_flutter/test/src/theme/message_search_list_view_theme_test.dart +++ b/packages/stream_chat_flutter/test/src/theme/message_search_list_view_theme_test.dart @@ -1,3 +1,6 @@ +// ignore: lines_longer_than_80_chars +// ignore_for_file: deprecated_member_use, deprecated_member_use_from_same_package + import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/packages/stream_chat_flutter/test/src/theme/user_list_view_theme_test.dart b/packages/stream_chat_flutter/test/src/theme/user_list_view_theme_test.dart index 27ef0ea7..7b3550c8 100644 --- a/packages/stream_chat_flutter/test/src/theme/user_list_view_theme_test.dart +++ b/packages/stream_chat_flutter/test/src/theme/user_list_view_theme_test.dart @@ -1,3 +1,6 @@ +// ignore: lines_longer_than_80_chars +// ignore_for_file: deprecated_member_use_from_same_package, deprecated_member_use + import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; diff --git a/packages/stream_chat_flutter/test/src/thread_header_test.dart b/packages/stream_chat_flutter/test/src/thread_header_test.dart index 6d1758fa..20ce03f0 100644 --- a/packages/stream_chat_flutter/test/src/thread_header_test.dart +++ b/packages/stream_chat_flutter/test/src/thread_header_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; diff --git a/packages/stream_chat_flutter_core/example/analysis_options.yaml b/packages/stream_chat_flutter_core/example/analysis_options.yaml index 61b6c4de..d56da71f 100644 --- a/packages/stream_chat_flutter_core/example/analysis_options.yaml +++ b/packages/stream_chat_flutter_core/example/analysis_options.yaml @@ -7,7 +7,6 @@ # The following line activates a set of recommended lints for Flutter apps, # packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml linter: # The lint rules applied to this project can be customized in the diff --git a/packages/stream_chat_flutter_core/example/test/widget_test.dart b/packages/stream_chat_flutter_core/example/test/widget_test.dart deleted file mode 100644 index a19dabb0..00000000 --- a/packages/stream_chat_flutter_core/example/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:example/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart b/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart index 5bde8abd..51be28e7 100644 --- a/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:async'; import 'dart:convert'; diff --git a/packages/stream_chat_flutter_core/lib/src/channels_bloc.dart b/packages/stream_chat_flutter_core/lib/src/channels_bloc.dart index 76bf3854..2f8838b5 100644 --- a/packages/stream_chat_flutter_core/lib/src/channels_bloc.dart +++ b/packages/stream_chat_flutter_core/lib/src/channels_bloc.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:async'; import 'package:flutter/material.dart'; diff --git a/packages/stream_chat_flutter_core/lib/src/message_search_bloc.dart b/packages/stream_chat_flutter_core/lib/src/message_search_bloc.dart index 0e8d011d..0c302c72 100644 --- a/packages/stream_chat_flutter_core/lib/src/message_search_bloc.dart +++ b/packages/stream_chat_flutter_core/lib/src/message_search_bloc.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/material.dart'; import 'package:rxdart/rxdart.dart'; import 'package:stream_chat/stream_chat.dart'; diff --git a/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart b/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart index a96f626d..e86d020b 100644 --- a/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:convert'; import 'package:flutter/foundation.dart'; diff --git a/packages/stream_chat_flutter_core/lib/src/paged_value_scroll_view.dart b/packages/stream_chat_flutter_core/lib/src/paged_value_scroll_view.dart index 56037075..00d96f56 100644 --- a/packages/stream_chat_flutter_core/lib/src/paged_value_scroll_view.dart +++ b/packages/stream_chat_flutter_core/lib/src/paged_value_scroll_view.dart @@ -463,7 +463,8 @@ class PagedValueGridView extends StatefulWidget { /// only scroll the view if it has sufficient content. See [physics]. /// /// Also when true, the scroll view is used for default [ScrollAction]s. If a - /// ScrollAction is not handled by an otherwise focused part of the application, + /// ScrollAction is not handled by + /// an otherwise focused part of the application, /// the ScrollAction will be evaluated using this scroll view, for example, /// when executing [Shortcuts] key events like page up and down. /// @@ -593,7 +594,8 @@ class PagedValueGridView extends StatefulWidget { /// /// See also: /// - /// * [SemanticsConfiguration.scrollChildCount], the corresponding semantics property. + /// * [SemanticsConfiguration.scrollChildCount], the corresponding + /// semantics property. final int? semanticChildCount; /// {@macro flutter.widgets.scrollable.dragStartBehavior} diff --git a/packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart b/packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart index e62ab380..92b5650b 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart @@ -49,6 +49,7 @@ class StreamChannelListEventHandler { /// This event is fired when a channel is updated. /// /// By default, this updates the channel received in the event. + // ignore: no-empty-block void onChannelUpdated(Event event, StreamChannelListController controller) {} /// Function which gets called for the event diff --git a/packages/stream_chat_flutter_core/lib/src/stream_message_input_controller.dart b/packages/stream_chat_flutter_core/lib/src/stream_message_input_controller.dart index e5dbc898..b8f9107d 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_message_input_controller.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_message_input_controller.dart @@ -274,8 +274,9 @@ class StreamMessageInputController extends ValueNotifier { /// A [RestorableProperty] that knows how to store and restore a /// [StreamMessageInputController]. /// -/// The [StreamMessageInputController] is accessible via the [value] getter. During -/// state restoration, the property will restore [StreamMessageInputController.value] +/// The [StreamMessageInputController] is accessible via the [value] getter. +/// During state restoration, +/// the property will restore [StreamMessageInputController.value] /// to the value it had when the restoration data it is getting restored from /// was collected. class StreamRestorableMessageInputController diff --git a/packages/stream_chat_flutter_core/lib/src/user_list_core.dart b/packages/stream_chat_flutter_core/lib/src/user_list_core.dart index ea6ba145..03159afb 100644 --- a/packages/stream_chat_flutter_core/lib/src/user_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/user_list_core.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:convert'; import 'package:flutter/foundation.dart'; diff --git a/packages/stream_chat_flutter_core/lib/src/users_bloc.dart b/packages/stream_chat_flutter_core/lib/src/users_bloc.dart index 63b88974..c01242ec 100644 --- a/packages/stream_chat_flutter_core/lib/src/users_bloc.dart +++ b/packages/stream_chat_flutter_core/lib/src/users_bloc.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/material.dart'; import 'package:rxdart/rxdart.dart'; import 'package:stream_chat_flutter_core/src/stream_controller_extension.dart'; diff --git a/packages/stream_chat_flutter_core/test/channel_list_core_test.dart b/packages/stream_chat_flutter_core/test/channel_list_core_test.dart index 5f7c0e03..f94ab3c6 100644 --- a/packages/stream_chat_flutter_core/test/channel_list_core_test.dart +++ b/packages/stream_chat_flutter_core/test/channel_list_core_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:async'; import 'package:flutter/widgets.dart'; diff --git a/packages/stream_chat_flutter_core/test/channels_bloc_test.dart b/packages/stream_chat_flutter_core/test/channels_bloc_test.dart index e6365868..630ef881 100644 --- a/packages/stream_chat_flutter_core/test/channels_bloc_test.dart +++ b/packages/stream_chat_flutter_core/test/channels_bloc_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:async'; import 'package:flutter/widgets.dart'; diff --git a/packages/stream_chat_flutter_core/test/message_search_bloc_test.dart b/packages/stream_chat_flutter_core/test/message_search_bloc_test.dart index 764e629b..c1465731 100644 --- a/packages/stream_chat_flutter_core/test/message_search_bloc_test.dart +++ b/packages/stream_chat_flutter_core/test/message_search_bloc_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; diff --git a/packages/stream_chat_flutter_core/test/message_search_list_core_test.dart b/packages/stream_chat_flutter_core/test/message_search_list_core_test.dart index d699faa0..c56e377b 100644 --- a/packages/stream_chat_flutter_core/test/message_search_list_core_test.dart +++ b/packages/stream_chat_flutter_core/test/message_search_list_core_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; diff --git a/packages/stream_chat_flutter_core/test/user_list_core_test.dart b/packages/stream_chat_flutter_core/test/user_list_core_test.dart index 27f4cbe8..86ae601d 100644 --- a/packages/stream_chat_flutter_core/test/user_list_core_test.dart +++ b/packages/stream_chat_flutter_core/test/user_list_core_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; diff --git a/packages/stream_chat_flutter_core/test/users_bloc_test.dart b/packages/stream_chat_flutter_core/test/users_bloc_test.dart index 549f9291..ce28c2f8 100644 --- a/packages/stream_chat_flutter_core/test/users_bloc_test.dart +++ b/packages/stream_chat_flutter_core/test/users_bloc_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; diff --git a/packages/stream_chat_localizations/CHANGELOG.md b/packages/stream_chat_localizations/CHANGELOG.md index 2a8addab..e318cc18 100644 --- a/packages/stream_chat_localizations/CHANGELOG.md +++ b/packages/stream_chat_localizations/CHANGELOG.md @@ -1,3 +1,7 @@ +## Upcoming + +* Added translations for viewLibrary. + ## 3.0.0-beta.1 * Updated `stream_chat_flutter` dependency to [`4.0.0-beta.1`](https://pub.dev/packages/stream_chat_flutter/changelog). diff --git a/packages/stream_chat_localizations/example/lib/add_new_lang.dart b/packages/stream_chat_localizations/example/lib/add_new_lang.dart index d111ead0..d0eca8e8 100644 --- a/packages/stream_chat_localizations/example/lib/add_new_lang.dart +++ b/packages/stream_chat_localizations/example/lib/add_new_lang.dart @@ -403,6 +403,9 @@ class NnStreamChatLocalizations extends GlobalStreamChatLocalizations { @override String get linkDisabledError => 'Links are disabled'; + + @override + String get viewLibrary => 'View library'; } void main() async { @@ -500,7 +503,8 @@ class MyApp extends StatelessWidget { /// A list of messages sent in the current channel. /// -/// This is implemented using [MessageListView], a widget that provides query +/// This is implemented using [StreamMessageListView], +/// a widget that provides query /// functionalities fetching the messages from the api and showing them in a /// listView. class ChannelPage extends StatelessWidget { @@ -511,13 +515,13 @@ class ChannelPage extends StatelessWidget { @override Widget build(BuildContext context) => Scaffold( - appBar: const ChannelHeader(), + appBar: const StreamChannelHeader(), body: Column( children: const [ Expanded( - child: MessageListView(), + child: StreamMessageListView(), ), - MessageInput(), + StreamMessageInput(), ], ), ); diff --git a/packages/stream_chat_localizations/example/lib/main.dart b/packages/stream_chat_localizations/example/lib/main.dart index 82d7e92c..55354e50 100644 --- a/packages/stream_chat_localizations/example/lib/main.dart +++ b/packages/stream_chat_localizations/example/lib/main.dart @@ -94,7 +94,8 @@ class MyApp extends StatelessWidget { /// A list of messages sent in the current channel. /// -/// This is implemented using [MessageListView], a widget that provides query +/// This is implemented using [StreamMessageListView], +/// a widget that provides query /// functionalities fetching the messages from the api and showing them in a /// listView. class ChannelPage extends StatelessWidget { @@ -105,13 +106,13 @@ class ChannelPage extends StatelessWidget { @override Widget build(BuildContext context) => Scaffold( - appBar: const ChannelHeader(), + appBar: const StreamChannelHeader(), body: Column( children: const [ Expanded( - child: MessageListView(), + child: StreamMessageListView(), ), - MessageInput(), + StreamMessageInput(), ], ), ); diff --git a/packages/stream_chat_localizations/example/lib/override_lang.dart b/packages/stream_chat_localizations/example/lib/override_lang.dart index 6f311544..33ebaa99 100644 --- a/packages/stream_chat_localizations/example/lib/override_lang.dart +++ b/packages/stream_chat_localizations/example/lib/override_lang.dart @@ -121,7 +121,8 @@ class MyApp extends StatelessWidget { /// A list of messages sent in the current channel. /// -/// This is implemented using [MessageListView], a widget that provides query +/// This is implemented using [StreamMessageListView], +/// a widget that provides query /// functionalities fetching the messages from the api and showing them in a /// listView. class ChannelPage extends StatelessWidget { @@ -132,13 +133,13 @@ class ChannelPage extends StatelessWidget { @override Widget build(BuildContext context) => Scaffold( - appBar: const ChannelHeader(), + appBar: const StreamChannelHeader(), body: Column( children: const [ Expanded( - child: MessageListView(), + child: StreamMessageListView(), ), - MessageInput(), + StreamMessageInput(), ], ), ); 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 6ea2eda4..16838cf5 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart @@ -74,8 +74,9 @@ GlobalStreamChatLocalizations? getStreamChatTranslation(Locale locale) { return const StreamChatLocalizationsKo(); case 'pt': return const StreamChatLocalizationsPt(); + default: + return null; } - return null; } /// Implementation of localized strings for the stream chat widgets diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_en.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_en.dart index 08dbb02a..1d1d82b3 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_en.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_en.dart @@ -379,4 +379,7 @@ class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations { @override String get linkDisabledError => 'Links are disabled'; + + @override + String get viewLibrary => 'View library'; } diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart index 50c748cb..b906843f 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart @@ -376,6 +376,9 @@ class StreamChatLocalizationsEs extends GlobalStreamChatLocalizations { No es posible añadir más de $limit archivos adjuntos '''; + @override + String get viewLibrary => 'Ver Librería'; + @override String get slowModeOnLabel => 'Modo lento activado'; diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_fr.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_fr.dart index 0671f5af..b5a44a51 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_fr.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_fr.dart @@ -375,6 +375,9 @@ class StreamChatLocalizationsFr extends GlobalStreamChatLocalizations { Limite de pièces jointes dépassée : il n'est pas possible d'ajouter plus de $limit pièces jointes '''; + @override + String get viewLibrary => 'Voir la bibliothèque'; + @override String get slowModeOnLabel => 'Mode lent activé'; diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_hi.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_hi.dart index 1244e2ea..e07566bd 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_hi.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_hi.dart @@ -369,6 +369,9 @@ class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations { अटैचमेंट लिमिट: $limit अटैचमेंट से अधिक जोड़ना संभव नहीं है '''; + @override + String get viewLibrary => 'पुस्तकालय देखिये'; + @override String get slowModeOnLabel => 'स्लो मोड चालू'; diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_it.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_it.dart index 1f7fd048..ffbdde94 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_it.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_it.dart @@ -372,6 +372,9 @@ Il file è troppo grande per essere caricato. Il limite è di $limitInMB MB.'''; Attenzione: il limite massimo di $limit file è stato superato. '''; + @override + String get viewLibrary => 'Vedi la biblioteca'; + @override String get slowModeOnLabel => 'Slowmode attiva'; diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ja.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ja.dart index e1eea3a4..7729a6ca 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ja.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ja.dart @@ -353,6 +353,9 @@ class StreamChatLocalizationsJa extends GlobalStreamChatLocalizations { @override String get slowModeOnLabel => 'スローモードオン'; + @override + String get viewLibrary => 'ライブラリを表示'; + @override String attachmentLimitExceedError(int limit) => ''' 添付ファイルの制限を超えました:$limit個のファイル以上を添付することはできません diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ko.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ko.dart index 820d58e4..c7c858f1 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ko.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ko.dart @@ -354,6 +354,10 @@ class StreamChatLocalizationsKo extends GlobalStreamChatLocalizations { @override String get slowModeOnLabel => '슬로모드 켜짐'; + @override + @override + String get viewLibrary => '라이브러리 보기'; + @override String attachmentLimitExceedError(int limit) => '첨부 파일 제한 초과: $limit 이상의 첨부 파일을 추가할 수 없습니다'; diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_pt.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_pt.dart index 4c1d2a58..3a1a7696 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_pt.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_pt.dart @@ -382,4 +382,7 @@ Não é possível adicionar mais de $limit arquivos de uma vez @override String get sendMessagePermissionError => 'Você não tem permissão para enviar mensagens'; + + @override + String get viewLibrary => 'Ver biblioteca'; } diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index 5b180e30..6eb29139 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -1,5 +1,4 @@ import 'package:flutter/foundation.dart'; -import 'package:logging/logging.dart' show LogRecord; import 'package:mutex/mutex.dart'; import 'package:stream_chat/stream_chat.dart';