use matrix_sdk_base::{
deserialized_responses::TimelineEventKind,
event_cache::{Event, Gap, store::EventCacheStoreLockGuard},
executor::spawn,
linked_chunk::{OwnedLinkedChunkId, Update},
};
use ruma::serde::Raw;
use tokio::sync::broadcast::Sender;
use tracing::trace;
use crate::event_cache::{Result, caches::room::RoomEventCacheLinkedChunkUpdate};
pub(super) async fn send_updates_to_store(
store: &EventCacheStoreLockGuard,
linked_chunk_id: OwnedLinkedChunkId,
linked_chunk_update_sender: &Sender<RoomEventCacheLinkedChunkUpdate>,
mut updates: Vec<Update<Event, Gap>>,
) -> Result<()> {
if updates.is_empty() {
return Ok(());
}
for update in updates.iter_mut() {
match update {
Update::PushItems { items, .. } => strip_relations_from_events(items),
Update::ReplaceItem { item, .. } => strip_relations_from_event(item),
Update::NewItemsChunk { .. }
| Update::NewGapChunk { .. }
| Update::RemoveChunk(_)
| Update::RemoveItem { .. }
| Update::DetachLastItems { .. }
| Update::StartReattachItems
| Update::EndReattachItems
| Update::Clear => {}
}
}
let store = store.clone();
let cloned_updates = updates.clone();
let cloned_linked_chunk_id = linked_chunk_id.clone();
spawn(async move {
trace!(updates = ?cloned_updates, "sending linked chunk updates to the store");
store.handle_linked_chunk_updates(cloned_linked_chunk_id.as_ref(), cloned_updates).await?;
trace!("linked chunk updates applied");
Result::Ok(())
})
.await
.expect("joining failed")?;
let _ = linked_chunk_update_sender
.send(RoomEventCacheLinkedChunkUpdate { linked_chunk_id, updates });
Ok(())
}
fn strip_relations_from_events(items: &mut [Event]) {
for ev in items.iter_mut() {
strip_relations_from_event(ev);
}
}
fn strip_relations_from_event(ev: &mut Event) {
match &mut ev.kind {
TimelineEventKind::Decrypted(decrypted) => {
decrypted.unsigned_encryption_info = None;
strip_relations_if_present(&mut decrypted.event);
}
TimelineEventKind::UnableToDecrypt { event, .. }
| TimelineEventKind::PlainText { event } => {
strip_relations_if_present(event);
}
}
}
fn strip_relations_if_present<T>(event: &mut Raw<T>) {
let mut closure = || -> Option<()> {
let mut val: serde_json::Value = event.deserialize_as().ok()?;
let unsigned = val.get_mut("unsigned")?;
let unsigned_obj = unsigned.as_object_mut()?;
if unsigned_obj.remove("m.relations").is_some() {
*event = Raw::new(&val).ok()?.cast_unchecked();
}
None
};
let _ = closure();
}