Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: threads 2.0 #1330

Merged
merged 42 commits into from
Sep 2, 2024
Merged

feat: threads 2.0 #1330

merged 42 commits into from
Sep 2, 2024

Conversation

arnautov-anton
Copy link
Contributor

@arnautov-anton arnautov-anton commented Jul 25, 2024

This PR adds two new classes: ThreadManager and Thread. These classes are designed to be used as "component backends" - the components being ThreadList and Thread respectively. To achieve easy integration with the UI framework, these classes expose state - a reactive state store you can subscribe to. Ideally, components contain no business logic and just subscribe to relevant parts of the state.

StateStore

This is an immutable store you can subscribe to. Get the latest value with getLatestValue(), update value with next or partialNext, subscribe with subscribe or subscribeWithSelector.

Thread

Thread loads, stores and paginates thread replies. It also keeps track of read states.

For some level of consistency with channel messages pagination indicators, we have a pagination object which stores cursors and loading indicators.

After calling registerSubscriptions, Thread instance starts listening to channel events. See a list of subscribe... methods to see which exact events we are listening to.

Thread can be active or inactive. This is a UI state - an integrator should mark visible/opened threads as active. Active thread immediately marks all the incoming messages as read.

Although backend supports a lot of query options for thread replies, we only support querying latest replies in chronological order, and then paginating through them. If we were to support all query options, we'd have to:

  1. Support message sets for replies like Channel does
  2. Implement complex pagination indicator logic

You are not likely to construct a Thread instance by yourself - you get by calling channel.getThread() instead.

ThreadManager

Loads, stores and paginates threads.

ThreadManager does its best to keep the order of threads in a list stable (which is a business requirement for the ThreadList component). So when a reply arrives in a thread which is not currently in a list, we don't load the thread - instead, we add it to the list of "unseen threads". The UI should then prompt user to reload the list if they require so.

Similarly, when a reply arrives in a thread which is already in the list, we don't reorder the list, but set a isThreadOrderStale flag.

ThreadManager makes sure that all Thread instances it stores are as up-to-date as possible.

Copy link
Contributor

github-actions bot commented Jul 25, 2024

Size Change: +33.5 kB (+8.57%) 🔍

Total Size: 425 kB

Filename Size Change
dist/browser.es.js 92.2 kB +7.4 kB (+8.73%) 🔍
dist/browser.full-bundle.min.js 54 kB +3.72 kB (+7.41%) 🔍
dist/browser.js 93.3 kB +7.5 kB (+8.75%) 🔍
dist/index.es.js 92.2 kB +7.41 kB (+8.73%) 🔍
dist/index.js 93.4 kB +7.5 kB (+8.74%) 🔍

compressed-size-action

@arnautov-anton arnautov-anton force-pushed the feat/threads-v2 branch 3 times, most recently from 4867084 to 6629c1d Compare August 1, 2024 08:59
src/store.ts Outdated Show resolved Hide resolved
myandrienko
myandrienko previously approved these changes Aug 29, 2024
src/thread_manager.ts Outdated Show resolved Hide resolved
myandrienko
myandrienko previously approved these changes Sep 2, 2024
oliverlaz
oliverlaz previously approved these changes Sep 2, 2024
@myandrienko myandrienko dismissed stale reviews from oliverlaz and themself via 226c03d September 2, 2024 15:05
@arnautov-anton arnautov-anton merged commit 4b1ffe8 into master Sep 2, 2024
5 checks passed
@arnautov-anton arnautov-anton deleted the feat/threads-v2 branch September 2, 2024 15:09
@github-actions github-actions bot mentioned this pull request Sep 2, 2024
arnautov-anton added a commit to GetStream/stream-chat-react that referenced this pull request Sep 4, 2024
🚂 GetStream/stream-chat-js#1330

This PR adds components for implementing a thread list view: ThreadList
and ChatView. It also adds support for reactive state stores, like the
ones that handle the thread list logic in the client.

## useStateStore

Implements a binding from the reactive state store in the client to
React components.

## ThreadList

Implements a thread list. The component itself consists mostly of
binding to the `ThreadManager` instance in the client.

## Thread

The Thread component was modified to optionally use a reactive `Thread`
instance from the `ThreadContext`. The component checks if
`ThreadContext` is provided, and if so uses the thread instance from
that context. Otherwise, it falls back to the `ChannelContext` as usual.

Currently, we use `ThreadContext` in the thread list view, where it is
provided by the `ChatView.ThreadAdapter` component.

Note that even when `ThreadContext` is used, `ChannelContext` also must
be provided. Most our components, including the ones used in threads,
still expect the channel context to be there.

## ChatView

A set of components implementing a simple in-memory router to switch
between channel view and thread list view. Using it is totally optional.
Most integrations will probably use their own router instead. Still,
nice to have something out-of-the-box.

## WithComponents

A new way to provide component overrides. Previously we allowed passing
component overrides as props to `Channel` component, and then in some
nested components as well, although not consistently.

`WithComponents` is a new recommended way to provide component
overrides, which requires far less prop drilling and nests nicely.

---------

Co-authored-by: Matvei Andrienko <m.y.andrienko@outlook.com>
arnautov-anton added a commit to GetStream/stream-chat-react that referenced this pull request Sep 4, 2024
🚂 GetStream/stream-chat-js#1330

This PR adds components for implementing a thread list view: ThreadList
and ChatView. It also adds support for reactive state stores, like the
ones that handle the thread list logic in the client.

Implements a binding from the reactive state store in the client to
React components.

Implements a thread list. The component itself consists mostly of
binding to the `ThreadManager` instance in the client.

The Thread component was modified to optionally use a reactive `Thread`
instance from the `ThreadContext`. The component checks if
`ThreadContext` is provided, and if so uses the thread instance from
that context. Otherwise, it falls back to the `ChannelContext` as usual.

Currently, we use `ThreadContext` in the thread list view, where it is
provided by the `ChatView.ThreadAdapter` component.

Note that even when `ThreadContext` is used, `ChannelContext` also must
be provided. Most our components, including the ones used in threads,
still expect the channel context to be there.

A set of components implementing a simple in-memory router to switch
between channel view and thread list view. Using it is totally optional.
Most integrations will probably use their own router instead. Still,
nice to have something out-of-the-box.

A new way to provide component overrides. Previously we allowed passing
component overrides as props to `Channel` component, and then in some
nested components as well, although not consistently.

`WithComponents` is a new recommended way to provide component
overrides, which requires far less prop drilling and nests nicely.

---------

Co-authored-by: Matvei Andrienko <m.y.andrienko@outlook.com>

BREAKING CHANGE: ComponentContext no longer provides any defaults
arnautov-anton added a commit to GetStream/stream-chat-react that referenced this pull request Sep 4, 2024
🚂 GetStream/stream-chat-js#1330

This PR adds components for implementing a thread list view: ThreadList
and ChatView. It also adds support for reactive state stores, like the
ones that handle the thread list logic in the client.

Implements a binding from the reactive state store in the client to
React components.

Implements a thread list. The component itself consists mostly of
binding to the `ThreadManager` instance in the client.

The Thread component was modified to optionally use a reactive `Thread`
instance from the `ThreadContext`. The component checks if
`ThreadContext` is provided, and if so uses the thread instance from
that context. Otherwise, it falls back to the `ChannelContext` as usual.

Currently, we use `ThreadContext` in the thread list view, where it is
provided by the `ChatView.ThreadAdapter` component.

Note that even when `ThreadContext` is used, `ChannelContext` also must
be provided. Most our components, including the ones used in threads,
still expect the channel context to be there.

A set of components implementing a simple in-memory router to switch
between channel view and thread list view. Using it is totally optional.
Most integrations will probably use their own router instead. Still,
nice to have something out-of-the-box.

A new way to provide component overrides. Previously we allowed passing
component overrides as props to `Channel` component, and then in some
nested components as well, although not consistently.

`WithComponents` is a new recommended way to provide component
overrides, which requires far less prop drilling and nests nicely.

BREAKING CHANGE: ComponentContext no longer provides any defaults

---------

Co-authored-by: Matvei Andrienko <m.y.andrienko@outlook.com>
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.

4 participants