Skip to content

Conversation

laevandus
Copy link
Contributor

@laevandus laevandus commented Aug 26, 2025

🔗 Issue Links

Resolves: IOS-1094

🎯 Goal

Channel list removes blocked channel on it is presented

📝 Summary

  • Any WS event which contains channel information can reset blocked state of a channel in channel lists what include blocked channels

🛠 Implementation

If there is a need for showing both blocked and unblocked channels (blocked are automatically hidden) then one needs to have a query looking like this:

filter: .and([
            .containMembers(userIds: [currentUserId]),
            .or([
                .and([.equal(.blocked, to: false), .equal(.hidden, to: false)]),
                .and([.equal(.blocked, to: true), .equal(.hidden, to: true)])
            ])
        ])

This works fine until blocked channel is opened which triggers notification.mark_read WS event which has channel data, but blocked field is nil. This triggered SDK to incorrectly setting isBlocked of the channel to false which in turn triggered removing it from the channel list.

🎨 Showcase

🧪 Manual Testing Notes

  1. Log in with user which has someone blocked (I used r2-d2 who has blocked anakin)
  2. Open channel list query picker and choose "Blocked Unblocked with Matching Hidden Channels"
  3. Open a 1:1 channel with blocked user
  4. Navigate back to channel list
    Result: that channel is still there.

☑️ 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

    • Added a demo filter to view channels where blocked and hidden states match (both on or both off).
  • Bug Fixes

    • Prevented channels from disappearing from the list when blocked channels are included.
    • Ensured blocked/hidden states remain consistent when update events omit those fields.
  • Tests

    • Added tests validating channel list behavior for blocked/hidden scenarios.
  • Chores

    • Updated data model defaults and test helpers to support optional blocked/hidden values.
  • Documentation

    • Added upcoming CHANGELOG entry describing the bug fix.

@laevandus laevandus requested a review from a team as a code owner August 26, 2025 06:52
@laevandus laevandus added 🐞 Bug An issue or PR related to a bug 🌐 SDK: StreamChat (LLC) Tasks related to the StreamChat LLC SDK labels Aug 26, 2025
Copy link

coderabbitai bot commented Aug 26, 2025

Walkthrough

Adds a demo app channel-list filter option for matching blocked/hidden channels, changes ChannelDTO saving to avoid overwriting isBlocked when payload.isBlocked is nil, updates test fixtures to allow optional blocked/hidden, adds a test ensuring blocked channels remain listed when events omit blocked/hidden, and updates the changelog.

Changes

Cohort / File(s) Summary
Demo app filter option
DemoApp/StreamChat/Components/DemoChatChannelListVC.swift
Adds blockedUnblockedWithHiddenChannelsQuery, a UI action to apply it, and a setter that replaces the active query.
Database save logic
Sources/StreamChat/Database/DTOs/ChannelDTO.swift
Removes the branch that forced dto.isBlocked = false when payload.isBlocked == nil, so dto.isBlocked is not overwritten when the payload omits the flag.
Core Data model
Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/.../contents
Sets ChannelDTO.isBlocked default value to NO; makes AttachmentDTO.id optional.
Test tools: channel payloads
TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift, TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift
Makes isBlocked optional in ChannelDetailPayload.dummy; adds blocked: Bool? and hidden: Bool? params to dummyPayload and threads them into payload creation; minor signature normalization for poll helpers.
State-layer tests
Tests/StreamChatTests/StateLayer/ChannelList_Tests.swift
Adds test_updatingChannels_whenBlockedAndUnblockedWithHiddenQuery and extends payload factory to set per-channel blocked/hidden flags; uses real updater to exercise save behavior.
Docs
CHANGELOG.md
Adds a “Fixed” entry under Upcoming referencing blocked channel deletion bug (PR #3794).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant DemoAppVC as DemoApp VC
  participant ChannelListCtrl as ChannelListController
  participant Backend
  participant DB as Database (ChannelDTO.saveChannel)

  User->>DemoAppVC: Select "Blocked/Unblocked with Matching Hidden" filter
  DemoAppVC->>ChannelListCtrl: replaceQuery(blocked/hidden composite)
  ChannelListCtrl->>Backend: Query channels
  Backend-->>ChannelListCtrl: Channel list payloads (with blocked/hidden)
  ChannelListCtrl->>DB: saveChannel(payload, via ChannelListQuery)
  note over DB: If payload.isBlocked == nil\nDO NOT overwrite existing dto.isBlocked
  DB-->>ChannelListCtrl: Persisted channels
  User->>DemoAppVC: Open a blocked channel
  Backend-->>ChannelListCtrl: Event (e.g., mark read) without blocked/hidden
  ChannelListCtrl->>DB: saveChannel(event payload, non-list context)
  note over DB: Missing flags leave dto.isBlocked/dto.isHidden unchanged
  DB-->>ChannelListCtrl: Channel remains blocked/hidden
  ChannelListCtrl-->>User: Channel stays in list
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Prevent blocked channel removal from list when opening, with composite blocked/hidden filter [IOS-1094]

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
AttachmentDTO.id made optional (Sources/StreamChat/Database/.../contents)` Changing AttachmentDTO.id optionality is unrelated to the IOS-1094 objective about blocked/hidden channel handling.
ChannelDTO.isBlocked default set to NO (Sources/StreamChat/Database/.../contents)` Adding a default DB value is a schema tweak not required by the linked issue; it's not directly referenced by IOS-1094.

Possibly related PRs

Suggested labels

🐞 Bug

Suggested reviewers

  • martinmitrevski
  • nuno-vieira

Poem

"I hop through lists with careful whisk,
blocked or hidden—no abrupt whisk.
When flags go missing, I hold tight,
channels stay put, through day and night.
A bunny nods: the fix feels right." 🐰✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • 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 577bdba and faf09d5.

📒 Files selected for processing (3)
  • CHANGELOG.md (1 hunks)
  • Sources/StreamChat/Database/DTOs/ChannelDTO.swift (0 hunks)
  • Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents (2 hunks)
💤 Files with no reviewable changes (1)
  • Sources/StreamChat/Database/DTOs/ChannelDTO.swift
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md
⏰ 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). (2)
  • GitHub Check: Build LLC + UI (Xcode 15)
  • GitHub Check: Metrics
🔇 Additional comments (2)
Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents (2)

52-52: DefaultValueString on isBlocked is effectively inert with the current scalar mapping—no action needed

The Core Data attribute for isBlocked is declared as Boolean with usesScalarValueType="YES", and the generated ChannelDTO property is a non‐optional Bool. In Core Data, scalar attributes default to false when no default value is specified, so removing defaultValueString="NO" would not introduce a true “nil = unknown” state:

  • Mapping of incoming payloads always sets dto.isBlocked when the payload includes a value, and the initial channel list payload always carries isBlocked (never omitted).
  • When events omit blocked, the code path guards on if let isBlocked = payload.isBlocked—so an existing state is preserved, independent of any default.

Tri‐state semantics (true/false/unknown) cannot be achieved without making the attribute object‐typed (e.g., an NSNumber by setting usesScalarValueType="NO") and adapting the generated Swift property to Bool?. If you genuinely need “unknown” as distinct from false, you’ll need to:

  • Change usesScalarValueType to NO in the model so the attribute is backed by an NSNumber?.
  • Update the ChannelDTO declaration to @NSManaged var isBlocked: NSNumber? (or bridge it to Bool?).
  • Adjust all mapping and model code to handle a nil state explicitly, rather than eliding it with ?? false.

As is, the default default (false) matches both the initial payload and the fallback in ChannelPayload+asModel (channelPayload.isBlocked ?? false), so removing the explicit default will not alter behavior.

Likely an incorrect or invalid review comment.


2-2: Model metadata bump only — migrations sanity check passed

  • Verified that Sources/StreamChat/Database/StreamChatModel.xcdatamodeld contains only the StreamChatModel.xcdatamodel subdirectory and no .xccurrentversion file, so there has been no change to the current model version.
  • Only the lastSavedToolsVersion and systemVersion attributes in the contents file were updated; there are no additions, removals, or modifications of entities or attributes.
  • As a result, the model version identifier remains unchanged and no lightweight migration will be triggered at runtime.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/blocked-hidden-channel-list-query

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@laevandus laevandus force-pushed the fix/blocked-hidden-channel-list-query branch from b9a417f to 577bdba Compare August 26, 2025 06:54
Copy link

github-actions bot commented Aug 26, 2025

Public Interface

🚀 No changes affecting the public interface.

@Stream-SDK-Bot
Copy link
Collaborator

Stream-SDK-Bot commented Aug 26, 2025

SDK Size

title develop branch diff status
StreamChat 8.09 MB 8.09 MB 0 KB 🟢
StreamChatUI 4.86 MB 4.86 MB -3 KB 🚀

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

🧹 Nitpick comments (7)
CHANGELOG.md (1)

9-10: Clarify the fix scope and trigger in the changelog entry

Current text is a bit vague. Consider making the trigger and impact explicit (WS event omitting blocked/hidden causing a channel to disappear from Channel List).

Proposed copy tweak:

- - Fix channel getting removed from channel list which includes blocked channels [#3794](https://github.com/GetStream/stream-chat-swift/pull/3794)
+ - Fix blocked 1:1 channels being removed from Channel List when a WebSocket event (e.g. `notification.mark_read`) omits `blocked`/`hidden` flags and the list includes blocked channels [#3794](https://github.com/GetStream/stream-chat-swift/pull/3794)
Sources/StreamChat/Database/DTOs/ChannelDTO.swift (1)

284-291: Add insertion-only default for isBlocked

We confirmed that every “event‐save” path calls

session.saveChannel(payload: )          // uses the overload with query: nil  
// or  
session.saveChannel(payload: , query: nil, cache: nil)

so query is always nil for WS events and the new branch will never run there. The suggested patch safely limits defaulting to channel‐list imports only:

     // Backend only returns a boolean
     // for blocked 1:1 channels on channel list query
     if let isBlocked = payload.isBlocked {
         dto.isBlocked = isBlocked
-    } else if query != nil {
-        dto.isBlocked = false
+    } else if query != nil, dto.isInserted {
+        // Only default for newly created rows during channel-list imports.
+        dto.isBlocked = false
     }

No other call sites pass a non-nil query, so existing channels won’t be accidentally unblocked.

TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift (1)

25-25: Optional isBlocked parameter: consider defaulting to nil for clarity

Making isBlocked optional is correct to model “field absent.” Defaulting it to false may hide intent at call sites. Defaulting to nil nudges tests to be explicit when the field should be present vs. omitted.

-        isBlocked: Bool? = false,
+        isBlocked: Bool? = nil,

If changing the default is risky for existing tests, keep it as-is but consider documenting that “nil means omitted by backend/event.”

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

52-60: Query looks good; minor readability nit: extract the paired condition

The filter is correct and mirrors the intended “blocked ⇔ hidden” pairing. For readability and reuse in this file, consider extracting the inner paired conditions into a small helper.

Example:

+    private var blockedHiddenParityFilter: Filter<ChannelListFilterScope> {
+        .or([
+            .and([.equal(.blocked, to: false), .equal(.hidden, to: false)]),
+            .and([.equal(.blocked, to: true),  .equal(.hidden, to: true)])
+        ])
+    }
-    lazy var blockedUnblockedWithHiddenChannelsQuery: ChannelListQuery = .init(
-        filter: .and([
-            .containMembers(userIds: [currentUserId]),
-            .or([
-                .and([.equal(.blocked, to: false), .equal(.hidden, to: false)]),
-                .and([.equal(.blocked, to: true), .equal(.hidden, to: true)])
-            ])
-        ])
-    )
+    lazy var blockedUnblockedWithHiddenChannelsQuery: ChannelListQuery = .init(
+        filter: .and([ .containMembers(userIds: [currentUserId]), blockedHiddenParityFilter ])
+    )

175-182: Rename action variable; title mentions “excluding deleted” which isn’t reflected in the filter

The variable name suggests “excluding deleted” and “UnBlocked” (mixed casing), but the filter neither references deletedAt nor adds special handling. The fetch request already excludes deleted channels by default.

-        let blockedUnBlockedExcludingDeletedChannelsAction = UIAlertAction(
-            title: "Blocked Unblocked with Matching Hidden Channels",
+        let blockedUnblockedWithHiddenChannelsAction = UIAlertAction(
+            title: "Blocked/Unblocked with Matching Hidden Channels",
             style: .default,
             handler: { [weak self] _ in
-                self?.title = "Blocked Unblocked with Matching Hidden Channels"
+                self?.title = "Blocked/Unblocked with Matching Hidden Channels"
                 self?.setBlockedUnblockedWithHiddenChannelsQuery()
             }
         )

And update its usage in the actions list (Line 252):

-                blockedUnBlockedExcludingDeletedChannelsAction,
+                blockedUnblockedWithHiddenChannelsAction,

268-274: Method naming is consistent; consider grouping “query setters” together and documenting them

Minor: You already follow a pattern with setXxxQuery(). Consider adding a brief doc comment explaining each query’s purpose for demo users scanning the code.

Tests/StreamChatTests/StateLayer/ChannelList_Tests.swift (1)

346-404: Solid regression test; add a state-layer assertion for the specific channel’s flags

The test validates DB and overall count. Add explicit assertions that the state-layer view of the same channel preserves isBlocked/isHidden, ensuring end-to-end correctness (DB → FRC → state).

@@
         let secondChannelDataAfterEvent = try env.client.databaseContainer.readSynchronously { session in
             try XCTUnwrap(session.channel(cid: secondChannel.cid)).asModel()
         }
         XCTAssertEqual(true, secondChannelDataAfterEvent.isBlocked, "State did not change")
         XCTAssertEqual(true, secondChannelDataAfterEvent.isHidden, "State did not change")
+        // Also assert the state-layer reflects the same flags for the specific channel.
+        let stateChannel = await channelList.state.channels.first(where: { $0.cid == secondChannel.cid })
+        XCTAssertEqual(true, stateChannel?.isBlocked)
+        XCTAssertEqual(true, stateChannel?.isHidden)
         await XCTAssertEqual(5, channelList.state.channels.count)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • 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 85234a6 and 577bdba.

📒 Files selected for processing (6)
  • CHANGELOG.md (1 hunks)
  • DemoApp/StreamChat/Components/DemoChatChannelListVC.swift (4 hunks)
  • Sources/StreamChat/Database/DTOs/ChannelDTO.swift (1 hunks)
  • TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift (1 hunks)
  • TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift (4 hunks)
  • Tests/StreamChatTests/StateLayer/ChannelList_Tests.swift (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Tests/StreamChatTests/StateLayer/ChannelList_Tests.swift (4)
Sources/StreamChat/Query/ChannelListQuery.swift (1)
  • containMembers (84-86)
TestTools/StreamChatTestTools/SpyPattern/Spy/APIClient_Spy.swift (1)
  • test_mockResponseResult (118-120)
TestTools/StreamChatTestTools/Mocks/StreamChat/Database/DatabaseSession_Mock.swift (2)
  • channel (400-402)
  • user (101-103)
TestTools/StreamChatTestTools/SpyPattern/Spy/DatabaseContainer_Spy.swift (1)
  • readSynchronously (162-172)
⏰ 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). (3)
  • GitHub Check: Automated Code Review
  • GitHub Check: Test LLC (Debug)
  • GitHub Check: Metrics
🔇 Additional comments (4)
Tests/StreamChatTests/StateLayer/ChannelList_Tests.swift (1)

549-565: Nice extensibility with per-channel blocked/hidden closures

This makes tests expressive and focused. No changes needed.

TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift (3)

194-195: Pass-through of optional blocked/hidden into ChannelPayload looks correct

Propagating blocked/hidden as optionals enables simulating both explicit values and field absence (nil). This aligns with the PR goal to prevent nil WS fields from overwriting existing state in tests.


414-416: Canonicalize Poll dictionaries to concrete types with empty defaults — LGTM

Switching to [String: RawJSON], [String: [PollVotePayload]], and [String: Int] with [:] defaults improves type clarity and reduces optional handling in tests.


506-506: No functional change

Looks like a harmless normalization; nothing to do.

@Stream-SDK-Bot
Copy link
Collaborator

SDK Performance

target metric benchmark branch performance status
MessageList Hitches total duration 10 ms 0.0 ms 100.0% 🔼 🟢
Duration 2.6 s 2.55 s 1.92% 🔼 🟢
Hitch time ratio 4 ms per s 0.0 ms per s 100.0% 🔼 🟢
Frame rate 75 fps 78.42 fps 4.56% 🔼 🟢
Number of hitches 1 0.0 100.0% 🔼 🟢

@@ -48,6 +48,16 @@ final class DemoChatChannelListVC: ChatChannelListVC {
.equal(.blocked, to: true)
])
]))

lazy var blockedUnblockedWithHiddenChannelsQuery: ChannelListQuery = .init(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this one? We already have:

lazy var allBlockedChannelsQuery: ChannelListQuery = .init(filter: .and([
        .containMembers(userIds: [currentUserId]),
        .or([
            .equal(.blocked, to: false),
            .equal(.blocked, to: true)
        ])
    ]))

This is the one customers would use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I learned was that they are going to use the one with blocked and hidden fields.

@@ -285,7 +285,7 @@ extension NSManagedObjectContext {
// for blocked 1:1 channels on channel list query
if let isBlocked = payload.isBlocked {
dto.isBlocked = isBlocked
} else {
} else if query != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this condition enough? I think it's better that this is only solved on the backend.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest I am not sure why the else part was added anyway. But there is a comment just above which seems to indicate that this is required. Ideally we wouldn't change the local state if payload does not have it. Currently I only change it in a way that it matches to the comment above. Maybe I should try to remove the else part completely. 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that could be dangerous too - if the backend just removes the field if you unblock someone.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the git history I found this comment, which still doesn't clarify the need for this fallback. I believe the existing isBlocked state should remain unchanged if a websocket event payload doesn’t include it, wdyt?

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 removed the else part and tested our manual regression testing test cases, all was good! Just in case added default value to the Core Data model as well since it did not have it before (looks mistake, but it was fine since ChannelDTO always updated this property).

@@ -49,7 +49,7 @@
<attribute name="hasUnreadSorting" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" optional="YES" attributeType="String"/>
<attribute name="imageURL" optional="YES" attributeType="URI"/>
<attribute name="isBlocked" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="isBlocked" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Safe if default value is set, but it is optional (since now ChannelDTO might not update the property anymore).

} else {
dto.isBlocked = false
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went through manual regression testing steps for blocked, and all was good.

@Stream-SDK-Bot
Copy link
Collaborator

SDK Size

title develop branch diff status
StreamChat 8.09 MB 8.09 MB 0 KB 🟢
StreamChatUI 4.86 MB 4.86 MB 0 KB 🟢

@martinmitrevski
Copy link
Contributor

@laevandus check the LLC test failures before merging

Copy link

@laevandus laevandus merged commit ccbe05e into develop Aug 28, 2025
23 of 24 checks passed
@laevandus laevandus deleted the fix/blocked-hidden-channel-list-query branch August 28, 2025 06:47
@Stream-SDK-Bot Stream-SDK-Bot mentioned this pull request Aug 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 Bug An issue or PR related to a bug 🌐 SDK: StreamChat (LLC) Tasks related to the StreamChat LLC SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants