-
Notifications
You must be signed in to change notification settings - Fork 229
Add support for filter tags in channels #3886
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds a new channel-level Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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 |
| warning: 25 | ||
| error: 30 | ||
| warning: 30 | ||
| error: 35 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was getting a warning about the ChatChannel equality implementation and there is no good solution so I bumped these values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift (1)
439-463: Fix type mismatch in filterTags assertion on ChatChannel
ChatChannel.filterTagsis aSet<String>, but the test asserts equality against an array literal:XCTAssertEqual(chatChannel.filterTags, ["football"])This will not compile due to mismatched types (
Set<String>vs[String]). The assertion should compareSet<String>toSet<String>.Apply this diff:
- XCTAssertEqual(chatChannel.filterTags, ["football"]) + XCTAssertEqual(chatChannel.filterTags, Set(["football"]))This keeps the intent while aligning with the
Set<String>-based public API.Also applies to: 490-502
🧹 Nitpick comments (5)
.swiftlint.yml (1)
68-71: Consider scoping the cyclomatic_complexity relaxationBumping the global
cyclomatic_complexitythresholds to 30/35 reduces signal from this rule across the codebase. If the primary offender is the ChatChannel equality implementation, consider either:
- refactoring that specific implementation, or
- locally disabling the rule just for that symbol
instead of relaxing it project‑wide, to keep linting pressure high elsewhere.
As per coding guidelines, exceptions are better scoped than broad.
Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swift (1)
45-45: filterTags coding key is correct; consider adding a brief doc comment
case filterTags = "filter_tags"matches the JSON field and is correctly integrated withChannelCodingKeys. For consistency with nearby cases, you might add a short comment like/// Tags used for filtering the channel.above it.Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift (1)
1559-1584: LivestreamChannelController now validates channel.filterTags propagationThe comprehensive ChannelUpdatedEvent test now also covering
filterTags(set to["football"]) is a good addition; it ensures the new property is updated in memory when channels change.If you later need more confidence, you could extend this to multiple tags to implicitly validate set semantics, but not required for this PR.
Also applies to: 1599-1610
TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatChannel_Mock.swift (1)
76-92: ChatChannel.mock now exposes filterTags; consider extending DM/non‑DM helpers laterAdding a
filterTags: Set<String> = []parameter and forwarding it intoself.initkeeps the mock aligned with the new Channel model surface while preserving existing call sites via the default.If tests ever need tagged DM/non‑DM channels, you could mirror this parameter into
mockDMChannel/mockNonDMChanneland forward it to the underlying initializer, but it’s fine to defer until needed.Also applies to: 115-128
Sources/StreamChat/Models/Channel.swift (1)
44-46: ChatChannel.filterTags integration looks correct end‑to‑end
- New public
filterTags: Set<String>with a concise doc comment fits the model and exposes channel tags cleanly.- The main initializer,
replacing(...), andchanging(...)all passfilterTagsthrough, so tags are preserved across derived instances.- Equality now includes
filterTags, ensuring channel updates are observed when tags change, while the hash implementation (based oncid) still satisfies Hashable constraints.Only note: if you ever need to mutate tags via
changing(...), adding an optionalfilterTagsparameter there would make that explicit, but it's not required for the current feature set.Also applies to: 186-199, 235-236, 270-307, 338-375, 440-467
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (27)
.swiftlint.yml(1 hunks)CHANGELOG.md(1 hunks)Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swift(1 hunks)Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swift(6 hunks)Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelListPayload.swift(2 hunks)Sources/StreamChat/Controllers/ChannelController/ChannelController.swift(6 hunks)Sources/StreamChat/Controllers/ChannelController/ChatClient+ChannelController.swift(6 hunks)Sources/StreamChat/Database/DTOs/ChannelDTO.swift(3 hunks)Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents(2 hunks)Sources/StreamChat/Models/Channel.swift(6 hunks)Sources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swift(2 hunks)Sources/StreamChat/Query/ChannelListQuery.swift(1 hunks)Sources/StreamChat/StateLayer/Chat.swift(6 hunks)Sources/StreamChat/StateLayer/ChatClient+Factory.swift(6 hunks)TestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swift(1 hunks)TestTools/StreamChatTestTools/Fixtures/JSONs/Channel.json(1 hunks)TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatChannel_Mock.swift(2 hunks)TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift(2 hunks)TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift(3 hunks)Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift(5 hunks)Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift(6 hunks)Tests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swift(1 hunks)Tests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swift(3 hunks)Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift(2 hunks)Tests/StreamChatTests/Query/ChannelListFilterScope_Tests.swift(2 hunks)Tests/StreamChatTests/Query/ChannelQuery_Tests.swift(3 hunks)Tests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swift(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
**/*.swift: Write Swift code compatible with iOS deployment targets specified in Package.swift and podspec files; do not lower deployment targets without approval
Use SwiftLint with strict mode and respect .swiftlint.yml rules; justify and scope any exceptions rather than suppressing rules broadly
Run SwiftFormat for code formatting and respect repository-specific style conventions
Never commit API keys or customer data; use obvious placeholders (e.g., YOUR_STREAM_KEY) in example code
Follow the project's zero-warnings policy: fix new warnings and avoid introducing any
Files:
TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatChannel_Mock.swiftTestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swiftSources/StreamChat/Models/Channel.swiftTests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swiftSources/StreamChat/Database/DTOs/ChannelDTO.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swiftSources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swiftSources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swiftTests/StreamChatTests/Query/ChannelListFilterScope_Tests.swiftTests/StreamChatTests/Query/ChannelQuery_Tests.swiftSources/StreamChat/StateLayer/ChatClient+Factory.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelListPayload.swiftTests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swiftTestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftTestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swiftTests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swiftSources/StreamChat/Query/ChannelListQuery.swiftSources/StreamChat/Controllers/ChannelController/ChatClient+ChannelController.swift
Tests/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Add or extend tests in the matching module's Tests/ folder for changes to StreamChat or StreamChatUI code, covering core models, API surfaces, and view controller behaviors; use fakes/mocks from test helpers provided by the repo
Files:
Tests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swiftTests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swiftTests/StreamChatTests/Query/ChannelListFilterScope_Tests.swiftTests/StreamChatTests/Query/ChannelQuery_Tests.swiftTests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swiftTests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift
Sources/StreamChat/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes
Files:
Sources/StreamChat/Models/Channel.swiftSources/StreamChat/Database/DTOs/ChannelDTO.swiftSources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swiftSources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swiftSources/StreamChat/StateLayer/ChatClient+Factory.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelListPayload.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftSources/StreamChat/Query/ChannelListQuery.swiftSources/StreamChat/Controllers/ChannelController/ChatClient+ChannelController.swift
CHANGELOG*
📄 CodeRabbit inference engine (AGENTS.md)
Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
Files:
CHANGELOG.md
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Tests/**/*.swift : Add or extend tests in the matching module's Tests/ folder for changes to StreamChat or StreamChatUI code, covering core models, API surfaces, and view controller behaviors; use fakes/mocks from test helpers provided by the repo
Applied to files:
TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatChannel_Mock.swiftTestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swiftTests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swiftTests/StreamChatTests/Query/ChannelListFilterScope_Tests.swiftTests/StreamChatTests/Query/ChannelQuery_Tests.swiftTests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swiftTestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swiftTests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Sources/StreamChatUI/**/*.swift : Ensure public API changes in StreamChatUI include inline documentation and migration notes
Applied to files:
TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatChannel_Mock.swiftSources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contentsTestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swiftSources/StreamChat/Models/Channel.swiftTests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swiftSources/StreamChat/Database/DTOs/ChannelDTO.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swiftSources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swiftSources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swiftTests/StreamChatTests/Query/ChannelListFilterScope_Tests.swiftTests/StreamChatTests/Query/ChannelQuery_Tests.swiftSources/StreamChat/StateLayer/ChatClient+Factory.swiftTests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swiftTestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftTestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swiftTests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swiftSources/StreamChat/Controllers/ChannelController/ChatClient+ChannelController.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Sources/StreamChat/**/*.swift : Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes
Applied to files:
TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatChannel_Mock.swiftSources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contentsTestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swiftSources/StreamChat/Models/Channel.swiftTests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swiftSources/StreamChat/Database/DTOs/ChannelDTO.swiftTests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swiftSources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swiftSources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swiftCHANGELOG.mdSources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swiftTests/StreamChatTests/Query/ChannelListFilterScope_Tests.swiftTests/StreamChatTests/Query/ChannelQuery_Tests.swiftSources/StreamChat/StateLayer/ChatClient+Factory.swiftTests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swiftTestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftTestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swiftTests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swiftSources/StreamChat/Controllers/ChannelController/ChatClient+ChannelController.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Maintain high test coverage when changing code in the Stream iOS Chat SDK
Applied to files:
TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatChannel_Mock.swiftTests/StreamChatTests/Query/ChannelListFilterScope_Tests.swiftTests/StreamChatTests/Query/ChannelQuery_Tests.swiftTests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to **/*.swift : Use SwiftLint with strict mode and respect .swiftlint.yml rules; justify and scope any exceptions rather than suppressing rules broadly
Applied to files:
.swiftlint.yml
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Prefer additive changes and avoid breaking public APIs in StreamChat and StreamChatUI
Applied to files:
.swiftlint.ymlSources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contentsSources/StreamChat/StateLayer/Chat.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
Applied to files:
Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contentsSources/StreamChat/StateLayer/Chat.swiftCHANGELOG.mdSources/StreamChat/StateLayer/ChatClient+Factory.swiftTestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftTests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swiftSources/StreamChat/Controllers/ChannelController/ChatClient+ChannelController.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Prioritize backwards compatibility and API stability when changing code in the Stream iOS Chat SDK
Applied to files:
Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contentsCHANGELOG.md
🧬 Code graph analysis (1)
Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swift (5)
Sources/StreamChat/Query/ChannelListQuery.swift (1)
encode(55-67)Sources/StreamChat/APIClient/Endpoints/Payloads/MessagePayloads.swift (1)
encode(358-384)Sources/StreamChat/APIClient/Endpoints/Payloads/UserPayloads.swift (2)
encode(140-146)encode(200-208)Sources/StreamChat/Query/Filter.swift (1)
encode(508-530)Sources/StreamChat/APIClient/Endpoints/Payloads/MessageAttachmentPayload.swift (1)
encode(23-27)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Test E2E UI (Debug) (1)
- GitHub Check: Test E2E UI (Debug) (0)
- GitHub Check: Build Demo App + Example Apps
- GitHub Check: Test UI (Debug)
🔇 Additional comments (29)
CHANGELOG.md (1)
12-17: ✅ CHANGELOG entry properly documents filterTags feature.The entry accurately captures all user-visible API additions from the PR objectives in the correct section with consistent formatting. All five key changes (model property, filtering key, factory methods, and update methods) are documented at the appropriate level of abstraction for a changelog.
TestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swift (1)
17-17: Unique ChannelEditDetailPayload now initializes filterTags correctlyWiring
filterTags: []into the unique helper keeps it compiling and defaults tags to empty, which matches the new API surface.Tests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swift (1)
301-325: ChannelDetailPayload test helper updated correctly for filterTagsPassing
filterTags: nilintoChannelDetailPayloadkeeps the helper compiling and doesn’t affect the identifiable‑payload/recursion assertions in this test.Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelListPayload.swift (1)
126-134: ChannelDetailPayload gains filterTags decoding in a consistent wayAdding
filterTags: [String]?toChannelDetailPayloadand decoding it viaChannelCodingKeys.filterTagscleanly exposes the new field from channel list payloads while keeping it optional and separate fromextraData. This matches how other list‑level properties are handled.Also applies to: 165-207
Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents (1)
2-2: Core Data model extended with ChannelDTO.filterTags; metadata bump is fineThe new optional Transformable
ChannelDTO.filterTagsattribute wired throughNSSecureUnarchiveFromDataTransformerfits the existing pattern for persisted collections and should be handled by lightweight migration. The updatedlastSavedToolsVersion/systemVersionin the model header is the usual Xcode metadata bump and is acceptable as part of this schema change.Also applies to: 42-51
Sources/StreamChat/Query/ChannelListQuery.swift (1)
295-297: NewfilterTagsfilter key wiring looks consistentUsing raw value
"filter_tags"and#keyPath(ChannelDTO.filterTags)matches the payload/DTO changes and other filter keys; no adjustments needed here.TestTools/StreamChatTestTools/Fixtures/JSONs/Channel.json (1)
1349-1351: Channel fixturefilter_tagsaddition looks correctThe new
"filter_tags": ["football"]field is placed at the correct level under"channel"and keeps the JSON syntactically valid; it matches the server field name used by the rest of the changes.Sources/StreamChat/Database/DTOs/ChannelDTO.swift (1)
19-20: DTO ↔ payload ↔ model wiring forfilterTagsis coherentPersisting
payload.filterTagsintoChannelDTO.filterTagsand then exposing it asSet(dto.filterTags)onChatChannelmirrors the existingownCapabilitiespattern and keeps network, DB, and model layers in sync. The conditional assignment also sensibly treatsnilas “no change”.Also applies to: 259-262, 652-653
Tests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swift (1)
1007-1031:ChannelDetailPayloadinitialization updated forfilterTagswithout changing behaviorIncluding
filterTags: nilin this test initializer correctly adapts to the new payload signature while preserving the original semantics around unread counts.Sources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swift (1)
15-16:ChannelPayload.asModelnow correctly setsChatChannel.filterTagsUsing
Set(channelPayload.filterTags ?? [])cleanly bridges the optional[String]?payload field into the non‑optionalSet<String>onChatChannel, matching the DTO‑based construction path.Also applies to: 44-45
Tests/StreamChatTests/Query/ChannelQuery_Tests.swift (1)
43-52:ChannelQueryapiPath tests updated forfilterTagswithout changing semanticsPassing
filterTags: []into theChannelPayloadinitializers keeps the tests compiling against the new API while verifying thatapiPathis still driven solely by type/id.Also applies to: 66-75, 80-89
Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift (1)
49-58:ChannelEditDetailPayloadapiPath tests correctly includefilterTagsAdding
filterTags: []to bothChannelEditDetailPayloadinitializers keeps the tests in sync with the new signature, and expectations aroundapiPathremain valid.Also applies to: 65-74
Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift (3)
148-152: Dummy channel list: filterTags population is appropriatePopulating
ChannelDetailPayloadincreateHugeChannelListwithfilterTags: ["football"]ensures the new field is exercised in performance / DB tests without changing behavior elsewhere. No issues here.
355-355: Decoding assertion for payload.channel.filterTags looks correctAsserting
XCTAssertEqual(payload.channel.filterTags, ["football"])matches the expected[String]?type onChannelDetailPayload.filterTagsand validates JSON fixture wiring. This is a good coverage point.
538-562: Minimal asModel test for filterTags is wired correctlyUsing
filterTags: nilinChannelDetailPayloadand then assertingXCTAssertTrue(chatChannel.filterTags.isEmpty)correctly verifies that missing tags map to an emptySetonChatChannel. This is a solid edge-case check.Also applies to: 586-598
Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swift (1)
15-36: ChannelEditDetailPayload: filterTags threading and encoding are consistent
- Adding
filterTags: Set<String>to the payload and both initializers keeps the type explicit and non-optional.- Encoding
filter_tagsonly whenfilterTagsis non-empty matches existing patterns (e.g. members, attachments) and avoids sending redundant empty arrays.This keeps create/update semantics consistent with other channel fields; clearing tags can still be handled via partial update APIs if needed.
Also applies to: 39-58, 71-74
Tests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swift (3)
4715-4723: watchActiveChannel test: updated payload construction is soundPassing
filterTags: []intoChannelEditDetailPayloadhere is the right way to satisfy the new non-optional field without changing test behavior (no tags for this synthetic payload).
5832-5841: DM controller setup: filterTags default correctly wired
setupControllerForNewDirectMessageChannelnow initializesChannelEditDetailPayloadwithfilterTags: [], which aligns with the new initializer and keeps default behavior of “no tags” for new DM channels.
5872-5881: New message channel setup: filterTags default correctly wiredSimilarly,
setupControllerForNewMessageChannelusesfilterTags: [], ensuring the helper continues to work with the updated payload shape without altering semantics.TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift (1)
23-23: LGTM! Test helper properly extended to support filterTags.The addition of the optional
filterTagsparameter with anildefault is appropriate for test helpers and maintains backward compatibility with existing tests.Also applies to: 48-48
Sources/StreamChat/StateLayer/Chat.swift (2)
1359-1384: LGTM! Channel update API properly extended with filterTags support.The
update(...)method correctly adds thefilterTagsparameter with an empty set default and threads it through to theChannelEditDetailPayload. The documentation is clear and the change is non-breaking.
1397-1425: LGTM! Partial update API properly extended with filterTags support.The
updatePartial(...)method correctly adds thefilterTagsparameter with an empty set default and threads it through to theChannelEditDetailPayload. The documentation is clear and consistent with the full update method.TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift (1)
157-157: LGTM! Test helpers properly updated to support filterTags.The dummy data builders correctly add the
filterTagsparameter and propagate it through to the Channel initialization. The explicitfilterTags: nilindummyPayloadWithNoExtraDatais good for clarity.Also applies to: 194-194, 315-315
Sources/StreamChat/Controllers/ChannelController/ChannelController.swift (2)
256-293: LGTM! Channel update method properly extended with filterTags.The
updateChannel(...)method correctly adds thefilterTagsparameter with appropriate defaults and documentation. The implementation properly constructs theChannelEditDetailPayloadwith the filterTags included.
301-340: LGTM! Partial channel update method properly extended with filterTags.The
partialChannelUpdate(...)method correctly adds thefilterTagsparameter with appropriate defaults and documentation. The implementation is consistent with the full update method.Sources/StreamChat/Controllers/ChannelController/ChatClient+ChannelController.swift (2)
68-108: LGTM! Channel creation factory properly extended with filterTags.The
channelController(createChannelWithId:...)factory method correctly adds thefilterTagsparameter and threads it through to theChannelEditDetailPayload. The documentation clearly describes the new parameter.
125-165: LGTM! Direct message channel factory properly extended with filterTags.The
channelController(createDirectMessageChannelWith:...)factory method correctly adds thefilterTagsparameter and threads it through to theChannelEditDetailPayload. Implementation is consistent with the regular channel creation method.Sources/StreamChat/StateLayer/ChatClient+Factory.swift (2)
124-163: LGTM! Chat factory with cid properly extended with filterTags.The
makeChat(with cid:...)factory method correctly adds thefilterTagsparameter and threads it through to theChannelEditDetailPayload. The documentation clearly describes the new parameter and the implementation is consistent with the controller layer.
181-220: LGTM! Direct message Chat factory properly extended with filterTags.The
makeDirectMessageChat(...)factory method correctly adds thefilterTagsparameter and threads it through to theChannelEditDetailPayload. The implementation is consistent with the regular channel creation method and properly handles the direct message use case.
Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift
Outdated
Show resolved
Hide resolved
SDK Performance
|
nuno-vieira
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall is looking good, but we are missing some critical test coverage 👍
| /// A filter key for matching channel filter tags. | ||
| /// Supported operators: `in`, `equal` | ||
| static var filterTags: FilterKey<Scope, String> { .init(rawValue: "filter_tags", keyPathString: #keyPath(ChannelDTO.filterTags)) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are missing test coverage to test if the automatic predicate is working as intended
8a6e484 to
92aac42
Compare
92aac42 to
33906aa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
Tests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift (1)
1947-1962: New filterTags predicate test correctly exercises automatic Core Data filtering
test_filterPredicate_filterTags_returnsExpectedResultsis well-structured: it uses.in(.filterTags, values: ["premium"])plusassertFilterPredicateto verify that channels whosefilterTagscontain"premium"are returned, covering the automatic predicate behavior for the new collection key. If you want slightly broader coverage, you could add a companion test using.equal(.filterTags, to: "premium")to confirmequalbehaves as expected too.DemoApp/StreamChat/Components/DemoChatChannelListVC.swift (1)
107-112: Premium-tagged channels query works; consider aligning membership filtering with other queriesThe new
premiumTaggedChannelsQueryand its action/wrapper method are wired correctly and integrate cleanly with the existing filter menu. One behavioral difference is that this query filters only byfilterTagsand does not also constrain to channels containingcurrentUserId, whereas most other queries here do. If you want consistency and to avoid listing channels the user isn’t a member of, consider:lazy var premiumTaggedChannelsQuery: ChannelListQuery = .init( filter: .and([ .containMembers(userIds: [currentUserId]), .in(.filterTags, values: ["premium"]) ]) )Also applies to: 262-269, 285-286, 343-345
Tests/StreamChatTests/StateLayer/Chat_Tests.swift (1)
1311-1401: Channel update/updatePartial tests validate payload mapping; consider also asserting filterTagsThese new tests correctly verify that
Chat.updateandChat.updatePartialpassname,imageURL,team,members,invites,extraData, andunsetPropertiesthrough toChannelEditDetailPayload, and that success/failure fromChannelUpdater_Mockis surfaced as expected. IfChat.update/updatePartialnow also exposefilterTags, it would be worth extending these tests to set non-emptyfilterTagsand assert they reach the mock payload as well, so changes to that wiring are caught at the state-layer.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
CHANGELOG.md(1 hunks)DemoApp/StreamChat/Components/DemoChatChannelListVC.swift(4 hunks)Sources/StreamChat/Query/ChannelListQuery.swift(1 hunks)TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift(3 hunks)Tests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift(1 hunks)Tests/StreamChatTests/StateLayer/Chat_Tests.swift(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- CHANGELOG.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
**/*.swift: Write Swift code compatible with iOS deployment targets specified in Package.swift and podspec files; do not lower deployment targets without approval
Use SwiftLint with strict mode and respect .swiftlint.yml rules; justify and scope any exceptions rather than suppressing rules broadly
Run SwiftFormat for code formatting and respect repository-specific style conventions
Never commit API keys or customer data; use obvious placeholders (e.g., YOUR_STREAM_KEY) in example code
Follow the project's zero-warnings policy: fix new warnings and avoid introducing any
Files:
Sources/StreamChat/Query/ChannelListQuery.swiftTests/StreamChatTests/StateLayer/Chat_Tests.swiftTests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swiftTestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swiftDemoApp/StreamChat/Components/DemoChatChannelListVC.swift
Sources/StreamChat/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes
Files:
Sources/StreamChat/Query/ChannelListQuery.swift
Tests/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Add or extend tests in the matching module's Tests/ folder for changes to StreamChat or StreamChatUI code, covering core models, API surfaces, and view controller behaviors; use fakes/mocks from test helpers provided by the repo
Files:
Tests/StreamChatTests/StateLayer/Chat_Tests.swiftTests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Sources/StreamChatUI/**/*.swift : Ensure public API changes in StreamChatUI include inline documentation and migration notes
Applied to files:
Sources/StreamChat/Query/ChannelListQuery.swiftTests/StreamChatTests/StateLayer/Chat_Tests.swiftTests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swiftTestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swiftDemoApp/StreamChat/Components/DemoChatChannelListVC.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Sources/StreamChat/**/*.swift : Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes
Applied to files:
Sources/StreamChat/Query/ChannelListQuery.swiftTests/StreamChatTests/StateLayer/Chat_Tests.swiftTests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swiftTestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swiftDemoApp/StreamChat/Components/DemoChatChannelListVC.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Tests/**/*.swift : Add or extend tests in the matching module's Tests/ folder for changes to StreamChat or StreamChatUI code, covering core models, API surfaces, and view controller behaviors; use fakes/mocks from test helpers provided by the repo
Applied to files:
Tests/StreamChatTests/StateLayer/Chat_Tests.swiftTests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swiftTestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Maintain high test coverage when changing code in the Stream iOS Chat SDK
Applied to files:
Tests/StreamChatTests/StateLayer/Chat_Tests.swiftTests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swiftTestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
Applied to files:
Tests/StreamChatTests/StateLayer/Chat_Tests.swiftTestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swiftDemoApp/StreamChat/Components/DemoChatChannelListVC.swift
🧬 Code graph analysis (2)
Tests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift (4)
Sources/StreamChat/Database/DTOs/ChannelDTO.swift (1)
channel(431-433)Tests/StreamChatTests/Database/DTOs/ChannelDTO_Tests.swift (1)
channel(1789-1791)TestTools/StreamChatTestTools/Mocks/StreamChat/Database/DatabaseSession_Mock.swift (1)
channel(403-405)Sources/StreamChat/Database/DataStore.swift (1)
channel(56-58)
DemoApp/StreamChat/Components/DemoChatChannelListVC.swift (1)
Sources/StreamChatUI/ChatChannelList/ChatChannelListVC.swift (1)
replaceQuery(236-241)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Metrics
🔇 Additional comments (2)
Sources/StreamChat/Query/ChannelListQuery.swift (1)
291-297: filterTags FilterKey wiring is correct and consistent with collection keysThe
filterTagskey uses the expected raw value, points atChannelDTO.filterTags, and setsisCollectionFilter: true, matching how other collection-backed keys (likememberName) are modeled. This will let the automatic predicate generation work for.in/.equalwithout extra mapping.TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift (1)
15-23: Mock completion_result hooks for updateChannel/partialChannelUpdate are consistent and enable async testsIntroducing
updateChannel_completion_resultandpartialChannelUpdate_completion_resultand invoking them in the overrides mirrors the existing pattern used for other operations (mute, delete, markRead, etc.). This lets tests drive success/failure forupdateChannelandpartialChannelUpdatewhile still recording payloads, andcleanUp()correctly resets the new fields. No issues spotted.Also applies to: 173-181, 338-349
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
Sources/StreamChat/StateLayer/Chat.swift (1)
1370-1380: ClarifyfilterTags: []semantics for full vs partial updatesBoth
updateandupdatePartialnow always passfilterTags: []into the channel payload. That has a couple of non‑obvious implications:
For
update(...)(full update): given the documented “any data not included is deleted” semantics, always sending an emptyfilterTagseffectively means “this channel has no filterTags” on every call. There’s no way here to either:
- preserve existing
filterTags, or- supply new
filterTags
via this API. If channels start relying on tags, this becomes a silent data‑loss vector for clients that callupdatejust to tweak name/image/team.For
updatePartial(...)(partial update): ifChannelEditDetailPayload.filterTagsis encoded whenever it is non‑nil, then passing[]will likely be interpreted by the backend as “setfilter_tagsto an empty array” on every partial update, which contradicts the documented behavior that unspecified fields are retained. Ideally, “no change to filterTags” should mean the field is omitted from the partial update payload (e.g.nil), and “clear tags” should be expressed explicitly, either viaunsetPropertiesor a dedicated API.Consider instead:
- Making
filterTagson the payload optional and:
- Passing
nilhere to indicate “do not touch filterTags” for bothupdateandupdatePartial.- Threading explicit
filterTagssupport through other, more specific APIs (e.g. controller/client factories) where the caller can intentionally set or clear tags.- Or, if you want
Chat.updateto behave as a true “replace everything” operation including tags, add an optionalfilterTags: Set<FilterTag>? = nilparameter toupdate(and possiblyupdatePartial), and:
- Use
filterTags ?? currentChannel.filterTagswhen building the payload, or- Document that omitting
filterTagsfrom the call preserves current tags, while passing[]clears them.Can you double‑check how
ChannelEditDetailPayload.filterTagsis encoded inChannelUpdater.update/updatePartialand confirm whether[]will clear tags or be treated as “no change”? If it does clear them, I’d strongly recommend adjusting this to avoid unintentional loss offilterTagswhen clients call these high‑level helpers.Also applies to: 1408-1418
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
CHANGELOG.md(1 hunks)Sources/StreamChat/Controllers/ChannelController/ChannelController.swift(2 hunks)Sources/StreamChat/StateLayer/Chat.swift(2 hunks)Tests/StreamChatTests/StateLayer/Chat_Tests.swift(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- Tests/StreamChatTests/StateLayer/Chat_Tests.swift
🧰 Additional context used
📓 Path-based instructions (3)
CHANGELOG*
📄 CodeRabbit inference engine (AGENTS.md)
Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
Files:
CHANGELOG.md
**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
**/*.swift: Write Swift code compatible with iOS deployment targets specified in Package.swift and podspec files; do not lower deployment targets without approval
Use SwiftLint with strict mode and respect .swiftlint.yml rules; justify and scope any exceptions rather than suppressing rules broadly
Run SwiftFormat for code formatting and respect repository-specific style conventions
Never commit API keys or customer data; use obvious placeholders (e.g., YOUR_STREAM_KEY) in example code
Follow the project's zero-warnings policy: fix new warnings and avoid introducing any
Files:
Sources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swift
Sources/StreamChat/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes
Files:
Sources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swift
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
Applied to files:
CHANGELOG.mdSources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Prioritize backwards compatibility and API stability when changing code in the Stream iOS Chat SDK
Applied to files:
CHANGELOG.mdSources/StreamChat/StateLayer/Chat.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Sources/StreamChat/**/*.swift : Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes
Applied to files:
CHANGELOG.mdSources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Sources/StreamChatUI/**/*.swift : Ensure public API changes in StreamChatUI include inline documentation and migration notes
Applied to files:
Sources/StreamChat/StateLayer/Chat.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Prefer additive changes and avoid breaking public APIs in StreamChat and StreamChatUI
Applied to files:
Sources/StreamChat/StateLayer/Chat.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Maintain high test coverage when changing code in the Stream iOS Chat SDK
Applied to files:
Sources/StreamChat/StateLayer/Chat.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Tests/**/*.swift : Add or extend tests in the matching module's Tests/ folder for changes to StreamChat or StreamChatUI code, covering core models, API surfaces, and view controller behaviors; use fakes/mocks from test helpers provided by the repo
Applied to files:
Sources/StreamChat/StateLayer/Chat.swift
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Test LLC (Debug)
- GitHub Check: Build LLC + UI (Xcode 15)
- GitHub Check: Build Test App and Frameworks
- GitHub Check: Metrics
🔇 Additional comments (2)
CHANGELOG.md (1)
12-15: CHANGELOG entry is well-structured and comprehensive. The entry clearly documents the three main additions (filterTags property, filtering key, and method arguments) with proper formatting and a valid PR reference. The placement under StreamChat > Added section is correct, and the bullet structure matches established conventions in the file.Sources/StreamChat/Controllers/ChannelController/ChannelController.swift (1)
275-284: The hardcodedfilterTags: []is correct and does not risk data loss.
ChannelEditDetailPayloadimplements custom encoding logic (line 72-74) that conditionally includesfilterTagsonly when the set is non-empty:if !filterTags.isEmpty { try container.encode(filterTags, ...) }. This means emptyfilterTagsare omitted entirely from the JSON payload sent to the backend—the field is simply not present in the request. The backend will not clear existing channel filterTags; it will ignore the field. This design is intentional and aligns with the PR's stated purpose: filterTags are managed server-side only, not through client update calls. The same conditional encoding pattern is used forinvitesandmemberssets.Likely an incorrect or invalid review comment.
…not supported by backend" This reverts commit 33906aa.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Sources/StreamChat/Controllers/ChannelController/ChannelController.swift (1)
295-340: ClarifyfilterTagssemantics and improve partial-update designThe current API design conflates two concerns:
Inaccurate documentation: The parameter doc says "A list of tags to add to the channel", but the actual behavior is "set/replace" (when non-empty) or "no-op" (when empty), since the
encode(to:)method skips empty sets. This contradicts the stated intent.No direct way to clear tags: While empty sets won't accidentally clear tags (they're not encoded), there's no clean way to explicitly clear
filterTagswithout usingunsetProperties. For a partial-update API, this forces awkward two-parameter patterns:// To clear tags, users must do: partialChannelUpdate(filterTags: [], unsetProperties: ["filter_tags"])Recommended improvements:
- Change
filterTags: Set<String> = []tofilterTags: Set<String>? = nilin bothChannelController.partialChannelUpdate()andChat.updatePartial().- Update the payload and encoding logic to handle nil → "leave unchanged", empty set → "clear", non-empty set → "set".
- Update documentation to explicitly state this behavior.
Add tests to verify:
- Calling
partialChannelUpdatewithout specifyingfilterTagspreserves existing tags.- Calling with
filterTags: []clears them (or document if unintended).- Calling with a non-empty set replaces them.
This ensures both APIs have consistent, intuitive semantics for partial updates.
🧹 Nitpick comments (1)
Sources/StreamChat/StateLayer/Chat.swift (1)
1353-1424: ReviewfilterTagsthreading inupdate/updatePartial(semantics & API shape)The wiring itself looks correct:
filterTagsis threaded into the channel payloads for both full and partial updates, and the public API remains source-compatible due to the default value.Two points to consider:
Partial update semantics / possible unintended clearing
For
updatePartialyou currently have:public func updatePartial( name: String? = nil, imageURL: URL? = nil, team: String? = nil, members: [UserId] = [], invites: [UserId] = [], filterTags: Set<String> = [], extraData: [String: RawJSON] = [:], unsetProperties: [String] = [] ) ... channelPayload: .init( cid: cid, name: name, imageURL: imageURL, team: team, members: Set(members), invites: Set(invites), filterTags: filterTags, extraData: extraData ),Because
filterTagsis non‑optional with default[], every call toupdatePartialwill pass a value forfilterTags. IfChannelEditDetailPayloadencodes empty sets as real values, this will clear existing tags even when the caller didn’t intend to touch them (e.g.chat.updatePartial(name: "New name")).If the intended semantics are “only mutate tags when the caller specifies them”, consider:
- public func updatePartial(
- public func updatePartial(
name: String? = nil,
imageURL: URL? = nil,
team: String? = nil,
members: [UserId] = [],
invites: [UserId] = [],
filterTags: Set<String> = [],
) async throws {filterTags: Set<String>? = nil, extraData: [String: RawJSON] = [:], unsetProperties: [String] = []
try await channelUpdater.updatePartial(
channelPayload: .init(
cid: cid,
name: name,
imageURL: imageURL,
team: team,
members: Set(members),
invites: Set(invites),
filterTags: filterTags,
}filterTags: filterTags, extraData: extraData ), unsetProperties: unsetProperties )This keeps the API additive while allowing “no change” vs “explicitly clear tags (pass [])” to be differentiated at the payload layer.
Doc wording for full update
For the full
updatemethod, the warning already states that unspecified data is deleted. The new param is documented as:/// - filterTags: A list of tags to add to the channel.Given full update semantics, it might be clearer to say something like “The set of filter tags for the channel. Passing an empty set clears all tags.” to make replacement vs additive behavior explicit.
As per coding guidelines, this helps avoid surprising behavior while keeping the public API additive.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
CHANGELOG.md(1 hunks)DemoApp/StreamChat/Components/DemoChatChannelListRouter.swift(1 hunks)Sources/StreamChat/Controllers/ChannelController/ChannelController.swift(6 hunks)Sources/StreamChat/StateLayer/Chat.swift(6 hunks)Tests/StreamChatTests/StateLayer/Chat_Tests.swift(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- CHANGELOG.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
**/*.swift: Write Swift code compatible with iOS deployment targets specified in Package.swift and podspec files; do not lower deployment targets without approval
Use SwiftLint with strict mode and respect .swiftlint.yml rules; justify and scope any exceptions rather than suppressing rules broadly
Run SwiftFormat for code formatting and respect repository-specific style conventions
Never commit API keys or customer data; use obvious placeholders (e.g., YOUR_STREAM_KEY) in example code
Follow the project's zero-warnings policy: fix new warnings and avoid introducing any
Files:
DemoApp/StreamChat/Components/DemoChatChannelListRouter.swiftTests/StreamChatTests/StateLayer/Chat_Tests.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftSources/StreamChat/StateLayer/Chat.swift
Tests/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Add or extend tests in the matching module's Tests/ folder for changes to StreamChat or StreamChatUI code, covering core models, API surfaces, and view controller behaviors; use fakes/mocks from test helpers provided by the repo
Files:
Tests/StreamChatTests/StateLayer/Chat_Tests.swift
Sources/StreamChat/**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes
Files:
Sources/StreamChat/Controllers/ChannelController/ChannelController.swiftSources/StreamChat/StateLayer/Chat.swift
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Sources/StreamChatUI/**/*.swift : Ensure public API changes in StreamChatUI include inline documentation and migration notes
Applied to files:
DemoApp/StreamChat/Components/DemoChatChannelListRouter.swiftTests/StreamChatTests/StateLayer/Chat_Tests.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftSources/StreamChat/StateLayer/Chat.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Sources/StreamChat/**/*.swift : Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes
Applied to files:
DemoApp/StreamChat/Components/DemoChatChannelListRouter.swiftTests/StreamChatTests/StateLayer/Chat_Tests.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftSources/StreamChat/StateLayer/Chat.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI
Applied to files:
DemoApp/StreamChat/Components/DemoChatChannelListRouter.swiftTests/StreamChatTests/StateLayer/Chat_Tests.swiftSources/StreamChat/Controllers/ChannelController/ChannelController.swiftSources/StreamChat/StateLayer/Chat.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Applies to Tests/**/*.swift : Add or extend tests in the matching module's Tests/ folder for changes to StreamChat or StreamChatUI code, covering core models, API surfaces, and view controller behaviors; use fakes/mocks from test helpers provided by the repo
Applied to files:
Tests/StreamChatTests/StateLayer/Chat_Tests.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Maintain high test coverage when changing code in the Stream iOS Chat SDK
Applied to files:
Tests/StreamChatTests/StateLayer/Chat_Tests.swift
📚 Learning: 2025-11-25T12:17:18.459Z
Learnt from: CR
Repo: GetStream/stream-chat-swift PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T12:17:18.459Z
Learning: Prefer additive changes and avoid breaking public APIs in StreamChat and StreamChatUI
Applied to files:
Sources/StreamChat/StateLayer/Chat.swift
🧬 Code graph analysis (2)
DemoApp/StreamChat/Components/DemoChatChannelListRouter.swift (3)
Sources/StreamChat/Controllers/ChannelController/ChannelController.swift (1)
partialChannelUpdate(307-340)Sources/StreamChat/APIClient/Endpoints/ChannelEndpoints.swift (1)
partialChannelUpdate(58-71)Sources/StreamChat/Workers/ChannelUpdater.swift (1)
partialChannelUpdate(140-148)
Tests/StreamChatTests/StateLayer/Chat_Tests.swift (3)
Sources/StreamChat/StateLayer/Chat.swift (2)
update(1363-1384)updatePartial(1402-1425)TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift (1)
update(325-336)Sources/StreamChat/Workers/ChannelUpdater.swift (4)
update(43-123)update(1079-1094)update(1096-1102)updatePartial(1104-1110)
🔇 Additional comments (3)
DemoApp/StreamChat/Components/DemoChatChannelListRouter.swift (1)
480-487: LGTM! Clean demo implementation of the new filterTags feature.The action correctly demonstrates the new
filterTagsparameter forpartialChannelUpdate. The implementation follows the established pattern in this file, includes appropriate permission checks (canUpdateChannel), and handles errors consistently with other actions.Tests/StreamChatTests/StateLayer/Chat_Tests.swift (1)
1311-1409: New update/updatePartial tests correctly coverfilterTagspropagationThe four added tests around channel updating look solid: they exercise both success and failure paths and assert that all relevant fields (including
filterTagsandunsetProperties) are forwarded toChannelUpdater_Mockas expected. The structure is consistent with the rest of this suite.Sources/StreamChat/Controllers/ChannelController/ChannelController.swift (1)
250-293: The implementation is actually safe due to theChannelEditDetailPayload.encode()method, which uses conditional encoding: emptyfilterTagssets are not included in the JSON payload. This prevents the concern about unintentionally clearing tags when callers omit the parameter.However, the documentation stating "A list of tags to add to the channel" is misleading—the implementation assigns/replaces tags, not adds to them. Consider updating the doc string to clarify the actual semantics, e.g., "The filter tags to assign to the channel; an empty set does not modify existing tags." The CHANGELOG entry could also benefit from documenting this behavior for clarity.
Likely an incorrect or invalid review comment.
SDK Size
|
Public Interface public enum ChannelCodingKeys: String, CodingKey, CaseIterable
- case team
+ case filterTags = "filter_tags"
- case memberCount = "member_count"
+ case team
- case messageCount = "message_count"
+ case memberCount = "member_count"
- case cooldownDuration = "cooldown"
+ case messageCount = "message_count"
- case blocked
+ case cooldownDuration = "cooldown"
+ case blocked
public class ChatChannelController: DataController, DelegateCallable, DataStoreProvider
- public func updateChannel(name: String?,imageURL: URL?,team: String?,members: Set<UserId> = [],invites: Set<UserId> = [],extraData: [String: RawJSON] = [:],completion: ((Error?) -> Void)? = nil)
+ public func updateChannel(name: String?,imageURL: URL?,team: String?,members: Set<UserId> = [],invites: Set<UserId> = [],filterTags: Set<String> = [],extraData: [String: RawJSON] = [:],completion: ((Error?) -> Void)? = nil)
- public func partialChannelUpdate(name: String? = nil,imageURL: URL? = nil,team: String? = nil,members: Set<UserId> = [],invites: Set<UserId> = [],extraData: [String: RawJSON] = [:],unsetProperties: [String] = [],completion: ((Error?) -> Void)? = nil)
+ public func partialChannelUpdate(name: String? = nil,imageURL: URL? = nil,team: String? = nil,members: Set<UserId> = [],invites: Set<UserId> = [],filterTags: Set<String> = [],extraData: [String: RawJSON] = [:],unsetProperties: [String] = [],completion: ((Error?) -> Void)? = nil)
public class Chat
- public func update(name: String?,imageURL: URL?,team: String?,members: Set<UserId> = [],invites: Set<UserId> = [],extraData: [String: RawJSON] = [:])async throws
+ public func update(name: String?,imageURL: URL?,team: String?,members: Set<UserId> = [],invites: Set<UserId> = [],filterTags: Set<String> = [],extraData: [String: RawJSON] = [:])async throws
- public func updatePartial(name: String? = nil,imageURL: URL? = nil,team: String? = nil,members: [UserId] = [],invites: [UserId] = [],extraData: [String: RawJSON] = [:],unsetProperties: [String] = [])async throws
+ public func updatePartial(name: String? = nil,imageURL: URL? = nil,team: String? = nil,members: [UserId] = [],invites: [UserId] = [],filterTags: Set<String> = [],extraData: [String: RawJSON] = [:],unsetProperties: [String] = [])async throws
public struct ChatChannel
- public let ownCapabilities: Set<ChannelCapability>
+ public let filterTags: Set<String>
- public let isFrozen: Bool
+ public let ownCapabilities: Set<ChannelCapability>
- public let isDisabled: Bool
+ public let isFrozen: Bool
- public let isBlocked: Bool
+ public let isDisabled: Bool
- public let memberCount: Int
+ public let isBlocked: Bool
- public let messageCount: Int?
+ public let memberCount: Int
- public let lastActiveMembers: [ChatChannelMember]
+ public let messageCount: Int?
- public let currentlyTypingUsers: Set<ChatUser>
+ public let lastActiveMembers: [ChatChannelMember]
- public internal var membership: ChatChannelMember?
+ public let currentlyTypingUsers: Set<ChatUser>
- public var isArchived: Bool
+ public internal var membership: ChatChannelMember?
- public var isPinned: Bool
+ public var isArchived: Bool
- public let lastActiveWatchers: [ChatUser]
+ public var isPinned: Bool
- public let watcherCount: Int
+ public let lastActiveWatchers: [ChatUser]
- public let team: TeamId?
+ public let watcherCount: Int
- public let unreadCount: ChannelUnreadCount
+ public let team: TeamId?
- public let latestMessages: [ChatMessage]
+ public let unreadCount: ChannelUnreadCount
- public let lastMessageFromCurrentUser: ChatMessage?
+ public let latestMessages: [ChatMessage]
- public let pinnedMessages: [ChatMessage]
+ public let lastMessageFromCurrentUser: ChatMessage?
- public let pendingMessages: [ChatMessage]
+ public let pinnedMessages: [ChatMessage]
- public let reads: [ChatChannelRead]
+ public let pendingMessages: [ChatMessage]
- public let muteDetails: MuteDetails?
+ public let reads: [ChatChannelRead]
- public var isMuted: Bool
+ public let muteDetails: MuteDetails?
- public let cooldownDuration: Int
+ public var isMuted: Bool
- public let extraData: [String: RawJSON]
+ public let cooldownDuration: Int
- public let previewMessage: ChatMessage?
+ public let extraData: [String: RawJSON]
- public let draftMessage: DraftMessage?
+ public let previewMessage: ChatMessage?
- public let activeLiveLocations: [SharedLocation]
+ public let draftMessage: DraftMessage?
- public let pushPreference: PushPreference?
+ public let activeLiveLocations: [SharedLocation]
-
+ public let pushPreference: PushPreference?
-
+
- public func replacing(name: String?,imageURL: URL?,extraData: [String: RawJSON]?)-> ChatChannel
+
- public func changing(name: String? = nil,imageURL: URL? = nil,lastMessageAt: Date? = nil,createdAt: Date? = nil,deletedAt: Date? = nil,updatedAt: Date? = nil,truncatedAt: Date? = nil,isHidden: Bool? = nil,createdBy: ChatUser? = nil,config: ChannelConfig? = nil,ownCapabilities: Set<ChannelCapability>? = nil,isFrozen: Bool? = nil,isDisabled: Bool? = nil,isBlocked: Bool? = nil,reads: [ChatChannelRead]? = nil,members: [ChatChannelMember]? = nil,membership: ChatChannelMember? = nil,memberCount: Int? = nil,watchers: [ChatUser]? = nil,watcherCount: Int? = nil,team: TeamId? = nil,cooldownDuration: Int? = nil,pinnedMessages: [ChatMessage]? = nil,pushPreference: PushPreference? = nil,extraData: [String: RawJSON]? = nil)-> ChatChannel
+ public func replacing(name: String?,imageURL: URL?,extraData: [String: RawJSON]?)-> ChatChannel
+ public func changing(name: String? = nil,imageURL: URL? = nil,lastMessageAt: Date? = nil,createdAt: Date? = nil,deletedAt: Date? = nil,updatedAt: Date? = nil,truncatedAt: Date? = nil,isHidden: Bool? = nil,createdBy: ChatUser? = nil,config: ChannelConfig? = nil,filterTags: Set<String>? = nil,ownCapabilities: Set<ChannelCapability>? = nil,isFrozen: Bool? = nil,isDisabled: Bool? = nil,isBlocked: Bool? = nil,reads: [ChatChannelRead]? = nil,members: [ChatChannelMember]? = nil,membership: ChatChannelMember? = nil,memberCount: Int? = nil,watchers: [ChatUser]? = nil,watcherCount: Int? = nil,team: TeamId? = nil,cooldownDuration: Int? = nil,pinnedMessages: [ChatMessage]? = nil,pushPreference: PushPreference? = nil,extraData: [String: RawJSON]? = nil)-> ChatChannel |
StreamChat XCSize
Show 15 more objects
|
StreamChatUI XCSize
|
|



🔗 Issue Links
Fixes: IOS-1278
🎯 Goal
Support filter tags in channel payload, filters, and channel updates
📝 Summary
ChatChannel.filterTagsfilterTagschannel list filtering keyfilterTagsargument toChatChannelControllerandChatfactory methods inChatClientfilterTagsargument toChatChannelController.updateChannelandChatChannelController.partialUpdateChannelfilterTagsargument toChat.updateandChat.updatePartial🛠 Implementation
🎨 Showcase
🧪 Manual Testing Notes
Added "Add Premium Tag" channel debug action and filter tags channel query.
☑️ Contributor Checklist
docs-contentrepoSummary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.