Skip to content

Commit

Permalink
Improve room handling (#37)
Browse files Browse the repository at this point in the history
- Introduce strongly-typed JIDs (UserId, RoomId, etc.)
- Add the ability to reconfigure rooms (needs server support to finalize)
- Handle room events (room was destroyed, user was kicked, etc.)
- Parse server events into unambigous Rust structs
  • Loading branch information
nesium authored Dec 19, 2023
1 parent 038276e commit d29486a
Show file tree
Hide file tree
Showing 200 changed files with 9,361 additions and 2,514 deletions.
6 changes: 3 additions & 3 deletions bindings/prose-sdk-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Client {

pub async fn connect(&self, password: String) -> Result<(), ConnectionError> {
self.client
.connect(&self.jid.to_bare().unwrap(), password)
.connect(&self.jid.to_bare().unwrap().into(), password)
.await?;
Ok(())
}
Expand All @@ -81,7 +81,7 @@ impl Client {
let profile = self
.client
.user_data
.load_user_profile(&from.to_bare().unwrap())
.load_user_profile(&from.to_bare().unwrap().into())
.await?;
Ok(profile)
}
Expand All @@ -100,7 +100,7 @@ impl Client {
let path = self
.client
.user_data
.load_avatar(&from.to_bare().unwrap())
.load_avatar(&from.to_bare().unwrap().into())
.await?;
Ok(path)
}
Expand Down
4 changes: 2 additions & 2 deletions bindings/prose-sdk-ffi/src/prose_sdk_ffi.udl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ enum Group {
"Other",
};

dictionary UserActivity {
dictionary UserStatus {
string emoji;
string? status;
};
Expand All @@ -142,7 +142,7 @@ dictionary Contact {
JID jid;
string name;
Availability availability;
UserActivity? activity;
UserStatus? status;
Group group;
};

Expand Down
8 changes: 4 additions & 4 deletions bindings/prose-sdk-ffi/src/types/contact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use crate::types::JID;
use prose_core_client::dtos::{
Availability, Contact as CoreContact, Group as CoreGroup, UserActivity,
Availability, Contact as CoreContact, Group as CoreGroup, UserStatus,
};

#[derive(Debug, PartialEq, Clone)]
Expand All @@ -20,17 +20,17 @@ pub struct Contact {
pub jid: JID,
pub name: String,
pub availability: Availability,
pub activity: Option<UserActivity>,
pub status: Option<UserStatus>,
pub group: Group,
}

impl From<CoreContact> for Contact {
fn from(value: CoreContact) -> Self {
Contact {
jid: value.jid.into(),
jid: value.id.into_inner().into(),
name: value.name,
availability: value.availability,
activity: value.activity,
status: value.status,
group: value.group.into(),
}
}
Expand Down
6 changes: 5 additions & 1 deletion bindings/prose-sdk-ffi/src/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ impl From<ProseReaction> for Reaction {
fn from(value: ProseReaction) -> Self {
Reaction {
emoji: value.emoji,
from: value.from.into_iter().map(Into::into).collect(),
from: value
.from
.into_iter()
.map(|id| id.into_inner().into())
.collect(),
}
}
}
2 changes: 1 addition & 1 deletion bindings/prose-sdk-ffi/src/uniffi_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use std::path::PathBuf;
pub use jid::{BareJid, Error as JidParseError, FullJid};

pub use prose_core_client::dtos::{
Address, Availability, Emoji, MessageId, StanzaId, Url, UserActivity, UserProfile,
Address, Availability, Emoji, MessageId, StanzaId, Url, UserProfile, UserStatus,
};
pub use prose_core_client::ConnectionEvent;
pub use prose_xmpp::ConnectionError;
Expand Down
23 changes: 17 additions & 6 deletions bindings/prose-sdk-js/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ use base64::{engine::general_purpose, Engine as _};
use js_sys::Array;
use wasm_bindgen::prelude::*;

use prose_core_client::dtos::{RoomJid, SoftwareVersion, UserActivity};
use prose_core_client::dtos::{RoomId, SoftwareVersion, UserStatus};
use prose_core_client::{open_store, Client as ProseClient, IndexedDBDriver, StoreAvatarCache};

use crate::connector::{Connector, ProseConnectionProvider};
use crate::delegate::{Delegate, JSDelegate};
use crate::types::{
try_jid_vec_from_string_array, Availability, BareJid, Channel, ChannelsArray, Contact,
try_user_id_vec_from_string_array, Availability, BareJid, Channel, ChannelsArray, Contact,
ContactsArray, IntoJSArray, SidebarItem, SidebarItemsArray, UserMetadata, UserProfile,
};

Expand Down Expand Up @@ -187,7 +187,7 @@ impl Client {
/// Pass a String[] as participants where each string is a valid BareJid.
#[wasm_bindgen(js_name = "startConversation")]
pub async fn start_conversation(&self, participants: Array) -> Result<BareJid> {
let participants = try_jid_vec_from_string_array(participants)?;
let participants = try_user_id_vec_from_string_array(participants)?;

Ok(self
.client
Expand All @@ -204,7 +204,7 @@ impl Client {
/// Pass a String[] as participants where each string is a valid BareJid.
#[wasm_bindgen(js_name = "createGroup")]
pub async fn create_group(&self, participants: Array) -> Result<BareJid> {
let participants = try_jid_vec_from_string_array(participants)?;
let participants = try_user_id_vec_from_string_array(participants)?;

Ok(self
.client
Expand Down Expand Up @@ -249,13 +249,24 @@ impl Client {
Ok(self
.client
.rooms
.join_room(&RoomJid::from(room_jid.clone()), password.as_deref())
.join_room(&RoomId::from(room_jid.clone()), password.as_deref())
.await
.map_err(|err| WasmError::from(anyhow::Error::from(err)))?
.into_inner()
.into())
}

/// Destroys the room identified by `room_jid`.
#[wasm_bindgen(js_name = "destroyRoom")]
pub async fn destroy_room(&self, room_jid: &BareJid) -> Result<()> {
self.client
.rooms
.destroy_room(&RoomId::from(room_jid.clone()))
.await
.map_err(|err| WasmError::from(anyhow::Error::from(err)))?;
Ok(())
}

/// XEP-0108: User Activity
/// https://xmpp.org/extensions/xep-0108.html
#[wasm_bindgen(js_name = "sendActivity")]
Expand All @@ -265,7 +276,7 @@ impl Client {
text: Option<String>,
) -> Result<()> {
let user_activity = if let Some(icon) = &icon {
Some(UserActivity {
Some(UserStatus {
emoji: icon.clone(),
status: text.clone(),
})
Expand Down
48 changes: 27 additions & 21 deletions bindings/prose-sdk-js/src/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tracing::warn;
use wasm_bindgen::prelude::*;

use prose_core_client::dtos::MessageId;
use prose_core_client::{ClientDelegate, ClientEvent, ConnectionEvent, RoomEventType};
use prose_core_client::{ClientDelegate, ClientEvent, ClientRoomEventType, ConnectionEvent};
use prose_xmpp::ConnectionError;

use crate::client::Client;
Expand Down Expand Up @@ -119,6 +119,13 @@ extern "C" {
client: Client,
room: JsValue,
) -> Result<(), JsValue>;

#[wasm_bindgen(method, catch, js_name = "roomParticipantsChanged")]
fn room_participants_changed(
this: &JSDelegate,
client: Client,
room: JsValue,
) -> Result<(), JsValue>;
}

#[wasm_bindgen(getter_with_clone)]
Expand Down Expand Up @@ -198,32 +205,31 @@ impl Delegate {
.inner
.client_disconnected(client, error.map(Into::into))?,
ClientEvent::SidebarChanged => self.inner.sidebar_changed(client)?,
ClientEvent::ContactChanged { jid } => {
self.inner.contact_changed(client, jid.into())?
ClientEvent::ContactChanged { id: jid } => self
.inner
.contact_changed(client, jid.into_inner().into())?,
ClientEvent::AvatarChanged { id: jid } => {
self.inner.avatar_changed(client, jid.into_inner().into())?
}
ClientEvent::AvatarChanged { jid } => self.inner.avatar_changed(client, jid.into())?,
ClientEvent::RoomChanged { room, r#type } => match r#type {
RoomEventType::MessagesAppended { message_ids } => self.inner.messages_appended(
client,
room.into_js_value(),
message_ids.into_js_array(),
)?,
RoomEventType::MessagesUpdated { message_ids } => self.inner.messages_updated(
client,
room.into_js_value(),
message_ids.into_js_array(),
)?,
RoomEventType::MessagesDeleted { message_ids } => self.inner.messages_deleted(
client,
room.into_js_value(),
message_ids.into_js_array(),
)?,
RoomEventType::ComposingUsersChanged => self
ClientRoomEventType::MessagesAppended { message_ids } => self
.inner
.messages_appended(client, room.into_js_value(), message_ids.into_js_array())?,
ClientRoomEventType::MessagesUpdated { message_ids } => self
.inner
.messages_updated(client, room.into_js_value(), message_ids.into_js_array())?,
ClientRoomEventType::MessagesDeleted { message_ids } => self
.inner
.messages_deleted(client, room.into_js_value(), message_ids.into_js_array())?,
ClientRoomEventType::ComposingUsersChanged => self
.inner
.composing_users_changed(client, room.into_js_value())?,
RoomEventType::AttributesChanged => self
ClientRoomEventType::AttributesChanged => self
.inner
.room_attributes_changed(client, room.into_js_value())?,
ClientRoomEventType::ParticipantsChanged => self
.inner
.room_participants_changed(client, room.into_js_value())?,
},
}
Ok(())
Expand Down
16 changes: 8 additions & 8 deletions bindings/prose-sdk-js/src/types/contact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use prose_core_client::dtos::{
Availability as CoreAvailability, Contact as CoreContact, Group as CoreGroup,
UserActivity as CoreUserActivity,
UserStatus as CoreUserStatus,
};
use wasm_bindgen::prelude::*;

Expand Down Expand Up @@ -48,13 +48,13 @@ impl From<Availability> for CoreAvailability {
}

#[wasm_bindgen]
pub struct UserActivity(CoreUserActivity);
pub struct UserStatus(CoreUserStatus);

#[wasm_bindgen]
impl Contact {
#[wasm_bindgen(getter)]
pub fn jid(&self) -> BareJid {
self.0.jid.clone().into()
self.0.id.clone().into_inner().into()
}

#[wasm_bindgen(getter)]
Expand All @@ -68,11 +68,11 @@ impl Contact {
}

#[wasm_bindgen(getter)]
pub fn activity(&self) -> Option<UserActivity> {
pub fn status(&self) -> Option<UserStatus> {
self.0
.activity
.status
.as_ref()
.map(|activity| UserActivity(activity.clone()))
.map(|activity| UserStatus(activity.clone()))
}

#[wasm_bindgen(getter)]
Expand All @@ -84,10 +84,10 @@ impl Contact {
}

#[wasm_bindgen]
impl UserActivity {
impl UserStatus {
#[wasm_bindgen(constructor)]
pub fn new(icon: &str, status: Option<String>) -> Self {
UserActivity(CoreUserActivity {
UserStatus(CoreUserStatus {
emoji: icon.to_string(),
status: status.clone(),
})
Expand Down
19 changes: 16 additions & 3 deletions bindings/prose-sdk-js/src/types/jid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
use core::fmt::{Debug, Display, Formatter};
use core::str::FromStr;

use prose_core_client::dtos::RoomJid;
use wasm_bindgen::prelude::*;

use prose_core_client::dtos::{RoomId, UserId};

#[derive(Debug, PartialEq, Clone)]
#[wasm_bindgen(js_name = "JID")]
pub struct BareJid(jid::BareJid);
Expand Down Expand Up @@ -90,8 +91,20 @@ impl Display for BareJid {
}
}

impl From<BareJid> for RoomJid {
impl From<BareJid> for RoomId {
fn from(value: BareJid) -> Self {
RoomId::from(value.0)
}
}

impl From<BareJid> for UserId {
fn from(value: BareJid) -> Self {
RoomJid::from(value.0)
UserId::from(value.0)
}
}

impl From<&BareJid> for UserId {
fn from(value: &BareJid) -> Self {
UserId::from(value.0.clone())
}
}
9 changes: 5 additions & 4 deletions bindings/prose-sdk-js/src/types/js_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
// Copyright: 2023, Marc Bauer <mb@nesium.com>
// License: Mozilla Public License v2.0 (MPL v2.0)

use crate::client::WasmError;
use anyhow::anyhow;
use core::str::FromStr;
use js_sys::Array;
use wasm_bindgen::prelude::*;

use prose_core_client::dtos::UserId;

use crate::client::WasmError;
use crate::types::Message;

#[wasm_bindgen]
Expand Down Expand Up @@ -97,15 +98,15 @@ impl TryFrom<&StringArray> for Vec<String> {
}
}

pub fn try_jid_vec_from_string_array(arr: Array) -> Result<Vec<jid::BareJid>, WasmError> {
pub fn try_user_id_vec_from_string_array(arr: Array) -> Result<Vec<UserId>, WasmError> {
arr.into_iter()
.map(|value| {
value
.as_string()
.ok_or(anyhow::format_err!(
"Could not read String from supposed String Array"
))
.and_then(|str| jid::BareJid::from_str(&str).map_err(Into::into))
.and_then(|str| str.parse::<UserId>().map_err(Into::into))
})
.collect::<Result<Vec<_>, _>>()
.map_err(WasmError::from)
Expand Down
6 changes: 5 additions & 1 deletion bindings/prose-sdk-js/src/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,11 @@ impl From<dtos::Reaction> for Reaction {
fn from(value: dtos::Reaction) -> Self {
Reaction {
emoji: value.emoji.into_inner(),
from: value.from.into_iter().map(Into::into).collect(),
from: value
.from
.into_iter()
.map(|id| id.into_inner().into())
.collect(),
}
}
}
5 changes: 4 additions & 1 deletion bindings/prose-sdk-js/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ pub use js_array::*;
pub use message::Message;
pub use room::RoomEnvelopeExt;
pub use sidebar_item::{SidebarItem, SidebarItemsArray};
pub use user_info::{UserBasicInfo, UserBasicInfoArray, UserPresenceInfo, UserPresenceInfoArray};
pub use user_info::{
ParticipantInfo, ParticipantInfoArray, UserBasicInfo, UserBasicInfoArray, UserPresenceInfo,
UserPresenceInfoArray,
};
pub use user_metadata::UserMetadata;
pub use user_profile::UserProfile;

Expand Down
Loading

0 comments on commit d29486a

Please sign in to comment.