diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 52152caaf..09e34851a 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -2318,11 +2318,14 @@ pub unsafe extern "C" fn dc_chatlist_get_msg_id( return 0; } let ffi_list = &*chatlist; - ffi_list - .list - .get_msg_id(index as usize) - .map(|msg_id| msg_id.to_u32()) - .unwrap_or(0) + let ctx = &*ffi_list.context; + match ffi_list.list.get_msg_id(index as usize) { + Ok(msg_id) => msg_id.map_or(0, |msg_id| msg_id.to_u32()), + Err(err) => { + warn!(ctx, "get_msg_id failed: {}", err); + 0 + } + } } #[no_mangle] @@ -2348,7 +2351,9 @@ pub unsafe extern "C" fn dc_chatlist_get_summary( let lot = ffi_list .list .get_summary(&ctx, index as usize, maybe_chat) - .await; + .await + .log_err(ctx, "get_summary failed") + .unwrap_or_default(); Box::into_raw(Box::new(lot)) }) } @@ -2364,9 +2369,16 @@ pub unsafe extern "C" fn dc_chatlist_get_summary2( return ptr::null_mut(); } let ctx = &*context; + let msg_id = if msg_id == 0 { + None + } else { + Some(MsgId::new(msg_id)) + }; block_on(async move { - let lot = - Chatlist::get_summary2(&ctx, ChatId::new(chat_id), MsgId::new(msg_id), None).await; + let lot = Chatlist::get_summary2(&ctx, ChatId::new(chat_id), msg_id, None) + .await + .log_err(ctx, "get_summary2 failed") + .unwrap_or_default(); Box::into_raw(Box::new(lot)) }) } diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 30723e5e6..8da9460cc 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -551,7 +551,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu }, if chat.is_protected() { "🛡️" } else { "" }, ); - let lot = chatlist.get_summary(&context, i, Some(&chat)).await; + let lot = chatlist.get_summary(&context, i, Some(&chat)).await?; let statestr = if chat.visibility == ChatVisibility::Archived { " [Archived]" } else { diff --git a/examples/simple.rs b/examples/simple.rs index d257442fe..9fe2dfc7c 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -86,7 +86,7 @@ async fn main() { let chats = Chatlist::try_load(&ctx, 0, None, None).await.unwrap(); for i in 0..chats.len() { - let msg = Message::load_from_db(&ctx, chats.get_msg_id(i).unwrap()) + let msg = Message::load_from_db(&ctx, chats.get_msg_id(i).unwrap().unwrap()) .await .unwrap(); log::info!("[{}] msg: {:?}", i, msg); diff --git a/src/chatlist.rs b/src/chatlist.rs index 827a06d61..8603214fb 100644 --- a/src/chatlist.rs +++ b/src/chatlist.rs @@ -42,7 +42,7 @@ use crate::stock_str; #[derive(Debug)] pub struct Chatlist { /// Stores pairs of `chat_id, message_id` - ids: Vec<(ChatId, MsgId)>, + ids: Vec<(ChatId, Option)>, } impl Chatlist { @@ -111,7 +111,7 @@ impl Chatlist { let process_row = |row: &rusqlite::Row| { let chat_id: ChatId = row.get(0)?; - let msg_id: MsgId = row.get(1).unwrap_or_default(); + let msg_id: Option = row.get(1)?; Ok((chat_id, msg_id)) }; @@ -261,7 +261,7 @@ impl Chatlist { get_last_deaddrop_fresh_msg(context).await? { if !flag_for_forwarding { - ids.insert(0, (DC_CHAT_ID_DEADDROP, last_deaddrop_fresh_msg_id)); + ids.insert(0, (DC_CHAT_ID_DEADDROP, Some(last_deaddrop_fresh_msg_id))); } } add_archived_link_item = true; @@ -271,9 +271,9 @@ impl Chatlist { if add_archived_link_item && dc_get_archived_cnt(context).await? > 0 { if ids.is_empty() && flag_add_alldone_hint { - ids.push((DC_CHAT_ID_ALLDONE_HINT, MsgId::new(0))); + ids.push((DC_CHAT_ID_ALLDONE_HINT, None)); } - ids.push((DC_CHAT_ID_ARCHIVED_LINK, MsgId::new(0))); + ids.push((DC_CHAT_ID_ARCHIVED_LINK, None)); } Ok(Chatlist { ids }) @@ -302,7 +302,7 @@ impl Chatlist { /// Get a single message ID of a chatlist. /// /// To get the message object from the message ID, use dc_get_msg(). - pub fn get_msg_id(&self, index: usize) -> Result { + pub fn get_msg_id(&self, index: usize) -> Result> { match self.ids.get(index) { Some((_chat_id, msg_id)) => Ok(*msg_id), None => bail!("Chatlist index out of range"), @@ -323,18 +323,19 @@ impl Chatlist { /// - dc_lot_t::timestamp: the timestamp of the message. 0 if not applicable. /// - dc_lot_t::state: The state of the message as one of the DC_STATE_* constants (see #dc_msg_get_state()). // 0 if not applicable. - pub async fn get_summary(&self, context: &Context, index: usize, chat: Option<&Chat>) -> Lot { + pub async fn get_summary( + &self, + context: &Context, + index: usize, + chat: Option<&Chat>, + ) -> Result { // The summary is created by the chat, not by the last message. // This is because we may want to display drafts here or stuff as // "is typing". // Also, sth. as "No messages" would not work if the summary comes from a message. let (chat_id, lastmsg_id) = match self.ids.get(index) { Some(ids) => ids, - None => { - let mut ret = Lot::new(); - ret.text2 = Some("ErrBadChatlistIndex".to_string()); - return Lot::new(); - } + None => bail!("Chatlist index out of range"), }; Chatlist::get_summary2(context, *chat_id, *lastmsg_id, chat).await @@ -343,50 +344,50 @@ impl Chatlist { pub async fn get_summary2( context: &Context, chat_id: ChatId, - lastmsg_id: MsgId, + lastmsg_id: Option, chat: Option<&Chat>, - ) -> Lot { + ) -> Result { let mut ret = Lot::new(); let chat_loaded: Chat; let chat = if let Some(chat) = chat { chat - } else if let Ok(chat) = Chat::load_from_db(context, chat_id).await { + } else { + let chat = Chat::load_from_db(context, chat_id).await?; chat_loaded = chat; &chat_loaded - } else { - return ret; }; - let (lastmsg, lastcontact) = - if let Ok(lastmsg) = Message::load_from_db(context, lastmsg_id).await { - if lastmsg.from_id == DC_CONTACT_ID_SELF { - (Some(lastmsg), None) - } else { - match chat.typ { - Chattype::Group | Chattype::Mailinglist => { - let lastcontact = - Contact::load_from_db(context, lastmsg.from_id).await.ok(); - (Some(lastmsg), lastcontact) - } - Chattype::Single | Chattype::Undefined => (Some(lastmsg), None), - } - } + let (lastmsg, lastcontact) = if let Some(lastmsg_id) = lastmsg_id { + let lastmsg = Message::load_from_db(context, lastmsg_id).await?; + if lastmsg.from_id == DC_CONTACT_ID_SELF { + (Some(lastmsg), None) } else { - (None, None) - }; + match chat.typ { + Chattype::Group | Chattype::Mailinglist => { + let lastcontact = + Contact::load_from_db(context, lastmsg.from_id).await.ok(); + (Some(lastmsg), lastcontact) + } + Chattype::Single | Chattype::Undefined => (Some(lastmsg), None), + } + } + } else { + (None, None) + }; if chat.id.is_archived_link() { ret.text2 = None; - } else if lastmsg.is_none() || lastmsg.as_ref().unwrap().from_id == DC_CONTACT_ID_UNDEFINED + } else if let Some(mut lastmsg) = + lastmsg.filter(|msg| msg.from_id != DC_CONTACT_ID_UNDEFINED) { - ret.text2 = Some(stock_str::no_messages(context).await); - } else { - ret.fill(&mut lastmsg.unwrap(), chat, lastcontact.as_ref(), context) + ret.fill(&mut lastmsg, chat, lastcontact.as_ref(), context) .await; + } else { + ret.text2 = Some(stock_str::no_messages(context).await); } - ret + Ok(ret) } pub fn get_index_for_id(&self, id: ChatId) -> Option { @@ -684,7 +685,7 @@ mod tests { chat_id1.set_draft(&t, Some(&mut msg)).await.unwrap(); let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap(); - let summary = chats.get_summary(&t, 0, None).await; + let summary = chats.get_summary(&t, 0, None).await.unwrap(); assert_eq!(summary.get_text2().unwrap(), "foo: bar test"); // the linebreak should be removed from summary } } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 81c26063e..708e95ebf 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2295,7 +2295,7 @@ mod tests { let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap(); assert_eq!(chats.len(), 1); assert!(chats.get_chat_id(0).is_deaddrop()); - let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap()) + let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap().unwrap()) .await .unwrap(); assert!(!chat_id.is_special()); @@ -2330,7 +2330,7 @@ mod tests { .unwrap(); let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap(); assert_eq!(chats.len(), 2); - let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap()) + let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap().unwrap()) .await .unwrap(); let chat = chat::Chat::load_from_db(&t, chat_id).await.unwrap(); @@ -2351,7 +2351,7 @@ mod tests { let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap(); assert_eq!(chats.len(), 1); assert!(chats.get_chat_id(0).is_deaddrop()); - let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap()) + let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap().unwrap()) .await .unwrap(); let chat = chat::Chat::load_from_db(&t, chat_id).await.unwrap(); @@ -2600,7 +2600,7 @@ mod tests { assert_eq!(contact.get_display_name(), "h2"); let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap(); - let msg = Message::load_from_db(&t, chats.get_msg_id(0).unwrap()) + let msg = Message::load_from_db(&t, chats.get_msg_id(0).unwrap().unwrap()) .await .unwrap(); assert_eq!(msg.is_dc_message, MessengerMessage::Yes); @@ -2751,7 +2751,7 @@ mod tests { .unwrap(); let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap(); - let msg_id = chats.get_msg_id(0).unwrap(); + let msg_id = chats.get_msg_id(0).unwrap().unwrap(); // Check that the ndn would be downloaded: let headers = mailparse::parse_mail(raw_ndn).unwrap().headers; @@ -2801,7 +2801,7 @@ mod tests { .unwrap(); let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap(); - let msg_id = chats.get_msg_id(0).unwrap(); + let msg_id = chats.get_msg_id(0).unwrap().unwrap(); let raw = include_bytes!("../test-data/message/gmail_ndn_group.eml"); dc_receive_imf(&t, raw, "INBOX", 1, false).await.unwrap(); @@ -2834,7 +2834,7 @@ mod tests { .await .unwrap(); let chats = Chatlist::try_load(context, 0, None, None).await.unwrap(); - let msg_id = chats.get_msg_id(0).unwrap(); + let msg_id = chats.get_msg_id(0).unwrap().unwrap(); Message::load_from_db(context, msg_id).await.unwrap() } @@ -2884,7 +2884,7 @@ mod tests { let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); assert_eq!(chats.len(), 1); - let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap()) + let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap().unwrap()) .await .unwrap(); let chat = chat::Chat::load_from_db(&t.ctx, chat_id).await.unwrap(); @@ -2957,7 +2957,7 @@ mod tests { .await .unwrap(); let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); - let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap()) + let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap().unwrap()) .await .unwrap(); let chat = Chat::load_from_db(&t.ctx, chat_id).await.unwrap(); diff --git a/src/mimefactory.rs b/src/mimefactory.rs index c171095eb..f51917b84 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1806,7 +1806,7 @@ mod tests { let chats = Chatlist::try_load(context, 0, None, None).await.unwrap(); - let chat_id = chat::create_by_msg_id(context, chats.get_msg_id(0).unwrap()) + let chat_id = chat::create_by_msg_id(context, chats.get_msg_id(0).unwrap().unwrap()) .await .unwrap(); diff --git a/src/mimeparser.rs b/src/mimeparser.rs index f6b3784a2..16472257b 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -2834,7 +2834,7 @@ On 2020-10-25, Bob wrote: .unwrap(); let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); - let msg_id = chats.get_msg_id(0).unwrap(); + let msg_id = chats.get_msg_id(0).unwrap().unwrap(); let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); assert_eq!( diff --git a/src/test_utils.rs b/src/test_utils.rs index 7a0a9fd32..3f2a10dcc 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -331,7 +331,7 @@ impl TestContext { // The chatlist describes what you see when you open DC, a list of chats and in each of them // the first words of the last message. To get the last message overall, we look at the chat at the top of the // list, which has the index 0. - let msg_id = chats.get_msg_id(0).unwrap(); + let msg_id = chats.get_msg_id(0).unwrap().unwrap(); Message::load_from_db(&self.ctx, msg_id) .await .expect("failed to load msg")