mirror of
https://github.com/chatmail/core.git
synced 2026-05-18 22:36:29 +03:00
Strongly type stock strings
This changes the internal stock strings API to be more strongly typed, ensuring that the caller can not construct the stock string in the wrong way. The old approach left it to the callers to figure out how a stock string should be created, now each stock string has their specific arguments and callers can not make mistakes. In particular all the subtleties and different ways of calling stock_system_msg() disappear. This could not use a trait for stock strings, as this would not allow having per-message typed arguments. So we needed a type per message with a custom method, only by convention this method is .stock_str(). The type is a enum without variants to avoid allowing someone to create the type. Sadly the fallback string and substitutions are still far away from each other, but it is now only one place which needs to know how to construct the string instead of many.
This commit is contained in:
141
src/chat.rs
141
src/chat.rs
@@ -1,6 +1,6 @@
|
|||||||
//! # Chat module
|
//! # Chat module
|
||||||
|
|
||||||
use deltachat_derive::{FromSql, ToSql};
|
use std::borrow::Cow;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
@@ -8,6 +8,7 @@ use std::time::{Duration, SystemTime};
|
|||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use anyhow::{bail, ensure, format_err, Error};
|
use anyhow::{bail, ensure, format_err, Error};
|
||||||
use async_std::path::{Path, PathBuf};
|
use async_std::path::{Path, PathBuf};
|
||||||
|
use deltachat_derive::{FromSql, ToSql};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -38,7 +39,11 @@ use crate::mimeparser::SystemMessage;
|
|||||||
use crate::param::{Param, Params};
|
use crate::param::{Param, Params};
|
||||||
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
|
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
|
||||||
use crate::sql;
|
use crate::sql;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{
|
||||||
|
ArchivedChats, DeadDrop, DeviceMessages, E2eAvailable, E2ePreferred, EncrNone, MsgAddMember,
|
||||||
|
MsgDelMember, MsgGroupLeft, MsgGrpImgChanged, MsgGrpImgDeleted, MsgGrpName, NewGroupDraft,
|
||||||
|
SavedMessages, SelfDeletedMsgBody, VideochatInviteMsgBody,
|
||||||
|
};
|
||||||
|
|
||||||
/// An chat item, such as a message or a marker.
|
/// An chat item, such as a message or a marker.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -396,12 +401,7 @@ impl ChatId {
|
|||||||
|
|
||||||
if chat.is_self_talk() {
|
if chat.is_self_talk() {
|
||||||
let mut msg = Message::new(Viewtype::Text);
|
let mut msg = Message::new(Viewtype::Text);
|
||||||
msg.text = Some(
|
msg.text = Some(SelfDeletedMsgBody::stock_str(context).await.into());
|
||||||
context
|
|
||||||
.stock_str(StockMessage::SelfDeletedMsgBody)
|
|
||||||
.await
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
add_device_msg(&context, None, Some(&mut msg)).await?;
|
add_device_msg(&context, None, Some(&mut msg)).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,23 +659,23 @@ impl ChatId {
|
|||||||
let addr = contact.get_addr();
|
let addr = contact.get_addr();
|
||||||
let peerstate = Peerstate::from_addr(context, addr).await?;
|
let peerstate = Peerstate::from_addr(context, addr).await?;
|
||||||
|
|
||||||
let stock_message = peerstate
|
let stock_message = match peerstate
|
||||||
.filter(|peerstate| {
|
.filter(|peerstate| {
|
||||||
peerstate
|
peerstate
|
||||||
.peek_key(PeerstateVerifiedStatus::Unverified)
|
.peek_key(PeerstateVerifiedStatus::Unverified)
|
||||||
.is_some()
|
.is_some()
|
||||||
})
|
})
|
||||||
.map(|peerstate| match peerstate.prefer_encrypt {
|
.map(|peerstate| peerstate.prefer_encrypt)
|
||||||
EncryptPreference::Mutual => StockMessage::E2ePreferred,
|
{
|
||||||
EncryptPreference::NoPreference => StockMessage::E2eAvailable,
|
Some(EncryptPreference::Mutual) => E2ePreferred::stock_str(context).await,
|
||||||
EncryptPreference::Reset => StockMessage::EncrNone,
|
Some(EncryptPreference::NoPreference) => E2eAvailable::stock_str(context).await,
|
||||||
})
|
Some(EncryptPreference::Reset) => EncrNone::stock_str(context).await,
|
||||||
.unwrap_or(StockMessage::EncrNone);
|
None => EncrNone::stock_str(context).await,
|
||||||
|
};
|
||||||
if !ret.is_empty() {
|
if !ret.is_empty() {
|
||||||
ret.push('\n')
|
ret.push('\n')
|
||||||
}
|
}
|
||||||
ret += &format!("{} {}", addr, context.stock_str(stock_message).await);
|
ret += &format!("{} {}", addr, stock_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
@@ -793,9 +793,9 @@ impl Chat {
|
|||||||
}
|
}
|
||||||
Ok(mut chat) => {
|
Ok(mut chat) => {
|
||||||
if chat.id.is_deaddrop() {
|
if chat.id.is_deaddrop() {
|
||||||
chat.name = context.stock_str(StockMessage::DeadDrop).await.into();
|
chat.name = DeadDrop::stock_str(context).await.into();
|
||||||
} else if chat.id.is_archived_link() {
|
} else if chat.id.is_archived_link() {
|
||||||
let tempname = context.stock_str(StockMessage::ArchivedChats).await;
|
let tempname = ArchivedChats::stock_str(context).await;
|
||||||
let cnt = dc_get_archived_cnt(context).await;
|
let cnt = dc_get_archived_cnt(context).await;
|
||||||
chat.name = format!("{} ({})", tempname, cnt);
|
chat.name = format!("{} ({})", tempname, cnt);
|
||||||
} else {
|
} else {
|
||||||
@@ -810,9 +810,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 = context.stock_str(StockMessage::SavedMessages).await.into();
|
chat.name = SavedMessages::stock_str(context).await.into();
|
||||||
} else if chat.param.exists(Param::Devicetalk) {
|
} else if chat.param.exists(Param::Devicetalk) {
|
||||||
chat.name = context.stock_str(StockMessage::DeviceMessages).await.into();
|
chat.name = DeviceMessages::stock_str(context).await.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(chat)
|
Ok(chat)
|
||||||
@@ -1411,10 +1411,10 @@ pub(crate) async fn update_device_icon(context: &Context) -> Result<(), Error> {
|
|||||||
async fn update_special_chat_name(
|
async fn update_special_chat_name(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
contact_id: u32,
|
contact_id: u32,
|
||||||
stock_id: StockMessage,
|
name: Cow<'static, str>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if let Ok((chat_id, _)) = lookup_by_contact_id(context, contact_id).await {
|
if let Ok((chat_id, _)) = lookup_by_contact_id(context, contact_id).await {
|
||||||
let name: String = context.stock_str(stock_id).await.into();
|
let name: String = name.into();
|
||||||
// the `!= name` condition avoids unneeded writes
|
// the `!= name` condition avoids unneeded writes
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
@@ -1428,8 +1428,18 @@ async fn update_special_chat_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn update_special_chat_names(context: &Context) -> Result<(), Error> {
|
pub(crate) async fn update_special_chat_names(context: &Context) -> Result<(), Error> {
|
||||||
update_special_chat_name(context, DC_CONTACT_ID_DEVICE, StockMessage::DeviceMessages).await?;
|
update_special_chat_name(
|
||||||
update_special_chat_name(context, DC_CONTACT_ID_SELF, StockMessage::SavedMessages).await?;
|
context,
|
||||||
|
DC_CONTACT_ID_DEVICE,
|
||||||
|
DeviceMessages::stock_str(context).await,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
update_special_chat_name(
|
||||||
|
context,
|
||||||
|
DC_CONTACT_ID_SELF,
|
||||||
|
SavedMessages::stock_str(context).await,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1812,12 +1822,9 @@ pub async fn send_videochat_invitation(context: &Context, chat_id: ChatId) -> Re
|
|||||||
let mut msg = Message::new(Viewtype::VideochatInvitation);
|
let mut msg = Message::new(Viewtype::VideochatInvitation);
|
||||||
msg.param.set(Param::WebrtcRoom, &instance);
|
msg.param.set(Param::WebrtcRoom, &instance);
|
||||||
msg.text = Some(
|
msg.text = Some(
|
||||||
context
|
VideochatInviteMsgBody::stock_str(context, Message::parse_webrtc_instance(&instance).1)
|
||||||
.stock_string_repl_str(
|
.await
|
||||||
StockMessage::VideochatInviteMsgBody,
|
.to_string(),
|
||||||
Message::parse_webrtc_instance(&instance).1,
|
|
||||||
)
|
|
||||||
.await,
|
|
||||||
);
|
);
|
||||||
send_msg(context, chat_id, &mut msg).await
|
send_msg(context, chat_id, &mut msg).await
|
||||||
}
|
}
|
||||||
@@ -2154,9 +2161,9 @@ pub async fn create_group_chat(
|
|||||||
let chat_name = improve_single_line_input(chat_name);
|
let chat_name = improve_single_line_input(chat_name);
|
||||||
ensure!(!chat_name.is_empty(), "Invalid chat name");
|
ensure!(!chat_name.is_empty(), "Invalid chat name");
|
||||||
|
|
||||||
let draft_txt = context
|
let draft_txt = NewGroupDraft::stock_str(context, &chat_name)
|
||||||
.stock_string_repl_str(StockMessage::NewGroupDraft, &chat_name)
|
.await
|
||||||
.await;
|
.to_string();
|
||||||
let grpid = dc_create_id();
|
let grpid = dc_create_id();
|
||||||
|
|
||||||
context.sql.execute(
|
context.sql.execute(
|
||||||
@@ -2334,14 +2341,9 @@ pub(crate) async fn add_contact_to_chat_ex(
|
|||||||
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||||
msg.viewtype = Viewtype::Text;
|
msg.viewtype = Viewtype::Text;
|
||||||
msg.text = Some(
|
msg.text = Some(
|
||||||
context
|
MsgAddMember::stock_str(context, contact.get_addr(), DC_CONTACT_ID_SELF)
|
||||||
.stock_system_msg(
|
.await
|
||||||
StockMessage::MsgAddMember,
|
.to_string(),
|
||||||
contact.get_addr(),
|
|
||||||
"",
|
|
||||||
DC_CONTACT_ID_SELF as u32,
|
|
||||||
)
|
|
||||||
.await,
|
|
||||||
);
|
);
|
||||||
msg.param.set_cmd(SystemMessage::MemberAddedToGroup);
|
msg.param.set_cmd(SystemMessage::MemberAddedToGroup);
|
||||||
msg.param.set(Param::Arg, contact.get_addr());
|
msg.param.set(Param::Arg, contact.get_addr());
|
||||||
@@ -2537,25 +2539,19 @@ pub async fn remove_contact_from_chat(
|
|||||||
if contact.id == DC_CONTACT_ID_SELF {
|
if contact.id == DC_CONTACT_ID_SELF {
|
||||||
set_group_explicitly_left(context, chat.grpid).await?;
|
set_group_explicitly_left(context, chat.grpid).await?;
|
||||||
msg.text = Some(
|
msg.text = Some(
|
||||||
context
|
MsgGroupLeft::stock_str(context, DC_CONTACT_ID_SELF)
|
||||||
.stock_system_msg(
|
.await
|
||||||
StockMessage::MsgGroupLeft,
|
.to_string(),
|
||||||
"",
|
|
||||||
"",
|
|
||||||
DC_CONTACT_ID_SELF,
|
|
||||||
)
|
|
||||||
.await,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
msg.text = Some(
|
msg.text = Some(
|
||||||
context
|
MsgDelMember::stock_str(
|
||||||
.stock_system_msg(
|
context,
|
||||||
StockMessage::MsgDelMember,
|
contact.get_addr(),
|
||||||
contact.get_addr(),
|
DC_CONTACT_ID_SELF,
|
||||||
"",
|
)
|
||||||
DC_CONTACT_ID_SELF,
|
.await
|
||||||
)
|
.to_string(),
|
||||||
.await,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
msg.param.set_cmd(SystemMessage::MemberRemovedFromGroup);
|
msg.param.set_cmd(SystemMessage::MemberRemovedFromGroup);
|
||||||
@@ -2651,14 +2647,9 @@ pub async fn set_chat_name(
|
|||||||
if chat.is_promoted() && !chat.is_mailing_list() {
|
if chat.is_promoted() && !chat.is_mailing_list() {
|
||||||
msg.viewtype = Viewtype::Text;
|
msg.viewtype = Viewtype::Text;
|
||||||
msg.text = Some(
|
msg.text = Some(
|
||||||
context
|
MsgGrpName::stock_str(context, &chat.name, &new_name, DC_CONTACT_ID_SELF)
|
||||||
.stock_system_msg(
|
.await
|
||||||
StockMessage::MsgGrpName,
|
.to_string(),
|
||||||
&chat.name,
|
|
||||||
&new_name,
|
|
||||||
DC_CONTACT_ID_SELF,
|
|
||||||
)
|
|
||||||
.await,
|
|
||||||
);
|
);
|
||||||
msg.param.set_cmd(SystemMessage::GroupNameChanged);
|
msg.param.set_cmd(SystemMessage::GroupNameChanged);
|
||||||
if !chat.name.is_empty() {
|
if !chat.name.is_empty() {
|
||||||
@@ -2716,9 +2707,9 @@ 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 = Some(
|
msg.text = Some(
|
||||||
context
|
MsgGrpImgDeleted::stock_str(context, DC_CONTACT_ID_SELF)
|
||||||
.stock_system_msg(StockMessage::MsgGrpImgDeleted, "", "", DC_CONTACT_ID_SELF)
|
.await
|
||||||
.await,
|
.to_string(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let image_blob = match BlobObject::from_path(context, Path::new(new_image.as_ref())) {
|
let image_blob = match BlobObject::from_path(context, Path::new(new_image.as_ref())) {
|
||||||
@@ -2734,9 +2725,9 @@ 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 = Some(
|
msg.text = Some(
|
||||||
context
|
MsgGrpImgChanged::stock_str(context, DC_CONTACT_ID_SELF)
|
||||||
.stock_system_msg(StockMessage::MsgGrpImgChanged, "", "", DC_CONTACT_ID_SELF)
|
.await
|
||||||
.await,
|
.to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
chat.update_param(context).await?;
|
chat.update_param(context).await?;
|
||||||
@@ -3215,7 +3206,7 @@ mod tests {
|
|||||||
assert!(chat.visibility == ChatVisibility::Normal);
|
assert!(chat.visibility == ChatVisibility::Normal);
|
||||||
assert!(!chat.is_device_talk());
|
assert!(!chat.is_device_talk());
|
||||||
assert!(chat.can_send());
|
assert!(chat.can_send());
|
||||||
assert_eq!(chat.name, t.stock_str(StockMessage::SavedMessages).await);
|
assert_eq!(chat.name, SavedMessages::stock_str(&t).await);
|
||||||
assert!(chat.get_profile_image(&t).await.is_some());
|
assert!(chat.get_profile_image(&t).await.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3231,7 +3222,7 @@ mod tests {
|
|||||||
assert!(chat.visibility == ChatVisibility::Normal);
|
assert!(chat.visibility == ChatVisibility::Normal);
|
||||||
assert!(!chat.is_device_talk());
|
assert!(!chat.is_device_talk());
|
||||||
assert!(!chat.can_send());
|
assert!(!chat.can_send());
|
||||||
assert_eq!(chat.name, t.stock_str(StockMessage::DeadDrop).await);
|
assert_eq!(chat.name, DeadDrop::stock_str(&t).await);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
@@ -3308,7 +3299,7 @@ mod tests {
|
|||||||
assert!(chat.is_device_talk());
|
assert!(chat.is_device_talk());
|
||||||
assert!(!chat.is_self_talk());
|
assert!(!chat.is_self_talk());
|
||||||
assert!(!chat.can_send());
|
assert!(!chat.can_send());
|
||||||
assert_eq!(chat.name, t.stock_str(StockMessage::DeviceMessages).await);
|
assert_eq!(chat.name, DeviceMessages::stock_str(&t).await);
|
||||||
assert!(chat.get_profile_image(&t).await.is_some());
|
assert!(chat.get_profile_image(&t).await.is_some());
|
||||||
|
|
||||||
// delete device message, make sure it is not added again
|
// delete device message, make sure it is not added again
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::context::Context;
|
|||||||
use crate::ephemeral::delete_expired_messages;
|
use crate::ephemeral::delete_expired_messages;
|
||||||
use crate::lot::Lot;
|
use crate::lot::Lot;
|
||||||
use crate::message::{Message, MessageState, MsgId};
|
use crate::message::{Message, MessageState, MsgId};
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::NoMessages;
|
||||||
|
|
||||||
/// An object representing a single chatlist in memory.
|
/// An object representing a single chatlist in memory.
|
||||||
///
|
///
|
||||||
@@ -385,12 +385,7 @@ impl Chatlist {
|
|||||||
ret.text2 = None;
|
ret.text2 = None;
|
||||||
} else if lastmsg.is_none() || lastmsg.as_ref().unwrap().from_id == DC_CONTACT_ID_UNDEFINED
|
} else if lastmsg.is_none() || lastmsg.as_ref().unwrap().from_id == DC_CONTACT_ID_UNDEFINED
|
||||||
{
|
{
|
||||||
ret.text2 = Some(
|
ret.text2 = Some(NoMessages::stock_str(context).await.to_string());
|
||||||
context
|
|
||||||
.stock_str(StockMessage::NoMessages)
|
|
||||||
.await
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
ret.fill(&mut lastmsg.unwrap(), chat, lastcontact.as_ref(), context)
|
ret.fill(&mut lastmsg.unwrap(), chat, lastcontact.as_ref(), context)
|
||||||
.await;
|
.await;
|
||||||
@@ -445,6 +440,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::chat::{create_group_chat, ProtectionStatus};
|
use crate::chat::{create_group_chat, ProtectionStatus};
|
||||||
use crate::constants::Viewtype;
|
use crate::constants::Viewtype;
|
||||||
|
use crate::stock::StockMessage;
|
||||||
use crate::test_utils::TestContext;
|
use crate::test_utils::TestContext;
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
use strum::{EnumProperty, IntoEnumIterator};
|
use strum::{EnumProperty, IntoEnumIterator};
|
||||||
use strum_macros::{AsRefStr, Display, EnumIter, EnumProperty, EnumString};
|
use strum_macros::{AsRefStr, Display, EnumIter, EnumProperty, EnumString};
|
||||||
|
|
||||||
|
use crate::blob::BlobObject;
|
||||||
use crate::chat::ChatId;
|
use crate::chat::ChatId;
|
||||||
use crate::constants::DC_VERSION_STR;
|
use crate::constants::DC_VERSION_STR;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
@@ -11,11 +12,8 @@ use crate::events::EventType;
|
|||||||
use crate::job;
|
use crate::job;
|
||||||
use crate::message::MsgId;
|
use crate::message::MsgId;
|
||||||
use crate::mimefactory::RECOMMENDED_FILE_SIZE;
|
use crate::mimefactory::RECOMMENDED_FILE_SIZE;
|
||||||
use crate::stock::StockMessage;
|
use crate::provider::{get_provider_by_id, Provider};
|
||||||
use crate::{
|
use crate::stock::StatusLine;
|
||||||
blob::BlobObject,
|
|
||||||
provider::{get_provider_by_id, Provider},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The available configuration keys.
|
/// The available configuration keys.
|
||||||
#[derive(
|
#[derive(
|
||||||
@@ -175,7 +173,7 @@ impl Context {
|
|||||||
|
|
||||||
// Default values
|
// Default values
|
||||||
match key {
|
match key {
|
||||||
Config::Selfstatus => Some(self.stock_str(StockMessage::StatusLine).await.into_owned()),
|
Config::Selfstatus => Some(StatusLine::stock_str(self).await.into_owned()),
|
||||||
Config::ConfiguredInboxFolder => Some("INBOX".to_owned()),
|
Config::ConfiguredInboxFolder => Some("INBOX".to_owned()),
|
||||||
_ => key.get_str("default").map(|s| s.to_string()),
|
_ => key.get_str("default").map(|s| s.to_string()),
|
||||||
}
|
}
|
||||||
@@ -260,7 +258,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Config::Selfstatus => {
|
Config::Selfstatus => {
|
||||||
let def = self.stock_str(StockMessage::StatusLine).await;
|
let def = StatusLine::stock_str(self).await;
|
||||||
let val = if value.is_none() || value.unwrap() == def {
|
let val = if value.is_none() || value.unwrap() == def {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use crate::message::Message;
|
|||||||
use crate::oauth2::dc_get_oauth2_addr;
|
use crate::oauth2::dc_get_oauth2_addr;
|
||||||
use crate::provider::{Protocol, Socket, UsernamePattern};
|
use crate::provider::{Protocol, Socket, UsernamePattern};
|
||||||
use crate::smtp::Smtp;
|
use crate::smtp::Smtp;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{ConfigurationFailed, ErrorNoNetwork};
|
||||||
use crate::{chat, e2ee, provider};
|
use crate::{chat, e2ee, provider};
|
||||||
use crate::{config::Config, dc_tools::time};
|
use crate::{config::Config, dc_tools::time};
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -127,12 +127,14 @@ impl Context {
|
|||||||
self,
|
self,
|
||||||
0,
|
0,
|
||||||
Some(
|
Some(
|
||||||
self.stock_string_repl_str(
|
ConfigurationFailed::stock_str(
|
||||||
StockMessage::ConfigurationFailed,
|
self,
|
||||||
// We are using Anyhow's .context() and to show the inner error, too, we need the {:#}:
|
// We are using Anyhow's .context() and to show the
|
||||||
|
// inner error, too, we need the {:#}:
|
||||||
format!("{:#}", err),
|
format!("{:#}", err),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.to_string()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
Err(err)
|
Err(err)
|
||||||
@@ -589,10 +591,7 @@ async fn nicer_configuration_error(context: &Context, errors: Vec<ConfigurationE
|
|||||||
.iter()
|
.iter()
|
||||||
.all(|e| e.msg.to_lowercase().contains("could not resolve"))
|
.all(|e| e.msg.to_lowercase().contains("could not resolve"))
|
||||||
{
|
{
|
||||||
return context
|
return ErrorNoNetwork::stock_str(context).await.to_string();
|
||||||
.stock_str(StockMessage::ErrorNoNetwork)
|
|
||||||
.await
|
|
||||||
.to_string();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.iter().all(|e| e.msg == first_err.msg) {
|
if errors.iter().all(|e| e.msg == first_err.msg) {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use crate::message::MessageState;
|
|||||||
use crate::mimeparser::AvatarAction;
|
use crate::mimeparser::AvatarAction;
|
||||||
use crate::param::{Param, Params};
|
use crate::param::{Param, Params};
|
||||||
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
|
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{DeviceMessages, E2eAvailable, E2ePreferred, EncrNone, FingerPrints, SelfMsg};
|
||||||
|
|
||||||
/// An object representing a single contact in memory.
|
/// An object representing a single contact in memory.
|
||||||
///
|
///
|
||||||
@@ -195,7 +195,7 @@ impl Contact {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
if contact_id == DC_CONTACT_ID_SELF {
|
if contact_id == DC_CONTACT_ID_SELF {
|
||||||
res.name = context.stock_str(StockMessage::SelfMsg).await.to_string();
|
res.name = SelfMsg::stock_str(context).await.to_string();
|
||||||
res.addr = context
|
res.addr = context
|
||||||
.get_config(Config::ConfiguredAddr)
|
.get_config(Config::ConfiguredAddr)
|
||||||
.await
|
.await
|
||||||
@@ -205,10 +205,7 @@ impl Contact {
|
|||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
} else if contact_id == DC_CONTACT_ID_DEVICE {
|
} else if contact_id == DC_CONTACT_ID_DEVICE {
|
||||||
res.name = context
|
res.name = DeviceMessages::stock_str(context).await.to_string();
|
||||||
.stock_str(StockMessage::DeviceMessages)
|
|
||||||
.await
|
|
||||||
.to_string();
|
|
||||||
res.addr = DC_CONTACT_ID_DEVICE_ADDR.to_string();
|
res.addr = DC_CONTACT_ID_DEVICE_ADDR.to_string();
|
||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
@@ -635,7 +632,7 @@ impl Contact {
|
|||||||
.get_config(Config::Displayname)
|
.get_config(Config::Displayname)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let self_name2 = context.stock_str(StockMessage::SelfMsg);
|
let self_name2 = SelfMsg::stock_str(context);
|
||||||
|
|
||||||
if let Some(query) = query {
|
if let Some(query) = query {
|
||||||
if self_addr.contains(query.as_ref())
|
if self_addr.contains(query.as_ref())
|
||||||
@@ -729,15 +726,15 @@ impl Contact {
|
|||||||
.is_some()
|
.is_some()
|
||||||
}) {
|
}) {
|
||||||
let stock_message = match peerstate.prefer_encrypt {
|
let stock_message = match peerstate.prefer_encrypt {
|
||||||
EncryptPreference::Mutual => StockMessage::E2ePreferred,
|
EncryptPreference::Mutual => E2ePreferred::stock_str(context).await,
|
||||||
EncryptPreference::NoPreference => StockMessage::E2eAvailable,
|
EncryptPreference::NoPreference => E2eAvailable::stock_str(context).await,
|
||||||
EncryptPreference::Reset => StockMessage::EncrNone,
|
EncryptPreference::Reset => EncrNone::stock_str(context).await,
|
||||||
};
|
};
|
||||||
|
|
||||||
ret += &format!(
|
ret += &format!(
|
||||||
"{}\n{}:",
|
"{}\n{}:",
|
||||||
context.stock_str(stock_message).await,
|
stock_message,
|
||||||
context.stock_str(StockMessage::FingerPrints).await
|
FingerPrints::stock_str(context).await
|
||||||
);
|
);
|
||||||
|
|
||||||
let fingerprint_self = SignedPublicKey::load_self(context)
|
let fingerprint_self = SignedPublicKey::load_self(context)
|
||||||
@@ -770,7 +767,7 @@ impl Contact {
|
|||||||
cat_fingerprint(&mut ret, &loginparam.addr, &fingerprint_self, "");
|
cat_fingerprint(&mut ret, &loginparam.addr, &fingerprint_self, "");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret += &context.stock_str(StockMessage::EncrNone).await;
|
ret += &EncrNone::stock_str(context).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1510,7 +1507,7 @@ mod tests {
|
|||||||
// check SELF
|
// check SELF
|
||||||
let contact = Contact::load_from_db(&t, DC_CONTACT_ID_SELF).await.unwrap();
|
let contact = Contact::load_from_db(&t, DC_CONTACT_ID_SELF).await.unwrap();
|
||||||
assert_eq!(DC_CONTACT_ID_SELF, 1);
|
assert_eq!(DC_CONTACT_ID_SELF, 1);
|
||||||
assert_eq!(contact.get_name(), t.stock_str(StockMessage::SelfMsg).await);
|
assert_eq!(contact.get_name(), SelfMsg::stock_str(&t).await);
|
||||||
assert_eq!(contact.get_addr(), ""); // we're not configured
|
assert_eq!(contact.get_addr(), ""); // we're not configured
|
||||||
assert!(!contact.is_blocked());
|
assert!(!contact.is_blocked());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ use crate::mimeparser::{parse_message_ids, AvatarAction, MimeMessage, SystemMess
|
|||||||
use crate::param::{Param, Params};
|
use crate::param::{Param, Params};
|
||||||
use crate::peerstate::{Peerstate, PeerstateKeyType, PeerstateVerifiedStatus};
|
use crate::peerstate::{Peerstate, PeerstateKeyType, PeerstateVerifiedStatus};
|
||||||
use crate::securejoin::{self, handle_securejoin_handshake, observe_securejoin_on_other_device};
|
use crate::securejoin::{self, handle_securejoin_handshake, observe_securejoin_on_other_device};
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{
|
||||||
|
MsgAddMember, MsgDelMember, MsgGroupLeft, MsgGrpImgChanged, MsgGrpImgDeleted, MsgGrpName,
|
||||||
|
MsgLocationEnabled, UnknownSenderForChat,
|
||||||
|
};
|
||||||
use crate::{contact, location};
|
use crate::{contact, location};
|
||||||
|
|
||||||
// IndexSet is like HashSet but maintains order of insertion
|
// IndexSet is like HashSet but maintains order of insertion
|
||||||
@@ -1165,9 +1168,9 @@ async fn create_or_lookup_group(
|
|||||||
let mut better_msg: String = From::from("");
|
let mut better_msg: String = From::from("");
|
||||||
|
|
||||||
if mime_parser.is_system_message == SystemMessage::LocationStreamingEnabled {
|
if mime_parser.is_system_message == SystemMessage::LocationStreamingEnabled {
|
||||||
better_msg = context
|
better_msg = MsgLocationEnabled::stock_str_by(context, from_id)
|
||||||
.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", from_id as u32)
|
.await
|
||||||
.await;
|
.to_string();
|
||||||
set_better_msg(mime_parser, &better_msg);
|
set_better_msg(mime_parser, &better_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1231,48 +1234,38 @@ async fn create_or_lookup_group(
|
|||||||
match removed_id {
|
match removed_id {
|
||||||
Some(contact_id) => {
|
Some(contact_id) => {
|
||||||
mime_parser.is_system_message = SystemMessage::MemberRemovedFromGroup;
|
mime_parser.is_system_message = SystemMessage::MemberRemovedFromGroup;
|
||||||
better_msg = context
|
better_msg = if contact_id == from_id {
|
||||||
.stock_system_msg(
|
MsgGroupLeft::stock_str(context, from_id).await.to_string()
|
||||||
if contact_id == from_id as u32 {
|
} else {
|
||||||
StockMessage::MsgGroupLeft
|
MsgDelMember::stock_str(context, &removed_addr, from_id)
|
||||||
} else {
|
.await
|
||||||
StockMessage::MsgDelMember
|
.to_string()
|
||||||
},
|
};
|
||||||
&removed_addr,
|
|
||||||
"",
|
|
||||||
from_id as u32,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
None => warn!(context, "removed {:?} has no contact_id", removed_addr),
|
None => warn!(context, "removed {:?} has no contact_id", removed_addr),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let field = mime_parser.get(HeaderDef::ChatGroupMemberAdded).cloned();
|
let field = mime_parser.get(HeaderDef::ChatGroupMemberAdded).cloned();
|
||||||
if let Some(optional_field) = field {
|
if let Some(added_member) = field {
|
||||||
mime_parser.is_system_message = SystemMessage::MemberAddedToGroup;
|
mime_parser.is_system_message = SystemMessage::MemberAddedToGroup;
|
||||||
better_msg = context
|
better_msg = MsgAddMember::stock_str(context, &added_member, from_id)
|
||||||
.stock_system_msg(
|
.await
|
||||||
StockMessage::MsgAddMember,
|
.to_string();
|
||||||
&optional_field,
|
X_MrAddToGrp = Some(added_member);
|
||||||
"",
|
|
||||||
from_id as u32,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
X_MrAddToGrp = Some(optional_field);
|
|
||||||
} else if let Some(old_name) = mime_parser.get(HeaderDef::ChatGroupNameChanged) {
|
} else if let Some(old_name) = mime_parser.get(HeaderDef::ChatGroupNameChanged) {
|
||||||
X_MrGrpNameChanged = true;
|
X_MrGrpNameChanged = true;
|
||||||
better_msg = context
|
better_msg = MsgGrpName::stock_str(
|
||||||
.stock_system_msg(
|
context,
|
||||||
StockMessage::MsgGrpName,
|
old_name,
|
||||||
old_name,
|
if let Some(ref name) = grpname {
|
||||||
if let Some(ref name) = grpname {
|
name
|
||||||
name
|
} else {
|
||||||
} else {
|
""
|
||||||
""
|
},
|
||||||
},
|
from_id as u32,
|
||||||
from_id as u32,
|
)
|
||||||
)
|
.await
|
||||||
.await;
|
.to_string();
|
||||||
mime_parser.is_system_message = SystemMessage::GroupNameChanged;
|
mime_parser.is_system_message = SystemMessage::GroupNameChanged;
|
||||||
} else if let Some(value) = mime_parser.get(HeaderDef::ChatContent) {
|
} else if let Some(value) = mime_parser.get(HeaderDef::ChatContent) {
|
||||||
if value == "group-avatar-changed" {
|
if value == "group-avatar-changed" {
|
||||||
@@ -1280,17 +1273,14 @@ async fn create_or_lookup_group(
|
|||||||
// this is just an explicit message containing the group-avatar,
|
// this is just an explicit message containing the group-avatar,
|
||||||
// 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
|
||||||
mime_parser.is_system_message = SystemMessage::GroupImageChanged;
|
mime_parser.is_system_message = SystemMessage::GroupImageChanged;
|
||||||
better_msg = context
|
better_msg = match avatar_action {
|
||||||
.stock_system_msg(
|
AvatarAction::Delete => MsgGrpImgDeleted::stock_str(context, from_id)
|
||||||
match avatar_action {
|
.await
|
||||||
AvatarAction::Delete => StockMessage::MsgGrpImgDeleted,
|
.to_string(),
|
||||||
AvatarAction::Change(_) => StockMessage::MsgGrpImgChanged,
|
AvatarAction::Change(_) => MsgGrpImgChanged::stock_str(context, from_id)
|
||||||
},
|
.await
|
||||||
"",
|
.to_string(),
|
||||||
"",
|
};
|
||||||
from_id as u32,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1308,7 +1298,7 @@ async fn create_or_lookup_group(
|
|||||||
// but still show the message as part of the chat.
|
// but still show the message as part of the chat.
|
||||||
// After all, the sender has a reference/in-reply-to that
|
// After all, the sender has a reference/in-reply-to that
|
||||||
// points to this chat.
|
// points to this chat.
|
||||||
let s = context.stock_str(StockMessage::UnknownSenderForChat).await;
|
let s = UnknownSenderForChat::stock_str(context).await;
|
||||||
mime_parser.repl_msg_by_error(s.to_string());
|
mime_parser.repl_msg_by_error(s.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1989,6 +1979,7 @@ mod tests {
|
|||||||
use crate::constants::{DC_CONTACT_ID_INFO, DC_GCL_NO_SPECIALS};
|
use crate::constants::{DC_CONTACT_ID_INFO, DC_GCL_NO_SPECIALS};
|
||||||
use crate::message::ContactRequestDecision::*;
|
use crate::message::ContactRequestDecision::*;
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
|
use crate::stock::FailedSendingTo;
|
||||||
use crate::test_utils::TestContext;
|
use crate::test_utils::TestContext;
|
||||||
use crate::{
|
use crate::{
|
||||||
chat::{ChatItem, ChatVisibility},
|
chat::{ChatItem, ChatVisibility},
|
||||||
@@ -2656,11 +2647,9 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
last_msg.text,
|
last_msg.text,
|
||||||
Some(
|
Some(
|
||||||
t.stock_string_repl_str(
|
FailedSendingTo::stock_str(&t, "assidhfaaspocwaeofi@gmail.com")
|
||||||
StockMessage::FailedSendingTo,
|
.await
|
||||||
"assidhfaaspocwaeofi@gmail.com",
|
.to_string(),
|
||||||
)
|
|
||||||
.await,
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(last_msg.from_id, DC_CONTACT_ID_INFO);
|
assert_eq!(last_msg.from_id, DC_CONTACT_ID_INFO);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use crate::context::Context;
|
|||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
use crate::provider::get_provider_update_timestamp;
|
use crate::provider::get_provider_update_timestamp;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{BadTimeMsgBody, UpdateReminderMsgBody};
|
||||||
|
|
||||||
/// Shortens a string to a specified length and adds "[...]" to the
|
/// Shortens a string to a specified length and adds "[...]" to the
|
||||||
/// end of the shortened string.
|
/// end of the shortened string.
|
||||||
@@ -169,15 +169,15 @@ async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestam
|
|||||||
if now < known_past_timestamp {
|
if now < known_past_timestamp {
|
||||||
let mut msg = Message::new(Viewtype::Text);
|
let mut msg = Message::new(Viewtype::Text);
|
||||||
msg.text = Some(
|
msg.text = Some(
|
||||||
context
|
BadTimeMsgBody::stock_str(
|
||||||
.stock_string_repl_str(
|
context,
|
||||||
StockMessage::BadTimeMsgBody,
|
Local
|
||||||
Local
|
.timestamp(now, 0)
|
||||||
.timestamp(now, 0)
|
.format("%Y-%m-%d %H:%M:%S")
|
||||||
.format("%Y-%m-%d %H:%M:%S")
|
.to_string(),
|
||||||
.to_string(),
|
)
|
||||||
)
|
.await
|
||||||
.await,
|
.to_string(),
|
||||||
);
|
);
|
||||||
add_device_msg_with_importance(
|
add_device_msg_with_importance(
|
||||||
context,
|
context,
|
||||||
@@ -201,12 +201,7 @@ async fn maybe_warn_on_bad_time(context: &Context, now: i64, known_past_timestam
|
|||||||
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(Viewtype::Text);
|
let mut msg = Message::new(Viewtype::Text);
|
||||||
msg.text = Some(
|
msg.text = Some(UpdateReminderMsgBody::stock_str(context).await.into());
|
||||||
context
|
|
||||||
.stock_str(StockMessage::UpdateReminderMsgBody)
|
|
||||||
.await
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
add_device_msg(
|
add_device_msg(
|
||||||
context,
|
context,
|
||||||
Some(
|
Some(
|
||||||
|
|||||||
217
src/ephemeral.rs
217
src/ephemeral.rs
@@ -56,7 +56,15 @@
|
|||||||
//! the database entries which are expired either according to their
|
//! the database entries which are expired either according to their
|
||||||
//! ephemeral message timers or global `delete_server_after` setting.
|
//! ephemeral message timers or global `delete_server_after` setting.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
use std::num::ParseIntError;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use anyhow::{ensure, Error};
|
use anyhow::{ensure, Error};
|
||||||
|
use async_std::task;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::chat::{lookup_by_contact_id, send_msg, ChatId};
|
use crate::chat::{lookup_by_contact_id, send_msg, ChatId};
|
||||||
use crate::constants::{
|
use crate::constants::{
|
||||||
@@ -68,13 +76,12 @@ use crate::events::EventType;
|
|||||||
use crate::message::{Message, MessageState, MsgId};
|
use crate::message::{Message, MessageState, MsgId};
|
||||||
use crate::mimeparser::SystemMessage;
|
use crate::mimeparser::SystemMessage;
|
||||||
use crate::sql;
|
use crate::sql;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{
|
||||||
use async_std::task;
|
MsgEphemeralTimerDay, MsgEphemeralTimerDays, MsgEphemeralTimerDisabled,
|
||||||
use serde::{Deserialize, Serialize};
|
MsgEphemeralTimerEnabled, MsgEphemeralTimerHour, MsgEphemeralTimerHours,
|
||||||
use std::convert::{TryFrom, TryInto};
|
MsgEphemeralTimerMinute, MsgEphemeralTimerMinutes, MsgEphemeralTimerWeek,
|
||||||
use std::num::ParseIntError;
|
MsgEphemeralTimerWeeks,
|
||||||
use std::str::FromStr;
|
};
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub enum Timer {
|
pub enum Timer {
|
||||||
@@ -194,7 +201,11 @@ impl ChatId {
|
|||||||
}
|
}
|
||||||
self.inner_set_ephemeral_timer(context, timer).await?;
|
self.inner_set_ephemeral_timer(context, timer).await?;
|
||||||
let mut msg = Message::new(Viewtype::Text);
|
let mut msg = Message::new(Viewtype::Text);
|
||||||
msg.text = Some(stock_ephemeral_timer_changed(context, timer, DC_CONTACT_ID_SELF).await);
|
msg.text = Some(
|
||||||
|
stock_ephemeral_timer_changed(context, timer, DC_CONTACT_ID_SELF)
|
||||||
|
.await
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
msg.param.set_cmd(SystemMessage::EphemeralTimerChanged);
|
msg.param.set_cmd(SystemMessage::EphemeralTimerChanged);
|
||||||
if let Err(err) = send_msg(context, self, &mut msg).await {
|
if let Err(err) = send_msg(context, self, &mut msg).await {
|
||||||
error!(
|
error!(
|
||||||
@@ -211,87 +222,48 @@ pub(crate) async fn stock_ephemeral_timer_changed(
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
from_id: u32,
|
from_id: u32,
|
||||||
) -> String {
|
) -> Cow<'static, str> {
|
||||||
match timer {
|
match timer {
|
||||||
Timer::Disabled => {
|
Timer::Disabled => MsgEphemeralTimerDisabled::stock_str(context, from_id).await,
|
||||||
context
|
Timer::Enabled { duration } => match duration {
|
||||||
.stock_system_msg(
|
0..=59 => {
|
||||||
StockMessage::MsgEphemeralTimerDisabled,
|
MsgEphemeralTimerEnabled::stock_str(context, timer.to_string(), from_id).await
|
||||||
timer.to_string(),
|
}
|
||||||
"",
|
60 => MsgEphemeralTimerMinute::stock_str(context, from_id).await,
|
||||||
|
61..=3599 => {
|
||||||
|
MsgEphemeralTimerMinutes::stock_str(
|
||||||
|
context,
|
||||||
|
format!("{}", (f64::from(duration) / 6.0).round() / 10.0),
|
||||||
from_id,
|
from_id,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
|
||||||
Timer::Enabled { duration } => match duration {
|
|
||||||
0..=59 => {
|
|
||||||
context
|
|
||||||
.stock_system_msg(
|
|
||||||
StockMessage::MsgEphemeralTimerEnabled,
|
|
||||||
timer.to_string(),
|
|
||||||
"",
|
|
||||||
from_id,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
60 => {
|
|
||||||
context
|
|
||||||
.stock_system_msg(StockMessage::MsgEphemeralTimerMinute, "", "", from_id)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
61..=3599 => {
|
|
||||||
context
|
|
||||||
.stock_system_msg(
|
|
||||||
StockMessage::MsgEphemeralTimerMinutes,
|
|
||||||
format!("{}", (f64::from(duration) / 6.0).round() / 10.0),
|
|
||||||
"",
|
|
||||||
from_id,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
3600 => {
|
|
||||||
context
|
|
||||||
.stock_system_msg(StockMessage::MsgEphemeralTimerHour, "", "", from_id)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
3600 => MsgEphemeralTimerHour::stock_str(context, from_id).await,
|
||||||
3601..=86399 => {
|
3601..=86399 => {
|
||||||
context
|
MsgEphemeralTimerHours::stock_str(
|
||||||
.stock_system_msg(
|
context,
|
||||||
StockMessage::MsgEphemeralTimerHours,
|
format!("{}", (f64::from(duration) / 360.0).round() / 10.0),
|
||||||
format!("{}", (f64::from(duration) / 360.0).round() / 10.0),
|
from_id,
|
||||||
"",
|
)
|
||||||
from_id,
|
.await
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
86400 => {
|
|
||||||
context
|
|
||||||
.stock_system_msg(StockMessage::MsgEphemeralTimerDay, "", "", from_id)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
86400 => MsgEphemeralTimerDay::stock_str(context, from_id).await,
|
||||||
86401..=604_799 => {
|
86401..=604_799 => {
|
||||||
context
|
MsgEphemeralTimerDays::stock_str(
|
||||||
.stock_system_msg(
|
context,
|
||||||
StockMessage::MsgEphemeralTimerDays,
|
format!("{}", (f64::from(duration) / 8640.0).round() / 10.0),
|
||||||
format!("{}", (f64::from(duration) / 8640.0).round() / 10.0),
|
from_id,
|
||||||
"",
|
)
|
||||||
from_id,
|
.await
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
604_800 => {
|
|
||||||
{ context.stock_system_msg(StockMessage::MsgEphemeralTimerWeek, "", "", from_id) }
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
604_800 => MsgEphemeralTimerWeek::stock_str(context, from_id).await,
|
||||||
_ => {
|
_ => {
|
||||||
context
|
MsgEphemeralTimerWeeks::stock_str(
|
||||||
.stock_system_msg(
|
context,
|
||||||
StockMessage::MsgEphemeralTimerWeeks,
|
format!("{}", (f64::from(duration) / 60480.0).round() / 10.0),
|
||||||
format!("{}", (f64::from(duration) / 60480.0).round() / 10.0),
|
from_id,
|
||||||
"",
|
)
|
||||||
from_id,
|
.await
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -547,36 +519,67 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(&context, Timer::Disabled, 0).await,
|
stock_ephemeral_timer_changed(
|
||||||
"Message deletion timer is disabled."
|
&context,
|
||||||
|
Timer::Enabled { duration: 1 },
|
||||||
|
DC_CONTACT_ID_SELF
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
"Message deletion timer is set to 1 s by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(&context, Timer::Enabled { duration: 1 }, 0).await,
|
stock_ephemeral_timer_changed(
|
||||||
"Message deletion timer is set to 1 s."
|
&context,
|
||||||
|
Timer::Enabled { duration: 30 },
|
||||||
|
DC_CONTACT_ID_SELF
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
"Message deletion timer is set to 30 s by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(&context, Timer::Enabled { duration: 30 }, 0).await,
|
stock_ephemeral_timer_changed(
|
||||||
"Message deletion timer is set to 30 s."
|
&context,
|
||||||
|
Timer::Enabled { duration: 60 },
|
||||||
|
DC_CONTACT_ID_SELF
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
"Message deletion timer is set to 1 minute by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(&context, Timer::Enabled { duration: 60 }, 0).await,
|
stock_ephemeral_timer_changed(
|
||||||
"Message deletion timer is set to 1 minute."
|
&context,
|
||||||
|
Timer::Enabled { duration: 90 },
|
||||||
|
DC_CONTACT_ID_SELF
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
"Message deletion timer is set to 1.5 minutes by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(&context, Timer::Enabled { duration: 90 }, 0).await,
|
stock_ephemeral_timer_changed(
|
||||||
"Message deletion timer is set to 1.5 minutes."
|
&context,
|
||||||
|
Timer::Enabled { duration: 30 * 60 },
|
||||||
|
DC_CONTACT_ID_SELF
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
"Message deletion timer is set to 30 minutes by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(&context, Timer::Enabled { duration: 30 * 60 }, 0).await,
|
stock_ephemeral_timer_changed(
|
||||||
"Message deletion timer is set to 30 minutes."
|
&context,
|
||||||
|
Timer::Enabled { duration: 60 * 60 },
|
||||||
|
DC_CONTACT_ID_SELF
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
"Message deletion timer is set to 1 hour by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(&context, Timer::Enabled { duration: 60 * 60 }, 0).await,
|
stock_ephemeral_timer_changed(
|
||||||
"Message deletion timer is set to 1 hour."
|
&context,
|
||||||
);
|
Timer::Enabled { duration: 5400 },
|
||||||
assert_eq!(
|
DC_CONTACT_ID_SELF
|
||||||
stock_ephemeral_timer_changed(&context, Timer::Enabled { duration: 5400 }, 0).await,
|
)
|
||||||
"Message deletion timer is set to 1.5 hours."
|
.await,
|
||||||
|
"Message deletion timer is set to 1.5 hours by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(
|
stock_ephemeral_timer_changed(
|
||||||
@@ -584,10 +587,10 @@ mod tests {
|
|||||||
Timer::Enabled {
|
Timer::Enabled {
|
||||||
duration: 2 * 60 * 60
|
duration: 2 * 60 * 60
|
||||||
},
|
},
|
||||||
0
|
DC_CONTACT_ID_SELF
|
||||||
)
|
)
|
||||||
.await,
|
.await,
|
||||||
"Message deletion timer is set to 2 hours."
|
"Message deletion timer is set to 2 hours by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(
|
stock_ephemeral_timer_changed(
|
||||||
@@ -595,10 +598,10 @@ mod tests {
|
|||||||
Timer::Enabled {
|
Timer::Enabled {
|
||||||
duration: 24 * 60 * 60
|
duration: 24 * 60 * 60
|
||||||
},
|
},
|
||||||
0
|
DC_CONTACT_ID_SELF
|
||||||
)
|
)
|
||||||
.await,
|
.await,
|
||||||
"Message deletion timer is set to 1 day."
|
"Message deletion timer is set to 1 day by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(
|
stock_ephemeral_timer_changed(
|
||||||
@@ -606,10 +609,10 @@ mod tests {
|
|||||||
Timer::Enabled {
|
Timer::Enabled {
|
||||||
duration: 2 * 24 * 60 * 60
|
duration: 2 * 24 * 60 * 60
|
||||||
},
|
},
|
||||||
0
|
DC_CONTACT_ID_SELF
|
||||||
)
|
)
|
||||||
.await,
|
.await,
|
||||||
"Message deletion timer is set to 2 days."
|
"Message deletion timer is set to 2 days by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(
|
stock_ephemeral_timer_changed(
|
||||||
@@ -617,10 +620,10 @@ mod tests {
|
|||||||
Timer::Enabled {
|
Timer::Enabled {
|
||||||
duration: 7 * 24 * 60 * 60
|
duration: 7 * 24 * 60 * 60
|
||||||
},
|
},
|
||||||
0
|
DC_CONTACT_ID_SELF
|
||||||
)
|
)
|
||||||
.await,
|
.await,
|
||||||
"Message deletion timer is set to 1 week."
|
"Message deletion timer is set to 1 week by me."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stock_ephemeral_timer_changed(
|
stock_ephemeral_timer_changed(
|
||||||
@@ -628,10 +631,10 @@ mod tests {
|
|||||||
Timer::Enabled {
|
Timer::Enabled {
|
||||||
duration: 4 * 7 * 24 * 60 * 60
|
duration: 4 * 7 * 24 * 60 * 60
|
||||||
},
|
},
|
||||||
0
|
DC_CONTACT_ID_SELF
|
||||||
)
|
)
|
||||||
.await,
|
.await,
|
||||||
"Message deletion timer is set to 4 weeks."
|
"Message deletion timer is set to 4 weeks by me."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,17 @@ use async_std::channel::Receiver;
|
|||||||
use async_std::prelude::*;
|
use async_std::prelude::*;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
|
use crate::chat;
|
||||||
|
use crate::config::Config;
|
||||||
use crate::constants::{
|
use crate::constants::{
|
||||||
Chattype, ShowEmails, Viewtype, DC_CONTACT_ID_SELF, DC_FETCH_EXISTING_MSGS_COUNT,
|
Chattype, ShowEmails, Viewtype, DC_CONTACT_ID_SELF, DC_FETCH_EXISTING_MSGS_COUNT,
|
||||||
DC_FOLDERS_CONFIGURED_VERSION, DC_LP_AUTH_OAUTH2,
|
DC_FOLDERS_CONFIGURED_VERSION, DC_LP_AUTH_OAUTH2,
|
||||||
};
|
};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::dc_receive_imf::{from_field_to_contact_id, get_prefetch_parent_message};
|
use crate::dc_receive_imf::{
|
||||||
|
dc_receive_imf_inner, from_field_to_contact_id, get_prefetch_parent_message,
|
||||||
|
};
|
||||||
|
use crate::dc_tools::dc_extract_grpid_from_rfc724_mid;
|
||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
use crate::headerdef::{HeaderDef, HeaderDefMap};
|
use crate::headerdef::{HeaderDef, HeaderDefMap};
|
||||||
use crate::job::{self, Action};
|
use crate::job::{self, Action};
|
||||||
@@ -29,10 +34,8 @@ use crate::mimeparser;
|
|||||||
use crate::oauth2::dc_get_oauth2_access_token;
|
use crate::oauth2::dc_get_oauth2_access_token;
|
||||||
use crate::param::Params;
|
use crate::param::Params;
|
||||||
use crate::provider::Socket;
|
use crate::provider::Socket;
|
||||||
use crate::{
|
use crate::scheduler::InterruptInfo;
|
||||||
chat, dc_tools::dc_extract_grpid_from_rfc724_mid, scheduler::InterruptInfo, stock::StockMessage,
|
use crate::stock::CannotLogin;
|
||||||
};
|
|
||||||
use crate::{config::Config, dc_receive_imf::dc_receive_imf_inner};
|
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
mod idle;
|
mod idle;
|
||||||
@@ -252,9 +255,9 @@ impl Imap {
|
|||||||
|
|
||||||
Err((err, _)) => {
|
Err((err, _)) => {
|
||||||
let imap_user = self.config.lp.user.to_owned();
|
let imap_user = self.config.lp.user.to_owned();
|
||||||
let message = context
|
let message = CannotLogin::stock_str(context, &imap_user)
|
||||||
.stock_string_repl_str(StockMessage::CannotLogin, &imap_user)
|
.await
|
||||||
.await;
|
.to_string();
|
||||||
|
|
||||||
warn!(context, "{} ({})", message, err);
|
warn!(context, "{} ({})", message, err);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ use crate::mimeparser::SystemMessage;
|
|||||||
use crate::param::Param;
|
use crate::param::Param;
|
||||||
use crate::pgp;
|
use crate::pgp;
|
||||||
use crate::sql::{self, Sql};
|
use crate::sql::{self, Sql};
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{AcSetupMsgBody, AcSetupMsgSubject};
|
||||||
use ::pgp::types::KeyTrait;
|
use ::pgp::types::KeyTrait;
|
||||||
use async_tar::Archive;
|
use async_tar::Archive;
|
||||||
|
|
||||||
@@ -275,8 +275,8 @@ pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result<St
|
|||||||
);
|
);
|
||||||
let pgp_msg = encr.replace("-----BEGIN PGP MESSAGE-----", &replacement);
|
let pgp_msg = encr.replace("-----BEGIN PGP MESSAGE-----", &replacement);
|
||||||
|
|
||||||
let msg_subj = context.stock_str(StockMessage::AcSetupMsgSubject).await;
|
let msg_subj = AcSetupMsgSubject::stock_str(context).await;
|
||||||
let msg_body = context.stock_str(StockMessage::AcSetupMsgBody).await;
|
let msg_body = AcSetupMsgBody::stock_str(context).await;
|
||||||
let msg_body_html = msg_body.replace("\r", "").replace("\n", "<br>");
|
let msg_body_html = msg_body.replace("\r", "").replace("\n", "<br>");
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
concat!(
|
concat!(
|
||||||
@@ -902,8 +902,11 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::pgp::{split_armored_data, HEADER_AUTOCRYPT, HEADER_SETUPCODE};
|
use crate::pgp::{split_armored_data, HEADER_AUTOCRYPT, HEADER_SETUPCODE};
|
||||||
|
use crate::stock::StockMessage;
|
||||||
use crate::test_utils::{alice_keypair, TestContext};
|
use crate::test_utils::{alice_keypair, TestContext};
|
||||||
|
|
||||||
use ::pgp::armor::BlockType;
|
use ::pgp::armor::BlockType;
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::job::{self, Job};
|
|||||||
use crate::message::{Message, MsgId};
|
use crate::message::{Message, MsgId};
|
||||||
use crate::mimeparser::SystemMessage;
|
use crate::mimeparser::SystemMessage;
|
||||||
use crate::param::Params;
|
use crate::param::Params;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{MsgLocationDisabled, MsgLocationEnabled};
|
||||||
|
|
||||||
/// Location record
|
/// Location record
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
@@ -212,19 +212,13 @@ pub async fn send_locations_to_chat(context: &Context, chat_id: ChatId, seconds:
|
|||||||
{
|
{
|
||||||
if 0 != seconds && !is_sending_locations_before {
|
if 0 != seconds && !is_sending_locations_before {
|
||||||
let mut msg = Message::new(Viewtype::Text);
|
let mut msg = Message::new(Viewtype::Text);
|
||||||
msg.text = Some(
|
msg.text = Some(MsgLocationEnabled::stock_str(context).await.to_string());
|
||||||
context
|
|
||||||
.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", 0)
|
|
||||||
.await,
|
|
||||||
);
|
|
||||||
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 = context
|
let stock_str = MsgLocationDisabled::stock_str(context).await;
|
||||||
.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0)
|
|
||||||
.await;
|
|
||||||
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));
|
||||||
@@ -716,9 +710,7 @@ pub(crate) async fn job_maybe_send_locations_ended(
|
|||||||
paramsv![chat_id],
|
paramsv![chat_id],
|
||||||
).await);
|
).await);
|
||||||
|
|
||||||
let stock_str = context
|
let stock_str = MsgLocationDisabled::stock_str(context).await;
|
||||||
.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0)
|
|
||||||
.await;
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ use crate::lot::{Lot, LotState, Meaning};
|
|||||||
use crate::mimeparser::{FailureReport, SystemMessage};
|
use crate::mimeparser::{FailureReport, SystemMessage};
|
||||||
use crate::param::{Param, Params};
|
use crate::param::{Param, Params};
|
||||||
use crate::pgp::split_armored_data;
|
use crate::pgp::split_armored_data;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{
|
||||||
|
AcSetupMsgSubject, Audio, Draft, FailedSendingTo, File, Gif, Image, Location, ReplyNoun,
|
||||||
|
SelfMsg, Sticker, Video, VideochatInvitation, VoiceMessage,
|
||||||
|
};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
// In practice, the user additionally cuts the string themselves
|
// In practice, the user additionally cuts the string themselves
|
||||||
@@ -1055,26 +1058,14 @@ impl Lot {
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
) {
|
) {
|
||||||
if msg.state == MessageState::OutDraft {
|
if msg.state == MessageState::OutDraft {
|
||||||
self.text1 = Some(
|
self.text1 = Some(Draft::stock_str(context).await.to_owned().into());
|
||||||
context
|
|
||||||
.stock_str(StockMessage::Draft)
|
|
||||||
.await
|
|
||||||
.to_owned()
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
self.text1_meaning = Meaning::Text1Draft;
|
self.text1_meaning = Meaning::Text1Draft;
|
||||||
} else if msg.from_id == DC_CONTACT_ID_SELF {
|
} else if msg.from_id == DC_CONTACT_ID_SELF {
|
||||||
if msg.is_info() || chat.is_self_talk() {
|
if msg.is_info() || chat.is_self_talk() {
|
||||||
self.text1 = None;
|
self.text1 = None;
|
||||||
self.text1_meaning = Meaning::None;
|
self.text1_meaning = Meaning::None;
|
||||||
} else {
|
} else {
|
||||||
self.text1 = Some(
|
self.text1 = Some(SelfMsg::stock_str(context).await.to_owned().into());
|
||||||
context
|
|
||||||
.stock_str(StockMessage::SelfMsg)
|
|
||||||
.await
|
|
||||||
.to_owned()
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
self.text1_meaning = Meaning::Text1Self;
|
self.text1_meaning = Meaning::Text1Self;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1107,10 +1098,7 @@ impl Lot {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
if text2.is_empty() && msg.quoted_text().is_some() {
|
if text2.is_empty() && msg.quoted_text().is_some() {
|
||||||
text2 = context
|
text2 = ReplyNoun::stock_str(context).await.into_owned()
|
||||||
.stock_str(StockMessage::ReplyNoun)
|
|
||||||
.await
|
|
||||||
.into_owned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.text2 = Some(text2);
|
self.text2 = Some(text2);
|
||||||
@@ -1562,21 +1550,15 @@ pub async fn get_summarytext_by_raw(
|
|||||||
) -> String {
|
) -> String {
|
||||||
let mut append_text = true;
|
let mut append_text = true;
|
||||||
let prefix = match viewtype {
|
let prefix = match viewtype {
|
||||||
Viewtype::Image => context.stock_str(StockMessage::Image).await.into_owned(),
|
Viewtype::Image => Image::stock_str(context).await.into_owned(),
|
||||||
Viewtype::Gif => context.stock_str(StockMessage::Gif).await.into_owned(),
|
Viewtype::Gif => Gif::stock_str(context).await.into_owned(),
|
||||||
Viewtype::Sticker => context.stock_str(StockMessage::Sticker).await.into_owned(),
|
Viewtype::Sticker => Sticker::stock_str(context).await.into_owned(),
|
||||||
Viewtype::Video => context.stock_str(StockMessage::Video).await.into_owned(),
|
Viewtype::Video => Video::stock_str(context).await.into_owned(),
|
||||||
Viewtype::Voice => context
|
Viewtype::Voice => VoiceMessage::stock_str(context).await.into_owned(),
|
||||||
.stock_str(StockMessage::VoiceMessage)
|
|
||||||
.await
|
|
||||||
.into_owned(),
|
|
||||||
Viewtype::Audio | Viewtype::File => {
|
Viewtype::Audio | Viewtype::File => {
|
||||||
if param.get_cmd() == SystemMessage::AutocryptSetupMessage {
|
if param.get_cmd() == SystemMessage::AutocryptSetupMessage {
|
||||||
append_text = false;
|
append_text = false;
|
||||||
context
|
AcSetupMsgSubject::stock_str(context).await.to_string()
|
||||||
.stock_str(StockMessage::AcSetupMsgSubject)
|
|
||||||
.await
|
|
||||||
.to_string()
|
|
||||||
} else {
|
} else {
|
||||||
let file_name: String = param
|
let file_name: String = param
|
||||||
.get_path(Param::File, context)
|
.get_path(Param::File, context)
|
||||||
@@ -1586,29 +1568,24 @@ pub async fn get_summarytext_by_raw(
|
|||||||
.map(|fname| fname.to_string_lossy().into_owned())
|
.map(|fname| fname.to_string_lossy().into_owned())
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| String::from("ErrFileName"));
|
.unwrap_or_else(|| String::from("ErrFileName"));
|
||||||
let label = context
|
let label = if viewtype == Viewtype::Audio {
|
||||||
.stock_str(if viewtype == Viewtype::Audio {
|
Audio::stock_str(context).await
|
||||||
StockMessage::Audio
|
} else {
|
||||||
} else {
|
File::stock_str(context).await
|
||||||
StockMessage::File
|
};
|
||||||
})
|
|
||||||
.await;
|
|
||||||
format!("{} – {}", label, file_name)
|
format!("{} – {}", label, file_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Viewtype::VideochatInvitation => {
|
Viewtype::VideochatInvitation => {
|
||||||
append_text = false;
|
append_text = false;
|
||||||
context
|
VideochatInvitation::stock_str(context).await.into_owned()
|
||||||
.stock_str(StockMessage::VideochatInvitation)
|
|
||||||
.await
|
|
||||||
.into_owned()
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if param.get_cmd() != SystemMessage::LocationOnly {
|
if param.get_cmd() != SystemMessage::LocationOnly {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else {
|
} else {
|
||||||
append_text = false;
|
append_text = false;
|
||||||
context.stock_str(StockMessage::Location).await.to_string()
|
Location::stock_str(context).await.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1865,13 +1842,9 @@ async fn ndn_maybe_add_info_msg(
|
|||||||
Error::msg("ndn_maybe_add_info_msg: Contact ID not found")
|
Error::msg("ndn_maybe_add_info_msg: Contact ID not found")
|
||||||
})?;
|
})?;
|
||||||
let contact = Contact::load_from_db(context, contact_id).await?;
|
let contact = Contact::load_from_db(context, contact_id).await?;
|
||||||
// Tell the user which of the recipients failed if we know that (because in a group, this might otherwise be unclear)
|
// Tell the user which of the recipients failed if we know that (because in
|
||||||
let text = context
|
// a group, this might otherwise be unclear)
|
||||||
.stock_string_repl_str(
|
let text = FailedSendingTo::stock_str(context, contact.get_display_name()).await;
|
||||||
StockMessage::FailedSendingTo,
|
|
||||||
contact.get_display_name(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
chat::add_info_msg(context, chat_id, text).await;
|
chat::add_info_msg(context, chat_id, text).await;
|
||||||
context.emit_event(EventType::ChatModified(chat_id));
|
context.emit_event(EventType::ChatModified(chat_id));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ use crate::mimeparser::SystemMessage;
|
|||||||
use crate::param::Param;
|
use crate::param::Param;
|
||||||
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
|
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
|
||||||
use crate::simplify::escape_message_footer_marks;
|
use crate::simplify::escape_message_footer_marks;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{
|
||||||
|
AcSetupMsgBody, AcSetupMsgSubject, EncryptedMsg, ReadRcpt, ReadRcptMailBody, StatusLine,
|
||||||
|
SubjectForNewContact,
|
||||||
|
};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
// attachments of 25 mb brutto should work on the majority of providers
|
// attachments of 25 mb brutto should work on the majority of providers
|
||||||
@@ -139,10 +142,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let default_str = context
|
let default_str = StatusLine::stock_str(context).await.to_string();
|
||||||
.stock_str(StockMessage::StatusLine)
|
|
||||||
.await
|
|
||||||
.to_string();
|
|
||||||
let factory = MimeFactory {
|
let factory = MimeFactory {
|
||||||
from_addr,
|
from_addr,
|
||||||
from_displayname,
|
from_displayname,
|
||||||
@@ -180,10 +180,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
.get_config(Config::Displayname)
|
.get_config(Config::Displayname)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let default_str = context
|
let default_str = StatusLine::stock_str(context).await.to_string();
|
||||||
.stock_str(StockMessage::StatusLine)
|
|
||||||
.await
|
|
||||||
.to_string();
|
|
||||||
let selfstatus = context
|
let selfstatus = context
|
||||||
.get_config(Config::Selfstatus)
|
.get_config(Config::Selfstatus)
|
||||||
.await
|
.await
|
||||||
@@ -345,8 +342,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
match self.loaded {
|
match self.loaded {
|
||||||
Loaded::Message { ref chat } => {
|
Loaded::Message { ref chat } => {
|
||||||
if self.msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage {
|
if self.msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage {
|
||||||
self.context
|
AcSetupMsgSubject::stock_str(self.context)
|
||||||
.stock_str(StockMessage::AcSetupMsgSubject)
|
|
||||||
.await
|
.await
|
||||||
.into_owned()
|
.into_owned()
|
||||||
} else if chat.typ == Chattype::Group {
|
} else if chat.typ == Chattype::Group {
|
||||||
@@ -390,21 +386,14 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.context
|
SubjectForNewContact::stock_str(self.context, self_name)
|
||||||
.stock_string_repl_str(
|
|
||||||
StockMessage::SubjectForNewContact,
|
|
||||||
self_name,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loaded::MDN { .. } => self
|
Loaded::MDN { .. } => ReadRcpt::stock_str(self.context).await.into_owned(),
|
||||||
.context
|
|
||||||
.stock_str(StockMessage::ReadRcpt)
|
|
||||||
.await
|
|
||||||
.into_owned(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,12 +797,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
unprotected_headers
|
unprotected_headers
|
||||||
.push(Header::new("Autocrypt-Setup-Message".into(), "v1".into()));
|
.push(Header::new("Autocrypt-Setup-Message".into(), "v1".into()));
|
||||||
|
|
||||||
placeholdertext = Some(
|
placeholdertext = Some(AcSetupMsgBody::stock_str(self.context).await.to_string());
|
||||||
self.context
|
|
||||||
.stock_str(StockMessage::AcSetupMsgBody)
|
|
||||||
.await
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
SystemMessage::SecurejoinMessage => {
|
SystemMessage::SecurejoinMessage => {
|
||||||
let msg = &self.msg;
|
let msg = &self.msg;
|
||||||
@@ -1071,17 +1055,11 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
|
|||||||
.get_int(Param::GuaranteeE2ee)
|
.get_int(Param::GuaranteeE2ee)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
self.context
|
EncryptedMsg::stock_str(self.context).await.into_owned()
|
||||||
.stock_str(StockMessage::EncryptedMsg)
|
|
||||||
.await
|
|
||||||
.into_owned()
|
|
||||||
} else {
|
} else {
|
||||||
self.msg.get_summarytext(self.context, 32).await
|
self.msg.get_summarytext(self.context, 32).await
|
||||||
};
|
};
|
||||||
let p2 = self
|
let p2 = ReadRcptMailBody::stock_str(self.context, p1).await;
|
||||||
.context
|
|
||||||
.stock_string_repl_str(StockMessage::ReadRcptMailBody, p1)
|
|
||||||
.await;
|
|
||||||
let message_text = format!("{}\r\n", p2);
|
let message_text = format!("{}\r\n", p2);
|
||||||
message = message.child(
|
message = message.child(
|
||||||
PartBuilder::new()
|
PartBuilder::new()
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ use std::future::Future;
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
use charset::Charset;
|
||||||
use deltachat_derive::{FromSql, ToSql};
|
use deltachat_derive::{FromSql, ToSql};
|
||||||
use lettre_email::mime::{self, Mime};
|
use lettre_email::mime::{self, Mime};
|
||||||
use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo};
|
use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use percent_encoding::percent_decode_str;
|
||||||
|
|
||||||
use crate::aheader::Aheader;
|
use crate::aheader::Aheader;
|
||||||
use crate::blob::BlobObject;
|
use crate::blob::BlobObject;
|
||||||
@@ -25,9 +27,7 @@ use crate::message;
|
|||||||
use crate::param::{Param, Params};
|
use crate::param::{Param, Params};
|
||||||
use crate::peerstate::Peerstate;
|
use crate::peerstate::Peerstate;
|
||||||
use crate::simplify::simplify;
|
use crate::simplify::simplify;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::CantDecryptMsgBody;
|
||||||
use charset::Charset;
|
|
||||||
use percent_encoding::percent_decode_str;
|
|
||||||
|
|
||||||
/// A parsed MIME message.
|
/// A parsed MIME message.
|
||||||
///
|
///
|
||||||
@@ -629,7 +629,7 @@ impl MimeMessage {
|
|||||||
// we currently do not try to decrypt non-autocrypt messages
|
// we currently do not try to decrypt non-autocrypt messages
|
||||||
// at all. If we see an encrypted part, we set
|
// at all. If we see an encrypted part, we set
|
||||||
// decrypting_failed.
|
// decrypting_failed.
|
||||||
let msg_body = context.stock_str(StockMessage::CantDecryptMsgBody).await;
|
let msg_body = CantDecryptMsgBody::stock_str(context).await;
|
||||||
let txt = format!("[{}]", msg_body);
|
let txt = format!("[{}]", msg_body);
|
||||||
|
|
||||||
let part = Part {
|
let part = Part {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use crate::context::Context;
|
|||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
use crate::key::{DcKey, Fingerprint, SignedPublicKey};
|
use crate::key::{DcKey, Fingerprint, SignedPublicKey};
|
||||||
use crate::sql::Sql;
|
use crate::sql::Sql;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::ContactSetupChanged;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PeerstateKeyType {
|
pub enum PeerstateKeyType {
|
||||||
@@ -281,9 +281,7 @@ impl<'a> Peerstate<'a> {
|
|||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let msg = context
|
let msg = ContactSetupChanged::stock_str(context, self.addr.clone()).await;
|
||||||
.stock_string_repl_str(StockMessage::ContactSetupChanged, self.addr.clone())
|
|
||||||
.await;
|
|
||||||
|
|
||||||
chat::add_info_msg(context, contact_chat_id, msg).await;
|
chat::add_info_msg(context, contact_chat_id, msg).await;
|
||||||
emit_event!(context, EventType::ChatModified(contact_chat_id));
|
emit_event!(context, EventType::ChatModified(contact_chat_id));
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use crate::param::Param;
|
|||||||
use crate::peerstate::{Peerstate, PeerstateKeyType, PeerstateVerifiedStatus, ToSave};
|
use crate::peerstate::{Peerstate, PeerstateKeyType, PeerstateVerifiedStatus, ToSave};
|
||||||
use crate::qr::check_qr;
|
use crate::qr::check_qr;
|
||||||
use crate::sql;
|
use crate::sql;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::{ContactNotVerified, ContactVerified};
|
||||||
use crate::token;
|
use crate::token;
|
||||||
|
|
||||||
mod bobstate;
|
mod bobstate;
|
||||||
@@ -822,10 +822,8 @@ async fn secure_connection_established(context: &Context, contact_chat_id: ChatI
|
|||||||
} else {
|
} else {
|
||||||
"?"
|
"?"
|
||||||
};
|
};
|
||||||
let msg = context
|
let msg = ContactVerified::stock_str(context, addr).await;
|
||||||
.stock_string_repl_str(StockMessage::ContactVerified, addr)
|
chat::add_info_msg(context, contact_chat_id, msg).await;
|
||||||
.await;
|
|
||||||
chat::add_info_msg(context, contact_chat_id, &msg).await;
|
|
||||||
emit_event!(context, EventType::ChatModified(contact_chat_id));
|
emit_event!(context, EventType::ChatModified(contact_chat_id));
|
||||||
info!(context, "StockMessage::ContactVerified posted to 1:1 chat");
|
info!(context, "StockMessage::ContactVerified posted to 1:1 chat");
|
||||||
}
|
}
|
||||||
@@ -837,16 +835,15 @@ async fn could_not_establish_secure_connection(
|
|||||||
) {
|
) {
|
||||||
let contact_id = chat_id_2_contact_id(context, contact_chat_id).await;
|
let contact_id = chat_id_2_contact_id(context, contact_chat_id).await;
|
||||||
let contact = Contact::get_by_id(context, contact_id).await;
|
let contact = Contact::get_by_id(context, contact_id).await;
|
||||||
let msg = context
|
let msg = ContactNotVerified::stock_str(
|
||||||
.stock_string_repl_str(
|
context,
|
||||||
StockMessage::ContactNotVerified,
|
if let Ok(ref contact) = contact {
|
||||||
if let Ok(ref contact) = contact {
|
contact.get_addr()
|
||||||
contact.get_addr()
|
} else {
|
||||||
} else {
|
"?"
|
||||||
"?"
|
},
|
||||||
},
|
)
|
||||||
)
|
.await;
|
||||||
.await;
|
|
||||||
|
|
||||||
chat::add_info_msg(context, contact_chat_id, &msg).await;
|
chat::add_info_msg(context, contact_chat_id, &msg).await;
|
||||||
error!(
|
error!(
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use crate::events::EventType;
|
|||||||
use crate::login_param::{dc_build_tls, CertificateChecks, LoginParam, ServerLoginParam};
|
use crate::login_param::{dc_build_tls, CertificateChecks, LoginParam, ServerLoginParam};
|
||||||
use crate::oauth2::dc_get_oauth2_access_token;
|
use crate::oauth2::dc_get_oauth2_access_token;
|
||||||
use crate::provider::Socket;
|
use crate::provider::Socket;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::ServerResponse;
|
||||||
|
|
||||||
/// SMTP write and read timeout in seconds.
|
/// SMTP write and read timeout in seconds.
|
||||||
const SMTP_TIMEOUT: u64 = 30;
|
const SMTP_TIMEOUT: u64 = 30;
|
||||||
@@ -111,13 +111,13 @@ impl Smtp {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
if let Err(ref err) = res {
|
if let Err(ref err) = res {
|
||||||
let message = context
|
let message = ServerResponse::stock_str(
|
||||||
.stock_string_repl_str2(
|
context,
|
||||||
StockMessage::ServerResponse,
|
format!("SMTP {}:{}", lp.smtp.server, lp.smtp.port),
|
||||||
format!("SMTP {}:{}", lp.smtp.server, lp.smtp.port),
|
err.to_string(),
|
||||||
err.to_string(),
|
)
|
||||||
)
|
.await
|
||||||
.await;
|
.to_string();
|
||||||
|
|
||||||
context.emit_event(EventType::ErrorNetwork(message));
|
context.emit_event(EventType::ErrorNetwork(message));
|
||||||
};
|
};
|
||||||
|
|||||||
20
src/sql.rs
20
src/sql.rs
@@ -10,22 +10,19 @@ use std::time::Duration;
|
|||||||
use anyhow::format_err;
|
use anyhow::format_err;
|
||||||
use rusqlite::{Connection, Error as SqlError, OpenFlags};
|
use rusqlite::{Connection, Error as SqlError, OpenFlags};
|
||||||
|
|
||||||
use crate::chat::add_device_msg;
|
use crate::chat::{add_device_msg, update_device_icon, update_saved_messages_icon};
|
||||||
|
use crate::config::Config;
|
||||||
use crate::config::Config::DeleteServerAfter;
|
use crate::config::Config::DeleteServerAfter;
|
||||||
use crate::constants::{ShowEmails, DC_CHAT_ID_TRASH};
|
use crate::constants::{ShowEmails, Viewtype, DC_CHAT_ID_TRASH};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::dc_tools::{dc_delete_file, time, EmailAddress};
|
use crate::dc_tools::{dc_delete_file, time, EmailAddress};
|
||||||
use crate::ephemeral::start_ephemeral_timers;
|
use crate::ephemeral::start_ephemeral_timers;
|
||||||
use crate::imap;
|
use crate::imap;
|
||||||
|
use crate::message::Message;
|
||||||
use crate::param::{Param, Params};
|
use crate::param::{Param, Params};
|
||||||
use crate::peerstate::Peerstate;
|
use crate::peerstate::Peerstate;
|
||||||
use crate::provider::get_provider_by_domain;
|
use crate::provider::get_provider_by_domain;
|
||||||
use crate::stock::StockMessage;
|
use crate::stock::DeleteServerTurnedOff;
|
||||||
use crate::{
|
|
||||||
chat::{update_device_icon, update_saved_messages_icon},
|
|
||||||
config::Config,
|
|
||||||
};
|
|
||||||
use crate::{constants::Viewtype, message::Message};
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! paramsv {
|
macro_rules! paramsv {
|
||||||
@@ -1544,12 +1541,7 @@ CREATE INDEX devmsglabels_index1 ON devmsglabels (label);
|
|||||||
// So, for people who have delete_server enabled, disable it and add a hint to the devicechat:
|
// So, for people who have delete_server enabled, disable it and add a hint to the devicechat:
|
||||||
if context.get_config_delete_server_after().await.is_some() {
|
if context.get_config_delete_server_after().await.is_some() {
|
||||||
let mut msg = Message::new(Viewtype::Text);
|
let mut msg = Message::new(Viewtype::Text);
|
||||||
msg.text = Some(
|
msg.text = Some(DeleteServerTurnedOff::stock_str(context).await.into());
|
||||||
context
|
|
||||||
.stock_str(StockMessage::DeleteServerTurnedOff)
|
|
||||||
.await
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
add_device_msg(context, None, Some(&mut msg)).await?;
|
add_device_msg(context, None, Some(&mut msg)).await?;
|
||||||
context.set_config(DeleteServerAfter, Some("0")).await?;
|
context.set_config(DeleteServerAfter, Some("0")).await?;
|
||||||
}
|
}
|
||||||
|
|||||||
1347
src/stock.rs
1347
src/stock.rs
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user