Wasm improvements for the bindings

This patch improves the Wasm support of the matrix-sdk-ffi crate.

First a uniffi feature needed to be enabled.
Secondly a bunch of methods which don't work under Wasm have been stubbed out.

Signed-off-by: MTRNord <MTRNord@users.noreply.github.com>
Co-authored-by: MTRNord <MTRNord@users.noreply.github.com>
This commit is contained in:
Marcel-Nordeck
2025-11-27 15:46:33 +01:00
committed by GitHub
parent 4585d5f4d8
commit 107fc07d08
3 changed files with 112 additions and 50 deletions
+2 -1
View File
@@ -89,7 +89,8 @@ oauth2.workspace = true
[target.'cfg(target_family = "wasm")'.dependencies]
console_error_panic_hook = "0.1.7"
tokio = { workspace = true, features = ["sync", "macros"] }
uniffi.workspace = true
uniffi = { workspace = true, features = ["wasm-unstable-single-threaded"] }
futures-executor.workspace = true
[target.'cfg(not(target_family = "wasm"))'.dependencies]
async-compat.workspace = true
+84 -43
View File
@@ -1016,7 +1016,6 @@ impl Client {
}
}
#[cfg(not(target_family = "wasm"))]
#[matrix_sdk_ffi_macros::export]
impl Client {
/// Retrieves a media file from the media source
@@ -1030,22 +1029,60 @@ impl Client {
use_cache: bool,
temp_dir: Option<String>,
) -> Result<Arc<MediaFileHandle>, ClientError> {
let source = (*media_source).clone();
let mime_type: mime::Mime = mime_type.parse()?;
#[cfg(not(target_family = "wasm"))]
{
let source = (*media_source).clone();
let mime_type: mime::Mime = mime_type.parse()?;
let handle = self
.inner
.media()
.get_media_file(
&MediaRequestParameters { source: source.media_source, format: MediaFormat::File },
filename,
&mime_type,
use_cache,
temp_dir,
)
.await?;
let handle = self
.inner
.media()
.get_media_file(
&MediaRequestParameters {
source: source.media_source,
format: MediaFormat::File,
},
filename,
&mime_type,
use_cache,
temp_dir,
)
.await?;
Ok(Arc::new(MediaFileHandle::new(handle)))
Ok(Arc::new(MediaFileHandle::new(handle)))
}
/// MediaFileHandle uses SdkMediaFileHandle which requires an
/// intermediate TempFile which is not available on wasm
/// platforms due to lack of an accessible file system.
#[cfg(target_family = "wasm")]
Err(ClientError::Generic {
msg: "get_media_file is not supported on wasm platforms".to_owned(),
details: None,
})
}
pub async fn set_display_name(&self, name: String) -> Result<(), ClientError> {
#[cfg(not(target_family = "wasm"))]
{
self.inner
.account()
.set_display_name(Some(name.as_str()))
.await
.context("Unable to set display name")?;
}
#[cfg(target_family = "wasm")]
{
self.inner.account().set_display_name(Some(name.as_str())).await.map_err(|e| {
ClientError::Generic {
msg: "Unable to set display name".to_owned(),
details: Some(e.to_string()),
}
})?;
}
Ok(())
}
}
@@ -1181,15 +1218,6 @@ impl Client {
Ok(display_name)
}
pub async fn set_display_name(&self, name: String) -> Result<(), ClientError> {
self.inner
.account()
.set_display_name(Some(name.as_str()))
.await
.context("Unable to set display name")?;
Ok(())
}
pub async fn upload_avatar(&self, mime_type: String, data: Vec<u8>) -> Result<(), ClientError> {
let mime: Mime = mime_type.parse()?;
self.inner.account().upload_avatar(&mime, data).await?;
@@ -2541,25 +2569,25 @@ fn gen_transaction_id() -> String {
/// A file handle that takes ownership of a media file on disk. When the handle
/// is dropped, the file will be removed from the disk.
#[cfg(not(target_family = "wasm"))]
#[derive(uniffi::Object)]
pub struct MediaFileHandle {
#[cfg(not(target_family = "wasm"))]
inner: std::sync::RwLock<Option<SdkMediaFileHandle>>,
}
#[cfg(not(target_family = "wasm"))]
impl MediaFileHandle {
#[cfg(not(target_family = "wasm"))]
fn new(handle: SdkMediaFileHandle) -> Self {
Self { inner: std::sync::RwLock::new(Some(handle)) }
}
}
#[cfg(not(target_family = "wasm"))]
#[matrix_sdk_ffi_macros::export]
impl MediaFileHandle {
/// Get the media file's path.
pub fn path(&self) -> Result<String, ClientError> {
Ok(self
#[cfg(not(target_family = "wasm"))]
return Ok(self
.inner
.read()
.unwrap()
@@ -2568,24 +2596,37 @@ impl MediaFileHandle {
.path()
.to_str()
.unwrap()
.to_owned())
.to_owned());
#[cfg(target_family = "wasm")]
Err(ClientError::Generic {
msg: "MediaFileHandle.path() is not supported on WASM targets".to_string(),
details: None,
})
}
pub fn persist(&self, path: String) -> Result<bool, ClientError> {
let mut guard = self.inner.write().unwrap();
Ok(
match guard
.take()
.context("MediaFileHandle was already persisted")?
.persist(path.as_ref())
{
Ok(_) => true,
Err(e) => {
*guard = Some(e.file);
false
}
},
)
#[cfg(not(target_family = "wasm"))]
{
let mut guard = self.inner.write().unwrap();
Ok(
match guard
.take()
.context("MediaFileHandle was already persisted")?
.persist(path.as_ref())
{
Ok(_) => true,
Err(e) => {
*guard = Some(e.file);
false
}
},
)
}
#[cfg(target_family = "wasm")]
Err(ClientError::Generic {
msg: "MediaFileHandle.persist() is not supported on WASM targets".to_string(),
details: None,
})
}
}
+26 -6
View File
@@ -152,15 +152,20 @@ impl ClientBuilder {
system_is_memory_constrained: false,
username: None,
homeserver_cfg: None,
#[cfg(not(target_family = "wasm"))]
user_agent: None,
sliding_sync_version_builder: SlidingSyncVersionBuilder::None,
#[cfg(not(target_family = "wasm"))]
proxy: None,
#[cfg(not(target_family = "wasm"))]
disable_ssl_verification: false,
disable_automatic_token_refresh: false,
cross_process_store_locks_holder_name: None,
enable_oidc_refresh_lock: false,
session_delegate: None,
#[cfg(not(target_family = "wasm"))]
additional_root_certificates: Default::default(),
#[cfg(not(target_family = "wasm"))]
disable_built_in_root_certificates: false,
encryption_settings: EncryptionSettings {
auto_enable_cross_signing: false,
@@ -559,18 +564,23 @@ impl ClientBuilder {
}
}
#[cfg(not(target_family = "wasm"))]
#[matrix_sdk_ffi_macros::export]
impl ClientBuilder {
pub fn proxy(self: Arc<Self>, url: String) -> Arc<Self> {
let mut builder = unwrap_or_clone_arc(self);
builder.proxy = Some(url);
#[cfg(not(target_family = "wasm"))]
{
builder.proxy = Some(url);
}
Arc::new(builder)
}
pub fn disable_ssl_verification(self: Arc<Self>) -> Arc<Self> {
let mut builder = unwrap_or_clone_arc(self);
builder.disable_ssl_verification = true;
#[cfg(not(target_family = "wasm"))]
{
builder.disable_ssl_verification = true;
}
Arc::new(builder)
}
@@ -579,7 +589,11 @@ impl ClientBuilder {
certificates: Vec<CertificateBytes>,
) -> Arc<Self> {
let mut builder = unwrap_or_clone_arc(self);
builder.additional_root_certificates = certificates;
#[cfg(not(target_family = "wasm"))]
{
builder.additional_root_certificates = certificates;
}
Arc::new(builder)
}
@@ -589,13 +603,19 @@ impl ClientBuilder {
/// [`add_root_certificates`][ClientBuilder::add_root_certificates].
pub fn disable_built_in_root_certificates(self: Arc<Self>) -> Arc<Self> {
let mut builder = unwrap_or_clone_arc(self);
builder.disable_built_in_root_certificates = true;
#[cfg(not(target_family = "wasm"))]
{
builder.disable_built_in_root_certificates = true;
}
Arc::new(builder)
}
pub fn user_agent(self: Arc<Self>, user_agent: String) -> Arc<Self> {
let mut builder = unwrap_or_clone_arc(self);
builder.user_agent = Some(user_agent);
#[cfg(not(target_family = "wasm"))]
{
builder.user_agent = Some(user_agent);
}
Arc::new(builder)
}
}