From 1b14e7f2234e0ad407fd7b791d711d9c1dc1b5ac Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 14:51:11 +0100 Subject: [PATCH 01/23] fix(llc): fix retry queue mechanism --- .../lib/src/client/retry_queue.dart | 35 +++++++++---------- .../lib/src/message_widget.dart | 4 +-- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/packages/stream_chat/lib/src/client/retry_queue.dart b/packages/stream_chat/lib/src/client/retry_queue.dart index c441b5fb..f00f12ed 100644 --- a/packages/stream_chat/lib/src/client/retry_queue.dart +++ b/packages/stream_chat/lib/src/client/retry_queue.dart @@ -71,14 +71,15 @@ class RetryQueue { /// Add a list of messages void add(List messages) { if (messages.isEmpty) return; - if (_messageQueue.containsAllMessage(messages)) return; + if (!_messageQueue.containsAllMessage(messages)) { + logger?.info('Adding ${messages.length} messages'); + final messageList = _messageQueue.toList(); + // we should not add message if already available in the queue + _messageQueue.addAll(messages.where( + (it) => !messageList.any((m) => m.id == it.id), + )); + } - logger?.info('Adding ${messages.length} messages'); - final messageList = _messageQueue.toList(); - // we should not add message if already available in the queue - _messageQueue.addAll(messages.where( - (it) => !messageList.any((m) => m.id == it.id), - )); _startRetrying(); } @@ -87,9 +88,9 @@ class RetryQueue { _isRetrying = true; logger?.info('Started retrying failed messages'); - while (_messageQueue.isNotEmpty) { + for (var i = 0; i < _messageQueue.length; ++i) { logger?.info('${_messageQueue.length} messages remaining in the queue'); - final message = _messageQueue.first; + final message = _messageQueue.toList()[i]; await _runAndRetry(message); } _isRetrying = false; @@ -109,8 +110,12 @@ class RetryQueue { await _retryMessage(message); logger?.info('Message (${message.id}) sent successfully'); _messageQueue.removeMessage(message); - break; - } on StreamChatError catch (e) { + return; + } catch (e) { + if (e is! StreamChatNetworkError || !e.isRetriable) { + _messageQueue.removeMessage(message); + return; + } // retry logic final maxAttempt = _retryPolicy.maxRetryAttempts; if (attempt < maxAttempt) { @@ -143,14 +148,6 @@ class RetryQueue { _sendFailedEvent(message); break; } - } catch (e) { - logger?.info( - 'API call failed due to unknown error (attempt $attempt). ' - 'Giving up for now, will retry when connection recovers. ' - 'Error was $e', - ); - _sendFailedEvent(message); - break; } } } diff --git a/packages/stream_chat_flutter/lib/src/message_widget.dart b/packages/stream_chat_flutter/lib/src/message_widget.dart index 6182df54..4010b11b 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget.dart @@ -832,8 +832,8 @@ class _MessageWidgetState extends State ), if (isFailedState) Positioned( - left: widget.reverse ? 0 : null, - right: widget.reverse ? null : 0, + right: widget.reverse ? 0 : null, + left: widget.reverse ? null : 0, bottom: showBottomRow ? 18 : -2, child: StreamSvgIcon.error(size: 20), ), From 7547bd6b86cc5b7b09dbac2376ed0b570404315a Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:38:23 +0100 Subject: [PATCH 02/23] fix(llc): retry queue now follows the creation date --- .../stream_chat/lib/src/client/channel.dart | 2 +- .../lib/src/client/retry_queue.dart | 19 ++++++++++++------- .../lib/src/message_actions_modal.dart | 6 +----- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 657b8617..51034d3a 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1698,7 +1698,7 @@ class ChannelClientState { } _channelState = _channelState.copyWith( - messages: newMessages, + messages: newMessages..sort(_sortByCreatedAt), channel: _channelState.channel?.copyWith( lastMessageAt: message.createdAt, ), diff --git a/packages/stream_chat/lib/src/client/retry_queue.dart b/packages/stream_chat/lib/src/client/retry_queue.dart index f00f12ed..e1b6df70 100644 --- a/packages/stream_chat/lib/src/client/retry_queue.dart +++ b/packages/stream_chat/lib/src/client/retry_queue.dart @@ -88,20 +88,24 @@ class RetryQueue { _isRetrying = true; logger?.info('Started retrying failed messages'); - for (var i = 0; i < _messageQueue.length; ++i) { + while (_messageQueue.isNotEmpty) { logger?.info('${_messageQueue.length} messages remaining in the queue'); - final message = _messageQueue.toList()[i]; - await _runAndRetry(message); + final message = _messageQueue.first; + final succeeded = await _runAndRetry(message); + if (!succeeded) { + _messageQueue.toList().forEach(_sendFailedEvent); + break; + } } _isRetrying = false; } - Future _runAndRetry(Message message) async { + Future _runAndRetry(Message message) async { var attempt = 1; final maxAttempt = _retryPolicy.maxRetryAttempts; // early return in case maxAttempt is less than 0 - if (attempt > maxAttempt) return; + if (attempt > maxAttempt) return false; // ignore: literal_only_boolean_expressions while (true) { @@ -110,11 +114,11 @@ class RetryQueue { await _retryMessage(message); logger?.info('Message (${message.id}) sent successfully'); _messageQueue.removeMessage(message); - return; + return true; } catch (e) { if (e is! StreamChatNetworkError || !e.isRetriable) { _messageQueue.removeMessage(message); - return; + return true; } // retry logic final maxAttempt = _retryPolicy.maxRetryAttempts; @@ -150,6 +154,7 @@ class RetryQueue { } } } + return false; } void _sendFailedEvent(Message message) { diff --git a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart index a67004af..23f3a096 100644 --- a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart @@ -533,11 +533,7 @@ class _MessageActionsModalState extends State { onTap: () { Navigator.pop(context); final channel = StreamChannel.of(context).channel; - if (isUpdateFailed) { - channel.updateMessage(widget.message); - } else { - channel.sendMessage(widget.message); - } + channel.state?.retryFailedMessages(); }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16), From 06b090dac2b4caa89fea136b09f87c83db4744e2 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:43:49 +0100 Subject: [PATCH 03/23] fix(llc): revert message action --- .../lib/src/message_actions_modal.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart index 23f3a096..e85e7cd8 100644 --- a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart @@ -533,7 +533,11 @@ class _MessageActionsModalState extends State { onTap: () { Navigator.pop(context); final channel = StreamChannel.of(context).channel; - channel.state?.retryFailedMessages(); + if (isUpdateFailed) { + channel.updateMessage(widget.message); + } else { + channel.sendMessage(widget.message); + } }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16), @@ -606,7 +610,9 @@ class _MessageActionsModalState extends State { widget.editMessageInputBuilder!(context, widget.message) else MessageInput( - editMessage: widget.message, + messageInputController: MessageInputController( + message: widget.message, + ), preMessageSending: (m) { FocusScope.of(context).unfocus(); Navigator.pop(context); From 37738461019ceded89ad49d5da32fd9311d8c7e0 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:45:13 +0100 Subject: [PATCH 04/23] fix(llc): revert message action --- .../stream_chat_flutter/lib/src/message_actions_modal.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart index e85e7cd8..ca062388 100644 --- a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart @@ -610,9 +610,6 @@ class _MessageActionsModalState extends State { widget.editMessageInputBuilder!(context, widget.message) else MessageInput( - messageInputController: MessageInputController( - message: widget.message, - ), preMessageSending: (m) { FocusScope.of(context).unfocus(); Navigator.pop(context); From 48e8ac25975f4d82c07297ddc66a98aa64026143 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:45:39 +0100 Subject: [PATCH 05/23] fix(llc): revert message action --- packages/stream_chat_flutter/lib/src/message_actions_modal.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart index ca062388..a67004af 100644 --- a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart @@ -610,6 +610,7 @@ class _MessageActionsModalState extends State { widget.editMessageInputBuilder!(context, widget.message) else MessageInput( + editMessage: widget.message, preMessageSending: (m) { FocusScope.of(context).unfocus(); Navigator.pop(context); From 14cd59f11b198c63ea840a9446e6647b347b67f3 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:54:30 +0100 Subject: [PATCH 06/23] chore(llc): update changelog --- packages/stream_chat/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index d27ac852..3f20271f 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -3,7 +3,8 @@ 🐞 Fixed - [[#799]](https://github.com/GetStream/stream-chat-flutter/issues/799) Fixed `totalUnreadCount` is not updating when - app is resumed from background mode + app is resumed from background mode. +- Fix retry mechanism failing in some cases. ## 3.3.0 From 5e91e1f501a55b5e75e229e3fae3214af4bed297 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 16:11:31 +0100 Subject: [PATCH 07/23] chore(repo): remove prefer-match-file-name --- analysis_options.yaml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index e5eaf7ca..03a4220e 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -154,18 +154,6 @@ dart_code_metrics: # Dart Specific - binary-expression-operand-order - double-literal-format - - prefer-match-file-name: - exclude: - - packages/*/test/** - - packages/*/example/** - - packages/**/util/** - - packages/**/utils.dart - - packages/stream_chat/lib/src/client/client.dart - - packages/stream_chat/lib/src/core/api/responses.dart - - packages/stream_chat/lib/src/core/api/requests.dart - - packages/stream_chat/lib/src/core/platform_detector/** - - packages/stream_chat_persistence/lib/src/db/shared/** - - packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart - no-boolean-literal-compare - no-equal-then-else - no-empty-block: From 9e9ed0667b3cf46b5f6858a2f23ed347a429db3e Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 16:23:45 +0100 Subject: [PATCH 08/23] chore(llc): update changelog and bump version --- packages/stream_chat/CHANGELOG.md | 2 +- packages/stream_chat/lib/version.dart | 2 +- packages/stream_chat/pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index 3f20271f..940d25c5 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,4 +1,4 @@ -## Upcoming +## 3.3.1 🐞 Fixed diff --git a/packages/stream_chat/lib/version.dart b/packages/stream_chat/lib/version.dart index cc19a375..ed6d9b09 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 = '3.3.0'; +const PACKAGE_VERSION = '3.3.1'; diff --git a/packages/stream_chat/pubspec.yaml b/packages/stream_chat/pubspec.yaml index 38ee620c..599b6ed8 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: 3.3.0 +version: 3.3.1 repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues From 28c05e7afc321acdf24f03140f93d80afb66f085 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 16:24:27 +0100 Subject: [PATCH 09/23] chore(core): update changelog and bump version --- packages/stream_chat_flutter_core/CHANGELOG.md | 4 ++++ packages/stream_chat_flutter_core/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/stream_chat_flutter_core/CHANGELOG.md b/packages/stream_chat_flutter_core/CHANGELOG.md index 9d0731aa..b69c4262 100644 --- a/packages/stream_chat_flutter_core/CHANGELOG.md +++ b/packages/stream_chat_flutter_core/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.3.1 + +- Updated `stream_chat` dependency to [`3.3.1`](https://pub.dev/packages/stream_chat/changelog). + ## 3.3.0 - Updated `stream_chat` dependency to [`3.3.0`](https://pub.dev/packages/stream_chat/changelog). diff --git a/packages/stream_chat_flutter_core/pubspec.yaml b/packages/stream_chat_flutter_core/pubspec.yaml index 48d104f3..8f0718f4 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: 3.3.0 +version: 3.3.1 repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues @@ -16,7 +16,7 @@ dependencies: sdk: flutter meta: ^1.3.0 rxdart: ^0.27.0 - stream_chat: ^3.3.0 + stream_chat: ^3.3.1 dev_dependencies: dart_code_metrics: ^4.4.0 From 502bb19e095b14d19fa24cee5c4189f1339469d1 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 16:25:34 +0100 Subject: [PATCH 10/23] chore(ui): update changelog and bump version --- packages/stream_chat_flutter/CHANGELOG.md | 4 ++++ packages/stream_chat_flutter/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 620ff07b..383eeb02 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.3.2 + +- Updated `stream_chat_flutter_core` dependency to [`3.3.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog). + ## 3.3.1 ✅ Added diff --git a/packages/stream_chat_flutter/pubspec.yaml b/packages/stream_chat_flutter/pubspec.yaml index 40894d3a..86dcd0f6 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: 3.3.1 +version: 3.3.2 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: ^3.0.4 shimmer: ^2.0.0 - stream_chat_flutter_core: ^3.3.0 + stream_chat_flutter_core: ^3.3.1 substring_highlight: ^1.0.26 synchronized: ^3.0.0 url_launcher: ^6.0.3 From 48dbeb3f9f95a306f32c555665dcba609e571fe4 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 8 Dec 2021 13:19:32 +0530 Subject: [PATCH 11/23] update connectivity deps --- packages/stream_chat_flutter_core/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat_flutter_core/pubspec.yaml b/packages/stream_chat_flutter_core/pubspec.yaml index 48d104f3..648d838c 100644 --- a/packages/stream_chat_flutter_core/pubspec.yaml +++ b/packages/stream_chat_flutter_core/pubspec.yaml @@ -11,7 +11,7 @@ environment: dependencies: collection: ^1.15.0 - connectivity_plus: ^2.0.2 + connectivity_plus: ^2.1.0 flutter: sdk: flutter meta: ^1.3.0 From 5567708fe9645de6e00fcc8b4df8eddc420072ae Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 13 Dec 2021 15:50:33 +0530 Subject: [PATCH 12/23] feat(llc): Add enrichUrl endpoint. Signed-off-by: xsahil03x --- .../stream_chat/lib/src/client/client.dart | 4 ++ .../lib/src/core/api/general_api.dart | 12 ++++++ .../lib/src/core/api/responses.dart | 40 +++++++++++++++++++ .../lib/src/core/api/responses.g.dart | 15 +++++++ .../test/src/client/client_test.dart | 40 +++++++++++++------ .../test/src/core/api/general_api_test.dart | 39 ++++++++++++++++-- 6 files changed, 133 insertions(+), 17 deletions(-) diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index 29e500ce..b2ae3657 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -1316,6 +1316,10 @@ class StreamChatClient { }, ); + /// Get OpenGraph data of the given [url]. + Future enrichUrl(String url) => + _chatApi.general.enrichUrl(url); + /// Closes the [_ws] connection and resets the [state] /// If [flushChatPersistence] is true the client deletes all offline /// user's data. diff --git a/packages/stream_chat/lib/src/core/api/general_api.dart b/packages/stream_chat/lib/src/core/api/general_api.dart index fa08a475..9a2e773c 100644 --- a/packages/stream_chat/lib/src/core/api/general_api.dart +++ b/packages/stream_chat/lib/src/core/api/general_api.dart @@ -96,4 +96,16 @@ class GeneralApi { return QueryMembersResponse.fromJson(response.data); } + + /// Get OpenGraph data of the given [url]. + Future enrichUrl(String url) async { + final response = await _client.get( + '/og', + queryParameters: { + 'url': url, + }, + ); + + return OGAttachmentResponse.fromJson(response.data); + } } diff --git a/packages/stream_chat/lib/src/core/api/responses.dart b/packages/stream_chat/lib/src/core/api/responses.dart index 5b52b65d..937e0150 100644 --- a/packages/stream_chat/lib/src/core/api/responses.dart +++ b/packages/stream_chat/lib/src/core/api/responses.dart @@ -442,3 +442,43 @@ class ChannelStateResponse extends _BaseResponse { static ChannelStateResponse fromJson(Map json) => _$ChannelStateResponseFromJson(json); } + +/// Model response for [Client.enrichUrl] api call. +@JsonSerializable(createToJson: false) +class OGAttachmentResponse extends _BaseResponse { + /// The URL of the page that was scraped. + late String ogScrapeUrl; + + /// The URL of the asset. + String? assetUrl; + + /// The URL of the author. + String? authorLink; + + /// The name of the author. + String? authorName; + + /// The URL of the image. + String? imageUrl; + + /// The text of the attachment. + String? text; + + /// The URL of the thumbnail. + String? thumbUrl; + + /// The title of the attachment. + String? title; + + /// The URL of the title. + String? titleLink; + + /// The type of the attachment. + /// + /// 'video' | 'audio' | 'image' + String? type; + + /// Create a new instance from a [json]. + static OGAttachmentResponse fromJson(Map json) => + _$OGAttachmentResponseFromJson(json); +} diff --git a/packages/stream_chat/lib/src/core/api/responses.g.dart b/packages/stream_chat/lib/src/core/api/responses.g.dart index 13d7d77b..fbcdd252 100644 --- a/packages/stream_chat/lib/src/core/api/responses.g.dart +++ b/packages/stream_chat/lib/src/core/api/responses.g.dart @@ -273,3 +273,18 @@ ChannelStateResponse _$ChannelStateResponseFromJson( ?.map((e) => Read.fromJson(e as Map)) .toList() ?? []; + +OGAttachmentResponse _$OGAttachmentResponseFromJson( + Map json) => + OGAttachmentResponse() + ..duration = json['duration'] as String? + ..ogScrapeUrl = json['og_scrape_url'] as String + ..assetUrl = json['asset_url'] as String? + ..authorLink = json['author_link'] as String? + ..authorName = json['author_name'] as String? + ..imageUrl = json['image_url'] as String? + ..text = json['text'] as String? + ..thumbUrl = json['thumb_url'] as String? + ..title = json['title'] as String? + ..titleLink = json['title_link'] as String? + ..type = json['type'] as String?; diff --git a/packages/stream_chat/test/src/client/client_test.dart b/packages/stream_chat/test/src/client/client_test.dart index 36c5919e..22e0edf8 100644 --- a/packages/stream_chat/test/src/client/client_test.dart +++ b/packages/stream_chat/test/src/client/client_test.dart @@ -1,20 +1,7 @@ import 'package:mocktail/mocktail.dart'; -import 'package:stream_chat/src/client/client.dart'; import 'package:stream_chat/src/core/api/device_api.dart'; -import 'package:stream_chat/src/core/api/requests.dart'; -import 'package:stream_chat/src/core/api/responses.dart'; -import 'package:stream_chat/src/core/error/error.dart'; import 'package:stream_chat/src/core/http/token.dart'; -import 'package:stream_chat/src/core/models/channel_model.dart'; -import 'package:stream_chat/src/core/models/event.dart'; -import 'package:stream_chat/src/core/models/filter.dart'; -import 'package:stream_chat/src/core/models/message.dart'; -import 'package:stream_chat/src/core/models/own_user.dart'; -import 'package:stream_chat/src/core/models/user.dart'; -import 'package:stream_chat/src/event_type.dart'; -import 'package:stream_chat/src/ws/connection_status.dart'; import 'package:stream_chat/stream_chat.dart'; -import 'package:test/scaffolding.dart'; import 'package:test/test.dart'; import '../fakes.dart'; @@ -2314,6 +2301,33 @@ void main() { verifyNoMoreInteractions(api.message); }); + test('`.enrichUrl`', () async { + const url = + 'https://www.techyourchance.com/finite-state-machine-with-unit-tests-real-world-example'; + + when(() => api.general.enrichUrl(url)).thenAnswer( + (_) async => OGAttachmentResponse() + ..type = 'image' + ..ogScrapeUrl = url + ..authorName = 'TechYourChance' + ..title = 'Finite State Machine with Unit Tests: Real World Example', + ); + + final res = await client.enrichUrl(url); + + expect(res, isNotNull); + expect(res.type, 'image'); + expect(res.ogScrapeUrl, url); + expect(res.authorName, 'TechYourChance'); + expect( + res.title, + 'Finite State Machine with Unit Tests: Real World Example', + ); + + verify(() => api.general.enrichUrl(url)).called(1); + verifyNoMoreInteractions(api.general); + }); + test( '''setting the `currentUser` should also compute and update the unreadCounts''', () { diff --git a/packages/stream_chat/test/src/core/api/general_api_test.dart b/packages/stream_chat/test/src/core/api/general_api_test.dart index 570d7c77..0a27cce4 100644 --- a/packages/stream_chat/test/src/core/api/general_api_test.dart +++ b/packages/stream_chat/test/src/core/api/general_api_test.dart @@ -3,10 +3,6 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:mocktail/mocktail.dart'; import 'package:stream_chat/src/core/api/general_api.dart'; -import 'package:stream_chat/src/core/api/requests.dart'; -import 'package:stream_chat/src/core/models/channel_model.dart'; -import 'package:stream_chat/src/core/models/event.dart'; -import 'package:stream_chat/src/core/models/filter.dart'; import 'package:stream_chat/stream_chat.dart'; import 'package:test/test.dart'; @@ -281,4 +277,39 @@ void main() { verifyNoMoreInteractions(client); }); }); + + test('enrichUrl', () async { + const path = '/og'; + const url = + 'https://www.techyourchance.com/finite-state-machine-with-unit-tests-real-world-example'; + + when(() => client.get( + path, + queryParameters: {'url': url}, + )).thenAnswer((_) async => successResponse(path, data: { + 'type': 'image', + 'og_scrape_url': url, + 'author_name': 'TechYourChance', + 'title': 'Finite State Machine with Unit Tests: Real World Example', + })); + + final res = await generalApi.enrichUrl(url); + + expect(res, isNotNull); + expect(res.type, 'image'); + expect(res.ogScrapeUrl, url); + expect(res.authorName, 'TechYourChance'); + expect( + res.title, + 'Finite State Machine with Unit Tests: Real World Example', + ); + + verify( + () => client.get( + path, + queryParameters: {'url': url}, + ), + ).called(1); + verifyNoMoreInteractions(client); + }); } From a5242627f9828e9a901bc3245ebcfeee21dc908e Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 13 Dec 2021 15:53:36 +0530 Subject: [PATCH 13/23] chore(llc): update CHANGELOG.md Signed-off-by: xsahil03x --- packages/stream_chat/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index 940d25c5..f7e02ba4 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,3 +1,9 @@ +## Upcoming + +✅ Added + +- Added `client.enrichUrl` endpoint for enriching URLs with metadata. + ## 3.3.1 🐞 Fixed From a5005bb78f9fb5074d40c9ce6bb6b4643ef782e4 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 16 Dec 2021 10:17:42 +0100 Subject: [PATCH 14/23] fix(ui): use file extension instead of mimeType --- .../lib/src/attachment_actions_modal.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/stream_chat_flutter/lib/src/attachment_actions_modal.dart b/packages/stream_chat_flutter/lib/src/attachment_actions_modal.dart index 0c10ae46..ac9213b6 100644 --- a/packages/stream_chat_flutter/lib/src/attachment_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/attachment_actions_modal.dart @@ -365,12 +365,13 @@ class AttachmentActionsModal extends StatelessWidget { }) async { String? filePath; final appDocDir = await getTemporaryDirectory(); + final url = + attachment.assetUrl ?? attachment.imageUrl ?? attachment.thumbUrl!; await Dio().download( - attachment.assetUrl ?? attachment.imageUrl ?? attachment.thumbUrl!, + url, (Headers responseHeaders) { - final contentType = responseHeaders[Headers.contentTypeHeader]!; - final mimeType = contentType.first.split('/').last; - filePath ??= '${appDocDir.path}/${attachment.id}.$mimeType'; + final ext = Uri.parse(url).pathSegments.last; + filePath ??= '${appDocDir.path}/${attachment.id}.$ext'; return filePath!; }, onReceiveProgress: progressCallback, From 505b11b12e185041038674afa51aeef0416a73e4 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 16 Dec 2021 10:19:29 +0100 Subject: [PATCH 15/23] chore(ui): update changelog --- packages/stream_chat_flutter/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 383eeb02..4fc7439e 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,3 +1,9 @@ +## Upcoming + +🐞 Fixed + +- Use file extension instead of mimeType for downloading files + ## 3.3.2 - Updated `stream_chat_flutter_core` dependency to [`3.3.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog). From 2638b148d0b59d12cd67b7668149ef260da52e44 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 16 Dec 2021 17:11:07 +0530 Subject: [PATCH 16/23] added autoplay to videos --- .../lib/src/full_screen_media.dart | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) 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 6547a93d..f56cc7dc 100644 --- a/packages/stream_chat_flutter/lib/src/full_screen_media.dart +++ b/packages/stream_chat_flutter/lib/src/full_screen_media.dart @@ -34,6 +34,7 @@ class FullScreenMedia extends StatefulWidget { String? userName, this.onShowMessage, this.attachmentActionsModalBuilder, + this.autoplayVideos = false, }) : userName = userName ?? '', super(key: key); @@ -57,6 +58,8 @@ class FullScreenMedia extends StatefulWidget { /// Use [defaultActionsModal.copyWith] to easily customize it final AttachmentActionsBuilder? attachmentActionsModalBuilder; + final bool autoplayVideos; + @override _FullScreenMediaState createState() => _FullScreenMediaState(); } @@ -81,7 +84,8 @@ class _FullScreenMediaState extends State ); _pageController = PageController(initialPage: widget.startIndex); _currentPage = widget.startIndex; - for (final attachment in widget.mediaAttachments) { + for (var i = 0; i < widget.mediaAttachments.length; i++) { + final attachment = widget.mediaAttachments[i]; if (attachment.type != 'video') continue; final package = VideoPackage(attachment, showControls: true); videoPackages[attachment.id] = package; @@ -90,9 +94,21 @@ class _FullScreenMediaState extends State } Future initializePlayers() async { + if (videoPackages.isEmpty) { + return; + } + + final currentAttachment = widget.mediaAttachments[widget.startIndex]; + await Future.wait(videoPackages.values.map( (it) => it.initialize(), )); + + if (widget.autoplayVideos && currentAttachment.type == 'video') { + final package = videoPackages.values + .firstWhere((e) => e._attachment == currentAttachment); + package._chewieController?.play(); + } setState(() {}); // ignore: no-empty-block } @@ -109,6 +125,24 @@ class _FullScreenMediaState extends State setState(() { _currentPage = val; }); + + if (videoPackages.isEmpty) { + return; + } + + final currentAttachment = widget.mediaAttachments[val]; + + for (final e in videoPackages.values) { + if (e._attachment != currentAttachment) { + e._chewieController?.pause(); + } + } + + if (widget.autoplayVideos && + currentAttachment.type == 'video') { + final controller = videoPackages[currentAttachment.id]!; + controller._chewieController?.play(); + } }, itemBuilder: (context, index) { final attachment = widget.mediaAttachments[index]; @@ -243,15 +277,16 @@ class _FullScreenMediaState extends State class VideoPackage { /// Constructor for creating [VideoPackage] VideoPackage( - Attachment attachment, { + this._attachment, { bool showControls = false, bool autoInitialize = true, }) : _showControls = showControls, _autoInitialize = autoInitialize, - _videoPlayerController = attachment.localUri != null - ? VideoPlayerController.file(File.fromUri(attachment.localUri!)) - : VideoPlayerController.network(attachment.assetUrl!); + _videoPlayerController = _attachment.localUri != null + ? VideoPlayerController.file(File.fromUri(_attachment.localUri!)) + : VideoPlayerController.network(_attachment.assetUrl!); + final Attachment _attachment; final bool _showControls; final bool _autoInitialize; final VideoPlayerController _videoPlayerController; From cb605673720c459e817f1e5e7e8f8b64e0d8a04f Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 16 Dec 2021 17:13:55 +0530 Subject: [PATCH 17/23] added autoplay to videos --- packages/stream_chat_flutter/CHANGELOG.md | 6 ++++++ packages/stream_chat_flutter/lib/src/full_screen_media.dart | 1 + 2 files changed, 7 insertions(+) diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 383eeb02..0b4089c7 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,3 +1,9 @@ +## Upcoming + +✅ Added + +- Videos can now be auto-played in `FullScreenMedia` + ## 3.3.2 - Updated `stream_chat_flutter_core` dependency to [`3.3.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog). 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 f56cc7dc..84ddb803 100644 --- a/packages/stream_chat_flutter/lib/src/full_screen_media.dart +++ b/packages/stream_chat_flutter/lib/src/full_screen_media.dart @@ -58,6 +58,7 @@ class FullScreenMedia extends StatefulWidget { /// Use [defaultActionsModal.copyWith] to easily customize it final AttachmentActionsBuilder? attachmentActionsModalBuilder; + /// Auto-play videos when page is opened final bool autoplayVideos; @override From 0aed43b1881703d3decc2909047e4f1d5db490b6 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 20 Dec 2021 10:55:51 +0100 Subject: [PATCH 18/23] fix(ui): use all message attachments in FullScreenMedia page --- .../lib/src/attachment/giphy_attachment.dart | 3 ++- .../lib/src/attachment/image_attachment.dart | 4 +++- .../lib/src/attachment/video_attachment.dart | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/stream_chat_flutter/lib/src/attachment/giphy_attachment.dart b/packages/stream_chat_flutter/lib/src/attachment/giphy_attachment.dart index fc0fb586..cc29f0b2 100644 --- a/packages/stream_chat_flutter/lib/src/attachment/giphy_attachment.dart +++ b/packages/stream_chat_flutter/lib/src/attachment/giphy_attachment.dart @@ -246,7 +246,8 @@ class GiphyAttachment extends AttachmentWidget { return StreamChannel( channel: channel, child: FullScreenMedia( - mediaAttachments: [attachment], + mediaAttachments: message.attachments, + startIndex: message.attachments.indexOf(attachment), userName: message.user?.name, message: message, onShowMessage: onShowMessage, diff --git a/packages/stream_chat_flutter/lib/src/attachment/image_attachment.dart b/packages/stream_chat_flutter/lib/src/attachment/image_attachment.dart index 41b8d039..ff01eea3 100644 --- a/packages/stream_chat_flutter/lib/src/attachment/image_attachment.dart +++ b/packages/stream_chat_flutter/lib/src/attachment/image_attachment.dart @@ -141,7 +141,9 @@ class ImageAttachment extends AttachmentWidget { return StreamChannel( channel: channel, child: FullScreenMedia( - mediaAttachments: [attachment], + mediaAttachments: message.attachments, + startIndex: + message.attachments.indexOf(attachment), userName: message.user?.name, message: message, onShowMessage: onShowMessage, diff --git a/packages/stream_chat_flutter/lib/src/attachment/video_attachment.dart b/packages/stream_chat_flutter/lib/src/attachment/video_attachment.dart index ce4ac804..0fc97d5e 100644 --- a/packages/stream_chat_flutter/lib/src/attachment/video_attachment.dart +++ b/packages/stream_chat_flutter/lib/src/attachment/video_attachment.dart @@ -87,7 +87,9 @@ class VideoAttachment extends AttachmentWidget { builder: (_) => StreamChannel( channel: channel, child: FullScreenMedia( - mediaAttachments: [attachment], + mediaAttachments: message.attachments, + startIndex: + message.attachments.indexOf(attachment), userName: message.user?.name, message: message, onShowMessage: onShowMessage, From b87e18ff3eb0a5f370b013c4fda6472f427cc136 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Mon, 27 Dec 2021 13:36:22 +0530 Subject: [PATCH 19/23] fixed svgs --- .../lib/svgs/STREAM MARK 1.svg | 10 +++++----- .../lib/svgs/UI_Reverse Pagination Loading.svg | 18 +++++++++--------- .../lib/svgs/filetype_DOC.svg | 12 ++++++------ .../lib/svgs/filetype_DOCX.svg | 12 ++++++------ .../lib/svgs/filetype_Generic.svg | 12 ++++++------ .../lib/svgs/filetype_PPT.svg | 12 ++++++------ .../lib/svgs/filetype_PPTX-1.svg | 12 ++++++------ .../lib/svgs/filetype_PPTX.svg | 12 ++++++------ .../lib/svgs/filetype_XLS.svg | 12 ++++++------ .../lib/svgs/filetype_XLSX.svg | 12 ++++++------ .../stream_chat_flutter/lib/svgs/imgur.svg | 10 +++++----- 11 files changed, 67 insertions(+), 67 deletions(-) diff --git a/packages/stream_chat_flutter/lib/svgs/STREAM MARK 1.svg b/packages/stream_chat_flutter/lib/svgs/STREAM MARK 1.svg index 57ccef0f..91fedc05 100644 --- a/packages/stream_chat_flutter/lib/svgs/STREAM MARK 1.svg +++ b/packages/stream_chat_flutter/lib/svgs/STREAM MARK 1.svg @@ -1,10 +1,10 @@ + + + + + - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/UI_Reverse Pagination Loading.svg b/packages/stream_chat_flutter/lib/svgs/UI_Reverse Pagination Loading.svg index dfc3754f..487388a5 100644 --- a/packages/stream_chat_flutter/lib/svgs/UI_Reverse Pagination Loading.svg +++ b/packages/stream_chat_flutter/lib/svgs/UI_Reverse Pagination Loading.svg @@ -1,14 +1,14 @@ + + + + + + + + + - - - - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/filetype_DOC.svg b/packages/stream_chat_flutter/lib/svgs/filetype_DOC.svg index 4233055a..36ce7610 100644 --- a/packages/stream_chat_flutter/lib/svgs/filetype_DOC.svg +++ b/packages/stream_chat_flutter/lib/svgs/filetype_DOC.svg @@ -1,12 +1,12 @@ + + + + + + - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/filetype_DOCX.svg b/packages/stream_chat_flutter/lib/svgs/filetype_DOCX.svg index 3077f515..dea4b040 100644 --- a/packages/stream_chat_flutter/lib/svgs/filetype_DOCX.svg +++ b/packages/stream_chat_flutter/lib/svgs/filetype_DOCX.svg @@ -1,12 +1,12 @@ + + + + + + - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/filetype_Generic.svg b/packages/stream_chat_flutter/lib/svgs/filetype_Generic.svg index 3ec0f239..453ee694 100644 --- a/packages/stream_chat_flutter/lib/svgs/filetype_Generic.svg +++ b/packages/stream_chat_flutter/lib/svgs/filetype_Generic.svg @@ -1,11 +1,11 @@ + + + + + + - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/filetype_PPT.svg b/packages/stream_chat_flutter/lib/svgs/filetype_PPT.svg index 0541a496..1d3d429c 100644 --- a/packages/stream_chat_flutter/lib/svgs/filetype_PPT.svg +++ b/packages/stream_chat_flutter/lib/svgs/filetype_PPT.svg @@ -1,12 +1,12 @@ + + + + + + - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/filetype_PPTX-1.svg b/packages/stream_chat_flutter/lib/svgs/filetype_PPTX-1.svg index a50efd64..c6d866a1 100644 --- a/packages/stream_chat_flutter/lib/svgs/filetype_PPTX-1.svg +++ b/packages/stream_chat_flutter/lib/svgs/filetype_PPTX-1.svg @@ -1,12 +1,12 @@ + + + + + + - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/filetype_PPTX.svg b/packages/stream_chat_flutter/lib/svgs/filetype_PPTX.svg index 83339acc..920fbb62 100644 --- a/packages/stream_chat_flutter/lib/svgs/filetype_PPTX.svg +++ b/packages/stream_chat_flutter/lib/svgs/filetype_PPTX.svg @@ -1,12 +1,12 @@ + + + + + + - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/filetype_XLS.svg b/packages/stream_chat_flutter/lib/svgs/filetype_XLS.svg index eec9a05d..60820220 100644 --- a/packages/stream_chat_flutter/lib/svgs/filetype_XLS.svg +++ b/packages/stream_chat_flutter/lib/svgs/filetype_XLS.svg @@ -1,12 +1,12 @@ + + + + + + - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/filetype_XLSX.svg b/packages/stream_chat_flutter/lib/svgs/filetype_XLSX.svg index 6203aa27..c71ff20b 100644 --- a/packages/stream_chat_flutter/lib/svgs/filetype_XLSX.svg +++ b/packages/stream_chat_flutter/lib/svgs/filetype_XLSX.svg @@ -1,12 +1,12 @@ + + + + + + - - - - - - diff --git a/packages/stream_chat_flutter/lib/svgs/imgur.svg b/packages/stream_chat_flutter/lib/svgs/imgur.svg index 1df5d71f..71ab1fc5 100644 --- a/packages/stream_chat_flutter/lib/svgs/imgur.svg +++ b/packages/stream_chat_flutter/lib/svgs/imgur.svg @@ -1,12 +1,12 @@ + + + + + - - - - - From 3ecfb745a2694d6bdb6a29c8bcb51bb189a8609d Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Mon, 27 Dec 2021 15:30:22 +0530 Subject: [PATCH 20/23] fixed svgs --- packages/stream_chat_flutter/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 0b4089c7..03a00d01 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,5 +1,9 @@ ## Upcoming +🐞 Fixed + +- SVG rendering fixes + ✅ Added - Videos can now be auto-played in `FullScreenMedia` From 96f0c8bf927e82e51f7be121ec6a27183d8f55ce Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 29 Dec 2021 17:25:56 +0530 Subject: [PATCH 21/23] fixed unread count after member removed --- packages/stream_chat/lib/src/client/channel.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 51034d3a..258122a7 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1538,6 +1538,7 @@ class ChannelClientState { members: List.from( channelState.members..removeWhere((m) => m.userId == user!.id), ), + read: channelState.read..removeWhere((r) => r.user.id == user!.id), )); })); } From 149f8c9e605bd56fc37cdc073c0fa94b06290e9a Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 29 Dec 2021 17:33:39 +0530 Subject: [PATCH 22/23] added changelog --- packages/stream_chat_flutter/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 8980e7af..e046ada8 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -4,6 +4,7 @@ - SVG rendering fixes - Use file extension instead of mimeType for downloading files +- Fixed `unreadCount` after removing user from a channel. ✅ Added From ba63be0cc2fd5d5831e8c3add0ff32da185985d5 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 29 Dec 2021 17:37:31 +0530 Subject: [PATCH 23/23] corrected changelog --- packages/stream_chat/CHANGELOG.md | 1 + packages/stream_chat_flutter/CHANGELOG.md | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index f7e02ba4..4a2bb7ec 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -3,6 +3,7 @@ ✅ Added - Added `client.enrichUrl` endpoint for enriching URLs with metadata. +- Fixed `unreadCount` after removing user from a channel. ## 3.3.1 diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index e046ada8..8980e7af 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -4,7 +4,6 @@ - SVG rendering fixes - Use file extension instead of mimeType for downloading files -- Fixed `unreadCount` after removing user from a channel. ✅ Added