From d82c533c30782f1039dff555e786a900ccf5d29a Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 31 Jan 2022 12:54:20 +0530 Subject: [PATCH] fix(llc): Update channel state when member gets banned/unbanned. Signed-off-by: xsahil03x --- .../stream_chat/lib/src/client/channel.dart | 52 +++++++++++++++++++ .../lib/src/core/models/member.dart | 7 +++ .../lib/src/core/models/member.g.dart | 4 ++ .../lib/src/core/models/own_user.dart | 4 ++ .../lib/src/core/models/own_user.g.dart | 3 ++ .../stream_chat/lib/src/core/models/user.dart | 16 ++++-- .../lib/src/core/models/user.g.dart | 6 ++- packages/stream_chat/lib/src/event_type.dart | 6 +++ 8 files changed, 94 insertions(+), 4 deletions(-) diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 7d026020..52409dda 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1515,6 +1515,10 @@ class ChannelClientState { _listenMemberRemoved(); + _listenMemberBanned(); + + _listenMemberUnbanned(); + _startCleaning(); _startCleaningPinnedMessages(); @@ -1615,6 +1619,54 @@ class ChannelClientState { })); } + void _listenMemberBanned() { + _subscriptions.add(_channel + .on(EventType.userBanned) + .where((it) => it.cid != null) // filters channel ban from app ban + .listen( + (event) async { + final user = event.user!; + final member = await _channel + .queryMembers(filter: Filter.equal('id', user.id)) + .then((it) => it.members.first); + + _updateMember(member); + }, + )); + } + + void _listenMemberUnbanned() { + _subscriptions.add(_channel + .on(EventType.userUnbanned) + .where((it) => it.cid != null) // filters channel ban from app ban + .listen( + (event) async { + final user = event.user!; + final member = await _channel + .queryMembers(filter: Filter.equal('id', user.id)) + .then((it) => it.members.first); + + _updateMember(member); + }, + )); + } + + void _updateMember(Member member) { + final currentMembers = [...members]; + final memberIndex = currentMembers.indexWhere( + (m) => m.userId == member.userId, + ); + + if (memberIndex == -1) return; + currentMembers[memberIndex] = member; + + updateChannelState( + channelState.copyWith( + members: currentMembers, + ), + ); + } + /// Flag which indicates if [ChannelClientState] contain latest/recent messages or not. /// /// This flag should be managed by UI sdks. diff --git a/packages/stream_chat/lib/src/core/models/member.dart b/packages/stream_chat/lib/src/core/models/member.dart index 0dae7c04..e8b0ecff 100644 --- a/packages/stream_chat/lib/src/core/models/member.dart +++ b/packages/stream_chat/lib/src/core/models/member.dart @@ -20,6 +20,7 @@ class Member extends Equatable { DateTime? createdAt, DateTime? updatedAt, this.banned = false, + this.banExpires, this.shadowBanned = false, }) : createdAt = createdAt ?? DateTime.now(), updatedAt = updatedAt ?? DateTime.now(); @@ -56,6 +57,9 @@ class Member extends Equatable { /// True if the member is banned from the channel final bool banned; + /// The date at which the ban will expire. + final DateTime? banExpires; + /// True if the member is shadow banned from the channel final bool shadowBanned; @@ -77,6 +81,7 @@ class Member extends Equatable { DateTime? createdAt, DateTime? updatedAt, bool? banned, + DateTime? banExpires, bool? shadowBanned, }) => Member( @@ -85,6 +90,7 @@ class Member extends Equatable { inviteRejectedAt: inviteRejectedAt ?? this.inviteRejectedAt, invited: invited ?? this.invited, banned: banned ?? this.banned, + banExpires: banExpires ?? this.banExpires, shadowBanned: shadowBanned ?? this.shadowBanned, role: role ?? this.role, userId: userId ?? this.userId, @@ -106,6 +112,7 @@ class Member extends Equatable { userId, isModerator, banned, + banExpires, shadowBanned, createdAt, updatedAt, diff --git a/packages/stream_chat/lib/src/core/models/member.g.dart b/packages/stream_chat/lib/src/core/models/member.g.dart index 0e711b1a..4da3cfd2 100644 --- a/packages/stream_chat/lib/src/core/models/member.g.dart +++ b/packages/stream_chat/lib/src/core/models/member.g.dart @@ -27,6 +27,9 @@ Member _$MemberFromJson(Map json) => Member( ? null : DateTime.parse(json['updated_at'] as String), banned: json['banned'] as bool? ?? false, + banExpires: json['ban_expires'] == null + ? null + : DateTime.parse(json['ban_expires'] as String), shadowBanned: json['shadow_banned'] as bool? ?? false, ); @@ -39,6 +42,7 @@ Map _$MemberToJson(Member instance) => { 'user_id': instance.userId, 'is_moderator': instance.isModerator, 'banned': instance.banned, + 'ban_expires': instance.banExpires?.toIso8601String(), 'shadow_banned': instance.shadowBanned, 'created_at': instance.createdAt.toIso8601String(), 'updated_at': instance.updatedAt.toIso8601String(), diff --git a/packages/stream_chat/lib/src/core/models/own_user.dart b/packages/stream_chat/lib/src/core/models/own_user.dart index 9077431b..5246f48e 100644 --- a/packages/stream_chat/lib/src/core/models/own_user.dart +++ b/packages/stream_chat/lib/src/core/models/own_user.dart @@ -26,6 +26,7 @@ class OwnUser extends User { bool online = false, Map extraData = const {}, bool banned = false, + DateTime? banExpires, List teams = const [], String? language, }) : super( @@ -39,6 +40,7 @@ class OwnUser extends User { online: online, extraData: extraData, banned: banned, + banExpires: banExpires, teams: teams, language: language, ); @@ -75,6 +77,7 @@ class OwnUser extends User { bool? online, Map? extraData, bool? banned, + DateTime? banExpires, List? teams, List? channelMutes, List? devices, @@ -91,6 +94,7 @@ class OwnUser extends User { // if null, it will be retrieved from extraData['image'] image: image, banned: banned ?? this.banned, + banExpires: banExpires ?? this.banExpires, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, lastActive: lastActive ?? this.lastActive, diff --git a/packages/stream_chat/lib/src/core/models/own_user.g.dart b/packages/stream_chat/lib/src/core/models/own_user.g.dart index 41b6e2f5..be8f2d45 100644 --- a/packages/stream_chat/lib/src/core/models/own_user.g.dart +++ b/packages/stream_chat/lib/src/core/models/own_user.g.dart @@ -35,6 +35,9 @@ OwnUser _$OwnUserFromJson(Map json) => OwnUser( online: json['online'] as bool? ?? false, extraData: json['extra_data'] as Map? ?? const {}, banned: json['banned'] as bool? ?? false, + banExpires: json['ban_expires'] == null + ? null + : DateTime.parse(json['ban_expires'] as String), teams: (json['teams'] as List?)?.map((e) => e as String).toList() ?? const [], diff --git a/packages/stream_chat/lib/src/core/models/user.dart b/packages/stream_chat/lib/src/core/models/user.dart index c6f62b6b..83b2a502 100644 --- a/packages/stream_chat/lib/src/core/models/user.dart +++ b/packages/stream_chat/lib/src/core/models/user.dart @@ -41,6 +41,7 @@ class User extends Equatable { Map extraData = const {}, this.online = false, this.banned = false, + this.banExpires, this.teams = const [], this.language, }) : createdAt = createdAt ?? DateTime.now(), @@ -67,6 +68,8 @@ class User extends Equatable { 'last_active', 'online', 'banned', + 'ban_expires', + 'dashboard_ban_channel_cid', 'teams', 'language', ]; @@ -129,14 +132,18 @@ class User extends Equatable { ) final bool banned; - /// Map of custom user extraData. - @JsonKey(includeIfNull: false) - final Map extraData; + /// The date at which the ban will expire. + @JsonKey(includeIfNull: false, toJson: Serializer.readOnly) + final DateTime? banExpires; /// The language this user prefers. @JsonKey(includeIfNull: false) final String? language; + /// Map of custom user extraData. + @JsonKey(includeIfNull: false) + final Map extraData; + /// List of users to list of userIds. static List? toIds(List? users) => users?.map((u) => u.id).toList(); @@ -158,6 +165,7 @@ class User extends Equatable { bool? online, Map? extraData, bool? banned, + DateTime? banExpires, List? teams, String? language, }) => @@ -174,6 +182,7 @@ class User extends Equatable { online: online ?? this.online, extraData: extraData ?? this.extraData, banned: banned ?? this.banned, + banExpires: banExpires ?? this.banExpires, teams: teams ?? this.teams, language: language ?? this.language, ); @@ -186,6 +195,7 @@ class User extends Equatable { online, extraData, banned, + banExpires, teams, language, ]; diff --git a/packages/stream_chat/lib/src/core/models/user.g.dart b/packages/stream_chat/lib/src/core/models/user.g.dart index 82c799a0..9e6ae3dc 100644 --- a/packages/stream_chat/lib/src/core/models/user.g.dart +++ b/packages/stream_chat/lib/src/core/models/user.g.dart @@ -21,6 +21,9 @@ User _$UserFromJson(Map json) => User( extraData: json['extra_data'] as Map? ?? const {}, online: json['online'] as bool? ?? false, banned: json['banned'] as bool? ?? false, + banExpires: json['ban_expires'] == null + ? null + : DateTime.parse(json['ban_expires'] as String), teams: (json['teams'] as List?)?.map((e) => e as String).toList() ?? const [], @@ -45,7 +48,8 @@ Map _$UserToJson(User instance) { writeNotNull('last_active', readonly(instance.lastActive)); writeNotNull('online', readonly(instance.online)); writeNotNull('banned', readonly(instance.banned)); - val['extra_data'] = instance.extraData; + writeNotNull('ban_expires', readonly(instance.banExpires)); writeNotNull('language', instance.language); + val['extra_data'] = instance.extraData; return val; } diff --git a/packages/stream_chat/lib/src/event_type.dart b/packages/stream_chat/lib/src/event_type.dart index 87529399..80628f2f 100644 --- a/packages/stream_chat/lib/src/event_type.dart +++ b/packages/stream_chat/lib/src/event_type.dart @@ -73,6 +73,12 @@ class EventType { /// Event sent when a member is removed to a channel static const String memberRemoved = 'member.removed'; + /// Event sent when a member is removed to a channel + static const String userBanned = 'user.banned'; + + /// Event sent when a member is removed to a channel + static const String userUnbanned = 'user.unbanned'; + /// Event sent when a channel is hidden static const String channelHidden = 'channel.hidden';