Skip to content

Commit edd371b

Browse files
pixlwavepoljar
authored andcommitted
ffi: Refactor ClientBuilder::build_with_qr_code into Client::login_with_qr_code
The FFI's API now matches the SDK and allows for checks to be made on the Client before logging in.
1 parent 817f32e commit edd371b

File tree

3 files changed

+48
-67
lines changed

3 files changed

+48
-67
lines changed

bindings/matrix-sdk-ffi/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.
66

77
## [Unreleased] - ReleaseDate
88

9+
### Breaking changes:
10+
11+
- `ClientBuilder::build_with_qr_code` has been removed. Instead, the Client should be built by passing
12+
`QrCodeData::server_name` to `ClientBuilder::server_name_or_homeserver_url`, after which QR login can be performed by
13+
calling `Client::login_with_qr_code`. ([#5388](https://github.com/matrix-org/matrix-rust-sdk/pull/5388))
14+
915
## [0.13.0] - 2025-07-10
1016

1117
### Features

bindings/matrix-sdk-ffi/src/client.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ use crate::{
9696
encryption::Encryption,
9797
notification::NotificationClient,
9898
notification_settings::NotificationSettings,
99+
qr_code::{HumanQrLoginError, QrCodeData, QrLoginProgressListener},
99100
room::{RoomHistoryVisibility, RoomInfoListener},
100101
room_directory_search::RoomDirectorySearch,
101102
room_preview::RoomPreview,
@@ -494,6 +495,45 @@ impl Client {
494495
Ok(())
495496
}
496497

498+
/// Log in using the provided [`QrCodeData`]. The `Client` must be built
499+
/// by providing [`QrCodeData::server_name`] as the server name for this
500+
/// login to succeed.
501+
///
502+
/// This method uses the login mechanism described in [MSC4108]. As such
503+
/// this method requires OAuth 2.0 support as well as sliding sync support.
504+
///
505+
/// The usage of the progress_listener is required to transfer the
506+
/// [`CheckCode`] to the existing client.
507+
///
508+
/// [MSC4108]: https://github.com/matrix-org/matrix-spec-proposals/pull/4108
509+
pub async fn login_with_qr_code(
510+
self: Arc<Self>,
511+
qr_code_data: &QrCodeData,
512+
oidc_configuration: &OidcConfiguration,
513+
progress_listener: Box<dyn QrLoginProgressListener>,
514+
) -> Result<(), HumanQrLoginError> {
515+
let registration_data = oidc_configuration
516+
.registration_data()
517+
.map_err(|_| HumanQrLoginError::OidcMetadataInvalid)?;
518+
519+
let oauth = self.inner.oauth();
520+
let login = oauth.login_with_qr_code(&qr_code_data.inner, Some(&registration_data));
521+
522+
let mut progress = login.subscribe_to_progress();
523+
524+
// We create this task, which will get cancelled once it's dropped, just in case
525+
// the progress stream doesn't end.
526+
let _progress_task = TaskHandle::new(get_runtime_handle().spawn(async move {
527+
while let Some(state) = progress.next().await {
528+
progress_listener.on_update(state.into());
529+
}
530+
}));
531+
532+
login.await?;
533+
534+
Ok(())
535+
}
536+
497537
/// Restores the client from a `Session`.
498538
///
499539
/// It reloads the entire set of rooms from the previous session.

bindings/matrix-sdk-ffi/src/client_builder.rs

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
use std::{fs, num::NonZeroUsize, path::Path, sync::Arc, time::Duration};
22

3-
use futures_util::StreamExt;
43
#[cfg(not(target_family = "wasm"))]
54
use matrix_sdk::reqwest::Certificate;
65
use matrix_sdk::{
7-
crypto::{
8-
types::qr_login::QrCodeModeData, CollectStrategy, DecryptionSettings, TrustRequirement,
9-
},
6+
crypto::{CollectStrategy, DecryptionSettings, TrustRequirement},
107
encryption::{BackupDownloadStrategy, EncryptionSettings},
118
event_cache::EventCacheError,
129
ruma::{ServerName, UserId},
@@ -22,15 +19,7 @@ use tracing::{debug, error};
2219
use zeroize::Zeroizing;
2320

2421
use super::client::Client;
25-
use crate::{
26-
authentication::OidcConfiguration,
27-
client::ClientSessionDelegate,
28-
error::ClientError,
29-
helpers::unwrap_or_clone_arc,
30-
qr_code::{HumanQrLoginError, QrCodeData, QrLoginProgressListener},
31-
runtime::get_runtime_handle,
32-
task_handle::TaskHandle,
33-
};
22+
use crate::{client::ClientSessionDelegate, error::ClientError, helpers::unwrap_or_clone_arc};
3423

3524
/// A list of bytes containing a certificate in DER or PEM form.
3625
pub type CertificateBytes = Vec<u8>;
@@ -582,60 +571,6 @@ impl ClientBuilder {
582571
.await?,
583572
))
584573
}
585-
586-
/// Finish the building of the client and attempt to log in using the
587-
/// provided [`QrCodeData`].
588-
///
589-
/// This method will build the client and immediately attempt to log the
590-
/// client in using the provided [`QrCodeData`] using the login
591-
/// mechanism described in [MSC4108]. As such this methods requires OAuth
592-
/// 2.0 support as well as sliding sync support.
593-
///
594-
/// The usage of the progress_listener is required to transfer the
595-
/// [`CheckCode`] to the existing client.
596-
///
597-
/// [MSC4108]: https://github.com/matrix-org/matrix-spec-proposals/pull/4108
598-
pub async fn build_with_qr_code(
599-
self: Arc<Self>,
600-
qr_code_data: &QrCodeData,
601-
oidc_configuration: &OidcConfiguration,
602-
progress_listener: Box<dyn QrLoginProgressListener>,
603-
) -> Result<Arc<Client>, HumanQrLoginError> {
604-
let QrCodeModeData::Reciprocate { server_name } = &qr_code_data.inner.mode_data else {
605-
return Err(HumanQrLoginError::OtherDeviceNotSignedIn);
606-
};
607-
608-
let builder = self.server_name_or_homeserver_url(server_name.to_owned());
609-
610-
let client = builder.build().await.map_err(|e| match e {
611-
ClientBuildError::SlidingSync(_) => HumanQrLoginError::SlidingSyncNotAvailable,
612-
_ => {
613-
error!("Couldn't build the client {e:?}");
614-
HumanQrLoginError::Unknown
615-
}
616-
})?;
617-
618-
let registration_data = oidc_configuration
619-
.registration_data()
620-
.map_err(|_| HumanQrLoginError::OidcMetadataInvalid)?;
621-
622-
let oauth = client.inner.oauth();
623-
let login = oauth.login_with_qr_code(&qr_code_data.inner, Some(&registration_data));
624-
625-
let mut progress = login.subscribe_to_progress();
626-
627-
// We create this task, which will get cancelled once it's dropped, just in case
628-
// the progress stream doesn't end.
629-
let _progress_task = TaskHandle::new(get_runtime_handle().spawn(async move {
630-
while let Some(state) = progress.next().await {
631-
progress_listener.on_update(state.into());
632-
}
633-
}));
634-
635-
login.await?;
636-
637-
Ok(client)
638-
}
639574
}
640575

641576
#[cfg(not(target_family = "wasm"))]

0 commit comments

Comments
 (0)