Skip to content

Commit

Permalink
Merge pull request #1538 from GetStream/release/v6.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
xsahil03x authored May 12, 2023
2 parents dc114d2 + 1a7e2d0 commit 13dce4d
Show file tree
Hide file tree
Showing 71 changed files with 3,575 additions and 1,202 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/stream_flutter_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ on:
pull_request:
paths:
- 'packages/**'
types:
- opened
- reopened
- synchronize
- ready_for_review
push:
branches:
- master
Expand Down
42 changes: 42 additions & 0 deletions packages/stream_chat/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
## 6.1.0

🐞 Fixed

- [[#1355]](https://github.com/GetStream/stream-chat-flutter/issues/1355) Fixed error while hiding channel and clearing
message history.
- [[#1525]](https://github.com/GetStream/stream-chat-flutter/issues/1525) Fixed removing message not removing quoted
message reference.

✅ Added

- Expose `ChannelMute` class. [#1473](https://github.com/GetStream/stream-chat-flutter/issues/1473)
- Added synchronization to the `StreamChatClient.sync`
api. [#1392](https://github.com/GetStream/stream-chat-flutter/issues/1392)
- Added support for `StreamChatClient.chatApiInterceptors` to add custom interceptors to the API client.
[#1265](https://github.com/GetStream/stream-chat-flutter/issues/1265).

```dart
final client = StreamChatClient(
chatApiInterceptors: [
InterceptorsWrapper(
onRequest: (options, handler) {
// Do something before request is sent.
return handler.next(options);
},
onResponse: (response, handler) {
// Do something with response data
return handler.next(response);
},
onError: (DioError e, handler) {
// Do something with response error
return handler.next(e);
},
),
],
);
```

🔄 Changed

- Updated `dart` sdk environment range to support `3.0.0`.

## 6.0.0

🐞 Fixed
Expand Down
84 changes: 52 additions & 32 deletions packages/stream_chat/lib/src/client/channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@ class Channel {
state!.deleteMessage(
message.copyWith(
type: 'deleted',
deletedAt: message.deletedAt ?? DateTime.now(),
status: MessageSendingStatus.sent,
),
hardDelete: hardDelete,
Expand Down Expand Up @@ -997,26 +998,24 @@ class Channel {
) async {
final type = reaction.type;

final reactionCounts = {...message.reactionCounts ?? <String, int>{}};
final reactionCounts = {...?message.reactionCounts};
if (reactionCounts.containsKey(type)) {
reactionCounts.update(type, (value) => value - 1);
}
final reactionScores = {...message.reactionScores ?? <String, int>{}};
final reactionScores = {...?message.reactionScores};
if (reactionScores.containsKey(type)) {
reactionScores.update(type, (value) => value - 1);
}

final latestReactions = [...message.latestReactions ?? <Reaction>[]]
..removeWhere((r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);
final latestReactions = [...?message.latestReactions]..removeWhere((r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);

final ownReactions = message.ownReactions
?..removeWhere((r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);
final ownReactions = [...?message.ownReactions]..removeWhere((r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);

final newMessage = message.copyWith(
reactionCounts: reactionCounts..removeWhere((_, value) => value == 0),
Expand Down Expand Up @@ -1485,19 +1484,11 @@ class Channel {
/// will be removed for the user.
Future<EmptyResponse> hide({bool clearHistory = false}) async {
_checkInitialized();
final response = await _client.hideChannel(
return _client.hideChannel(
id!,
type,
clearHistory: clearHistory,
);
if (clearHistory) {
state!.truncate();
final cid = _cid;
if (cid != null) {
await _client.chatPersistenceClient?.deleteMessageByCid(cid);
}
}
return response;
}

/// Removes the hidden status for the channel.
Expand Down Expand Up @@ -1938,11 +1929,9 @@ class ChannelClientState {
void _listenMessageDeleted() {
_subscriptions.add(_channel.on(EventType.messageDeleted).listen((event) {
final message = event.message!;
if (event.hardDelete == true) {
removeMessage(message);
} else {
updateMessage(message);
}
final hardDelete = event.hardDelete ?? false;

deleteMessage(message, hardDelete: hardDelete);
}));
}

Expand All @@ -1967,18 +1956,35 @@ class ChannelClientState {

/// Updates the [message] in the state if it exists. Adds it otherwise.
void updateMessage(Message message) {
// Regular messages, which are shown in channel.
if (message.parentId == null || message.showInChannel == true) {
final newMessages = [...messages];
var newMessages = [...messages];
final oldIndex = newMessages.indexWhere((m) => m.id == message.id);
if (oldIndex != -1) {
Message? m;
var updatedMessage = message;
// Add quoted message to the message if it is not present.
if (message.quotedMessageId != null && message.quotedMessage == null) {
final oldMessage = newMessages[oldIndex];
m = message.copyWith(
updatedMessage = updatedMessage.copyWith(
quotedMessage: oldMessage.quotedMessage,
);
}
newMessages[oldIndex] = m ?? message;
newMessages[oldIndex] = updatedMessage;

// Update quoted message reference for every message if available.
newMessages = [...newMessages].map((it) {
// Early return if the message doesn't have a quoted message.
if (it.quotedMessageId != message.id) return it;

// Setting it to null will remove the quoted message from the message
// So, we are setting the same message but with the deleted state.
return it.copyWith(
quotedMessage: updatedMessage.copyWith(
type: 'deleted',
deletedAt: updatedMessage.deletedAt ?? DateTime.now(),
),
);
}).toList();
} else {
newMessages.add(message);
}
Expand Down Expand Up @@ -2007,6 +2013,7 @@ class ChannelClientState {
);
}

// Thread messages, which are shown in thread page.
if (message.parentId != null) {
updateThreadInfo(message.parentId!, [message]);
}
Expand Down Expand Up @@ -2036,9 +2043,22 @@ class ChannelClientState {
}

// Remove regular message, thread message shown in channel
final allMessages = [...messages];
var updatedMessages = [...messages]..removeWhere((e) => e.id == message.id);

// Remove quoted message reference from every message if available.
updatedMessages = [...updatedMessages].map((it) {
// Early return if the message doesn't have a quoted message.
if (it.quotedMessageId != message.id) return it;

// Setting it to null will remove the quoted message from the message.
return it.copyWith(
quotedMessage: null,
quotedMessageId: null,
);
}).toList();

_channelState = _channelState.copyWith(
messages: allMessages..removeWhere((e) => e.id == message.id),
messages: updatedMessages,
);
}

Expand Down
68 changes: 37 additions & 31 deletions packages/stream_chat/lib/src/client/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import 'package:stream_chat/src/event_type.dart';
import 'package:stream_chat/src/ws/connection_status.dart';
import 'package:stream_chat/src/ws/websocket.dart';
import 'package:stream_chat/version.dart';
import 'package:synchronized/extension.dart';

/// Handler function used for logging records. Function requires a single
/// [LogRecord] as the only parameter.
Expand Down Expand Up @@ -72,6 +73,7 @@ class StreamChatClient {
WebSocket? ws,
AttachmentFileUploaderProvider attachmentFileUploaderProvider =
StreamAttachmentFileUploader.new,
Iterable<Interceptor>? chatApiInterceptors,
}) {
logger.info('Initiating new StreamChatClient');

Expand All @@ -90,6 +92,7 @@ class StreamChatClient {
connectionIdManager: _connectionIdManager,
attachmentFileUploaderProvider: attachmentFileUploaderProvider,
logger: detachedLogger('🕸️'),
interceptors: chatApiInterceptors,
);

_ws = ws ??
Expand Down Expand Up @@ -488,37 +491,40 @@ class StreamChatClient {

/// Get the events missed while offline to sync the offline storage
/// Will automatically fetch [cids] and [lastSyncedAt] if [persistenceEnabled]
Future<void> sync({List<String>? cids, DateTime? lastSyncAt}) async {
cids ??= await _chatPersistenceClient?.getChannelCids();
if (cids == null || cids.isEmpty) {
return;
}
Future<void> sync({List<String>? cids, DateTime? lastSyncAt}) {
return synchronized(() async {
final channels = cids ?? await _chatPersistenceClient?.getChannelCids();
if (channels == null || channels.isEmpty) {
return;
}

lastSyncAt ??= await _chatPersistenceClient?.getLastSyncAt();
if (lastSyncAt == null) {
return;
}
final syncAt =
lastSyncAt ?? await _chatPersistenceClient?.getLastSyncAt();
if (syncAt == null) {
return;
}

try {
final res = await _chatApi.general.sync(cids, lastSyncAt);
final events = res.events
..sort((a, b) => a.createdAt.compareTo(b.createdAt));

for (final event in events) {
logger.fine('event.type: ${event.type}');
final messageText = event.message?.text;
if (messageText != null) {
logger.fine('event.message.text: $messageText');
try {
final res = await _chatApi.general.sync(channels, syncAt);
final events = res.events
..sort((a, b) => a.createdAt.compareTo(b.createdAt));

for (final event in events) {
logger.fine('event.type: ${event.type}');
final messageText = event.message?.text;
if (messageText != null) {
logger.fine('event.message.text: $messageText');
}
handleEvent(event);
}
handleEvent(event);
}

final now = DateTime.now();
_lastSyncedAt = now;
_chatPersistenceClient?.updateLastSyncAt(now);
} catch (e, stk) {
logger.severe('Error during sync', e, stk);
}
final now = DateTime.now();
_lastSyncedAt = now;
_chatPersistenceClient?.updateLastSyncAt(now);
} catch (e, stk) {
logger.severe('Error during sync', e, stk);
}
});
}

final _queryChannelsStreams = <String, Future<List<Channel>>>{};
Expand Down Expand Up @@ -1567,7 +1573,7 @@ class ClientState {
_client.on(EventType.channelHidden).listen((event) async {
final eventChannel = event.channel!;
await _client.chatPersistenceClient?.deleteChannels([eventChannel.cid]);
channels[eventChannel.cid]?.dispose();
channels.remove(eventChannel.cid)?.dispose();
}),
);
}
Expand Down Expand Up @@ -1606,7 +1612,7 @@ class ClientState {
.listen((Event event) async {
final eventChannel = event.channel!;
await _client.chatPersistenceClient?.deleteChannels([eventChannel.cid]);
channels[eventChannel.cid]?.dispose();
channels.remove(eventChannel.cid)?.dispose();
}),
);
}
Expand Down Expand Up @@ -1713,9 +1719,9 @@ class ClientState {
_unreadChannelsController.close();
_totalUnreadCountController.close();

final channels = this.channels.values.toList();
final channels = [...this.channels.keys];
for (final channel in channels) {
channel.dispose();
this.channels.remove(channel)?.dispose();
}
_channelsController.close();
}
Expand Down
3 changes: 3 additions & 0 deletions packages/stream_chat/lib/src/core/api/stream_chat_api.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:dio/dio.dart';
import 'package:logging/logging.dart';
import 'package:stream_chat/src/core/api/attachment_file_uploader.dart';
import 'package:stream_chat/src/core/api/call_api.dart';
Expand Down Expand Up @@ -26,6 +27,7 @@ class StreamChatApi {
AttachmentFileUploaderProvider attachmentFileUploaderProvider =
StreamAttachmentFileUploader.new,
Logger? logger,
Iterable<Interceptor>? interceptors,
}) : _fileUploaderProvider = attachmentFileUploaderProvider,
_client = client ??
StreamHttpClient(
Expand All @@ -34,6 +36,7 @@ class StreamChatApi {
tokenManager: tokenManager,
connectionIdManager: connectionIdManager,
logger: logger,
interceptors: interceptors,
);

final StreamHttpClient _client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ class LoggingInterceptor extends Interceptor {
options.data as Map?,
header: 'Body',
);
}
if (data is FormData) {
} else if (data is FormData) {
final formDataMap = <String, dynamic>{}
..addEntries(data.fields)
..addEntries(data.files);
Expand Down Expand Up @@ -163,7 +162,7 @@ class LoggingInterceptor extends Interceptor {
_logPrintResponse('║');
_printResponse(_logPrintResponse, response);
_logPrintResponse('║');
_logPrintResponse('╚');
_printLine(_logPrintResponse, '╚');
}
super.onResponse(response, handler);
}
Expand Down
Loading

0 comments on commit 13dce4d

Please sign in to comment.