feat(ui,ffi): Add a new experimental-room-list-with-unified-invites feature.

The idea of this patch is to explore the possibility to unify the
`all_rooms` list with the `invites` list in `RoomListService`.
Since this is entirely experimental, it's behind a new feature
flag. The feature itself can be configured at runtime by using the
new `SyncServiceBuilder::with_unified_invites_in_room_list` builder
method, or directly with `RoomListService::new_with_unified_invites`
constructor.
This commit is contained in:
Ivan Enderlin
2024-03-11 12:05:32 +01:00
parent fd709b9d52
commit e9cca7f68d
8 changed files with 80 additions and 8 deletions

View File

@@ -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"

View File

@@ -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};

View File

@@ -1,4 +1,4 @@
use std::{convert::TryFrom, sync::Arc};
use std::sync::Arc;
use anyhow::{Context, Result};
use matrix_sdk::{

View File

@@ -95,6 +95,15 @@ impl SyncServiceBuilder {
#[uniffi::export(async_runtime = "tokio")]
impl SyncServiceBuilder {
pub fn with_unified_invites_in_room_list(
self: Arc<Self>,
with_unified_invites: bool,
) -> Arc<Self> {
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<Self>, app_identifier: Option<String>) -> Arc<Self> {
let this = unwrap_or_clone_arc(self);
let builder = this.builder.with_cross_process_lock(app_identifier);

View File

@@ -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"]

View File

@@ -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, Error> {
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, Error> {
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, Error> {
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<Self, Error> {
async fn new_internal(
client: Client,
with_encryption: bool,
#[cfg(feature = "experimental-room-list-with-unified-invites")] with_unified_invites: bool,
) -> Result<Self, Error> {
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()],
})))

View File

@@ -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)?;

View File

@@ -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<SyncService, Error> {
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,