refactor: replace async RwLock with sync RwLock for stock strings

This commit is contained in:
link2xt
2026-03-25 09:41:11 +01:00
committed by l
parent d1f1633c60
commit 2637c3bea4
29 changed files with 309 additions and 412 deletions

View File

@@ -306,20 +306,17 @@ pub unsafe extern "C" fn dc_set_stock_translation(
let msg = to_string_lossy(stock_msg); let msg = to_string_lossy(stock_msg);
let ctx = &*context; let ctx = &*context;
block_on(async move { match StockMessage::from_u32(stock_id)
match StockMessage::from_u32(stock_id) .with_context(|| format!("Invalid stock message ID {stock_id}"))
.with_context(|| format!("Invalid stock message ID {stock_id}")) .log_err(ctx)
{
Ok(id) => ctx
.set_stock_translation(id, msg)
.context("set_stock_translation failed")
.log_err(ctx) .log_err(ctx)
{ .is_ok() as libc::c_int,
Ok(id) => ctx Err(_) => 0,
.set_stock_translation(id, msg) }
.await
.context("set_stock_translation failed")
.log_err(ctx)
.is_ok() as libc::c_int,
Err(_) => 0,
}
})
} }
#[no_mangle] #[no_mangle]

View File

@@ -473,9 +473,7 @@ impl CommandApi {
let accounts = self.accounts.read().await; let accounts = self.accounts.read().await;
for (stock_id, stock_message) in strings { for (stock_id, stock_message) in strings {
if let Some(stock_id) = StockMessage::from_u32(stock_id) { if let Some(stock_id) = StockMessage::from_u32(stock_id) {
accounts accounts.set_stock_translation(stock_id, stock_message)?;
.set_stock_translation(stock_id, stock_message)
.await?;
} }
} }
Ok(()) Ok(())

View File

@@ -1249,13 +1249,11 @@ mod tests {
let account1 = accounts.get_account(1).context("failed to get account 1")?; let account1 = accounts.get_account(1).context("failed to get account 1")?;
let account2 = accounts.get_account(2).context("failed to get account 2")?; let account2 = accounts.get_account(2).context("failed to get account 2")?;
assert_eq!(stock_str::no_messages(&account1).await, "No messages."); assert_eq!(stock_str::no_messages(&account1), "No messages.");
assert_eq!(stock_str::no_messages(&account2).await, "No messages."); assert_eq!(stock_str::no_messages(&account2), "No messages.");
account1 account1.set_stock_translation(StockMessage::NoMessages, "foobar".to_string())?;
.set_stock_translation(StockMessage::NoMessages, "foobar".to_string()) assert_eq!(stock_str::no_messages(&account1), "foobar");
.await?; assert_eq!(stock_str::no_messages(&account2), "foobar");
assert_eq!(stock_str::no_messages(&account1).await, "foobar");
assert_eq!(stock_str::no_messages(&account2).await, "foobar");
Ok(()) Ok(())
} }

View File

@@ -104,13 +104,11 @@ impl CallInfo {
}; };
if self.is_incoming() { if self.is_incoming() {
let incoming_call_str = let incoming_call_str = stock_str::incoming_call(context, self.has_video_initially());
stock_str::incoming_call(context, self.has_video_initially()).await;
self.update_text(context, &format!("{incoming_call_str}\n{duration}")) self.update_text(context, &format!("{incoming_call_str}\n{duration}"))
.await?; .await?;
} else { } else {
let outgoing_call_str = let outgoing_call_str = stock_str::outgoing_call(context, self.has_video_initially());
stock_str::outgoing_call(context, self.has_video_initially()).await;
self.update_text(context, &format!("{outgoing_call_str}\n{duration}")) self.update_text(context, &format!("{outgoing_call_str}\n{duration}"))
.await?; .await?;
} }
@@ -207,7 +205,7 @@ impl Context {
); );
ensure!(!chat.is_self_talk(), "Cannot call self"); ensure!(!chat.is_self_talk(), "Cannot call self");
let outgoing_call_str = stock_str::outgoing_call(self, has_video_initially).await; let outgoing_call_str = stock_str::outgoing_call(self, has_video_initially);
let mut call = Message { let mut call = Message {
viewtype: Viewtype::Call, viewtype: Viewtype::Call,
text: outgoing_call_str, text: outgoing_call_str,
@@ -286,11 +284,11 @@ impl Context {
if call.is_incoming() { if call.is_incoming() {
call.mark_as_ended(self).await?; call.mark_as_ended(self).await?;
markseen_msgs(self, vec![call_id]).await?; markseen_msgs(self, vec![call_id]).await?;
let declined_call_str = stock_str::declined_call(self).await; let declined_call_str = stock_str::declined_call(self);
call.update_text(self, &declined_call_str).await?; call.update_text(self, &declined_call_str).await?;
} else { } else {
call.mark_as_canceled(self).await?; call.mark_as_canceled(self).await?;
let canceled_call_str = stock_str::canceled_call(self).await; let canceled_call_str = stock_str::canceled_call(self);
call.update_text(self, &canceled_call_str).await?; call.update_text(self, &canceled_call_str).await?;
} }
} else { } else {
@@ -333,11 +331,11 @@ impl Context {
if !call.is_accepted() && !call.is_ended() { if !call.is_accepted() && !call.is_ended() {
if call.is_incoming() { if call.is_incoming() {
call.mark_as_canceled(&context).await?; call.mark_as_canceled(&context).await?;
let missed_call_str = stock_str::missed_call(&context).await; let missed_call_str = stock_str::missed_call(&context);
call.update_text(&context, &missed_call_str).await?; call.update_text(&context, &missed_call_str).await?;
} else { } else {
call.mark_as_ended(&context).await?; call.mark_as_ended(&context).await?;
let canceled_call_str = stock_str::canceled_call(&context).await; let canceled_call_str = stock_str::canceled_call(&context);
call.update_text(&context, &canceled_call_str).await?; call.update_text(&context, &canceled_call_str).await?;
} }
context.emit_msgs_changed(call.msg.chat_id, call_id); context.emit_msgs_changed(call.msg.chat_id, call_id);
@@ -363,12 +361,12 @@ impl Context {
if call.is_incoming() { if call.is_incoming() {
if call.is_stale() { if call.is_stale() {
let missed_call_str = stock_str::missed_call(self).await; let missed_call_str = stock_str::missed_call(self);
call.update_text(self, &missed_call_str).await?; call.update_text(self, &missed_call_str).await?;
self.emit_incoming_msg(call.msg.chat_id, call_id); // notify missed call self.emit_incoming_msg(call.msg.chat_id, call_id); // notify missed call
} else { } else {
let incoming_call_str = let incoming_call_str =
stock_str::incoming_call(self, call.has_video_initially()).await; stock_str::incoming_call(self, call.has_video_initially());
call.update_text(self, &incoming_call_str).await?; call.update_text(self, &incoming_call_str).await?;
self.emit_msgs_changed(call.msg.chat_id, call_id); // ringing calls are not additionally notified self.emit_msgs_changed(call.msg.chat_id, call_id); // ringing calls are not additionally notified
let can_call_me = match who_can_call_me(self).await? { let can_call_me = match who_can_call_me(self).await? {
@@ -409,8 +407,7 @@ impl Context {
)); ));
} }
} else { } else {
let outgoing_call_str = let outgoing_call_str = stock_str::outgoing_call(self, call.has_video_initially());
stock_str::outgoing_call(self, call.has_video_initially()).await;
call.update_text(self, &outgoing_call_str).await?; call.update_text(self, &outgoing_call_str).await?;
self.emit_msgs_changed(call.msg.chat_id, call_id); self.emit_msgs_changed(call.msg.chat_id, call_id);
} }
@@ -462,22 +459,22 @@ impl Context {
if call.is_incoming() { if call.is_incoming() {
if from_id == ContactId::SELF { if from_id == ContactId::SELF {
call.mark_as_ended(self).await?; call.mark_as_ended(self).await?;
let declined_call_str = stock_str::declined_call(self).await; let declined_call_str = stock_str::declined_call(self);
call.update_text(self, &declined_call_str).await?; call.update_text(self, &declined_call_str).await?;
} else { } else {
call.mark_as_canceled(self).await?; call.mark_as_canceled(self).await?;
let missed_call_str = stock_str::missed_call(self).await; let missed_call_str = stock_str::missed_call(self);
call.update_text(self, &missed_call_str).await?; call.update_text(self, &missed_call_str).await?;
} }
} else { } else {
// outgoing // outgoing
if from_id == ContactId::SELF { if from_id == ContactId::SELF {
call.mark_as_canceled(self).await?; call.mark_as_canceled(self).await?;
let canceled_call_str = stock_str::canceled_call(self).await; let canceled_call_str = stock_str::canceled_call(self);
call.update_text(self, &canceled_call_str).await?; call.update_text(self, &canceled_call_str).await?;
} else { } else {
call.mark_as_ended(self).await?; call.mark_as_ended(self).await?;
let declined_call_str = stock_str::declined_call(self).await; let declined_call_str = stock_str::declined_call(self);
call.update_text(self, &declined_call_str).await?; call.update_text(self, &declined_call_str).await?;
} }
} }

View File

@@ -476,7 +476,7 @@ impl ChatId {
/// Adds message "Messages are end-to-end encrypted". /// Adds message "Messages are end-to-end encrypted".
pub(crate) async fn add_e2ee_notice(self, context: &Context, timestamp: i64) -> Result<()> { pub(crate) async fn add_e2ee_notice(self, context: &Context, timestamp: i64) -> Result<()> {
let text = stock_str::messages_e2ee_info_msg(context).await; let text = stock_str::messages_e2ee_info_msg(context);
add_info_msg_with_cmd( add_info_msg_with_cmd(
context, context,
self, self,
@@ -669,7 +669,7 @@ SELECT id, rfc724_mid, pre_rfc724_mid, timestamp, ?, 1 FROM msgs WHERE chat_id=?
} }
if chat.is_self_talk() { if chat.is_self_talk() {
let mut msg = Message::new_text(stock_str::self_deleted_msg_body(context).await); let mut msg = Message::new_text(stock_str::self_deleted_msg_body(context));
add_device_msg(context, None, Some(&mut msg)).await?; add_device_msg(context, None, Some(&mut msg)).await?;
} }
chatlist_events::emit_chatlist_changed(context); chatlist_events::emit_chatlist_changed(context);
@@ -1155,10 +1155,10 @@ SELECT id, rfc724_mid, pre_rfc724_mid, timestamp, ?, 1 FROM msgs WHERE chat_id=?
pub async fn get_encryption_info(self, context: &Context) -> Result<String> { pub async fn get_encryption_info(self, context: &Context) -> Result<String> {
let chat = Chat::load_from_db(context, self).await?; let chat = Chat::load_from_db(context, self).await?;
if !chat.is_encrypted(context).await? { if !chat.is_encrypted(context).await? {
return Ok(stock_str::encr_none(context).await); return Ok(stock_str::encr_none(context));
} }
let mut ret = stock_str::messages_are_e2ee(context).await + "\n"; let mut ret = stock_str::messages_are_e2ee(context) + "\n";
for &contact_id in get_chat_contacts(context, self) for &contact_id in get_chat_contacts(context, self)
.await? .await?
@@ -1392,7 +1392,7 @@ impl Chat {
.context(format!("Failed loading chat {chat_id} from database"))?; .context(format!("Failed loading chat {chat_id} from database"))?;
if chat.id.is_archived_link() { if chat.id.is_archived_link() {
chat.name = stock_str::archived_chats(context).await; chat.name = stock_str::archived_chats(context);
} else { } else {
if chat.typ == Chattype::Single && chat.name.is_empty() { if chat.typ == Chattype::Single && chat.name.is_empty() {
// chat.name is set to contact.display_name on changes, // chat.name is set to contact.display_name on changes,
@@ -1416,9 +1416,9 @@ impl Chat {
chat.name = chat_name; chat.name = chat_name;
} }
if chat.param.exists(Param::Selftalk) { if chat.param.exists(Param::Selftalk) {
chat.name = stock_str::saved_messages(context).await; chat.name = stock_str::saved_messages(context);
} else if chat.param.exists(Param::Devicetalk) { } else if chat.param.exists(Param::Devicetalk) {
chat.name = stock_str::device_messages(context).await; chat.name = stock_str::device_messages(context);
} }
} }
@@ -2306,15 +2306,10 @@ pub(crate) async fn update_special_chat_names(context: &Context) -> Result<()> {
update_special_chat_name( update_special_chat_name(
context, context,
ContactId::DEVICE, ContactId::DEVICE,
stock_str::device_messages(context).await, stock_str::device_messages(context),
)
.await?;
update_special_chat_name(
context,
ContactId::SELF,
stock_str::saved_messages(context).await,
) )
.await?; .await?;
update_special_chat_name(context, ContactId::SELF, stock_str::saved_messages(context)).await?;
Ok(()) Ok(())
} }
@@ -3068,7 +3063,7 @@ async fn donation_request_maybe(context: &Context) -> Result<()> {
let ts = if ts == 0 || msg_cnt.await? < 100 { let ts = if ts == 0 || msg_cnt.await? < 100 {
now.saturating_add(secs_between_checks) now.saturating_add(secs_between_checks)
} else { } else {
let mut msg = Message::new_text(stock_str::donation_request(context).await); let mut msg = Message::new_text(stock_str::donation_request(context));
add_device_msg(context, None, Some(&mut msg)).await?; add_device_msg(context, None, Some(&mut msg)).await?;
i64::MAX i64::MAX
}; };
@@ -3622,10 +3617,10 @@ pub(crate) async fn create_group_ex(
{ {
let text = if !grpid.is_empty() { let text = if !grpid.is_empty() {
// Add "Others will only see this group after you sent a first message." message. // Add "Others will only see this group after you sent a first message." message.
stock_str::new_group_send_first_message(context).await stock_str::new_group_send_first_message(context)
} else { } else {
// Add "Messages in this chat use classic email and are not encrypted." message. // Add "Messages in this chat use classic email and are not encrypted." message.
stock_str::chat_unencrypted_explanation(context).await stock_str::chat_unencrypted_explanation(context)
}; };
add_info_msg(context, chat_id, &text).await?; add_info_msg(context, chat_id, &text).await?;
} }
@@ -4197,7 +4192,7 @@ async fn send_member_removal_msg(
if contact_id == ContactId::SELF { if contact_id == ContactId::SELF {
if chat.typ == Chattype::InBroadcast { if chat.typ == Chattype::InBroadcast {
msg.text = stock_str::msg_you_left_broadcast(context).await; msg.text = stock_str::msg_you_left_broadcast(context);
} else { } else {
msg.text = stock_str::msg_group_left_local(context, ContactId::SELF).await; msg.text = stock_str::msg_group_left_local(context, ContactId::SELF).await;
} }
@@ -4358,7 +4353,7 @@ async fn rename_ex(
{ {
msg.viewtype = Viewtype::Text; msg.viewtype = Viewtype::Text;
msg.text = if chat.typ == Chattype::OutBroadcast { msg.text = if chat.typ == Chattype::OutBroadcast {
stock_str::msg_broadcast_name_changed(context, &chat.name, &new_name).await stock_str::msg_broadcast_name_changed(context, &chat.name, &new_name)
} else { } else {
stock_str::msg_grp_name(context, &chat.name, &new_name, ContactId::SELF).await stock_str::msg_grp_name(context, &chat.name, &new_name, ContactId::SELF).await
}; };
@@ -4423,7 +4418,7 @@ pub async fn set_chat_profile_image(
chat.param.remove(Param::ProfileImage); chat.param.remove(Param::ProfileImage);
msg.param.remove(Param::Arg); msg.param.remove(Param::Arg);
msg.text = if chat.typ == Chattype::OutBroadcast { msg.text = if chat.typ == Chattype::OutBroadcast {
stock_str::msg_broadcast_img_changed(context).await stock_str::msg_broadcast_img_changed(context)
} else { } else {
stock_str::msg_grp_img_deleted(context, ContactId::SELF).await stock_str::msg_grp_img_deleted(context, ContactId::SELF).await
}; };
@@ -4437,7 +4432,7 @@ pub async fn set_chat_profile_image(
chat.param.set(Param::ProfileImage, image_blob.as_name()); chat.param.set(Param::ProfileImage, image_blob.as_name());
msg.param.set(Param::Arg, image_blob.as_name()); msg.param.set(Param::Arg, image_blob.as_name());
msg.text = if chat.typ == Chattype::OutBroadcast { msg.text = if chat.typ == Chattype::OutBroadcast {
stock_str::msg_broadcast_img_changed(context).await stock_str::msg_broadcast_img_changed(context)
} else { } else {
stock_str::msg_grp_img_changed(context, ContactId::SELF).await stock_str::msg_grp_img_changed(context, ContactId::SELF).await
}; };

View File

@@ -806,7 +806,7 @@ async fn test_self_talk() -> Result<()> {
assert!(chat.visibility == ChatVisibility::Normal); assert!(chat.visibility == ChatVisibility::Normal);
assert!(!chat.is_device_talk()); assert!(!chat.is_device_talk());
assert!(chat.can_send(&t).await?); assert!(chat.can_send(&t).await?);
assert_eq!(chat.name, stock_str::saved_messages(&t).await); assert_eq!(chat.name, stock_str::saved_messages(&t));
assert!(chat.get_profile_image(&t).await?.is_some()); assert!(chat.get_profile_image(&t).await?.is_some());
let msg_id = send_text_msg(&t, chat.id, "foo self".to_string()).await?; let msg_id = send_text_msg(&t, chat.id, "foo self".to_string()).await?;
@@ -911,7 +911,7 @@ async fn test_add_device_msg_labelled() -> Result<()> {
assert!(!chat.can_send(&t).await?); assert!(!chat.can_send(&t).await?);
assert!(chat.why_cant_send(&t).await? == Some(CantSendReason::DeviceChat)); assert!(chat.why_cant_send(&t).await? == Some(CantSendReason::DeviceChat));
assert_eq!(chat.name, stock_str::device_messages(&t).await); assert_eq!(chat.name, stock_str::device_messages(&t));
let device_msg_icon = chat.get_profile_image(&t).await?.unwrap(); let device_msg_icon = chat.get_profile_image(&t).await?.unwrap();
assert_eq!( assert_eq!(
device_msg_icon.metadata()?.len(), device_msg_icon.metadata()?.len(),
@@ -3797,7 +3797,7 @@ async fn test_leave_broadcast_multidevice() -> Result<()> {
assert_eq!(rcvd.chat_id, bob1_hello.chat_id); assert_eq!(rcvd.chat_id, bob1_hello.chat_id);
assert!(rcvd.is_info()); assert!(rcvd.is_info());
assert_eq!(rcvd.get_info_type(), SystemMessage::MemberRemovedFromGroup); assert_eq!(rcvd.get_info_type(), SystemMessage::MemberRemovedFromGroup);
assert_eq!(rcvd.text, stock_str::msg_you_left_broadcast(bob1).await); assert_eq!(rcvd.text, stock_str::msg_you_left_broadcast(bob1));
Ok(()) Ok(())
} }

View File

@@ -417,7 +417,7 @@ impl Chatlist {
Summary::new_with_reaction_details(context, &lastmsg, chat, lastcontact.as_ref()).await Summary::new_with_reaction_details(context, &lastmsg, chat, lastcontact.as_ref()).await
} else { } else {
Ok(Summary { Ok(Summary {
text: stock_str::no_messages(context).await, text: stock_str::no_messages(context),
..Default::default() ..Default::default()
}) })
} }
@@ -648,7 +648,6 @@ mod tests {
assert_eq!(chats.len(), 0); assert_eq!(chats.len(), 0);
t.set_stock_translation(StockMessage::SavedMessages, "test-1234-save".to_string()) t.set_stock_translation(StockMessage::SavedMessages, "test-1234-save".to_string())
.await
.unwrap(); .unwrap();
let chats = Chatlist::try_load(&t, 0, Some("t-1234-s"), None) let chats = Chatlist::try_load(&t, 0, Some("t-1234-s"), None)
.await .await
@@ -656,7 +655,6 @@ mod tests {
assert_eq!(chats.len(), 1); assert_eq!(chats.len(), 1);
t.set_stock_translation(StockMessage::DeviceMessages, "test-5678-babbel".to_string()) t.set_stock_translation(StockMessage::DeviceMessages, "test-5678-babbel".to_string())
.await
.unwrap(); .unwrap();
let chats = Chatlist::try_load(&t, 0, Some("t-5678-b"), None) let chats = Chatlist::try_load(&t, 0, Some("t-5678-b"), None)
.await .await

View File

@@ -146,7 +146,7 @@ impl Context {
if let Err(err) = res.as_ref() { if let Err(err) = res.as_ref() {
// We are using Anyhow's .context() and to show the // We are using Anyhow's .context() and to show the
// inner error, too, we need the {:#}: // inner error, too, we need the {:#}:
let error_msg = stock_str::configuration_failed(self, &format!("{err:#}")).await; let error_msg = stock_str::configuration_failed(self, &format!("{err:#}"));
progress!(self, 0, Some(error_msg.clone())); progress!(self, 0, Some(error_msg.clone()));
bail!(error_msg); bail!(error_msg);
} else { } else {
@@ -637,10 +637,7 @@ async fn configure(ctx: &Context, param: &EnteredLoginParam) -> Result<Option<&'
let imap_session = match imap.connect(ctx, configuring).await { let imap_session = match imap.connect(ctx, configuring).await {
Ok(imap_session) => imap_session, Ok(imap_session) => imap_session,
Err(err) => { Err(err) => {
bail!( bail!("{}", nicer_configuration_error(ctx, format!("{err:#}")));
"{}",
nicer_configuration_error(ctx, format!("{err:#}")).await
);
} }
}; };
@@ -781,7 +778,7 @@ async fn get_autoconfig(
None None
} }
async fn nicer_configuration_error(context: &Context, e: String) -> String { fn nicer_configuration_error(context: &Context, e: String) -> String {
if e.to_lowercase().contains("could not resolve") if e.to_lowercase().contains("could not resolve")
|| e.to_lowercase().contains("connection attempts") || e.to_lowercase().contains("connection attempts")
|| e.to_lowercase() || e.to_lowercase()
@@ -790,7 +787,7 @@ async fn nicer_configuration_error(context: &Context, e: String) -> String {
|| e.to_lowercase() || e.to_lowercase()
.contains("failed to lookup address information") .contains("failed to lookup address information")
{ {
return stock_str::error_no_network(context).await; return stock_str::error_no_network(context);
} }
e e

View File

@@ -688,7 +688,7 @@ impl Contact {
.await? .await?
{ {
if contact_id == ContactId::SELF { if contact_id == ContactId::SELF {
contact.name = stock_str::self_msg(context).await; contact.name = stock_str::self_msg(context);
contact.authname = context contact.authname = context
.get_config(Config::Displayname) .get_config(Config::Displayname)
.await? .await?
@@ -705,9 +705,9 @@ impl Contact {
.await? .await?
.unwrap_or_default(); .unwrap_or_default();
} else if contact_id == ContactId::DEVICE { } else if contact_id == ContactId::DEVICE {
contact.name = stock_str::device_messages(context).await; contact.name = stock_str::device_messages(context);
contact.addr = ContactId::DEVICE_ADDR.to_string(); contact.addr = ContactId::DEVICE_ADDR.to_string();
contact.status = stock_str::device_messages_hint(context).await; contact.status = stock_str::device_messages_hint(context);
} }
Ok(Some(contact)) Ok(Some(contact))
} else { } else {
@@ -1240,7 +1240,7 @@ ORDER BY c.origin>=? DESC, c.last_seen DESC, c.id DESC
if self_addr.contains(query) if self_addr.contains(query)
|| self_name.contains(query) || self_name.contains(query)
|| self_name2.await.contains(query) || self_name2.contains(query)
{ {
add_self = true; add_self = true;
} }
@@ -1392,17 +1392,17 @@ WHERE addr=?
.unwrap_or_default(); .unwrap_or_default();
let Some(fingerprint_other) = contact.fingerprint() else { let Some(fingerprint_other) = contact.fingerprint() else {
return Ok(stock_str::encr_none(context).await); return Ok(stock_str::encr_none(context));
}; };
let fingerprint_other = fingerprint_other.to_string(); let fingerprint_other = fingerprint_other.to_string();
let stock_message = if contact.public_key(context).await?.is_some() { let stock_message = if contact.public_key(context).await?.is_some() {
stock_str::messages_are_e2ee(context).await stock_str::messages_are_e2ee(context)
} else { } else {
stock_str::encr_none(context).await stock_str::encr_none(context)
}; };
let finger_prints = stock_str::finger_prints(context).await; let finger_prints = stock_str::finger_prints(context);
let mut ret = format!("{stock_message}\n{finger_prints}:"); let mut ret = format!("{stock_message}\n{finger_prints}:");
let fingerprint_self = load_self_public_key(context) let fingerprint_self = load_self_public_key(context)
@@ -1412,7 +1412,7 @@ WHERE addr=?
if addr < contact.addr { if addr < contact.addr {
cat_fingerprint( cat_fingerprint(
&mut ret, &mut ret,
&stock_str::self_msg(context).await, &stock_str::self_msg(context),
&addr, &addr,
&fingerprint_self, &fingerprint_self,
); );
@@ -1431,7 +1431,7 @@ WHERE addr=?
); );
cat_fingerprint( cat_fingerprint(
&mut ret, &mut ret,
&stock_str::self_msg(context).await, &stock_str::self_msg(context),
&addr, &addr,
&fingerprint_self, &fingerprint_self,
); );

View File

@@ -282,7 +282,7 @@ async fn test_add_or_lookup() {
// check SELF // check SELF
let contact = Contact::get_by_id(&t, ContactId::SELF).await.unwrap(); let contact = Contact::get_by_id(&t, ContactId::SELF).await.unwrap();
assert_eq!(contact.get_name(), stock_str::self_msg(&t).await); assert_eq!(contact.get_name(), stock_str::self_msg(&t));
assert_eq!(contact.get_addr(), "alice@example.org"); assert_eq!(contact.get_addr(), "alice@example.org");
assert!(!contact.is_blocked()); assert!(!contact.is_blocked());
} }

View File

@@ -437,7 +437,7 @@ impl Imap {
Err(err) => { Err(err) => {
let imap_user = lp.user.to_owned(); let imap_user = lp.user.to_owned();
let message = stock_str::cannot_login(context, &imap_user).await; let message = stock_str::cannot_login(context, &imap_user);
warn!(context, "IMAP failed to login: {err:#}."); warn!(context, "IMAP failed to login: {err:#}.");
first_error.get_or_insert(format_err!("{message} ({err:#})")); first_error.get_or_insert(format_err!("{message} ({err:#})"));

View File

@@ -208,7 +208,7 @@ impl BackupProvider {
info!(context, "Received backup reception acknowledgement."); info!(context, "Received backup reception acknowledgement.");
context.emit_event(EventType::ImexProgress(1000)); context.emit_event(EventType::ImexProgress(1000));
let mut msg = Message::new_text(backup_transfer_msg_body(&context).await); let mut msg = Message::new_text(backup_transfer_msg_body(&context));
add_device_msg(&context, None, Some(&mut msg)).await?; add_device_msg(&context, None, Some(&mut msg)).await?;
Ok(()) Ok(())

View File

@@ -288,13 +288,13 @@ pub async fn send_locations_to_chat(
) )
.await?; .await?;
if 0 != seconds && !is_sending_locations_before { if 0 != seconds && !is_sending_locations_before {
let mut msg = Message::new_text(stock_str::msg_location_enabled(context).await); let mut msg = Message::new_text(stock_str::msg_location_enabled(context));
msg.param.set_cmd(SystemMessage::LocationStreamingEnabled); msg.param.set_cmd(SystemMessage::LocationStreamingEnabled);
chat::send_msg(context, chat_id, &mut msg) chat::send_msg(context, chat_id, &mut msg)
.await .await
.unwrap_or_default(); .unwrap_or_default();
} else if 0 == seconds && is_sending_locations_before { } else if 0 == seconds && is_sending_locations_before {
let stock_str = stock_str::msg_location_disabled(context).await; let stock_str = stock_str::msg_location_disabled(context);
chat::add_info_msg(context, chat_id, &stock_str).await?; chat::add_info_msg(context, chat_id, &stock_str).await?;
} }
context.emit_event(EventType::ChatModified(chat_id)); context.emit_event(EventType::ChatModified(chat_id));
@@ -852,7 +852,7 @@ async fn maybe_send_locations(context: &Context) -> Result<Option<u64>> {
.await .await
.context("failed to disable location streaming")?; .context("failed to disable location streaming")?;
let stock_str = stock_str::msg_location_disabled(context).await; let stock_str = stock_str::msg_location_disabled(context);
chat::add_info_msg(context, chat_id, &stock_str).await?; chat::add_info_msg(context, chat_id, &stock_str).await?;
context.emit_event(EventType::ChatModified(chat_id)); context.emit_event(EventType::ChatModified(chat_id));
chatlist_events::emit_chatlist_item_changed(context, chat_id); chatlist_events::emit_chatlist_item_changed(context, chat_id);

View File

@@ -598,7 +598,7 @@ impl Message {
if let Some(msg) = &mut msg { if let Some(msg) = &mut msg {
msg.additional_text = msg.additional_text =
Self::get_additional_text(context, msg.download_state, &msg.param).await?; Self::get_additional_text(context, msg.download_state, &msg.param)?;
} }
Ok(msg) Ok(msg)
@@ -607,7 +607,7 @@ impl Message {
/// Returns additional text which is appended to the message's text field /// Returns additional text which is appended to the message's text field
/// when it is loaded from the database. /// when it is loaded from the database.
/// Currently this is used to add infomation to pre-messages of what the download will be and how large it is /// Currently this is used to add infomation to pre-messages of what the download will be and how large it is
async fn get_additional_text( fn get_additional_text(
context: &Context, context: &Context,
download_state: DownloadState, download_state: DownloadState,
param: &Params, param: &Params,
@@ -630,7 +630,7 @@ impl Message {
return match viewtype { return match viewtype {
Viewtype::File => Ok(format!(" [{file_name} {file_size}]")), Viewtype::File => Ok(format!(" [{file_name} {file_size}]")),
_ => { _ => {
let translated_viewtype = viewtype.to_locale_string(context).await; let translated_viewtype = viewtype.to_locale_string(context);
Ok(format!(" [{translated_viewtype} {file_size}]")) Ok(format!(" [{translated_viewtype} {file_size}]"))
} }
}; };

View File

@@ -732,7 +732,7 @@ impl MimeFactory {
Some(name) => name, Some(name) => name,
None => context.get_config(Config::Addr).await?.unwrap_or_default(), None => context.get_config(Config::Addr).await?.unwrap_or_default(),
}; };
stock_str::subject_for_new_contact(context, self_name).await stock_str::subject_for_new_contact(context, self_name)
} }
Loaded::Mdn { .. } => "Receipt Notification".to_string(), // untranslated to no reveal sender's language Loaded::Mdn { .. } => "Receipt Notification".to_string(), // untranslated to no reveal sender's language
}; };

View File

@@ -111,10 +111,10 @@ async fn generate_join_group_qr_code(context: &Context, chat_id: ChatId) -> Resu
let qrcode_description = match chat.typ { let qrcode_description = match chat.typ {
crate::constants::Chattype::Group => { crate::constants::Chattype::Group => {
stock_str::secure_join_group_qr_description(context, &chat).await stock_str::secure_join_group_qr_description(context, &chat)
} }
crate::constants::Chattype::OutBroadcast => { crate::constants::Chattype::OutBroadcast => {
stock_str::secure_join_broadcast_qr_description(context, &chat).await stock_str::secure_join_broadcast_qr_description(context, &chat)
} }
_ => bail!("Unexpected chat type {}", chat.typ), _ => bail!("Unexpected chat type {}", chat.typ),
}; };
@@ -132,7 +132,7 @@ async fn generate_verification_qr(context: &Context) -> Result<String> {
let (avatar, displayname, addr, color) = self_info(context).await?; let (avatar, displayname, addr, color) = self_info(context).await?;
inner_generate_secure_join_qr_code( inner_generate_secure_join_qr_code(
&stock_str::setup_contact_qr_description(context, &displayname, &addr).await, &stock_str::setup_contact_qr_description(context, &displayname, &addr),
&securejoin::get_securejoin_qr(context, None).await?, &securejoin::get_securejoin_qr(context, None).await?,
&color, &color,
avatar, avatar,

View File

@@ -128,7 +128,7 @@ impl Context {
let folders = get_watched_folders(self).await?; let folders = get_watched_folders(self).await?;
get_unique_quota_roots_and_usage(session, folders).await get_unique_quota_roots_and_usage(session, folders).await
} else { } else {
Err(anyhow!(stock_str::not_supported_by_provider(self).await)) Err(anyhow!(stock_str::not_supported_by_provider(self)))
}; };
if let Ok(quota) = &quota { if let Ok(quota) = &quota {
@@ -143,8 +143,7 @@ impl Context {
Some(&highest.to_string()), Some(&highest.to_string()),
) )
.await?; .await?;
let mut msg = let mut msg = Message::new_text(stock_str::quota_exceeding(self, highest));
Message::new_text(stock_str::quota_exceeding(self, highest).await);
add_device_msg_with_importance(self, None, Some(&mut msg), true).await?; add_device_msg_with_importance(self, None, Some(&mut msg), true).await?;
} else if highest <= QUOTA_ALLCLEAR_PERCENTAGE { } else if highest <= QUOTA_ALLCLEAR_PERCENTAGE {
self.set_config_internal(Config::QuotaExceeding, None) self.set_config_internal(Config::QuotaExceeding, None)

View File

@@ -3357,7 +3357,7 @@ async fn apply_chat_name_avatar_and_description_changes(
let old_name = &sanitize_single_line(old_name); let old_name = &sanitize_single_line(old_name);
better_msg.get_or_insert( better_msg.get_or_insert(
if matches!(chat.typ, Chattype::InBroadcast | Chattype::OutBroadcast) { if matches!(chat.typ, Chattype::InBroadcast | Chattype::OutBroadcast) {
stock_str::msg_broadcast_name_changed(context, old_name, grpname).await stock_str::msg_broadcast_name_changed(context, old_name, grpname)
} else { } else {
stock_str::msg_grp_name(context, old_name, grpname, from_id).await stock_str::msg_grp_name(context, old_name, grpname, from_id).await
}, },
@@ -3420,7 +3420,7 @@ async fn apply_chat_name_avatar_and_description_changes(
// apart from that, the group-avatar is send along with various other messages // apart from that, the group-avatar is send along with various other messages
better_msg.get_or_insert( better_msg.get_or_insert(
if matches!(chat.typ, Chattype::InBroadcast | Chattype::OutBroadcast) { if matches!(chat.typ, Chattype::InBroadcast | Chattype::OutBroadcast) {
stock_str::msg_broadcast_img_changed(context).await stock_str::msg_broadcast_img_changed(context)
} else { } else {
match avatar_action { match avatar_action {
AvatarAction::Delete => stock_str::msg_grp_img_deleted(context, from_id).await, AvatarAction::Delete => stock_str::msg_grp_img_deleted(context, from_id).await,
@@ -3860,7 +3860,7 @@ async fn apply_in_broadcast_changes(
info!(context, "No-op broadcast 'Member added' message (TRASH)"); info!(context, "No-op broadcast 'Member added' message (TRASH)");
"".to_string() "".to_string()
} else { } else {
stock_str::msg_you_joined_broadcast(context).await stock_str::msg_you_joined_broadcast(context)
}; };
better_msg.get_or_insert(msg); better_msg.get_or_insert(msg);
@@ -3876,7 +3876,7 @@ async fn apply_in_broadcast_changes(
chat::delete_broadcast_secret(context, chat.id).await?; chat::delete_broadcast_secret(context, chat.id).await?;
if from_id == ContactId::SELF { if from_id == ContactId::SELF {
better_msg.get_or_insert(stock_str::msg_you_left_broadcast(context).await); better_msg.get_or_insert(stock_str::msg_you_left_broadcast(context));
} else { } else {
better_msg.get_or_insert( better_msg.get_or_insert(
stock_str::msg_del_member_local(context, ContactId::SELF, from_id).await, stock_str::msg_del_member_local(context, ContactId::SELF, from_id).await,

View File

@@ -109,36 +109,36 @@ impl DetailedConnectivity {
} }
} }
async fn to_string_imap(&self, context: &Context) -> String { fn to_string_imap(&self, context: &Context) -> String {
match self { match self {
DetailedConnectivity::Error(e) => stock_str::error(context, e).await, DetailedConnectivity::Error(e) => stock_str::error(context, e),
DetailedConnectivity::Uninitialized => "Not started".to_string(), DetailedConnectivity::Uninitialized => "Not started".to_string(),
DetailedConnectivity::Connecting => stock_str::connecting(context).await, DetailedConnectivity::Connecting => stock_str::connecting(context),
DetailedConnectivity::Preparing | DetailedConnectivity::Working => { DetailedConnectivity::Preparing | DetailedConnectivity::Working => {
stock_str::updating(context).await stock_str::updating(context)
} }
DetailedConnectivity::InterruptingIdle | DetailedConnectivity::Idle => { DetailedConnectivity::InterruptingIdle | DetailedConnectivity::Idle => {
stock_str::connected(context).await stock_str::connected(context)
} }
DetailedConnectivity::NotConfigured => "Not configured".to_string(), DetailedConnectivity::NotConfigured => "Not configured".to_string(),
} }
} }
async fn to_string_smtp(&self, context: &Context) -> String { fn to_string_smtp(&self, context: &Context) -> String {
match self { match self {
DetailedConnectivity::Error(e) => stock_str::error(context, e).await, DetailedConnectivity::Error(e) => stock_str::error(context, e),
DetailedConnectivity::Uninitialized => { DetailedConnectivity::Uninitialized => {
"You did not try to send a message recently.".to_string() "You did not try to send a message recently.".to_string()
} }
DetailedConnectivity::Connecting => stock_str::connecting(context).await, DetailedConnectivity::Connecting => stock_str::connecting(context),
DetailedConnectivity::Working => stock_str::sending(context).await, DetailedConnectivity::Working => stock_str::sending(context),
// We don't know any more than that the last message was sent successfully; // We don't know any more than that the last message was sent successfully;
// since sending the last message, connectivity could have changed, which we don't notice // since sending the last message, connectivity could have changed, which we don't notice
// until another message is sent // until another message is sent
DetailedConnectivity::InterruptingIdle DetailedConnectivity::InterruptingIdle
| DetailedConnectivity::Preparing | DetailedConnectivity::Preparing
| DetailedConnectivity::Idle => stock_str::last_msg_sent_successfully(context).await, | DetailedConnectivity::Idle => stock_str::last_msg_sent_successfully(context),
DetailedConnectivity::NotConfigured => "Not configured".to_string(), DetailedConnectivity::NotConfigured => "Not configured".to_string(),
} }
} }
@@ -369,8 +369,8 @@ impl Context {
.get_config_bool(crate::config::Config::ProxyEnabled) .get_config_bool(crate::config::Config::ProxyEnabled)
.await? .await?
{ {
let proxy_enabled = stock_str::proxy_enabled(self).await; let proxy_enabled = stock_str::proxy_enabled(self);
let proxy_description = stock_str::proxy_description(self).await; let proxy_description = stock_str::proxy_description(self);
ret += &format!("<h3>{proxy_enabled}</h3><ul><li>{proxy_description}</li></ul>"); ret += &format!("<h3>{proxy_enabled}</h3><ul><li>{proxy_description}</li></ul>");
} }
@@ -396,7 +396,7 @@ impl Context {
_ => { _ => {
ret += &format!( ret += &format!(
"<h3>{}</h3>\n</body></html>\n", "<h3>{}</h3>\n</body></html>\n",
stock_str::not_connected(self).await stock_str::not_connected(self)
); );
return Ok(ret); return Ok(ret);
} }
@@ -412,7 +412,7 @@ impl Context {
// ============================================================================================= // =============================================================================================
let watched_folders = get_watched_folder_configs(self).await?; let watched_folders = get_watched_folder_configs(self).await?;
let incoming_messages = stock_str::incoming_messages(self).await; let incoming_messages = stock_str::incoming_messages(self);
ret += &format!("<h3>{incoming_messages}</h3><ul>"); ret += &format!("<h3>{incoming_messages}</h3><ul>");
let transports = self let transports = self
@@ -449,7 +449,7 @@ impl Context {
ret += &*escaper::encode_minimal(&foldername); ret += &*escaper::encode_minimal(&foldername);
} }
ret += ":</b> "; ret += ":</b> ";
ret += &*escaper::encode_minimal(&detailed.to_string_imap(self).await); ret += &*escaper::encode_minimal(&detailed.to_string_imap(self));
ret += "<br />"; ret += "<br />";
folder_added = true; folder_added = true;
@@ -464,7 +464,7 @@ impl Context {
ret += &*detailed.to_icon(); ret += &*detailed.to_icon();
ret += " "; ret += " ";
ret += &*escaper::encode_minimal(&detailed.to_string_imap(self).await); ret += &*escaper::encode_minimal(&detailed.to_string_imap(self));
ret += "<br />"; ret += "<br />";
} }
} }
@@ -504,13 +504,12 @@ impl Context {
); );
} }
let messages = stock_str::messages(self).await; let messages = stock_str::messages(self);
let part_of_total_used = stock_str::part_of_total_used( let part_of_total_used = stock_str::part_of_total_used(
self, self,
&resource.usage.to_string(), &resource.usage.to_string(),
&resource.limit.to_string(), &resource.limit.to_string(),
) );
.await;
ret += &match &resource.name { ret += &match &resource.name {
Atom(resource_name) => { Atom(resource_name) => {
format!( format!(
@@ -531,7 +530,7 @@ impl Context {
// - most times, this is the only item anyway // - most times, this is the only item anyway
let usage = &format_size(resource.usage * 1024, BINARY); let usage = &format_size(resource.usage * 1024, BINARY);
let limit = &format_size(resource.limit * 1024, BINARY); let limit = &format_size(resource.limit * 1024, BINARY);
stock_str::part_of_total_used(self, usage, limit).await stock_str::part_of_total_used(self, usage, limit)
} }
}; };
@@ -565,12 +564,12 @@ impl Context {
// Your last message was sent successfully // Your last message was sent successfully
// ============================================================================================= // =============================================================================================
let outgoing_messages = stock_str::outgoing_messages(self).await; let outgoing_messages = stock_str::outgoing_messages(self);
ret += &format!("<h3>{outgoing_messages}</h3><ul><li>"); ret += &format!("<h3>{outgoing_messages}</h3><ul><li>");
let detailed = smtp.get_detailed(); let detailed = smtp.get_detailed();
ret += &*detailed.to_icon(); ret += &*detailed.to_icon();
ret += " "; ret += " ";
ret += &*escaper::encode_minimal(&detailed.to_string_smtp(self).await); ret += &*escaper::encode_minimal(&detailed.to_string_smtp(self));
ret += "</li></ul>"; ret += "</li></ul>";
// ============================================================================================= // =============================================================================================

View File

@@ -158,7 +158,7 @@ pub(super) async fn start_protocol(context: &Context, invite: QrInvite) -> Resul
chat::add_info_msg_with_cmd( chat::add_info_msg_with_cmd(
context, context,
private_chat_id, private_chat_id,
&stock_str::securejoin_wait(context).await, &stock_str::securejoin_wait(context),
SystemMessage::SecurejoinWait, SystemMessage::SecurejoinWait,
None, None,
time(), time(),

View File

@@ -109,10 +109,10 @@ async fn test_setup_contact_ex(case: SetupContactCase) {
let mut i = 0..msg_cnt; let mut i = 0..msg_cnt;
let msg = get_chat_msg(&bob, bob_chat.get_id(), i.next().unwrap(), msg_cnt).await; let msg = get_chat_msg(&bob, bob_chat.get_id(), i.next().unwrap(), msg_cnt).await;
assert!(msg.is_info()); assert!(msg.is_info());
assert_eq!(msg.get_text(), messages_e2ee_info_msg(&bob).await); assert_eq!(msg.get_text(), messages_e2ee_info_msg(&bob));
let msg = get_chat_msg(&bob, bob_chat.get_id(), i.next().unwrap(), msg_cnt).await; let msg = get_chat_msg(&bob, bob_chat.get_id(), i.next().unwrap(), msg_cnt).await;
assert!(msg.is_info()); assert!(msg.is_info());
assert_eq!(msg.get_text(), stock_str::securejoin_wait(&bob).await); assert_eq!(msg.get_text(), stock_str::securejoin_wait(&bob));
let contact_alice_id = bob.add_or_lookup_contact_no_key(&alice).await.id; let contact_alice_id = bob.add_or_lookup_contact_no_key(&alice).await.id;
let sent = bob.pop_sent_msg().await; let sent = bob.pop_sent_msg().await;
@@ -250,7 +250,7 @@ async fn test_setup_contact_ex(case: SetupContactCase) {
let chat = alice.get_chat(&bob).await; let chat = alice.get_chat(&bob).await;
let msg = get_chat_msg(&alice, chat.get_id(), 0, 1).await; let msg = get_chat_msg(&alice, chat.get_id(), 0, 1).await;
assert!(msg.is_info()); assert!(msg.is_info());
let expected_text = messages_e2ee_info_msg(&alice).await; let expected_text = messages_e2ee_info_msg(&alice);
assert_eq!(msg.get_text(), expected_text); assert_eq!(msg.get_text(), expected_text);
} }
@@ -295,7 +295,7 @@ async fn test_setup_contact_ex(case: SetupContactCase) {
// The `SecurejoinWait` info message has been removed, but the e2ee notice remains. // The `SecurejoinWait` info message has been removed, but the e2ee notice remains.
let msg = get_chat_msg(&bob, bob_chat.get_id(), 0, 1).await; let msg = get_chat_msg(&bob, bob_chat.get_id(), 0, 1).await;
assert!(msg.is_info()); assert!(msg.is_info());
assert_eq!(msg.get_text(), messages_e2ee_info_msg(&bob).await); assert_eq!(msg.get_text(), messages_e2ee_info_msg(&bob));
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -625,7 +625,7 @@ async fn test_secure_join_group_ex(v3: bool, remove_invite: bool) -> Result<()>
// - You added member bob@example.net // - You added member bob@example.net
let msg = get_chat_msg(&alice, alice_chatid, 0, 2).await; let msg = get_chat_msg(&alice, alice_chatid, 0, 2).await;
assert!(msg.is_info()); assert!(msg.is_info());
let expected_text = messages_e2ee_info_msg(&alice).await; let expected_text = messages_e2ee_info_msg(&alice);
assert_eq!(msg.get_text(), expected_text); assert_eq!(msg.get_text(), expected_text);
} }

View File

@@ -901,7 +901,7 @@ async fn maybe_add_mvbox_move_deprecation_message(context: &Context) -> Result<(
if !context.get_config_bool(Config::OnlyFetchMvbox).await? if !context.get_config_bool(Config::OnlyFetchMvbox).await?
&& context.get_config_bool(Config::MvboxMove).await? && context.get_config_bool(Config::MvboxMove).await?
{ {
let mut msg = Message::new_text(stock_str::mvbox_move_deprecation(context).await); let mut msg = Message::new_text(stock_str::mvbox_move_deprecation(context));
add_device_msg(context, Some("mvbox_move_deprecation"), Some(&mut msg)).await?; add_device_msg(context, Some("mvbox_move_deprecation"), Some(&mut msg)).await?;
} }
Ok(()) Ok(())

View File

@@ -281,7 +281,7 @@ async fn send_stats(context: &Context) -> Result<ChatId> {
let chat_id = get_stats_chat_id(context).await?; let chat_id = get_stats_chat_id(context).await?;
let mut msg = Message::new(Viewtype::File); let mut msg = Message::new(Viewtype::File);
msg.set_text(crate::stock_str::stats_msg_body(context).await); msg.set_text(crate::stock_str::stats_msg_body(context));
let stats = get_stats(context).await?; let stats = get_stats(context).await?;

View File

@@ -4,9 +4,9 @@ use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use anyhow::{Result, bail}; use anyhow::{Result, bail};
use parking_lot::RwLock;
use strum::EnumProperty as EnumPropertyTrait; use strum::EnumProperty as EnumPropertyTrait;
use strum_macros::EnumProperty; use strum_macros::EnumProperty;
use tokio::sync::RwLock;
use crate::accounts::Accounts; use crate::accounts::Accounts;
use crate::blob::BlobObject; use crate::blob::BlobObject;
@@ -463,17 +463,16 @@ impl StockStrings {
} }
} }
async fn translated(&self, id: StockMessage) -> String { fn translated(&self, id: StockMessage) -> String {
self.translated_stockstrings self.translated_stockstrings
.read() .read()
.await
.get(&(id as usize)) .get(&(id as usize))
.map(AsRef::as_ref) .map(AsRef::as_ref)
.unwrap_or_else(|| id.fallback()) .unwrap_or_else(|| id.fallback())
.to_string() .to_string()
} }
async fn set_stock_translation(&self, id: StockMessage, stockstring: String) -> Result<()> { fn set_stock_translation(&self, id: StockMessage, stockstring: String) -> Result<()> {
if stockstring.contains("%1") && !id.fallback().contains("%1") { if stockstring.contains("%1") && !id.fallback().contains("%1") {
bail!( bail!(
"translation {} contains invalid %1 placeholder, default is {}", "translation {} contains invalid %1 placeholder, default is {}",
@@ -490,14 +489,13 @@ impl StockStrings {
} }
self.translated_stockstrings self.translated_stockstrings
.write() .write()
.await
.insert(id as usize, stockstring); .insert(id as usize, stockstring);
Ok(()) Ok(())
} }
} }
async fn translated(context: &Context, id: StockMessage) -> String { fn translated(context: &Context, id: StockMessage) -> String {
context.translated_stockstrings.translated(id).await context.translated_stockstrings.translated(id)
} }
/// Helper trait only meant to be implemented for [`String`]. /// Helper trait only meant to be implemented for [`String`].
@@ -546,43 +544,43 @@ impl ContactId {
impl StockStringMods for String {} impl StockStringMods for String {}
/// Stock string: `No messages.`. /// Stock string: `No messages.`.
pub(crate) async fn no_messages(context: &Context) -> String { pub(crate) fn no_messages(context: &Context) -> String {
translated(context, StockMessage::NoMessages).await translated(context, StockMessage::NoMessages)
} }
/// Stock string: `Me`. /// Stock string: `Me`.
pub(crate) async fn self_msg(context: &Context) -> String { pub(crate) fn self_msg(context: &Context) -> String {
translated(context, StockMessage::SelfMsg).await translated(context, StockMessage::SelfMsg)
} }
/// Stock string: `Draft`. /// Stock string: `Draft`.
pub(crate) async fn draft(context: &Context) -> String { pub(crate) fn draft(context: &Context) -> String {
translated(context, StockMessage::Draft).await translated(context, StockMessage::Draft)
} }
/// Stock string: `Voice message`. /// Stock string: `Voice message`.
pub(crate) async fn voice_message(context: &Context) -> String { pub(crate) fn voice_message(context: &Context) -> String {
translated(context, StockMessage::VoiceMessage).await translated(context, StockMessage::VoiceMessage)
} }
/// Stock string: `Image`. /// Stock string: `Image`.
pub(crate) async fn image(context: &Context) -> String { pub(crate) fn image(context: &Context) -> String {
translated(context, StockMessage::Image).await translated(context, StockMessage::Image)
} }
/// Stock string: `Video`. /// Stock string: `Video`.
pub(crate) async fn video(context: &Context) -> String { pub(crate) fn video(context: &Context) -> String {
translated(context, StockMessage::Video).await translated(context, StockMessage::Video)
} }
/// Stock string: `Audio`. /// Stock string: `Audio`.
pub(crate) async fn audio(context: &Context) -> String { pub(crate) fn audio(context: &Context) -> String {
translated(context, StockMessage::Audio).await translated(context, StockMessage::Audio)
} }
/// Stock string: `File`. /// Stock string: `File`.
pub(crate) async fn file(context: &Context) -> String { pub(crate) fn file(context: &Context) -> String {
translated(context, StockMessage::File).await translated(context, StockMessage::File)
} }
/// Stock string: `Group name changed from "%1$s" to "%2$s".`. /// Stock string: `Group name changed from "%1$s" to "%2$s".`.
@@ -594,12 +592,10 @@ pub(crate) async fn msg_grp_name(
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouChangedGrpName) translated(context, StockMessage::MsgYouChangedGrpName)
.await
.replace1(from_group) .replace1(from_group)
.replace2(to_group) .replace2(to_group)
} else { } else {
translated(context, StockMessage::MsgGrpNameChangedBy) translated(context, StockMessage::MsgGrpNameChangedBy)
.await
.replace1(from_group) .replace1(from_group)
.replace2(to_group) .replace2(to_group)
.replace3(&by_contact.get_stock_name(context).await) .replace3(&by_contact.get_stock_name(context).await)
@@ -608,10 +604,9 @@ pub(crate) async fn msg_grp_name(
pub(crate) async fn msg_grp_img_changed(context: &Context, by_contact: ContactId) -> String { pub(crate) async fn msg_grp_img_changed(context: &Context, by_contact: ContactId) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouChangedGrpImg).await translated(context, StockMessage::MsgYouChangedGrpImg)
} else { } else {
translated(context, StockMessage::MsgGrpImgChangedBy) translated(context, StockMessage::MsgGrpImgChangedBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
@@ -621,10 +616,9 @@ pub(crate) async fn msg_chat_description_changed(
by_contact: ContactId, by_contact: ContactId,
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouChangedDescription).await translated(context, StockMessage::MsgYouChangedDescription)
} else { } else {
translated(context, StockMessage::MsgChatDescriptionChangedBy) translated(context, StockMessage::MsgChatDescriptionChangedBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
@@ -640,16 +634,11 @@ pub(crate) async fn msg_add_member_local(
) -> String { ) -> String {
let whom = added_member.get_stock_name(context).await; let whom = added_member.get_stock_name(context).await;
if by_contact == ContactId::UNDEFINED { if by_contact == ContactId::UNDEFINED {
translated(context, StockMessage::MsgAddMember) translated(context, StockMessage::MsgAddMember).replace1(&whom)
.await
.replace1(&whom)
} else if by_contact == ContactId::SELF { } else if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouAddMember) translated(context, StockMessage::MsgYouAddMember).replace1(&whom)
.await
.replace1(&whom)
} else { } else {
translated(context, StockMessage::MsgAddMemberBy) translated(context, StockMessage::MsgAddMemberBy)
.await
.replace1(&whom) .replace1(&whom)
.replace2(&by_contact.get_stock_name(context).await) .replace2(&by_contact.get_stock_name(context).await)
} }
@@ -666,16 +655,11 @@ pub(crate) async fn msg_del_member_local(
) -> String { ) -> String {
let whom = removed_member.get_stock_name(context).await; let whom = removed_member.get_stock_name(context).await;
if by_contact == ContactId::UNDEFINED { if by_contact == ContactId::UNDEFINED {
translated(context, StockMessage::MsgDelMember) translated(context, StockMessage::MsgDelMember).replace1(&whom)
.await
.replace1(&whom)
} else if by_contact == ContactId::SELF { } else if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouDelMember) translated(context, StockMessage::MsgYouDelMember).replace1(&whom)
.await
.replace1(&whom)
} else { } else {
translated(context, StockMessage::MsgDelMemberBy) translated(context, StockMessage::MsgDelMemberBy)
.await
.replace1(&whom) .replace1(&whom)
.replace2(&by_contact.get_stock_name(context).await) .replace2(&by_contact.get_stock_name(context).await)
} }
@@ -684,22 +668,21 @@ pub(crate) async fn msg_del_member_local(
/// Stock string: `You left the group.` or `Group left by %1$s.`. /// Stock string: `You left the group.` or `Group left by %1$s.`.
pub(crate) async fn msg_group_left_local(context: &Context, by_contact: ContactId) -> String { pub(crate) async fn msg_group_left_local(context: &Context, by_contact: ContactId) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouLeftGroup).await translated(context, StockMessage::MsgYouLeftGroup)
} else { } else {
translated(context, StockMessage::MsgGroupLeftBy) translated(context, StockMessage::MsgGroupLeftBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
/// Stock string: `You left the channel.` /// Stock string: `You left the channel.`
pub(crate) async fn msg_you_left_broadcast(context: &Context) -> String { pub(crate) fn msg_you_left_broadcast(context: &Context) -> String {
translated(context, StockMessage::MsgYouLeftBroadcast).await translated(context, StockMessage::MsgYouLeftBroadcast)
} }
/// Stock string: `You joined the channel.` /// Stock string: `You joined the channel.`
pub(crate) async fn msg_you_joined_broadcast(context: &Context) -> String { pub(crate) fn msg_you_joined_broadcast(context: &Context) -> String {
translated(context, StockMessage::MsgYouJoinedBroadcast).await translated(context, StockMessage::MsgYouJoinedBroadcast)
} }
/// Stock string: `%1$s invited you to join this channel. Waiting for the device of %2$s to reply…`. /// Stock string: `%1$s invited you to join this channel. Waiting for the device of %2$s to reply…`.
@@ -709,7 +692,6 @@ pub(crate) async fn secure_join_broadcast_started(
) -> String { ) -> String {
if let Ok(contact) = Contact::get_by_id(context, inviter_contact_id).await { if let Ok(contact) = Contact::get_by_id(context, inviter_contact_id).await {
translated(context, StockMessage::SecureJoinBroadcastStarted) translated(context, StockMessage::SecureJoinBroadcastStarted)
.await
.replace1(contact.get_display_name()) .replace1(contact.get_display_name())
.replace2(contact.get_display_name()) .replace2(contact.get_display_name())
} else { } else {
@@ -718,16 +700,15 @@ pub(crate) async fn secure_join_broadcast_started(
} }
/// Stock string: `Channel name changed from "1%s" to "2$s".` /// Stock string: `Channel name changed from "1%s" to "2$s".`
pub(crate) async fn msg_broadcast_name_changed(context: &Context, from: &str, to: &str) -> String { pub(crate) fn msg_broadcast_name_changed(context: &Context, from: &str, to: &str) -> String {
translated(context, StockMessage::MsgBroadcastNameChanged) translated(context, StockMessage::MsgBroadcastNameChanged)
.await
.replace1(from) .replace1(from)
.replace2(to) .replace2(to)
} }
/// Stock string `Channel image changed.` /// Stock string `Channel image changed.`
pub(crate) async fn msg_broadcast_img_changed(context: &Context) -> String { pub(crate) fn msg_broadcast_img_changed(context: &Context) -> String {
translated(context, StockMessage::MsgBroadcastImgChanged).await translated(context, StockMessage::MsgBroadcastImgChanged)
} }
/// Stock string: `You reacted %1$s to "%2$s"` or `%1$s reacted %2$s to "%3$s"`. /// Stock string: `You reacted %1$s to "%2$s"` or `%1$s reacted %2$s to "%3$s"`.
@@ -739,12 +720,10 @@ pub(crate) async fn msg_reacted(
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouReacted) translated(context, StockMessage::MsgYouReacted)
.await
.replace1(reaction) .replace1(reaction)
.replace2(summary) .replace2(summary)
} else { } else {
translated(context, StockMessage::MsgReactedBy) translated(context, StockMessage::MsgReactedBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
.replace2(reaction) .replace2(reaction)
.replace3(summary) .replace3(summary)
@@ -752,27 +731,26 @@ pub(crate) async fn msg_reacted(
} }
/// Stock string: `GIF`. /// Stock string: `GIF`.
pub(crate) async fn gif(context: &Context) -> String { pub(crate) fn gif(context: &Context) -> String {
translated(context, StockMessage::Gif).await translated(context, StockMessage::Gif)
} }
/// Stock string: `No encryption.`. /// Stock string: `No encryption.`.
pub(crate) async fn encr_none(context: &Context) -> String { pub(crate) fn encr_none(context: &Context) -> String {
translated(context, StockMessage::EncrNone).await translated(context, StockMessage::EncrNone)
} }
/// Stock string: `Fingerprints`. /// Stock string: `Fingerprints`.
pub(crate) async fn finger_prints(context: &Context) -> String { pub(crate) fn finger_prints(context: &Context) -> String {
translated(context, StockMessage::FingerPrints).await translated(context, StockMessage::FingerPrints)
} }
/// Stock string: `Group image deleted.`. /// Stock string: `Group image deleted.`.
pub(crate) async fn msg_grp_img_deleted(context: &Context, by_contact: ContactId) -> String { pub(crate) async fn msg_grp_img_deleted(context: &Context, by_contact: ContactId) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouDeletedGrpImg).await translated(context, StockMessage::MsgYouDeletedGrpImg)
} else { } else {
translated(context, StockMessage::MsgGrpImgDeletedBy) translated(context, StockMessage::MsgGrpImgDeletedBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
@@ -784,7 +762,6 @@ pub(crate) async fn secure_join_started(
) -> String { ) -> String {
if let Ok(contact) = Contact::get_by_id(context, inviter_contact_id).await { if let Ok(contact) = Contact::get_by_id(context, inviter_contact_id).await {
translated(context, StockMessage::SecureJoinStarted) translated(context, StockMessage::SecureJoinStarted)
.await
.replace1(contact.get_display_name()) .replace1(contact.get_display_name())
.replace2(contact.get_display_name()) .replace2(contact.get_display_name())
} else { } else {
@@ -795,22 +772,21 @@ pub(crate) async fn secure_join_started(
/// Stock string: `%1$s replied, waiting for being added to the group…`. /// Stock string: `%1$s replied, waiting for being added to the group…`.
pub(crate) async fn secure_join_replies(context: &Context, contact_id: ContactId) -> String { pub(crate) async fn secure_join_replies(context: &Context, contact_id: ContactId) -> String {
translated(context, StockMessage::SecureJoinReplies) translated(context, StockMessage::SecureJoinReplies)
.await
.replace1(&contact_id.get_stock_name(context).await) .replace1(&contact_id.get_stock_name(context).await)
} }
/// Stock string: `Establishing connection, please wait…`. /// Stock string: `Establishing connection, please wait…`.
pub(crate) async fn securejoin_wait(context: &Context) -> String { pub(crate) fn securejoin_wait(context: &Context) -> String {
translated(context, StockMessage::SecurejoinWait).await translated(context, StockMessage::SecurejoinWait)
} }
/// Stock string: `❤️ Seems you're enjoying Delta Chat!`… /// Stock string: `❤️ Seems you're enjoying Delta Chat!`…
pub(crate) async fn donation_request(context: &Context) -> String { pub(crate) fn donation_request(context: &Context) -> String {
translated(context, StockMessage::DonationRequest).await translated(context, StockMessage::DonationRequest)
} }
/// Stock string: `Outgoing video call` or `Outgoing audio call`. /// Stock string: `Outgoing video call` or `Outgoing audio call`.
pub(crate) async fn outgoing_call(context: &Context, has_video: bool) -> String { pub(crate) fn outgoing_call(context: &Context, has_video: bool) -> String {
translated( translated(
context, context,
if has_video { if has_video {
@@ -819,11 +795,10 @@ pub(crate) async fn outgoing_call(context: &Context, has_video: bool) -> String
StockMessage::OutgoingAudioCall StockMessage::OutgoingAudioCall
}, },
) )
.await
} }
/// Stock string: `Incoming video call` or `Incoming audio call`. /// Stock string: `Incoming video call` or `Incoming audio call`.
pub(crate) async fn incoming_call(context: &Context, has_video: bool) -> String { pub(crate) fn incoming_call(context: &Context, has_video: bool) -> String {
translated( translated(
context, context,
if has_video { if has_video {
@@ -832,26 +807,25 @@ pub(crate) async fn incoming_call(context: &Context, has_video: bool) -> String
StockMessage::IncomingAudioCall StockMessage::IncomingAudioCall
}, },
) )
.await
} }
/// Stock string: `Declined call`. /// Stock string: `Declined call`.
pub(crate) async fn declined_call(context: &Context) -> String { pub(crate) fn declined_call(context: &Context) -> String {
translated(context, StockMessage::DeclinedCall).await translated(context, StockMessage::DeclinedCall)
} }
/// Stock string: `Canceled call`. /// Stock string: `Canceled call`.
pub(crate) async fn canceled_call(context: &Context) -> String { pub(crate) fn canceled_call(context: &Context) -> String {
translated(context, StockMessage::CanceledCall).await translated(context, StockMessage::CanceledCall)
} }
/// Stock string: `Missed call`. /// Stock string: `Missed call`.
pub(crate) async fn missed_call(context: &Context) -> String { pub(crate) fn missed_call(context: &Context) -> String {
translated(context, StockMessage::MissedCall).await translated(context, StockMessage::MissedCall)
} }
/// Stock string: `Scan to chat with %1$s`. /// Stock string: `Scan to chat with %1$s`.
pub(crate) async fn setup_contact_qr_description( pub(crate) fn setup_contact_qr_description(
context: &Context, context: &Context,
display_name: &str, display_name: &str,
addr: &str, addr: &str,
@@ -861,113 +835,100 @@ pub(crate) async fn setup_contact_qr_description(
} else { } else {
display_name.to_owned() display_name.to_owned()
}; };
translated(context, StockMessage::SetupContactQRDescription) translated(context, StockMessage::SetupContactQRDescription).replace1(&name)
.await
.replace1(&name)
} }
/// Stock string: `Scan to join group %1$s`. /// Stock string: `Scan to join group %1$s`.
pub(crate) async fn secure_join_group_qr_description(context: &Context, chat: &Chat) -> String { pub(crate) fn secure_join_group_qr_description(context: &Context, chat: &Chat) -> String {
translated(context, StockMessage::SecureJoinGroupQRDescription) translated(context, StockMessage::SecureJoinGroupQRDescription).replace1(chat.get_name())
.await
.replace1(chat.get_name())
} }
/// Stock string: `Scan to join channel %1$s`. /// Stock string: `Scan to join channel %1$s`.
pub(crate) async fn secure_join_broadcast_qr_description(context: &Context, chat: &Chat) -> String { pub(crate) fn secure_join_broadcast_qr_description(context: &Context, chat: &Chat) -> String {
translated(context, StockMessage::SecureJoinBrodcastQRDescription) translated(context, StockMessage::SecureJoinBrodcastQRDescription).replace1(chat.get_name())
.await
.replace1(chat.get_name())
} }
/// Stock string: `%1$s verified.`. /// Stock string: `%1$s verified.`.
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) async fn contact_verified(context: &Context, contact: &Contact) -> String { pub(crate) fn contact_verified(context: &Context, contact: &Contact) -> String {
let addr = contact.get_display_name(); let addr = contact.get_display_name();
translated(context, StockMessage::ContactVerified) translated(context, StockMessage::ContactVerified).replace1(addr)
.await
.replace1(addr)
} }
/// Stock string: `Archived chats`. /// Stock string: `Archived chats`.
pub(crate) async fn archived_chats(context: &Context) -> String { pub(crate) fn archived_chats(context: &Context) -> String {
translated(context, StockMessage::ArchivedChats).await translated(context, StockMessage::ArchivedChats)
} }
/// Stock string: `Multi Device Synchronization`. /// Stock string: `Multi Device Synchronization`.
pub(crate) async fn sync_msg_subject(context: &Context) -> String { pub(crate) fn sync_msg_subject(context: &Context) -> String {
translated(context, StockMessage::SyncMsgSubject).await translated(context, StockMessage::SyncMsgSubject)
} }
/// Stock string: `This message is used to synchronize data between your devices.`. /// Stock string: `This message is used to synchronize data between your devices.`.
pub(crate) async fn sync_msg_body(context: &Context) -> String { pub(crate) fn sync_msg_body(context: &Context) -> String {
translated(context, StockMessage::SyncMsgBody).await translated(context, StockMessage::SyncMsgBody)
} }
/// Stock string: `Cannot login as \"%1$s\". Please check...`. /// Stock string: `Cannot login as \"%1$s\". Please check...`.
pub(crate) async fn cannot_login(context: &Context, user: &str) -> String { pub(crate) fn cannot_login(context: &Context, user: &str) -> String {
translated(context, StockMessage::CannotLogin) translated(context, StockMessage::CannotLogin).replace1(user)
.await
.replace1(user)
} }
/// Stock string: `Location streaming enabled.`. /// Stock string: `Location streaming enabled.`.
pub(crate) async fn msg_location_enabled(context: &Context) -> String { pub(crate) fn msg_location_enabled(context: &Context) -> String {
translated(context, StockMessage::MsgLocationEnabled).await translated(context, StockMessage::MsgLocationEnabled)
} }
/// Stock string: `Location streaming enabled by ...`. /// Stock string: `Location streaming enabled by ...`.
pub(crate) async fn msg_location_enabled_by(context: &Context, contact: ContactId) -> String { pub(crate) async fn msg_location_enabled_by(context: &Context, contact: ContactId) -> String {
if contact == ContactId::SELF { if contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEnabledLocation).await translated(context, StockMessage::MsgYouEnabledLocation)
} else { } else {
translated(context, StockMessage::MsgLocationEnabledBy) translated(context, StockMessage::MsgLocationEnabledBy)
.await
.replace1(&contact.get_stock_name(context).await) .replace1(&contact.get_stock_name(context).await)
} }
} }
/// Stock string: `Location streaming disabled.`. /// Stock string: `Location streaming disabled.`.
pub(crate) async fn msg_location_disabled(context: &Context) -> String { pub(crate) fn msg_location_disabled(context: &Context) -> String {
translated(context, StockMessage::MsgLocationDisabled).await translated(context, StockMessage::MsgLocationDisabled)
} }
/// Stock string: `Location`. /// Stock string: `Location`.
pub(crate) async fn location(context: &Context) -> String { pub(crate) fn location(context: &Context) -> String {
translated(context, StockMessage::Location).await translated(context, StockMessage::Location)
} }
/// Stock string: `Sticker`. /// Stock string: `Sticker`.
pub(crate) async fn sticker(context: &Context) -> String { pub(crate) fn sticker(context: &Context) -> String {
translated(context, StockMessage::Sticker).await translated(context, StockMessage::Sticker)
} }
/// Stock string: `Device messages`. /// Stock string: `Device messages`.
pub(crate) async fn device_messages(context: &Context) -> String { pub(crate) fn device_messages(context: &Context) -> String {
translated(context, StockMessage::DeviceMessages).await translated(context, StockMessage::DeviceMessages)
} }
/// Stock string: `Saved messages`. /// Stock string: `Saved messages`.
pub(crate) async fn saved_messages(context: &Context) -> String { pub(crate) fn saved_messages(context: &Context) -> String {
translated(context, StockMessage::SavedMessages).await translated(context, StockMessage::SavedMessages)
} }
/// Stock string: `Messages in this chat are generated locally by...`. /// Stock string: `Messages in this chat are generated locally by...`.
pub(crate) async fn device_messages_hint(context: &Context) -> String { pub(crate) fn device_messages_hint(context: &Context) -> String {
translated(context, StockMessage::DeviceMessagesHint).await translated(context, StockMessage::DeviceMessagesHint)
} }
/// Stock string: `Welcome to Delta Chat! ...`. /// Stock string: `Welcome to Delta Chat! ...`.
pub(crate) async fn welcome_message(context: &Context) -> String { pub(crate) fn welcome_message(context: &Context) -> String {
translated(context, StockMessage::WelcomeMessage).await translated(context, StockMessage::WelcomeMessage)
} }
/// Stock string: `Message from %1$s`. /// Stock string: `Message from %1$s`.
// TODO: This can compute `self_name` itself instead of asking the caller to do this. // TODO: This can compute `self_name` itself instead of asking the caller to do this.
pub(crate) async fn subject_for_new_contact(context: &Context, self_name: &str) -> String { pub(crate) fn subject_for_new_contact(context: &Context, self_name: &str) -> String {
translated(context, StockMessage::SubjectForNewContact) translated(context, StockMessage::SubjectForNewContact).replace1(self_name)
.await
.replace1(self_name)
} }
/// Stock string: `Message deletion timer is disabled.`. /// Stock string: `Message deletion timer is disabled.`.
@@ -976,10 +937,9 @@ pub(crate) async fn msg_ephemeral_timer_disabled(
by_contact: ContactId, by_contact: ContactId,
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouDisabledEphemeralTimer).await translated(context, StockMessage::MsgYouDisabledEphemeralTimer)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerDisabledBy) translated(context, StockMessage::MsgEphemeralTimerDisabledBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
@@ -991,12 +951,9 @@ pub(crate) async fn msg_ephemeral_timer_enabled(
by_contact: ContactId, by_contact: ContactId,
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEnabledEphemeralTimer) translated(context, StockMessage::MsgYouEnabledEphemeralTimer).replace1(timer)
.await
.replace1(timer)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerEnabledBy) translated(context, StockMessage::MsgEphemeralTimerEnabledBy)
.await
.replace1(timer) .replace1(timer)
.replace2(&by_contact.get_stock_name(context).await) .replace2(&by_contact.get_stock_name(context).await)
} }
@@ -1005,10 +962,9 @@ pub(crate) async fn msg_ephemeral_timer_enabled(
/// Stock string: `Message deletion timer is set to 1 hour.`. /// Stock string: `Message deletion timer is set to 1 hour.`.
pub(crate) async fn msg_ephemeral_timer_hour(context: &Context, by_contact: ContactId) -> String { pub(crate) async fn msg_ephemeral_timer_hour(context: &Context, by_contact: ContactId) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEphemeralTimerHour).await translated(context, StockMessage::MsgYouEphemeralTimerHour)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerHourBy) translated(context, StockMessage::MsgEphemeralTimerHourBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
@@ -1016,10 +972,9 @@ pub(crate) async fn msg_ephemeral_timer_hour(context: &Context, by_contact: Cont
/// Stock string: `Message deletion timer is set to 1 day.`. /// Stock string: `Message deletion timer is set to 1 day.`.
pub(crate) async fn msg_ephemeral_timer_day(context: &Context, by_contact: ContactId) -> String { pub(crate) async fn msg_ephemeral_timer_day(context: &Context, by_contact: ContactId) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEphemeralTimerDay).await translated(context, StockMessage::MsgYouEphemeralTimerDay)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerDayBy) translated(context, StockMessage::MsgEphemeralTimerDayBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
@@ -1027,10 +982,9 @@ pub(crate) async fn msg_ephemeral_timer_day(context: &Context, by_contact: Conta
/// Stock string: `Message deletion timer is set to 1 week.`. /// Stock string: `Message deletion timer is set to 1 week.`.
pub(crate) async fn msg_ephemeral_timer_week(context: &Context, by_contact: ContactId) -> String { pub(crate) async fn msg_ephemeral_timer_week(context: &Context, by_contact: ContactId) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEphemeralTimerWeek).await translated(context, StockMessage::MsgYouEphemeralTimerWeek)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerWeekBy) translated(context, StockMessage::MsgEphemeralTimerWeekBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
@@ -1038,57 +992,52 @@ pub(crate) async fn msg_ephemeral_timer_week(context: &Context, by_contact: Cont
/// Stock string: `Message deletion timer is set to 1 year.`. /// Stock string: `Message deletion timer is set to 1 year.`.
pub(crate) async fn msg_ephemeral_timer_year(context: &Context, by_contact: ContactId) -> String { pub(crate) async fn msg_ephemeral_timer_year(context: &Context, by_contact: ContactId) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEphemeralTimerYear).await translated(context, StockMessage::MsgYouEphemeralTimerYear)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerYearBy) translated(context, StockMessage::MsgEphemeralTimerYearBy)
.await
.replace1(&by_contact.get_stock_name(context).await) .replace1(&by_contact.get_stock_name(context).await)
} }
} }
/// Stock string: `Error:\n\n“%1$s”`. /// Stock string: `Error:\n\n“%1$s”`.
pub(crate) async fn configuration_failed(context: &Context, details: &str) -> String { pub(crate) fn configuration_failed(context: &Context, details: &str) -> String {
translated(context, StockMessage::ConfigurationFailed) translated(context, StockMessage::ConfigurationFailed).replace1(details)
.await
.replace1(details)
} }
/// Stock string: `⚠️ Date or time of your device seem to be inaccurate (%1$s)...`. /// Stock string: `⚠️ Date or time of your device seem to be inaccurate (%1$s)...`.
// TODO: This could compute now itself. // TODO: This could compute now itself.
pub(crate) async fn bad_time_msg_body(context: &Context, now: &str) -> String { pub(crate) fn bad_time_msg_body(context: &Context, now: &str) -> String {
translated(context, StockMessage::BadTimeMsgBody) translated(context, StockMessage::BadTimeMsgBody).replace1(now)
.await
.replace1(now)
} }
/// Stock string: `⚠️ Your Delta Chat version might be outdated...`. /// Stock string: `⚠️ Your Delta Chat version might be outdated...`.
pub(crate) async fn update_reminder_msg_body(context: &Context) -> String { pub(crate) fn update_reminder_msg_body(context: &Context) -> String {
translated(context, StockMessage::UpdateReminderMsgBody).await translated(context, StockMessage::UpdateReminderMsgBody)
} }
/// Stock string: `Could not find your mail server...`. /// Stock string: `Could not find your mail server...`.
pub(crate) async fn error_no_network(context: &Context) -> String { pub(crate) fn error_no_network(context: &Context) -> String {
translated(context, StockMessage::ErrorNoNetwork).await translated(context, StockMessage::ErrorNoNetwork)
} }
/// Stock string: `Messages are end-to-end encrypted.`, used in info-messages, UI may add smth. as `Tap to learn more.` /// Stock string: `Messages are end-to-end encrypted.`, used in info-messages, UI may add smth. as `Tap to learn more.`
pub(crate) async fn messages_e2ee_info_msg(context: &Context) -> String { pub(crate) fn messages_e2ee_info_msg(context: &Context) -> String {
translated(context, StockMessage::ChatProtectionEnabled).await translated(context, StockMessage::ChatProtectionEnabled)
} }
/// Stock string: `Messages are end-to-end encrypted.` /// Stock string: `Messages are end-to-end encrypted.`
pub(crate) async fn messages_are_e2ee(context: &Context) -> String { pub(crate) fn messages_are_e2ee(context: &Context) -> String {
translated(context, StockMessage::MessagesAreE2ee).await translated(context, StockMessage::MessagesAreE2ee)
} }
/// Stock string: `Reply`. /// Stock string: `Reply`.
pub(crate) async fn reply_noun(context: &Context) -> String { pub(crate) fn reply_noun(context: &Context) -> String {
translated(context, StockMessage::ReplyNoun).await translated(context, StockMessage::ReplyNoun)
} }
/// Stock string: `You deleted the \"Saved messages\" chat...`. /// Stock string: `You deleted the \"Saved messages\" chat...`.
pub(crate) async fn self_deleted_msg_body(context: &Context) -> String { pub(crate) fn self_deleted_msg_body(context: &Context) -> String {
translated(context, StockMessage::SelfDeletedMsgBody).await translated(context, StockMessage::SelfDeletedMsgBody)
} }
/// Stock string: `Message deletion timer is set to %1$s minutes.`. /// Stock string: `Message deletion timer is set to %1$s minutes.`.
@@ -1098,12 +1047,9 @@ pub(crate) async fn msg_ephemeral_timer_minutes(
by_contact: ContactId, by_contact: ContactId,
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEphemeralTimerMinutes) translated(context, StockMessage::MsgYouEphemeralTimerMinutes).replace1(minutes)
.await
.replace1(minutes)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerMinutesBy) translated(context, StockMessage::MsgEphemeralTimerMinutesBy)
.await
.replace1(minutes) .replace1(minutes)
.replace2(&by_contact.get_stock_name(context).await) .replace2(&by_contact.get_stock_name(context).await)
} }
@@ -1116,12 +1062,9 @@ pub(crate) async fn msg_ephemeral_timer_hours(
by_contact: ContactId, by_contact: ContactId,
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEphemeralTimerHours) translated(context, StockMessage::MsgYouEphemeralTimerHours).replace1(hours)
.await
.replace1(hours)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerHoursBy) translated(context, StockMessage::MsgEphemeralTimerHoursBy)
.await
.replace1(hours) .replace1(hours)
.replace2(&by_contact.get_stock_name(context).await) .replace2(&by_contact.get_stock_name(context).await)
} }
@@ -1134,12 +1077,9 @@ pub(crate) async fn msg_ephemeral_timer_days(
by_contact: ContactId, by_contact: ContactId,
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEphemeralTimerDays) translated(context, StockMessage::MsgYouEphemeralTimerDays).replace1(days)
.await
.replace1(days)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerDaysBy) translated(context, StockMessage::MsgEphemeralTimerDaysBy)
.await
.replace1(days) .replace1(days)
.replace2(&by_contact.get_stock_name(context).await) .replace2(&by_contact.get_stock_name(context).await)
} }
@@ -1152,112 +1092,103 @@ pub(crate) async fn msg_ephemeral_timer_weeks(
by_contact: ContactId, by_contact: ContactId,
) -> String { ) -> String {
if by_contact == ContactId::SELF { if by_contact == ContactId::SELF {
translated(context, StockMessage::MsgYouEphemeralTimerWeeks) translated(context, StockMessage::MsgYouEphemeralTimerWeeks).replace1(weeks)
.await
.replace1(weeks)
} else { } else {
translated(context, StockMessage::MsgEphemeralTimerWeeksBy) translated(context, StockMessage::MsgEphemeralTimerWeeksBy)
.await
.replace1(weeks) .replace1(weeks)
.replace2(&by_contact.get_stock_name(context).await) .replace2(&by_contact.get_stock_name(context).await)
} }
} }
/// Stock string: `Forwarded`. /// Stock string: `Forwarded`.
pub(crate) async fn forwarded(context: &Context) -> String { pub(crate) fn forwarded(context: &Context) -> String {
translated(context, StockMessage::Forwarded).await translated(context, StockMessage::Forwarded)
} }
/// Stock string: `⚠️ Your provider's storage is about to exceed...`. /// Stock string: `⚠️ Your provider's storage is about to exceed...`.
pub(crate) async fn quota_exceeding(context: &Context, highest_usage: u64) -> String { pub(crate) fn quota_exceeding(context: &Context, highest_usage: u64) -> String {
translated(context, StockMessage::QuotaExceedingMsgBody) translated(context, StockMessage::QuotaExceedingMsgBody)
.await
.replace1(&format!("{highest_usage}")) .replace1(&format!("{highest_usage}"))
.replace("%%", "%") .replace("%%", "%")
} }
/// Stock string: `Incoming Messages`. /// Stock string: `Incoming Messages`.
pub(crate) async fn incoming_messages(context: &Context) -> String { pub(crate) fn incoming_messages(context: &Context) -> String {
translated(context, StockMessage::IncomingMessages).await translated(context, StockMessage::IncomingMessages)
} }
/// Stock string: `Outgoing Messages`. /// Stock string: `Outgoing Messages`.
pub(crate) async fn outgoing_messages(context: &Context) -> String { pub(crate) fn outgoing_messages(context: &Context) -> String {
translated(context, StockMessage::OutgoingMessages).await translated(context, StockMessage::OutgoingMessages)
} }
/// Stock string: `Not connected`. /// Stock string: `Not connected`.
pub(crate) async fn not_connected(context: &Context) -> String { pub(crate) fn not_connected(context: &Context) -> String {
translated(context, StockMessage::NotConnected).await translated(context, StockMessage::NotConnected)
} }
/// Stock string: `Connected`. /// Stock string: `Connected`.
pub(crate) async fn connected(context: &Context) -> String { pub(crate) fn connected(context: &Context) -> String {
translated(context, StockMessage::Connected).await translated(context, StockMessage::Connected)
} }
/// Stock string: `Connecting…`. /// Stock string: `Connecting…`.
pub(crate) async fn connecting(context: &Context) -> String { pub(crate) fn connecting(context: &Context) -> String {
translated(context, StockMessage::Connecting).await translated(context, StockMessage::Connecting)
} }
/// Stock string: `Updating…`. /// Stock string: `Updating…`.
pub(crate) async fn updating(context: &Context) -> String { pub(crate) fn updating(context: &Context) -> String {
translated(context, StockMessage::Updating).await translated(context, StockMessage::Updating)
} }
/// Stock string: `Sending…`. /// Stock string: `Sending…`.
pub(crate) async fn sending(context: &Context) -> String { pub(crate) fn sending(context: &Context) -> String {
translated(context, StockMessage::Sending).await translated(context, StockMessage::Sending)
} }
/// Stock string: `Your last message was sent successfully.`. /// Stock string: `Your last message was sent successfully.`.
pub(crate) async fn last_msg_sent_successfully(context: &Context) -> String { pub(crate) fn last_msg_sent_successfully(context: &Context) -> String {
translated(context, StockMessage::LastMsgSentSuccessfully).await translated(context, StockMessage::LastMsgSentSuccessfully)
} }
/// Stock string: `Error: %1$s…`. /// Stock string: `Error: %1$s…`.
/// `%1$s` will be replaced by a possibly more detailed, typically english, error description. /// `%1$s` will be replaced by a possibly more detailed, typically english, error description.
pub(crate) async fn error(context: &Context, error: &str) -> String { pub(crate) fn error(context: &Context, error: &str) -> String {
translated(context, StockMessage::Error) translated(context, StockMessage::Error).replace1(error)
.await
.replace1(error)
} }
/// Stock string: `Not supported by your provider.`. /// Stock string: `Not supported by your provider.`.
pub(crate) async fn not_supported_by_provider(context: &Context) -> String { pub(crate) fn not_supported_by_provider(context: &Context) -> String {
translated(context, StockMessage::NotSupportedByProvider).await translated(context, StockMessage::NotSupportedByProvider)
} }
/// Stock string: `Messages`. /// Stock string: `Messages`.
/// Used as a subtitle in quota context; can be plural always. /// Used as a subtitle in quota context; can be plural always.
pub(crate) async fn messages(context: &Context) -> String { pub(crate) fn messages(context: &Context) -> String {
translated(context, StockMessage::Messages).await translated(context, StockMessage::Messages)
} }
/// Stock string: `%1$s of %2$s used`. /// Stock string: `%1$s of %2$s used`.
pub(crate) async fn part_of_total_used(context: &Context, part: &str, total: &str) -> String { pub(crate) fn part_of_total_used(context: &Context, part: &str, total: &str) -> String {
translated(context, StockMessage::PartOfTotallUsed) translated(context, StockMessage::PartOfTotallUsed)
.await
.replace1(part) .replace1(part)
.replace2(total) .replace2(total)
} }
/// Stock string: `⚠️ Your email provider %1$s requires end-to-end encryption which is not setup yet. Tap to learn more.`. /// Stock string: `⚠️ Your email provider %1$s requires end-to-end encryption which is not setup yet. Tap to learn more.`.
pub(crate) async fn unencrypted_email(context: &Context, provider: &str) -> String { pub(crate) async fn unencrypted_email(context: &Context, provider: &str) -> String {
translated(context, StockMessage::InvalidUnencryptedMail) translated(context, StockMessage::InvalidUnencryptedMail).replace1(provider)
.await
.replace1(provider)
} }
/// Stock string: `The attachment contains anonymous usage statistics, which helps us improve Delta Chat. Thank you!` /// Stock string: `The attachment contains anonymous usage statistics, which helps us improve Delta Chat. Thank you!`
pub(crate) async fn stats_msg_body(context: &Context) -> String { pub(crate) fn stats_msg_body(context: &Context) -> String {
translated(context, StockMessage::StatsMsgBody).await translated(context, StockMessage::StatsMsgBody)
} }
/// Stock string: `Others will only see this group after you sent a first message.`. /// Stock string: `Others will only see this group after you sent a first message.`.
pub(crate) async fn new_group_send_first_message(context: &Context) -> String { pub(crate) fn new_group_send_first_message(context: &Context) -> String {
translated(context, StockMessage::NewGroupSendFirstMessage).await translated(context, StockMessage::NewGroupSendFirstMessage)
} }
/// Text to put in the [`Qr::Backup2`] rendered SVG image. /// Text to put in the [`Qr::Backup2`] rendered SVG image.
@@ -1272,46 +1203,44 @@ pub(crate) async fn backup_transfer_qr(context: &Context) -> Result<String> {
} else { } else {
context.get_primary_self_addr().await? context.get_primary_self_addr().await?
}; };
Ok(translated(context, StockMessage::BackupTransferQr) Ok(translated(context, StockMessage::BackupTransferQr).replace1(&name))
.await
.replace1(&name))
} }
pub(crate) async fn backup_transfer_msg_body(context: &Context) -> String { pub(crate) fn backup_transfer_msg_body(context: &Context) -> String {
translated(context, StockMessage::BackupTransferMsgBody).await translated(context, StockMessage::BackupTransferMsgBody)
} }
/// Stock string: `Proxy Enabled`. /// Stock string: `Proxy Enabled`.
pub(crate) async fn proxy_enabled(context: &Context) -> String { pub(crate) fn proxy_enabled(context: &Context) -> String {
translated(context, StockMessage::ProxyEnabled).await translated(context, StockMessage::ProxyEnabled)
} }
/// Stock string: `You are using a proxy. If you're having trouble connecting, try a different proxy.`. /// Stock string: `You are using a proxy. If you're having trouble connecting, try a different proxy.`.
pub(crate) async fn proxy_description(context: &Context) -> String { pub(crate) fn proxy_description(context: &Context) -> String {
translated(context, StockMessage::ProxyEnabledDescription).await translated(context, StockMessage::ProxyEnabledDescription)
} }
/// Stock string: `Messages in this chat use classic email and are not encrypted.`. /// Stock string: `Messages in this chat use classic email and are not encrypted.`.
pub(crate) async fn chat_unencrypted_explanation(context: &Context) -> String { pub(crate) fn chat_unencrypted_explanation(context: &Context) -> String {
translated(context, StockMessage::ChatUnencryptedExplanation).await translated(context, StockMessage::ChatUnencryptedExplanation)
} }
/// Stock string: `You are using the legacy option "Move automatically to DeltaChat Folder`… /// Stock string: `You are using the legacy option "Move automatically to DeltaChat Folder`…
pub(crate) async fn mvbox_move_deprecation(context: &Context) -> String { pub(crate) fn mvbox_move_deprecation(context: &Context) -> String {
translated(context, StockMessage::MvboxMoveDeprecation).await translated(context, StockMessage::MvboxMoveDeprecation)
} }
impl Viewtype { impl Viewtype {
/// returns Localized name for message viewtype /// returns Localized name for message viewtype
pub async fn to_locale_string(&self, context: &Context) -> String { pub fn to_locale_string(&self, context: &Context) -> String {
match self { match self {
Viewtype::Image => image(context).await, Viewtype::Image => image(context),
Viewtype::Gif => gif(context).await, Viewtype::Gif => gif(context),
Viewtype::Sticker => sticker(context).await, Viewtype::Sticker => sticker(context),
Viewtype::Audio => audio(context).await, Viewtype::Audio => audio(context),
Viewtype::Voice => voice_message(context).await, Viewtype::Voice => voice_message(context),
Viewtype::Video => video(context).await, Viewtype::Video => video(context),
Viewtype::File => file(context).await, Viewtype::File => file(context),
Viewtype::Webxdc => "Mini App".to_owned(), Viewtype::Webxdc => "Mini App".to_owned(),
Viewtype::Vcard => "👤".to_string(), Viewtype::Vcard => "👤".to_string(),
// The following shouldn't normally be shown to users, so translations aren't needed. // The following shouldn't normally be shown to users, so translations aren't needed.
@@ -1323,10 +1252,9 @@ impl Viewtype {
impl Context { impl Context {
/// Set the stock string for the [StockMessage]. /// Set the stock string for the [StockMessage].
/// ///
pub async fn set_stock_translation(&self, id: StockMessage, stockstring: String) -> Result<()> { pub fn set_stock_translation(&self, id: StockMessage, stockstring: String) -> Result<()> {
self.translated_stockstrings self.translated_stockstrings
.set_stock_translation(id, stockstring) .set_stock_translation(id, stockstring)?;
.await?;
Ok(()) Ok(())
} }
@@ -1353,7 +1281,7 @@ impl Context {
msg.param.set(Param::Filename, "welcome-image.jpg"); msg.param.set(Param::Filename, "welcome-image.jpg");
chat::add_device_msg(self, Some("core-welcome-image"), Some(&mut msg)).await?; chat::add_device_msg(self, Some("core-welcome-image"), Some(&mut msg)).await?;
let mut msg = Message::new_text(welcome_message(self).await); let mut msg = Message::new_text(welcome_message(self));
chat::add_device_msg(self, Some("core-welcome"), Some(&mut msg)).await?; chat::add_device_msg(self, Some("core-welcome"), Some(&mut msg)).await?;
Ok(()) Ok(())
} }
@@ -1362,10 +1290,8 @@ impl Context {
impl Accounts { impl Accounts {
/// Set the stock string for the [StockMessage]. /// Set the stock string for the [StockMessage].
/// ///
pub async fn set_stock_translation(&self, id: StockMessage, stockstring: String) -> Result<()> { pub fn set_stock_translation(&self, id: StockMessage, stockstring: String) -> Result<()> {
self.stockstrings self.stockstrings.set_stock_translation(id, stockstring)?;
.set_stock_translation(id, stockstring)
.await?;
Ok(()) Ok(())
} }
} }

View File

@@ -20,9 +20,8 @@ fn test_fallback() {
async fn test_set_stock_translation() { async fn test_set_stock_translation() {
let t = TestContext::new().await; let t = TestContext::new().await;
t.set_stock_translation(StockMessage::NoMessages, "xyz".to_string()) t.set_stock_translation(StockMessage::NoMessages, "xyz".to_string())
.await
.unwrap(); .unwrap();
assert_eq!(no_messages(&t).await, "xyz") assert_eq!(no_messages(&t), "xyz")
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -31,13 +30,11 @@ async fn test_set_stock_translation_wrong_replacements() {
assert!( assert!(
t.ctx t.ctx
.set_stock_translation(StockMessage::NoMessages, "xyz %1$s ".to_string()) .set_stock_translation(StockMessage::NoMessages, "xyz %1$s ".to_string())
.await
.is_err() .is_err()
); );
assert!( assert!(
t.ctx t.ctx
.set_stock_translation(StockMessage::NoMessages, "xyz %2$s ".to_string()) .set_stock_translation(StockMessage::NoMessages, "xyz %2$s ".to_string())
.await
.is_err() .is_err()
); );
} }
@@ -45,7 +42,7 @@ async fn test_set_stock_translation_wrong_replacements() {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_stock_str() { async fn test_stock_str() {
let t = TestContext::new().await; let t = TestContext::new().await;
assert_eq!(no_messages(&t).await, "No messages."); assert_eq!(no_messages(&t), "No messages.");
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -56,17 +53,14 @@ async fn test_stock_string_repl_str() {
.unwrap(); .unwrap();
let contact = Contact::get_by_id(&t.ctx, contact_id).await.unwrap(); let contact = Contact::get_by_id(&t.ctx, contact_id).await.unwrap();
// uses %1$s substitution // uses %1$s substitution
assert_eq!(contact_verified(&t, &contact).await, "Someone verified."); assert_eq!(contact_verified(&t, &contact), "Someone verified.");
// We have no string using %1$d to test... // We have no string using %1$d to test...
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_stock_system_msg_simple() { async fn test_stock_system_msg_simple() {
let t = TestContext::new().await; let t = TestContext::new().await;
assert_eq!( assert_eq!(msg_location_enabled(&t), "Location streaming enabled.")
msg_location_enabled(&t).await,
"Location streaming enabled."
)
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -111,7 +105,7 @@ async fn test_stock_system_msg_add_member_by_other_with_displayname() {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_quota_exceeding_stock_str() -> Result<()> { async fn test_quota_exceeding_stock_str() -> Result<()> {
let t = TestContext::new().await; let t = TestContext::new().await;
let str = quota_exceeding(&t, 81).await; let str = quota_exceeding(&t, 81);
assert!(str.contains("81% ")); assert!(str.contains("81% "));
assert!(str.contains("100% ")); assert!(str.contains("100% "));
assert!(!str.contains("%%")); assert!(!str.contains("%%"));

View File

@@ -98,13 +98,13 @@ impl Summary {
contact: Option<&Contact>, contact: Option<&Contact>,
) -> Result<Summary> { ) -> Result<Summary> {
let prefix = if msg.state == MessageState::OutDraft { let prefix = if msg.state == MessageState::OutDraft {
Some(SummaryPrefix::Draft(stock_str::draft(context).await)) Some(SummaryPrefix::Draft(stock_str::draft(context)))
} else if msg.from_id == ContactId::SELF { } else if msg.from_id == ContactId::SELF {
if msg.is_info() || msg.viewtype == Viewtype::Call || chat.typ == Chattype::OutBroadcast if msg.is_info() || msg.viewtype == Viewtype::Call || chat.typ == Chattype::OutBroadcast
{ {
None None
} else { } else {
Some(SummaryPrefix::Me(stock_str::self_msg(context).await)) Some(SummaryPrefix::Me(stock_str::self_msg(context)))
} }
} else if chat.typ == Chattype::Group } else if chat.typ == Chattype::Group
|| chat.typ == Chattype::Mailinglist || chat.typ == Chattype::Mailinglist
@@ -124,7 +124,7 @@ impl Summary {
let mut text = msg.get_summary_text(context).await; let mut text = msg.get_summary_text(context).await;
if text.is_empty() && msg.quoted_text().is_some() { if text.is_empty() && msg.quoted_text().is_some() {
text = stock_str::reply_noun(context).await text = stock_str::reply_noun(context)
} }
let thumbnail_path = if msg.viewtype == Viewtype::Image let thumbnail_path = if msg.viewtype == Viewtype::Image
@@ -160,7 +160,7 @@ impl Message {
let summary = self.get_summary_text_without_prefix(context).await; let summary = self.get_summary_text_without_prefix(context).await;
if self.is_forwarded() { if self.is_forwarded() {
format!("{}: {}", stock_str::forwarded(context).await, summary) format!("{}: {}", stock_str::forwarded(context), summary)
} else { } else {
summary summary
} }
@@ -180,43 +180,43 @@ impl Message {
match viewtype { match viewtype {
Viewtype::Image => { Viewtype::Image => {
emoji = Some("📷"); emoji = Some("📷");
type_name = Some(stock_str::image(context).await); type_name = Some(stock_str::image(context));
type_file = None; type_file = None;
append_text = true; append_text = true;
} }
Viewtype::Gif => { Viewtype::Gif => {
emoji = None; emoji = None;
type_name = Some(stock_str::gif(context).await); type_name = Some(stock_str::gif(context));
type_file = None; type_file = None;
append_text = true; append_text = true;
} }
Viewtype::Sticker => { Viewtype::Sticker => {
emoji = None; emoji = None;
type_name = Some(stock_str::sticker(context).await); type_name = Some(stock_str::sticker(context));
type_file = None; type_file = None;
append_text = true; append_text = true;
} }
Viewtype::Video => { Viewtype::Video => {
emoji = Some("🎥"); emoji = Some("🎥");
type_name = Some(stock_str::video(context).await); type_name = Some(stock_str::video(context));
type_file = None; type_file = None;
append_text = true; append_text = true;
} }
Viewtype::Voice => { Viewtype::Voice => {
emoji = Some("🎤"); emoji = Some("🎤");
type_name = Some(stock_str::voice_message(context).await); type_name = Some(stock_str::voice_message(context));
type_file = None; type_file = None;
append_text = true; append_text = true;
} }
Viewtype::Audio => { Viewtype::Audio => {
emoji = Some("🎵"); emoji = Some("🎵");
type_name = Some(stock_str::audio(context).await); type_name = Some(stock_str::audio(context));
type_file = self.get_filename(); type_file = self.get_filename();
append_text = true append_text = true
} }
Viewtype::File => { Viewtype::File => {
emoji = Some("📎"); emoji = Some("📎");
type_name = Some(stock_str::file(context).await); type_name = Some(stock_str::file(context));
type_file = self.get_filename(); type_file = self.get_filename();
append_text = true append_text = true
} }
@@ -255,14 +255,14 @@ impl Message {
type_name = Some(match call_state { type_name = Some(match call_state {
CallState::Alerting | CallState::Active | CallState::Completed { .. } => { CallState::Alerting | CallState::Active | CallState::Completed { .. } => {
if self.from_id == ContactId::SELF { if self.from_id == ContactId::SELF {
stock_str::outgoing_call(context, has_video).await stock_str::outgoing_call(context, has_video)
} else { } else {
stock_str::incoming_call(context, has_video).await stock_str::incoming_call(context, has_video)
} }
} }
CallState::Missed => stock_str::missed_call(context).await, CallState::Missed => stock_str::missed_call(context),
CallState::Declined => stock_str::declined_call(context).await, CallState::Declined => stock_str::declined_call(context),
CallState::Canceled => stock_str::canceled_call(context).await, CallState::Canceled => stock_str::canceled_call(context),
}); });
type_file = None; type_file = None;
append_text = false append_text = false
@@ -270,7 +270,7 @@ impl Message {
Viewtype::Text | Viewtype::Unknown => { Viewtype::Text | Viewtype::Unknown => {
emoji = None; emoji = None;
if self.param.get_cmd() == SystemMessage::LocationOnly { if self.param.get_cmd() == SystemMessage::LocationOnly {
type_name = Some(stock_str::location(context).await); type_name = Some(stock_str::location(context));
type_file = None; type_file = None;
append_text = false; append_text = false;
} else { } else {

View File

@@ -229,9 +229,9 @@ impl Context {
let mut msg = Message { let mut msg = Message {
chat_id, chat_id,
viewtype: Viewtype::Text, viewtype: Viewtype::Text,
text: stock_str::sync_msg_body(self).await, text: stock_str::sync_msg_body(self),
hidden: true, hidden: true,
subject: stock_str::sync_msg_subject(self).await, subject: stock_str::sync_msg_subject(self),
..Default::default() ..Default::default()
}; };
msg.param.set_cmd(SystemMessage::MultiDeviceSync); msg.param.set_cmd(SystemMessage::MultiDeviceSync);

View File

@@ -195,7 +195,7 @@ async fn test_degrade_verified_oneonone_chat() -> Result<()> {
.await?; .await?;
let msg0 = get_chat_msg(&alice, alice_chat.id, 0, 1).await; let msg0 = get_chat_msg(&alice, alice_chat.id, 0, 1).await;
let enabled = stock_str::messages_e2ee_info_msg(&alice).await; let enabled = stock_str::messages_e2ee_info_msg(&alice);
assert_eq!(msg0.text, enabled); assert_eq!(msg0.text, enabled);
assert_eq!(msg0.param.get_cmd(), SystemMessage::ChatE2ee); assert_eq!(msg0.param.get_cmd(), SystemMessage::ChatE2ee);

View File

@@ -233,8 +233,7 @@ async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestam
|| "YY-MM-DD hh:mm:ss".to_string(), || "YY-MM-DD hh:mm:ss".to_string(),
|ts| ts.format("%Y-%m-%d %H:%M:%S").to_string(), |ts| ts.format("%Y-%m-%d %H:%M:%S").to_string(),
), ),
) );
.await;
if let Some(timestamp) = chrono::DateTime::<chrono::Utc>::from_timestamp(now, 0) { if let Some(timestamp) = chrono::DateTime::<chrono::Utc>::from_timestamp(now, 0) {
add_device_msg_with_importance( add_device_msg_with_importance(
context, context,
@@ -261,7 +260,7 @@ async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestam
#[expect(clippy::arithmetic_side_effects)] #[expect(clippy::arithmetic_side_effects)]
async fn maybe_warn_on_outdated(context: &Context, now: i64, approx_compile_time: i64) { async fn maybe_warn_on_outdated(context: &Context, now: i64, approx_compile_time: i64) {
if now > approx_compile_time + DC_OUTDATED_WARNING_DAYS * 24 * 60 * 60 { if now > approx_compile_time + DC_OUTDATED_WARNING_DAYS * 24 * 60 * 60 {
let mut msg = Message::new_text(stock_str::update_reminder_msg_body(context).await); let mut msg = Message::new_text(stock_str::update_reminder_msg_body(context));
if let Some(timestamp) = chrono::DateTime::<chrono::Utc>::from_timestamp(now, 0) { if let Some(timestamp) = chrono::DateTime::<chrono::Utc>::from_timestamp(now, 0) {
add_device_msg( add_device_msg(
context, context,