diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index f24de72ca..e9980296c 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -1112,8 +1112,10 @@ void dc_set_draft (dc_context_t* context, uint32_t ch * If you pass NULL here, the message is added unconditionally. * @param msg Message to be added to the device-chat. * The message appears to the user as an incoming message. - * @return The ID of the added message, - * if the message was already added or skipped before or on errors, 0 is returned. + * If you pass NULL here, only the given label will be added + * and block adding messages with that label in the future. + * @return The ID of the just added message, + * if the message was already added or no message to add is given, 0 is returned. * * Example: * ~~~ @@ -1126,7 +1128,7 @@ void dc_set_draft (dc_context_t* context, uint32_t ch * if (dc_add_device_msg(context, "welcome", welcome_msg)) { * // do not add the changelog on a new installations - * // not now and not when this code is executed again - * dc_skip_device_msg(context, "update-123"); + * dc_add_device_msg(context, "update-123", NULL); * } else { * // welcome message was not added now, this is an oder installation, * // add a changelog @@ -1138,35 +1140,14 @@ uint32_t dc_add_device_msg (dc_context_t* context, const char* /** - * Skip a device-message permanently. - * Subsequent calls to dc_add_device_msg() with the same label - * won't add the device-message then. - * This might be handy if you want to add - * eg. different messages for first-install and updates. - * - * @memberof dc_context_t - * @param context The context as created by dc_context_new(). - * @param label A unique name for the message to skip. - * The label is typically not displayed to the user and - * must be created from the characters `A-Z`, `a-z`, `0-9`, `_` or `-`. - * If a message with that label already exist, - * nothing happens. - * @return None. - */ -void dc_skip_device_msg (dc_context_t* context, const char* label); - - - -/** - * Check if a device-message was ever added or skipped. - * Device-messages can be added or skipped - * using dc_add_device_msg() or dc_skip_device_msg(). + * Check if a device-message with a given label was ever added. + * Device-messages can be added dc_add_device_msg(). * * @memberof dc_context_t * @param context The context as created by dc_context_new(). * @param label Label of the message to check. - * @return 1=A message with this label was added or skipped at some point, - * 0=A message with this label was never added nor skipped. + * @return 1=A message with this label was added at some point, + * 0=A message with this label was never added. */ int dc_has_device_msg (dc_context_t* context, const char* label); diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 37062f422..b68d408e6 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -817,18 +817,23 @@ pub unsafe extern "C" fn dc_add_device_msg( label: *const libc::c_char, msg: *mut dc_msg_t, ) -> u32 { - if context.is_null() || label.is_null() || msg.is_null() { + if context.is_null() || (label.is_null() && msg.is_null()) { eprintln!("ignoring careless call to dc_add_device_msg()"); return 0; } let ffi_context = &mut *context; - let ffi_msg = &mut *msg; + let msg = if msg.is_null() { + None + } else { + let ffi_msg: &mut MessageWrapper = &mut *msg; + Some(&mut ffi_msg.message) + }; ffi_context .with_inner(|ctx| { chat::add_device_msg( ctx, to_opt_string_lossy(label).as_ref().map(|x| x.as_str()), - &mut ffi_msg.message, + msg, ) .unwrap_or_log_default(ctx, "Failed to add device message") }) @@ -836,24 +841,6 @@ pub unsafe extern "C" fn dc_add_device_msg( .unwrap_or(0) } -#[no_mangle] -pub unsafe extern "C" fn dc_skip_device_msg( - context: *mut dc_context_t, - label: *const libc::c_char, -) { - if context.is_null() || label.is_null() { - eprintln!("ignoring careless call to dc_skip_device_msg()"); - return; - } - let ffi_context = &mut *context; - ffi_context - .with_inner(|ctx| { - chat::skip_device_msg(ctx, &to_string_lossy(label)) - .unwrap_or_log_default(ctx, "Failed to skip device message") - }) - .unwrap_or(()) -} - #[no_mangle] pub unsafe extern "C" fn dc_has_device_msg( context: *mut dc_context_t, diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 09cd3c3cf..4656b1dd3 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -837,7 +837,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E ); let mut msg = Message::new(Viewtype::Text); msg.set_text(Some(arg1.to_string())); - chat::add_device_msg(context, None, &mut msg)?; + chat::add_device_msg(context, None, Some(&mut msg))?; } "listmedia" => { ensure!(sel_chat.is_some(), "No chat selected."); diff --git a/src/chat.rs b/src/chat.rs index d452c2058..ab2fdaed4 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1955,45 +1955,53 @@ pub fn get_chat_id_by_grpid(context: &Context, grpid: impl AsRef) -> (u32, pub fn add_device_msg( context: &Context, label: Option<&str>, - msg: &mut Message, + msg: Option<&mut Message>, ) -> Result { + ensure!( + label.is_some() || msg.is_some(), + "device-messages need label, msg or both" + ); let (chat_id, _blocked) = create_or_lookup_by_contact_id(context, DC_CONTACT_ID_DEVICE, Blocked::Not)?; + let mut msg_id = MsgId::new_unset(); - // if the device message is labeled and was ever added, do nothing if let Some(label) = label { if has_device_msg(context, label)? { info!(context, "device-message {} already added", label); - return Ok(MsgId::new_unset()); + return Ok(msg_id); } } - // insert the device message - let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device"); - prepare_msg_blob(context, msg)?; - unarchive(context, chat_id)?; + if let Some(msg) = msg { + let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device"); + prepare_msg_blob(context, msg)?; + unarchive(context, chat_id)?; - context.sql.execute( - "INSERT INTO msgs (chat_id,from_id,to_id, timestamp,type,state, txt,param,rfc724_mid) \ - VALUES (?,?,?, ?,?,?, ?,?,?);", - params![ - chat_id, - DC_CONTACT_ID_DEVICE, - DC_CONTACT_ID_SELF, - dc_create_smeared_timestamp(context), - msg.type_0, - MessageState::InFresh, - msg.text.as_ref().map_or("", String::as_str), - msg.param.to_string(), - rfc724_mid, - ], - )?; + context.sql.execute( + "INSERT INTO msgs (chat_id,from_id,to_id, timestamp,type,state, txt,param,rfc724_mid) \ + VALUES (?,?,?, ?,?,?, ?,?,?);", + params![ + chat_id, + DC_CONTACT_ID_DEVICE, + DC_CONTACT_ID_SELF, + dc_create_smeared_timestamp(context), + msg.type_0, + MessageState::InFresh, + msg.text.as_ref().map_or("", String::as_str), + msg.param.to_string(), + rfc724_mid, + ], + )?; - let row_id = sql::get_rowid(context, &context.sql, "msgs", "rfc724_mid", &rfc724_mid); - let msg_id = MsgId::new(row_id); + let row_id = sql::get_rowid(context, &context.sql, "msgs", "rfc724_mid", &rfc724_mid); + msg_id = MsgId::new(row_id); + } if let Some(label) = label { - skip_device_msg(context, label)?; + context.sql.execute( + "INSERT INTO devmsglabels (label) VALUES (?);", + params![label], + )?; } if !msg_id.is_unset() { @@ -2003,20 +2011,6 @@ pub fn add_device_msg( Ok(msg_id) } -pub fn skip_device_msg(context: &Context, label: &str) -> Result<(), Error> { - if has_device_msg(context, label)? { - info!(context, "device-message {} already added", label); - return Ok(()); - } - - context.sql.execute( - "INSERT INTO devmsglabels (label) VALUES (?);", - params![label], - )?; - - Ok(()) -} - pub fn has_device_msg(context: &Context, label: &str) -> Result { ensure!(!label.is_empty(), "empty label"); if let Ok(()) = context.sql.query_row( @@ -2144,12 +2138,12 @@ mod tests { // add two device-messages let mut msg1 = Message::new(Viewtype::Text); msg1.text = Some("first message".to_string()); - let msg1_id = add_device_msg(&t.ctx, None, &mut msg1); + let msg1_id = add_device_msg(&t.ctx, None, Some(&mut msg1)); assert!(msg1_id.is_ok()); let mut msg2 = Message::new(Viewtype::Text); msg2.text = Some("second message".to_string()); - let msg2_id = add_device_msg(&t.ctx, None, &mut msg2); + let msg2_id = add_device_msg(&t.ctx, None, Some(&mut msg2)); assert!(msg2_id.is_ok()); assert_ne!(msg1_id.as_ref().unwrap(), msg2_id.as_ref().unwrap()); @@ -2179,13 +2173,13 @@ mod tests { // add two device-messages with the same label (second attempt is not added) let mut msg1 = Message::new(Viewtype::Text); msg1.text = Some("first message".to_string()); - let msg1_id = add_device_msg(&t.ctx, Some("any-label"), &mut msg1); + let msg1_id = add_device_msg(&t.ctx, Some("any-label"), Some(&mut msg1)); assert!(msg1_id.is_ok()); assert!(!msg1_id.as_ref().unwrap().is_unset()); let mut msg2 = Message::new(Viewtype::Text); msg2.text = Some("second message".to_string()); - let msg2_id = add_device_msg(&t.ctx, Some("any-label"), &mut msg2); + let msg2_id = add_device_msg(&t.ctx, Some("any-label"), Some(&mut msg2)); assert!(msg2_id.is_ok()); assert!(msg2_id.as_ref().unwrap().is_unset()); @@ -2217,27 +2211,27 @@ mod tests { message::delete_msgs(&t.ctx, &[*msg1_id.as_ref().unwrap()]); let msg1 = message::Message::load_from_db(&t.ctx, *msg1_id.as_ref().unwrap()); assert!(msg1.is_err() || msg1.unwrap().chat_id == DC_CHAT_ID_TRASH); - let msg3_id = add_device_msg(&t.ctx, Some("any-label"), &mut msg2); + let msg3_id = add_device_msg(&t.ctx, Some("any-label"), Some(&mut msg2)); assert!(msg3_id.is_ok()); assert!(msg2_id.as_ref().unwrap().is_unset()); } #[test] - fn test_skip_device_msg() { + fn test_add_device_msg_label_only() { let t = test_context(Some(Box::new(logging_cb))); - let res = skip_device_msg(&t.ctx, ""); + let res = add_device_msg(&t.ctx, Some(""), None); assert!(res.is_err()); - let res = skip_device_msg(&t.ctx, "some-label"); + let res = add_device_msg(&t.ctx, Some("some-label"), None); assert!(res.is_ok()); let mut msg = Message::new(Viewtype::Text); msg.text = Some("message text".to_string()); - let msg_id = add_device_msg(&t.ctx, Some("some-label"), &mut msg); + let msg_id = add_device_msg(&t.ctx, Some("some-label"), Some(&mut msg)); assert!(msg_id.is_ok()); assert!(msg_id.as_ref().unwrap().is_unset()); - let msg_id = add_device_msg(&t.ctx, Some("unused-label"), &mut msg); + let msg_id = add_device_msg(&t.ctx, Some("unused-label"), Some(&mut msg)); assert!(msg_id.is_ok()); assert!(!msg_id.as_ref().unwrap().is_unset()); } @@ -2245,12 +2239,12 @@ mod tests { #[test] fn test_has_device_msg() { let t = test_context(Some(Box::new(logging_cb))); - skip_device_msg(&t.ctx, "some-label").ok(); + add_device_msg(&t.ctx, Some("some-label"), None).ok(); assert!(has_device_msg(&t.ctx, "some-label").unwrap()); let mut msg = Message::new(Viewtype::Text); msg.text = Some("message text".to_string()); - add_device_msg(&t.ctx, Some("another-label"), &mut msg).ok(); + add_device_msg(&t.ctx, Some("another-label"), Some(&mut msg)).ok(); assert!(has_device_msg(&t.ctx, "another-label").unwrap()); assert!(!has_device_msg(&t.ctx, "unused-label").unwrap()); @@ -2270,7 +2264,7 @@ mod tests { let t = dummy_context(); let mut msg = Message::new(Viewtype::Text); msg.text = Some("foo".to_string()); - let msg_id = add_device_msg(&t.ctx, None, &mut msg).unwrap(); + let msg_id = add_device_msg(&t.ctx, None, Some(&mut msg)).unwrap(); let chat_id1 = message::Message::load_from_db(&t.ctx, msg_id) .unwrap() .chat_id; diff --git a/src/imex.rs b/src/imex.rs index e16d2b839..756fe15b2 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -247,7 +247,7 @@ fn maybe_add_bcc_self_device_msg(context: &Context) -> Result<()> { go to the settings and enable \"Send copy to self\"." .to_string(), ); - chat::add_device_msg(context, Some("bcc-self-hint"), &mut msg)?; + chat::add_device_msg(context, Some("bcc-self-hint"), Some(&mut msg))?; } Ok(()) }