mirror of
https://github.com/chatmail/core.git
synced 2026-07-15 07:23:12 +03:00
feat: a way to add a device message as InNoticed
This is useful for adding the same device message on multiple accounts,
which is what we do at least on Desktop currently:
c50896f1d5/packages/frontend/src/deviceMessages.ts (L35-L44).
The problem on desktop is that we then have to `rpc.marknoticedChat()`
so that the user isn't forced to read the same message
on all their accounts:
https://github.com/deltachat/deltachat-desktop/issues/3934.
However, that, in turn, is now causing problems
in our notification clearing logic: marking a chat as noticed
is supposed to remove the per-account "N messages in M chats"
notification, but we only want to do that when the user
actually reads a message on the account and,
whereas we do this `marknoticedChat()` for device messages
on app startup for all accounts. See the TODO in
https://github.com/deltachat/deltachat-desktop/pull/6154.
This commit is contained in:
@@ -53,7 +53,7 @@ use types::chat::FullChat;
|
||||
use types::contact::{ContactObject, VcardContact};
|
||||
use types::events::Event;
|
||||
use types::http::HttpResponse;
|
||||
use types::message::{MessageData, MessageObject, MessageReadReceipt};
|
||||
use types::message::{DeviceMessageData, MessageData, MessageObject, MessageReadReceipt};
|
||||
use types::notify_state::JsonrpcNotifyState;
|
||||
use types::provider_info::ProviderInfo;
|
||||
use types::reactions::JsonrpcReactions;
|
||||
@@ -1229,18 +1229,27 @@ impl CommandApi {
|
||||
&self,
|
||||
account_id: u32,
|
||||
label: String,
|
||||
msg: Option<MessageData>,
|
||||
msg: Option<DeviceMessageData>,
|
||||
) -> Result<Option<u32>> {
|
||||
let ctx = self.get_context(account_id).await?;
|
||||
if let Some(msg) = msg {
|
||||
let mut message = msg.create_message(&ctx).await?;
|
||||
let message_id =
|
||||
deltachat::chat::add_device_msg(&ctx, Some(&label), Some(&mut message)).await?;
|
||||
let mut message = msg.message_data.create_message(&ctx).await?;
|
||||
if let Some(state) = msg.message_state {
|
||||
deltachat::chat::set_device_msg_state(&mut message, state.into());
|
||||
}
|
||||
let message_id = deltachat::chat::add_device_msg_with_importance(
|
||||
&ctx,
|
||||
Some(&label),
|
||||
Some(&mut message),
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
if !message_id.is_unset() {
|
||||
return Ok(Some(message_id.to_u32()));
|
||||
}
|
||||
} else {
|
||||
deltachat::chat::add_device_msg(&ctx, Some(&label), None).await?;
|
||||
deltachat::chat::add_device_msg_with_importance(&ctx, Some(&label), None, false)
|
||||
.await?;
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@@ -661,6 +661,42 @@ impl MessageData {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeDef, schemars::JsonSchema)]
|
||||
#[repr(u32)]
|
||||
pub enum DeviceMessageState {
|
||||
// Variants that are not really wanted for device messages are omitted,
|
||||
// to avoid misuse.
|
||||
|
||||
// Undefined,
|
||||
InFresh,
|
||||
InNoticed,
|
||||
// InSeen,
|
||||
// OutDraft,
|
||||
// OutPending,
|
||||
// OutFailed,
|
||||
// OutDelivered,
|
||||
// OutMdnRcvd,
|
||||
}
|
||||
|
||||
impl From<DeviceMessageState> for deltachat::message::MessageState {
|
||||
fn from(message_state: DeviceMessageState) -> Self {
|
||||
use deltachat::message::MessageState;
|
||||
match message_state {
|
||||
DeviceMessageState::InFresh => MessageState::InFresh,
|
||||
DeviceMessageState::InNoticed => MessageState::InNoticed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeDef, schemars::JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DeviceMessageData {
|
||||
#[serde(flatten)]
|
||||
pub message_data: MessageData,
|
||||
#[serde(default)]
|
||||
pub message_state: Option<DeviceMessageState>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MessageReadReceipt {
|
||||
|
||||
16
src/chat.rs
16
src/chat.rs
@@ -4810,10 +4810,20 @@ pub(crate) async fn get_chat_id_by_grpid(
|
||||
.await
|
||||
}
|
||||
|
||||
/// Intended to be used only for messages passed to
|
||||
/// [`add_device_msg_with_importance`].
|
||||
pub fn set_device_msg_state(msg: &mut Message, state: MessageState) {
|
||||
msg.state = state;
|
||||
}
|
||||
|
||||
/// Adds a message to device chat.
|
||||
///
|
||||
/// Optional `label` can be provided to ensure that message is added only once.
|
||||
/// If `important` is true, a notification will be sent.
|
||||
///
|
||||
/// If message state is [`MessageState::Undefined`],
|
||||
/// the message will be added to the DB as [`MessageState::InFresh`].
|
||||
/// To set message state, you may utilize [`set_device_msg_state`].
|
||||
#[expect(clippy::arithmetic_side_effects)]
|
||||
pub async fn add_device_msg_with_importance(
|
||||
context: &Context,
|
||||
@@ -4850,7 +4860,11 @@ pub async fn add_device_msg_with_importance(
|
||||
msg.timestamp_sort = last_msg_time + 1;
|
||||
}
|
||||
prepare_msg_blob(context, msg).await?;
|
||||
let state = MessageState::InFresh;
|
||||
let state = if msg.state == MessageState::Undefined {
|
||||
MessageState::InFresh
|
||||
} else {
|
||||
msg.state
|
||||
};
|
||||
let row_id = context
|
||||
.sql
|
||||
.insert(
|
||||
|
||||
@@ -854,6 +854,7 @@ async fn test_add_device_msg_unlabelled() {
|
||||
|
||||
// add two device-messages
|
||||
let mut msg1 = Message::new_text("first message".to_string());
|
||||
msg1.state = MessageState::InNoticed;
|
||||
let msg1_id = add_device_msg(&t, None, Some(&mut msg1)).await;
|
||||
assert!(msg1_id.is_ok());
|
||||
|
||||
@@ -869,12 +870,14 @@ async fn test_add_device_msg_unlabelled() {
|
||||
assert_eq!(msg1.text, "first message");
|
||||
assert_eq!(msg1.from_id, ContactId::DEVICE);
|
||||
assert_eq!(msg1.to_id, ContactId::SELF);
|
||||
assert_eq!(msg1.get_state(), MessageState::InNoticed);
|
||||
assert!(!msg1.is_info());
|
||||
|
||||
let msg2 = message::Message::load_from_db(&t, msg2_id.unwrap()).await;
|
||||
assert!(msg2.is_ok());
|
||||
let msg2 = msg2.unwrap();
|
||||
assert_eq!(msg2.text, "second message");
|
||||
assert_eq!(msg2.get_state(), MessageState::InFresh);
|
||||
|
||||
// check device chat
|
||||
assert_eq!(msg2.chat_id.get_msg_cnt(&t).await.unwrap(), 2);
|
||||
|
||||
Reference in New Issue
Block a user