From 96a4b06ca69d44cd03f1646b0b78295887c7bb70 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 29 Mar 2024 19:41:46 +0100 Subject: [PATCH] timeline: use the day divider adjuster when updating the send state of a message --- .../matrix-sdk-ui/src/timeline/inner/mod.rs | 41 +++++++++---------- .../matrix-sdk-ui/src/timeline/inner/state.rs | 4 +- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/crates/matrix-sdk-ui/src/timeline/inner/mod.rs b/crates/matrix-sdk-ui/src/timeline/inner/mod.rs index 59f7e59dc..a1f08fb0a 100644 --- a/crates/matrix-sdk-ui/src/timeline/inner/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/inner/mod.rs @@ -62,7 +62,10 @@ use super::{ AnnotationKey, EventSendState, EventTimelineItem, InReplyToDetails, Message, Profile, RepliedToEvent, TimelineDetails, TimelineItem, TimelineItemContent, TimelineItemKind, }; -use crate::{timeline::TimelineEventFilterFn, unable_to_decrypt_hook::UtdHookManager}; +use crate::{ + timeline::{day_dividers::DayDividerAdjuster, TimelineEventFilterFn}, + unable_to_decrypt_hook::UtdHookManager, +}; mod state; @@ -491,14 +494,14 @@ impl TimelineInner

{ send_state: EventSendState, ) { let mut state = self.state.write().await; - let mut items_txn = state.items.transaction(); + let mut txn = state.transaction(); let new_event_id: Option<&EventId> = as_variant!(&send_state, EventSendState::Sent { event_id } => event_id); // The local echoes are always at the end of the timeline, we must first make // sure the remote echo hasn't showed up yet. - if rfind_event_item(&items_txn, |it| { + if rfind_event_item(&txn.items, |it| { new_event_id.is_some() && it.event_id() == new_event_id && it.as_remote().is_some() }) .is_some() @@ -506,33 +509,26 @@ impl TimelineInner

{ // Remote echo already received. This is very unlikely. trace!("Remote echo received before send-event response"); - let local_echo = rfind_event_item(&items_txn, |it| it.transaction_id() == Some(txn_id)); + let local_echo = rfind_event_item(&txn.items, |it| it.transaction_id() == Some(txn_id)); // If there's both the remote echo and a local echo, that means the // remote echo was received before the response *and* contained no // transaction ID (and thus duplicated the local echo). if let Some((idx, _)) = local_echo { warn!("Message echo got duplicated, removing the local one"); - items_txn.remove(idx); + txn.items.remove(idx); - if idx == 0 { - error!("Inconsistent state: Local echo was not preceded by day divider"); - return; - } - - if idx == items_txn.len() && items_txn[idx - 1].is_day_divider() { - // The day divider may have been added for this local echo, remove it and let - // the next message decide whether it's required or not. - items_txn.remove(idx - 1); - } + // Adjust the day dividers, if needs be. + let mut adjuster = DayDividerAdjuster::default(); + adjuster.run(&mut txn.items, &mut txn.meta); } - items_txn.commit(); + txn.commit(); return; } // Look for the local event by the transaction ID or event ID. - let result = rfind_event_item(&items_txn, |it| { + let result = rfind_event_item(&txn.items, |it| { it.transaction_id() == Some(txn_id) || new_event_id.is_some() && it.event_id() == new_event_id @@ -560,26 +556,27 @@ impl TimelineInner

{ let is_error = matches!(send_state, EventSendState::SendingFailed { .. }); let new_item = item.with_inner_kind(local_item.with_send_state(send_state)); - items_txn.set(idx, new_item); + txn.items.set(idx, new_item); if is_error { // When there is an error, sending further messages is paused. This // should be reflected in the timeline, so we set all other pending // events to cancelled. - let num_items = items_txn.len(); + let items = &mut txn.items; + let num_items = items.len(); for idx in 0..num_items { - let item = items_txn[idx].clone(); + let item = &items[idx]; let Some(event_item) = item.as_event() else { continue }; let Some(local_item) = event_item.as_local() else { continue }; if matches!(&local_item.send_state, EventSendState::NotSentYet) { let new_event_item = event_item.with_kind(local_item.with_send_state(EventSendState::Cancelled)); - items_txn.set(idx, item.with_kind(new_event_item)); + items.set(idx, item.with_kind(new_event_item)); } } } - items_txn.commit(); + txn.commit(); } /// Reconcile the timeline with the result of a request to toggle a diff --git a/crates/matrix-sdk-ui/src/timeline/inner/state.rs b/crates/matrix-sdk-ui/src/timeline/inner/state.rs index 561063d5e..0c23c4565 100644 --- a/crates/matrix-sdk-ui/src/timeline/inner/state.rs +++ b/crates/matrix-sdk-ui/src/timeline/inner/state.rs @@ -410,7 +410,7 @@ impl TimelineInnerState { txn.commit(); } - fn transaction(&mut self) -> TimelineInnerStateTransaction<'_> { + pub(super) fn transaction(&mut self) -> TimelineInnerStateTransaction<'_> { let items = self.items.transaction(); let meta = self.meta.clone(); TimelineInnerStateTransaction { items, previous_meta: &mut self.meta, meta } @@ -645,7 +645,7 @@ impl TimelineInnerStateTransaction<'_> { self.meta.update_read_marker(&mut self.items); } - fn commit(self) { + pub(super) fn commit(self) { let Self { items, previous_meta, meta } = self; // Replace the pointer to the previous meta with the new one.