diff --git a/bindings/matrix-sdk-ffi/src/room.rs b/bindings/matrix-sdk-ffi/src/room.rs index 9f0e3014909..fd0f6aef3fa 100644 --- a/bindings/matrix-sdk-ffi/src/room.rs +++ b/bindings/matrix-sdk-ffi/src/room.rs @@ -39,7 +39,7 @@ use crate::{ room_info::RoomInfo, room_member::RoomMember, ruma::{ImageInfo, Mentions, NotifyType}, - timeline::{FocusEventError, ReceiptType, SendHandle, Timeline}, + timeline::{DateDividerMode, FocusEventError, ReceiptType, SendHandle, Timeline}, utils::u64_to_uint, TaskHandle, }; @@ -278,6 +278,7 @@ impl Room { &self, internal_id_prefix: Option, allowed_message_types: Vec, + date_divider_mode: DateDividerMode, ) -> Result, ClientError> { let mut builder = matrix_sdk_ui::timeline::Timeline::builder(&self.inner); @@ -285,6 +286,8 @@ impl Room { builder = builder.with_internal_id_prefix(internal_id_prefix); } + builder = builder.with_date_divider_mode(date_divider_mode.into()); + builder = builder.event_filter(move |event, room_version_id| { default_event_filter(event, room_version_id) && match event { diff --git a/bindings/matrix-sdk-ffi/src/timeline/mod.rs b/bindings/matrix-sdk-ffi/src/timeline/mod.rs index c9075a928c1..89f226dc6a0 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/mod.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/mod.rs @@ -986,7 +986,7 @@ impl TimelineItem { pub fn as_virtual(self: Arc) -> Option { use matrix_sdk_ui::timeline::VirtualTimelineItem as VItem; match self.0.as_virtual()? { - VItem::DayDivider(ts) => Some(VirtualTimelineItem::DayDivider { ts: ts.0.into() }), + VItem::DateDivider(ts) => Some(VirtualTimelineItem::DateDivider { ts: ts.0.into() }), VItem::ReadMarker => Some(VirtualTimelineItem::ReadMarker), } } @@ -1255,8 +1255,9 @@ impl SendAttachmentJoinHandle { /// A [`TimelineItem`](super::TimelineItem) that doesn't correspond to an event. #[derive(uniffi::Enum)] pub enum VirtualTimelineItem { - /// A divider between messages of two days. - DayDivider { + /// A divider between messages of different day or month depending on + /// timeline settings. + DateDivider { /// A timestamp in milliseconds since Unix Epoch on that day in local /// time. ts: u64, @@ -1358,3 +1359,20 @@ impl LazyTimelineItemProvider { self.0.local_echo_send_handle().map(|handle| Arc::new(SendHandle::new(handle))) } } + +/// Changes how date dividers get inserted, either in between each day or in +/// between each month +#[derive(Debug, Clone, uniffi::Enum)] +pub enum DateDividerMode { + Daily, + Monthly, +} + +impl From for matrix_sdk_ui::timeline::DateDividerMode { + fn from(value: DateDividerMode) -> Self { + match value { + DateDividerMode::Daily => Self::Daily, + DateDividerMode::Monthly => Self::Monthly, + } + } +} diff --git a/crates/matrix-sdk-ui/src/timeline/builder.rs b/crates/matrix-sdk-ui/src/timeline/builder.rs index 8e131e21f6e..b3e7ec8cd01 100644 --- a/crates/matrix-sdk-ui/src/timeline/builder.rs +++ b/crates/matrix-sdk-ui/src/timeline/builder.rs @@ -28,7 +28,7 @@ use tracing::{info, info_span, trace, warn, Instrument, Span}; use super::{ controller::{TimelineController, TimelineSettings}, to_device::{handle_forwarded_room_key_event, handle_room_key_event}, - Error, Timeline, TimelineDropHandle, TimelineFocus, + DateDividerMode, Error, Timeline, TimelineDropHandle, TimelineFocus, }; use crate::{ timeline::{controller::TimelineNewItemPosition, event_item::RemoteEventOrigin}, @@ -89,6 +89,13 @@ impl TimelineBuilder { self } + /// Chose when to insert the date separators, either in between each day + /// or each month. + pub fn with_date_divider_mode(mut self, mode: DateDividerMode) -> Self { + self.settings.date_divider_mode = mode; + self + } + /// Enable tracking of the fully-read marker and the read receipts on the /// timeline. pub fn track_read_marker_and_receipts(mut self) -> Self { diff --git a/crates/matrix-sdk-ui/src/timeline/controller/mod.rs b/crates/matrix-sdk-ui/src/timeline/controller/mod.rs index 5d82572470c..47a1673f02d 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/mod.rs @@ -69,13 +69,13 @@ use super::{ item::TimelineUniqueId, traits::{Decryptor, RoomDataProvider}, util::{rfind_event_by_id, rfind_event_item, RelativePosition}, - Error, EventSendState, EventTimelineItem, InReplyToDetails, Message, PaginationError, Profile, - ReactionInfo, RepliedToEvent, TimelineDetails, TimelineEventItemId, TimelineFocus, - TimelineItem, TimelineItemContent, TimelineItemKind, + DateDividerMode, Error, EventSendState, EventTimelineItem, InReplyToDetails, Message, + PaginationError, Profile, ReactionInfo, RepliedToEvent, TimelineDetails, TimelineEventItemId, + TimelineFocus, TimelineItem, TimelineItemContent, TimelineItemKind, }; use crate::{ timeline::{ - day_dividers::DayDividerAdjuster, + date_dividers::DateDividerAdjuster, event_item::EventTimelineItemKind, pinned_events_loader::{PinnedEventsLoader, PinnedEventsLoaderError}, reactions::FullReactionKey, @@ -136,6 +136,8 @@ pub(super) struct TimelineSettings { pub(super) event_filter: Arc, /// Are unparsable events added as timeline items of their own kind? pub(super) add_failed_to_parse: bool, + /// Should the timeline items be grouped by day or month? + pub(super) date_divider_mode: DateDividerMode, } #[cfg(not(tarpaulin_include))] @@ -154,6 +156,7 @@ impl Default for TimelineSettings { track_read_receipts: false, event_filter: Arc::new(default_event_filter), add_failed_to_parse: true, + date_divider_mode: DateDividerMode::Daily, } } } @@ -742,9 +745,19 @@ impl TimelineController

{ // Only add new items if the timeline is live. let should_add_new_items = self.is_live().await; + let date_divider_mode = self.settings.date_divider_mode.clone(); + let mut state = self.state.write().await; state - .handle_local_event(sender, profile, should_add_new_items, txn_id, send_handle, content) + .handle_local_event( + sender, + profile, + should_add_new_items, + date_divider_mode, + txn_id, + send_handle, + content, + ) .await; } @@ -783,8 +796,9 @@ impl TimelineController

{ warn!("Message echo got duplicated, removing the local one"); txn.items.remove(idx); - // Adjust the day dividers, if needs be. - let mut adjuster = DayDividerAdjuster::default(); + // Adjust the date dividers, if needs be. + let mut adjuster = + DateDividerAdjuster::new(self.settings.date_divider_mode.clone()); adjuster.run(&mut txn.items, &mut txn.meta); } @@ -881,9 +895,9 @@ impl TimelineController

{ txn.items.remove(idx); - // A read marker or a day divider may have been inserted before the local echo. + // A read marker or a date divider may have been inserted before the local echo. // Ensure both are up to date. - let mut adjuster = DayDividerAdjuster::default(); + let mut adjuster = DateDividerAdjuster::new(self.settings.date_divider_mode.clone()); adjuster.run(&mut txn.items, &mut txn.meta); txn.meta.update_read_marker(&mut txn.items); @@ -973,7 +987,7 @@ impl TimelineController

{ txn.items.replace(idx, new_item); // This doesn't change the original sending time, so there's no need to adjust - // day dividers. + // date dividers. txn.commit(); diff --git a/crates/matrix-sdk-ui/src/timeline/controller/state.rs b/crates/matrix-sdk-ui/src/timeline/controller/state.rs index 878573af3ea..bfff486a6fe 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/state.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/state.rs @@ -48,12 +48,12 @@ use super::{ AllRemoteEvents, ObservableItems, ObservableItemsTransaction, ObservableItemsTransactionEntry, }, - HandleManyEventsResult, TimelineFocusKind, TimelineSettings, + DateDividerMode, HandleManyEventsResult, TimelineFocusKind, TimelineSettings, }; use crate::{ events::SyncTimelineEventWithoutContent, timeline::{ - day_dividers::DayDividerAdjuster, + date_dividers::DateDividerAdjuster, event_handler::{ Flow, HandleEventResult, TimelineEventContext, TimelineEventHandler, TimelineEventKind, TimelineItemPosition, @@ -192,12 +192,14 @@ impl TimelineState { } /// Adds a local echo (for an event) to the timeline. + #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub(super) async fn handle_local_event( &mut self, own_user_id: OwnedUserId, own_profile: Option, should_add_new_items: bool, + date_divider_mode: DateDividerMode, txn_id: OwnedTransactionId, send_handle: Option, content: TimelineEventKind, @@ -216,13 +218,13 @@ impl TimelineState { let mut txn = self.transaction(); - let mut day_divider_adjuster = DayDividerAdjuster::default(); + let mut date_divider_adjuster = DateDividerAdjuster::new(date_divider_mode); TimelineEventHandler::new(&mut txn, ctx) - .handle_event(&mut day_divider_adjuster, content) + .handle_event(&mut date_divider_adjuster, content) .await; - txn.adjust_day_dividers(day_divider_adjuster); + txn.adjust_date_dividers(date_divider_adjuster); txn.commit(); } @@ -239,7 +241,8 @@ impl TimelineState { { let mut txn = self.transaction(); - let mut day_divider_adjuster = DayDividerAdjuster::default(); + let mut date_divider_adjuster = + DateDividerAdjuster::new(settings.date_divider_mode.clone()); // Loop through all the indices, in order so we don't decrypt edits // before the event being edited, if both were UTD. Keep track of @@ -261,7 +264,7 @@ impl TimelineState { TimelineItemPosition::UpdateDecrypted { timeline_item_index: idx }, room_data_provider, settings, - &mut day_divider_adjuster, + &mut date_divider_adjuster, ) .await; @@ -272,7 +275,7 @@ impl TimelineState { } } - txn.adjust_day_dividers(day_divider_adjuster); + txn.adjust_date_dividers(date_divider_adjuster); txn.commit(); } @@ -381,7 +384,8 @@ impl TimelineStateTransaction<'_> { let position = position.into(); - let mut day_divider_adjuster = DayDividerAdjuster::default(); + let mut date_divider_adjuster = + DateDividerAdjuster::new(settings.date_divider_mode.clone()); // Implementation note: when `position` is `TimelineEnd::Front`, events are in // the reverse topological order. Prepending them one by one in the order they @@ -398,7 +402,7 @@ impl TimelineStateTransaction<'_> { position, room_data_provider, settings, - &mut day_divider_adjuster, + &mut date_divider_adjuster, ) .await; @@ -406,7 +410,7 @@ impl TimelineStateTransaction<'_> { total.items_updated += handle_one_res.items_updated as u64; } - self.adjust_day_dividers(day_divider_adjuster); + self.adjust_date_dividers(date_divider_adjuster); self.check_no_unused_unique_ids(); total @@ -442,7 +446,7 @@ impl TimelineStateTransaction<'_> { position: TimelineItemPosition, room_data_provider: &P, settings: &TimelineSettings, - day_divider_adjuster: &mut DayDividerAdjuster, + date_divider_adjuster: &mut DateDividerAdjuster, ) -> HandleEventResult { let SyncTimelineEvent { push_actions, kind } = event; let encryption_info = kind.encryption_info().cloned(); @@ -642,7 +646,7 @@ impl TimelineStateTransaction<'_> { }; // Handle the event to create or update a timeline item. - TimelineEventHandler::new(self, ctx).handle_event(day_divider_adjuster, event_kind).await + TimelineEventHandler::new(self, ctx).handle_event(date_divider_adjuster, event_kind).await } fn clear(&mut self) { @@ -661,11 +665,11 @@ impl TimelineStateTransaction<'_> { } }); - // Remove stray day dividers + // Remove stray date dividers let mut idx = 0; while idx < self.items.len() { - if self.items[idx].is_day_divider() - && self.items.get(idx + 1).map_or(true, |item| item.is_day_divider()) + if self.items[idx].is_date_divider() + && self.items.get(idx + 1).map_or(true, |item| item.is_date_divider()) { self.items.remove(idx); // don't increment idx because all elements have shifted @@ -773,7 +777,7 @@ impl TimelineStateTransaction<'_> { } } - fn adjust_day_dividers(&mut self, mut adjuster: DayDividerAdjuster) { + fn adjust_date_dividers(&mut self, mut adjuster: DateDividerAdjuster) { adjuster.run(&mut self.items, &mut self.meta); } diff --git a/crates/matrix-sdk-ui/src/timeline/day_dividers.rs b/crates/matrix-sdk-ui/src/timeline/date_dividers.rs similarity index 63% rename from crates/matrix-sdk-ui/src/timeline/day_dividers.rs rename to crates/matrix-sdk-ui/src/timeline/date_dividers.rs index ba9cd9175b3..09f903b7b86 100644 --- a/crates/matrix-sdk-ui/src/timeline/day_dividers.rs +++ b/crates/matrix-sdk-ui/src/timeline/date_dividers.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Algorithm to adjust (insert/replace/remove) day dividers after new events +//! Algorithm to adjust (insert/replace/remove) date dividers after new events //! have been received from any source. use std::{fmt::Display, sync::Arc}; @@ -23,37 +23,28 @@ use tracing::{error, event_enabled, instrument, trace, warn, Level}; use super::{ controller::{ObservableItemsTransaction, TimelineMetadata}, util::timestamp_to_date, - TimelineItem, TimelineItemKind, VirtualTimelineItem, + DateDividerMode, TimelineItem, TimelineItemKind, VirtualTimelineItem, }; -/// Algorithm ensuring that day dividers are adjusted correctly, according to +/// Algorithm ensuring that date dividers are adjusted correctly, according to /// new items that have been inserted. -pub(super) struct DayDividerAdjuster { +pub(super) struct DateDividerAdjuster { /// The list of recorded operations to apply, after analyzing the latest /// items. - ops: Vec, + ops: Vec, /// A boolean indicating whether the struct has been used and thus must be /// mark unused manually by calling [`Self::run`]. consumed: bool, + + mode: DateDividerMode, } -impl Drop for DayDividerAdjuster { +impl Drop for DateDividerAdjuster { fn drop(&mut self) { // Only run the assert if we're not currently panicking. if !std::thread::panicking() && !self.consumed { - error!("a DayDividerAdjuster has not been consumed with run()"); - } - } -} - -impl Default for DayDividerAdjuster { - fn default() -> Self { - Self { - ops: Default::default(), - // The adjuster starts as consumed, and it will be marked no consumed iff it's used - // with `mark_used`. - consumed: true, + error!("a DateDividerAdjuster has not been consumed with run()"); } } } @@ -70,9 +61,19 @@ struct PrevItemDesc<'a> { insert_op_at: usize, } -impl DayDividerAdjuster { - /// Marks this [`DayDividerAdjuster`] as used, which means it'll require a - /// call to [`DayDividerAdjuster::run`] before getting dropped. +impl DateDividerAdjuster { + pub fn new(mode: DateDividerMode) -> Self { + Self { + ops: Default::default(), + // The adjuster starts as consumed, and it will be marked no consumed iff it's used + // with `mark_used`. + consumed: true, + mode, + } + } + + /// Marks this [`DateDividerAdjuster`] as used, which means it'll require a + /// call to [`DateDividerAdjuster::run`] before getting dropped. pub fn mark_used(&mut self) { // Mark the adjuster as needing to be consumed. self.consumed = false; @@ -83,7 +84,7 @@ impl DayDividerAdjuster { #[instrument(skip_all)] pub fn run(&mut self, items: &mut ObservableItemsTransaction<'_>, meta: &mut TimelineMetadata) { // We're going to record vector operations like inserting, replacing and - // removing day dividers. Since we may remove or insert new items, + // removing date dividers. Since we may remove or insert new items, // recorded offsets will change as we're iterating over the array. The // only way this is possible is because we're recording operations // happening in non-decreasing order of the indices, i.e. we can't do an @@ -104,10 +105,10 @@ impl DayDividerAdjuster { for (i, item) in items.iter().enumerate() { match item.kind() { - TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(ts)) => { - // Record what the last alive item pair is only if we haven't removed the day + TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(ts)) => { + // Record what the last alive item pair is only if we haven't removed the date // divider. - if !self.handle_day_divider(i, *ts, prev_item.as_ref().map(|desc| desc.item)) { + if !self.handle_date_divider(i, *ts, prev_item.as_ref().map(|desc| desc.item)) { prev_item = Some(PrevItemDesc { item_index: i, item, @@ -132,19 +133,19 @@ impl DayDividerAdjuster { } } - // Also chase trailing day dividers explicitly, by iterating from the end to the - // start. Since they wouldn't be the prev_item of anything, we wouldn't - // analyze them in the previous loop. + // Also chase trailing date dividers explicitly, by iterating from the end to + // the start. Since they wouldn't be the prev_item of anything, we + // wouldn't analyze them in the previous loop. for (i, item) in items.iter().enumerate().rev() { - if item.is_day_divider() { - // The item is a trailing day divider: remove it, if it wasn't already scheduled - // for deletion. + if item.is_date_divider() { + // The item is a trailing date divider: remove it, if it wasn't already + // scheduled for deletion. if !self .ops .iter() - .any(|op| matches!(op, DayDividerOperation::Remove(j) if i == *j)) + .any(|op| matches!(op, DateDividerOperation::Remove(j) if i == *j)) { - trace!("removing trailing day divider @ {i}"); + trace!("removing trailing date divider @ {i}"); // Find the index at which to insert the removal operation. It must be before // any other operation on a bigger index, to maintain the @@ -152,7 +153,7 @@ impl DayDividerAdjuster { let index = self.ops.iter().position(|op| op.index() > i).unwrap_or(self.ops.len()); - self.ops.insert(index, DayDividerOperation::Remove(i)); + self.ops.insert(index, DateDividerOperation::Remove(i)); } } @@ -180,38 +181,38 @@ impl DayDividerAdjuster { self.consumed = true; } - /// Decides what to do with a day divider. + /// Decides what to do with a date divider. /// /// Returns whether it's been removed or not. #[inline] - fn handle_day_divider( + fn handle_date_divider( &mut self, i: usize, ts: MilliSecondsSinceUnixEpoch, prev_item: Option<&Arc>, ) -> bool { let Some(prev_item) = prev_item else { - // No interesting item prior to the day divider: it must be the first one, + // No interesting item prior to the date divider: it must be the first one, // nothing to do. return false; }; match prev_item.kind() { TimelineItemKind::Event(event) => { - // This day divider is preceded by an event. - if is_same_date_as(event.timestamp(), ts) { - // The event has the same date as the day divider: remove the current day + // This date divider is preceded by an event. + if self.is_same_date_divider_group_as(event.timestamp(), ts) { + // The event has the same date as the date divider: remove the current date // divider. - trace!("removing day divider following event with same timestamp @ {i}"); - self.ops.push(DayDividerOperation::Remove(i)); + trace!("removing date divider following event with same timestamp @ {i}"); + self.ops.push(DateDividerOperation::Remove(i)); return true; } } - TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(_)) => { - trace!("removing duplicate day divider @ {i}"); - // This day divider is preceded by another one: remove the current one. - self.ops.push(DayDividerOperation::Remove(i)); + TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(_)) => { + trace!("removing duplicate date divider @ {i}"); + // This date divider is preceded by another one: remove the current one. + self.ops.push(DateDividerOperation::Remove(i)); return true; } @@ -232,45 +233,48 @@ impl DayDividerAdjuster { latest_event_ts: Option, ) { let Some(PrevItemDesc { item_index, insert_op_at, item }) = prev_item_desc else { - // The event was the first item, so there wasn't any day divider before it: + // The event was the first item, so there wasn't any date divider before it: // insert one. - trace!("inserting the first day divider @ {}", i); - self.ops.push(DayDividerOperation::Insert(i, ts)); + trace!("inserting the first date divider @ {}", i); + self.ops.push(DateDividerOperation::Insert(i, ts)); return; }; match item.kind() { TimelineItemKind::Event(prev_event) => { // The event is preceded by another event. If they're not the same date, - // insert a day divider. + // insert a date divider. let prev_ts = prev_event.timestamp(); - if !is_same_date_as(prev_ts, ts) { - trace!("inserting day divider @ {} between two events with different dates", i); - self.ops.push(DayDividerOperation::Insert(i, ts)); + if !self.is_same_date_divider_group_as(prev_ts, ts) { + trace!( + "inserting date divider @ {} between two events with different dates", + i + ); + self.ops.push(DateDividerOperation::Insert(i, ts)); } } - TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(prev_ts)) => { + TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(prev_ts)) => { let event_date = timestamp_to_date(ts); - // The event is preceded by a day divider. + // The event is preceded by a date divider. if timestamp_to_date(*prev_ts) != event_date { - // The day divider is wrong. Should we replace it with the correct value, or + // The date divider is wrong. Should we replace it with the correct value, or // remove it entirely? if let Some(last_event_ts) = latest_event_ts { if timestamp_to_date(last_event_ts) == event_date { // There's a previous event with the same date: remove the divider. - trace!("removed day divider @ {item_index} between two events that have the same date"); - self.ops.insert(insert_op_at, DayDividerOperation::Remove(item_index)); + trace!("removed date divider @ {item_index} between two events that have the same date"); + self.ops.insert(insert_op_at, DateDividerOperation::Remove(item_index)); return; } } // There's no previous event or there's one with a different date: replace // the current divider. - trace!("replacing day divider @ {item_index} with new timestamp from event"); - self.ops.insert(insert_op_at, DayDividerOperation::Replace(item_index, ts)); + trace!("replacing date divider @ {item_index} with new timestamp from event"); + self.ops.insert(insert_op_at, DateDividerOperation::Replace(item_index, ts)); } } @@ -289,7 +293,7 @@ impl DayDividerAdjuster { for op in &self.ops { match *op { - DayDividerOperation::Insert(i, ts) => { + DateDividerOperation::Insert(i, ts) => { assert!(i >= max_i, "trying to insert at {i} < max_i={max_i}"); let at = (i64::try_from(i).unwrap() + offset) @@ -297,7 +301,7 @@ impl DayDividerAdjuster { assert!(at >= 0); let at = at as usize; - let item = meta.new_timeline_item(VirtualTimelineItem::DayDivider(ts)); + let item = meta.new_timeline_item(VirtualTimelineItem::DateDivider(ts)); // Keep push semantics, if we're inserting at the front or the back. if at == items.len() { @@ -312,7 +316,7 @@ impl DayDividerAdjuster { max_i = i; } - DayDividerOperation::Replace(i, ts) => { + DateDividerOperation::Replace(i, ts) => { assert!(i >= max_i, "trying to replace at {i} < max_i={max_i}"); let at = i64::try_from(i).unwrap() + offset; @@ -320,13 +324,13 @@ impl DayDividerAdjuster { let at = at as usize; let replaced = &items[at]; - if !replaced.is_day_divider() { - error!("we replaced a non day-divider @ {i}: {:?}", replaced.kind()); + if !replaced.is_date_divider() { + error!("we replaced a non date-divider @ {i}: {:?}", replaced.kind()); } let unique_id = replaced.unique_id(); let item = TimelineItem::new( - VirtualTimelineItem::DayDivider(ts), + VirtualTimelineItem::DateDivider(ts), unique_id.to_owned(), ); @@ -334,15 +338,15 @@ impl DayDividerAdjuster { max_i = i; } - DayDividerOperation::Remove(i) => { + DateDividerOperation::Remove(i) => { assert!(i >= max_i, "trying to replace at {i} < max_i={max_i}"); let at = i64::try_from(i).unwrap() + offset; assert!(at >= 0); let removed = items.remove(at as usize); - if !removed.is_day_divider() { - error!("we removed a non day-divider @ {i}: {:?}", removed.kind()); + if !removed.is_date_divider() { + error!("we removed a non date-divider @ {i}: {:?}", removed.kind()); } offset -= 1; @@ -352,7 +356,7 @@ impl DayDividerAdjuster { } } - /// Checks the invariants that must hold at any time after inserting day + /// Checks the invariants that must hold at any time after inserting date /// dividers. /// /// Returns a report if and only if there was at least one error. @@ -360,8 +364,8 @@ impl DayDividerAdjuster { &mut self, items: &'a ObservableItemsTransaction<'o>, initial_state: Option>>, - ) -> Option> { - let mut report = DayDividerInvariantsReport { + ) -> Option> { + let mut report = DateDividerInvariantsReport { initial_state, errors: Vec::new(), operations: std::mem::take(&mut self.ops), @@ -369,45 +373,45 @@ impl DayDividerAdjuster { }; // Assert invariants. - // 1. The timeline starts with a day divider. + // 1. The timeline starts with a date divider. if let Some(item) = items.get(0) { if item.is_read_marker() { if let Some(next_item) = items.get(1) { - if !next_item.is_day_divider() { - report.errors.push(DayDividerInsertError::FirstItemNotDayDivider); + if !next_item.is_date_divider() { + report.errors.push(DateDividerInsertError::FirstItemNotDateDivider); } } - } else if !item.is_day_divider() { - report.errors.push(DayDividerInsertError::FirstItemNotDayDivider); + } else if !item.is_date_divider() { + report.errors.push(DateDividerInsertError::FirstItemNotDateDivider); } } - // 2. There are no two day dividers following each other. + // 2. There are no two date dividers following each other. { - let mut prev_was_day_divider = false; + let mut prev_was_date_divider = false; for (i, item) in items.iter().enumerate() { - if item.is_day_divider() { - if prev_was_day_divider { - report.errors.push(DayDividerInsertError::DuplicateDayDivider { at: i }); + if item.is_date_divider() { + if prev_was_date_divider { + report.errors.push(DateDividerInsertError::DuplicateDateDivider { at: i }); } - prev_was_day_divider = true; + prev_was_date_divider = true; } else { - prev_was_day_divider = false; + prev_was_date_divider = false; } } }; - // 3. There's no trailing day divider. + // 3. There's no trailing date divider. if let Some(last) = items.last() { - if last.is_day_divider() { - report.errors.push(DayDividerInsertError::TrailingDayDivider); + if last.is_date_divider() { + report.errors.push(DateDividerInsertError::TrailingDateDivider); } } - // 4. Items are properly separated with day dividers. + // 4. Items are properly separated with date dividers. { let mut prev_event_ts = None; - let mut prev_day_divider_ts = None; + let mut prev_date_divider_ts = None; for (i, item) in items.iter().enumerate() { if let Some(ev) = item.as_event() { @@ -415,18 +419,18 @@ impl DayDividerAdjuster { // We have the same date as the previous event we've seen. if let Some(prev_ts) = prev_event_ts { - if !is_same_date_as(prev_ts, ts) { + if !self.is_same_date_divider_group_as(prev_ts, ts) { report.errors.push( - DayDividerInsertError::MissingDayDividerBetweenEvents { at: i }, + DateDividerInsertError::MissingDateDividerBetweenEvents { at: i }, ); } } - // There is a day divider before us, and it's the same date as our timestamp. - if let Some(prev_ts) = prev_day_divider_ts { - if !is_same_date_as(prev_ts, ts) { + // There is a date divider before us, and it's the same date as our timestamp. + if let Some(prev_ts) = prev_date_divider_ts { + if !self.is_same_date_divider_group_as(prev_ts, ts) { report.errors.push( - DayDividerInsertError::InconsistentDateAfterPreviousDayDivider { + DateDividerInsertError::InconsistentDateAfterPreviousDateDivider { at: i, }, ); @@ -434,24 +438,24 @@ impl DayDividerAdjuster { } else { report .errors - .push(DayDividerInsertError::MissingDayDividerBeforeEvent { at: i }); + .push(DateDividerInsertError::MissingDateDividerBeforeEvent { at: i }); } prev_event_ts = Some(ts); - } else if let TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(ts)) = + } else if let TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(ts)) = item.kind() { - // The previous day divider is for a different date. - if let Some(prev_ts) = prev_day_divider_ts { - if is_same_date_as(prev_ts, *ts) { + // The previous date divider is for a different date. + if let Some(prev_ts) = prev_date_divider_ts { + if self.is_same_date_divider_group_as(prev_ts, *ts) { report .errors - .push(DayDividerInsertError::DuplicateDayDivider { at: i }); + .push(DateDividerInsertError::DuplicateDateDivider { at: i }); } } prev_event_ts = None; - prev_day_divider_ts = Some(*ts); + prev_date_divider_ts = Some(*ts); } } } @@ -462,7 +466,7 @@ impl DayDividerAdjuster { if state.iter().any(|item| item.is_read_marker()) && !report.final_state.iter().any(|item| item.is_read_marker()) { - report.errors.push(DayDividerInsertError::ReadMarkerDisappeared); + report.errors.push(DateDividerInsertError::ReadMarkerDisappeared); } } @@ -472,44 +476,53 @@ impl DayDividerAdjuster { Some(report) } } + + /// Returns whether the two dates for the given timestamps are the same or + /// not. + fn is_same_date_divider_group_as( + &self, + lhs: MilliSecondsSinceUnixEpoch, + rhs: MilliSecondsSinceUnixEpoch, + ) -> bool { + match self.mode { + DateDividerMode::Daily => timestamp_to_date(lhs) == timestamp_to_date(rhs), + DateDividerMode::Monthly => { + timestamp_to_date(lhs).is_same_month_as(timestamp_to_date(rhs)) + } + } + } } #[derive(Debug)] -enum DayDividerOperation { +enum DateDividerOperation { Insert(usize, MilliSecondsSinceUnixEpoch), Replace(usize, MilliSecondsSinceUnixEpoch), Remove(usize), } -impl DayDividerOperation { +impl DateDividerOperation { fn index(&self) -> usize { match self { - DayDividerOperation::Insert(i, _) - | DayDividerOperation::Replace(i, _) - | DayDividerOperation::Remove(i) => *i, + DateDividerOperation::Insert(i, _) + | DateDividerOperation::Replace(i, _) + | DateDividerOperation::Remove(i) => *i, } } } -/// Returns whether the two dates for the given timestamps are the same or not. -#[inline] -fn is_same_date_as(lhs: MilliSecondsSinceUnixEpoch, rhs: MilliSecondsSinceUnixEpoch) -> bool { - timestamp_to_date(lhs) == timestamp_to_date(rhs) -} - -/// A report returned by [`DayDividerAdjuster::check_invariants`]. -struct DayDividerInvariantsReport<'a, 'o> { +/// A report returned by [`DateDividerAdjuster::check_invariants`]. +struct DateDividerInvariantsReport<'a, 'o> { /// Initial state before inserting the items. initial_state: Option>>, /// The operations that have been applied on the list. - operations: Vec, - /// Final state after inserting the day dividers. + operations: Vec, + /// Final state after inserting the date dividers. final_state: &'a ObservableItemsTransaction<'o>, /// Errors encountered in the algorithm. - errors: Vec, + errors: Vec, } -impl Display for DayDividerInvariantsReport<'_, '_> { +impl Display for DateDividerInvariantsReport<'_, '_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Write all the items of a slice of timeline items. fn write_items( @@ -517,7 +530,7 @@ impl Display for DayDividerInvariantsReport<'_, '_> { items: &[Arc], ) -> std::fmt::Result { for (i, item) in items.iter().enumerate() { - if let TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(ts)) = item.kind() + if let TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(ts)) = item.kind() { writeln!(f, "#{i} --- {}", ts.0)?; } else if let Some(event) = item.as_event() { @@ -545,9 +558,9 @@ impl Display for DayDividerInvariantsReport<'_, '_> { writeln!(f, "\nOperations to apply:")?; for op in &self.operations { match *op { - DayDividerOperation::Insert(i, ts) => writeln!(f, "insert @ {i}: {}", ts.0)?, - DayDividerOperation::Replace(i, ts) => writeln!(f, "replace @ {i}: {}", ts.0)?, - DayDividerOperation::Remove(i) => writeln!(f, "remove @ {i}")?, + DateDividerOperation::Insert(i, ts) => writeln!(f, "insert @ {i}: {}", ts.0)?, + DateDividerOperation::Replace(i, ts) => writeln!(f, "replace @ {i}: {}", ts.0)?, + DateDividerOperation::Remove(i) => writeln!(f, "remove @ {i}")?, } } @@ -566,31 +579,31 @@ impl Display for DayDividerInvariantsReport<'_, '_> { } #[derive(Debug, thiserror::Error)] -enum DayDividerInsertError { - /// The first item isn't a day divider. - #[error("The first item isn't a day divider")] - FirstItemNotDayDivider, +enum DateDividerInsertError { + /// The first item isn't a date divider. + #[error("The first item isn't a date divider")] + FirstItemNotDateDivider, - /// There are two day dividers for the same date. - #[error("Duplicate day divider @ {at}.")] - DuplicateDayDivider { at: usize }, + /// There are two date dividers for the same date. + #[error("Duplicate date divider @ {at}.")] + DuplicateDateDivider { at: usize }, - /// The last item is a day divider. - #[error("The last item is a day divider.")] - TrailingDayDivider, + /// The last item is a date divider. + #[error("The last item is a date divider.")] + TrailingDateDivider, /// Two events are following each other but they have different dates - /// without a day divider between them. - #[error("Missing day divider between events @ {at}")] - MissingDayDividerBetweenEvents { at: usize }, + /// without a date divider between them. + #[error("Missing date divider between events @ {at}")] + MissingDateDividerBetweenEvents { at: usize }, - /// Some event is missing a day divider before it. - #[error("Missing day divider before event @ {at}")] - MissingDayDividerBeforeEvent { at: usize }, + /// Some event is missing a date divider before it. + #[error("Missing date divider before event @ {at}")] + MissingDateDividerBeforeEvent { at: usize }, - /// An event and the previous day divider aren't focused on the same date. - #[error("Event @ {at} and the previous day divider aren't targeting the same date")] - InconsistentDateAfterPreviousDayDivider { at: usize }, + /// An event and the previous date divider aren't focused on the same date. + #[error("Event @ {at} and the previous date divider aren't targeting the same date")] + InconsistentDateAfterPreviousDateDivider { at: usize }, /// The read marker has been removed. #[error("The read marker has been removed")] @@ -602,12 +615,12 @@ mod tests { use assert_matches2::assert_let; use ruma::{owned_event_id, owned_user_id, uint, MilliSecondsSinceUnixEpoch}; - use super::{super::controller::ObservableItems, DayDividerAdjuster}; + use super::{super::controller::ObservableItems, DateDividerAdjuster}; use crate::timeline::{ controller::TimelineMetadata, event_item::{EventTimelineItemKind, RemoteEventTimelineItem}, util::timestamp_to_date, - EventTimelineItem, TimelineItemContent, VirtualTimelineItem, + DateDividerMode, EventTimelineItem, TimelineItemContent, VirtualTimelineItem, }; fn event_with_ts(timestamp: MilliSecondsSinceUnixEpoch) -> EventTimelineItem { @@ -644,7 +657,7 @@ mod tests { } #[test] - fn test_no_trailing_day_divider() { + fn test_no_trailing_date_divider() { let mut items = ObservableItems::new(); let mut txn = items.transaction(); @@ -656,12 +669,12 @@ mod tests { txn.push_back(meta.new_timeline_item(event_with_ts(timestamp)), None); txn.push_back( - meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp_next_day)), + meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp_next_day)), None, ); txn.push_back(meta.new_timeline_item(VirtualTimelineItem::ReadMarker), None); - let mut adjuster = DayDividerAdjuster::default(); + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Daily); adjuster.run(&mut txn, &mut meta); txn.commit(); @@ -669,7 +682,7 @@ mod tests { let mut iter = items.iter(); assert_let!(Some(item) = iter.next()); - assert!(item.is_day_divider()); + assert!(item.is_date_divider()); assert_let!(Some(item) = iter.next()); assert!(item.is_remote_event()); @@ -681,7 +694,7 @@ mod tests { } #[test] - fn test_read_marker_in_between_event_and_day_divider() { + fn test_read_marker_in_between_event_and_date_divider() { let mut items = ObservableItems::new(); let mut txn = items.transaction(); @@ -695,20 +708,20 @@ mod tests { let event = event_with_ts(timestamp); txn.push_back(meta.new_timeline_item(event.clone()), None); txn.push_back( - meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp_next_day)), + meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp_next_day)), None, ); txn.push_back(meta.new_timeline_item(VirtualTimelineItem::ReadMarker), None); txn.push_back(meta.new_timeline_item(event), None); - let mut adjuster = DayDividerAdjuster::default(); + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Daily); adjuster.run(&mut txn, &mut meta); txn.commit(); let mut iter = items.iter(); - assert!(iter.next().unwrap().is_day_divider()); + assert!(iter.next().unwrap().is_date_divider()); assert!(iter.next().unwrap().is_remote_event()); assert!(iter.next().unwrap().is_read_marker()); assert!(iter.next().unwrap().is_remote_event()); @@ -716,7 +729,7 @@ mod tests { } #[test] - fn test_read_marker_in_between_day_dividers() { + fn test_read_marker_in_between_date_dividers() { let mut items = ObservableItems::new(); let mut txn = items.transaction(); @@ -728,29 +741,29 @@ mod tests { assert_ne!(timestamp_to_date(timestamp), timestamp_to_date(timestamp_next_day)); txn.push_back(meta.new_timeline_item(event_with_ts(timestamp)), None); - txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp)), None); - txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp)), None); + txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp)), None); + txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp)), None); txn.push_back(meta.new_timeline_item(VirtualTimelineItem::ReadMarker), None); - txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp)), None); + txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp)), None); txn.push_back(meta.new_timeline_item(event_with_ts(timestamp_next_day)), None); - let mut adjuster = DayDividerAdjuster::default(); + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Daily); adjuster.run(&mut txn, &mut meta); txn.commit(); let mut iter = items.iter(); - assert!(iter.next().unwrap().is_day_divider()); + assert!(iter.next().unwrap().is_date_divider()); assert!(iter.next().unwrap().is_remote_event()); assert!(iter.next().unwrap().is_read_marker()); - assert!(iter.next().unwrap().is_day_divider()); + assert!(iter.next().unwrap().is_date_divider()); assert!(iter.next().unwrap().is_remote_event()); assert!(iter.next().is_none()); } #[test] - fn test_remove_all_day_dividers() { + fn test_remove_all_date_dividers() { let mut items = ObservableItems::new(); let mut txn = items.transaction(); @@ -762,25 +775,25 @@ mod tests { assert_ne!(timestamp_to_date(timestamp), timestamp_to_date(timestamp_next_day)); txn.push_back(meta.new_timeline_item(event_with_ts(timestamp_next_day)), None); - txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp)), None); - txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp)), None); + txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp)), None); + txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp)), None); txn.push_back(meta.new_timeline_item(event_with_ts(timestamp_next_day)), None); - let mut adjuster = DayDividerAdjuster::default(); + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Daily); adjuster.run(&mut txn, &mut meta); txn.commit(); let mut iter = items.iter(); - assert!(iter.next().unwrap().is_day_divider()); + assert!(iter.next().unwrap().is_date_divider()); assert!(iter.next().unwrap().is_remote_event()); assert!(iter.next().unwrap().is_remote_event()); assert!(iter.next().is_none()); } #[test] - fn test_event_read_marker_spurious_day_divider() { + fn test_event_read_marker_spurious_date_divider() { let mut items = ObservableItems::new(); let mut txn = items.transaction(); @@ -790,23 +803,23 @@ mod tests { txn.push_back(meta.new_timeline_item(event_with_ts(timestamp)), None); txn.push_back(meta.new_timeline_item(VirtualTimelineItem::ReadMarker), None); - txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp)), None); + txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp)), None); - let mut adjuster = DayDividerAdjuster::default(); + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Daily); adjuster.run(&mut txn, &mut meta); txn.commit(); let mut iter = items.iter(); - assert!(iter.next().unwrap().is_day_divider()); + assert!(iter.next().unwrap().is_date_divider()); assert!(iter.next().unwrap().is_remote_event()); assert!(iter.next().unwrap().is_read_marker()); assert!(iter.next().is_none()); } #[test] - fn test_multiple_trailing_day_dividers() { + fn test_multiple_trailing_date_dividers() { let mut items = ObservableItems::new(); let mut txn = items.transaction(); @@ -815,10 +828,10 @@ mod tests { let timestamp = MilliSecondsSinceUnixEpoch(uint!(42)); txn.push_back(meta.new_timeline_item(VirtualTimelineItem::ReadMarker), None); - txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp)), None); - txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DayDivider(timestamp)), None); + txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp)), None); + txn.push_back(meta.new_timeline_item(VirtualTimelineItem::DateDivider(timestamp)), None); - let mut adjuster = DayDividerAdjuster::default(); + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Daily); adjuster.run(&mut txn, &mut meta); txn.commit(); @@ -840,7 +853,7 @@ mod tests { txn.push_back(meta.new_timeline_item(VirtualTimelineItem::ReadMarker), None); txn.push_back(meta.new_timeline_item(event_with_ts(timestamp)), None); - let mut adjuster = DayDividerAdjuster::default(); + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Daily); adjuster.run(&mut txn, &mut meta); txn.commit(); @@ -848,7 +861,78 @@ mod tests { let mut iter = items.iter(); assert!(iter.next().unwrap().is_read_marker()); - assert!(iter.next().unwrap().is_day_divider()); + assert!(iter.next().unwrap().is_date_divider()); + assert!(iter.next().unwrap().is_remote_event()); + assert!(iter.next().is_none()); + } + + #[test] + fn test_daily_divider_mode() { + let mut items = ObservableItems::new(); + let mut txn = items.transaction(); + + let mut meta = test_metadata(); + + txn.push_back( + meta.new_timeline_item(event_with_ts(MilliSecondsSinceUnixEpoch(uint!(0)))), + None, + ); + txn.push_back( + meta.new_timeline_item(event_with_ts(MilliSecondsSinceUnixEpoch(uint!(86_400_000)))), // One day later + None, + ); + txn.push_back( + meta.new_timeline_item(event_with_ts(MilliSecondsSinceUnixEpoch(uint!(2_678_400_000)))), // One month later + None, + ); + + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Daily); + adjuster.run(&mut txn, &mut meta); + + txn.commit(); + + let mut iter = items.iter(); + + assert!(iter.next().unwrap().is_date_divider()); + assert!(iter.next().unwrap().is_remote_event()); + assert!(iter.next().unwrap().is_date_divider()); + assert!(iter.next().unwrap().is_remote_event()); + assert!(iter.next().unwrap().is_date_divider()); + assert!(iter.next().unwrap().is_remote_event()); + assert!(iter.next().is_none()); + } + + #[test] + fn test_monthly_divider_mode() { + let mut items = ObservableItems::new(); + let mut txn = items.transaction(); + + let mut meta = test_metadata(); + + txn.push_back( + meta.new_timeline_item(event_with_ts(MilliSecondsSinceUnixEpoch(uint!(0)))), + None, + ); + txn.push_back( + meta.new_timeline_item(event_with_ts(MilliSecondsSinceUnixEpoch(uint!(86_400_000)))), // One day later + None, + ); + txn.push_back( + meta.new_timeline_item(event_with_ts(MilliSecondsSinceUnixEpoch(uint!(2_678_400_000)))), // One month later + None, + ); + + let mut adjuster = DateDividerAdjuster::new(DateDividerMode::Monthly); + adjuster.run(&mut txn, &mut meta); + + txn.commit(); + + let mut iter = items.iter(); + + assert!(iter.next().unwrap().is_date_divider()); + assert!(iter.next().unwrap().is_remote_event()); + assert!(iter.next().unwrap().is_remote_event()); + assert!(iter.next().unwrap().is_date_divider()); assert!(iter.next().unwrap().is_remote_event()); assert!(iter.next().is_none()); } diff --git a/crates/matrix-sdk-ui/src/timeline/event_handler.rs b/crates/matrix-sdk-ui/src/timeline/event_handler.rs index 1eba4147626..17b8b819ad1 100644 --- a/crates/matrix-sdk-ui/src/timeline/event_handler.rs +++ b/crates/matrix-sdk-ui/src/timeline/event_handler.rs @@ -54,7 +54,7 @@ use super::{ ObservableItemsTransaction, ObservableItemsTransactionEntry, PendingEdit, PendingEditKind, TimelineMetadata, TimelineStateTransaction, }, - day_dividers::DayDividerAdjuster, + date_dividers::DateDividerAdjuster, event_item::{ extract_bundled_edit_event_json, extract_poll_edit_content, extract_room_msg_edit_content, AnyOtherFullStateEventContent, EventSendState, EventTimelineItemKind, @@ -348,12 +348,12 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> { #[instrument(skip_all, fields(txn_id, event_id, position))] pub(super) async fn handle_event( mut self, - day_divider_adjuster: &mut DayDividerAdjuster, + date_divider_adjuster: &mut DateDividerAdjuster, event_kind: TimelineEventKind, ) -> HandleEventResult { let span = tracing::Span::current(); - day_divider_adjuster.mark_used(); + date_divider_adjuster.mark_used(); match &self.ctx.flow { Flow::Local { txn_id, .. } => { @@ -1143,7 +1143,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> { let old_item_id = old_item.internal_id; if idx == self.items.len() - 1 { - // If the old item is the last one and no day divider + // If the old item is the last one and no date divider // changes need to happen, replace and return early. trace!(idx, "Replacing existing event"); self.items.replace(idx, TimelineItem::new(item, old_item_id.to_owned())); diff --git a/crates/matrix-sdk-ui/src/timeline/item.rs b/crates/matrix-sdk-ui/src/timeline/item.rs index 6487d28f6d7..a192cb2c666 100644 --- a/crates/matrix-sdk-ui/src/timeline/item.rs +++ b/crates/matrix-sdk-ui/src/timeline/item.rs @@ -33,7 +33,7 @@ pub enum TimelineItemKind { /// An event or aggregation of multiple events. Event(EventTimelineItem), /// An item that doesn't correspond to an event, for example the user's - /// own read marker, or a day divider. + /// own read marker, or a date divider. Virtual(VirtualTimelineItem), } @@ -79,9 +79,9 @@ impl TimelineItem { /// /// It identifies the item on a best-effort basis. For instance, edits /// to an [`EventTimelineItem`] will not change the ID of the - /// enclosing `TimelineItem`. For some virtual items like day + /// enclosing `TimelineItem`. For some virtual items like date /// dividers, identity isn't easy to define though and you might - /// see a new ID getting generated for a day divider that you + /// see a new ID getting generated for a date divider that you /// perceive to be "the same" as a previous one. pub fn unique_id(&self) -> &TimelineUniqueId { &self.internal_id @@ -106,10 +106,10 @@ impl TimelineItem { matches!(&self.kind, TimelineItemKind::Event(_)) } - /// Check whether this item is a day divider. + /// Check whether this item is a date divider. #[must_use] - pub fn is_day_divider(&self) -> bool { - matches!(self.kind, TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(_))) + pub fn is_date_divider(&self) -> bool { + matches!(self.kind, TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(_))) } pub(crate) fn is_read_marker(&self) -> bool { diff --git a/crates/matrix-sdk-ui/src/timeline/mod.rs b/crates/matrix-sdk-ui/src/timeline/mod.rs index da5dcbfef78..61fc7824ce2 100644 --- a/crates/matrix-sdk-ui/src/timeline/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/mod.rs @@ -59,7 +59,7 @@ use crate::timeline::pinned_events_loader::PinnedEventsRoom; mod builder; mod controller; -mod day_dividers; +mod date_dividers; mod error; mod event_handler; mod event_item; @@ -177,6 +177,14 @@ impl TimelineFocus { } } +/// Changes how dividers get inserted, either in between each day or in between +/// each month +#[derive(Debug, Clone)] +pub enum DateDividerMode { + Daily, + Monthly, +} + impl Timeline { /// Create a new [`TimelineBuilder`] for the given room. pub fn builder(room: &Room) -> TimelineBuilder { diff --git a/crates/matrix-sdk-ui/src/timeline/tests/basic.rs b/crates/matrix-sdk-ui/src/timeline/tests/basic.rs index 85cc7c2d48c..ba7abb9f7a3 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/basic.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/basic.rs @@ -62,7 +62,7 @@ async fn test_initial_events() { assert_eq!(item.as_event().unwrap().sender(), *BOB); let item = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert_matches!(&item.kind, TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(_))); + assert_matches!(&item.kind, TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(_))); } #[async_test] @@ -100,7 +100,7 @@ async fn test_replace_with_initial_events_and_read_marker() { let items = timeline.controller.items().await; assert_eq!(items.len(), 2); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert_eq!(items[1].as_event().unwrap().content().as_message().unwrap().body(), "hey"); let ev = f.text_msg("yo").sender(*BOB).into_sync(); @@ -111,7 +111,7 @@ async fn test_replace_with_initial_events_and_read_marker() { let items = timeline.controller.items().await; assert_eq!(items.len(), 2); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert_eq!(items[1].as_event().unwrap().content().as_message().unwrap().body(), "yo"); } @@ -269,8 +269,8 @@ async fn test_other_state() { assert_eq!(content.name, "Alice's room"); assert_matches!(prev_content, None); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); timeline.handle_live_redacted_state_event(&ALICE, RedactedRoomTopicEventContent::new()).await; @@ -298,7 +298,7 @@ async fn test_dedup_pagination() { assert_eq!(timeline_items.len(), 2); assert_matches!( timeline_items[0].kind, - TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(_)) + TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(_)) ); assert_matches!(timeline_items[1].kind, TimelineItemKind::Event(_)); } @@ -333,7 +333,7 @@ async fn test_dedup_initial() { let timeline_items = timeline.controller.items().await; assert_eq!(timeline_items.len(), 4); - assert!(timeline_items[0].is_day_divider()); + assert!(timeline_items[0].is_date_divider()); let event1 = &timeline_items[1]; let event2 = &timeline_items[2]; @@ -371,7 +371,7 @@ async fn test_internal_id_prefix() { let timeline_items = timeline.controller.items().await; assert_eq!(timeline_items.len(), 4); - assert!(timeline_items[0].is_day_divider()); + assert!(timeline_items[0].is_date_divider()); assert_eq!(timeline_items[0].unique_id().0, "le_prefix_3"); let event1 = &timeline_items[1]; @@ -427,8 +427,8 @@ async fn test_sanitized() { " ); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); } #[async_test] @@ -445,8 +445,8 @@ async fn test_reply() { let first_event_id = first_event.event_id().unwrap(); let first_event_sender = *ALICE; - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); let reply_formatted_body = format!("\ \ @@ -495,8 +495,8 @@ async fn test_thread() { let first_event = item.as_event().unwrap(); let first_event_id = first_event.event_id().unwrap(); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); timeline .handle_live_event( @@ -537,7 +537,7 @@ async fn test_replace_with_initial_events_when_batched() { let (items, mut stream) = timeline.controller.subscribe_batched().await; assert_eq!(items.len(), 2); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert_eq!(items[1].as_event().unwrap().content().as_message().unwrap().body(), "hey"); let ev = f.text_msg("yo").sender(*BOB).into_sync(); @@ -547,7 +547,7 @@ async fn test_replace_with_initial_events_when_batched() { .await; // Assert there are more than a single Clear diff in the next batch: - // Clear + PushBack (event) + PushFront (day divider) + // Clear + PushBack (event) + PushFront (date divider) let batched_diffs = stream.next().await.unwrap(); assert_eq!(batched_diffs.len(), 3); assert_matches!(batched_diffs[0], VectorDiff::Clear); @@ -555,6 +555,6 @@ async fn test_replace_with_initial_events_when_batched() { assert!(value.as_event().is_some()); }); assert_matches!(&batched_diffs[2], VectorDiff::PushFront { value } => { - assert_matches!(value.as_virtual(), Some(VirtualTimelineItem::DayDivider(_))); + assert_matches!(value.as_virtual(), Some(VirtualTimelineItem::DateDivider(_))); }); } diff --git a/crates/matrix-sdk-ui/src/timeline/tests/echo.rs b/crates/matrix-sdk-ui/src/timeline/tests/echo.rs index cd88dfd9b73..533c1c2c56d 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/echo.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/echo.rs @@ -56,9 +56,9 @@ async fn test_remote_echo_full_trip() { }; { - // The day divider comes in late. - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + // The date divider comes in late. + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); } // Scenario 2: The local event has not been sent to the server successfully, it @@ -143,8 +143,8 @@ async fn test_remote_echo_new_position() { let txn_id_from_event = item.as_event().unwrap(); assert_eq!(txn_id, txn_id_from_event.transaction_id().unwrap()); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); // ā€¦ and another event that comes back before the remote echo timeline.handle_live_event(f.text_msg("test").sender(&BOB)).await; @@ -153,8 +153,8 @@ async fn test_remote_echo_new_position() { let bob_message = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); assert!(bob_message.is_remote_event()); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); // When the remote echo comes inā€¦ timeline @@ -171,13 +171,13 @@ async fn test_remote_echo_new_position() { let item = assert_next_matches!(stream, VectorDiff::Set { index: 3, value } => value); assert!(!item.as_event().unwrap().is_local_echo()); - // ā€¦ the day divider is removed (because both bob's and alice's message are from - // the same day according to server timestamps). + // ā€¦ the date divider is removed (because both bob's and alice's message are + // from the same day according to server timestamps). assert_next_matches!(stream, VectorDiff::Remove { index: 2 }); } #[async_test] -async fn test_day_divider_duplication() { +async fn test_date_divider_duplication() { let timeline = TestTimeline::new(); // Given two remote events from one day, and a local event from another dayā€¦ @@ -192,28 +192,28 @@ async fn test_day_divider_duplication() { let items = timeline.controller.items().await; assert_eq!(items.len(), 5); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert!(items[1].is_remote_event()); assert!(items[2].is_remote_event()); - assert!(items[3].is_day_divider()); + assert!(items[3].is_date_divider()); assert!(items[4].is_local_echo()); // ā€¦ when the second remote event is re-received (day still the same) let event_id = items[2].as_event().unwrap().event_id().unwrap(); timeline.handle_live_event(f.text_msg("B").event_id(event_id).server_ts(1)).await; - // ā€¦ it should not impact the day dividers. + // ā€¦ it should not impact the date dividers. let items = timeline.controller.items().await; assert_eq!(items.len(), 5); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert!(items[1].is_remote_event()); assert!(items[2].is_remote_event()); - assert!(items[3].is_day_divider()); + assert!(items[3].is_date_divider()); assert!(items[4].is_local_echo()); } #[async_test] -async fn test_day_divider_removed_after_local_echo_disappeared() { +async fn test_date_divider_removed_after_local_echo_disappeared() { let timeline = TestTimeline::new(); let f = &timeline.factory; @@ -225,7 +225,7 @@ async fn test_day_divider_removed_after_local_echo_disappeared() { let items = timeline.controller.items().await; assert_eq!(items.len(), 2); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert!(items[1].is_remote_event()); // Add a local echo. @@ -237,9 +237,9 @@ async fn test_day_divider_removed_after_local_echo_disappeared() { let items = timeline.controller.items().await; assert_eq!(items.len(), 4); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert!(items[1].is_remote_event()); - assert!(items[2].is_day_divider()); + assert!(items[2].is_date_divider()); assert!(items[3].is_local_echo()); // Cancel the local echo. @@ -252,7 +252,7 @@ async fn test_day_divider_removed_after_local_echo_disappeared() { let items = timeline.controller.items().await; assert_eq!(items.len(), 2); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert!(items[1].is_remote_event()); } @@ -285,7 +285,7 @@ async fn test_no_read_marker_with_local_echo() { let items = timeline.controller.items().await; assert_eq!(items.len(), 2); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert!(items[1].is_remote_event()); // Add a local echo. @@ -297,7 +297,7 @@ async fn test_no_read_marker_with_local_echo() { let items = timeline.controller.items().await; assert_eq!(items.len(), 3); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert!(items[1].is_remote_event()); assert!(items[2].is_local_echo()); @@ -311,7 +311,7 @@ async fn test_no_read_marker_with_local_echo() { let items = timeline.controller.items().await; assert_eq!(items.len(), 2); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); assert!(items[1].is_remote_event()); } @@ -339,10 +339,10 @@ async fn test_no_reuse_of_counters() { item.unique_id().to_owned() }); - // The day divider comes in late. - // Timeline = [day-divider local] + // The date divider comes in late. + // Timeline = [date-divider local] assert_next_matches_with_timeout!(stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // Add a remote event now. @@ -357,19 +357,19 @@ async fn test_no_reuse_of_counters() { ) .await; - // Timeline = [remote day-divider local] + // Timeline = [remote date-divider local] assert_next_matches_with_timeout!(stream, VectorDiff::PushFront { value: item } => { assert!(!item.as_event().unwrap().is_local_echo()); // Both items have a different unique id. assert_ne!(local_id, item.unique_id().to_owned()); }); - // Day divider shenanigans. - // Timeline = [day-divider remote day-divider local] + // Date divider shenanigans. + // Timeline = [date-divider remote date-divider local] assert_next_matches_with_timeout!(stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); - // Timeline = [day-divider remote local] + // Timeline = [date-divider remote local] assert_next_matches_with_timeout!(stream, VectorDiff::Remove { index: 2 }); // When clearing the timeline, the local echo remains. diff --git a/crates/matrix-sdk-ui/src/timeline/tests/edit.rs b/crates/matrix-sdk-ui/src/timeline/tests/edit.rs index e6c59889891..a0efc1370c1 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/edit.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/edit.rs @@ -58,8 +58,8 @@ async fn test_live_redacted() { assert_eq!(timeline.controller.items().await.len(), 2); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); } #[async_test] @@ -81,8 +81,8 @@ async fn test_live_sanitized() { assert_eq!(text.body, "**original** message"); assert_eq!(text.formatted.as_ref().unwrap().body, "original message"); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); let first_event_id = first_event.event_id().unwrap(); @@ -151,8 +151,8 @@ async fn test_aggregated_sanitized() { assert_eq!(text.body, "!!edited!! **better** message"); assert_eq!(text.formatted.as_ref().unwrap().body, " better message"); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); } #[async_test] @@ -288,8 +288,8 @@ async fn test_relations_edit_overrides_pending_edit_msg() { let text = event.content().as_message().unwrap(); assert_eq!(text.body(), "edit 2"); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); assert_pending!(stream); } @@ -366,8 +366,8 @@ async fn test_relations_edit_overrides_pending_edit_poll() { ); assert_eq!(poll.start_event_content.poll_start.answers.len(), 3); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); assert_pending!(stream); } diff --git a/crates/matrix-sdk-ui/src/timeline/tests/encryption.rs b/crates/matrix-sdk-ui/src/timeline/tests/encryption.rs index 1daebc20160..135a662bca1 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/encryption.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/encryption.rs @@ -127,7 +127,7 @@ async fn test_retry_message_decryption() { assert_eq!(session_id, SESSION_ID); assert_next_matches!(stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); { @@ -451,7 +451,7 @@ async fn test_retry_edit_and_more() { let timeline_items = timeline.controller.items().await; assert_eq!(timeline_items.len(), 3); - assert!(timeline_items[0].is_day_divider()); + assert!(timeline_items[0].is_date_divider()); assert_eq!( timeline_items[1].as_event().unwrap().content().as_message().unwrap().body(), "edited" @@ -520,8 +520,8 @@ async fn test_retry_message_decryption_highlighted() { ); assert_eq!(session_id, SESSION_ID); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); let own_user_id = user_id!("@example:matrix.org"); let exported_keys = decrypt_room_key_export(Cursor::new(SESSION_KEY), "1234").unwrap(); diff --git a/crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs b/crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs index b6617cf5682..eb9e3bbafaf 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/event_filter.rs @@ -47,7 +47,7 @@ async fn test_default_filter() { timeline.handle_live_event(f.text_msg("The first message").sender(&ALICE)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); - let _day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + let _date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); let first_event_id = item.as_event().unwrap().event_id().unwrap(); timeline @@ -134,7 +134,7 @@ async fn test_custom_filter() { let f = &timeline.factory; timeline.handle_live_event(f.text_msg("The first message").sender(&ALICE)).await; let _item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); - let _day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + let _date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); timeline .handle_live_redacted_message_event(&ALICE, RedactedRoomMessageEventContent::new()) diff --git a/crates/matrix-sdk-ui/src/timeline/tests/reactions.rs b/crates/matrix-sdk-ui/src/timeline/tests/reactions.rs index 5cd0282bd84..46f89bc0606 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/reactions.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/reactions.rs @@ -229,8 +229,8 @@ async fn send_first_message( let event_id = event_item.event_id().unwrap().to_owned(); let position = timeline.len().await - 1; - let day_divider = assert_next_matches!(*stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(*stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); (item_id, event_id, position) } diff --git a/crates/matrix-sdk-ui/src/timeline/tests/read_receipts.rs b/crates/matrix-sdk-ui/src/timeline/tests/read_receipts.rs index 2da7584f949..99ef23a08a9 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/read_receipts.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/read_receipts.rs @@ -54,7 +54,7 @@ async fn test_read_receipts_updates_on_live_events() { let event_a = item_a.as_event().unwrap(); assert!(event_a.read_receipts().is_empty()); - let _day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + let _date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); // Implicit read receipt of Bob. let item_b = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); @@ -124,7 +124,7 @@ async fn test_read_receipts_updates_on_back_paginated_events() { let items = timeline.controller.items().await; assert_eq!(items.len(), 3); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); // Implicit read receipt of Bob. let event_a = items[2].as_event().unwrap(); @@ -155,7 +155,7 @@ async fn test_read_receipts_updates_on_filtered_events() { let event_a = item_a.as_event().unwrap(); assert!(event_a.read_receipts().is_empty()); - let _day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + let _date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); // Implicit read receipt of Bob. let item_a = assert_next_matches!(stream, VectorDiff::Set { index: 1, value } => value); @@ -240,7 +240,7 @@ async fn test_read_receipts_updates_on_filtered_events_with_stored() { let event_a = item_a.as_event().unwrap(); assert!(event_a.read_receipts().is_empty()); - let _day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + let _date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); // Stored read receipt of Bob. let item_a = assert_next_matches!(stream, VectorDiff::Set { index: 1, value } => value); @@ -301,8 +301,8 @@ async fn test_read_receipts_updates_on_back_paginated_filtered_events() { let event_a = item_a.as_event().unwrap(); assert!(event_a.read_receipts().is_empty()); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); // Add non-filtered event to show read receipts. timeline @@ -318,11 +318,11 @@ async fn test_read_receipts_updates_on_back_paginated_filtered_events() { assert!(event_c.read_receipts().get(*BOB).is_some()); assert!(event_c.read_receipts().get(*CAROL).is_some()); - // Reinsert a new day divider before the first back-paginated event. - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + // Reinsert a new date divider before the first back-paginated event. + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); - // Remove the last day divider. + // Remove the last date divider. assert_next_matches!(stream, VectorDiff::Remove { index: 2 }); assert_pending!(stream); @@ -413,7 +413,7 @@ async fn test_read_receipts_updates_on_message_decryption() { assert_eq!(clear_event.read_receipts().len(), 1); assert!(clear_event.read_receipts().get(*CAROL).is_some()); - let _day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + let _date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); // The second event is encrypted and only has Bob's receipt. let encrypted_item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); diff --git a/crates/matrix-sdk-ui/src/timeline/tests/redaction.rs b/crates/matrix-sdk-ui/src/timeline/tests/redaction.rs index ea1e06d80c4..11fa3023721 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/redaction.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/redaction.rs @@ -160,7 +160,7 @@ async fn test_reaction_redaction_timeline_filter() { // Adding a room message timeline.handle_live_event(f.text_msg("hi!").sender(&ALICE)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); - // Creates a day divider and the message. + // Creates a date divider and the message. assert_eq!(timeline.controller.items().await.len(), 2); // Reaction is attached to the message and doesn't add a timeline item. @@ -192,7 +192,7 @@ async fn test_receive_unredacted() { // redact the first one as well let items = timeline.controller.items().await; - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); let fst = items[1].as_event().unwrap(); timeline.handle_live_event(f.redaction(fst.event_id().unwrap()).sender(&ALICE)).await; diff --git a/crates/matrix-sdk-ui/src/timeline/tests/shields.rs b/crates/matrix-sdk-ui/src/timeline/tests/shields.rs index 33c90d0e25c..b87177e4ed0 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/shields.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/shields.rs @@ -75,9 +75,9 @@ async fn test_local_sent_in_clear_shield() { assert_eq!(shield, None); { - // The day divider comes in late. - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + // The date divider comes in late. + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); } // When the event is sent (but without a remote echo). diff --git a/crates/matrix-sdk-ui/src/timeline/tests/virt.rs b/crates/matrix-sdk-ui/src/timeline/tests/virt.rs index 14c230ca0fd..a0ddb01da26 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/virt.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/virt.rs @@ -28,7 +28,7 @@ use super::TestTimeline; use crate::timeline::{traits::RoomDataProvider as _, VirtualTimelineItem}; #[async_test] -async fn test_day_divider() { +async fn test_date_divider() { let timeline = TestTimeline::new(); let mut stream = timeline.subscribe().await; @@ -41,8 +41,8 @@ async fn test_day_divider() { let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); item.as_event().unwrap(); - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert_let!(VirtualTimelineItem::DayDivider(ts) = day_divider.as_virtual().unwrap()); + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert_let!(VirtualTimelineItem::DateDivider(ts) = date_divider.as_virtual().unwrap()); let date = Local.timestamp_millis_opt(ts.0.into()).single().unwrap(); assert_eq!(date.year(), 1970); assert_eq!(date.month(), 1); @@ -65,8 +65,9 @@ async fn test_day_divider() { let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); item.as_event().unwrap(); - let day_divider = assert_next_matches!(stream, VectorDiff::Insert { index: 3, value } => value); - assert_let!(VirtualTimelineItem::DayDivider(ts) = day_divider.as_virtual().unwrap()); + let date_divider = + assert_next_matches!(stream, VectorDiff::Insert { index: 3, value } => value); + assert_let!(VirtualTimelineItem::DateDivider(ts) = date_divider.as_virtual().unwrap()); let date = Local.timestamp_millis_opt(ts.0.into()).single().unwrap(); assert_eq!(date.year(), 1970); assert_eq!(date.month(), 1); @@ -81,10 +82,11 @@ async fn test_day_divider() { let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); item.as_event().unwrap(); - // The other events are in the past so a local event always creates a new day + // The other events are in the past so a local event always creates a new date // divider. - let day_divider = assert_next_matches!(stream, VectorDiff::Insert { index: 5, value } => value); - assert!(day_divider.is_day_divider()); + let date_divider = + assert_next_matches!(stream, VectorDiff::Insert { index: 5, value } => value); + assert!(date_divider.is_date_divider()); } #[async_test] @@ -102,9 +104,9 @@ async fn test_update_read_marker() { let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let event_id1 = item.as_event().unwrap().event_id().unwrap().to_owned(); - // Timeline: [day-divider, A]. - let day_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + // Timeline: [date-divider, A]. + let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); timeline.controller.handle_fully_read_marker(event_id1.clone()).await; @@ -113,13 +115,13 @@ async fn test_update_read_marker() { // ^-- fully read assert!(stream.next().now_or_never().is_none()); - // Timeline: [day-divider, A, B]. + // Timeline: [date-divider, A, B]. timeline.handle_live_event(f.text_msg("B").sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let event_id2 = item.as_event().unwrap().event_id().unwrap().to_owned(); // Now the read marker appears after the first event. - // Timeline: [day-divider, A, read-marker, B]. + // Timeline: [date-divider, A, read-marker, B]. // fully read --^ let item = assert_next_matches!(stream, VectorDiff::Insert { index: 2, value } => value); assert_matches!(item.as_virtual(), Some(VirtualTimelineItem::ReadMarker)); @@ -128,18 +130,18 @@ async fn test_update_read_marker() { // The read marker is removed but not reinserted, because it cannot be added at // the end. - // Timeline: [day-divider, A, B]. + // Timeline: [date-divider, A, B]. // ^-- fully read assert_next_matches!(stream, VectorDiff::Remove { index: 2 }); - // Timeline: [day-divider, A, B, C]. + // Timeline: [date-divider, A, B, C]. // ^-- fully read timeline.handle_live_event(f.text_msg("C").sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); let event_id3 = item.as_event().unwrap().event_id().unwrap().to_owned(); // Now the read marker is reinserted after the second event. - // Timeline: [day-divider, A, B, read-marker, C]. + // Timeline: [date-divider, A, B, read-marker, C]. // ^-- fully read let marker = assert_next_matches!(stream, VectorDiff::Insert { index: 3, value } => value); assert!(marker.is_read_marker()); @@ -158,7 +160,7 @@ async fn test_update_read_marker() { timeline.controller.handle_fully_read_marker(event_id2).await; assert!(stream.next().now_or_never().is_none()); - // Timeline: [day-divider, A, B, read-marker, C, D]. + // Timeline: [date-divider, A, B, read-marker, C, D]. // ^-- fully read timeline.handle_live_event(f.text_msg("D").sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); @@ -167,17 +169,17 @@ async fn test_update_read_marker() { timeline.controller.handle_fully_read_marker(event_id3).await; // The read marker is moved after the third event (sent by another user). - // Timeline: [day-divider, A, B, C, D]. + // Timeline: [date-divider, A, B, C, D]. // fully read --^ assert_next_matches!(stream, VectorDiff::Remove { index: 3 }); - // Timeline: [day-divider, A, B, C, read-marker, D]. + // Timeline: [date-divider, A, B, C, read-marker, D]. // fully read --^ let marker = assert_next_matches!(stream, VectorDiff::Insert { index: 4, value } => value); assert!(marker.is_read_marker()); // If the current user sends an event afterwards, the read marker doesn't move. - // Timeline: [day-divider, A, B, C, read-marker, D, E]. + // Timeline: [date-divider, A, B, C, read-marker, D, E]. // fully read --^ timeline.handle_live_event(f.text_msg("E").sender(&own_user)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); @@ -187,7 +189,7 @@ async fn test_update_read_marker() { // If the marker moved forward to another user's event, and there's no other // event sent from another user, then it will be removed. - // Timeline: [day-divider, A, B, C, D, E]. + // Timeline: [date-divider, A, B, C, D, E]. // fully read --^ timeline.controller.handle_fully_read_marker(event_id4).await; assert_next_matches!(stream, VectorDiff::Remove { index: 4 }); @@ -195,13 +197,13 @@ async fn test_update_read_marker() { assert!(stream.next().now_or_never().is_none()); // When a last event is inserted by ourselves, still no read marker. - // Timeline: [day-divider, A, B, C, D, E, F]. + // Timeline: [date-divider, A, B, C, D, E, F]. // fully read --^ timeline.handle_live_event(f.text_msg("F").sender(&own_user)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); item.as_event().unwrap(); - // Timeline: [day-divider, A, B, C, D, E, F, G]. + // Timeline: [date-divider, A, B, C, D, E, F, G]. // fully read --^ timeline.handle_live_event(f.text_msg("G").sender(&own_user)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); @@ -213,14 +215,14 @@ async fn test_update_read_marker() { // before their message. It is the first message that's both after the // fully-read event and not sent by us. // - // Timeline: [day-divider, A, B, C, D, E, F, G, H]. + // Timeline: [date-divider, A, B, C, D, E, F, G, H]. // fully read --^ timeline.handle_live_event(f.text_msg("H").sender(&BOB)).await; let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value); item.as_event().unwrap(); // [our own] v-- sent by Bob - // Timeline: [day-divider, A, B, C, D, E, F, G, read-marker, H]. + // Timeline: [date-divider, A, B, C, D, E, F, G, read-marker, H]. // fully read --^ let marker = assert_next_matches!(stream, VectorDiff::Insert { index: 8, value } => value); assert!(marker.is_read_marker()); diff --git a/crates/matrix-sdk-ui/src/timeline/util.rs b/crates/matrix-sdk-ui/src/timeline/util.rs index 9ad3be2b851..2bb9c449456 100644 --- a/crates/matrix-sdk-ui/src/timeline/util.rs +++ b/crates/matrix-sdk-ui/src/timeline/util.rs @@ -132,6 +132,12 @@ pub(super) struct Date { day: u32, } +impl Date { + pub fn is_same_month_as(&self, date: Date) -> bool { + self.year == date.year && self.month == date.month + } +} + /// Converts a timestamp since Unix Epoch to a year, month and day. pub(super) fn timestamp_to_date(ts: MilliSecondsSinceUnixEpoch) -> Date { let datetime = Local diff --git a/crates/matrix-sdk-ui/src/timeline/virtual_item.rs b/crates/matrix-sdk-ui/src/timeline/virtual_item.rs index 650bc38b643..727a44c2f5c 100644 --- a/crates/matrix-sdk-ui/src/timeline/virtual_item.rs +++ b/crates/matrix-sdk-ui/src/timeline/virtual_item.rs @@ -17,11 +17,12 @@ use ruma::MilliSecondsSinceUnixEpoch; /// A [`TimelineItem`](super::TimelineItem) that doesn't correspond to an event. #[derive(Clone, Debug)] pub enum VirtualTimelineItem { - /// A divider between messages of two days. + /// A divider between messages of two days or months depending on the + /// timeline configuration. /// /// The value is a timestamp in milliseconds since Unix Epoch on the given /// day in local time. - DayDivider(MilliSecondsSinceUnixEpoch), + DateDivider(MilliSecondsSinceUnixEpoch), /// The user's own read marker. ReadMarker, diff --git a/crates/matrix-sdk-ui/tests/integration/room_list_service.rs b/crates/matrix-sdk-ui/tests/integration/room_list_service.rs index c9e8374c16b..b28df20f150 100644 --- a/crates/matrix-sdk-ui/tests/integration/room_list_service.rs +++ b/crates/matrix-sdk-ui/tests/integration/room_list_service.rs @@ -2448,7 +2448,7 @@ async fn test_room_timeline() -> Result<(), Error> { // Previous timeline items. assert_matches!( **previous_timeline_items[0], - TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(_)) + TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(_)) ); assert_matches!( &**previous_timeline_items[1], diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/echo.rs b/crates/matrix-sdk-ui/tests/integration/timeline/echo.rs index 1479c3648c3..f00ad135d05 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/echo.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/echo.rs @@ -92,8 +92,8 @@ async fn test_echo() { assert!(item.event_id().is_none()); let txn_id = item.transaction_id().unwrap(); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); // Wait for the sending to finish and assert everything was successful send_hdl.await.unwrap().unwrap(); @@ -127,10 +127,10 @@ async fn test_echo() { assert!(item.is_own()); assert_eq!(item.timestamp(), MilliSecondsSinceUnixEpoch(uint!(152038280))); - // The day divider is also replaced. - let day_divider = + // The date divider is also replaced. + let date_divider = assert_next_matches!(timeline_stream, VectorDiff::Set { index: 0, value } => value); - assert!(day_divider.is_day_divider()); + assert!(date_divider.is_date_divider()); } #[async_test] @@ -255,9 +255,9 @@ async fn test_dedup_by_event_id_late() { let item = local_echo.as_event().unwrap(); assert_matches!(item.send_state(), Some(EventSendState::NotSentYet)); - // Timeline: [day-divider, local echo] - let day_divider = assert_next_matches_with_timeout!( timeline_stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + // Timeline: [date-divider, local echo] + let date_divider = assert_next_matches_with_timeout!( timeline_stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); let f = EventFactory::new(); sync_builder.add_joined_room( @@ -273,20 +273,20 @@ async fn test_dedup_by_event_id_late() { mock_sync(&server, sync_builder.build_json_sync_response(), None).await; let _response = client.sync_once(sync_settings.clone()).await.unwrap(); - // Timeline: [remote-echo, day-divider, local echo] + // Timeline: [remote-echo, date-divider, local echo] let remote_echo = assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => value); let item = remote_echo.as_event().unwrap(); assert_eq!(item.event_id(), Some(event_id)); - // Timeline: [day-divider, remote-echo, day-divider, local echo] - let day_divider = assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushFront { value } => value); - assert!(day_divider.is_day_divider()); + // Timeline: [date-divider, remote-echo, date-divider, local echo] + let date_divider = assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushFront { value } => value); + assert!(date_divider.is_date_divider()); - // Local echo and its day divider are removed. - // Timeline: [day-divider, remote-echo, day-divider] + // Local echo and its date divider are removed. + // Timeline: [date-divider, remote-echo, date-divider] assert_matches!(timeline_stream.next().await, Some(VectorDiff::Remove { index: 3 })); - // Timeline: [day-divider, remote-echo] + // Timeline: [date-divider, remote-echo] assert_matches!(timeline_stream.next().await, Some(VectorDiff::Remove { index: 2 })); } diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/edit.rs b/crates/matrix-sdk-ui/tests/integration/timeline/edit.rs index 4ad9e834238..9945e6e2c9b 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/edit.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/edit.rs @@ -103,8 +103,8 @@ async fn test_edit() { assert_matches!(msg.in_reply_to(), None); assert!(!msg.is_edited()); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); sync_builder.add_joined_room( JoinedRoomBuilder::new(room_id) @@ -208,8 +208,8 @@ async fn test_edit_local_echo() { let item = item.as_event().unwrap(); assert_matches!(item.send_state(), Some(EventSendState::NotSentYet)); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); // We haven't set a route for sending events, so this will fail. @@ -780,8 +780,8 @@ async fn test_edit_local_echo_with_unsupported_content() { let item = item.as_event().unwrap(); assert_matches!(item.send_state(), Some(EventSendState::NotSentYet)); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); // We haven't set a route for sending events, so this will fail. @@ -939,9 +939,9 @@ async fn test_pending_edit() { assert!(msg.is_edited()); assert_eq!(msg.body(), "[edit]"); - // The day divider. + // The date divider. assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // And nothing else. @@ -992,9 +992,9 @@ async fn test_pending_edit_overrides() { assert!(msg.is_edited()); assert_eq!(msg.body(), "bonjour"); - // The day divider. + // The date divider. assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // And nothing else. @@ -1040,9 +1040,9 @@ async fn test_pending_edit_from_backpagination() { assert!(msg.is_edited()); assert_eq!(msg.body(), "hello"); - // The day divider. + // The date divider. assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // And nothing else. @@ -1100,9 +1100,9 @@ async fn test_pending_edit_from_backpagination_doesnt_override_pending_edit_from assert!(msg.is_edited()); assert_eq!(msg.body(), "[edit]"); - // The day divider. + // The date divider. assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // And nothing else. @@ -1170,9 +1170,9 @@ async fn test_pending_poll_edit() { assert_eq!(results.answers[0].text, "Yes"); assert_eq!(results.answers[1].text, "No"); - // The day divider. + // The date divider. assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // And nothing else. diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/focus_event.rs b/crates/matrix-sdk-ui/tests/integration/timeline/focus_event.rs index 240586a7ad0..29a68e0d939 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/focus_event.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/focus_event.rs @@ -91,8 +91,8 @@ async fn test_new_focused() { let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 5 + 1); // event items + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 5 + 1); // event items + a date divider + assert!(items[0].is_date_divider()); assert_eq!( items[1].as_event().unwrap().content().as_message().unwrap().body(), "i tried so hard" @@ -141,9 +141,9 @@ async fn test_new_focused() { "I kept everything inside" ); - // Day divider post processing. + // Date divider post processing. assert_let!(Some(VectorDiff::PushFront { value: item }) = timeline_stream.next().await); - assert!(item.is_day_divider()); + assert!(item.is_date_divider()); assert_let!(Some(VectorDiff::Remove { index }) = timeline_stream.next().await); assert_eq!(index, 3); @@ -227,8 +227,8 @@ async fn test_focused_timeline_reacts() { let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 1 + 1); // event items + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 1 + 1); // event items + a date divider + assert!(items[0].is_date_divider()); let event_item = items[1].as_event().unwrap(); assert_eq!(event_item.content().as_message().unwrap().body(), "yolo"); @@ -309,8 +309,8 @@ async fn test_focused_timeline_local_echoes() { let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 1 + 1); // event items + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 1 + 1); // event items + a date divider + assert!(items[0].is_date_divider()); let event_item = items[1].as_event().unwrap(); assert_eq!(event_item.content().as_message().unwrap().body(), "yolo"); @@ -385,8 +385,8 @@ async fn test_focused_timeline_doesnt_show_local_echoes() { let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 1 + 1); // event items + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 1 + 1); // event items + a date divider + assert!(items[0].is_date_divider()); let event_item = items[1].as_event().unwrap(); assert_eq!(event_item.content().as_message().unwrap().body(), "yolo"); diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs b/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs index df1319c7066..570323f4e8c 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/mod.rs @@ -145,9 +145,9 @@ async fn test_reaction() { let senders: Vec<_> = group.keys().collect(); assert_eq!(senders.as_slice(), [user_id!("@bob:example.org")]); - // The day divider. - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + // The date divider. + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); sync_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_event( sync_timeline_event!({ @@ -228,8 +228,8 @@ async fn test_redacted_message() { assert_let!(Some(VectorDiff::PushBack { value: first }) = timeline_stream.next().await); assert_matches!(first.as_event().unwrap().content(), TimelineItemContent::RedactedMessage); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); } #[async_test] @@ -270,8 +270,8 @@ async fn test_redact_message() { "buy my bitcoins bro" ); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); // Redacting a remote event works. mock_redaction(event_id!("$42")).mount(&server).await; @@ -347,11 +347,11 @@ async fn test_redact_local_sent_message() { assert!(event.is_local_echo()); assert_matches!(event.send_state(), Some(EventSendState::NotSentYet)); - // As well as a day divider. + // As well as a date divider. assert_let_timeout!( - Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next() + Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next() ); - assert!(day_divider.is_day_divider()); + assert!(date_divider.is_date_divider()); // We receive an update in the timeline from the send queue. assert_let_timeout!(Some(VectorDiff::Set { index, value: item }) = timeline_stream.next()); @@ -439,8 +439,8 @@ async fn test_read_marker() { assert_let!(Some(VectorDiff::PushBack { value: message }) = timeline_stream.next().await); assert_matches!(message.as_event().unwrap().content(), TimelineItemContent::Message(_)); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); sync_builder.add_joined_room( JoinedRoomBuilder::new(room_id).add_account_data(RoomAccountDataTestEvent::FullyRead), @@ -525,8 +525,8 @@ async fn test_sync_highlighted() { // Own events don't trigger push rules. assert!(!remote_event.is_highlighted()); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); sync_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_event( sync_timeline_event!({ @@ -589,7 +589,7 @@ async fn test_duplicate_maintains_correct_order() { let items = timeline.items().await; assert_eq!(items.len(), 2); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); let content = items[1].as_event().unwrap().content().as_message().unwrap().body(); assert_eq!(content, "C"); @@ -609,7 +609,7 @@ async fn test_duplicate_maintains_correct_order() { let items = timeline.items().await; assert_eq!(items.len(), 4, "{items:?}"); - assert!(items[0].is_day_divider()); + assert!(items[0].is_date_divider()); let content = items[1].as_event().unwrap().content().as_message().unwrap().body(); assert_eq!(content, "A"); let content = items[2].as_event().unwrap().content().as_message().unwrap().body(); diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/pagination.rs b/crates/matrix-sdk-ui/tests/integration/timeline/pagination.rs index bc0225d92ea..06189a3531f 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/pagination.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/pagination.rs @@ -118,11 +118,11 @@ async fn test_back_pagination() { assert_eq!(content.name, "New room name"); assert_eq!(prev_content.as_ref().unwrap().name.as_ref().unwrap(), "Old room name"); - let day_divider = assert_next_matches!( + let date_divider = assert_next_matches!( timeline_stream, VectorDiff::PushFront { value } => value ); - assert!(day_divider.is_day_divider()); + assert!(date_divider.is_date_divider()); Mock::given(method("GET")) .and(path_regex(r"^/_matrix/client/r0/rooms/.*/messages$")) @@ -228,11 +228,11 @@ async fn test_back_pagination_highlighted() { // `m.room.tombstone` should be highlighted by default. assert!(remote_event.is_highlighted()); - let day_divider = assert_next_matches!( + let date_divider = assert_next_matches!( timeline_stream, VectorDiff::PushFront { value } => value ); - assert!(day_divider.is_day_divider()); + assert!(date_divider.is_date_divider()); } #[async_test] @@ -480,7 +480,7 @@ async fn test_timeline_reset_while_paginating() { // field. assert!(hit_start); - // No events in back-pagination responses, day divider + event from latest + // No events in back-pagination responses, date divider + event from latest // sync is present assert_eq!(timeline.items().await.len(), 2); @@ -644,11 +644,11 @@ async fn test_empty_chunk() { assert_eq!(content.name, "New room name"); assert_eq!(prev_content.as_ref().unwrap().name.as_ref().unwrap(), "Old room name"); - let day_divider = assert_next_matches!( + let date_divider = assert_next_matches!( timeline_stream, VectorDiff::PushFront { value } => value ); - assert!(day_divider.is_day_divider()); + assert!(date_divider.is_date_divider()); } #[async_test] @@ -744,11 +744,11 @@ async fn test_until_num_items_with_empty_chunk() { assert_eq!(content.name, "New room name"); assert_eq!(prev_content.as_ref().unwrap().name.as_ref().unwrap(), "Old room name"); - let day_divider = assert_next_matches!( + let date_divider = assert_next_matches!( timeline_stream, VectorDiff::PushFront { value } => value ); - assert!(day_divider.is_day_divider()); + assert!(date_divider.is_date_divider()); timeline.live_paginate_backwards(10).await.unwrap(); @@ -760,11 +760,11 @@ async fn test_until_num_items_with_empty_chunk() { assert_let!(MessageType::Text(text) = msg.msgtype()); assert_eq!(text.body, "hello room then"); - let day_divider = assert_next_matches!( + let date_divider = assert_next_matches!( timeline_stream, VectorDiff::PushFront { value } => value ); - assert!(day_divider.is_day_divider()); + assert!(date_divider.is_date_divider()); assert_next_matches!(timeline_stream, VectorDiff::Remove { index: 2 }); } diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs b/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs index 044b8cc354d..6a1e75a95fd 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs @@ -62,8 +62,8 @@ async fn test_new_pinned_events_are_added_on_sync() { // Load timeline items let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 1 + 1); // event item + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 1 + 1); // event item + a date divider + assert!(items[0].is_date_divider()); assert_eq!(items[1].as_event().unwrap().content().as_message().unwrap().body(), "in the end"); assert_pending!(timeline_stream); test_helper.server.reset().await; @@ -96,7 +96,7 @@ async fn test_new_pinned_events_are_added_on_sync() { assert_eq!(value.as_event().unwrap().event_id().unwrap(), event_id!("$2")); }); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); test_helper.server.reset().await; } @@ -142,8 +142,8 @@ async fn test_new_pinned_event_ids_reload_the_timeline() { let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 1 + 1); // event item + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 1 + 1); // event item + a date divider + assert!(items[0].is_date_divider()); assert_eq!(items[1].as_event().unwrap().content().as_message().unwrap().body(), "in the end"); assert_pending!(timeline_stream); test_helper.server.reset().await; @@ -164,7 +164,7 @@ async fn test_new_pinned_event_ids_reload_the_timeline() { assert_eq!(value.as_event().unwrap().event_id().unwrap(), event_id!("$2")); }); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); assert_pending!(timeline_stream); test_helper.server.reset().await; @@ -375,8 +375,8 @@ async fn test_edited_events_are_reflected_in_sync() { // Load timeline items let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 1 + 1); // event item + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 1 + 1); // event item + a date divider + assert!(items[0].is_date_divider()); assert_eq!(items[1].as_event().unwrap().content().as_message().unwrap().body(), "in the end"); assert_pending!(timeline_stream); test_helper.server.reset().await; @@ -402,7 +402,7 @@ async fn test_edited_events_are_reflected_in_sync() { assert_eq!(event.event_id().unwrap(), event_id!("$1")); }); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // The edit replaces the original event assert_next_matches_with_timeout!(timeline_stream, VectorDiff::Set { index, value } => { @@ -451,8 +451,8 @@ async fn test_redacted_events_are_reflected_in_sync() { // Load timeline items let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 1 + 1); // event item + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 1 + 1); // event item + a date divider + assert!(items[0].is_date_divider()); assert_eq!(items[1].as_event().unwrap().content().as_message().unwrap().body(), "in the end"); assert_pending!(timeline_stream); test_helper.server.reset().await; @@ -474,7 +474,7 @@ async fn test_redacted_events_are_reflected_in_sync() { assert_eq!(event.event_id().unwrap(), event_id!("$1")); }); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // The redaction replaces the original event assert_next_matches_with_timeout!(timeline_stream, VectorDiff::Set { index, value } => { @@ -518,8 +518,8 @@ async fn test_edited_events_survive_pinned_event_ids_change() { // Load timeline items let (items, mut timeline_stream) = timeline.subscribe().await; - assert_eq!(items.len(), 1 + 1); // event item + a day divider - assert!(items[0].is_day_divider()); + assert_eq!(items.len(), 1 + 1); // event item + a date divider + assert!(items[0].is_date_divider()); assert_eq!(items[1].as_event().unwrap().content().as_message().unwrap().body(), "in the end"); assert_pending!(timeline_stream); test_helper.server.reset().await; @@ -547,7 +547,7 @@ async fn test_edited_events_survive_pinned_event_ids_change() { assert_eq!(event.event_id().unwrap(), event_id!("$1")); }); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); // The edit replaces the original event assert_next_matches_with_timeout!(timeline_stream, VectorDiff::Set { index, value } => { @@ -601,7 +601,7 @@ async fn test_edited_events_survive_pinned_event_ids_change() { assert_eq!(event.event_id().unwrap(), event_id!("$3")); }); assert_next_matches_with_timeout!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); assert_pending!(timeline_stream); } diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/profiles.rs b/crates/matrix-sdk-ui/tests/integration/timeline/profiles.rs index 8dd7a05328d..8eeeefa7b23 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/profiles.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/profiles.rs @@ -79,7 +79,7 @@ async fn test_update_sender_profiles() { let timeline_items = timeline.items().await; assert_eq!(timeline_items.len(), 4); - assert!(timeline_items[0].is_day_divider()); + assert!(timeline_items[0].is_date_divider()); // We have seen a member event for alice from alice => we have a profile // albeit empty. assert_matches!( @@ -104,7 +104,7 @@ async fn test_update_sender_profiles() { let timeline_items = timeline.items().await; assert_eq!(timeline_items.len(), 4); - assert!(timeline_items[0].is_day_divider()); + assert!(timeline_items[0].is_date_divider()); assert_matches!( timeline_items[1].as_event().unwrap().sender_profile(), TimelineDetails::Ready(_) @@ -166,7 +166,7 @@ async fn test_update_sender_profiles() { let timeline_items = timeline.items().await; assert_eq!(timeline_items.len(), 4); - assert!(timeline_items[0].is_day_divider()); + assert!(timeline_items[0].is_date_divider()); assert_matches!( timeline_items[1].as_event().unwrap().sender_profile(), TimelineDetails::Ready(_) @@ -185,7 +185,7 @@ async fn test_update_sender_profiles() { let timeline_items = timeline.items().await; assert_eq!(timeline_items.len(), 4); - assert!(timeline_items[0].is_day_divider()); + assert!(timeline_items[0].is_date_divider()); assert_matches!( timeline_items[1].as_event().unwrap().sender_profile(), TimelineDetails::Ready(_) diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/queue.rs b/crates/matrix-sdk-ui/tests/integration/timeline/queue.rs index edc522c5ab0..32a11923dfc 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/queue.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/queue.rs @@ -335,7 +335,7 @@ async fn test_clear_with_echoes() { // Wait for the first message to fail. Don't use time, but listen for the first // timeline item diff to get back signalling the error. - let _day_divider = timeline_stream.next().await; + let _date_divider = timeline_stream.next().await; let _local_echo = timeline_stream.next().await; let _local_echo_replaced_with_failure = timeline_stream.next().await; } @@ -389,7 +389,7 @@ async fn test_clear_with_echoes() { } #[async_test] -async fn test_no_duplicate_day_divider() { +async fn test_no_duplicate_date_divider() { let room_id = room_id!("!a98sd12bjh:example.org"); let (client, server) = logged_in_client_with_server().await; let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); @@ -448,7 +448,7 @@ async fn test_no_duplicate_day_divider() { }); assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); assert_next_matches!(timeline_stream, VectorDiff::PushBack { value } => { @@ -515,12 +515,12 @@ async fn test_no_duplicate_day_divider() { assert_eq!(value.event_id().unwrap(), "$5E2kLK/Sg342bgBU9ceEIEPYpbFaqJpZ"); }); - // A new day divider is inserted -> [DD First DD Second] + // A new date divider is inserted -> [DD First DD Second] assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); - // The useless day divider is removed. -> [DD First Second] + // The useless date divider is removed. -> [DD First Second] assert_next_matches!(timeline_stream, VectorDiff::Remove { index: 2 }); assert_pending!(timeline_stream); diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/reactions.rs b/crates/matrix-sdk-ui/tests/integration/timeline/reactions.rs index cbc8c04fe50..fdc958f9af8 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/reactions.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/reactions.rs @@ -76,8 +76,8 @@ async fn test_abort_before_being_sent() { let item_id = item.identifier(); assert_eq!(item.content().as_message().unwrap().body(), "hello"); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = stream.next().await); + assert!(date_divider.is_date_divider()); // Now we try to add two reactions to this messageā€¦ @@ -223,8 +223,8 @@ async fn test_redact_failed() { assert_eq!(item.as_event().unwrap().reactions().len(), 1); }); - assert_next_matches_with_timeout!(stream, VectorDiff::PushFront { value: day_divider } => { - assert!(day_divider.is_day_divider()); + assert_next_matches_with_timeout!(stream, VectorDiff::PushFront { value: date_divider } => { + assert!(date_divider.is_date_divider()); }); // Now, redact the annotation we previously added. @@ -315,9 +315,9 @@ async fn test_local_reaction_to_local_echo() { item.identifier() }); - // Good ol' day divider. - assert_next_matches_with_timeout!(stream, VectorDiff::PushFront { value: day_divider } => { - assert!(day_divider.is_day_divider()); + // Good ol' date divider. + assert_next_matches_with_timeout!(stream, VectorDiff::PushFront { value: date_divider } => { + assert!(date_divider.is_date_divider()); }); // Add a reaction before the remote echo comes back. diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/read_receipts.rs b/crates/matrix-sdk-ui/tests/integration/timeline/read_receipts.rs index cd9817f80b3..22e39defb78 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/read_receipts.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/read_receipts.rs @@ -162,8 +162,8 @@ async fn test_read_receipts_updates() { let (alice_receipt_event_id, _) = timeline.latest_user_read_receipt(alice).await.unwrap(); assert_eq!(alice_receipt_event_id, third_event_id); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); // Read receipt on unknown event is ignored. sync_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_ephemeral_event( @@ -412,8 +412,8 @@ async fn test_read_receipts_updates_on_filtered_events() { timeline.latest_user_read_receipt_timeline_event_id(*ALICE).await.unwrap(); assert_eq!(alice_receipt_timeline_event, event_c_id); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); // Read receipt on filtered event. sync_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_ephemeral_event( diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/replies.rs b/crates/matrix-sdk-ui/tests/integration/timeline/replies.rs index 580bdc92860..e4a953da94c 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/replies.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/replies.rs @@ -84,8 +84,8 @@ async fn test_in_reply_to_details() { assert_eq!(in_reply_to.event_id, event_id!("$event1")); assert_matches!(in_reply_to.event, TimelineDetails::Ready(_)); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); // Add an reply to an unknown event to the timeline let event_id_2 = event_id!("$event2"); @@ -198,7 +198,7 @@ async fn test_transfer_in_reply_to_details_to_re_received_item() { server.reset().await; let items = timeline.items().await; - assert_eq!(items.len(), 2); // day divider, reply + assert_eq!(items.len(), 2); // date divider, reply let event_item = items[1].as_event().unwrap(); let in_reply_to = event_item.content().as_message().unwrap().in_reply_to().unwrap(); assert_eq!(in_reply_to.event_id, event_id_1); diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/sliding_sync.rs b/crates/matrix-sdk-ui/tests/integration/timeline/sliding_sync.rs index 3d11c4c4a1a..ae194ceecaf 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/sliding_sync.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/sliding_sync.rs @@ -70,8 +70,8 @@ macro_rules! timeline_event { pub(crate) use timeline_event; macro_rules! assert_timeline_stream { - // `--- day divider ---` - ( @_ [ $stream:ident ] [ --- day divider --- ; $( $rest:tt )* ] [ $( $accumulator:tt )* ] ) => { + // `--- date divider ---` + ( @_ [ $stream:ident ] [ --- date divider --- ; $( $rest:tt )* ] [ $( $accumulator:tt )* ] ) => { assert_timeline_stream!( @_ [ $stream ] @@ -85,7 +85,7 @@ macro_rules! assert_timeline_stream { assert_matches!( **value, TimelineItemKind::Virtual( - VirtualTimelineItem::DayDivider(_) + VirtualTimelineItem::DateDivider(_) ) ); } @@ -120,8 +120,8 @@ macro_rules! assert_timeline_stream { ) }; - // `prepend --- day divider ---` - ( @_ [ $stream:ident ] [ prepend --- day divider --- ; $( $rest:tt )* ] [ $( $accumulator:tt )* ] ) => { + // `prepend --- date divider ---` + ( @_ [ $stream:ident ] [ prepend --- date divider --- ; $( $rest:tt )* ] [ $( $accumulator:tt )* ] ) => { assert_timeline_stream!( @_ [ $stream ] @@ -134,7 +134,7 @@ macro_rules! assert_timeline_stream { Some(Some(VectorDiff::PushFront { value })) => { assert_matches!( &**value, - TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(_)) => {} + TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(_)) => {} ); } ); @@ -335,7 +335,7 @@ async fn test_timeline_basic() -> Result<()> { append "$x1:bar.org"; update[0] "$x1:bar.org"; append "$x2:bar.org"; - prepend --- day divider ---; + prepend --- date divider ---; }; } @@ -385,7 +385,7 @@ async fn test_timeline_duplicated_events() -> Result<()> { append "$x2:bar.org"; update[1] "$x2:bar.org"; append "$x3:bar.org"; - prepend --- day divider ---; + prepend --- date divider ---; }; } @@ -463,7 +463,7 @@ async fn test_timeline_read_receipts_are_updated_live() -> Result<()> { append "$x1:bar.org"; update[0] "$x1:bar.org"; append "$x2:bar.org"; - prepend --- day divider ---; + prepend --- date divider ---; }; } diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/subscribe.rs b/crates/matrix-sdk-ui/tests/integration/timeline/subscribe.rs index 4989d51c3b2..249037faa1b 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/subscribe.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/subscribe.rs @@ -60,7 +60,7 @@ async fn test_batched() { let hdl = tokio::spawn(async move { let next_batch = timeline_stream.next().await.unwrap(); // There can be more than three updates because we add things like - // day dividers and implicit read receipts + // date dividers and implicit read receipts assert!(next_batch.len() >= 3); }); @@ -133,8 +133,8 @@ async fn test_event_filter() { assert_matches!(msg.msgtype(), MessageType::Text(_)); assert!(!msg.is_edited()); - assert_let!(Some(VectorDiff::PushFront { value: day_divider }) = timeline_stream.next().await); - assert!(day_divider.is_day_divider()); + assert_let!(Some(VectorDiff::PushFront { value: date_divider }) = timeline_stream.next().await); + assert!(date_divider.is_date_divider()); let second_event_id = event_id!("$Ga6Y2l0gKY"); let edit_event_id = event_id!("$7i9In0gEmB"); @@ -251,7 +251,7 @@ async fn test_timeline_is_reset_when_a_user_is_ignored_or_unignored() { assert_eq!(value.as_event().unwrap().event_id(), Some(third_event_id)); }); assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); assert_pending!(timeline_stream); @@ -299,7 +299,7 @@ async fn test_timeline_is_reset_when_a_user_is_ignored_or_unignored() { assert_eq!(value.as_event().unwrap().event_id(), Some(fifth_event_id)); }); assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); assert_pending!(timeline_stream); } @@ -370,7 +370,7 @@ async fn test_profile_updates() { assert_matches!(event_2_item.sender_profile(), TimelineDetails::Unavailable); assert_next_matches!(timeline_stream, VectorDiff::PushFront { value } => { - assert!(value.is_day_divider()); + assert!(value.is_date_divider()); }); assert_pending!(timeline_stream); diff --git a/labs/multiverse/src/main.rs b/labs/multiverse/src/main.rs index 9032993726b..e61cc17348b 100644 --- a/labs/multiverse/src/main.rs +++ b/labs/multiverse/src/main.rs @@ -832,7 +832,7 @@ impl App { } TimelineItemKind::Virtual(virt) => match virt { - VirtualTimelineItem::DayDivider(unix_ts) => { + VirtualTimelineItem::DateDivider(unix_ts) => { content.push(format!("Date: {unix_ts:?}")); } VirtualTimelineItem::ReadMarker => {