[v4] Support predefined filters in ChannelListQuery#4120
Conversation
Backport of #4113 to the v4 release line. Reference a server-side predefined channel-list filter by name and let the server resolve its filter/sort templates instead of constructing the filter client-side. Adds ChannelListQuery(predefinedFilter:filterValues:sortValues:), decodes the predefined_filter response, caches the resolved filter/sort on ChannelListQueryDTO, and re-applies it locally. Adapted for v4: StreamCollection-based state layer, channelListQuery(_:) lookup, no StreamCore dependency. Includes the Sourcery codegen pipeline (make generate + CI validate_generated_code) and demo app query samples.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Generated by 🚫 Danger |
SDK Performance
|
martinmitrevski
left a comment
There was a problem hiding this comment.
lgtm, just have one question (see comments). Also, should we run a qa here as well?
Public Interface public struct ChannelListQuery: Encodable, LocalConvertibleSortingQuery
-
+ case predefinedFilter = "predefined_filter"
-
+ case filterValues = "filter_values"
- public let filter: Filter<ChannelListFilterScope>
+ case sortValues = "sort_values"
- public let sort: [Sorting<ChannelListSortingKey>]
+
- public var pagination: Pagination
+
- public let messagesLimit: Int?
+ public internal var filter: Filter<ChannelListFilterScope>
- public let membersLimit: Int?
+ public internal var sort: [Sorting<ChannelListSortingKey>]
- public var options: QueryOptions
+ public var pagination: Pagination
-
+ public let messagesLimit: Int?
-
+ public let membersLimit: Int?
- public init(filter: Filter<ChannelListFilterScope>,sort: [Sorting<ChannelListSortingKey>] = [],pageSize: Int = .channelsPageSize,messagesLimit: Int? = nil,membersLimit: Int? = nil)
+ public var options: QueryOptions
-
+ public let predefinedFilter: String?
-
+ public let filterValues: [String: RawJSON]?
- public func encode(to encoder: Encoder)throws
+ public let sortValues: [String: RawJSON]?
+
+
+ public init(filter: Filter<ChannelListFilterScope>,sort: [Sorting<ChannelListSortingKey>] = [],pageSize: Int = .channelsPageSize,messagesLimit: Int? = nil,membersLimit: Int? = nil)
+ public init(predefinedFilter: String,filterValues: [String: RawJSON]? = nil,sortValues: [String: RawJSON]? = nil,pageSize: Int = .channelsPageSize,messagesLimit: Int? = nil,membersLimit: Int? = nil)
+
+
+ public func encode(to encoder: Encoder)throws
@MainActor public final class ChannelListState: ObservableObject
- public let query: ChannelListQuery
+ public internal var query: ChannelListQuery
public class ChatChannelListController: DataController, DelegateCallable, DataStoreProvider
- public let query: ChannelListQuery
+ public internal var query: ChannelListQuery |
SDK Size
|
StreamChat XCSize
Show 39 more objects
|
StreamChatUI XCSize
|
|



🔗 Issue Links
https://linear.app/stream/issue/IOS-1706
🎯 Goal
Backport of #4113 to the v4 release line.
Let apps reference a server-side predefined channel-list filter by name and have the server resolve its filter/sort templates, instead of constructing the filter client-side.
📝 Summary
ChannelListQuery(predefinedFilter:filterValues:sortValues:)initializer.predefined_filterresponse are decoded and re-applied locally for Core Data caching.ChatChannelListController.queryandChannelListState.querybecomeinternal(set)so the SDK can swap to the resolved query after the first response.Filterdecoder now supports multi-key objects as implicit$andand the{ key: value }short form as implicit$eq, matching the Stream filter JSON shape.🛠 Implementation
ChannelListQuery+PredefinedFilter.swiftdecodes persisted filter/sort JSON and re-attaches Core Data wiring (keyPathString,valueMapper,predicateMapper) viaChannelListFilterScope.predefinedFilterKeyMapping. Unknown keys are logged and dropped.predefinedFilterKeyMapping/predefinedSortingKeyMappingregistries are generated by Sourcery from the channel-listFilterKey/ChannelListSortingKeydeclarations (Generated/PredefinedFilter+Generated.swift).make generateregenerates them and CI (validate_generated_code) fails if the committed output is stale.ChannelListPayloaddecodes the newpredefined_filterresponse key.ChannelListUpdaterpersists the resolved filter+sort ontoChannelListQueryDTOand returns an updatedChannelListQueryto the controller/state layer.loadPredefinedFilter(for:)rehydrates the locally cached resolved query so Core Data fetch predicates work before the first server response lands. Channels are linked and the fetch request matches onquery.queryHash.v4 adaptations
StreamCollection<ChatChannel>channels andlazy var state.channelListQuery(_ query:)/ChannelListQueryDTO.load(query:)keyed onqueryHash.StreamCoredependency (v4 predates it); the v5-only grouped-channels code is excluded.🧪 Manual Testing Notes
New pre-defined filters can be added through the dashboard.
☑️ Contributor Checklist
docs-contentrepo