diff --git a/bindings/matrix-sdk-ffi/Cargo.toml b/bindings/matrix-sdk-ffi/Cargo.toml index 4ca3307e2..502cf3407 100644 --- a/bindings/matrix-sdk-ffi/Cargo.toml +++ b/bindings/matrix-sdk-ffi/Cargo.toml @@ -29,7 +29,7 @@ eyeball-im = { workspace = true } extension-trait = "1.0.1" futures-core = { workspace = true } futures-util = { workspace = true } -matrix-sdk-ui = { workspace = true, features = ["e2e-encryption", "uniffi"] } +matrix-sdk-ui = { workspace = true, features = ["e2e-encryption", "uniffi", "experimental-room-list-with-unified-invites"] } mime = "0.3.16" once_cell = { workspace = true } opentelemetry = "0.21.0" diff --git a/bindings/matrix-sdk-ffi/src/error.rs b/bindings/matrix-sdk-ffi/src/error.rs index 80f7de2ef..27e7d9ed7 100644 --- a/bindings/matrix-sdk-ffi/src/error.rs +++ b/bindings/matrix-sdk-ffi/src/error.rs @@ -1,7 +1,7 @@ use std::fmt::Display; use matrix_sdk::{ - self, encryption::CryptoStoreError, event_cache::EventCacheError, oidc::OidcError, HttpError, + encryption::CryptoStoreError, event_cache::EventCacheError, oidc::OidcError, HttpError, IdParseError, NotificationSettingsError as SdkNotificationSettingsError, StoreError, }; use matrix_sdk_ui::{encryption_sync_service, notification_client, sync_service, timeline}; diff --git a/bindings/matrix-sdk-ffi/src/room.rs b/bindings/matrix-sdk-ffi/src/room.rs index 73ee3815a..375f0a2e0 100644 --- a/bindings/matrix-sdk-ffi/src/room.rs +++ b/bindings/matrix-sdk-ffi/src/room.rs @@ -1,4 +1,4 @@ -use std::{convert::TryFrom, sync::Arc}; +use std::sync::Arc; use anyhow::{Context, Result}; use matrix_sdk::{ diff --git a/bindings/matrix-sdk-ffi/src/sync_service.rs b/bindings/matrix-sdk-ffi/src/sync_service.rs index b1441ea6c..069966801 100644 --- a/bindings/matrix-sdk-ffi/src/sync_service.rs +++ b/bindings/matrix-sdk-ffi/src/sync_service.rs @@ -95,6 +95,15 @@ impl SyncServiceBuilder { #[uniffi::export(async_runtime = "tokio")] impl SyncServiceBuilder { + pub fn with_unified_invites_in_room_list( + self: Arc, + with_unified_invites: bool, + ) -> Arc { + let this = unwrap_or_clone_arc(self); + let builder = this.builder.with_unified_invites_in_room_list(with_unified_invites); + Arc::new(Self { builder }) + } + pub fn with_cross_process_lock(self: Arc, app_identifier: Option) -> Arc { let this = unwrap_or_clone_arc(self); let builder = this.builder.with_cross_process_lock(app_identifier); diff --git a/crates/matrix-sdk-ui/Cargo.toml b/crates/matrix-sdk-ui/Cargo.toml index f18b6edb5..1dd41ae72 100644 --- a/crates/matrix-sdk-ui/Cargo.toml +++ b/crates/matrix-sdk-ui/Cargo.toml @@ -12,6 +12,9 @@ default = ["e2e-encryption", "native-tls"] e2e-encryption = ["matrix-sdk/e2e-encryption"] +# This feature will unify the `invites` list with the `all_rooms` list. +experimental-room-list-with-unified-invites = [] + native-tls = ["matrix-sdk/native-tls"] rustls-tls = ["matrix-sdk/rustls-tls"] diff --git a/crates/matrix-sdk-ui/src/room_list_service/mod.rs b/crates/matrix-sdk-ui/src/room_list_service/mod.rs index afd28bc2f..5d03cc650 100644 --- a/crates/matrix-sdk-ui/src/room_list_service/mod.rs +++ b/crates/matrix-sdk-ui/src/room_list_service/mod.rs @@ -136,7 +136,24 @@ impl RoomListService { /// This won't start an encryption sync, and it's the user's responsibility /// to create one in this case using `EncryptionSync`. pub async fn new(client: Client) -> Result { - Self::new_internal(client, false).await + Self::new_internal( + client, + false, + #[cfg(feature = "experimental-room-list-with-unified-invites")] + false, + ) + .await + } + + /// Create a new `RoomList` that disables encryption, and enables the + /// unified invites (i.e. invites are part of the `all_rooms` list; side + /// note: the `invites` list is still present). + #[cfg(feature = "experimental-room-list-with-unified-invites")] + pub async fn new_with_unified_invites( + client: Client, + with_unified_invites: bool, + ) -> Result { + Self::new_internal(client, false, with_unified_invites).await } /// Create a new `RoomList` that enables encryption. @@ -144,10 +161,20 @@ impl RoomListService { /// This will include syncing the encryption information, so there must not /// be any instance of `EncryptionSync` running in the background. pub async fn new_with_encryption(client: Client) -> Result { - Self::new_internal(client, true).await + Self::new_internal( + client, + true, + #[cfg(feature = "experimental-room-list-with-unified-invites")] + false, + ) + .await } - async fn new_internal(client: Client, with_encryption: bool) -> Result { + async fn new_internal( + client: Client, + with_encryption: bool, + #[cfg(feature = "experimental-room-list-with-unified-invites")] with_unified_invites: bool, + ) -> Result { let mut builder = client .sliding_sync("room-list") .map_err(Error::SlidingSync)? @@ -185,6 +212,8 @@ impl RoomListService { (StateEventType::RoomMember, "$ME".to_owned()), (StateEventType::RoomPowerLevels, "".to_owned()), ]), + #[cfg(feature = "experimental-room-list-with-unified-invites")] + with_unified_invites, )) .await .map_err(Error::SlidingSync)? @@ -479,11 +508,15 @@ impl RoomListService { /// properties, so that they are exactly the same. fn configure_all_or_visible_rooms_list( list_builder: SlidingSyncListBuilder, + #[cfg(feature = "experimental-room-list-with-unified-invites")] with_invites: bool, ) -> SlidingSyncListBuilder { + #[cfg(not(feature = "experimental-room-list-with-unified-invites"))] + let with_invites = false; + list_builder .sort(vec!["by_recency".to_owned(), "by_name".to_owned()]) .filters(Some(assign!(SyncRequestListFilters::default(), { - is_invite: Some(false), + is_invite: Some(with_invites), is_tombstoned: Some(false), not_room_types: vec!["m.space".to_owned()], }))) diff --git a/crates/matrix-sdk-ui/src/room_list_service/state.rs b/crates/matrix-sdk-ui/src/room_list_service/state.rs index 04faf8798..f2c1991d7 100644 --- a/crates/matrix-sdk-ui/src/room_list_service/state.rs +++ b/crates/matrix-sdk-ui/src/room_list_service/state.rs @@ -120,6 +120,8 @@ impl Action for AddVisibleRooms { (StateEventType::RoomEncryption, "".to_owned()), (StateEventType::RoomMember, "$LAZY".to_owned()), ]), + #[cfg(feature = "experimental-room-list-with-unified-invites")] + false, )) .await .map_err(Error::SlidingSync)?; diff --git a/crates/matrix-sdk-ui/src/sync_service.rs b/crates/matrix-sdk-ui/src/sync_service.rs index d86343a4c..25b36baa6 100644 --- a/crates/matrix-sdk-ui/src/sync_service.rs +++ b/crates/matrix-sdk-ui/src/sync_service.rs @@ -435,6 +435,10 @@ pub struct SyncServiceBuilder { /// SDK client. client: Client, + /// Whether we want to unify `all_rooms` and `invites`. + #[cfg(feature = "experimental-room-list-with-unified-invites")] + with_unified_invites_in_room_list: bool, + /// Is the cross-process lock for the crypto store enabled? with_cross_process_lock: bool, @@ -445,7 +449,20 @@ pub struct SyncServiceBuilder { impl SyncServiceBuilder { fn new(client: Client) -> Self { - Self { client, with_cross_process_lock: false, identifier: "app".to_owned() } + Self { + client, + #[cfg(feature = "experimental-room-list-with-unified-invites")] + with_unified_invites_in_room_list: false, + with_cross_process_lock: false, + identifier: "app".to_owned(), + } + } + + #[cfg(feature = "experimental-room-list-with-unified-invites")] + pub fn with_unified_invites_in_room_list(mut self, with_unified_invites: bool) -> Self { + self.with_unified_invites_in_room_list = with_unified_invites; + + self } /// Enables the cross-process lock, if the sync service is being built in a @@ -475,8 +492,16 @@ impl SyncServiceBuilder { pub async fn build(self) -> Result { let encryption_sync_permit = Arc::new(AsyncMutex::new(EncryptionSyncPermit::new())); + #[cfg(not(feature = "experimental-room-list-with-unified-invites"))] let room_list = RoomListService::new(self.client.clone()).await?; + #[cfg(feature = "experimental-room-list-with-unified-invites")] + let room_list = RoomListService::new_with_unified_invites( + self.client.clone(), + self.with_unified_invites_in_room_list, + ) + .await?; + let encryption_sync = Arc::new( EncryptionSyncService::new( self.identifier,