diff --git a/bindings/matrix-sdk-ffi/src/timeline/configuration.rs b/bindings/matrix-sdk-ffi/src/timeline/configuration.rs index 02e31456f..4a32e5fac 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/configuration.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/configuration.rs @@ -63,8 +63,8 @@ impl From for TimelineEventType { #[derive(uniffi::Enum)] pub enum TimelineFocus { - Live, - Event { event_id: String, num_context_events: u16 }, + Live { hide_threaded_events: bool }, + Event { event_id: String, num_context_events: u16, hide_threaded_events: bool }, Thread { root_event_id: String, num_events: u16 }, PinnedEvents { max_events_to_load: u16, max_concurrent_requests: u16 }, } @@ -76,15 +76,19 @@ impl TryFrom for matrix_sdk_ui::timeline::TimelineFocus { value: TimelineFocus, ) -> Result { match value { - TimelineFocus::Live => Ok(Self::Live), - TimelineFocus::Event { event_id, num_context_events } => { + TimelineFocus::Live { hide_threaded_events } => Ok(Self::Live { hide_threaded_events }), + TimelineFocus::Event { event_id, num_context_events, hide_threaded_events } => { let parsed_event_id = EventId::parse(&event_id).map_err(|err| FocusEventError::InvalidEventId { event_id: event_id.clone(), err: err.to_string(), })?; - Ok(Self::Event { target: parsed_event_id, num_context_events }) + Ok(Self::Event { + target: parsed_event_id, + num_context_events, + hide_threaded_events, + }) } TimelineFocus::Thread { root_event_id, num_events } => { let parsed_root_event_id = EventId::parse(&root_event_id).map_err(|err| { diff --git a/crates/matrix-sdk-ui/src/timeline/builder.rs b/crates/matrix-sdk-ui/src/timeline/builder.rs index 2528c5a23..c8dc73122 100644 --- a/crates/matrix-sdk-ui/src/timeline/builder.rs +++ b/crates/matrix-sdk-ui/src/timeline/builder.rs @@ -63,7 +63,7 @@ impl TimelineBuilder { room: room.clone(), settings: TimelineSettings::default(), unable_to_decrypt_hook: None, - focus: TimelineFocus::Live, + focus: TimelineFocus::Live { hide_threaded_events: false }, internal_id_prefix: None, } } @@ -172,7 +172,7 @@ impl TimelineBuilder { let (room_event_cache, event_cache_drop) = room.event_cache().await?; let (_, event_subscriber) = room_event_cache.subscribe().await; - let is_live = matches!(focus, TimelineFocus::Live); + let is_live = matches!(focus, TimelineFocus::Live { .. }); let is_pinned_events = matches!(focus, TimelineFocus::PinnedEvents { .. }); let is_room_encrypted = room .latest_encryption_state() diff --git a/crates/matrix-sdk-ui/src/timeline/controller/mod.rs b/crates/matrix-sdk-ui/src/timeline/controller/mod.rs index 85f87cdb4..5aaa59260 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/mod.rs @@ -183,8 +183,8 @@ impl Default for TimelineSettings { #[derive(Debug, Clone)] pub(super) enum TimelineFocusKind { - Live, - Event, + Live { hide_threaded_events: bool }, + Event { hide_threaded_events: bool }, Thread { root_event_id: OwnedEventId }, PinnedEvents, } @@ -279,13 +279,15 @@ impl TimelineController { is_room_encrypted: bool, ) -> Self { let (focus_data, focus_kind) = match focus { - TimelineFocus::Live => (TimelineFocusData::Live, TimelineFocusKind::Live), + TimelineFocus::Live { hide_threaded_events } => { + (TimelineFocusData::Live, TimelineFocusKind::Live { hide_threaded_events }) + } - TimelineFocus::Event { target, num_context_events } => { + TimelineFocus::Event { target, num_context_events, hide_threaded_events } => { let paginator = Paginator::new(room_data_provider.clone()); ( TimelineFocusData::Event { paginator, event_id: target, num_context_events }, - TimelineFocusKind::Event, + TimelineFocusKind::Event { hide_threaded_events }, ) } diff --git a/crates/matrix-sdk-ui/src/timeline/controller/state.rs b/crates/matrix-sdk-ui/src/timeline/controller/state.rs index c00e7777b..a9e126c44 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/state.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/state.rs @@ -199,13 +199,15 @@ impl TimelineState { thread_root: &Option, ) -> bool { match &timeline_focus { - TimelineFocusKind::Live => thread_root.is_none(), + TimelineFocusKind::Live { hide_threaded_events } => { + thread_root.is_none() || thread_root.is_some() && !hide_threaded_events + } TimelineFocusKind::Thread { root_event_id } => { thread_root.as_ref().is_some_and(|r| r == root_event_id) } - TimelineFocusKind::Event | TimelineFocusKind::PinnedEvents => false, + TimelineFocusKind::Event { .. } | TimelineFocusKind::PinnedEvents => false, } } diff --git a/crates/matrix-sdk-ui/src/timeline/controller/state_transaction.rs b/crates/matrix-sdk-ui/src/timeline/controller/state_transaction.rs index c2bbe0615..38bbb1479 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/state_transaction.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/state_transaction.rs @@ -408,8 +408,8 @@ impl<'a> TimelineStateTransaction<'a> { room_data_provider.is_pinned_event(event.event_id()) } - TimelineFocusKind::Event => { - if thread_root.is_some() { + TimelineFocusKind::Event { hide_threaded_events } => { + if thread_root.is_some() && *hide_threaded_events { return false; } @@ -433,7 +433,9 @@ impl<'a> TimelineStateTransaction<'a> { } } - TimelineFocusKind::Live => thread_root.is_none(), + TimelineFocusKind::Live { hide_threaded_events } => { + thread_root.is_none() || thread_root.is_some() && !hide_threaded_events + } TimelineFocusKind::Thread { root_event_id } => { event.event_id() == root_event_id diff --git a/crates/matrix-sdk-ui/src/timeline/mod.rs b/crates/matrix-sdk-ui/src/timeline/mod.rs index 771fe14ad..f25b809d4 100644 --- a/crates/matrix-sdk-ui/src/timeline/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/mod.rs @@ -126,10 +126,10 @@ pub struct Timeline { pub enum TimelineFocus { /// Focus on live events, i.e. receive events from sync and append them in /// real-time. - Live, + Live { hide_threaded_events: bool }, /// Focus on a specific event, e.g. after clicking a permalink. - Event { target: OwnedEventId, num_context_events: u16 }, + Event { target: OwnedEventId, num_context_events: u16, hide_threaded_events: bool }, /// Focus on a specific thread Thread { root_event_id: OwnedEventId, num_events: u16 }, @@ -141,7 +141,7 @@ pub enum TimelineFocus { impl TimelineFocus { pub(super) fn debug_string(&self) -> String { match self { - TimelineFocus::Live => "live".to_owned(), + TimelineFocus::Live { .. } => "live".to_owned(), TimelineFocus::Event { target, .. } => format!("permalink:{target}"), TimelineFocus::Thread { root_event_id, .. } => format!("thread:{root_event_id}"), TimelineFocus::PinnedEvents { .. } => "pinned-events".to_owned(), diff --git a/crates/matrix-sdk-ui/src/timeline/subscriber.rs b/crates/matrix-sdk-ui/src/timeline/subscriber.rs index ff7a6a77b..caf6f72dc 100644 --- a/crates/matrix-sdk-ui/src/timeline/subscriber.rs +++ b/crates/matrix-sdk-ui/src/timeline/subscriber.rs @@ -249,7 +249,7 @@ pub mod skip { /// Update the skip count if and only if the timeline has a live focus /// ([`TimelineFocusKind::Live`]). pub fn update(&self, count: usize, focus_kind: &TimelineFocusKind) { - if matches!(focus_kind, TimelineFocusKind::Live) { + if matches!(focus_kind, TimelineFocusKind::Live { .. }) { self.count.set_if_not_eq(count); } } diff --git a/crates/matrix-sdk-ui/src/timeline/tests/mod.rs b/crates/matrix-sdk-ui/src/timeline/tests/mod.rs index 026eff17a..db408c1f9 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/mod.rs @@ -123,7 +123,7 @@ impl TestTimelineBuilder { fn build(self) -> TestTimeline { let mut controller = TimelineController::new( self.provider.unwrap_or_default(), - TimelineFocus::Live, + TimelineFocus::Live { hide_threaded_events: false }, self.internal_id_prefix, self.utd_hook, self.is_room_encrypted, 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 a674a3ea7..927183404 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/focus_event.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/focus_event.rs @@ -74,6 +74,7 @@ async fn test_new_focused() { .with_focus(TimelineFocus::Event { target: target_event.to_owned(), num_context_events: 20, + hide_threaded_events: false, }) .build() .await @@ -222,6 +223,7 @@ async fn test_live_aggregations_are_reflected_on_focused_timelines() { .with_focus(TimelineFocus::Event { target: target_event.to_owned(), num_context_events: 20, + hide_threaded_events: false, }) .build() .await @@ -304,6 +306,7 @@ async fn test_focused_timeline_local_echoes() { .with_focus(TimelineFocus::Event { target: target_event.to_owned(), num_context_events: 20, + hide_threaded_events: false, }) .build() .await @@ -383,6 +386,7 @@ async fn test_focused_timeline_doesnt_show_local_echoes() { .with_focus(TimelineFocus::Event { target: target_event.to_owned(), num_context_events: 20, + hide_threaded_events: false, }) .build() .await