Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(timeline): Configurable timeline date dividers #4398

Merged
merged 4 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion bindings/matrix-sdk-ffi/src/room.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -278,13 +278,16 @@ impl Room {
&self,
internal_id_prefix: Option<String>,
allowed_message_types: Vec<RoomMessageEventMessageType>,
date_divider_mode: DateDividerMode,
) -> Result<Arc<Timeline>, ClientError> {
let mut builder = matrix_sdk_ui::timeline::Timeline::builder(&self.inner);

if let Some(internal_id_prefix) = internal_id_prefix {
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 {
Expand Down
24 changes: 21 additions & 3 deletions bindings/matrix-sdk-ffi/src/timeline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ impl TimelineItem {
pub fn as_virtual(self: Arc<Self>) -> Option<VirtualTimelineItem> {
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),
}
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<DateDividerMode> for matrix_sdk_ui::timeline::DateDividerMode {
fn from(value: DateDividerMode) -> Self {
match value {
DateDividerMode::Daily => Self::Daily,
DateDividerMode::Monthly => Self::Monthly,
}
}
}
9 changes: 8 additions & 1 deletion crates/matrix-sdk-ui/src/timeline/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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 {
Expand Down
34 changes: 24 additions & 10 deletions crates/matrix-sdk-ui/src/timeline/controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -136,6 +136,8 @@ pub(super) struct TimelineSettings {
pub(super) event_filter: Arc<TimelineEventFilterFn>,
/// 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))]
Expand All @@ -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,
}
}
}
Expand Down Expand Up @@ -742,9 +745,19 @@ impl<P: RoomDataProvider> TimelineController<P> {
// 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;
}

Expand Down Expand Up @@ -783,8 +796,9 @@ impl<P: RoomDataProvider> TimelineController<P> {
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);
}

Expand Down Expand Up @@ -881,9 +895,9 @@ impl<P: RoomDataProvider> TimelineController<P> {

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);
Expand Down Expand Up @@ -973,7 +987,7 @@ impl<P: RoomDataProvider> TimelineController<P> {
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();

Expand Down
38 changes: 21 additions & 17 deletions crates/matrix-sdk-ui/src/timeline/controller/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<Profile>,
should_add_new_items: bool,
date_divider_mode: DateDividerMode,
txn_id: OwnedTransactionId,
send_handle: Option<SendHandle>,
content: TimelineEventKind,
Expand All @@ -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();
}
Expand All @@ -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
Expand All @@ -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;

Expand All @@ -272,7 +275,7 @@ impl TimelineState {
}
}

txn.adjust_day_dividers(day_divider_adjuster);
txn.adjust_date_dividers(date_divider_adjuster);

txn.commit();
}
Expand Down Expand Up @@ -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
Expand All @@ -398,15 +402,15 @@ impl TimelineStateTransaction<'_> {
position,
room_data_provider,
settings,
&mut day_divider_adjuster,
&mut date_divider_adjuster,
)
.await;

total.items_added += handle_one_res.item_added as u64;
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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand All @@ -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
Expand Down Expand Up @@ -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);
}

Expand Down
Loading
Loading