Skip to content

fix: channels sorting with predefined filters#1747

Open
isekovanic wants to merge 3 commits into
masterfrom
fix/channels-sorting-with-predefined-filters
Open

fix: channels sorting with predefined filters#1747
isekovanic wants to merge 3 commits into
masterfrom
fix/channels-sorting-with-predefined-filters

Conversation

@isekovanic
Copy link
Copy Markdown
Contributor

CLA

  • I have signed the Stream CLA (required).
  • Code changes are tested

Description of the changes, What, Why and How?

This PR fixes ChannelManager list mutation behavior for queryChannels() calls that use options.predefined_filter.

Previously, predefined filter requests were sent correctly, but queryChannelsRequest() returned only data.channels, so the top level predefined_filter metadata from /channels was discarded. That metadata contains the backend resolved effective filter and sort. Without it, ChannelManager continued using only the original caller inputs for WS-driven list mutations.

For predefined queries, the caller input can be intentionally empty:

filters = {};
sort = [];
options = { predefined_filter: 'messaging_channels' };

while the backend may resolve the actual list semantics to:

  predefined_filter: {
    filter: { archived: false },
    sort: [{ field: 'pinned_at', direction: -1 }],
  }

Because ChannelManager did not have access to that resolved metadata, events such as message.new, notification.message_new, channel.visible and member.updated behaved as if archived and pinned handling was disabled. That could allow archived channels to be promoted into non-archived lists, unarchived channels to be promoted into archived lists or pinned channels to move when pinned_at sorting should keep them stable.

This PR adds an explicit full response query path:

queryChannelsRequestWithResponse()

The existing queryChannelsRequest() keeps its current behavior and still returns only raw channel API responses. queryChannels() also keeps returning Channel[] normally. When called with:

  stateOptions.withResponse = true

queryChannels() returns the full query response with hydrated channels:

  {
    ...queryChannelsResponse,
    channels: Channel[],
  }

ChannelManager then uses this internal withResponse path so it can read response.predefined_filter without changing the default public queryChannels() behaviour.

ChannelManager now keeps the original request inputs separate from the backend resolved response metadata through 2 new state properties:

  • responseFilters
  • responseSort

The original filters, sort and options remain the source of truth for pagination, loadNext(), retries, offline DB query context and preserving the existing pagination state semantics. The new responseFilters and responseSort are used only for local WS driven channel list mutation decisions (i.e when do we promote a channel and how).

The predefined filter response sort shape is:

[{ field: 'pinned_at', direction: -1 }]

but ChannelManager utilities expect ChannelSort:

[{ pinned_at: -1 }]

so we also convert the response sort before storing it as responseSort.

I also considered using the existing channels.queried event to pass this metadata to ChannelManager, however I decided against that for now because channels.queried is client wide and not scoped to a specific ChannelManager request. Without a request/correlation ID, multiple ChannelManagers or direct client.queryChannels() calls could very well race and attach resolved metadata to the wrong list. The metadata is also local list state, not general client state and event ordering would be fragile because ChannelManager updates pagination after its query resolves. The explicit withResponse return path keeps the data tied directly to the request that produced it.

Changelog

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

Size Change: +2.31 kB (+0.6%)

Total Size: 387 kB

📦 View Changed
Filename Size Change
dist/cjs/index.browser.js 129 kB +767 B (+0.6%)
dist/cjs/index.node.js 130 kB +771 B (+0.6%)
dist/esm/index.mjs 128 kB +774 B (+0.61%)

compressed-size-action

@isekovanic isekovanic changed the title Fix/channels sorting with predefined filters fix: channels sorting with predefined filters May 14, 2026
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.

2 participants