Skip to content

Conversation

@laevandus
Copy link
Contributor

@laevandus laevandus commented Nov 28, 2025

🔗 Issue Links

Fixes: IOS-1278

🎯 Goal

Support filter tags in channel payload, filters, and channel updates

📝 Summary

  • Add support for filter tags in channels
    • Add ChatChannel.filterTags
    • Add filterTags channel list filtering key
    • Add filterTags argument to ChatChannelController and Chat factory methods in ChatClient
    • Add filterTags argument to ChatChannelController.updateChannel and ChatChannelController.partialUpdateChannel
    • Add filterTags argument to Chat.update and Chat.updatePartial

🛠 Implementation

🎨 Showcase

🧪 Manual Testing Notes

Added "Add Premium Tag" channel debug action and filter tags channel query.

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change should be manually QAed
  • Changelog is updated with client-facing changes
  • Changelog is updated with new localization keys
  • New code is covered by unit tests
  • Documentation has been updated in the docs-content repo

Summary by CodeRabbit

  • New Features

    • Channel filter tags: create/update channels with tags and filter channel lists by tag (e.g., "premium").
    • Demo UI: "Premium Tagged Channels" view and "Add Premium Tag" action to mark channels as premium.
  • Chores

    • Increased lint complexity thresholds to reduce noisy control-flow warnings.

✏️ Tip: You can customize this high-level summary in your review settings.

@laevandus laevandus requested a review from a team as a code owner November 28, 2025 13:25
@laevandus laevandus marked this pull request as draft November 28, 2025 13:25
@coderabbitai
Copy link

coderabbitai bot commented Nov 28, 2025

Walkthrough

Adds a new channel-level filterTags field and threads it across models, payloads, coding keys, persistence, queries, controllers, factory APIs, mocks/fixtures, tests, and a demo UI; also raises cyclomatic complexity thresholds in the linter config.

Changes

Cohort / File(s) Summary
Configuration & Changelog
\.swiftlint\.yml, CHANGELOG\.md
Increased cyclomatic complexity thresholds (warning 25→30, error 30→35) and documented the new filterTags feature.
Channel Model & Mapping
Sources/StreamChat/Models/Channel.swift, Sources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swift
Added public filterTags: Set<String> to ChatChannel, updated initializers/replacing/changing/hash equality, and populated it from payloads.
Payloads & CodingKeys
Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swift, .../ChannelEditDetailPayload.swift, .../ChannelListPayload.swift
Added filterTags coding key ("filter_tags"); added filterTags property to edit/detail/list payloads with decoding and conditional encoding.
Controllers & Public Factories
Sources/StreamChat/Controllers/ChannelController/ChatClient+ChannelController.swift, Sources/StreamChat/StateLayer/ChatClient+Factory.swift, Sources/StreamChat/Controllers/ChannelController/ChannelController.swift, Sources/StreamChat/StateLayer/Chat.swift
Added filterTags: Set<String> = [] parameter to channel creation/update factory methods and to update/updatePartial APIs; threaded filterTags into ChannelEditDetailPayload payloads.
Livestream Controller
Sources/StreamChat/Controllers/ChannelController/LivestreamChannelController.swift
Propagates filterTags from ChannelUpdatedEvent into channel reconciliation (channel.changing(...)).
Database & Core Data
Sources/StreamChat/Database/DTOs/ChannelDTO.swift, Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/.../contents
Added filterTags attribute (Transformable) to ChannelDTO and Core Data model; persist and restore filterTags during save/restore.
Query Filtering
Sources/StreamChat/Query/ChannelListQuery.swift
Added FilterKey entry filterTags for ChannelListFilterScope (collection filtering support; operators like in/equal).
Mocks, Fixtures & Test Tools
TestTools/.../ChatChannel_Mock.swift, .../ChannelEditDetailPayload+Unique.swift, .../ChannelUpdater_Mock.swift, TestTools/.../Fixtures/JSONs/Channel.json
Added filterTags to mocks and JSON fixtures; ChannelUpdater_Mock gained atomic result holders for update/partialUpdate and invokes them in the mock implementations.
Test Data & Builders
TestTools/.../TestData/ChannelDetailPayload.swift, TestTools/.../TestData/XCTestCase+Dummy.swift
Added optional filterTags parameters to dummy payload builders and propagated into channel payloads.
Tests
Tests/.../Payloads/*, Controllers/*, Query/*, ChannelListController_Tests.swift, Chat_Tests.swift, WebSocketClient/...
Updated/added tests to cover encoding/decoding, model mapping, filterTags query predicate behavior, channel update/partial-update flows, and event-driven updates.
Demo App
DemoApp/StreamChat/Components/DemoChatChannelListVC.swift, DemoApp/StreamChat/Components/DemoChatChannelListRouter.swift
Added premiumTaggedChannelsQuery and menu actions: "Premium Tagged Channels" query switch and "Add Premium Tag" action invoking partialChannelUpdate(filterTags: ["premium"]).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay extra attention to:
    • ChannelEditDetailPayload encoding: conditional emission when empty vs non-empty.
    • Core Data model attribute type (Transformable) and ChannelDTO persistence mapping.
    • Consistency across public API surfaces (factory methods, ChannelController, Chat public methods) for default values and signatures.
    • LivestreamChannelController: channel.changing(...) signature alignment and event propagation.
    • ChannelUpdater_Mock: atomic result holders lifecycle and invocation semantics in tests.

Possibly related PRs

Suggested labels

🌐 SDK: StreamChat (LLC), ✅ Feature

Suggested reviewers

  • martinmitrevski

Poem

🐰 A tag hops lightly on the stream,

filterTags tucked in a developer's dream.
Through payloads, DB, and tests they roam,
"premium" finds its cozy home.
Hooray — the channels wear their badge with glee! 🏷️

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.89% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add support for filter tags in channels' clearly and concisely summarizes the main change: introducing filterTags support to channels.
Linked Issues check ✅ Passed The PR comprehensively implements all objectives from IOS-1278: adds ChatChannel.filterTags property, introduces filterTags as a channel list filtering key, adds filterTags parameters to ChatChannelController and Chat factory methods, and supports filterTags in channel updates.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the stated objective of adding filterTags support. The PR includes necessary infrastructure updates (Core Data model, payloads, endpoints, query filters, and tests), plus demo app enhancements showing practical usage.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add/channel-filter-tags

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@laevandus laevandus changed the title Add filterTags to ChatChannel, filterTags filter key and to channel update methods Add support for filter tags in channels Nov 28, 2025
Comment on lines -70 to +71
warning: 25
error: 30
warning: 30
error: 35
Copy link
Contributor Author

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.

@laevandus laevandus marked this pull request as ready for review November 28, 2025 14:08
Copy link

@coderabbitai coderabbitai bot left a 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.filterTags is a Set<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 compare Set<String> to Set<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 relaxation

Bumping the global cyclomatic_complexity thresholds 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 with ChannelCodingKeys. 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 propagation

The 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 later

Adding a filterTags: Set<String> = [] parameter and forwarding it into self.init keeps 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/mockNonDMChannel and 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(...), and changing(...) all pass filterTags through, so tags are preserved across derived instances.
  • Equality now includes filterTags, ensuring channel updates are observed when tags change, while the hash implementation (based on cid) still satisfies Hashable constraints.

Only note: if you ever need to mutate tags via changing(...), adding an optional filterTags parameter 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 7e59297 and 65ab87c.

📒 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.swift
  • TestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift
  • Sources/StreamChat/Models/Channel.swift
  • Tests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swift
  • Sources/StreamChat/Database/DTOs/ChannelDTO.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift
  • Sources/StreamChat/StateLayer/Chat.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swift
  • Sources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swift
  • Tests/StreamChatTests/Query/ChannelListFilterScope_Tests.swift
  • Tests/StreamChatTests/Query/ChannelQuery_Tests.swift
  • Sources/StreamChat/StateLayer/ChatClient+Factory.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelListPayload.swift
  • Tests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift
  • Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift
  • Sources/StreamChat/Query/ChannelListQuery.swift
  • Sources/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.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift
  • Tests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift
  • Tests/StreamChatTests/Query/ChannelListFilterScope_Tests.swift
  • Tests/StreamChatTests/Query/ChannelQuery_Tests.swift
  • Tests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swift
  • Tests/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.swift
  • Sources/StreamChat/Database/DTOs/ChannelDTO.swift
  • Sources/StreamChat/StateLayer/Chat.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swift
  • Sources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swift
  • Sources/StreamChat/StateLayer/ChatClient+Factory.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelListPayload.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • Sources/StreamChat/Query/ChannelListQuery.swift
  • Sources/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.swift
  • TestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift
  • Tests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift
  • Tests/StreamChatTests/Query/ChannelListFilterScope_Tests.swift
  • Tests/StreamChatTests/Query/ChannelQuery_Tests.swift
  • Tests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift
  • Tests/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.swift
  • Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents
  • TestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift
  • Sources/StreamChat/Models/Channel.swift
  • Tests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swift
  • Sources/StreamChat/Database/DTOs/ChannelDTO.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift
  • Sources/StreamChat/StateLayer/Chat.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swift
  • Sources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swift
  • Tests/StreamChatTests/Query/ChannelListFilterScope_Tests.swift
  • Tests/StreamChatTests/Query/ChannelQuery_Tests.swift
  • Sources/StreamChat/StateLayer/ChatClient+Factory.swift
  • Tests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift
  • Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift
  • Sources/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.swift
  • Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents
  • TestTools/StreamChatTestTools/Extensions/Unique/ChannelEditDetailPayload+Unique.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/IdentifiablePayload_Tests.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift
  • Sources/StreamChat/Models/Channel.swift
  • Tests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swift
  • Sources/StreamChat/Database/DTOs/ChannelDTO.swift
  • Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift
  • Sources/StreamChat/StateLayer/Chat.swift
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelEditDetailPayload.swift
  • Sources/StreamChat/Models/Payload+asModel/ChannelPayload+asModel.swift
  • CHANGELOG.md
  • Sources/StreamChat/APIClient/Endpoints/Payloads/ChannelCodingKeys.swift
  • Tests/StreamChatTests/Query/ChannelListFilterScope_Tests.swift
  • Tests/StreamChatTests/Query/ChannelQuery_Tests.swift
  • Sources/StreamChat/StateLayer/ChatClient+Factory.swift
  • Tests/StreamChatTests/Controllers/ChannelController/ChannelController_Tests.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift
  • Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift
  • Sources/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.swift
  • Tests/StreamChatTests/Query/ChannelListFilterScope_Tests.swift
  • Tests/StreamChatTests/Query/ChannelQuery_Tests.swift
  • Tests/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.yml
  • Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents
  • 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 CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI

Applied to files:

  • Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents
  • Sources/StreamChat/StateLayer/Chat.swift
  • CHANGELOG.md
  • Sources/StreamChat/StateLayer/ChatClient+Factory.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • Tests/StreamChatTests/Controllers/ChannelController/LivestreamChannelController_Tests.swift
  • Sources/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/contents
  • CHANGELOG.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 correctly

Wiring 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 filterTags

Passing filterTags: nil into ChannelDetailPayload keeps 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 way

Adding filterTags: [String]? to ChannelDetailPayload and decoding it via ChannelCodingKeys.filterTags cleanly exposes the new field from channel list payloads while keeping it optional and separate from extraData. 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 fine

The new optional Transformable ChannelDTO.filterTags attribute wired through NSSecureUnarchiveFromDataTransformer fits the existing pattern for persisted collections and should be handled by lightweight migration. The updated lastSavedToolsVersion/systemVersion in 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: New filterTags filter key wiring looks consistent

Using 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 fixture filter_tags addition looks correct

The 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 for filterTags is coherent

Persisting payload.filterTags into ChannelDTO.filterTags and then exposing it as Set(dto.filterTags) on ChatChannel mirrors the existing ownCapabilities pattern and keeps network, DB, and model layers in sync. The conditional assignment also sensibly treats nil as “no change”.

Also applies to: 259-262, 652-653

Tests/StreamChatTests/WebSocketClient/EventMiddlewares/ChannelReadUpdaterMiddleware_Tests.swift (1)

1007-1031: ChannelDetailPayload initialization updated for filterTags without changing behavior

Including filterTags: nil in 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.asModel now correctly sets ChatChannel.filterTags

Using Set(channelPayload.filterTags ?? []) cleanly bridges the optional [String]? payload field into the non‑optional Set<String> on ChatChannel, matching the DTO‑based construction path.

Also applies to: 44-45

Tests/StreamChatTests/Query/ChannelQuery_Tests.swift (1)

43-52: ChannelQuery apiPath tests updated for filterTags without changing semantics

Passing filterTags: [] into the ChannelPayload initializers keeps the tests compiling against the new API while verifying that apiPath is still driven solely by type/id.

Also applies to: 66-75, 80-89

Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelEditDetailPayload_Tests.swift (1)

49-58: ChannelEditDetailPayload apiPath tests correctly include filterTags

Adding filterTags: [] to both ChannelEditDetailPayload initializers keeps the tests in sync with the new signature, and expectations around apiPath remain valid.

Also applies to: 65-74

Tests/StreamChatTests/APIClient/Endpoints/Payloads/ChannelListPayload_Tests.swift (3)

148-152: Dummy channel list: filterTags population is appropriate

Populating ChannelDetailPayload in createHugeChannelList with filterTags: ["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 correct

Asserting XCTAssertEqual(payload.channel.filterTags, ["football"]) matches the expected [String]? type on ChannelDetailPayload.filterTags and validates JSON fixture wiring. This is a good coverage point.


538-562: Minimal asModel test for filterTags is wired correctly

Using filterTags: nil in ChannelDetailPayload and then asserting XCTAssertTrue(chatChannel.filterTags.isEmpty) correctly verifies that missing tags map to an empty Set on ChatChannel. 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_tags only when filterTags is 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 sound

Passing filterTags: [] into ChannelEditDetailPayload here 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

setupControllerForNewDirectMessageChannel now initializes ChannelEditDetailPayload with filterTags: [], 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 wired

Similarly, setupControllerForNewMessageChannel uses filterTags: [], 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 filterTags parameter with a nil default 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 the filterTags parameter with an empty set default and threads it through to the ChannelEditDetailPayload. 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 the filterTags parameter with an empty set default and threads it through to the ChannelEditDetailPayload. 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 filterTags parameter and propagate it through to the Channel initialization. The explicit filterTags: nil in dummyPayloadWithNoExtraData is 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 the filterTags parameter with appropriate defaults and documentation. The implementation properly constructs the ChannelEditDetailPayload with the filterTags included.


301-340: LGTM! Partial channel update method properly extended with filterTags.

The partialChannelUpdate(...) method correctly adds the filterTags parameter 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 the filterTags parameter and threads it through to the ChannelEditDetailPayload. 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 the filterTags parameter and threads it through to the ChannelEditDetailPayload. 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 the filterTags parameter and threads it through to the ChannelEditDetailPayload. 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 the filterTags parameter and threads it through to the ChannelEditDetailPayload. The implementation is consistent with the regular channel creation method and properly handles the direct message use case.

@Stream-SDK-Bot
Copy link
Collaborator

SDK Performance

target metric benchmark branch performance status
MessageList Hitches total duration 10 ms 6.68 ms 33.2% 🔼 🟢
Duration 2.6 s 2.54 s 2.31% 🔼 🟢
Hitch time ratio 4 ms per s 2.62 ms per s 34.5% 🔼 🟢
Frame rate 75 fps 78.1 fps 4.13% 🔼 🟢
Number of hitches 1 0.6 40.0% 🔼 🟢

Copy link
Member

@nuno-vieira nuno-vieira left a 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 👍

Comment on lines 295 to 297
/// 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)) }
Copy link
Member

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

@laevandus laevandus force-pushed the add/channel-filter-tags branch from 8a6e484 to 92aac42 Compare December 1, 2025 08:37
@laevandus laevandus force-pushed the add/channel-filter-tags branch from 92aac42 to 33906aa Compare December 1, 2025 08:41
Copy link

@coderabbitai coderabbitai bot left a 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_returnsExpectedResults is well-structured: it uses .in(.filterTags, values: ["premium"]) plus assertFilterPredicate to verify that channels whose filterTags contain "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 confirm equal behaves as expected too.

DemoApp/StreamChat/Components/DemoChatChannelListVC.swift (1)

107-112: Premium-tagged channels query works; consider aligning membership filtering with other queries

The new premiumTaggedChannelsQuery and its action/wrapper method are wired correctly and integrate cleanly with the existing filter menu. One behavioral difference is that this query filters only by filterTags and does not also constrain to channels containing currentUserId, 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 filterTags

These new tests correctly verify that Chat.update and Chat.updatePartial pass name, imageURL, team, members, invites, extraData, and unsetProperties through to ChannelEditDetailPayload, and that success/failure from ChannelUpdater_Mock is surfaced as expected. If Chat.update/updatePartial now also expose filterTags, it would be worth extending these tests to set non-empty filterTags and 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 7851679 and 92aac42.

📒 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.swift
  • Tests/StreamChatTests/StateLayer/Chat_Tests.swift
  • Tests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift
  • DemoApp/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.swift
  • Tests/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.swift
  • Tests/StreamChatTests/StateLayer/Chat_Tests.swift
  • Tests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift
  • DemoApp/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.swift
  • Tests/StreamChatTests/StateLayer/Chat_Tests.swift
  • Tests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift
  • DemoApp/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.swift
  • Tests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift
  • TestTools/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.swift
  • Tests/StreamChatTests/Controllers/ChannelListController/ChannelListController_Tests.swift
  • TestTools/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.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ChannelUpdater_Mock.swift
  • DemoApp/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 keys

The filterTags key uses the expected raw value, points at ChannelDTO.filterTags, and sets isCollectionFilter: true, matching how other collection-backed keys (like memberName) are modeled. This will let the automatic predicate generation work for .in/.equal without 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 tests

Introducing updateChannel_completion_result and partialChannelUpdate_completion_result and invoking them in the overrides mirrors the existing pattern used for other operations (mute, delete, markRead, etc.). This lets tests drive success/failure for updateChannel and partialChannelUpdate while still recording payloads, and cleanUp() correctly resets the new fields. No issues spotted.

Also applies to: 173-181, 338-349

Copy link

@coderabbitai coderabbitai bot left a 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: Clarify filterTags: [] semantics for full vs partial updates

Both update and updatePartial now always pass filterTags: [] 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 empty filterTags effectively 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 call update just to tweak name/image/team.
  • For updatePartial(...) (partial update): if ChannelEditDetailPayload.filterTags is encoded whenever it is non‑nil, then passing [] will likely be interpreted by the backend as “set filter_tags to 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 via unsetProperties or a dedicated API.

Consider instead:

  • Making filterTags on the payload optional and:
    • Passing nil here to indicate “do not touch filterTags” for both update and updatePartial.
    • Threading explicit filterTags support through other, more specific APIs (e.g. controller/client factories) where the caller can intentionally set or clear tags.
  • Or, if you want Chat.update to behave as a true “replace everything” operation including tags, add an optional filterTags: Set<FilterTag>? = nil parameter to update (and possibly updatePartial), and:
    • Use filterTags ?? currentChannel.filterTags when building the payload, or
    • Document that omitting filterTags from the call preserves current tags, while passing [] clears them.

Can you double‑check how ChannelEditDetailPayload.filterTags is encoded in ChannelUpdater.update / updatePartial and 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 of filterTags when 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 92aac42 and 33906aa.

📒 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.swift
  • Sources/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.swift
  • Sources/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.md
  • Sources/StreamChat/StateLayer/Chat.swift
  • Sources/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.md
  • 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 Sources/StreamChat/**/*.swift : Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes

Applied to files:

  • CHANGELOG.md
  • Sources/StreamChat/StateLayer/Chat.swift
  • Sources/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.swift
  • Sources/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 hardcoded filterTags: [] is correct and does not risk data loss.

ChannelEditDetailPayload implements custom encoding logic (line 72-74) that conditionally includes filterTags only when the set is non-empty: if !filterTags.isEmpty { try container.encode(filterTags, ...) }. This means empty filterTags are 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 for invites and members sets.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a 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: Clarify filterTags semantics and improve partial-update design

The current API design conflates two concerns:

  1. 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.

  2. 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 filterTags without using unsetProperties. 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> = [] to filterTags: Set<String>? = nil in both ChannelController.partialChannelUpdate() and Chat.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 partialChannelUpdate without specifying filterTags preserves 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: Review filterTags threading in update/updatePartial (semantics & API shape)

The wiring itself looks correct: filterTags is 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:

  1. Partial update semantics / possible unintended clearing

    For updatePartial you 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 filterTags is non‑optional with default [], every call to updatePartial will pass a value for filterTags. If ChannelEditDetailPayload encodes 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> = [],
    
  •    filterTags: Set<String>? = nil,
       extraData: [String: RawJSON] = [:],
       unsetProperties: [String] = []
    
    ) async throws {
    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.
    
    
  1. Doc wording for full update

    For the full update method, 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 33906aa and f25a30e.

📒 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.swift
  • Tests/StreamChatTests/StateLayer/Chat_Tests.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • Sources/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.swift
  • Sources/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.swift
  • Tests/StreamChatTests/StateLayer/Chat_Tests.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • 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 Sources/StreamChat/**/*.swift : Ensure public API changes in StreamChat and StreamChatUI include inline documentation and migration notes

Applied to files:

  • DemoApp/StreamChat/Components/DemoChatChannelListRouter.swift
  • Tests/StreamChatTests/StateLayer/Chat_Tests.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • 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 CHANGELOG* : Update CHANGELOG entries for user-visible SDK changes in StreamChat and StreamChatUI

Applied to files:

  • DemoApp/StreamChat/Components/DemoChatChannelListRouter.swift
  • Tests/StreamChatTests/StateLayer/Chat_Tests.swift
  • Sources/StreamChat/Controllers/ChannelController/ChannelController.swift
  • 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:

  • 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 filterTags parameter for partialChannelUpdate. 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 cover filterTags propagation

The four added tests around channel updating look solid: they exercise both success and failure paths and assert that all relevant fields (including filterTags and unsetProperties) are forwarded to ChannelUpdater_Mock as 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 the ChannelEditDetailPayload.encode() method, which uses conditional encoding: empty filterTags sets 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.

@Stream-SDK-Bot
Copy link
Collaborator

SDK Size

title develop branch diff status
StreamChat 7.26 MB 7.26 MB 0 KB 🟢
StreamChatUI 4.89 MB 4.89 MB 0 KB 🟢

@github-actions
Copy link

github-actions bot commented Dec 1, 2025

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

@Stream-SDK-Bot
Copy link
Collaborator

StreamChat XCSize

Object Diff (bytes)
ChannelListPayload.o +620
Channel.o +304
ChannelListQuery.o +292
ChannelEditDetailPayload.o +263
ThreadListPayload.o +244
Show 15 more objects
Object Diff (bytes)
ThreadEndpoints.o +244
MutedChannelPayload.o +240
Thread.o +232
ChannelDTO.o +177
ChannelQuery.o +144
ChannelController.o +100
ChatClient+Factory.o +96
MessageReminder.o +84
ChannelUpdater.o +84
LivestreamChannelController.o +64
ChannelListLinker.o +60
ChatClient+ChannelController.o +56
Chat.o +56
ChannelCodingKeys.o +44
ChannelPayload+asModel.o +44

@Stream-SDK-Bot
Copy link
Collaborator

StreamChatUI XCSize

Object Diff (bytes)
QuotedChatMessageView.o -628
InputChatMessageView.o +252
ChatMessageDeliveryStatusView.o +224
ChatThreadListItemView.o +68
ChatMessageHeaderDecoratorView.o +48

@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 1, 2025

@laevandus laevandus merged commit fa38d7a into develop Dec 1, 2025
23 of 24 checks passed
@laevandus laevandus deleted the add/channel-filter-tags branch December 1, 2025 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants