diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index fe83a1966..191e1f51e 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,3 +1,11 @@ +## Upcoming + +✅ Added + +- Added support for `hideHistoryBefore` in `Channel.addMembers` and `Client.addChannelMembers` to + specify a timestamp before which channel history should be hidden for newly added members. When + provided, it takes precedence over the `hideHistory` boolean flag. + ## 9.21.0 🐞 Fixed diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index d7b85a395..dcbb5b84d 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1575,6 +1575,7 @@ class Channel { List memberIds, { Message? message, bool hideHistory = false, + DateTime? hideHistoryBefore, }) async { _checkInitialized(); return _client.addChannelMembers( @@ -1583,6 +1584,7 @@ class Channel { memberIds, message: message, hideHistory: hideHistory, + hideHistoryBefore: hideHistoryBefore, ); } diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index 9f8261bfa..293b7de10 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -1266,6 +1266,7 @@ class StreamChatClient { List memberIds, { Message? message, bool hideHistory = false, + DateTime? hideHistoryBefore, }) => _chatApi.channel.addMembers( channelId, @@ -1273,6 +1274,7 @@ class StreamChatClient { memberIds, message: message, hideHistory: hideHistory, + hideHistoryBefore: hideHistoryBefore, ); /// Remove members from the channel diff --git a/packages/stream_chat/lib/src/core/api/channel_api.dart b/packages/stream_chat/lib/src/core/api/channel_api.dart index f09c764b5..80bb1606f 100644 --- a/packages/stream_chat/lib/src/core/api/channel_api.dart +++ b/packages/stream_chat/lib/src/core/api/channel_api.dart @@ -209,13 +209,18 @@ class ChannelApi { List memberIds, { Message? message, bool hideHistory = false, + DateTime? hideHistoryBefore, }) async { final response = await _client.post( _getChannelUrl(channelId, channelType), data: { 'add_members': memberIds, - 'message': message, - 'hide_history': hideHistory, + if (message != null) 'message': message, + // [hideHistoryBefore] takes precedence over [hideHistory] + ...switch (hideHistoryBefore?.toUtc().toIso8601String()) { + final hideBefore? => {'hide_history_before': hideBefore}, + _ => {'hide_history': hideHistory}, + }, }, ); return AddMembersResponse.fromJson(response.data); diff --git a/packages/stream_chat/test/src/client/channel_test.dart b/packages/stream_chat/test/src/client/channel_test.dart index a22f1195d..55ae1c75a 100644 --- a/packages/stream_chat/test/src/client/channel_test.dart +++ b/packages/stream_chat/test/src/client/channel_test.dart @@ -2686,6 +2686,53 @@ void main() { message: any(named: 'message'))).called(1); }); + test('`.addMembers` with hideHistoryBefore', () async { + final members = List.generate( + 3, + (index) => Member(userId: 'test-member-id-$index'), + ); + final memberIds = members + .map((it) => it.userId) + .whereType() + .toList(growable: false); + final message = Message(id: 'test-message-id', text: 'Members Added'); + final hideHistoryBefore = DateTime.parse('2024-01-01T00:00:00Z'); + + final channelModel = ChannelModel(cid: channelCid); + + when(() => client.addChannelMembers( + channelId, + channelType, + memberIds, + message: message, + hideHistoryBefore: hideHistoryBefore, + )).thenAnswer( + (_) async => AddMembersResponse() + ..channel = channelModel + ..members = members + ..message = message, + ); + + final res = await channel.addMembers( + memberIds, + message: message, + hideHistoryBefore: hideHistoryBefore, + ); + + expect(res, isNotNull); + expect(res.channel.cid, channelModel.cid); + expect(res.members.length, members.length); + expect(res.message?.id, message.id); + + verify(() => client.addChannelMembers( + channelId, + channelType, + memberIds, + message: message, + hideHistoryBefore: hideHistoryBefore, + )).called(1); + }); + test('`.inviteMembers`', () async { final members = List.generate( 3, diff --git a/packages/stream_chat/test/src/client/client_test.dart b/packages/stream_chat/test/src/client/client_test.dart index 8ecf73823..4d750dde4 100644 --- a/packages/stream_chat/test/src/client/client_test.dart +++ b/packages/stream_chat/test/src/client/client_test.dart @@ -1915,6 +1915,50 @@ void main() { verifyNoMoreInteractions(api.channel); }); + test('`.addChannelMembers` with hideHistoryBefore', () async { + const channelType = 'test-channel-type'; + const channelId = 'test-channel-id'; + const channelCid = '$channelType:$channelId'; + + final members = List.generate( + 3, + (index) => Member(userId: 'test-user-id-$index'), + ); + + final memberIds = members.map((e) => e.userId!).toList(growable: false); + final hideHistoryBefore = DateTime.parse('2024-01-01T00:00:00Z'); + + when(() => api.channel.addMembers( + channelId, + channelType, + memberIds, + hideHistoryBefore: hideHistoryBefore, + )).thenAnswer((_) async => AddMembersResponse() + ..channel = ChannelModel(cid: channelCid) + ..members = members); + + final res = await client.addChannelMembers( + channelId, + channelType, + memberIds, + hideHistoryBefore: hideHistoryBefore, + ); + + expect(res, isNotNull); + expect(res.channel.cid, channelCid); + expect(res.members.length, memberIds.length); + + verify( + () => api.channel.addMembers( + channelId, + channelType, + memberIds, + hideHistoryBefore: hideHistoryBefore, + ), + ).called(1); + verifyNoMoreInteractions(api.channel); + }); + test('`.removeChannelMembers`', () async { const channelType = 'test-channel-type'; const channelId = 'test-channel-id'; diff --git a/packages/stream_chat/test/src/core/api/channel_api_test.dart b/packages/stream_chat/test/src/core/api/channel_api_test.dart index 2f05c98ab..7c12a3d3b 100644 --- a/packages/stream_chat/test/src/core/api/channel_api_test.dart +++ b/packages/stream_chat/test/src/core/api/channel_api_test.dart @@ -409,6 +409,85 @@ void main() { verifyNoMoreInteractions(client); }); + test('addMembers with hideHistoryBefore', () async { + const channelId = 'test-channel-id'; + const channelType = 'test-channel-type'; + const memberIds = ['test-member-id-1', 'test-member-id-2']; + final channelModel = ChannelModel(id: channelId, type: channelType); + final message = Message(id: 'test-message-id', text: 'members-added'); + final hideHistoryBefore = DateTime.parse('2024-01-01T00:00:00Z'); + + final path = _getChannelUrl(channelId, channelType); + + when(() => client.post( + path, + data: { + 'add_members': memberIds, + 'message': message, + 'hide_history_before': hideHistoryBefore.toUtc().toIso8601String(), + }, + )).thenAnswer((_) async => successResponse(path, data: { + 'channel': channelModel.toJson(), + 'message': message.toJson(), + })); + + final res = await channelApi.addMembers( + channelId, + channelType, + memberIds, + message: message, + hideHistoryBefore: hideHistoryBefore, + ); + + expect(res, isNotNull); + expect(res.channel.cid, channelModel.cid); + expect(res.message?.id, message.id); + + verify(() => client.post(path, data: any(named: 'data'))).called(1); + verifyNoMoreInteractions(client); + }); + + test('addMembers with hideHistoryBefore takes precedence over hideHistory', + () async { + const channelId = 'test-channel-id'; + const channelType = 'test-channel-type'; + const memberIds = ['test-member-id-1', 'test-member-id-2']; + final channelModel = ChannelModel(id: channelId, type: channelType); + final message = Message(id: 'test-message-id', text: 'members-added'); + const hideHistory = true; + final hideHistoryBefore = DateTime.parse('2024-01-01T00:00:00Z'); + + final path = _getChannelUrl(channelId, channelType); + + when(() => client.post( + path, + data: { + 'add_members': memberIds, + 'message': message, + 'hide_history_before': hideHistoryBefore.toUtc().toIso8601String(), + }, + )).thenAnswer((_) async => successResponse(path, data: { + 'channel': channelModel.toJson(), + 'message': message.toJson(), + })); + + final res = await channelApi.addMembers( + channelId, + channelType, + memberIds, + message: message, + hideHistory: hideHistory, + hideHistoryBefore: hideHistoryBefore, + ); + + expect(res, isNotNull); + expect(res.channel.cid, channelModel.cid); + expect(res.message?.id, message.id); + + verify(() => client.post(path, data: any(named: 'data'))).called(1); + verifyNoMoreInteractions(client); + }); + test('removeMembers', () async { const channelId = 'test-channel-id'; const channelType = 'test-channel-type';