Skip to content

feat: MSC 4278 implementation #5014

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

Closed
wants to merge 1 commit into from
Closed
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
24 changes: 8 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ reqwest = { version = "0.12.12", default-features = false }
rmp-serde = "1.3.0"
# Be careful to use commits from the https://github.com/ruma/ruma/tree/ruma-0.12
# branch until a proper release with breaking changes happens.
ruma = { version = "0.12.2", features = [
ruma = { git = "https://github.com/ruma/ruma", rev = "689d9613a985edc089b5b729e6d9362f09b5df4f", features = [
"client-api-c",
"compat-upload-signatures",
"compat-user-id",
Expand All @@ -74,8 +74,9 @@ ruma = { version = "0.12.2", features = [
"unstable-msc4075",
"unstable-msc4140",
"unstable-msc4171",
] }
ruma-common = "0.15.2"
"unstable-msc4278",
] }
ruma-common = { git = "https://github.com/ruma/ruma", rev = "689d9613a985edc089b5b729e6d9362f09b5df4f" }
serde = "1.0.217"
serde_html_form = "0.2.7"
serde_json = "1.0.138"
Expand Down
2 changes: 1 addition & 1 deletion bindings/matrix-sdk-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ matrix-sdk-ffi-macros = { workspace = true }
matrix-sdk-ui = { workspace = true, features = ["uniffi"] }
mime = "0.3.16"
once_cell = { workspace = true }
ruma = { workspace = true, features = ["html", "unstable-unspecified", "unstable-msc3488", "compat-unset-avatar", "unstable-msc3245-v1-compat"] }
ruma = { workspace = true, features = ["html", "unstable-unspecified", "unstable-msc3488", "compat-unset-avatar", "unstable-msc3245-v1-compat", "unstable-msc4278"] }
serde = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
Expand Down
88 changes: 88 additions & 0 deletions bindings/matrix-sdk-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ use ruma::{
events::{
ignored_user_list::IgnoredUserListEventContent,
key::verification::request::ToDeviceKeyVerificationRequestEvent,
media_preview_config::{
InviteAvatars as RumaInviteAvatars, MediaPreviews as RumaMediaPreviews,
},
room::{
history_visibility::RoomHistoryVisibilityEventContent,
join_rules::{
Expand Down Expand Up @@ -1207,6 +1210,91 @@ impl Client {
pub async fn is_report_room_api_supported(&self) -> Result<bool, ClientError> {
Ok(self.inner.server_versions().await?.contains(&ruma::api::MatrixVersion::V1_13))
}

/// Get the media previews display policy setting.
pub async fn get_media_previews(&self) -> Result<MediaPreviews, ClientError> {
let media_previews = self.inner.account().get_media_previews_setting().await?;
Ok(media_previews.into())
}

/// Set the media previews display policy setting.
pub async fn set_media_previews(
&self,
media_previews: MediaPreviews,
) -> Result<(), ClientError> {
self.inner.account().set_media_previews_setting(media_previews.into()).await?;
Ok(())
}

/// Get the invite avatars display policy setting.
pub async fn get_invite_avatars(&self) -> Result<InviteAvatars, ClientError> {
let invite_avatars = self.inner.account().get_invite_avatars_setting().await?;
Ok(invite_avatars.into())
}

/// Set the invite avatars display policy setting.
pub async fn set_invite_avatars(
&self,
invite_avatars: InviteAvatars,
) -> Result<(), ClientError> {
self.inner.account().set_invite_avatars_setting(invite_avatars.into()).await?;
Ok(())
}
}

#[derive(uniffi::Enum)]
pub enum MediaPreviews {
On,
Private,
Off,
}

impl From<RumaMediaPreviews> for MediaPreviews {
fn from(value: RumaMediaPreviews) -> Self {
match value {
RumaMediaPreviews::On => MediaPreviews::On,
RumaMediaPreviews::Private => MediaPreviews::Private,
RumaMediaPreviews::Off => MediaPreviews::Off,
// Use the default value of On for unhandled cases.
_ => MediaPreviews::On,
}
}
}

impl From<MediaPreviews> for RumaMediaPreviews {
fn from(value: MediaPreviews) -> Self {
match value {
MediaPreviews::On => RumaMediaPreviews::On,
MediaPreviews::Private => RumaMediaPreviews::Private,
MediaPreviews::Off => RumaMediaPreviews::Off,
}
}
}

#[derive(uniffi::Enum)]
pub enum InviteAvatars {
On,
Off,
}

impl From<RumaInviteAvatars> for InviteAvatars {
fn from(value: RumaInviteAvatars) -> Self {
match value {
RumaInviteAvatars::On => InviteAvatars::On,
RumaInviteAvatars::Off => InviteAvatars::Off,
// Use the default value of On for unhandled cases.
_ => InviteAvatars::On,
}
}
}

impl From<InviteAvatars> for RumaInviteAvatars {
fn from(value: InviteAvatars) -> Self {
match value {
InviteAvatars::On => RumaInviteAvatars::On,
InviteAvatars::Off => RumaInviteAvatars::Off,
}
}
}

#[matrix_sdk_ffi_macros::export(callback_interface)]
Expand Down
1 change: 1 addition & 0 deletions crates/matrix-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ ruma = { workspace = true, features = [
"unstable-msc4230",
"unstable-msc2967",
"unstable-msc4108",
"unstable-msc4278",
] }
serde = { workspace = true }
serde_html_form = { workspace = true }
Expand Down
86 changes: 86 additions & 0 deletions crates/matrix-sdk/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ use ruma::{
assign,
events::{
ignored_user_list::{IgnoredUser, IgnoredUserListEventContent},
media_preview_config::{
InviteAvatars, MediaPreviewConfigEventContent, MediaPreviews,
UnstableMediaPreviewConfigEventContent,
},
push_rules::PushRulesEventContent,
room::MediaSource,
AnyGlobalAccountDataEventContent, GlobalAccountDataEventContent,
Expand Down Expand Up @@ -916,6 +920,88 @@ impl Account {
Ok(ignored_user_list)
}

/// Set the media previews display policy for the account.
///
/// This is an unstable event, so we always default to setting the unstable
/// version of the event for now.
pub async fn set_media_previews_setting(&self, new_setting: MediaPreviews) -> Result<()> {
let mut media_preview_config_to_update =
self.get_unstable_media_preview_config().await?.unwrap_or_else(|| {
UnstableMediaPreviewConfigEventContent::new(Default::default(), Default::default())
});
media_preview_config_to_update.media_previews = new_setting;

// Updating the account data
self.set_account_data(media_preview_config_to_update).await?;
// TODO: I think I should reset all the storage and perform a new local sync
// here but I don't know how
Comment on lines +936 to +937
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really sure what to do here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was actually looking at this recently and was surprised to see the store not getting updated when we set some account data. @poljar is there a way to tell the store that a piece of account data has been changed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the assumption is that a sync is running. Or maybe I'm misunderstanding what a local sync would be?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just looked at the the ignore_user and unignore_user function which has the exact same comment. So I assume this is a known issue maybe? I imagine that since the sync might take some time this means that if we change the value and immediately check the account data again, it won't be updated right?
And if so how long may it take to be update, are we talking about seconds or milliseconds?
Since this may affect how we design the UI.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as a sync takes, you can subscribe to listen to account data events. There's actually a PR in flight to add exactly this to the bindings: #4994.

I suppose you'll have to subscribe to this anyways, in case the value gets updated on another device.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice this would be very useful!

Ok(())
}

/// Set the avatars in invite requests display policy for the account.
///
/// This is an unstable event, so we always default to setting the unstable
/// version of the event for now.
pub async fn set_invite_avatars_setting(&self, new_setting: InviteAvatars) -> Result<()> {
let mut media_preview_config_to_update =
self.get_unstable_media_preview_config().await?.unwrap_or_else(|| {
UnstableMediaPreviewConfigEventContent::new(Default::default(), Default::default())
});
media_preview_config_to_update.invite_avatars = new_setting;
// Updating the account data
self.set_account_data(media_preview_config_to_update).await?;
// TODO: I think I should reset all the storage and perform a new local sync
// here but I don't know how
Comment on lines +953 to +954
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really sure what to do here

Ok(())
}

/// Get the current media previews display policy for the account.
pub async fn get_media_previews_setting(&self) -> Result<MediaPreviews> {
if let Some(media_preview_config) = self.get_media_preview_config().await? {
Ok(media_preview_config.media_previews)
} else if let Some(unstable_media_preview_config) =
self.get_unstable_media_preview_config().await?
{
Ok(unstable_media_preview_config.media_previews)
} else {
Ok(Default::default())
}
}

/// Get the current avatars in invite requests display policy for the
/// account.
pub async fn get_invite_avatars_setting(&self) -> Result<InviteAvatars> {
if let Some(media_preview_config) = self.get_media_preview_config().await? {
Ok(media_preview_config.invite_avatars)
} else if let Some(unstable_media_preview_config) =
self.get_unstable_media_preview_config().await?
{
Ok(unstable_media_preview_config.invite_avatars)
} else {
Ok(Default::default())
}
}

async fn get_unstable_media_preview_config(
&self,
) -> Result<Option<UnstableMediaPreviewConfigEventContent>> {
let unstable_media_preview_config = self
.account_data::<UnstableMediaPreviewConfigEventContent>()
.await?
.map(|c| c.deserialize())
.transpose()?;
Ok(unstable_media_preview_config)
}

async fn get_media_preview_config(&self) -> Result<Option<MediaPreviewConfigEventContent>> {
let media_preview_config = self
.account_data::<MediaPreviewConfigEventContent>()
.await?
.map(|c| c.deserialize())
.transpose()?;
Ok(media_preview_config)
}

/// Get the current push rules from storage.
///
/// If no push rules event was found, or it fails to deserialize, a ruleset
Expand Down
Loading