Skip to content

Conversation

@isekovanic
Copy link
Contributor

@isekovanic isekovanic commented May 22, 2025

🎯 Goal

🛠️ Summary of Changes

📦 SDK Architecture and Offline Persistence Refactor

🧠 Major Restructuring

  • Moved all SDK logic and API handling into the LLC (Low-Level Client):
    • Centralizes logic and improves maintainability across platforms.
  • Offline DB initialization moved to the LLC abstract class:
    • Can now be initialized before rendering the Chat component.
    • Prevents reinitialization on Chat unmount/remount.
    • Ensures openConnection() is only called once per app session.

💬 Reactions: Rewritten for Consistency and Performance

  • Optimistic reaction updates fully reimplemented:
    • Properly respects enforce_unique.
    • Now handled entirely in LLC state (reaction.new, reaction.updated, reaction.removed).
    • Reactions are persisted to the DB (was previously memory-only).
  • Fetching and displaying reactions fixed:
    • Fetched optimistically from DB, then updated via HTTP.
    • Removed limit of 10 reactions stored offline.
    • Reaction pagination now supported in offline mode.
    • Updates are batched rather than run synchronously.

🔄 Channel Handling and Sync Reliability

  • Channel truncation fixes:
    • Read states are cleared correctly.
    • Messages are removed in efficient batches.
  • Faster and more reliable channel guards:
    • Eliminates extra DB query.
    • Prefers event.channel for state updates when available.
  • Visibility handling now updates DB rows instead of deleting them.
  • Sync API behavior revised:
    • No longer reprocesses events already sent by SDK.
    • Sync errors no longer block the entire SDK.
  • Callback scheduling added to sync manager:
    • Enables deferred state updates after sync completion.
    • Replaces unreliable listener-based sync logic.

📋 Channel List and Task Queue Improvements

  • ChannelListManager now fully resides in the LLC:
    • Prevents duplicate queryChannels requests (esp. on slower devices).
    • Introduces a scheduling system to control re-queries.
  • Pending task queue is now more stable and minimal:
    • Only queues failures — no more insert/remove jitter.
    • Tasks are dropped if retry is not viable (e.g., due to capability errors).
  • Safe (detached) write queries introduced:
    • Enables state updates in sync event handlers and non-async contexts.

🚀 New Features

  • Offline message sending support added:
    • Failed sends are queued and retried in order upon reconnect.
  • Support for channel pinning and archiving.
  • Soft and hard deletes now reflected in DB correctly.
  • channel.truncated_at is respected and synced.
  • Retry and error handling for queryChannels built into channelManager.

🧠 Performance and Stability Fixes

  • Read query performance improved (getChannels, getChannelsForQuery).
  • Member events now correctly update member_count.
  • All event handling now routed through LLC’s internal state (not WS listeners).
  • Only a single SQLite connection is used throughout:
    • Prevents issues from multi-writer scenarios in op-sqlite.
    • Previously, multiple Chat mounts could trigger multiple DB connections.

🛠 Implementation details

🎨 UI Changes

iOS
Before After
Android
Before After

🧪 Testing

☑️ Checklist

  • I have signed the Stream CLA (required)
  • PR targets the develop branch
  • Documentation is updated
  • New code is tested in main example apps, including all possible scenarios
    • SampleApp iOS and Android
    • Expo iOS and Android

isekovanic and others added 30 commits March 7, 2025 15:07
* feat: remove StreamChatGenerics and introduce interface merging

* fix: some of the outstanding todos

* chore: add default interfaces

* chore: remove SCG from sample app

* fix: remove redundant types

* fix: remove type module

* fix: change the way interface declaration is consumed

* fix: ignore ts complaints for interface declaration

* chore: migrate TypescriptMessagingApp away from SCG

* chore: migrate the Expo sample app away from SCG

* fix: commit missing files

* fix: revert mistaken change

* fix: add resolutions for symlinked libs
* feat: introduce support for expo-video

* fix: remove redundant test

* fix: add check for audio component
# Conflicts:
#	.github/workflows/sample-distribution.yml
#	package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayPresence.ts
#	package/src/components/ChannelPreview/hooks/useIsChannelMuted.ts
#	package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts
#	package/src/hooks/useTranslatedMessage.ts
# Conflicts:
#	examples/ExpoMessaging/yarn.lock
#	examples/SampleApp/ios/Podfile.lock
#	examples/SampleApp/yarn.lock
#	examples/TypeScriptMessaging/yarn.lock
#	package/expo-package/yarn.lock
#	package/native-package/yarn.lock
#	package/src/components/ChannelList/hooks/listeners/useUserPresence.ts
#	package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayPresence.ts
#	package/src/hooks/useSelectedChannelState.ts
# Conflicts:
#	package/expo-package/package.json
#	package/expo-package/yarn.lock
#	package/native-package/package.json
#	package/native-package/yarn.lock
#	package/src/components/ImageGallery/__tests__/ImageGalleryFooter.test.tsx
#	package/src/components/ImageGallery/components/AnimatedGalleryVideo.tsx
#	package/src/components/Message/Message.tsx
#	package/src/components/Message/MessageSimple/MessageSimple.tsx
#	package/src/components/Message/MessageSimple/MessageStatus.tsx
#	package/src/components/Message/hooks/useMessageActionHandlers.ts
#	package/src/components/MessageMenu/MessageReactionPicker.tsx
#	package/src/contexts/messageInputContext/__tests__/pickFile.test.tsx
#	package/src/contexts/messagesContext/MessagesContext.tsx
@isekovanic isekovanic requested review from khushal87 and oliverlaz May 22, 2025 13:57
@Stream-SDK-Bot
Copy link
Contributor

Stream-SDK-Bot commented May 22, 2025

SDK Size

title develop branch diff status
js_bundle_size 466 KB 459 KB -6759 B 🚀

Copy link
Member

@khushal87 khushal87 left a comment

Choose a reason for hiding this comment

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

Apart from the reviews above on some testing I found out a couple of bugs on my side. Not sure if you will be able to repro it but here are they:

  • Even when I have loaded the channels in the channel list after the 1st page(2nd or subsequent pages) when my internet was active, it doesn’t load if I turn off my internet connection and open the app again. I am not able to load the 2nd page. Seems like a bug. Only able to load the first page.
  • When your internet is off and you send some message they are in pending state for a long time(I think they should fail asap) after being sent, and when the connection recovers they are not resent instead you see them as a failed message. This is off, because if you are in the app and then you turn off your internet then it is sent as a failed message, but when you restart the app and send a message, it shows pending status for a long time.

@isekovanic
Copy link
Contributor Author

Thanks for the detailed review @khushal87 !

As discussed offline:

  1. This behaviour is by design, due to the fact that it is pointless to load more channels from the offline DB if we're going to overwrite them with the first query anyway. Once we move to indexed channelManagers in the future (and can reliably gather all of them) we can maybe revisit how we handle this, but if we do load more than the offset/limit combination we will either not be watching channels we are supposed to or the pagination will be broken (in terms of never covering those channels under queryChannels with watch: true.
  2. Well spotted, both of these issues are fixed in the latest build.

@khushal87
Copy link
Member

Overall, it looks fine after the testing. We will see if anything appears in the future and fix it subsequently. Great work @isekovanic 🚀

@isekovanic isekovanic merged commit 0d07522 into develop May 27, 2025
5 checks passed
@isekovanic isekovanic deleted the feat/offline-support-v2 branch May 27, 2025 12:36
@github-actions github-actions bot mentioned this pull request May 27, 2025
6 tasks
isekovanic added a commit that referenced this pull request May 27, 2025
* chore: modify gh workflows

* feat: removal of StreamChatGenerics (#2993)

* feat: remove StreamChatGenerics and introduce interface merging

* fix: some of the outstanding todos

* chore: add default interfaces

* chore: remove SCG from sample app

* fix: remove redundant types

* fix: remove type module

* fix: change the way interface declaration is consumed

* fix: ignore ts complaints for interface declaration

* chore: migrate TypescriptMessagingApp away from SCG

* chore: migrate the Expo sample app away from SCG

* fix: commit missing files

* fix: revert mistaken change

* fix: add resolutions for symlinked libs

* chore: remove support for react-native-document-picker (#3000)

* chore: add rc channel

* fix: typo in branch name

* chore: remove dryRun

* chore: bump stream-chat version to latest rc

* chore: bump stream-chat to latest

* feat: introduce expo-video support (#3010)

* feat: introduce support for expo-video

* fix: remove redundant test

* fix: add check for audio component

* fix: lint issues

* fix: different types inference with latest stream-chat changes

* chore(deps): update sample apps too

* fix: remove generics from new hook

* fix: remove remnants from SCG and fix missing types

* fix: lint issues

* fix: replace TouchableOpacity with Pressable

* fix: move to RN TouchableOpacity instead

* chore(deps): update peer deps

* chore: remove unused hooks

* chore: remove deps scope

* feat: move queryChannels events to LLC

* feat: move sync manager to LLC too

* chore: remove no longer used code

* chore: revert threads fix to move it to develop

* fix: lint issues

* feat: include sending reactions in llc

* feat: add delete reactions and fix sending reactions

* fix: adapt to new api

* feat: add hard and soft deletes in the db

* fix: remove await

* fix: ts errors

* feat: move app settings logic to LLC

* fix: non-unique reactions and db writes

* fix: move reaction removal updates to llc and update

* fix: bottom sheet closing on received reaction

* feat: implement selective fetching from offline db

* feat: move fetching reactions to llc

* fix: make reaction updates realtime

* fix: properly take enforced unique reactions into account

* feat: move poll db updates to llc

* chore: cleanup of redundant code

* fix: all instances of FormatMessageResponse in respect to the new llc changes

* chore: ref branch specifically

* fix: try clearing cache

* fix: remove cache clean

* fix: remove console.log

* fix: use latest commit

* fix: use latest rc of llc

* chore: use specific commit again

* fix: SCG remnants from merge

* fix: channel watching edge case

* fix: own reactions

* feat: sync api and reactions to sync api as well as ws

* perf: message simple perf improvements for swipe to reply

* chore: cleanupo

* fix: lint issues

* fix: lint issues

* fix: unify file and image types (#3050)

* fix: unify file and image types

* fix: refine types

* fix: remove props from auto complete input

* chore: update deps

* fix: failing tests and AutoCompleteInput type

* chore: update custom data module interfaces

* fix: change RNFile to FileReference as per latest client changes (#3061)

* fix: merge conflicts

* fix: remove MessageType type from the SDK

* fix: resolve conflicts from V7 branch

* fix: broken tests

* fix: useMessageActions remove reserved fields logic

* revert: useMessageActions change

* fix: confine readBy data to Message Status component

* fix: change date separator and group styles to ref

* feat: move new message handling to llc

* fix: add app changes

* feat: move message deleting to llc completely

* feat: fix test and move read events to llc

* fix: bump stream-chat to latest rc

* chore: bump stream-chat version to latest rc again

* fix: thread messages state not updating properly

* chore: change type to inferred one

* fix: set correct core lib versions

* chore: bump stream-chat to latest rc again

* chore: update sample app yarn.locks as well

* fix: lint issues

* feat: move members and message updated events to llc

* fix: keyboard taking full screen issue when the prefer cross-fade transition setting is enabled (#3073)

* fix: respect the hasCommand channel prop as well

* fix: keybaord taking full screen issue when the prefer cross-fade transition setting is enabled (#3072)

* fix: keybaord taking full screen issue when the prefer cross-fade transition setting is enabled

* chore: add delete channel api

* chore: bump stream-chat-js rc again

* chore: full reinstall after merge from develop

* fix: add back mistakenly removed mime dep

* feat: move channel updated, visibility and deleted events to llc

* feat: move more event handling to llc

* fix: channel guard queries and improve member tests

* feat: move truncated event to llc

* feat: reimplement channel manager handling and retry policy

* fix: muted channels not updating properly

* chore: cleanup

* fix: broken tests

* fix: broken tests and weird edge cases

* feat: add support for pinning and archiving in the offline db

* perf: parallelize getChannels

* feat: reimplement dropPendingTasks

* fix: make sure membership is part of members

* chore: update sample app

* fix: corrupt member response in membership

* fix: PN channel navigation

* chore: cleanup of old stuff

* chore: rename flush to execute

* fix: only process healthcheck event on first connection

* fix: white screen on opening channel from PN

* chore: extend truncation testsa

* fix: take reads into account in tests as well

* chore: add more tests for offline support

* chore: cover all reaction cases for offline mode

* chore: add mark unread tests and update read tests in db

* chore: add tests for updating message on reactions

* fix: tests happy path

* chore: add tests for send message pending tasks

* chore: remove logs and lint issues

* chore: add read checks for message.new as well

* chore: add test for own messages and read

* chore: cleanup

* chore: add stream-chat beta version

* chore: add gh workflow changes for app build

* fix: modify app settings fetching logic as per develop changes

* chore: remove console.log

* fix: remove redundant query

* fix: remove console.log again

* chore: bump stream chat offline beta version

* fix: critical message state mutation issue

* fix: properly handle failed messages in the offline case

* fix: error on offline msgs

* chore: bump stream-chat to latest beta

* fix: pr remarks

* chore: revert GH workflows and update sample apps

* chore: bump to actual stream-chat version and modify types

---------

Co-authored-by: Khushal Agarwal <[email protected]>
@github-actions github-actions bot mentioned this pull request May 27, 2025
6 tasks
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