Skip to content

Commit 117038d

Browse files
authored
Add channelRole filter key for ChannelListQuery (#3802)
1 parent 18a38bb commit 117038d

File tree

5 files changed

+48
-4
lines changed

5 files changed

+48
-4
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
33

44
# Upcoming
55

6-
### 🔄 Changed
6+
## StreamChat
7+
### ✅ Added
8+
- Add `FilterKey.channelRole` for `ChannelListQuery` [3802](https://github.com/GetStream/stream-chat-swift/pull/3802)
79

810
# [4.87.0](https://github.com/GetStream/stream-chat-swift/releases/tag/4.87.0)
911
_August 29, 2025_

DemoApp/StreamChat/Components/DemoChatChannelListVC.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ final class DemoChatChannelListVC: ChatChannelListVC {
5858
])
5959
])
6060
)
61+
62+
lazy var channelModeratorChannelsQuery: ChannelListQuery = .init(
63+
filter: .and([
64+
.containMembers(userIds: [currentUserId]),
65+
.equal(.channelRole, to: "channel_moderator")
66+
])
67+
)
6168

6269
lazy var unreadCountChannelsQuery: ChannelListQuery = .init(
6370
filter: .and([
@@ -180,6 +187,15 @@ final class DemoChatChannelListVC: ChatChannelListVC {
180187
self?.setBlockedUnblockedWithHiddenChannelsQuery()
181188
}
182189
)
190+
191+
let channelRoleChannelsAction = UIAlertAction(
192+
title: "Moderator Channels",
193+
style: .default,
194+
handler: { [weak self] _ in
195+
self?.title = "Moderator Channels"
196+
self?.setChannelModeratorChannelsQuery()
197+
}
198+
)
183199

184200
let unreadCountChannelsAction = UIAlertAction(
185201
title: "Unread Count Channels",
@@ -254,7 +270,8 @@ final class DemoChatChannelListVC: ChatChannelListVC {
254270
coolChannelsAction,
255271
pinnedChannelsAction,
256272
archivedChannelsAction,
257-
equalMembersAction
273+
equalMembersAction,
274+
channelRoleChannelsAction
258275
].sorted(by: { $0.title ?? "" < $1.title ?? "" }),
259276
preferredStyle: .actionSheet,
260277
sourceView: filterChannelsButton
@@ -272,6 +289,10 @@ final class DemoChatChannelListVC: ChatChannelListVC {
272289
func setBlockedUnblockedWithHiddenChannelsQuery() {
273290
replaceQuery(blockedUnblockedWithHiddenChannelsQuery)
274291
}
292+
293+
func setChannelModeratorChannelsQuery() {
294+
replaceQuery(channelModeratorChannelsQuery)
295+
}
275296

276297
func setUnreadCountChannelsQuery() {
277298
replaceQuery(unreadCountChannelsQuery)

Sources/StreamChat/Database/DTOs/MemberModelDTO.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ extension NSManagedObjectContext {
122122

123123
// Save member specific data
124124
if let role = payload.role {
125-
dto.channelRoleRaw = role.rawValue
125+
dto.channelRoleRaw = role.rawChannelValue
126126
}
127127

128128
dto.memberCreatedAt = payload.createdAt.bridgeDate
@@ -213,7 +213,7 @@ extension ChatChannelMember {
213213
memberExtraData = [:]
214214
}
215215

216-
let role = dto.channelRoleRaw.flatMap { MemberRole(rawValue: $0) } ?? .member
216+
let role = dto.channelRoleRaw.flatMap { MemberRole(rawChannelValue: $0) } ?? .member
217217
let language: TranslationLanguage? = dto.user.language.map(TranslationLanguage.init)
218218

219219
var member = ChatChannelMember(

Sources/StreamChat/Models/Member.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,26 @@ public struct MemberRole: RawRepresentable, Codable, Hashable, ExpressibleByStri
172172

173173
public init(rawValue: String) {
174174
self.rawValue = rawValue
175+
rawChannelValue = rawValue
175176
}
176177

177178
public init(stringLiteral value: String) {
178179
self.init(rawValue: value)
179180
}
181+
182+
init(rawChannelValue: String) {
183+
// Historically these have been mapped when decoding JSON
184+
switch rawChannelValue {
185+
case "channel_member":
186+
self.init(rawValue: Self.member.rawValue)
187+
case "channel_moderator":
188+
self.init(rawValue: Self.moderator.rawValue)
189+
default:
190+
self.init(rawValue: rawChannelValue)
191+
}
192+
}
193+
194+
var rawChannelValue: String
180195
}
181196

182197
public extension MemberRole {
@@ -207,6 +222,8 @@ public extension MemberRole {
207222
default:
208223
self = MemberRole(rawValue: value)
209224
}
225+
// Store the original raw value from the backend for local filtering
226+
rawChannelValue = value
210227
}
211228

212229
func encode(to encoder: any Encoder) throws {

Sources/StreamChat/Query/ChannelListQuery.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ public extension FilterKey where Scope == ChannelListFilterScope {
287287
/// Filter for the time of the last message in the channel. If the channel has no messages, then the time the channel was created.
288288
/// Supported operators: `equal`, `greaterThan`, `lessThan`, `greaterOrEqual`, `lessOrEqual`
289289
static var lastUpdatedAt: FilterKey<Scope, Date> { .init(rawValue: "last_updated", keyPathString: #keyPath(ChannelDTO.defaultSortingAt)) }
290+
291+
/// Filter for checking if the current user has a specific channel role set.
292+
/// Supported operatios: `equal`, `in`
293+
static var channelRole: FilterKey<Scope, String> { .init(rawValue: "channel_role", keyPathString: #keyPath(ChannelDTO.membership.channelRoleRaw)) }
290294
}
291295

292296
/// Internal filter queries for the channel list.

0 commit comments

Comments
 (0)