From 823e3e039243dba984d9ad372a03c2d404027bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 5 Aug 2024 09:57:40 +0200 Subject: [PATCH] ffi: add `RoomPinnedEventsChange` and a diffing step to know what happened in the last pinning/unpinning events action --- .../matrix-sdk-ffi/src/timeline/content.rs | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/timeline/content.rs b/bindings/matrix-sdk-ffi/src/timeline/content.rs index dad31e94742..87b464f6732 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/content.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/content.rs @@ -12,7 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{collections::HashMap, sync::Arc}; +use std::{ + collections::{HashMap, HashSet}, + hash::Hash, + sync::Arc, +}; use matrix_sdk::{crypto::types::events::UtdCause, room::power_levels::power_level_user_changes}; use matrix_sdk_ui::timeline::{PollResult, TimelineDetails}; @@ -338,7 +342,7 @@ pub enum OtherState { RoomHistoryVisibility, RoomJoinRules, RoomName { name: Option }, - RoomPinnedEvents, + RoomPinnedEvents { change: RoomPinnedEventsChange }, RoomPowerLevels { users: HashMap, previous: Option> }, RoomServerAcl, RoomThirdPartyInvite { display_name: Option }, @@ -349,6 +353,13 @@ pub enum OtherState { Custom { event_type: String }, } +#[derive(Clone, uniffi::Enum)] +pub enum RoomPinnedEventsChange { + Added, + Removed, + Changed, +} + impl From<&matrix_sdk_ui::timeline::AnyOtherFullStateEventContent> for OtherState { fn from(content: &matrix_sdk_ui::timeline::AnyOtherFullStateEventContent) -> Self { use matrix_sdk::ruma::events::FullStateEventContent as FullContent; @@ -381,7 +392,45 @@ impl From<&matrix_sdk_ui::timeline::AnyOtherFullStateEventContent> for OtherStat }; Self::RoomName { name } } - Content::RoomPinnedEvents(_) => Self::RoomPinnedEvents, + Content::RoomPinnedEvents(c) => { + match c { + FullContent::Original { content, prev_content } => { + let change = if let Some(prev_content) = prev_content { + let mut new_pinned = HashSet::from_iter(&content.pinned); + if let Some(raw_old_pinned) = &prev_content.pinned { + let mut old_pinned = HashSet::from_iter(raw_old_pinned); + + // Added elements will be kept in new_pinned, previous ones in + // old_pinned instead + old_pinned.retain(|item| new_pinned.remove(item)); + + let added = !new_pinned.is_empty(); + let removed = old_pinned.len() < raw_old_pinned.len(); + if added && removed { + RoomPinnedEventsChange::Changed + } else if added { + RoomPinnedEventsChange::Added + } else if removed { + RoomPinnedEventsChange::Removed + } else { + // Any other case + RoomPinnedEventsChange::Changed + } + } else { + // We don't know the previous state, so let's assume a generic + // change + RoomPinnedEventsChange::Changed + } + } else { + RoomPinnedEventsChange::Added + }; + Self::RoomPinnedEvents { change } + } + FullContent::Redacted(_) => { + Self::RoomPinnedEvents { change: RoomPinnedEventsChange::Changed } + } + } + } Content::RoomPowerLevels(c) => match c { FullContent::Original { content, prev_content } => Self::RoomPowerLevels { users: power_level_user_changes(content, prev_content)