From 821d8ee0f09bad1e0582b57b7784a6d398524df2 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Fri, 12 Nov 2021 16:42:33 +0530 Subject: [PATCH 1/4] added hard delete --- packages/stream_chat/CHANGELOG.md | 6 ++++++ packages/stream_chat/lib/src/client/channel.dart | 4 ++-- packages/stream_chat/lib/src/client/client.dart | 4 ++-- packages/stream_chat/lib/src/core/api/message_api.dart | 8 ++++++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index 4b409536..33a95b03 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,3 +1,9 @@ +## Upcoming + +✅ Added + +- Added hard delete functionality. + ## 3.2.0 🐞 Fixed diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index e7c2d459..ab4f17c3 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -648,7 +648,7 @@ class Channel { } /// Deletes the [message] from the channel. - Future deleteMessage(Message message) async { + Future deleteMessage(Message message, {bool? hard}) async { // Directly deleting the local messages which are not yet sent to server if (message.status == MessageSendingStatus.sending || message.status == MessageSendingStatus.failed) { @@ -675,7 +675,7 @@ class Channel { state?.addMessage(message); - final response = await _client.deleteMessage(message.id); + final response = await _client.deleteMessage(message.id, hard: hard); state?.addMessage(message.copyWith(status: MessageSendingStatus.sent)); diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index c9bdebc1..ef03288d 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -1213,8 +1213,8 @@ class StreamChatClient { ); /// Deletes the given message - Future deleteMessage(String messageId) => - _chatApi.message.deleteMessage(messageId); + Future deleteMessage(String messageId, {bool? hard}) => + _chatApi.message.deleteMessage(messageId, hard: hard); /// Get a message by [messageId] Future getMessage(String messageId) => diff --git a/packages/stream_chat/lib/src/core/api/message_api.dart b/packages/stream_chat/lib/src/core/api/message_api.dart index 17269820..0fdb41eb 100644 --- a/packages/stream_chat/lib/src/core/api/message_api.dart +++ b/packages/stream_chat/lib/src/core/api/message_api.dart @@ -80,10 +80,14 @@ class MessageApi { /// Deletes the given [messageId] Future deleteMessage( - String messageId, - ) async { + String messageId, { + bool? hard, + }) async { final response = await _client.delete( '/messages/$messageId', + queryParameters: { + if (hard != null) 'hard': hard, + }, ); return EmptyResponse.fromJson(response.data); } From 5916a282d18d2d032ac797b3cf83b806174b0ed2 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 25 Nov 2021 15:03:32 +0530 Subject: [PATCH 2/4] fixed tests --- packages/stream_chat/lib/src/core/api/message_api.dart | 8 +++++--- packages/stream_chat/lib/src/core/models/read.dart | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/stream_chat/lib/src/core/api/message_api.dart b/packages/stream_chat/lib/src/core/api/message_api.dart index 0fdb41eb..8894e14c 100644 --- a/packages/stream_chat/lib/src/core/api/message_api.dart +++ b/packages/stream_chat/lib/src/core/api/message_api.dart @@ -85,9 +85,11 @@ class MessageApi { }) async { final response = await _client.delete( '/messages/$messageId', - queryParameters: { - if (hard != null) 'hard': hard, - }, + queryParameters: hard != null + ? { + 'hard': hard, + } + : null, ); return EmptyResponse.fromJson(response.data); } diff --git a/packages/stream_chat/lib/src/core/models/read.dart b/packages/stream_chat/lib/src/core/models/read.dart index 0ad1164c..40a72c92 100644 --- a/packages/stream_chat/lib/src/core/models/read.dart +++ b/packages/stream_chat/lib/src/core/models/read.dart @@ -8,7 +8,7 @@ part 'read.g.dart'; @JsonSerializable() class Read extends Equatable { /// Constructor used for json serialization - Read({ + const Read({ required this.lastRead, required this.user, this.unreadMessages = 0, From 065df414dff778e240b2bf16c4f38c58f054365d Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 25 Nov 2021 16:54:23 +0530 Subject: [PATCH 3/4] fixed deletion off the main list and offline storage --- packages/stream_chat/lib/src/client/channel.dart | 13 ++++++++++--- packages/stream_chat/lib/src/client/client.dart | 10 ++++++++-- packages/stream_chat/lib/src/core/models/event.dart | 7 +++++++ .../stream_chat/lib/src/core/models/event.g.dart | 2 ++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 482427d6..b4a29ca4 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1663,7 +1663,11 @@ class ChannelClientState { void _listenMessageDeleted() { _subscriptions.add(_channel.on(EventType.messageDeleted).listen((event) { final message = event.message!; - addMessage(message); + if (event.hardDelete == true) { + removeMessage(message, hardDelete: true); + } else { + addMessage(message); + } })); } @@ -1718,7 +1722,7 @@ class ChannelClientState { } /// Remove a [message] from this [channelState]. - void removeMessage(Message message) { + void removeMessage(Message message, {bool hardDelete = false}) { final parentId = message.parentId; // i.e. it's a thread message // 1. Remove the thread message @@ -1740,7 +1744,10 @@ class ChannelClientState { } else { // Remove regular message final allMessages = [...messages]; - if (allMessages.remove(message)) { + if (hardDelete) { + allMessages.removeWhere((e) => e.id == message.id); + _channelState = _channelState.copyWith(messages: allMessages); + } else if (allMessages.remove(message)) { _channelState = _channelState.copyWith(messages: allMessages); } } diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index ef03288d..d6b9e8b5 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -1213,8 +1213,14 @@ class StreamChatClient { ); /// Deletes the given message - Future deleteMessage(String messageId, {bool? hard}) => - _chatApi.message.deleteMessage(messageId, hard: hard); + Future deleteMessage(String messageId, {bool? hard}) async { + final response = + await _chatApi.message.deleteMessage(messageId, hard: hard); + if (hard == true) { + await _chatPersistenceClient?.deleteMessageById(messageId); + } + return response; + } /// Get a message by [messageId] Future getMessage(String messageId) => diff --git a/packages/stream_chat/lib/src/core/models/event.dart b/packages/stream_chat/lib/src/core/models/event.dart index aed35696..b8ddafa7 100644 --- a/packages/stream_chat/lib/src/core/models/event.dart +++ b/packages/stream_chat/lib/src/core/models/event.dart @@ -27,6 +27,7 @@ class Event { this.channelId, this.channelType, this.parentId, + this.hardDelete, this.extraData = const {}, this.isLocal = true, }) : createdAt = createdAt?.toUtc() ?? DateTime.now().toUtc(); @@ -91,6 +92,9 @@ class Event { @JsonKey(defaultValue: false) final bool isLocal; + /// This is true if the message has been hard deleted + final bool? hardDelete; + /// Map of custom channel extraData final Map extraData; @@ -113,6 +117,7 @@ class Event { 'channel_id', 'channel_type', 'parent_id', + 'hard_delete', 'is_local', ]; @@ -139,6 +144,7 @@ class Event { int? unreadChannels, bool? online, String? parentId, + bool? hardDelete, Map? extraData, }) => Event( @@ -158,6 +164,7 @@ class Event { channelId: channelId ?? this.channelId, channelType: channelType ?? this.channelType, parentId: parentId ?? this.parentId, + hardDelete: hardDelete ?? this.hardDelete, extraData: extraData ?? this.extraData, isLocal: isLocal, ); diff --git a/packages/stream_chat/lib/src/core/models/event.g.dart b/packages/stream_chat/lib/src/core/models/event.g.dart index 29a4482b..3a521c9a 100644 --- a/packages/stream_chat/lib/src/core/models/event.g.dart +++ b/packages/stream_chat/lib/src/core/models/event.g.dart @@ -37,6 +37,7 @@ Event _$EventFromJson(Map json) => Event( channelId: json['channel_id'] as String?, channelType: json['channel_type'] as String?, parentId: json['parent_id'] as String?, + hardDelete: json['hard_delete'] as bool?, extraData: json['extra_data'] as Map? ?? const {}, isLocal: json['is_local'] as bool? ?? false, ); @@ -59,6 +60,7 @@ Map _$EventToJson(Event instance) => { 'online': instance.online, 'parent_id': instance.parentId, 'is_local': instance.isLocal, + 'hard_delete': instance.hardDelete, 'extra_data': instance.extraData, }; From f3c0f4b4943f06f8f20e60a5adb79aa553f891aa Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 25 Nov 2021 17:03:17 +0530 Subject: [PATCH 4/4] fixed tests --- .../lib/src/core/models/event.dart | 1 + .../lib/src/core/models/event.g.dart | 52 +++++++++++-------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/packages/stream_chat/lib/src/core/models/event.dart b/packages/stream_chat/lib/src/core/models/event.dart index b8ddafa7..3522c35c 100644 --- a/packages/stream_chat/lib/src/core/models/event.dart +++ b/packages/stream_chat/lib/src/core/models/event.dart @@ -93,6 +93,7 @@ class Event { final bool isLocal; /// This is true if the message has been hard deleted + @JsonKey(includeIfNull: false) final bool? hardDelete; /// Map of custom channel extraData diff --git a/packages/stream_chat/lib/src/core/models/event.g.dart b/packages/stream_chat/lib/src/core/models/event.g.dart index 3a521c9a..660e4542 100644 --- a/packages/stream_chat/lib/src/core/models/event.g.dart +++ b/packages/stream_chat/lib/src/core/models/event.g.dart @@ -42,27 +42,37 @@ Event _$EventFromJson(Map json) => Event( isLocal: json['is_local'] as bool? ?? false, ); -Map _$EventToJson(Event instance) => { - 'type': instance.type, - 'cid': instance.cid, - 'channel_id': instance.channelId, - 'channel_type': instance.channelType, - 'connection_id': instance.connectionId, - 'created_at': instance.createdAt.toIso8601String(), - 'me': instance.me?.toJson(), - 'user': instance.user?.toJson(), - 'message': instance.message?.toJson(), - 'channel': instance.channel?.toJson(), - 'member': instance.member?.toJson(), - 'reaction': instance.reaction?.toJson(), - 'total_unread_count': instance.totalUnreadCount, - 'unread_channels': instance.unreadChannels, - 'online': instance.online, - 'parent_id': instance.parentId, - 'is_local': instance.isLocal, - 'hard_delete': instance.hardDelete, - 'extra_data': instance.extraData, - }; +Map _$EventToJson(Event instance) { + final val = { + 'type': instance.type, + 'cid': instance.cid, + 'channel_id': instance.channelId, + 'channel_type': instance.channelType, + 'connection_id': instance.connectionId, + 'created_at': instance.createdAt.toIso8601String(), + 'me': instance.me?.toJson(), + 'user': instance.user?.toJson(), + 'message': instance.message?.toJson(), + 'channel': instance.channel?.toJson(), + 'member': instance.member?.toJson(), + 'reaction': instance.reaction?.toJson(), + 'total_unread_count': instance.totalUnreadCount, + 'unread_channels': instance.unreadChannels, + 'online': instance.online, + 'parent_id': instance.parentId, + 'is_local': instance.isLocal, + }; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('hard_delete', instance.hardDelete); + val['extra_data'] = instance.extraData; + return val; +} EventChannel _$EventChannelFromJson(Map json) => EventChannel( members: (json['members'] as List?)