Skip to content

Conversation

@Stream-SDK-Bot
Copy link
Collaborator

StreamChat

✅ Added

  • Add support for message delivered info #3846
    • Add ChatRemoteNotificationHandler.markMessageAsDelivered(deliveries:)
    • Add ChatChannel.reads(message:) and ChatChannel.deliveredReads(message:)
    • Add ChatChannelRead.lastDeliveredAt
    • Add ChatChannelRead.lastDeliveredMessageId
    • Add MessageDeliveryStatus.delivered

🐞 Fixed

  • Fix ChannelController.hasLoadedAllPreviousMessages not correct for newly created channels #3855
  • Fix duplicated watch channel requests when a channel is created and it belongs to multiple queries #3857
  • Fix calling watch channel request when a channel is updated and it already belongs to another query #3857
  • Fix syncing error when trying to sync too many channels #3863

🔄 Changed

  • Deprecated ChatMessage.deliveryStatus in favour of ChatMessage.deliveryStatus(channel:) #3846

StreamChatUI

✅ Added

  • Display double grey checkmark when delivery events are enabled #3846

🐞 Fixed

  • Fix date separator not shown on newly created channel #3855
  • Fix composer deleting newly entered text after deleting draft text #3854

Stream Bot and others added 8 commits October 22, 2025 15:53
…3854)

* Fix new input text in the composer deleted after quickly deleting previous text from draft

* Update CHANGELOG.md
* Fix date separator not shown on newly created channel

* Update CHANGELOG.md

* Fix test with pagination
…t belongs to multiple queries (#3857)

* Track ongoing watch channel requests to avoid duplicate watch channels

* Update CHANGELOG.md

* Update CHANGELOG.md

* Rename to `ChannelWatchingActiveRequests`

* Introduce a `ChannelWatcherHandler`

* Fix ChannelListController_Tests
* Add Channel Delivered endpoint and payloads

* Add `CurrentChatUserController.markChannelsDelivered()`

* Handle marking channels as delivered in the ChannelListController

* Add `lastDeliveredAt` and `lastDeliveredMessageId` properties

* Add `ChannelDeliveredMiddleware`

* Message delivered event handling

* Add example to the demo app to view the delivery info

* Fix handling delivered event tests

* Mark message as delivered in the demo app when a push is received

Expose markMessageAsDelivered in chat notification handler

* Fix AppConfigViewController incorrect delivery flag name

* Simplify notification service

* Improve the naming of getting the message of a channel to be marked as delivered

* Rename markChannelsDelivered -> markMessagesAsDelivered

* Improve the channel delivered middleware safeness

* Add a `ChannelDeliveryTracker` to handle only the throttling and submitting channels for delivery

* Use the tracker in the notification service

* Make sure to update the latest message whenever it is delivered to a user

* Add documentation to latestMessageNotMarkedAsDelivered()

* Update CHANGELOG.md

* Fix forgotten super call in demo app code

* Change the type of `latestMessageNotMarkedAsDelivered` to `ChatMessage`

* Add `ChatChannel.reads(message:)` and `ChatChannel.deliveredReads(message:)`

* Update CHANGELOG.md

* Make the `DemoMessageReadsInfoView` live updated

* Remove delivery tracker from Push Notification Service

Since the NSE is spawned fresh everytime it can't have in-memory state

* Change Message Events to classes to improve SDK size

* Add sorting tie breaker to the reads info view

* Cancel message delivery if it was delivered from another device of the current user

* Add `ChatChannelConfig.deliveredEventsEnabled`

* Centralize logic to check if a message can be marked as delivered

* Fix tests with new canMarkMessageAsDelivered logic

* Add user delivery receipts settings

* Use the privacy settings to check canMarkasDelivered

* Fix UI tests not compiling

* Update CHANGELOG.md

* Fix wrong config name

* Make the notifcation handler safer

* Remove `CurrentUserController.markMessageAsDelivered()` since it should not be exposed.

* Remove `ChatChannel.latestUndeliveredMessage`

* Add `MessageDeliveryCriteriaValidator`

* Fix default privacy setting value

* Self review changes

* Comparison dates robostuness

* Remove outdated documentation

* Fix deliveredReads sometimes not returning when message was indeed delivered

* Make SwiftUI ENV the default of the Demo App

* Add `MessageDeliveryStatus.delivered` + Double grey checkmark when message is delivered

* Add test coverage to the new delivered status

* Update CHANGELOG.md

* Fix ChannelConfig mock in tests

* AI Code review changes

* Fix channel list controller tests

* Update CHANGELOG.md

* [CI] Snapshots (#3864)

Co-authored-by: Stream Bot <[email protected]>

* Move delivered reload cell to the SDK

* Only refresh last cell if needed

* Fix e2e tests api key issue (#3865)

* Revert channel config mock tests for E2E Tests

* Revert "Make SwiftUI ENV the default of the Demo App"

This reverts commit df89bc7.

---------

Co-authored-by: Stream SDK Bot <[email protected]>
Co-authored-by: Stream Bot <[email protected]>
Co-authored-by: Alexey Alter-Pesotskiy <[email protected]>
@Stream-SDK-Bot Stream-SDK-Bot requested a review from a team as a code owner November 5, 2025 12:21
@coderabbitai
Copy link

coderabbitai bot commented Nov 5, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch release/4.92.0

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Stream-SDK-Bot
Copy link
Collaborator Author

SDK Performance

target metric benchmark branch performance status
MessageList Hitches total duration 10 ms 5.01 ms 49.9% 🔼 🟢
Duration 2.6 s 2.54 s 2.31% 🔼 🟢
Hitch time ratio 4 ms per s 1.98 ms per s 50.5% 🔼 🟢
Frame rate 75 fps 77.99 fps 3.99% 🔼 🟢
Number of hitches 1 0.6 40.0% 🔼 🟢

@github-actions
Copy link

github-actions bot commented Nov 5, 2025

Build for regression testing №123457101 has been uploaded to TestFlight 🎁

@github-actions
Copy link

github-actions bot commented Nov 5, 2025

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

@Stream-SDK-Bot
Copy link
Collaborator Author

StreamChat XCSize

Object Diff (bytes)
MessageEvents.o -461607
ChatRemoteNotificationHandler.o +13546
MemberController.o -11376
ChannelDeliveredPayload.o +7086
ChannelDeliveryTracker.o +6146
Show 54 more objects
Object Diff (bytes)
MessageEditor.o -5988
ChannelWatcherHandler.o +4693
ChannelListLinker.o +4439
ChannelList.o +3531
ChannelListController.o +2927
MessageDeliveryCriteriaValidator.o +2640
ChannelDeliveredMiddleware.o +2505
WebSocketConnectPayload.o +2351
Channel.o +2112
EndpointPath.o +1965
ChannelRead.o +1834
ChannelListPayload.o +1771
ChatMessage.o +1560
ChannelListState.o -1443
Logger.o +1322
ChatClient+Environment.o +1287
EventPayload.o +1275
CurrentUserController.o -1235
ChannelListState+Observer.o -1216
DeliveredMessageInfo.o +1166
ChannelController.o +1144
ErrorPayload.o +836
ThreadQuery.o +716
ChannelReadDTO.o +714
MessageSearchQuery.o +660
SyncOperations.o +648
CurrentUserUpdater.o +612
ReminderPayloads.o +464
ChatClient.o +449
Chat.o +436
MemberPayload.o -412
UserInfo.o +381
Deprecations.o +316
MessagesPaginationStateHandling.o +260
MessageSender.o -258
ChatMessageVideoAttachment.o +256
ManualEventHandler.o -252
AnyAttachmentPayload.o +220
CurrentUserDTO.o +218
ConnectionRepository.o +212
EventType.o +198
ChatClientFactory.o +172
ChannelConfigDTO.o +162
EventsController.o +160
ChannelPayload+asModel.o +136
MessageController.o +104
UserPayloads.o +92
ChannelDTO.o +88
ChannelUpdater.o -80
LivestreamChannelController.o -72
CurrentUser.o +68
DatabaseSession.o +68
SyncRepository.o +60
PollVoteListController.o +48

@Stream-SDK-Bot
Copy link
Collaborator Author

StreamChatUI XCSize

Object Diff (bytes)
ChatThreadVC.o -460
ChatChannelListItemView.o +136
ChatMessageLayoutOptionsResolver.o +92
ChatMessageDeliveryStatusCheckmarkView.o +52
ChatChannelVC.o -44

@Stream-SDK-Bot
Copy link
Collaborator Author

SDK Size

title previous release current release diff status
StreamChat 7.88 MB 7.88 MB 0 KB 🟢
StreamChatUI 4.89 MB 4.89 MB 0 KB 🟢

@github-actions
Copy link

github-actions bot commented Nov 5, 2025

Build for regression testing №123457102 has been uploaded to TestFlight 🎁

@github-actions
Copy link

github-actions bot commented Nov 5, 2025

Public Interface

+ public class MessageReadEvent: ChannelSpecificEvent  
+ 
+   public let user: ChatUser
+   public var cid: ChannelId
+   public let channel: ChatChannel
+   public let thread: ChatThread?
+   public let createdAt: Date
+   public let unreadCount: UnreadCount?

+ public class MessageNewEvent: ChannelSpecificEvent, HasUnreadCount  
+ 
+   public let user: ChatUser
+   public let message: ChatMessage
+   public var cid: ChannelId
+   public let channel: ChatChannel
+   public let createdAt: Date
+   public let watcherCount: Int?
+   public let unreadCount: UnreadCount?

+ public class MessageDeliveredEvent: ChannelSpecificEvent  
+ 
+   public let user: ChatUser
+   public var cid: ChannelId
+   public let channel: ChatChannel
+   public let createdAt: Date
+   public let lastDeliveredMessageId: MessageId
+   public let lastDeliveredAt: Date

+ public class MessageUpdatedEvent: ChannelSpecificEvent  
+ 
+   public let user: ChatUser
+   public var cid: ChannelId
+   public let channel: ChatChannel
+   public let message: ChatMessage
+   public let createdAt: Date

+ public struct MessageDeliveryInfo: Equatable  
+ 
+   public let channelId: ChannelId
+   public let messageId: MessageId
+   
+ 
+   public init(channelId: ChannelId,messageId: MessageId)

+ public struct DeliveryReceiptsPrivacySettings  
+ 
+   public var enabled: Bool
+   
+ 
+   public init(enabled: Bool = true)

+ public class NewMessagePendingEvent: ChannelSpecificEvent  
+ 
+   public var message: ChatMessage
+   public var cid: ChannelId

+ public class MessageDeletedEvent: ChannelSpecificEvent  
+ 
+   public let user: ChatUser?
+   public var cid: ChannelId
+   public let channel: ChatChannel
+   public let message: ChatMessage
+   public let createdAt: Date
+   public let isHardDelete: Bool
+   public let deletedForMe: Bool

+ public class NewMessageErrorEvent: ChannelSpecificEvent  
+ 
+   public let messageId: MessageId
+   public let cid: ChannelId
+   public let error: Error

- public struct NewMessageErrorEvent: ChannelSpecificEvent  
- 
-   public let messageId: MessageId
-   public let cid: ChannelId
-   public let error: Error

- public struct MessageNewEvent: ChannelSpecificEvent, HasUnreadCount  
- 
-   public let user: ChatUser
-   public let message: ChatMessage
-   public var cid: ChannelId
-   public let channel: ChatChannel
-   public let createdAt: Date
-   public let watcherCount: Int?
-   public let unreadCount: UnreadCount?

- public struct MessageReadEvent: ChannelSpecificEvent  
- 
-   public let user: ChatUser
-   public var cid: ChannelId
-   public let channel: ChatChannel
-   public let thread: ChatThread?
-   public let createdAt: Date
-   public let unreadCount: UnreadCount?

- public struct MessageUpdatedEvent: ChannelSpecificEvent  
- 
-   public let user: ChatUser
-   public var cid: ChannelId
-   public let channel: ChatChannel
-   public let message: ChatMessage
-   public let createdAt: Date

- public struct MessageDeletedEvent: ChannelSpecificEvent  
- 
-   public let user: ChatUser?
-   public var cid: ChannelId
-   public let channel: ChatChannel
-   public let message: ChatMessage
-   public let createdAt: Date
-   public let isHardDelete: Bool
-   public let deletedForMe: Bool

- public struct NewMessagePendingEvent: ChannelSpecificEvent  
- 
-   public var message: ChatMessage
-   public var cid: ChannelId

 open class ChatMessageDeliveryStatusView: _Control, ThemeProvider  
-     
+     public var deliveryStatus: MessageDeliveryStatus?
-   
+     
-     public init(message: ChatMessage,channel: ChatChannel)
+   
+     public init(message: ChatMessage,channel: ChatChannel)

 public struct MessageDeliveryStatus: RawRepresentable, Hashable  
-   public static let read
+   public static let delivered
-   public static let failed
+   public static let read
-   
+   public static let failed
- 
+   
-   public init(rawValue: String)
+ 
+   public init(rawValue: String)

 public class ChannelConfig: Codable  
-   case readEventsEnabled = "read_events"
+   case deliveryEventsEnabled = "delivery_events"
-   case connectEventsEnabled = "connect_events"
+   case readEventsEnabled = "read_events"
-   case uploadsEnabled = "uploads"
+   case connectEventsEnabled = "connect_events"
-   case repliesEnabled = "replies"
+   case uploadsEnabled = "uploads"
-   case quotesEnabled = "quotes"
+   case repliesEnabled = "replies"
-   case searchEnabled = "search"
+   case quotesEnabled = "quotes"
-   case mutesEnabled = "mutes"
+   case searchEnabled = "search"
-   case pollsEnabled = "polls"
+   case mutesEnabled = "mutes"
-   case urlEnrichmentEnabled = "url_enrichment"
+   case pollsEnabled = "polls"
-   case messageRetention = "message_retention"
+   case urlEnrichmentEnabled = "url_enrichment"
-   case maxMessageLength = "max_message_length"
+   case messageRetention = "message_retention"
-   case commands
+   case maxMessageLength = "max_message_length"
-   case createdAt = "created_at"
+   case commands
-   case updatedAt = "updated_at"
+   case createdAt = "created_at"
-   case skipLastMsgAtUpdateForSystemMsg = "skip_last_msg_update_for_system_msgs"
+   case updatedAt = "updated_at"
-   case messageRemindersEnabled = "user_message_reminders"
+   case skipLastMsgAtUpdateForSystemMsg = "skip_last_msg_update_for_system_msgs"
-   case sharedLocationsEnabled = "shared_locations"
+   case messageRemindersEnabled = "user_message_reminders"
-   
+   case sharedLocationsEnabled = "shared_locations"
- 
+   
-   public let reactionsEnabled: Bool
+ 
-   public let typingEventsEnabled: Bool
+   public let reactionsEnabled: Bool
-   public let readEventsEnabled: Bool
+   public let typingEventsEnabled: Bool
-   public let connectEventsEnabled: Bool
+   public let readEventsEnabled: Bool
-   public let uploadsEnabled: Bool
+   public let deliveryEventsEnabled: Bool
-   public let repliesEnabled: Bool
+   public let connectEventsEnabled: Bool
-   public let quotesEnabled: Bool
+   public let uploadsEnabled: Bool
-   public let searchEnabled: Bool
+   public let repliesEnabled: Bool
-   public let mutesEnabled: Bool
+   public let quotesEnabled: Bool
-   public let urlEnrichmentEnabled: Bool
+   public let searchEnabled: Bool
-   public let messageRetention: String
+   public let mutesEnabled: Bool
-   public let maxMessageLength: Int
+   public let urlEnrichmentEnabled: Bool
-   public let commands: [Command]
+   public let messageRetention: String
-   public let createdAt: Date
+   public let maxMessageLength: Int
-   public let updatedAt: Date
+   public let commands: [Command]
-   public let pollsEnabled: Bool
+   public let createdAt: Date
-   public let skipLastMsgAtUpdateForSystemMsg: Bool
+   public let updatedAt: Date
-   public let messageRemindersEnabled: Bool
+   public let pollsEnabled: Bool
-   public let sharedLocationsEnabled: Bool
+   public let skipLastMsgAtUpdateForSystemMsg: Bool
-   
+   public let messageRemindersEnabled: Bool
- 
+   public let sharedLocationsEnabled: Bool
-   public required init(from decoder: Decoder)throws
+   
+ 
+   public required init(from decoder: Decoder)throws

 public struct UserPrivacySettings  
-   
+   public var deliveryReceipts: DeliveryReceiptsPrivacySettings?
- 
+   
-   public init(typingIndicators: TypingIndicatorPrivacySettings? = nil,readReceipts: ReadReceiptsPrivacySettings? = nil)
+ 
+   public init(typingIndicators: TypingIndicatorPrivacySettings? = nil,readReceipts: ReadReceiptsPrivacySettings? = nil,deliveryReceipts: DeliveryReceiptsPrivacySettings? = nil)

 public struct ChatChannelRead: Equatable  
+   public let lastDeliveredAt: Date?
+   public let lastDeliveredMessageId: MessageId?

 public class ChatRemoteNotificationHandler  
+   public func markMessageAsDelivered(_ message: ChatMessage,for channel: ChatChannel)

@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 5, 2025

@nuno-vieira
Copy link
Member

/merge release

@testableapple
Copy link
Contributor

Publication of the release has been launched 👍

@github-actions github-actions bot merged commit e6b7636 into main Nov 7, 2025
14 of 15 checks passed
@github-actions github-actions bot deleted the release/4.92.0 branch November 7, 2025 11:44
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