Skip to content

Commit 944699e

Browse files
authored
Merge branch 'main' into dima/variable-font-weight
2 parents eb7aad9 + 19cbd97 commit 944699e

File tree

2 files changed

+96
-79
lines changed

2 files changed

+96
-79
lines changed

coreclient/src/clients/message.rs

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
//
33
// SPDX-License-Identifier: AGPL-3.0-or-later
44

5-
use anyhow::Context;
5+
use anyhow::{bail, Context};
66
use openmls::storage::OpenMlsProvider;
77
use phnxtypes::{
88
identifiers::QualifiedUserName, messages::client_ds_out::SendMessageParamsOut, time::TimeStamp,
99
};
1010
use rusqlite::{Connection, Transaction};
11+
use uuid::Uuid;
1112

12-
use crate::{Conversation, ConversationId, ConversationMessage, MimiContent};
13+
use crate::{Conversation, ConversationId, ConversationMessage, Message, MimiContent};
1314

1415
use super::{ApiClients, CoreUser, Group, PhnxOpenMlsProvider, StoreNotifier};
1516

@@ -25,7 +26,7 @@ impl CoreUser {
2526
) -> anyhow::Result<ConversationMessage> {
2627
let unsent_group_message = self
2728
.with_transaction(|transaction| {
28-
InitialParams {
29+
UnsentContent {
2930
conversation_id,
3031
content,
3132
}
@@ -44,21 +45,43 @@ impl CoreUser {
4445
})
4546
.await
4647
}
48+
49+
/// Re-try sending a message, where sending previously failed.
50+
pub async fn re_send_message(&self, local_message_id: Uuid) -> anyhow::Result<()> {
51+
let unsent_group_message = self
52+
.with_transaction(|transaction| {
53+
LocalMessage { local_message_id }
54+
.load(transaction)?
55+
.create_group_message(&PhnxOpenMlsProvider::new(transaction))
56+
})
57+
.await?;
58+
59+
let sent_message = unsent_group_message
60+
.send_message_to_ds(&self.inner.api_clients)
61+
.await?;
62+
63+
self.with_transaction(|transaction| {
64+
sent_message.mark_as_sent_and_read(transaction, self.store_notifier())
65+
})
66+
.await?;
67+
68+
Ok(())
69+
}
4770
}
4871

49-
struct InitialParams {
72+
struct UnsentContent {
5073
conversation_id: ConversationId,
5174
content: MimiContent,
5275
}
5376

54-
impl InitialParams {
77+
impl UnsentContent {
5578
fn store_unsent_message(
5679
self,
5780
connection: &Connection,
5881
mut notifier: StoreNotifier,
5982
sender: &QualifiedUserName,
60-
) -> anyhow::Result<UnsentMessage<WithContent>> {
61-
let InitialParams {
83+
) -> anyhow::Result<UnsentMessage<WithContent, GroupUpdateNeeded>> {
84+
let UnsentContent {
6285
conversation_id,
6386
content,
6487
} = self;
@@ -85,34 +108,80 @@ impl InitialParams {
85108
conversation,
86109
group,
87110
conversation_message,
88-
state: WithContent(content),
111+
content: WithContent(content),
112+
group_update: GroupUpdateNeeded,
89113
})
90114
}
91115
}
92116

93-
// States of an unsent message
117+
struct LocalMessage {
118+
local_message_id: Uuid,
119+
}
94120

121+
impl LocalMessage {
122+
fn load(
123+
self,
124+
connection: &Connection,
125+
) -> anyhow::Result<UnsentMessage<WithContent, GroupUpdated>> {
126+
let Self { local_message_id } = self;
127+
128+
let conversation_message = ConversationMessage::load(connection, &local_message_id)?
129+
.with_context(|| format!("Can't find unsent message with id {local_message_id}"))?;
130+
let content = match conversation_message.message() {
131+
Message::Content(content_message) if !content_message.was_sent() => {
132+
content_message.content().clone()
133+
}
134+
Message::Content(_) => bail!("Message with id {local_message_id} was already sent"),
135+
_ => bail!("Message with id {local_message_id} is not a content message"),
136+
};
137+
let conversation_id = conversation_message.conversation_id();
138+
let conversation = Conversation::load(connection, &conversation_id)?
139+
.with_context(|| format!("Can't find conversation with id {conversation_id}"))?;
140+
let group_id = conversation.group_id();
141+
let group = Group::load(connection, group_id)?
142+
.with_context(|| format!("Can't find group with id {group_id:?}"))?;
143+
144+
let message = UnsentMessage {
145+
conversation,
146+
group,
147+
conversation_message,
148+
content: WithContent(content),
149+
group_update: GroupUpdated,
150+
};
151+
152+
Ok(message)
153+
}
154+
}
155+
156+
/// Message type state: Message with MIMI content
95157
struct WithContent(MimiContent);
158+
/// Message type state: Message with prepared send parameters
96159
struct WithParams(SendMessageParamsOut);
97-
struct StoredWithParams(SendMessageParamsOut);
98160

99-
struct UnsentMessage<State> {
161+
/// Message type state: Group update needed before sending the message
162+
struct GroupUpdateNeeded;
163+
/// Message type state: Group already updated, message can be sent
164+
struct GroupUpdated;
165+
166+
struct UnsentMessage<State, GroupUpdate> {
100167
conversation: Conversation,
101168
group: Group,
102169
conversation_message: ConversationMessage,
103-
state: State,
170+
content: State,
171+
group_update: GroupUpdate,
104172
}
105173

106-
impl UnsentMessage<WithContent> {
174+
impl<GroupUpdate> UnsentMessage<WithContent, GroupUpdate> {
107175
fn create_group_message(
108176
self,
109177
provider: &impl OpenMlsProvider,
110-
) -> anyhow::Result<UnsentMessage<WithParams>> {
178+
) -> anyhow::Result<UnsentMessage<WithParams, GroupUpdate>> {
111179
let Self {
112180
conversation,
113181
mut group,
114182
conversation_message,
115-
state: WithContent(content),
183+
content: WithContent(content),
184+
group_update,
116185
} = self;
117186

118187
let params = group.create_message(provider, content)?;
@@ -121,22 +190,24 @@ impl UnsentMessage<WithContent> {
121190
conversation,
122191
conversation_message,
123192
group,
124-
state: WithParams(params),
193+
content: WithParams(params),
194+
group_update,
125195
})
126196
}
127197
}
128198

129-
impl UnsentMessage<WithParams> {
199+
impl UnsentMessage<WithParams, GroupUpdateNeeded> {
130200
fn store_group_update(
131201
self,
132202
transaction: &Transaction,
133203
mut notifier: StoreNotifier,
134-
) -> anyhow::Result<UnsentMessage<StoredWithParams>> {
204+
) -> anyhow::Result<UnsentMessage<WithParams, GroupUpdated>> {
135205
let Self {
136206
conversation,
137207
group,
138208
conversation_message,
139-
state: WithParams(params),
209+
content: WithParams(params),
210+
group_update: GroupUpdateNeeded,
140211
} = self;
141212

142213
// Immediately write the group back. No need to wait for the DS to
@@ -155,18 +226,20 @@ impl UnsentMessage<WithParams> {
155226
conversation,
156227
group,
157228
conversation_message,
158-
state: StoredWithParams(params),
229+
content: WithParams(params),
230+
group_update: GroupUpdated,
159231
})
160232
}
161233
}
162234

163-
impl UnsentMessage<StoredWithParams> {
235+
impl UnsentMessage<WithParams, GroupUpdated> {
164236
async fn send_message_to_ds(self, api_clients: &ApiClients) -> anyhow::Result<SentMessage> {
165237
let Self {
166238
conversation,
167239
conversation_message,
168240
group,
169-
state: StoredWithParams(params),
241+
content: WithParams(params),
242+
group_update: GroupUpdated,
170243
} = self;
171244

172245
let ds_timestamp = api_clients

coreclient/src/clients/mod.rs

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ use store::ClientRecord;
5050
use thiserror::Error;
5151
use tokio_stream::Stream;
5252
use tracing::{error, info};
53-
use uuid::Uuid;
5453

5554
use crate::store::StoreNotificationsSender;
55+
use crate::utils::persistence::{SqliteConnection, Storable};
5656
use crate::{
5757
clients::connection_establishment::{ConnectionEstablishmentPackageTbs, FriendshipPackage},
5858
contacts::{Contact, ContactAddInfos, PartialContact},
@@ -75,10 +75,6 @@ use crate::{
7575
Asset,
7676
};
7777
use crate::{key_stores::as_credentials::AsCredentials, ConversationId};
78-
use crate::{
79-
utils::persistence::{SqliteConnection, Storable},
80-
Message,
81-
};
8278

8379
use self::{api_clients::ApiClients, create_user::InitialUserState, store::UserCreationState};
8480

@@ -522,58 +518,6 @@ impl CoreUser {
522518
Ok(conversation_messages)
523519
}
524520

525-
/// Re-try sending a message, where sending previously failed.
526-
pub async fn re_send_message(&self, local_message_id: Uuid) -> Result<()> {
527-
// Phase 1: Load the unsent message
528-
let connection = self.inner.connection.lock().await;
529-
let mut unsent_message = ConversationMessage::load(&connection, &local_message_id)?.ok_or(
530-
anyhow!("Can't find unsent message with id {}", local_message_id),
531-
)?;
532-
let content = match unsent_message.message() {
533-
Message::Content(content_message) if !content_message.was_sent() => {
534-
content_message.content().clone()
535-
}
536-
_ => bail!("Message with id {} was already sent", local_message_id),
537-
};
538-
let conversation_id = unsent_message.conversation_id();
539-
let conversation = Conversation::load(&connection, &conversation_id)?.ok_or(anyhow!(
540-
"Can't find conversation with id {}",
541-
conversation_id.as_uuid()
542-
))?;
543-
let group_id = conversation.group_id();
544-
let mut group = Group::load(&connection, group_id)?
545-
.ok_or(anyhow!("Can't find group with id {:?}", group_id))?;
546-
let params = {
547-
let provider = PhnxOpenMlsProvider::new(&connection);
548-
group.create_message(&provider, content)?
549-
};
550-
drop(connection);
551-
552-
// Phase 2: Send message to DS
553-
let ds_timestamp = self
554-
.inner
555-
.api_clients
556-
.get(&conversation.owner_domain())?
557-
.ds_send_message(params, group.leaf_signer(), group.group_state_ear_key())
558-
.await?;
559-
560-
// Phase 3: Merge the commit into the group & update conversation
561-
let mut connection = self.inner.connection.lock().await;
562-
let mut notifier = self.store_notifier();
563-
unsent_message.mark_as_sent(&connection, &mut notifier, ds_timestamp)?;
564-
group.store_update(&connection)?;
565-
let transaction = connection.transaction()?;
566-
Conversation::mark_as_read(
567-
&transaction,
568-
&mut notifier,
569-
vec![(conversation.id(), unsent_message.timestamp())].into_iter(),
570-
)?;
571-
transaction.commit()?;
572-
notifier.notify();
573-
574-
Ok(())
575-
}
576-
577521
/// Create a connection with a new user.
578522
///
579523
/// Returns the [`ConversationId`] of the newly created connection

0 commit comments

Comments
 (0)