diff --git a/CHANGELOG.md b/CHANGELOG.md index a9082b9ade..68b2add74e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add `ChannelListSortingKey.pinnedAt` - Add `ChatChannel.membership.pinnedAt` - Add `ChatChannel.isPinned` +- Add member list filtering keys: `FilterKey.channelRole` and `FilterKey.email` [#3535](https://github.com/GetStream/stream-chat-swift/pull/3535) +- Add member list sorting key: `ChannelMemberListSortingKey.channelRole` [#3535](https://github.com/GetStream/stream-chat-swift/pull/3535) ### 🐞 Fixed - End background task before starting a new one [#3528](https://github.com/GetStream/stream-chat-swift/pull/3528) diff --git a/Sources/StreamChat/Models/Member.swift b/Sources/StreamChat/Models/Member.swift index d7126c4863..25d12c3cd1 100644 --- a/Sources/StreamChat/Models/Member.swift +++ b/Sources/StreamChat/Models/Member.swift @@ -159,6 +159,18 @@ public extension MemberRole { self = MemberRole(rawValue: value) } } + + func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .member: + try container.encode("channel_member") + case .moderator: + try container.encode("channel_moderator") + default: + try container.encode(rawValue) + } + } } /// The member information when adding a member to a channel. diff --git a/Sources/StreamChat/Query/ChannelMemberListQuery.swift b/Sources/StreamChat/Query/ChannelMemberListQuery.swift index 72f1c773ee..293909ec79 100644 --- a/Sources/StreamChat/Query/ChannelMemberListQuery.swift +++ b/Sources/StreamChat/Query/ChannelMemberListQuery.swift @@ -24,6 +24,14 @@ public extension FilterKey where Scope: AnyMemberListFilterScope { /// Filter key matching the name of the user /// Supported operators: `equal`, `notEqual`, `in`, `notIn`, `autocomplete`, `query` static var name: FilterKey { "name" } + + /// Filter key matching the email of the user + /// Supported operators: `equal`, `in`, `autocomplete` + static var email: FilterKey { "user.email" } + + /// Filter key matching the channel role of the user + /// Supported operators: `equal` + static var channelRole: FilterKey { "channel_role" } /// Filter key matching the banned status /// Supported operators: `equal` diff --git a/Sources/StreamChat/Query/Filter.swift b/Sources/StreamChat/Query/Filter.swift index 869bda0dd1..4c0d6076b0 100644 --- a/Sources/StreamChat/Query/Filter.swift +++ b/Sources/StreamChat/Query/Filter.swift @@ -80,6 +80,7 @@ extension Filter: FilterValue {} extension ChannelId: FilterValue {} extension ChannelType: FilterValue {} +extension MemberRole: FilterValue {} extension UserRole: FilterValue {} extension AttachmentType: FilterValue {} extension Optional: FilterValue where Wrapped == TeamId {} diff --git a/Sources/StreamChat/Query/Sorting/ChannelMemberListSortingKey.swift b/Sources/StreamChat/Query/Sorting/ChannelMemberListSortingKey.swift index 51dccd9a55..aa3bb07c58 100644 --- a/Sources/StreamChat/Query/Sorting/ChannelMemberListSortingKey.swift +++ b/Sources/StreamChat/Query/Sorting/ChannelMemberListSortingKey.swift @@ -16,13 +16,16 @@ public enum ChannelMemberListSortingKey: String, SortingKey { /// /// - Warning: This option is heavy for the backend and can slow down API requests' response time. If there's no explicit requirement for this sorting option consider using a different one. case name = "user.name" + + /// Sort channel members by their channel role. + case channelRole = "channelRoleRaw" public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() let value: String switch self { - /// Sort channel members by date they were created. + case .channelRole: value = "channel_role" case .createdAt: value = "created_at" case .name: value = "name" case .userId: value = "user_id" diff --git a/Tests/StreamChatTests/Query/MemberListFilterScope_Tests.swift b/Tests/StreamChatTests/Query/MemberListFilterScope_Tests.swift index 2e3d887956..88b559e6eb 100644 --- a/Tests/StreamChatTests/Query/MemberListFilterScope_Tests.swift +++ b/Tests/StreamChatTests/Query/MemberListFilterScope_Tests.swift @@ -12,6 +12,8 @@ final class MemberListFilterScope_Tests: XCTestCase { func test_filterKeys_matchChannelCodingKeys() { // Member specific coding keys XCTAssertEqual(Key.isModerator.rawValue, "is_moderator") + XCTAssertEqual(Key.email.rawValue, "user.email") + XCTAssertEqual(Key.channelRole.rawValue, "channel_role") // User-related coding keys XCTAssertEqual(Key.id.rawValue, UserPayloadsCodingKeys.id.rawValue) diff --git a/Tests/StreamChatTests/Query/Sorting/ChannelMemberListSortingKey_Tests.swift b/Tests/StreamChatTests/Query/Sorting/ChannelMemberListSortingKey_Tests.swift index d075123dca..9f8b4ebf6a 100644 --- a/Tests/StreamChatTests/Query/Sorting/ChannelMemberListSortingKey_Tests.swift +++ b/Tests/StreamChatTests/Query/Sorting/ChannelMemberListSortingKey_Tests.swift @@ -11,7 +11,7 @@ final class ChannelMemberListSortingKey_Tests: XCTestCase { func test_sortDescriptor_keyPaths_areValid() throws { // Put all `ChannelMemberListSortingKey`s in an array // We don't use `CaseIterable` since we only need this for tests - let sortingKeys: [ChannelMemberListSortingKey] = [.createdAt, .name, .userId] + let sortingKeys: [ChannelMemberListSortingKey] = [.createdAt, .name, .channelRole, .userId] // Iterate over keys... for key in sortingKeys { @@ -24,6 +24,8 @@ final class ChannelMemberListSortingKey_Tests: XCTestCase { ChannelMemberListSortingKey.name.rawValue, NSExpression(forKeyPath: \MemberDTO.user.name).keyPath ) + case .channelRole: + XCTAssertEqual(key.rawValue, KeyPath.string(\MemberDTO.channelRoleRaw)) case .userId: XCTAssertEqual(key.rawValue, NSExpression(forKeyPath: \MemberDTO.user.id).keyPath) }