Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to detect/handle tombstone rooms. No way to test it yet. #228

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/home/rooms_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,7 @@ impl Widget for RoomsList {
let should_display = (self.display_filter)(&room);
let _replaced = self.all_rooms.insert(room_id.clone(), room);
if let Some(_old_room) = _replaced {
// TODO: handle tombstoned rooms, and treat this case as a bug/error.
warning!("Added room {room_id} that already exists in the list of all rooms");
error!("BUG: Added room {room_id} that already existed");
} else {
if should_display {
self.displayed_rooms.push(room_id);
Expand Down
71 changes: 58 additions & 13 deletions src/sliding_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,15 @@ use eyeball_im::VectorDiff;
use futures_util::StreamExt;
use makepad_widgets::{error, log, warning, Cx, SignalToUI};
use matrix_sdk::{
config::RequestConfig,
event_handler::EventHandlerDropGuard,
media::MediaRequest,
room::{Receipts, RoomMember},
ruma::{
config::RequestConfig, event_handler::EventHandlerDropGuard, media::MediaRequest, room::{Receipts, RoomMember}, ruma::{
api::client::{receipt::create_receipt::v3::ReceiptType, session::get_login_types::v3::LoginType},
events::{
receipt::ReceiptThread, room::{
message::{ForwardThread, RoomMessageEventContent},
MediaSource,
message::{ForwardThread, RoomMessageEventContent}, tombstone::RoomTombstoneEventContent, MediaSource
}, FullStateEventContent
},
OwnedEventId, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomId, UserId
},
sliding_sync::VersionBuilder,
Client,
Room,
}, sliding_sync::VersionBuilder, Client, Room
};
use matrix_sdk_ui::{
room_list_service::{self, RoomListLoadingState},
Expand Down Expand Up @@ -802,11 +794,19 @@ struct RoomInfo {
timeline_update_receiver: Option<crossbeam_channel::Receiver<TimelineUpdate>>,
/// A drop guard for the event handler that represents a subscription to typing notices for this room.
typing_notice_subscriber: Option<EventHandlerDropGuard>,
/// The ID of the old tombstoned room that this room has replaced, if any.
replaces_tombstoned_room: Option<OwnedRoomId>,
}

/// Information about all of the rooms we currently know about.
static ALL_ROOM_INFO: Mutex<BTreeMap<OwnedRoomId, RoomInfo>> = Mutex::new(BTreeMap::new());

/// Information about all of the rooms that have been tombstoned.
///
/// The map key is the **NEW** replacement room ID, and the value is the **OLD** tombstoned room ID.
/// This allows us to quickly query if a newly-encountered room is a replacement for an old tombstoned room.
static TOMBSTONED_ROOMS: Mutex<BTreeMap<OwnedRoomId, OwnedRoomId>> = Mutex::new(BTreeMap::new());

/// The logged-in Matrix client, which can be freely and cheaply cloned.
static CLIENT: OnceLock<Client> = OnceLock::new();

Expand Down Expand Up @@ -1098,7 +1098,47 @@ fn remove_room(room: room_list_service::Room) {
async fn add_new_room(room: &room_list_service::Room) -> Result<()> {
let room_id = room.room_id().to_owned();

log!("Adding new room: {:?}, room_id: {room_id}", room.compute_display_name().await.map(|n| n.to_string()).unwrap_or_default());
let room_tombstone_event_content = room.get_state_event_static::<RoomTombstoneEventContent>()
.await
.ok()
.flatten()
// .map(|tombstone| match tombstone {
// RawSyncOrStrippedState::Sync()
// replacement_room.clone());
;


// NOTE: the call to `sync_up()` never returns, so I'm not sure how to force a room to fully sync.
// I suspect that's the problem -- we can't get the room's tombstone event content because
// the room isn't fully synced yet. But I don't know how to force it to fully sync.
//
// if !room.is_state_fully_synced() {
// log!("Room {room_id} is not fully synced yet; waiting for sync_up...");
// room.sync_up().await;
// log!("Room {room_id} is now fully synced? {}", room.is_state_fully_synced());
// }


// Do not add tombstoned rooms to the rooms list; they require special handling.
if let Some(tombstoned_info) = room.tombstone() {
log!("Room {room_id} has been tombstoned: {tombstoned_info:#?}");
// Since we don't know the order in which we'll learn about new rooms,
// we need to first check to see if the replacement for this tombstoned room
// refers to an already-known room as its replacement.
// If so, we can immediately update the replacement room's room info
// to indicate that it replaces this tombstoned room.
let replacement_room_id = tombstoned_info.replacement_room;
if let Some(room_info) = ALL_ROOM_INFO.lock().unwrap().get_mut(&replacement_room_id) {
room_info.replaces_tombstoned_room = Some(replacement_room_id.clone());
}
// But if we don't know about the replacement room yet, we need to save this tombstoned room
// in a separate list so that the replacement room we will discover in the future
// can know which old tombstoned room it replaces (see the bottom of this function).
else {
TOMBSTONED_ROOMS.lock().unwrap().insert(replacement_room_id, room_id.clone());
}
return Ok(());
}

let timeline = {
let builder = room.default_room_timeline_builder().await?
Expand Down Expand Up @@ -1152,6 +1192,11 @@ async fn add_new_room(room: &room_list_service::Room) -> Result<()> {

spawn_fetch_room_avatar(room.inner_room().clone());

let tombstoned_room_replaced_by_this_room = TOMBSTONED_ROOMS.lock()
.unwrap()
.remove(&room_id);

log!("Adding new room {room_id} to ALL_ROOM_INFO. Replaces tombstoned room: {tombstoned_room_replaced_by_this_room:?}");
ALL_ROOM_INFO.lock().unwrap().insert(
room_id.clone(),
RoomInfo {
Expand All @@ -1160,9 +1205,9 @@ async fn add_new_room(room: &room_list_service::Room) -> Result<()> {
timeline_update_receiver: Some(timeline_update_receiver),
timeline_update_sender,
typing_notice_subscriber: None,
replaces_tombstoned_room: tombstoned_room_replaced_by_this_room,
},
);

Ok(())
}

Expand Down