Browse Source

room: Count our own user's membership changes as activity

That way freshly joined or newly created rooms are at the top of the
list.
pipelines/816197
Kévin Commaille 1 year ago
parent
commit
7c8e4b2577
No known key found for this signature in database
GPG Key ID: C971D9DBC9D678D
  1. 5
      src/session/model/room/mod.rs
  2. 11
      src/session/model/room/timeline/event/mod.rs
  3. 46
      src/utils/matrix/ext_traits.rs

5
src/session/model/room/mod.rs

@ -782,7 +782,7 @@ mod imp {
}
/// The member corresponding to our own user.
fn own_member(&self) -> &Member {
pub(super) fn own_member(&self) -> &Member {
self.own_member.get().expect("Own member was initialized")
}
@ -2009,10 +2009,11 @@ impl Room {
///
/// The events must be in reverse chronological order.
fn update_latest_activity<'a>(&self, events: impl Iterator<Item = &'a Event>) {
let own_user_id = self.imp().own_member().user_id();
let mut latest_activity = self.latest_activity();
for event in events {
if event.counts_as_unread() {
if event.counts_as_activity(own_user_id) {
latest_activity = latest_activity.max(event.origin_server_ts().get().into());
break;
}

11
src/session/model/room/timeline/event/mod.rs

@ -9,7 +9,7 @@ use matrix_sdk_ui::timeline::{
use ruma::{
events::{receipt::Receipt, AnySyncTimelineEvent, TimelineEventType},
serde::Raw,
MatrixToUri, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId,
MatrixToUri, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId, UserId,
};
use serde::{de::IgnoredAny, Deserialize};
use tracing::{debug, error};
@ -744,6 +744,15 @@ impl Event {
self.item().content().counts_as_unread()
}
/// Whether this `Event` can count as activity in a room.
///
/// This includes content that counts as unread, plus membership changes for
/// our own user towards joining a room, so that freshly joined rooms are at
/// the top of the list.
pub(crate) fn counts_as_activity(&self, own_user_id: &UserId) -> bool {
self.item().content().counts_as_activity(own_user_id)
}
/// The `matrix.to` URI representation for this event.
///
/// Returns `None` if we don't have the ID of the event.

46
src/utils/matrix/ext_traits.rs

@ -4,12 +4,13 @@ use std::borrow::Cow;
use gtk::{glib, prelude::*};
use matrix_sdk_ui::timeline::{
AnyOtherFullStateEventContent, EventTimelineItem, Message, TimelineEventItemId,
TimelineItemContent,
AnyOtherFullStateEventContent, EventTimelineItem, MembershipChange, Message,
TimelineEventItemId, TimelineItemContent,
};
use ruma::{
events::{room::message::MessageType, AnySyncTimelineEvent},
serde::Raw,
UserId,
};
use serde::Deserialize;
@ -90,6 +91,13 @@ pub(crate) trait TimelineItemContentExt {
/// [MSC2654]: https://github.com/matrix-org/matrix-spec-proposals/pull/2654
fn counts_as_unread(&self) -> bool;
/// Whether this content can count as the latest activity in a room.
///
/// This includes content that counts as unread, plus membership changes for
/// our own user towards joining a room, so that freshly joined rooms are at
/// the top of the list.
fn counts_as_activity(&self, own_user_id: &UserId) -> bool;
/// Whether we can show the header for this content.
fn can_show_header(&self) -> bool;
@ -112,6 +120,40 @@ impl TimelineItemContentExt for TimelineItemContent {
}
}
fn counts_as_activity(&self, own_user_id: &UserId) -> bool {
if self.counts_as_unread() {
return true;
}
match self {
TimelineItemContent::MembershipChange(membership) => {
if membership.user_id() != own_user_id {
return false;
}
// We need to bump the room for every meaningful change towards joining a room.
//
// The change cannot be computed in two cases:
// - This is the first membership event for our user in the room: we need to
// count it.
// - The event was redacted: we do not know if we should count it or not, so we
// count it too for simplicity.
membership.change().is_none_or(|change| {
matches!(
change,
MembershipChange::Joined
| MembershipChange::Unbanned
| MembershipChange::Invited
| MembershipChange::InvitationAccepted
| MembershipChange::KnockAccepted
| MembershipChange::Knocked
)
})
}
_ => false,
}
}
fn can_show_header(&self) -> bool {
match self {
TimelineItemContent::Message(message) => {

Loading…
Cancel
Save