MSC3773: Notifications for threads (#3773)
* Add initial MSC for notfications for threads. * No longer depends on MSC3664. * Fix events in diagram. * Major simplification. * Add missing words. * Add a note about reactions. * Clarify homeserver behavior when processing push rules. * Link to a spec version instead of latest. Co-authored-by: Travis Ralston <travisr@matrix.org> * Update 3773-notifications-for-threads.md typoe * Clarify wording. * Update how homeservers are to partition threads. Co-authored-by: Travis Ralston <travisr@matrix.org> Co-authored-by: Matthew Hodgson <matthew@matrix.org>rei/unable_partial_state_room
parent
4e1b56247b
commit
9d80dcb6bd
@ -0,0 +1,162 @@
|
||||
# MSC3773: Notifications for threads
|
||||
|
||||
Since the unread notification count does not consider threads, a client is unable
|
||||
to separate the unread message counts into threads (as defined by
|
||||
[MSC3440](https://github.com/matrix-org/matrix-doc/pull/3440))
|
||||
without iterating over every missing message. Without this, clients are unable to:
|
||||
|
||||
* Let users know that a thread has new messages since they last read it.
|
||||
* Accurately display a count of unread messages in a room (or a thread).
|
||||
|
||||
## Proposal
|
||||
|
||||
### Modification to push rule processing
|
||||
|
||||
When an event which is part of a thread matches a push rule which results in a
|
||||
`notify` action then the homeserver should partition the resulting notification
|
||||
count per-thread. (This is needed for the
|
||||
[proposed `/sync` changes](#unread-thread-notifications-in-the-sync-response)).
|
||||
|
||||
It is recommended that at least 3 relations are traversed when attempting to
|
||||
find a thread, implementations should be careful to not infinitely recurse.[^1]
|
||||
|
||||
Similar behavior should be applied for an event which results in `notify` action
|
||||
with a `highlight` tweak set.
|
||||
|
||||
This MSC does not propose any changes to the payload sent to push gateways.
|
||||
|
||||
### Unread thread notifications in the sync response
|
||||
|
||||
Threaded clients can opt into receiving unread thread notifications by passing
|
||||
a new `unread_thread_notifications` parameter
|
||||
[as part of the `RoomEventFilter`](https://spec.matrix.org/v1.2/client-server-api/#filtering).
|
||||
(This is [similar to `lazy_load_members`](https://spec.matrix.org/v1.2/client-server-api/#lazy-loading-room-members),
|
||||
but only applies to the `/sync` endpoint.):
|
||||
|
||||
* `unread_thread_notifications`: If `true`, enables partitioning of unread notification
|
||||
counts by thread. Defaults to false.
|
||||
|
||||
If this flag is set to `true`, for each ["Joined Room" in the `/sync` response](https://spec.matrix.org/v1.3/client-server-api/#get_matrixclientv3sync)
|
||||
a new field is added:
|
||||
|
||||
* `unread_thread_notifications`: Counts of unread thread notifications for this
|
||||
room, an object which maps thread ID (the parent event ID) to
|
||||
`Unread Notification Counts`.
|
||||
|
||||
Additionally, the `unread_notifications` dictionary is modified to only include
|
||||
unread notifications from events which are not part of a thread.
|
||||
|
||||
An example of a joined room from a sync response:
|
||||
|
||||
```json5
|
||||
{
|
||||
"account_data": {
|
||||
// ...
|
||||
},
|
||||
"ephemeral": {
|
||||
// ...
|
||||
},
|
||||
"state": {
|
||||
// ...
|
||||
},
|
||||
"summary": {
|
||||
// ...
|
||||
},
|
||||
"timeline": {
|
||||
"events": [
|
||||
{
|
||||
"event_id": "$143273582443PhrSn:example.org",
|
||||
// other fields ...
|
||||
},
|
||||
{
|
||||
"event_id": "$SGNxGPGUopcPBUoTTL:example.org",
|
||||
"m.relates_to": {
|
||||
"event_id": "$143273582443PhrSn:example.org",
|
||||
"rel_type": "m.thread"
|
||||
}
|
||||
// other fields ...
|
||||
}
|
||||
]
|
||||
},
|
||||
"unread_notifications": {
|
||||
"highlight_count": 2,
|
||||
"notification_count": 18
|
||||
},
|
||||
"unread_thread_notifications": {
|
||||
"$143273582443PhrSn:example.org": {
|
||||
"highlight_count": 0,
|
||||
"notification_count": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Potential issues
|
||||
|
||||
### Scalability
|
||||
|
||||
Rooms with many unread threads could cause some downsides:
|
||||
|
||||
* The size of the `/sync` response would increase without bound.
|
||||
* The effort to generate and process the receipts for each room would increase
|
||||
without bound.
|
||||
|
||||
This is not dissimilar to rooms which are never read, however, as their unread
|
||||
counts are continually tracked and returned as part of the `/sync` response.
|
||||
|
||||
### Clearing unread notifications
|
||||
|
||||
This MSC does not attempt to modify how unread notifications (for a thread or
|
||||
otherwise) are cleared. It currently assumes the rules set forth by
|
||||
[read receipts](https://spec.matrix.org/v1.3/client-server-api/#receiving-notifications)
|
||||
still apply. This will cause some flakiness with unread notifications, as the current
|
||||
receipt infrastructure assumes that a room's timeline is linear, which is no
|
||||
longer true.
|
||||
|
||||
[MSC3771](https://github.com/matrix-org/matrix-spec-proposals/pull/3771) is a
|
||||
potential solution for this.
|
||||
|
||||
## Alternatives
|
||||
|
||||
### Using push rules
|
||||
|
||||
It might seem that a new push rule `action` (or `tweak`) should be used to control
|
||||
the behavior of whether an event generates a notification for a thread or the
|
||||
room itself. There are issues with either approach though:
|
||||
|
||||
A new `action` (e.g. `notify_thread`) would mean that additional logic would
|
||||
need to be defined and added for events which aren't part of a thread but attempt
|
||||
to use this action. It also conflicts with [MSC3768](https://github.com/matrix-org/matrix-spec-proposals/pull/3768),
|
||||
which attempts to define another `action` which should also work fine for threads.
|
||||
|
||||
A new `tweak` (e.g. `threaded`) was discarded as an option since there is no need to
|
||||
pass this through to the push server, which is at odds with the current `tweaks`
|
||||
mechanism.
|
||||
|
||||
Regardless, the main issue with using push rules is that it becomes necessary to
|
||||
define rules which match threaded events. Whenever adding a new rule, matching rules
|
||||
would need to be added, but as a thread-specific version.
|
||||
|
||||
## Security considerations
|
||||
|
||||
N/A
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
While this feature is in development the following unstable prefixes should be used:
|
||||
|
||||
* `unread_thread_notifications` --> `org.matrix.msc3773.unread_thread_notifications`
|
||||
|
||||
To detect server support, clients can either rely on the spec version (when stable)
|
||||
or the presence of a `org.matrix.msc3773` flag in `unstable_features` on `/versions`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
N/A
|
||||
|
||||
[^1]: Three relations is relatively arbitrary, but is meant to cover an edit or
|
||||
reaction to a thread (to an event with no relations, i.e. the root of a thread):
|
||||
`A<--[m.thread]--B<--[m.annotation]--C`.
|
||||
With an additional leftover for future improvements. This is considered reasonable
|
||||
since threads cannot fork, edits cannot modify relation information, and generally
|
||||
annotations to annotations are ignored by user interfaces.
|
Loading…
Reference in New Issue