mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-04-29 03:23:50 -04:00
refactor(bindings): Use UniFFI proc-macro frontend more
This commit is contained in:
committed by
Jonas Platte
parent
e05de8d4ce
commit
4628481d0e
@@ -2,10 +2,7 @@ namespace matrix_sdk_ffi {};
|
||||
|
||||
|
||||
/// Cancels on drop
|
||||
interface StoppableSpawn {
|
||||
boolean is_cancelled();
|
||||
void cancel();
|
||||
};
|
||||
interface StoppableSpawn {};
|
||||
|
||||
[Error]
|
||||
interface ClientError {
|
||||
@@ -138,44 +135,14 @@ interface SlidingSyncView {
|
||||
StoppableSpawn observe_state(SlidingSyncViewStateObserver observer);
|
||||
StoppableSpawn observe_room_items(SlidingSyncViewRoomItemsObserver observer);
|
||||
|
||||
u32? current_room_count();
|
||||
sequence<RoomListEntry> current_rooms_list();
|
||||
|
||||
void add_range(u32 from, u32 to);
|
||||
void reset_ranges();
|
||||
void set_range(u32 from, u32 to);
|
||||
};
|
||||
|
||||
interface UnreadNotificationsCount {
|
||||
boolean has_notifications();
|
||||
|
||||
u32 highlight_count();
|
||||
u32 notification_count();
|
||||
};
|
||||
|
||||
interface SlidingSyncRoom {
|
||||
string? name();
|
||||
string room_id();
|
||||
|
||||
Room? full_room();
|
||||
|
||||
boolean? is_dm();
|
||||
boolean? is_initial();
|
||||
|
||||
boolean has_unread_notifications();
|
||||
UnreadNotificationsCount unread_notifications();
|
||||
|
||||
// aliveness
|
||||
boolean is_loading_more();
|
||||
|
||||
AnyMessage? latest_room_message();
|
||||
};
|
||||
interface SlidingSyncRoom {};
|
||||
|
||||
interface SlidingSync {
|
||||
void set_observer(SlidingSyncObserver? observer);
|
||||
|
||||
StoppableSpawn sync();
|
||||
|
||||
[Throws=ClientError]
|
||||
void subscribe(string room_id, RoomSubscription? settings);
|
||||
[Throws=ClientError]
|
||||
@@ -233,8 +200,6 @@ interface Client {
|
||||
[Throws=ClientError]
|
||||
void restore_login(string restore_token);
|
||||
|
||||
void start_sync(u16? timeline_limit);
|
||||
|
||||
[Throws=ClientError]
|
||||
string restore_token();
|
||||
|
||||
@@ -268,8 +233,6 @@ interface Client {
|
||||
[Throws=ClientError]
|
||||
SlidingSync full_sliding_sync();
|
||||
|
||||
SlidingSyncBuilder sliding_sync();
|
||||
|
||||
[Throws=ClientError]
|
||||
void logout();
|
||||
};
|
||||
@@ -285,19 +248,8 @@ enum Membership {
|
||||
};
|
||||
|
||||
interface Room {
|
||||
string id();
|
||||
string? name();
|
||||
string? topic();
|
||||
string? avatar_url();
|
||||
|
||||
Membership membership();
|
||||
|
||||
boolean is_direct();
|
||||
boolean is_public();
|
||||
boolean is_space();
|
||||
boolean is_encrypted();
|
||||
boolean is_tombstoned();
|
||||
|
||||
[Throws=ClientError]
|
||||
string display_name();
|
||||
|
||||
@@ -372,17 +324,9 @@ enum AuthenticationError {
|
||||
"Generic",
|
||||
};
|
||||
|
||||
interface HomeserverLoginDetails {
|
||||
string url();
|
||||
string? authentication_issuer();
|
||||
boolean supports_password_login();
|
||||
};
|
||||
|
||||
interface AuthenticationService {
|
||||
constructor(string base_path);
|
||||
|
||||
HomeserverLoginDetails? homeserver_details();
|
||||
|
||||
[Throws=AuthenticationError]
|
||||
void configure_homeserver(string server_name);
|
||||
|
||||
@@ -393,10 +337,7 @@ interface AuthenticationService {
|
||||
Client restore_with_access_token(string token, string device_id);
|
||||
};
|
||||
|
||||
interface SessionVerificationEmoji {
|
||||
string symbol();
|
||||
string description();
|
||||
};
|
||||
interface SessionVerificationEmoji {};
|
||||
|
||||
callback interface SessionVerificationControllerDelegate {
|
||||
void did_receive_verification_data(sequence<SessionVerificationEmoji> data);
|
||||
|
||||
@@ -30,12 +30,14 @@ impl From<anyhow::Error> for AuthenticationError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct HomeserverLoginDetails {
|
||||
url: String,
|
||||
authentication_issuer: Option<String>,
|
||||
supports_password_login: bool,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl HomeserverLoginDetails {
|
||||
/// The URL of the currently configured homeserver.
|
||||
pub fn url(&self) -> String {
|
||||
@@ -54,6 +56,13 @@ impl HomeserverLoginDetails {
|
||||
}
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl AuthenticationService {
|
||||
pub fn homeserver_details(&self) -> Option<Arc<HomeserverLoginDetails>> {
|
||||
self.homeserver_details.read().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl AuthenticationService {
|
||||
/// Creates a new service to authenticate a user with.
|
||||
pub fn new(base_path: String) -> Self {
|
||||
@@ -64,10 +73,6 @@ impl AuthenticationService {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn homeserver_details(&self) -> Option<Arc<HomeserverLoginDetails>> {
|
||||
self.homeserver_details.read().unwrap().clone()
|
||||
}
|
||||
|
||||
/// Updates the service to authenticate with the homeserver for the
|
||||
/// specified address.
|
||||
pub fn configure_homeserver(&self, server_name: String) -> Result<(), AuthenticationError> {
|
||||
|
||||
@@ -130,66 +130,6 @@ impl Client {
|
||||
.block_on(async move { self.client.whoami().await.map_err(|e| anyhow!(e.to_string())) })
|
||||
}
|
||||
|
||||
pub fn start_sync(&self, timeline_limit: Option<u16>) {
|
||||
let client = self.client.clone();
|
||||
let state = self.state.clone();
|
||||
let delegate = self.delegate.clone();
|
||||
let session_verification_controller = self.session_verification_controller.clone();
|
||||
let local_self = self.clone();
|
||||
RUNTIME.spawn(async move {
|
||||
let mut filter = FilterDefinition::default();
|
||||
let mut room_filter = RoomFilter::default();
|
||||
let mut event_filter = RoomEventFilter::default();
|
||||
let mut timeline_filter = RoomEventFilter::default();
|
||||
|
||||
event_filter.lazy_load_options =
|
||||
LazyLoadOptions::Enabled { include_redundant_members: false };
|
||||
room_filter.state = event_filter;
|
||||
filter.room = room_filter;
|
||||
|
||||
timeline_filter.limit = timeline_limit.map(|limit| limit.into());
|
||||
filter.room.timeline = timeline_filter;
|
||||
|
||||
let filter_id = client.get_or_upload_filter("sync", filter).await.unwrap();
|
||||
|
||||
let sync_settings = SyncSettings::new().filter(Filter::FilterId(&filter_id));
|
||||
|
||||
client
|
||||
.sync_with_result_callback(sync_settings, |result| async {
|
||||
Ok(if let Ok(sync_response) = result {
|
||||
if !state.read().unwrap().has_first_synced {
|
||||
state.write().unwrap().has_first_synced = true;
|
||||
}
|
||||
|
||||
if state.read().unwrap().should_stop_syncing {
|
||||
state.write().unwrap().is_syncing = false;
|
||||
return Ok(LoopCtrl::Break);
|
||||
} else if !state.read().unwrap().is_syncing {
|
||||
state.write().unwrap().is_syncing = true;
|
||||
}
|
||||
|
||||
if let Some(delegate) = &*delegate.read().unwrap() {
|
||||
delegate.did_receive_sync_update()
|
||||
}
|
||||
|
||||
if let Some(session_verification_controller) =
|
||||
&*session_verification_controller.read().await
|
||||
{
|
||||
session_verification_controller
|
||||
.process_to_device_messages(sync_response.to_device)
|
||||
.await;
|
||||
}
|
||||
|
||||
LoopCtrl::Continue
|
||||
} else {
|
||||
local_self.process_sync_error(result.err().unwrap())
|
||||
})
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn restore_token(&self) -> anyhow::Result<String> {
|
||||
RUNTIME.block_on(async move {
|
||||
let session = self.client.session().expect("Missing session");
|
||||
@@ -376,6 +316,66 @@ impl Client {
|
||||
pub fn rooms(&self) -> Vec<Arc<Room>> {
|
||||
self.client.rooms().into_iter().map(|room| Arc::new(Room::new(room))).collect()
|
||||
}
|
||||
|
||||
pub fn start_sync(&self, timeline_limit: Option<u16>) {
|
||||
let client = self.client.clone();
|
||||
let state = self.state.clone();
|
||||
let delegate = self.delegate.clone();
|
||||
let session_verification_controller = self.session_verification_controller.clone();
|
||||
let local_self = self.clone();
|
||||
RUNTIME.spawn(async move {
|
||||
let mut filter = FilterDefinition::default();
|
||||
let mut room_filter = RoomFilter::default();
|
||||
let mut event_filter = RoomEventFilter::default();
|
||||
let mut timeline_filter = RoomEventFilter::default();
|
||||
|
||||
event_filter.lazy_load_options =
|
||||
LazyLoadOptions::Enabled { include_redundant_members: false };
|
||||
room_filter.state = event_filter;
|
||||
filter.room = room_filter;
|
||||
|
||||
timeline_filter.limit = timeline_limit.map(|limit| limit.into());
|
||||
filter.room.timeline = timeline_filter;
|
||||
|
||||
let filter_id = client.get_or_upload_filter("sync", filter).await.unwrap();
|
||||
|
||||
let sync_settings = SyncSettings::new().filter(Filter::FilterId(&filter_id));
|
||||
|
||||
client
|
||||
.sync_with_result_callback(sync_settings, |result| async {
|
||||
Ok(if let Ok(sync_response) = result {
|
||||
if !state.read().unwrap().has_first_synced {
|
||||
state.write().unwrap().has_first_synced = true;
|
||||
}
|
||||
|
||||
if state.read().unwrap().should_stop_syncing {
|
||||
state.write().unwrap().is_syncing = false;
|
||||
return Ok(LoopCtrl::Break);
|
||||
} else if !state.read().unwrap().is_syncing {
|
||||
state.write().unwrap().is_syncing = true;
|
||||
}
|
||||
|
||||
if let Some(delegate) = &*delegate.read().unwrap() {
|
||||
delegate.did_receive_sync_update()
|
||||
}
|
||||
|
||||
if let Some(session_verification_controller) =
|
||||
&*session_verification_controller.read().await
|
||||
{
|
||||
session_verification_controller
|
||||
.process_to_device_messages(sync_response.to_device)
|
||||
.await;
|
||||
}
|
||||
|
||||
LoopCtrl::Continue
|
||||
} else {
|
||||
local_self.process_sync_error(result.err().unwrap())
|
||||
})
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
|
||||
@@ -74,4 +74,16 @@ fn setup_tracing(configuration: String) {
|
||||
|
||||
mod uniffi_types {
|
||||
pub use matrix_sdk::ruma::events::room::{message::RoomMessageEventContent, MediaSource};
|
||||
|
||||
pub use crate::{
|
||||
authentication_service::{AuthenticationService, HomeserverLoginDetails},
|
||||
client::Client,
|
||||
messages::AnyMessage,
|
||||
room::Room,
|
||||
session_verification::SessionVerificationEmoji,
|
||||
sliding_sync::{
|
||||
SlidingSync, SlidingSyncBuilder, SlidingSyncRoom, SlidingSyncView, StoppableSpawn,
|
||||
UnreadNotificationsCount,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,11 +25,8 @@ pub struct Room {
|
||||
room: MatrixRoom,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl Room {
|
||||
pub fn new(room: MatrixRoom) -> Self {
|
||||
Room { room }
|
||||
}
|
||||
|
||||
pub fn id(&self) -> String {
|
||||
self.room.room_id().to_string()
|
||||
}
|
||||
@@ -38,11 +35,6 @@ impl Room {
|
||||
self.room.name()
|
||||
}
|
||||
|
||||
pub fn display_name(&self) -> Result<String> {
|
||||
let r = self.room.clone();
|
||||
RUNTIME.block_on(async move { Ok(r.display_name().await?.to_string()) })
|
||||
}
|
||||
|
||||
pub fn topic(&self) -> Option<String> {
|
||||
self.room.topic()
|
||||
}
|
||||
@@ -51,6 +43,37 @@ impl Room {
|
||||
self.room.avatar_url().map(|m| m.to_string())
|
||||
}
|
||||
|
||||
pub fn is_direct(&self) -> bool {
|
||||
self.room.is_direct()
|
||||
}
|
||||
|
||||
pub fn is_public(&self) -> bool {
|
||||
self.room.is_public()
|
||||
}
|
||||
|
||||
pub fn is_encrypted(&self) -> bool {
|
||||
self.room.is_encrypted()
|
||||
}
|
||||
|
||||
pub fn is_space(&self) -> bool {
|
||||
self.room.is_space()
|
||||
}
|
||||
|
||||
pub fn is_tombstoned(&self) -> bool {
|
||||
self.room.is_tombstoned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Room {
|
||||
pub fn new(room: MatrixRoom) -> Self {
|
||||
Room { room }
|
||||
}
|
||||
|
||||
pub fn display_name(&self) -> Result<String> {
|
||||
let r = self.room.clone();
|
||||
RUNTIME.block_on(async move { Ok(r.display_name().await?.to_string()) })
|
||||
}
|
||||
|
||||
pub fn member_avatar_url(&self, user_id: String) -> Result<Option<String>> {
|
||||
let room = self.room.clone();
|
||||
let user_id = user_id;
|
||||
@@ -81,26 +104,6 @@ impl Room {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_direct(&self) -> bool {
|
||||
self.room.is_direct()
|
||||
}
|
||||
|
||||
pub fn is_public(&self) -> bool {
|
||||
self.room.is_public()
|
||||
}
|
||||
|
||||
pub fn is_encrypted(&self) -> bool {
|
||||
self.room.is_encrypted()
|
||||
}
|
||||
|
||||
pub fn is_space(&self) -> bool {
|
||||
self.room.is_space()
|
||||
}
|
||||
|
||||
pub fn is_tombstoned(&self) -> bool {
|
||||
self.room.is_tombstoned()
|
||||
}
|
||||
|
||||
pub fn send(&self, msg: Arc<RoomMessageEventContent>, txn_id: Option<String>) -> Result<()> {
|
||||
let room = match &self.room {
|
||||
MatrixRoom::Joined(j) => j.clone(),
|
||||
|
||||
@@ -18,6 +18,7 @@ pub struct SessionVerificationEmoji {
|
||||
description: String,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl SessionVerificationEmoji {
|
||||
pub fn symbol(&self) -> String {
|
||||
self.symbol.clone()
|
||||
|
||||
@@ -18,8 +18,8 @@ pub use matrix_sdk::{
|
||||
};
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
use super::{Client, RUNTIME};
|
||||
use crate::helpers::unwrap_or_clone_arc;
|
||||
use super::{Client, Room, RUNTIME};
|
||||
use crate::{helpers::unwrap_or_clone_arc, messages::AnyMessage};
|
||||
|
||||
pub struct StoppableSpawn {
|
||||
handle: Arc<RwLock<Option<JoinHandle<()>>>>,
|
||||
@@ -33,7 +33,10 @@ impl StoppableSpawn {
|
||||
fn with_handle_ref(handle: Arc<RwLock<Option<JoinHandle<()>>>>) -> StoppableSpawn {
|
||||
StoppableSpawn { handle }
|
||||
}
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl StoppableSpawn {
|
||||
pub fn cancel(&self) {
|
||||
if let Some(handle) = self.handle.write().unwrap().take() {
|
||||
handle.abort();
|
||||
@@ -44,11 +47,13 @@ impl StoppableSpawn {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct UnreadNotificationsCount {
|
||||
highlight_count: u32,
|
||||
notification_count: u32,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl UnreadNotificationsCount {
|
||||
pub fn highlight_count(&self) -> u32 {
|
||||
self.highlight_count
|
||||
@@ -81,6 +86,7 @@ pub struct SlidingSyncRoom {
|
||||
client: Client,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl SlidingSyncRoom {
|
||||
pub fn name(&self) -> Option<String> {
|
||||
self.inner.name().map(ToOwned::to_owned)
|
||||
@@ -110,7 +116,7 @@ impl SlidingSyncRoom {
|
||||
}
|
||||
|
||||
#[allow(clippy::significant_drop_in_scrutinee)]
|
||||
pub fn latest_room_message(&self) -> Option<Arc<crate::messages::AnyMessage>> {
|
||||
pub fn latest_room_message(&self) -> Option<Arc<AnyMessage>> {
|
||||
let messages = self.inner.timeline();
|
||||
// room is having the latest events at the end,
|
||||
let lock = messages.lock_ref();
|
||||
@@ -122,8 +128,8 @@ impl SlidingSyncRoom {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn full_room(&self) -> Option<Arc<super::Room>> {
|
||||
self.client.get_room(self.inner.room_id()).map(|room| Arc::new(super::Room::new(room)))
|
||||
pub fn full_room(&self) -> Option<Arc<Room>> {
|
||||
self.client.get_room(self.inner.room_id()).map(|room| Arc::new(Room::new(room)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,6 +387,13 @@ impl SlidingSyncView {
|
||||
})))
|
||||
}
|
||||
|
||||
pub fn current_rooms_list(&self) -> Vec<RoomListEntry> {
|
||||
self.inner.rooms_list.lock_ref().as_slice().iter().map(|e| e.into()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl SlidingSyncView {
|
||||
/// Reset the ranges to a particular set
|
||||
///
|
||||
/// Remember to cancel the existing stream and fetch a new one as this will
|
||||
@@ -404,10 +417,6 @@ impl SlidingSyncView {
|
||||
pub fn current_room_count(&self) -> Option<u32> {
|
||||
self.inner.rooms_count.get_cloned()
|
||||
}
|
||||
|
||||
pub fn current_rooms_list(&self) -> Vec<RoomListEntry> {
|
||||
self.inner.rooms_list.lock_ref().as_slice().iter().map(|e| e.into()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SlidingSyncObserver: Sync + Send {
|
||||
@@ -481,7 +490,10 @@ impl SlidingSync {
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl SlidingSync {
|
||||
pub fn sync(&self) -> Arc<StoppableSpawn> {
|
||||
let inner = self.inner.clone();
|
||||
let observer = self.observer.clone();
|
||||
@@ -572,7 +584,10 @@ impl Client {
|
||||
Ok(Arc::new(SlidingSync::new(inner, self.clone())))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl Client {
|
||||
pub fn sliding_sync(&self) -> Arc<SlidingSyncBuilder> {
|
||||
RUNTIME.block_on(async move {
|
||||
let inner = self.client.sliding_sync().await;
|
||||
|
||||
Reference in New Issue
Block a user