From 877e037747b4378b379546b57616425311026429 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 1 Jul 2024 20:31:27 +0200 Subject: [PATCH] Spec for MSC2867 (Marking rooms as unread) Relates to: matrix-org/matrix-spec-proposals#2867 Signed-off-by: Johannes Marbach --- content/client-server-api/_index.md | 2 +- .../client-server-api/modules/read_markers.md | 50 +++++++++++++++++-- .../examples/m.marked_unread.yaml | 7 +++ .../event-schemas/schema/m.marked_unread.yaml | 25 ++++++++++ 4 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 data/event-schemas/examples/m.marked_unread.yaml create mode 100644 data/event-schemas/schema/m.marked_unread.yaml diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 9558d536d..e4ba4e90d 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -2746,7 +2746,7 @@ that profile. | [Event Annotations and reactions](#event-annotations-and-reactions) | Optional | Optional | Optional | Optional | Optional | | [Event Context](#event-context) | Optional | Optional | Optional | Optional | Optional | | [Event Replacements](#event-replacements) | Optional | Optional | Optional | Optional | Optional | -| [Fully read markers](#fully-read-markers) | Optional | Optional | Optional | Optional | Optional | +| [(Un)read markers](#unread-markers) | Optional | Optional | Optional | Optional | Optional | | [Guest Access](#guest-access) | Optional | Optional | Optional | Optional | Optional | | [Moderation Policy Lists](#moderation-policy-lists) | Optional | Optional | Optional | Optional | Optional | | [OpenID](#openid) | Optional | Optional | Optional | Optional | Optional | diff --git a/content/client-server-api/modules/read_markers.md b/content/client-server-api/modules/read_markers.md index aa0baf477..1f970fb29 100644 --- a/content/client-server-api/modules/read_markers.md +++ b/content/client-server-api/modules/read_markers.md @@ -1,5 +1,6 @@ +### (Un)read markers -### Fully read markers +#### Fully read markers The history for a given room may be split into three sections: messages the user has read (or indicated they aren't interested in them), @@ -8,7 +9,7 @@ user hasn't seen yet. The "fully read marker" (also known as a "read marker") marks the last event of the first section, whereas the user's read receipt marks the last event of the second section. -#### Events +##### Events The user's fully read marker is kept as an event in the room's [account data](#client-config). The event may be read to determine the user's @@ -22,7 +23,7 @@ should be considered to be the user's read receipt location. {{% event event="m.fully_read" %}} -#### Client behaviour +##### Client behaviour The client cannot update fully read markers by directly modifying the `m.fully_read` account data event. Instead, the client must make use of @@ -41,7 +42,7 @@ might wish to save an extra HTTP call. Providing `m.read` and/or {{% http-api spec="client-server" api="read_markers" %}} -#### Server behaviour +##### Server behaviour The server MUST prevent clients from setting `m.fully_read` directly in room account data. The server must additionally ensure that it treats @@ -53,3 +54,44 @@ Upon updating the `m.fully_read` event due to a request to `/read_markers`, the server MUST send the updated account data event through to the client via the event stream (eg: `/sync`), provided any applicable filters are also satisfied. + +#### Unread markers + +Clients may use "unread markers" to allow users to label rooms for later +attention irrespective of [read receipts](#receipts) or +[fully read markers](#fully-read-markers). + +##### Events + +The user's unread marker in a room is kept under an `m.marked_unread` +event in the room's [account data](#client-config). The event may be read +to determine the user's current unread marker state in the room, and just +like other account data events the event will be pushed down the event +stream when updated. + +{{% event event="m.marked_unread" %}} + +##### Client behaviour + +Clients MUST update unread markers by directly modifying the `m.marked_unread` +account data event. When marking a room as unread, clients SHOULD NOT change +the `m.fully_read` marker so that the user's read position in the room is +retained. + +When the `unread` field is `true`, clients SHOULD visually annotate the room +to indicate that it is unread. Exactly how this is achieved is left as an +implementation detail. It is RECOMMENDED that clients use a treatment similar +to how they represent rooms with unread notifications. + +Clients SHOULD reset the unread marker by setting `unread` to `false` when +opening a room to display its timeline. + +Clients that offer functionality to mark a room as _read_ by sending a read +receipt for the last event, SHOULD reset the unread marker simultaneously. + +If the `m.marked_unread` event does not exist on the user's account data, +clients MUST behave as if `unread` was `false`. + +##### Server behaviour + +Servers have no additional requirements placed on them by this submodule. diff --git a/data/event-schemas/examples/m.marked_unread.yaml b/data/event-schemas/examples/m.marked_unread.yaml new file mode 100644 index 000000000..b9937196f --- /dev/null +++ b/data/event-schemas/examples/m.marked_unread.yaml @@ -0,0 +1,7 @@ +{ + "$ref": "core/event.json", + "type": "m.marked_unread", + "content": { + "unread": true + } +} diff --git a/data/event-schemas/schema/m.marked_unread.yaml b/data/event-schemas/schema/m.marked_unread.yaml new file mode 100644 index 000000000..56b3ba624 --- /dev/null +++ b/data/event-schemas/schema/m.marked_unread.yaml @@ -0,0 +1,25 @@ +{ + "type": "object", + "title": "Unread Marker Event", + "description": "The current state of the user's unread marker in a room. This event appears in the user's room account data for the room the marker is applicable for.", + "allOf": [{ + "$ref": "core-event-schema/event.yaml" + }], + "properties": { + "content": { + "type": "object", + "properties": { + "unread": { + "type": "boolean", + "description": "Whether the room is marked unread or not." + } + }, + "required": ["unread"] + }, + "type": { + "type": "string", + "enum": ["m.marked_unread"] + } + }, + "required": ["type", "content"] +}