syntax = "proto3"; package chatto.api.v1; import "buf/validate/validate.proto"; import "google/protobuf/timestamp.proto"; // Request to mark a room timeline as read. message MarkRoomAsReadRequest { // Required. Room whose timeline should be marked read. string room_id = 1 [(buf.validate.field).string.min_len = 1]; // Highest room event ID the current user has read. When set, the event must // exist as a root event in the room timeline. Leave empty to mark through the // room's current latest root event. string up_to_event_id = 2; } // Result of marking a room timeline as read. // // Clients can use the previous timestamp to place a local New messages // separator. Notification policy controls room Badge attention separately. message MarkRoomAsReadResponse { // New room read timestamp stored for the current user. google.protobuf.Timestamp last_read_at = 1; // Previous room read timestamp, when one existed. google.protobuf.Timestamp previous_last_read_at = 2; } // Request to mark a message thread as read. message MarkThreadAsReadRequest { // Required. Room containing the thread. string room_id = 1 [(buf.validate.field).string.min_len = 1]; // Required. Event ID of the root message for the thread. string thread_root_event_id = 2 [(buf.validate.field).string.min_len = 1]; // Highest thread event ID the current user has read. The event should belong // to the thread identified by thread_root_event_id. string up_to_event_id = 3; } // Result of marking a message thread as read. message MarkThreadAsReadResponse { reserved "previous_read_at"; // Previous thread read timestamp, when one existed. google.protobuf.Timestamp previous_last_read_at = 1; // Resulting thread read timestamp. A stale request retains the newer marker. // Absent when no marker exists. google.protobuf.Timestamp last_read_at = 2; } // Current stored read position. Its event can later be retracted. The timestamp // is absent if the event can no longer be resolved. This is not Badge attention. message ReadMarker { // Last-read event ID, to locate the boundary in a timeline. string last_read_event_id = 1; // Creation time of the last-read event, when available. google.protobuf.Timestamp last_read_at = 2; } // Current viewer's stored room read state. message RoomReadState { // Room ID. string room_id = 1; // Absent when no non-empty marker has been stored. Reading never initializes it. ReadMarker marker = 2; } // Current viewer's stored thread read state. message ThreadReadState { // Room ID. string room_id = 1; // Root message ID. string thread_root_event_id = 2; // Absent when no non-empty marker has been stored. Reading never advances it. ReadMarker marker = 3; } // Request current room read state without changing it. message GetRoomReadStateRequest { // Room ID. string room_id = 1 [(buf.validate.field).string.min_len = 1]; } // Current room read state, including an absent marker when none is stored. message GetRoomReadStateResponse { // State for the requested room and viewer. RoomReadState state = 1; } // Request room read states. Duplicates are removed in first-seen order. message BatchGetRoomReadStatesRequest { // Up to 100 room IDs. Missing or inaccessible rooms are omitted. repeated string room_ids = 1 [(buf.validate.field).repeated = { min_items: 1, max_items: 100, items: {string: {min_len: 1}} }]; } // Accessible room read states in first-seen request order. message BatchGetRoomReadStatesResponse { // States for the current viewer. An absent marker does not omit the state. repeated RoomReadState states = 1; } // Request current thread read state without changing it. message GetThreadReadStateRequest { // Room ID. string room_id = 1 [(buf.validate.field).string.min_len = 1]; // Root message ID. string thread_root_event_id = 2 [(buf.validate.field).string.min_len = 1]; } // Current thread read state. message GetThreadReadStateResponse { // State for the requested thread and viewer. ThreadReadState state = 1; } // Request thread read states. Duplicates are removed in first-seen order. message BatchGetThreadReadStatesRequest { // Up to 100 room/thread targets. Missing or inaccessible targets are omitted. repeated ThreadReadStateTarget targets = 1 [(buf.validate.field).repeated = {min_items: 1, max_items: 100}]; } // Accessible thread read states in first-seen request order. message BatchGetThreadReadStatesResponse { // States for the current viewer. An absent marker does not omit the state. repeated ThreadReadState states = 1; } // Room and root identity for one thread read state. message ThreadReadStateTarget { // Room ID. string room_id = 1 [(buf.validate.field).string.min_len = 1]; // Root message ID. string thread_root_event_id = 2 [(buf.validate.field).string.min_len = 1]; }