Skip to content

fix(sdk): maybe_apply_new_redaction updates in-store events #4740

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

Merged
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
16 changes: 8 additions & 8 deletions crates/matrix-sdk/src/event_cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -717,13 +717,6 @@ impl EventCacheInner {
let pagination_status =
SharedObservable::new(RoomPaginationStatus::Idle { hit_timeline_start: false });

let room_state = RoomEventCacheState::new(
room_id.to_owned(),
self.store.clone(),
pagination_status.clone(),
)
.await?;

let room_version = self
.client
.get()
Expand All @@ -735,6 +728,14 @@ impl EventCacheInner {
RoomVersionId::V1
});

let room_state = RoomEventCacheState::new(
room_id.to_owned(),
room_version,
self.store.clone(),
pagination_status.clone(),
)
.await?;

// SAFETY: we must have subscribed before reaching this coed, otherwise
// something is very wrong.
let auto_shrink_sender =
Expand All @@ -747,7 +748,6 @@ impl EventCacheInner {
room_state,
pagination_status,
room_id.to_owned(),
room_version,
self.all_events.clone(),
auto_shrink_sender,
);
Expand Down
2 changes: 1 addition & 1 deletion crates/matrix-sdk/src/event_cache/pagination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ impl RoomPagination {
debug!("not storing previous batch token, because we deduplicated all new back-paginated events");
}

room_events.on_new_events(&self.inner.room_version, reversed_events.iter());
reversed_events
})
.await?;

Expand Down
104 changes: 8 additions & 96 deletions crates/matrix-sdk/src/event_cache/room/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use as_variant::as_variant;
use eyeball_im::VectorDiff;
pub use matrix_sdk_base::event_cache::{Event, Gap};
use matrix_sdk_base::{
apply_redaction,
event_cache::store::DEFAULT_CHUNK_CAPACITY,
linked_chunk::{
lazy_loader::{self, LazyLoaderError},
Expand All @@ -27,11 +26,6 @@ use matrix_sdk_common::linked_chunk::{
AsVector, Chunk, ChunkIdentifier, EmptyChunkRule, Error, Iter, IterBackward, LinkedChunk,
ObservableUpdates, Position,
};
use ruma::{
events::{room::redaction::SyncRoomRedactionEvent, AnySyncTimelineEvent, MessageLikeEventType},
RoomVersionId,
};
use tracing::{instrument, trace, warn};

/// This type represents all events of a single room.
#[derive(Debug)]
Expand Down Expand Up @@ -99,96 +93,6 @@ impl RoomEvents {
lazy_loader::replace_with(&mut self.chunks, last_chunk, chunk_identifier_generator)
}

/// If the given event is a redaction, try to retrieve the to-be-redacted
/// event in the chunk, and replace it by the redacted form.
#[instrument(skip_all)]
fn maybe_apply_new_redaction(&mut self, room_version: &RoomVersionId, event: &Event) {
let raw_event = event.raw();

// Do not deserialise the entire event if we aren't certain it's a
// `m.room.redaction`. It saves a non-negligible amount of computations.
let Ok(Some(MessageLikeEventType::RoomRedaction)) =
raw_event.get_field::<MessageLikeEventType>("type")
else {
return;
};

// It is a `m.room.redaction`! We can deserialize it entirely.

let Ok(AnySyncTimelineEvent::MessageLike(
ruma::events::AnySyncMessageLikeEvent::RoomRedaction(redaction),
)) = event.raw().deserialize()
else {
return;
};

let Some(event_id) = redaction.redacts(room_version) else {
warn!("missing target event id from the redaction event");
return;
};

// Replace the redacted event by a redacted form, if we knew about it.
let mut items = self.chunks.items();

if let Some((pos, target_event)) =
items.find(|(_, item)| item.event_id().as_deref() == Some(event_id))
{
// Don't redact already redacted events.
if let Ok(deserialized) = target_event.raw().deserialize() {
match deserialized {
AnySyncTimelineEvent::MessageLike(ev) => {
if ev.original_content().is_none() {
// Already redacted.
return;
}
}
AnySyncTimelineEvent::State(ev) => {
if ev.original_content().is_none() {
// Already redacted.
return;
}
}
}
}

if let Some(redacted_event) = apply_redaction(
target_event.raw(),
event.raw().cast_ref::<SyncRoomRedactionEvent>(),
room_version,
) {
let mut copy = target_event.clone();

// It's safe to cast `redacted_event` here:
// - either the event was an `AnyTimelineEvent` cast to `AnySyncTimelineEvent`
// when calling .raw(), so it's still one under the hood.
// - or it wasn't, and it's a plain `AnySyncTimelineEvent` in this case.
copy.replace_raw(redacted_event.cast());

// Get rid of the immutable borrow on self.chunks.
drop(items);

self.chunks
.replace_item_at(pos, copy)
.expect("should have been a valid position of an item");
}
} else {
trace!("redacted event is missing from the linked chunk");
}

// TODO: remove all related events too!
}

/// Callback to call whenever we touch events in the database.
pub fn on_new_events<'a>(
&mut self,
room_version: &RoomVersionId,
events: impl Iterator<Item = &'a Event>,
) {
for ev in events {
self.maybe_apply_new_redaction(room_version, ev);
}
}

/// Push events after all events or gaps.
///
/// The last event in `events` is the most recent one.
Expand Down Expand Up @@ -269,6 +173,14 @@ impl RoomEvents {
Ok(())
}

/// Replace event at a specified position.
///
/// `position` must point to a valid item, otherwise the method returns an
/// error.
pub fn replace_event_at(&mut self, position: Position, event: Event) -> Result<(), Error> {
self.chunks.replace_item_at(position, event)
}

/// Search for a chunk, and return its identifier.
pub fn chunk_identifier<'a, P>(&'a self, predicate: P) -> Option<ChunkIdentifier>
where
Expand Down
Loading
Loading