refactor(bindings): Use UniFFI proc-macro frontend more

This commit is contained in:
Jonas Platte
2022-09-26 19:29:33 +02:00
committed by Jonas Platte
parent e05de8d4ce
commit 4628481d0e
7 changed files with 141 additions and 164 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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(),

View File

@@ -18,6 +18,7 @@ pub struct SessionVerificationEmoji {
description: String,
}
#[uniffi::export]
impl SessionVerificationEmoji {
pub fn symbol(&self) -> String {
self.symbol.clone()

View File

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