diff --git a/bindings/prose-sdk-js/src/client.rs b/bindings/prose-sdk-js/src/client.rs index 237ea46a..795baaee 100644 --- a/bindings/prose-sdk-js/src/client.rs +++ b/bindings/prose-sdk-js/src/client.rs @@ -235,6 +235,18 @@ impl Client { .collect_into_js_array::()) } + /// Returns the `BareJid` of the public room with `name` if one exists. + #[wasm_bindgen(js_name = "findPublicChannelByName")] + pub async fn find_public_channel_by_name(&self, name: &str) -> Result> { + Ok(self + .client + .rooms + .find_public_channel_by_name(name) + .await + .map_err(WasmError::from)? + .map(|room_id| room_id.into_inner().into())) + } + #[wasm_bindgen(js_name = "loadAccountInfo")] pub async fn load_account_info(&self) -> Result { Ok(self diff --git a/bindings/prose-sdk-js/src/types/channel.rs b/bindings/prose-sdk-js/src/types/channel.rs index 67e7d2b0..3d821ce6 100644 --- a/bindings/prose-sdk-js/src/types/channel.rs +++ b/bindings/prose-sdk-js/src/types/channel.rs @@ -31,11 +31,11 @@ impl Channel { impl From for Channel { fn from(value: PublicRoomInfo) -> Self { Channel { - jid: value.jid.clone().into_inner().into(), + jid: value.id.clone().into_inner().into(), name: value .name - .or(value.jid.node_str().map(|n| n.to_string())) - .unwrap_or(value.jid.to_string()), + .or(value.id.node_str().map(|n| n.to_string())) + .unwrap_or(value.id.to_string()), } } } diff --git a/crates/prose-core-client/src/app/services/rooms_service.rs b/crates/prose-core-client/src/app/services/rooms_service.rs index 2accb002..33469982 100644 --- a/crates/prose-core-client/src/app/services/rooms_service.rs +++ b/crates/prose-core-client/src/app/services/rooms_service.rs @@ -44,6 +44,19 @@ impl RoomsService { .await?) } + pub async fn find_public_channel_by_name(&self, name: &str) -> Result> { + let rooms = self + .room_management_service + .load_public_rooms(&self.ctx.muc_service()?) + .await?; + + let needle = name.to_lowercase(); + Ok(rooms + .into_iter() + .find(|r| r.name.as_ref().map(|name| name.to_lowercase()).as_ref() == Some(&needle)) + .map(|room| room.id)) + } + pub async fn start_conversation(&self, participants: &[UserId]) -> Result { if participants.is_empty() { bail!("You need at least one participant to start a conversation") diff --git a/crates/prose-core-client/src/domain/rooms/models/public_room_info.rs b/crates/prose-core-client/src/domain/rooms/models/public_room_info.rs index 4ffbbe94..22b47e2a 100644 --- a/crates/prose-core-client/src/domain/rooms/models/public_room_info.rs +++ b/crates/prose-core-client/src/domain/rooms/models/public_room_info.rs @@ -7,6 +7,6 @@ use crate::domain::shared::models::RoomId; #[derive(Debug, Clone, PartialEq)] pub struct PublicRoomInfo { - pub jid: RoomId, + pub id: RoomId, pub name: Option, } diff --git a/crates/prose-core-client/src/infra/rooms/room_management_service.rs b/crates/prose-core-client/src/infra/rooms/room_management_service.rs index 8eb16b1f..470a9708 100644 --- a/crates/prose-core-client/src/infra/rooms/room_management_service.rs +++ b/crates/prose-core-client/src/infra/rooms/room_management_service.rs @@ -37,7 +37,7 @@ impl RoomManagementService for XMPPClient { .await? .into_iter() .map(|room| PublicRoomInfo { - jid: room.jid.into_bare().into(), + id: room.jid.into_bare().into(), name: room.name, }) .collect(); diff --git a/crates/prose-core-client/tests/rooms_domain_service.rs b/crates/prose-core-client/tests/rooms_domain_service.rs index 12cacdbc..0865cd01 100644 --- a/crates/prose-core-client/tests/rooms_domain_service.rs +++ b/crates/prose-core-client/tests/rooms_domain_service.rs @@ -363,7 +363,7 @@ async fn test_throws_conflict_error_if_room_exists() -> Result<()> { .return_once(|_| { Box::pin(async { Ok(vec![PublicRoomInfo { - jid: room_id!("room@conference.prose.org"), + id: room_id!("room@conference.prose.org"), name: Some("new channel".to_string()), }]) }) @@ -732,7 +732,7 @@ async fn test_creates_public_room_if_it_does_not_exist() -> Result<()> { .return_once(|_| { Box::pin(async { Ok(vec![PublicRoomInfo { - jid: room_id!("room@conference.prose.org"), + id: room_id!("room@conference.prose.org"), name: Some("Old Channel".to_string()), }]) }) @@ -1081,7 +1081,7 @@ async fn test_converts_private_to_public_channel_name_conflict() -> Result<()> { .return_once(|_| { Box::pin(async { Ok(vec![PublicRoomInfo { - jid: room_id!("room@conference.prose.org"), + id: room_id!("room@conference.prose.org"), name: Some("new channel".to_string()), }]) }) diff --git a/crates/prose-core-client/tests/rooms_service.rs b/crates/prose-core-client/tests/rooms_service.rs new file mode 100644 index 00000000..bbe6ca6b --- /dev/null +++ b/crates/prose-core-client/tests/rooms_service.rs @@ -0,0 +1,41 @@ +use prose_core_client::domain::shared::models::RoomId; +use prose_core_client::dtos::PublicRoomInfo; +use prose_core_client::room_id; +use prose_core_client::services::RoomsService; +use prose_core_client::test::MockAppDependencies; + +#[tokio::test] +async fn test_find_public_channel_by_name() -> anyhow::Result<()> { + let mut deps = MockAppDependencies::default(); + + deps.room_management_service + .expect_load_public_rooms() + .returning(|_| { + Box::pin(async { + Ok(vec![ + PublicRoomInfo { + id: room_id!("dev-core@muc.prose.org"), + name: Some("Dev-Core".to_string()), + }, + PublicRoomInfo { + id: room_id!("dev-web@muc.prose.org"), + name: Some("dev-web".to_string()), + }, + ]) + }) + }); + + let service = RoomsService::from(&deps.into_deps()); + + assert_eq!( + service.find_public_channel_by_name("dev-core").await?, + Some(room_id!("dev-core@muc.prose.org")) + ); + assert_eq!( + service.find_public_channel_by_name("Dev-Web").await?, + Some(room_id!("dev-web@muc.prose.org")) + ); + assert_eq!(service.find_public_channel_by_name("dev-pod").await?, None); + + Ok(()) +} diff --git a/examples/prose-core-client-cli/src/main.rs b/examples/prose-core-client-cli/src/main.rs index deedce37..b14252f3 100644 --- a/examples/prose-core-client-cli/src/main.rs +++ b/examples/prose-core-client-cli/src/main.rs @@ -230,7 +230,7 @@ impl From for JidWithName { impl From for JidWithName { fn from(value: PublicRoomInfo) -> Self { Self { - jid: value.jid.into_inner(), + jid: value.id.into_inner(), name: value.name.as_deref().unwrap_or("").to_string(), } } @@ -882,7 +882,7 @@ async fn main() -> Result<()> { } Selection::JoinPublicRoom => { let room = select_public_channel(&client).await?; - client.rooms.join_room(&room.jid, None).await?; + client.rooms.join_room(&room.id, None).await?; } Selection::JoinRoomByJid => { let jid = prompt_bare_jid(None);