From 8017c125182400fe691228f0755a5f921b97367e Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 Nov 2019 12:36:41 +0100 Subject: [PATCH 01/12] rename DC_CONTACT_ID_DEVICE to DC_CONTACT_ID_INFO to be in-line with dc_msg_is_info() --- deltachat-ffi/deltachat.h | 2 +- python/src/deltachat/const.py | 2 +- src/chat.rs | 8 ++++---- src/constants.rs | 2 +- src/location.rs | 4 ++-- src/message.rs | 6 +++--- src/qr.rs | 2 +- src/securejoin.rs | 6 +++--- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 56ceefad00..47b511cde5 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -3370,7 +3370,7 @@ void dc_msg_latefiling_mediasize (dc_msg_t* msg, int width, int hei #define DC_CONTACT_ID_SELF 1 -#define DC_CONTACT_ID_DEVICE 2 +#define DC_CONTACT_ID_INFO 2 #define DC_CONTACT_ID_LAST_SPECIAL 9 diff --git a/python/src/deltachat/const.py b/python/src/deltachat/const.py index ecfd5a86ba..e3e2bfc7e9 100644 --- a/python/src/deltachat/const.py +++ b/python/src/deltachat/const.py @@ -47,7 +47,7 @@ DC_STATE_OUT_DELIVERED = 26 DC_STATE_OUT_MDN_RCVD = 28 DC_CONTACT_ID_SELF = 1 -DC_CONTACT_ID_DEVICE = 2 +DC_CONTACT_ID_INFO = 2 DC_CONTACT_ID_LAST_SPECIAL = 9 DC_MSG_TEXT = 10 DC_MSG_IMAGE = 20 diff --git a/src/chat.rs b/src/chat.rs index 977b7249c3..b1c6f777be 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -994,7 +994,7 @@ pub fn get_chat_msgs( " LEFT JOIN contacts", " ON m.from_id=contacts.id", " WHERE m.from_id!=1", // 1=DC_CONTACT_ID_SELF - " AND m.from_id!=2", // 2=DC_CONTACT_ID_DEVICE + " AND m.from_id!=2", // 2=DC_CONTACT_ID_INFO " AND m.hidden=0", " AND chats.blocked=2", " AND contacts.blocked=0", @@ -1898,15 +1898,15 @@ pub fn get_chat_id_by_grpid(context: &Context, grpid: impl AsRef) -> (u32, .unwrap_or((0, false, Blocked::Not)) } -pub fn add_device_msg(context: &Context, chat_id: u32, text: impl AsRef) { +pub fn add_info_msg(context: &Context, chat_id: u32, text: impl AsRef) { let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device"); if context.sql.execute( "INSERT INTO msgs (chat_id,from_id,to_id, timestamp,type,state, txt,rfc724_mid) VALUES (?,?,?, ?,?,?, ?,?);", params![ chat_id as i32, - DC_CONTACT_ID_DEVICE, - DC_CONTACT_ID_DEVICE, + DC_CONTACT_ID_INFO, + DC_CONTACT_ID_INFO, dc_create_smeared_timestamp(context), Viewtype::Text, MessageState::InNoticed, diff --git a/src/constants.rs b/src/constants.rs index f6d752ff3b..23ce20c1b8 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -130,7 +130,7 @@ const DC_MAX_GET_INFO_LEN: usize = 100000; pub const DC_CONTACT_ID_UNDEFINED: u32 = 0; pub const DC_CONTACT_ID_SELF: u32 = 1; -pub const DC_CONTACT_ID_DEVICE: u32 = 2; +pub const DC_CONTACT_ID_INFO: u32 = 2; pub const DC_CONTACT_ID_LAST_SPECIAL: u32 = 9; pub const DC_CREATE_MVBOX: usize = 1; diff --git a/src/location.rs b/src/location.rs index 14ef83dda0..20527f06a7 100644 --- a/src/location.rs +++ b/src/location.rs @@ -219,7 +219,7 @@ pub fn send_locations_to_chat(context: &Context, chat_id: u32, seconds: i64) { } else if 0 == seconds && is_sending_locations_before { let stock_str = context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0); - chat::add_device_msg(context, chat_id, stock_str); + chat::add_info_msg(context, chat_id, stock_str); } context.call_cb(Event::ChatModified(chat_id)); if 0 != seconds { @@ -651,7 +651,7 @@ pub fn job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context: &Context, job: &mut Job) { params![chat_id as i32], ).is_ok() { let stock_str = context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0); - chat::add_device_msg(context, chat_id, stock_str); + chat::add_info_msg(context, chat_id, stock_str); context.call_cb(Event::ChatModified(chat_id)); } } diff --git a/src/message.rs b/src/message.rs index b2988d9107..bf4cdfecd7 100644 --- a/src/message.rs +++ b/src/message.rs @@ -476,8 +476,8 @@ impl Message { pub fn is_info(&self) -> bool { let cmd = self.param.get_cmd(); - self.from_id == DC_CONTACT_ID_DEVICE as libc::c_uint - || self.to_id == DC_CONTACT_ID_DEVICE as libc::c_uint + self.from_id == DC_CONTACT_ID_INFO as libc::c_uint + || self.to_id == DC_CONTACT_ID_INFO as libc::c_uint || cmd != SystemMessage::Unknown && cmd != SystemMessage::AutocryptSetupMessage } @@ -714,7 +714,7 @@ pub fn get_msg_info(context: &Context, msg_id: MsgId) -> String { ret += "\n"; } - if msg.from_id == DC_CONTACT_ID_DEVICE || msg.to_id == DC_CONTACT_ID_DEVICE { + if msg.from_id == DC_CONTACT_ID_INFO || msg.to_id == DC_CONTACT_ID_INFO { // device-internal message, no further details needed return ret; } diff --git a/src/qr.rs b/src/qr.rs index e53c71bf48..72f2b2d65f 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -150,7 +150,7 @@ fn decode_openpgp(context: &Context, qr: &str) -> Lot { let (id, _) = chat::create_or_lookup_by_contact_id(context, lot.id, Blocked::Deaddrop) .unwrap_or_default(); - chat::add_device_msg( + chat::add_info_msg( context, id, format!("{} verified.", peerstate.addr.unwrap_or_default()), diff --git a/src/securejoin.rs b/src/securejoin.rs index f8f8dc74de..783f6f3d14 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -638,7 +638,7 @@ fn secure_connection_established(context: &Context, contact_chat_id: u32) { "?" }; let msg = context.stock_string_repl_str(StockMessage::ContactVerified, addr); - chat::add_device_msg(context, contact_chat_id, msg); + chat::add_info_msg(context, contact_chat_id, msg); emit_event!(context, Event::ChatModified(contact_chat_id)); } @@ -654,7 +654,7 @@ fn could_not_establish_secure_connection(context: &Context, contact_chat_id: u32 }, ); - chat::add_device_msg(context, contact_chat_id, &msg); + chat::add_info_msg(context, contact_chat_id, &msg); error!(context, "{} ({})", &msg, details); } @@ -735,7 +735,7 @@ pub fn handle_degrade_event(context: &Context, peerstate: &Peerstate) -> Result< }; let msg = context.stock_string_repl_str(StockMessage::ContactSetupChanged, peeraddr); - chat::add_device_msg(context, contact_chat_id, msg); + chat::add_info_msg(context, contact_chat_id, msg); emit_event!(context, Event::ChatModified(contact_chat_id)); } } From 8b6b9ec7a9be589e1534cceb3585d3e6ad43935d Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 Nov 2019 12:44:36 +0100 Subject: [PATCH 02/12] prototype a device-chat --- deltachat-ffi/deltachat.h | 57 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 47b511cde5..a76ef367c2 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -1098,6 +1098,27 @@ uint32_t dc_send_text_msg (dc_context_t* context, uint32_t ch void dc_set_draft (dc_context_t* context, uint32_t chat_id, dc_msg_t* msg); +/** + * Add a message to the device-chat. + * Device-messages usually contain update information + * and some hints that are added during the program runs, multi-device etc. + * + * Device-messages may be added from the core, + * however, with this function, this can be done from the ui as well. + * If needed, the device-chat is created before. + * + * Sends the event #DC_EVENT_MSGS_CHANGED on success. + * To check, if a given chat is a device-chat, see dc_chat_is_device_talk() + * + * @memberof dc_context_t + * @param context The context as created by dc_context_new(). + * @param msg Message to be added to the device-chat. + * The message appears to the user as an incoming message. + * @return None. + */ +void dc_add_device_msg (dc_context_t* context, dc_msg_t* msg); + + /** * Get draft for a chat, if any. * See dc_set_draft() for more details about drafts. @@ -2715,6 +2736,39 @@ int dc_chat_is_unpromoted (const dc_chat_t* chat); int dc_chat_is_self_talk (const dc_chat_t* chat); +/** + * Check if a chat is a device-talk. + * Device-talks contain update information + * and some hints that are added during the program runs, multi-device etc. + * + * From the ui view, device-talks are not very special, + * the user can delete and forward messages, archive the chat, set notifications etc. + * + * Messages may be added from the core to the device chat, + * so the chat just pops up as usual. + * However, if needed the ui can also add messages using dc_add_device_msg() + * + * @memberof dc_chat_t + * @param chat The chat object. + * @return 1=chat is device-talk, 0=chat is no device-talk + */ +int dc_chat_is_device_talk (const dc_chat_t* chat); + + +/** + * Check if messages can be sent to a give chat. + * This is not true eg. for the deaddrop or for the device-talk, cmp. dc_chat_is_device_talk(). + * + * Calling dc_send_msg() for these chats will fail + * and the ui may decide to hide input controls therefore. + * + * @memberof dc_chat_t + * @param chat The chat object. + * @return 1=chat is writable, 0=chat is not writable + */ +int dc_chat_is_writable (const dc_chat_t* chat); + + /** * Check if a chat is verified. Verified chats contain only verified members * and encryption is alwasy enabled. Verified chats are created using @@ -3370,7 +3424,8 @@ void dc_msg_latefiling_mediasize (dc_msg_t* msg, int width, int hei #define DC_CONTACT_ID_SELF 1 -#define DC_CONTACT_ID_INFO 2 +#define DC_CONTACT_ID_INFO 2 // centered messages as "member added", used in all chats +#define DC_CONTACT_ID_DEVICE 5 // messages "update info" in the device-chat #define DC_CONTACT_ID_LAST_SPECIAL 9 From 5380a96e7b05c65d64ed831702e9e27ed5cf415e Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 Nov 2019 13:30:16 +0100 Subject: [PATCH 03/12] basic devicetalk implementation --- deltachat-ffi/src/lib.rs | 20 ++++++++++++++++++++ python/src/deltachat/const.py | 1 + src/chat.rs | 14 +++++++++++++- src/constants.rs | 1 + src/param.rs | 2 ++ src/sql.rs | 4 ++-- 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index dc3019a444..36190f3938 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -2264,6 +2264,26 @@ pub unsafe extern "C" fn dc_chat_is_self_talk(chat: *mut dc_chat_t) -> libc::c_i ffi_chat.chat.is_self_talk() as libc::c_int } +#[no_mangle] +pub unsafe extern "C" fn dc_chat_is_device_talk(chat: *mut dc_chat_t) -> libc::c_int { + if chat.is_null() { + eprintln!("ignoring careless call to dc_chat_is_device_talk()"); + return 0; + } + let ffi_chat = &*chat; + ffi_chat.chat.is_device_talk() as libc::c_int +} + +#[no_mangle] +pub unsafe extern "C" fn dc_chat_is_writable(chat: *mut dc_chat_t) -> libc::c_int { + if chat.is_null() { + eprintln!("ignoring careless call to dc_chat_is_writable()"); + return 0; + } + let ffi_chat = &*chat; + ffi_chat.chat.is_writable() as libc::c_int +} + #[no_mangle] pub unsafe extern "C" fn dc_chat_is_verified(chat: *mut dc_chat_t) -> libc::c_int { if chat.is_null() { diff --git a/python/src/deltachat/const.py b/python/src/deltachat/const.py index e3e2bfc7e9..ff22addb28 100644 --- a/python/src/deltachat/const.py +++ b/python/src/deltachat/const.py @@ -48,6 +48,7 @@ DC_STATE_OUT_MDN_RCVD = 28 DC_CONTACT_ID_SELF = 1 DC_CONTACT_ID_INFO = 2 +DC_CONTACT_ID_DEVICE = 5 DC_CONTACT_ID_LAST_SPECIAL = 9 DC_MSG_TEXT = 10 DC_MSG_IMAGE = 20 diff --git a/src/chat.rs b/src/chat.rs index b1c6f777be..c806a2a9cf 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -109,6 +109,14 @@ impl Chat { self.param.exists(Param::Selftalk) } + pub fn is_device_talk(&self) -> bool { + self.param.exists(Param::Devicetalk) + } + + pub fn is_writable(&self) -> bool { + self.id > DC_CHAT_ID_LAST_SPECIAL && !self.is_device_talk() + } + pub fn update_param(&mut self, context: &Context) -> Result<(), Error> { sql::execute( context, @@ -605,7 +613,11 @@ pub fn create_or_lookup_by_contact_id( "INSERT INTO chats (type, name, param, blocked, grpid) VALUES({}, '{}', '{}', {}, '{}')", 100, chat_name, - if contact_id == DC_CONTACT_ID_SELF as u32 { "K=1" } else { "" }, + match contact_id { + DC_CONTACT_ID_SELF => "K=1", // K = Param::Selftalk + DC_CONTACT_ID_DEVICE => "D=1", // K = Param::Devicetalk + _ => "" + }, create_blocked as u8, contact.get_addr(), ), diff --git a/src/constants.rs b/src/constants.rs index 23ce20c1b8..68783837f5 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -131,6 +131,7 @@ const DC_MAX_GET_INFO_LEN: usize = 100000; pub const DC_CONTACT_ID_UNDEFINED: u32 = 0; pub const DC_CONTACT_ID_SELF: u32 = 1; pub const DC_CONTACT_ID_INFO: u32 = 2; +pub const DC_CONTACT_ID_DEVICE: u32 = 5; pub const DC_CONTACT_ID_LAST_SPECIAL: u32 = 9; pub const DC_CREATE_MVBOX: usize = 1; diff --git a/src/param.rs b/src/param.rs index 9fcdf0db3c..524fcedf66 100644 --- a/src/param.rs +++ b/src/param.rs @@ -76,6 +76,8 @@ pub enum Param { ProfileImage = b'i', // For Chats Selftalk = b'K', + // For Chats + Devicetalk = b'D', // For QR Auth = b's', // For QR diff --git a/src/sql.rs b/src/sql.rs index 6cac599fae..16b1a39247 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -385,8 +385,8 @@ fn open( )?; sql.execute( "INSERT INTO contacts (id,name,origin) VALUES \ - (1,'self',262144), (2,'device',262144), (3,'rsvd',262144), \ - (4,'rsvd',262144), (5,'rsvd',262144), (6,'rsvd',262144), \ + (1,'self',262144), (2,'info',262144), (3,'rsvd',262144), \ + (4,'rsvd',262144), (5,'device',262144), (6,'rsvd',262144), \ (7,'rsvd',262144), (8,'rsvd',262144), (9,'rsvd',262144);", params![], )?; From 024f03404670cc9745a9274d1c2aae5c779c862b Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 Nov 2019 17:00:23 +0100 Subject: [PATCH 04/12] create separate function for preparing a blob --- src/chat.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index c806a2a9cf..11ae5fee29 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -689,8 +689,7 @@ pub fn msgtype_has_file(msgtype: Viewtype) -> bool { } } -fn prepare_msg_common(context: &Context, chat_id: u32, msg: &mut Message) -> Result { - msg.id = MsgId::new_unset(); +fn prepare_msg_blob(context: &Context, msg: &mut Message) -> Result<(), Error> { if msg.type_0 == Viewtype::Text { // the caller should check if the message text is empty } else if msgtype_has_file(msg.type_0) { @@ -726,7 +725,12 @@ fn prepare_msg_common(context: &Context, chat_id: u32, msg: &mut Message) -> Res } else { bail!("Cannot send messages of type #{}.", msg.type_0); } + Ok(()) +} +fn prepare_msg_common(context: &Context, chat_id: u32, msg: &mut Message) -> Result { + msg.id = MsgId::new_unset(); + prepare_msg_blob(context, msg)?; unarchive(context, chat_id)?; let mut chat = Chat::load_from_db(context, chat_id)?; From 15031f1653bbfc8753ca7ebe571c3caacfa5aae6 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 Nov 2019 17:00:50 +0100 Subject: [PATCH 05/12] implement add_device_msg() --- deltachat-ffi/src/lib.rs | 17 +++++++++++++++++ src/chat.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 36190f3938..8771e4a0c3 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -811,6 +811,23 @@ pub unsafe extern "C" fn dc_set_draft( .unwrap_or(()) } +#[no_mangle] +pub unsafe extern "C" fn dc_add_device_msg(context: *mut dc_context_t, msg: *mut dc_msg_t) -> u32 { + if context.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; + ffi_context + .with_inner(|ctx| { + chat::add_device_msg(ctx, &mut ffi_msg.message) + .unwrap_or_log_default(ctx, "Failed to add device message") + }) + .map(|msg_id| msg_id.to_u32()) + .unwrap_or(0) +} + #[no_mangle] pub unsafe extern "C" fn dc_get_draft(context: *mut dc_context_t, chat_id: u32) -> *mut dc_msg_t { if context.is_null() { diff --git a/src/chat.rs b/src/chat.rs index 11ae5fee29..c98be6328e 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1914,6 +1914,37 @@ pub fn get_chat_id_by_grpid(context: &Context, grpid: impl AsRef) -> (u32, .unwrap_or((0, false, Blocked::Not)) } +pub fn add_device_msg(context: &Context, msg: &mut Message) -> Result { + let (chat_id, _blocked) = + create_or_lookup_by_contact_id(context, DC_CONTACT_ID_DEVICE, Blocked::Not)?; + 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, + ], + )?; + + let row_id = sql::get_rowid(context, &context.sql, "msgs", "rfc724_mid", &rfc724_mid); + let msg_id = MsgId::new(row_id); + context.call_cb(Event::IncomingMsg { chat_id, msg_id }); + + Ok(msg_id) +} + pub fn add_info_msg(context: &Context, chat_id: u32, text: impl AsRef) { let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device"); From ba1e79f1009119edfb73740f5c98fba5fedb0b89 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 Nov 2019 17:01:07 +0100 Subject: [PATCH 06/12] add devicemsg to repl tool --- examples/repl/cmdline.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 0796b159d0..77705340c0 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -379,6 +379,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E sendimage []\n\ sendfile []\n\ draft []\n\ + devicemsg \n\ listmedia\n\ archive \n\ unarchive \n\ @@ -521,13 +522,12 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E for i in (0..cnt).rev() { let chat = Chat::load_from_db(context, chatlist.get_chat_id(i))?; - let temp_name = chat.get_name(); info!( context, "{}#{}: {} [{} fresh]", chat_prefix(&chat), chat.get_id(), - temp_name, + chat.get_name(), chat::get_fresh_msg_cnt(context, chat.get_id()), ); let lot = chatlist.get_summary(context, i, Some(&chat)); @@ -586,20 +586,21 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E let msglist = chat::get_chat_msgs(context, sel_chat.get_id(), 0x1, None); let members = chat::get_chat_contacts(context, sel_chat.id); - let temp2 = if sel_chat.get_type() == Chattype::Single && members.len() >= 1 { + let subtitle = if sel_chat.is_device_talk() { + "device-talk".to_string() + } else if sel_chat.get_type() == Chattype::Single && members.len() >= 1 { let contact = Contact::get_by_id(context, members[0])?; contact.get_addr().to_string() } else { format!("{} member(s)", members.len()) }; - let temp_name = sel_chat.get_name(); info!( context, "{}#{}: {} [{}]{}", chat_prefix(sel_chat), sel_chat.get_id(), - temp_name, - temp2, + sel_chat.get_name(), + subtitle, if sel_chat.is_sending_locations() { "📍" } else { @@ -822,6 +823,15 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E println!("Draft deleted."); } } + "devicemsg" => { + ensure!( + !arg1.is_empty(), + "Please specify text to add as device message." + ); + let mut msg = Message::new(Viewtype::Text); + msg.set_text(Some(arg1.to_string())); + chat::add_device_msg(context, &mut msg)?; + } "listmedia" => { ensure!(sel_chat.is_some(), "No chat selected."); From 8733d66e4a0ea96639f57af23e16fb5764e81ece Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 Nov 2019 20:35:25 +0100 Subject: [PATCH 07/12] get contact- and chat-info for device-messages --- src/chat.rs | 2 ++ src/contact.rs | 11 ++++++++++- src/stock.rs | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/chat.rs b/src/chat.rs index c98be6328e..50debaadac 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -97,6 +97,8 @@ impl Chat { if chat.param.exists(Param::Selftalk) { chat.name = context.stock_str(StockMessage::SelfMsg).into(); + } else if chat.param.exists(Param::Devicetalk) { + chat.name = context.stock_str(StockMessage::DeviceMessages).into(); } } } diff --git a/src/contact.rs b/src/contact.rs index f0c765c4c9..e0d8821287 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -153,7 +153,16 @@ impl Contact { blocked: false, origin: Origin::Unknown, }; - + return Ok(contact); + } else if contact_id == DC_CONTACT_ID_DEVICE { + let contact = Contact { + id: contact_id, + name: context.stock_str(StockMessage::DeviceMessages).into(), + authname: "".into(), + addr: "device@localhost".into(), + blocked: false, + origin: Origin::Unknown, + }; return Ok(contact); } diff --git a/src/stock.rs b/src/stock.rs index af24bac01b..f5d27f0edd 100644 --- a/src/stock.rs +++ b/src/stock.rs @@ -110,6 +110,8 @@ pub enum StockMessage { Location = 66, #[strum(props(fallback = "Sticker"))] Sticker = 67, + #[strum(props(fallback = "Device Messages"))] + DeviceMessages = 68, } impl StockMessage { From 7791f777155e7c3dced505b420d87eb7295c3265 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 4 Nov 2019 23:04:12 +0100 Subject: [PATCH 08/12] target comments of @flub --- deltachat-ffi/deltachat.h | 2 +- deltachat-ffi/src/lib.rs | 6 +++--- src/chat.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index a76ef367c2..56918e8d07 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -2766,7 +2766,7 @@ int dc_chat_is_device_talk (const dc_chat_t* chat); * @param chat The chat object. * @return 1=chat is writable, 0=chat is not writable */ -int dc_chat_is_writable (const dc_chat_t* chat); +int dc_chat_can_send (const dc_chat_t* chat); /** diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 8771e4a0c3..6c52f09ca4 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -2292,13 +2292,13 @@ pub unsafe extern "C" fn dc_chat_is_device_talk(chat: *mut dc_chat_t) -> libc::c } #[no_mangle] -pub unsafe extern "C" fn dc_chat_is_writable(chat: *mut dc_chat_t) -> libc::c_int { +pub unsafe extern "C" fn dc_chat_can_send(chat: *mut dc_chat_t) -> libc::c_int { if chat.is_null() { - eprintln!("ignoring careless call to dc_chat_is_writable()"); + eprintln!("ignoring careless call to dc_chat_can_send()"); return 0; } let ffi_chat = &*chat; - ffi_chat.chat.is_writable() as libc::c_int + ffi_chat.chat.can_send() as libc::c_int } #[no_mangle] diff --git a/src/chat.rs b/src/chat.rs index 50debaadac..d21f4333e1 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -115,7 +115,7 @@ impl Chat { self.param.exists(Param::Devicetalk) } - pub fn is_writable(&self) -> bool { + pub fn can_send(&self) -> bool { self.id > DC_CHAT_ID_LAST_SPECIAL && !self.is_device_talk() } From c61455034ea4b482dada7bcd7c5e5321fc4f3541 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 5 Nov 2019 00:43:04 +0100 Subject: [PATCH 09/12] add profile-icon for device-chat --- assets/icon-device.png | Bin 0 -> 3696 bytes src/chat.rs | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 assets/icon-device.png diff --git a/assets/icon-device.png b/assets/icon-device.png new file mode 100644 index 0000000000000000000000000000000000000000..ff2d545bf54eb927fa4308a862c960d00f4d3aaf GIT binary patch literal 3696 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 b .is_ok() } +fn copy_device_icon_to_blobs(context: &Context) -> Result { + let icon = include_bytes!("../assets/icon-device.png"); + let blob = BlobObject::create(context, "icon-device.png".to_string(), icon)?; + Ok(blob.as_name().to_string()) +} + pub fn create_or_lookup_by_contact_id( context: &Context, contact_id: u32, @@ -616,9 +622,12 @@ pub fn create_or_lookup_by_contact_id( 100, chat_name, match contact_id { - DC_CONTACT_ID_SELF => "K=1", // K = Param::Selftalk - DC_CONTACT_ID_DEVICE => "D=1", // K = Param::Devicetalk - _ => "" + DC_CONTACT_ID_SELF => "K=1".to_string(), // K = Param::Selftalk + DC_CONTACT_ID_DEVICE => { + let icon = copy_device_icon_to_blobs(context)?; + format!("D=1\ni={}", icon) // D = Param::Devicetalk, i = Param::ProfileImage + }, + _ => "".to_string() }, create_blocked as u8, contact.get_addr(), From 01ae2bb4c29273776dae1e8f983e386ea2f79a71 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 5 Nov 2019 00:43:53 +0100 Subject: [PATCH 10/12] show chat-profile-image in repl tool --- examples/repl/cmdline.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 77705340c0..aeb6c4fb15 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -596,7 +596,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E }; info!( context, - "{}#{}: {} [{}]{}", + "{}#{}: {} [{}]{}{}", chat_prefix(sel_chat), sel_chat.get_id(), sel_chat.get_name(), @@ -606,6 +606,13 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E } else { "" }, + match sel_chat.get_profile_image(context) { + Some(icon) => match icon.to_str() { + Some(icon) => format!(" Icon: {}", icon), + _ => " Icon: Err".to_string(), + }, + _ => "".to_string(), + }, ); log_msglist(context, &msglist)?; if let Some(draft) = chat::get_draft(context, sel_chat.get_id())? { From 13d12a70aba7beba67063c4503d1ae678ef309a5 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 5 Nov 2019 13:52:01 +0100 Subject: [PATCH 11/12] block sending to chats that do not support sending (normally, this should already be avoided in the ui) --- src/chat.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chat.rs b/src/chat.rs index 92ae61d55d..6accc8ef62 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -745,6 +745,7 @@ fn prepare_msg_common(context: &Context, chat_id: u32, msg: &mut Message) -> Res unarchive(context, chat_id)?; let mut chat = Chat::load_from_db(context, chat_id)?; + ensure!(chat.can_send(), "cannot send to chat #{}", chat_id); // The OutPreparing state is set by dc_prepare_msg() before it // calls this function and the message is left in the OutPreparing From b59c421a685b4ed7b1e36e98798db78896bc7cd8 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 5 Nov 2019 23:23:18 +0100 Subject: [PATCH 12/12] correct ffi return value of dc_add_device_msg() --- deltachat-ffi/deltachat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 56918e8d07..60404603b2 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -1114,9 +1114,9 @@ void dc_set_draft (dc_context_t* context, uint32_t ch * @param context The context as created by dc_context_new(). * @param msg Message to be added to the device-chat. * The message appears to the user as an incoming message. - * @return None. + * @return The ID of the added message. */ -void dc_add_device_msg (dc_context_t* context, dc_msg_t* msg); +uint32_t dc_add_device_msg (dc_context_t* context, dc_msg_t* msg); /**