Commit 57f41ff
Introduce message delivery receipts (#5979)
* Add ChatClient.markMessagesAsDelivered function to mark messages as delivered
* Add delivery receipts support to user privacy settings
* Introduce a initial DeliveryReceiptsManager to handle message delivery receipts
* Introduce MessageReceiptDao and MessageReceiptEntity for handling message receipts
* Introduce MessageReceipt model and repository for handling message delivery receipts
* Make MessageReceiptRepository `getAllByType` return a Flow and add a `clear` function
The `MessageReceiptRepository.getAllByType` function now accepts a `limit` parameter and returns a `Flow<List<MessageReceipt>>` instead of a `suspend` function returning `List<MessageReceipt>`.
A new `clear()` function has been added to `MessageReceiptRepository` to delete all receipts from the database.
* Refactor DeliveryReceiptsManager to store receipts locally
The `DeliveryReceiptsManager` has been renamed to `MessageReceiptManager`.
Instead of making a direct API call to mark messages as delivered, the manager now creates `MessageReceipt` objects and upserts them into the local `MessageReceiptRepository`. This change also refactors the corresponding tests to verify the local database interaction rather than the API call.
* Introduced `MessageReceiptReporter`, a new class responsible for observing the local database for delivery receipts and reporting them to the backend.
This reporter collects receipts in batches and sends them periodically to reduce network traffic. After a successful API call, the reported receipts are removed from the local database. New tests are included to verify this functionality.
* Prapare to move internal persistence to the client module
* Add ChatClientDatabase, DateConverter, and ChatClientRepository for message receipt management
* Refactor: Move message receipt logic to client
Moves the `MessageReceiptRepository` and related classes from the `stream-chat-android-offline` module to the `stream-chat-android-client` module. This refactoring centralizes persistence logic within the client module.
The moved classes have been renamed and their package structure updated. Method names within the repository have been made more specific (e.g., `upsert` is now `upsertMessageReceipts`). The `MessageReceiptRepository` is now an internal interface with a companion object factory.
* Support `message.delivered` event
This commit adds support for the `message.delivered` event, which is triggered when a message is marked as delivered.
The following changes are included:
- A new `MessageDeliveredEvent` data class.
- New fields (`last_delivered_at`, `last_delivered_message_id`) to the `ChannelUserRead` DTO and model.
- Logic to parse and map the `message.delivered` event from the backend DTO to the domain model.
* Refactor: Add default empty implementations for `QueryChannelsListener` interface instead
* Deprecate `hasUnread` in favor of `currentUserUnreadCount`
* Add `userRead` and `deliveredReads` helper functions
Extracted the logic for retrieving a user's read state into a new `Channel.userRead()` helper function. This simplifies the implementation of `countUnreadMentionsForUser` and `currentUserUnreadCount`.
Additionally, introduced `Channel.deliveredReads(message)` to get a list of users who have received a specific message.
* Introduce `markChannelsAsDelivered`, a new function to mark the last message in a list of channels as delivered. It contains logic to identify the appropriate message to mark as delivered, considering factors like whether the message is already read or delivered.
* Refactor MessageReceiptReporter to use a polling mechanism
Replaced the Flow-based implementation in `MessageReceiptReporter` with a `while(isActive)` loop and a `delay`. This change simplifies the logic for polling and reporting message delivery receipts.
The `getAllMessageReceiptsByType` function in `MessageReceiptRepository` and `MessageReceiptDao` is now a `suspend` function instead of returning a `Flow`.
The corresponding tests have been updated to reflect these changes.
* Moves the user ID update in the `switchUser` function to after the user is disconnected. This ensures that coroutines related to the previous user are properly cancelled before the new user connects.
* Rename MessageReceiptReporter.init to start and add logging
* Refactor MessageReceiptManagerTest to standardize verification methods for upsertMessageReceipts calls
* Automatically mark messages as delivered when querying channels
Introduced a `MessageDeliveredPlugin` that automatically marks messages as delivered upon a successful `queryChannels` call. This plugin is enabled by default.
* Introduce `ChatClientRepository` to encapsulate internal repositories used by `ChatClient`. This new repository is now a required dependency for `ChatClient`.
* Add MessageReceiptManager and MessageReceiptReporter to ChatClient
* Decoupled `MessageReceiptReporter` from `ChatClient` by passing `ChatApi` directly to its constructor. This simplifies dependencies and removes the need for `ChatClient` as an intermediary for API calls.
Updated tests to reflect this change, mocking `ChatApi` instead of `ChatClient`.
* Refactor ChatClientTest to simplify test setup
- Remove unused properties and simplify the `setUp` method.
- Make test properties `private`.
- Remove `runTest` from test function signatures as it's already handled by the `TestCoroutineExtension`.
* Rename deliveredReads to deliveredReadsOf
* feat: Add delivered status indicator for messages
This commit introduces a new "delivered" status for messages, which is displayed when a message has been delivered but not yet read.
**Key changes:**
- Added `isMessageDelivered` property to `MessageItemState` and `MessageListItem`.
- Introduced a new grey double-check icon (`stream_ui_ic_check_double_grey`) for the delivered state.
- Updated `ChannelListViewStyle` and `MessageListItemStyle` to include `indicatorDeliveredIcon`.
- The message status indicator logic in both UI Components and Compose has been updated to show the delivered icon between the "sent" and "read" states.
- Added a new `stream_ui_message_list_semantics_message_status_delivered` string for accessibility.
- In Compose, `MessageFooterStatusIndicator` is updated to accept `MessageFooterStatusIndicatorParams` to handle the new delivered state, deprecating the old signature.
* Fix flaky test
* Add more tests
* Feat: Add `Channel.readsOf()` extension function
Adds a `readsOf(message: Message)` extension function to the `Channel` class. This function returns a list of `ChannelUserRead` objects for users who have read the given message, excluding the message sender.
Also includes:
- Adding corresponding unit tests for the new function.
- Renaming `ChannelExtensionsTests.kt` to `ChannelExtensionTest.kt`.
- Migrating existing tests from `kluent` to `JUnit Jupiter` assertions.
* Add pending status indicator snapshot test
* Add unit test for MessageReceiptRepository instantiation
* Fix the message status indicator paddings
* Mark messages as delivered on push notification
* sonar lint
* Mark channel as delivered on query a single channel
* Provide a ChatClient lazily in ChatNotifications
* Hide the message status indicator when a message is deleted
* Do not expose ChatClient.markMessagesAsDelivered
* feat: Add delivery_events flag to Config
Added a `deliveryEventsEnabled` flag to the `Config` model. This allows disabling message delivery events on a per-channel basis. Delivery receipts will not be stored or sent if this flag is disabled in the channel configuration.
* Refactor: Improve message delivery receipts logic
This commit refactors the `MessageReceiptManager` to enhance the logic for marking messages as delivered.
Key changes include:
- Renaming `markMessagesAsDelivered(messages: List<Message>)` to `markMessageAsDelivered(message: Message)` and making it the public API. The old function is now private and handles batch processing.
- Before marking a message as delivered, the manager now fetches the corresponding channel from the local repository or the API to ensure all conditions are met.
- The responsibility of filtering messages that can be marked as delivered is moved into a new private function `canMarkMessageAsDelivered`.
- Test cases have been updated to reflect these changes and improve coverage.
* Add DELIVERY_EVENTS to ChannelCapabilities
* Refactor: Make MessageReceiptManager functions suspend
The `MessageReceiptManager` is refactored to use `suspend` functions instead of launching new coroutines from a provided `CoroutineScope`. This simplifies the class by removing the need for an injected scope and improves testability.
Key changes:
- `markChannelsAsDelivered` and `markMessageAsDelivered` are now `suspend` functions.
- The `CoroutineScope` dependency has been removed from `MessageReceiptManager` and its initialization in `ChatClient`.
- `MessageDeliveredPlugin` is updated to use `onSuccessSuspend` to call the new suspend functions.
- `ChatNotificationsImpl` now launches a coroutine to call the suspend function `markMessageAsDelivered`.
- Tests are updated to use `verifyBlocking` for testing suspend functions and to provide the necessary `CoroutineScope` where required.
* Refactor: Lazy initialize messageReceiptManager in MessageDeliveredPlugin and ChatClient
* Fix: Fetch message from API when marking as delivered by ID
When `markMessageAsDelivered` is called with a `messageId`, the SDK now fetches the message from the local repository. If the message is not found locally, it falls back to fetching it from the API.
This ensures that a delivery receipt can be sent for a push notification even if the message is not yet in the local database.
* Skip sending delivery receipts for shadowed messages and muted users
This change prevents sending message delivery receipts for messages that are either shadowed or sent by a user who has been muted by the current user.
* Add deliveryEventsEnabled to channel configuration and mapping
* Add message info option to message menu
* Extra PaneTitle and PaneRow components for reusing
* Add message info component to display read and delivered status
* Stop using kluent assertions
* Update read and delivered status checks to include equal comparison
* Add user profile privacy settings screen
* Add privacy settings mapping to domain model
* Fix message info component to display read and delivered timestamps correctly
* typo
* CHANGELOG
* Change userRead function visibility to internal
* Use getCreatedAtOrDefault
* Remove MessageReceipt's 'type' field
* Move MessageReceiptRepositoryImpl to the same file as MessageReceiptRepository
* Fix tests after rebased from develop
* Update User.mergePartially to conditionally merge based on update timestamps
* Store UserMuteEntity properly
* Refactor event handling to consolidate user updates
* Refactor `MessageReceiptManager` to fetch the current user from the repository
* Refactor: Lazily inject RepositoryFacade into MessageReceiptManager
* Expose `markMessageAsDelivered` and allow custom handling of incoming push messages before they are processed by the SDK.
* Enhance UserRepositoryTests: Add tests for user insertion and selection with privacy settings and mutes
* improve test coverage
* Rename `onNewPushMessage` to `onNewMessage` to keep consistency between SDKs
* Stop using kluent
* Refactor markMessageAsDelivered methods to return Boolean indicating success or failure
* Check for the `MESSAGE_NEW` event type before marking a message as delivered.
* Add unit tests for MessagingStyleNotificationHandler
* Remove timestamps of the read and delivered members since the timestamp is always related to the latest message in the channel, and not for each message individually.
* kdoc
* Check for the `MESSAGE_NEW` event type before marking a message as delivered.
* Add unit tests for NotificationHandlerFactory
---------
Co-authored-by: Petar Velikov <[email protected]>1 parent d9c13ea commit 57f41ff
File tree
143 files changed
+4850
-504
lines changed- stream-chat-android-client-test/src/main/java/io/getstream/chat/android/client/test
- stream-chat-android-client
- api
- src
- main/java/io/getstream/chat/android/client
- api2
- endpoint
- mapping
- model
- dto
- requests
- api
- channel
- events
- extensions
- internal
- notifications
- handler
- parser2/adapters
- persistence
- db
- converter
- dao
- entity
- repository
- plugin
- listeners
- receipts
- utils
- test/java/io/getstream/chat/android/client
- api2
- mapping
- chatclient
- debugger
- extensions
- notifications
- handler
- parser2/testdata
- persistence
- db/converter
- repository
- plugin
- receipts
- utils
- observable
- stream-chat-android-compose-sample/src/main
- java/io/getstream/chat/android/compose/sample
- ui
- component
- profile
- res/values
- stream-chat-android-compose
- api
- src
- main/java/io/getstream/chat/android/compose/ui
- channels/list
- components
- channels
- messages
- theme
- test
- kotlin/io/getstream/chat/android/compose/ui/channels
- snapshots/images
- stream-chat-android-core
- api
- src
- main/java/io/getstream/chat/android
- models
- testFixtures/kotlin/io/getstream/chat/android
- stream-chat-android-offline/src
- main/java/io/getstream/chat/android/offline/repository
- database
- converter/internal
- internal
- domain
- channelconfig/internal
- channel/userread/internal
- user/internal
- test/java/io/getstream/chat/android/offline
- repository
- database/converter
- stream-chat-android-state/src
- main/java/io/getstream/chat/android/state
- event/handler/internal
- utils
- plugin
- logic/channel/internal
- state/channel/internal
- test/java/io/getstream/chat/android/state
- event/handler/internal/utils
- plugin
- logic/channel/internal
- state/channel/internal
- stream-chat-android-ui-common
- api
- src/main
- kotlin/io/getstream/chat/android/ui/common
- feature/messages/list
- state/messages/list
- utils/extensions
- res/values
- stream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/application
- stream-chat-android-ui-components
- api
- src
- main
- kotlin/io/getstream/chat/android/ui
- feature
- channels/list
- adapter/viewholder/internal
- messages/list
- adapter
- viewholder/decorator/internal
- utils/extensions
- res
- drawable
- values
- test/kotlin/io/getstream/chat/android/ui
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
143 files changed
+4850
-504
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
20 | 24 | | |
21 | 25 | | |
| 26 | + | |
22 | 27 | | |
23 | 28 | | |
24 | 29 | | |
| |||
3613 | 3618 | | |
3614 | 3619 | | |
3615 | 3620 | | |
3616 | | - | |
| 3621 | + | |
3617 | 3622 | | |
3618 | 3623 | | |
3619 | 3624 | | |
| |||
Lines changed: 21 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| |||
260 | 261 | | |
261 | 262 | | |
262 | 263 | | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
263 | 284 | | |
264 | 285 | | |
265 | 286 | | |
| |||
Lines changed: 56 additions & 10 deletions
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
92 | 92 | | |
93 | 93 | | |
94 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
95 | 99 | | |
96 | 100 | | |
97 | 101 | | |
| |||
106 | 110 | | |
107 | 111 | | |
108 | 112 | | |
| 113 | + | |
109 | 114 | | |
110 | 115 | | |
| 116 | + | |
111 | 117 | | |
112 | 118 | | |
113 | 119 | | |
| |||
Lines changed: 81 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
122 | 122 | | |
123 | 123 | | |
124 | 124 | | |
| 125 | + | |
| 126 | + | |
125 | 127 | | |
| 128 | + | |
126 | 129 | | |
127 | 130 | | |
128 | 131 | | |
129 | 132 | | |
130 | 133 | | |
| 134 | + | |
| 135 | + | |
131 | 136 | | |
132 | 137 | | |
133 | 138 | | |
| |||
275 | 280 | | |
276 | 281 | | |
277 | 282 | | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
278 | 286 | | |
279 | 287 | | |
280 | 288 | | |
| |||
447 | 455 | | |
448 | 456 | | |
449 | 457 | | |
450 | | - | |
451 | | - | |
452 | | - | |
453 | | - | |
| 458 | + | |
454 | 459 | | |
| 460 | + | |
455 | 461 | | |
456 | 462 | | |
| 463 | + | |
| 464 | + | |
457 | 465 | | |
458 | 466 | | |
459 | 467 | | |
| |||
642 | 650 | | |
643 | 651 | | |
644 | 652 | | |
| 653 | + | |
645 | 654 | | |
646 | 655 | | |
647 | 656 | | |
| |||
737 | 746 | | |
738 | 747 | | |
739 | 748 | | |
740 | | - | |
741 | 749 | | |
742 | 750 | | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
743 | 754 | | |
744 | 755 | | |
745 | 756 | | |
| |||
1505 | 1516 | | |
1506 | 1517 | | |
1507 | 1518 | | |
| 1519 | + | |
| 1520 | + | |
1508 | 1521 | | |
1509 | 1522 | | |
1510 | 1523 | | |
| |||
2869 | 2882 | | |
2870 | 2883 | | |
2871 | 2884 | | |
| 2885 | + | |
| 2886 | + | |
| 2887 | + | |
| 2888 | + | |
| 2889 | + | |
| 2890 | + | |
| 2891 | + | |
| 2892 | + | |
| 2893 | + | |
| 2894 | + | |
| 2895 | + | |
| 2896 | + | |
| 2897 | + | |
| 2898 | + | |
| 2899 | + | |
| 2900 | + | |
| 2901 | + | |
| 2902 | + | |
| 2903 | + | |
| 2904 | + | |
| 2905 | + | |
| 2906 | + | |
| 2907 | + | |
| 2908 | + | |
| 2909 | + | |
| 2910 | + | |
| 2911 | + | |
| 2912 | + | |
| 2913 | + | |
| 2914 | + | |
| 2915 | + | |
| 2916 | + | |
| 2917 | + | |
| 2918 | + | |
| 2919 | + | |
| 2920 | + | |
| 2921 | + | |
2872 | 2922 | | |
2873 | 2923 | | |
2874 | 2924 | | |
| |||
4716 | 4766 | | |
4717 | 4767 | | |
4718 | 4768 | | |
4719 | | - | |
| 4769 | + | |
| 4770 | + | |
4720 | 4771 | | |
4721 | 4772 | | |
4722 | 4773 | | |
| |||
4732 | 4783 | | |
4733 | 4784 | | |
4734 | 4785 | | |
| 4786 | + | |
| 4787 | + | |
| 4788 | + | |
4735 | 4789 | | |
4736 | | - | |
4737 | | - | |
4738 | | - | |
4739 | | - | |
4740 | | - | |
| 4790 | + | |
| 4791 | + | |
| 4792 | + | |
| 4793 | + | |
| 4794 | + | |
4741 | 4795 | | |
4742 | 4796 | | |
4743 | 4797 | | |
| |||
4755 | 4809 | | |
4756 | 4810 | | |
4757 | 4811 | | |
| 4812 | + | |
| 4813 | + | |
| 4814 | + | |
| 4815 | + | |
| 4816 | + | |
| 4817 | + | |
| 4818 | + | |
| 4819 | + | |
| 4820 | + | |
| 4821 | + | |
| 4822 | + | |
| 4823 | + | |
4758 | 4824 | | |
4759 | 4825 | | |
4760 | 4826 | | |
| |||
4799 | 4865 | | |
4800 | 4866 | | |
4801 | 4867 | | |
4802 | | - | |
| 4868 | + | |
| 4869 | + | |
| 4870 | + | |
| 4871 | + | |
4803 | 4872 | | |
4804 | 4873 | | |
4805 | 4874 | | |
| |||
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
338 | 338 | | |
339 | 339 | | |
340 | 340 | | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
341 | 346 | | |
342 | 347 | | |
343 | 348 | | |
| |||
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
60 | 61 | | |
61 | 62 | | |
62 | 63 | | |
| |||
960 | 961 | | |
961 | 962 | | |
962 | 963 | | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
963 | 969 | | |
964 | 970 | | |
965 | 971 | | |
| |||
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
| |||
211 | 212 | | |
212 | 213 | | |
213 | 214 | | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
214 | 220 | | |
Lines changed: 12 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| 27 | + | |
26 | 28 | | |
27 | 29 | | |
28 | 30 | | |
| |||
309 | 311 | | |
310 | 312 | | |
311 | 313 | | |
| 314 | + | |
312 | 315 | | |
313 | 316 | | |
314 | 317 | | |
| |||
525 | 528 | | |
526 | 529 | | |
527 | 530 | | |
| 531 | + | |
| 532 | + | |
528 | 533 | | |
529 | 534 | | |
530 | 535 | | |
| |||
599 | 604 | | |
600 | 605 | | |
601 | 606 | | |
| 607 | + | |
602 | 608 | | |
603 | 609 | | |
604 | 610 | | |
| |||
675 | 681 | | |
676 | 682 | | |
677 | 683 | | |
| 684 | + | |
678 | 685 | | |
679 | 686 | | |
680 | 687 | | |
| |||
685 | 692 | | |
686 | 693 | | |
687 | 694 | | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
688 | 700 | | |
689 | 701 | | |
690 | 702 | | |
| |||
0 commit comments