diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c1887e318a..532828e247 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -middlewareVersion = "v0.40.0-rc7" +middlewareVersion = "v0.40.0-rc8" kotlinVersion = '2.0.21' kspVersion = "2.0.21-1.0.25" diff --git a/protocol/src/main/proto/commands.proto b/protocol/src/main/proto/commands.proto index 6fbc0333e8..a82465cde6 100644 --- a/protocol/src/main/proto/commands.proto +++ b/protocol/src/main/proto/commands.proto @@ -7905,12 +7905,13 @@ message Rpc { string afterOrderId = 4; // OrderId of the message after which to get messages string beforeOrderId = 2; // OrderId of the message before which to get messages int32 limit = 3; + bool includeBoundary = 5; // If true, include a message at the boundary (afterOrderId or beforeOrderId) } message Response { Error error = 1; repeated model.ChatMessage messages = 2; - + model.ChatState chatState = 3; message Error { Code code = 1; string description = 2; @@ -7960,7 +7961,7 @@ message Rpc { Error error = 1; repeated model.ChatMessage messages = 2; // List of messages int32 numMessagesBefore = 3; // Number of messages before the returned messages - + model.ChatState chatState = 4; // Chat state message Error { Code code = 1; string description = 2; @@ -8017,6 +8018,60 @@ message Rpc { } } } + + message ReadMessages { + enum ReadType { + messages = 0; + replies = 1; + } + message Request { + ReadType type = 1; + string chatObjectId = 2; // id of the chat object + string afterOrderId = 3; // read from this orderId; if empty - read from the beginning of the chat + string beforeOrderId = 4; // read til this orderId + int64 lastDbTimestamp = 5; // dbTimestamp from the last processed ChatState event(or GetMessages). Used to prevent race conditions + } + + message Response { + Error error = 1; + ResponseEvent event = 2; + message Error { + Code code = 1; + string description = 2; + + enum Code { + NULL = 0; + UNKNOWN_ERROR = 1; + BAD_INPUT = 2; + + MESSAGES_NOT_FOUND = 100; // chat is empty or invalid beforeOrderId/lastDbState + // ... + } + } + } + } + + message Unread { + message Request { + string chatObjectId = 2; // id of the chat object + string afterOrderId = 3; + } + + message Response { + Error error = 1; + ResponseEvent event = 2; + message Error { + Code code = 1; + string description = 2; + + enum Code { + NULL = 0; + UNKNOWN_ERROR = 1; + BAD_INPUT = 2; + } + } + } + } } } diff --git a/protocol/src/main/proto/events.proto b/protocol/src/main/proto/events.proto index 7ec5066e58..11c4f524ae 100644 --- a/protocol/src/main/proto/events.proto +++ b/protocol/src/main/proto/events.proto @@ -116,7 +116,10 @@ message Event { Chat.Add chatAdd = 128; Chat.Update chatUpdate = 129; Chat.UpdateReactions chatUpdateReactions = 130; + Chat.UpdateReadStatus chatUpdateReadStatus = 134; // received to update per-message read status (if needed to highlight the unread messages in the UI) + Chat.Delete chatDelete = 131; + Chat.UpdateState chatStateUpdate = 133; // in case new unread messages received or chat state changed (e.g. message read on another device) } } @@ -132,6 +135,7 @@ message Event { message Delete { string id = 1; repeated string subIds = 2; + model.ChatState state = 3; // Chat state. dbState should be persisted after rendered } message Update { string id = 1; @@ -143,6 +147,17 @@ message Event { model.ChatMessage.Reactions reactions = 2; repeated string subIds = 3; } + + message UpdateReadStatus { + repeated string ids = 1; + bool isRead = 2; + repeated string subIds = 3; + } + + message UpdateState { + model.ChatState state = 1; + repeated string subIds = 2; + } } message Account { diff --git a/protocol/src/main/proto/models.proto b/protocol/src/main/proto/models.proto index d554f28568..5d9b5f38b2 100644 --- a/protocol/src/main/proto/models.proto +++ b/protocol/src/main/proto/models.proto @@ -1378,17 +1378,28 @@ message DeviceInfo { bool isConnected = 5; } +message ChatState { + message UnreadState { + string oldestOrderId = 1; // oldest(in the lex sorting) unread message order id. Client should ALWAYS scroll through unread messages from the oldest to the newest + int32 counter = 2; // total number of unread messages + } + UnreadState messages = 1; // unread messages + UnreadState mentions = 2; // unread mentions + int64 dbTimestamp = 3; // reflects the state of the chat db at the moment of sending response/event that includes this state +} + message ChatMessage { string id = 1; // Unique message identifier string orderId = 2; // Used for subscriptions string creator = 3; // Identifier for the message creator int64 createdAt = 4; int64 modifiedAt = 9; + int64 addedAt = 11; // Message received and added to db at string replyToMessageId = 5; // Identifier for the message being replied to MessageContent message = 6; // Message content repeated Attachment attachments = 7; // Attachments slice Reactions reactions = 8; // Reactions to the message - + bool read = 10; // Message read status message MessageContent { string text = 1; // The text content of the message part Block.Content.Text.Style style = 2; // The style/type of the message part