Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions examples/vite/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
createCommandInjectionMiddleware,
createCommandStringExtractionMiddleware,
createDraftCommandInjectionMiddleware,
createPriorityOwnershipResolver,
SearchController,
UserSearchSource,
} from 'stream-chat';
Expand Down Expand Up @@ -123,6 +124,10 @@ if (!apiKey) {
// page size is a paginator concern and is passed via `paginatorOptions.pageSize` instead.
const CHANNELS_PAGE_SIZE = 10;

// Unlike the archived / muted / default lists, which are mutually exclusive buckets, the unread
// inbox is a view over them: a channel with unread messages belongs both here and in "My channels".
const UNREAD_LIST_ID = 'channels:unread';

const requestOptions: ChannelPaginatorRequestOptions = {
presence: true,
state: true,
Expand Down Expand Up @@ -370,7 +375,7 @@ const App = () => {
fallback.setItems({ isLastPage: true, valueOrFactory: [] });

// One state update for the whole set — inserting them one by one would publish (and re-render)
// four times.
// once per list.
channelManager.setPaginators([
new ChannelPaginator({
client: chatClient,
Expand All @@ -380,6 +385,15 @@ const App = () => {
requestOptions,
sort,
}),
new ChannelPaginator({
client: chatClient,
// `has_unread: false` is rejected by the API, so there is no "all read" counterpart
filters: { ...filters, archived: false, has_unread: true, muted: false },
id: UNREAD_LIST_ID,
paginatorOptions: { pageSize: CHANNELS_PAGE_SIZE },
requestOptions,
sort,
}),
new ChannelPaginator({
client: chatClient,
filters: { ...filters, archived: true },
Expand All @@ -395,13 +409,27 @@ const App = () => {
fallback,
]);

channelManager.setOwnershipResolver([
// Ownership is exclusive, so the unread list has to be granted outside the priority order —
// ranked, it would steal every unread channel out of "My channels"; unranked, the priority
// winner would evict it from the unread list instead.
const byPriority = createPriorityOwnershipResolver([
'channels:archived',
'channels:muted',
'channels:default',
'channels:opened',
]);

channelManager.setOwnershipResolver((params) => {
const buckets = params.matchingPaginators.filter(
(paginator) => paginator.id !== UNREAD_LIST_ID,
);
const owners = byPriority({ ...params, matchingPaginators: buckets });

return buckets.length === params.matchingPaginators.length
? owners
: [...owners, UNREAD_LIST_ID];
});

return () => {
// this app is the only one registering lists on the manager, so it can drop them all at once
channelManager.clearPaginators();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { ScrollToActiveChannelButton } from './ScrollToActiveChannelButton';
// this map lives here in the example rather than in the SDK.
const CHANNEL_LIST_LABELS: Record<string, string> = {
'channels:default': 'My channels',
'channels:unread': 'Unread',
'channels:archived': 'Archived',
'channels:muted': 'Muted',
'channels:opened': 'Opened',
Expand Down