diff --git a/crates/matrix-sdk/src/client/mod.rs b/crates/matrix-sdk/src/client/mod.rs index 4024c4ebb..31bdc8ba0 100644 --- a/crates/matrix-sdk/src/client/mod.rs +++ b/crates/matrix-sdk/src/client/mod.rs @@ -15,6 +15,7 @@ // limitations under the License. use std::{ + collections::BTreeMap, fmt::{self, Debug}, future::Future, pin::Pin, @@ -67,7 +68,7 @@ use ruma::{ create::RoomCreateEventContent, member::{MembershipState, RoomMemberEventContent}, }, - SyncStateEvent, + GlobalAccountDataEventType, SyncStateEvent, }, presence::PresenceState, DeviceId, MilliSecondsSinceUnixEpoch, OwnedDeviceId, OwnedRoomId, OwnedServerName, RoomAliasId, @@ -1846,6 +1847,44 @@ impl Client { } } + /// Create a direct message room with the specified user. + pub async fn create_dm_room(&self, user_id: &UserId) -> Result { + use ruma::{api::client::room::create_room::v3::RoomPreset, events::direct::DirectEvent}; + + // First we create the DM room, where we invite the user and tell the + // invitee that the room should be a DM. + let invite = &[user_id.to_owned()]; + + let request = assign!(ruma::api::client::room::create_room::v3::Request::new(), { + invite, + is_direct: true, + preset: Some(RoomPreset::TrustedPrivateChat), + }); + + let room = self.create_room(request).await?; + + // Now we need to mark the room as a DM for ourselves, we fetch the + // existing `m.direct` event and append the room to the list of DMs we + // have with this user. + let mut content = self + .store() + .get_account_data_event(GlobalAccountDataEventType::Direct) + .await? + .map(|e| e.deserialize_as::()) + .transpose()? + .map(|e| e.content) + .unwrap_or_else(|| ruma::events::direct::DirectEventContent(BTreeMap::new())); + + content.entry(user_id.to_owned()).or_default().push(room.room_id().to_owned()); + + // TODO We should probably save the fact that we need to send this out + // because otherwise we might end up in a state where we have a DM that + // isn't marked as one. + self.account().set_account_data(content).await?; + + Ok(room) + } + /// Search the homeserver's directory for public rooms with a filter. /// /// # Arguments diff --git a/crates/matrix-sdk/src/encryption/identities/users.rs b/crates/matrix-sdk/src/encryption/identities/users.rs index 9e8d27248..7f790aae3 100644 --- a/crates/matrix-sdk/src/encryption/identities/users.rs +++ b/crates/matrix-sdk/src/encryption/identities/users.rs @@ -475,12 +475,8 @@ impl OtherUserIdentity { room.invite_user_by_id(self.inner.user_id()).await?; } room.clone() - } else if let Some(room) = - self.client.create_dm_room(self.inner.user_id().to_owned()).await? - { - room } else { - return Err(RequestVerificationError::RoomCreation(self.inner.user_id().to_owned())); + self.client.create_dm_room(self.inner.user_id()).await? }; let response = room diff --git a/crates/matrix-sdk/src/encryption/mod.rs b/crates/matrix-sdk/src/encryption/mod.rs index 5e07e798f..db437e12e 100644 --- a/crates/matrix-sdk/src/encryption/mod.rs +++ b/crates/matrix-sdk/src/encryption/mod.rs @@ -38,7 +38,6 @@ pub use matrix_sdk_base::crypto::{ use matrix_sdk_base::crypto::{ CrossSigningStatus, OutgoingRequest, RoomMessageRequest, ToDeviceRequest, }; -use matrix_sdk_common::instant::Duration; #[cfg(feature = "e2e-encryption")] use ruma::OwnedDeviceId; use ruma::{ @@ -57,14 +56,13 @@ use ruma::{ }; use tracing::{debug, instrument, trace, warn}; -pub use crate::error::RoomKeyImportError; use crate::{ attachment::{AttachmentInfo, Thumbnail}, encryption::{ identities::{Device, UserDevices}, verification::{SasVerification, Verification, VerificationRequest}, }, - error::HttpResult, + error::{HttpResult, RoomKeyImportError}, room, Client, Error, Result, }; @@ -226,57 +224,6 @@ impl Client { }) } - #[cfg(feature = "e2e-encryption")] - pub(crate) async fn create_dm_room( - &self, - user_id: OwnedUserId, - ) -> Result> { - use ruma::{ - api::client::room::create_room::v3::RoomPreset, events::direct::DirectEventContent, - }; - - const SYNC_WAIT_TIME: Duration = Duration::from_secs(3); - - // First we create the DM room, where we invite the user and tell the - // invitee that the room should be a DM. - let invite = &[user_id.clone()]; - - let request = assign!(ruma::api::client::room::create_room::v3::Request::new(), { - invite, - is_direct: true, - preset: Some(RoomPreset::TrustedPrivateChat), - }); - - let response = self.send(request, None).await?; - - // Now we need to mark the room as a DM for ourselves, we fetch the - // existing `m.direct` event and append the room to the list of DMs we - // have with this user. - let mut content = self - .account() - .account_data::() - .await? - .map(|c| c.deserialize()) - .transpose()? - .unwrap_or_default(); - - content.entry(user_id.to_owned()).or_default().push(response.room_id.to_owned()); - - // TODO We should probably save the fact that we need to send this out - // because otherwise we might end up in a state where we have a DM that - // isn't marked as one. - self.account().set_account_data(content).await?; - - // If the room is already in our store, fetch it, otherwise wait for a - // sync to be done which should put the room into our store. - if let Some(room) = self.get_joined_room(&response.room_id) { - Ok(Some(room)) - } else { - self.inner.sync_beat.listen().wait_timeout(SYNC_WAIT_TIME); - Ok(self.get_joined_room(&response.room_id)) - } - } - /// Claim one-time keys creating new Olm sessions. /// /// # Arguments