From 0eb67cff7e4a7b4c4b56df639d8212131f2859de Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Sat, 7 Jan 2023 02:00:48 +0100 Subject: [PATCH] add get_chat_list_item_by_id method why? because desktop currently fetches the chatlist multiple times, even though it just needs the chatlistitem for one chat Note: @r10s was worried before that exposing the method to get a single updated chatlistitem could lead to race conditions where the chatlist item is newer than the chatlist order. But I don't think this will change anything for desktop besides making it a little faster. (because currently desktop fetches the whole chatlist instead of just the entry it needs when an entry updates) --- deltachat-jsonrpc/src/api/mod.rs | 19 ++++++++++-- deltachat-jsonrpc/src/api/types/chat_list.rs | 7 ++--- src/chatlist.rs | 32 ++++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/deltachat-jsonrpc/src/api/mod.rs b/deltachat-jsonrpc/src/api/mod.rs index a311f8f07..96d63374b 100644 --- a/deltachat-jsonrpc/src/api/mod.rs +++ b/deltachat-jsonrpc/src/api/mod.rs @@ -4,7 +4,7 @@ use deltachat::{ self, add_contact_to_chat, forward_msgs, get_chat_media, get_chat_msgs, marknoticed_chat, remove_contact_from_chat, Chat, ChatId, ChatItem, ProtectionStatus, }, - chatlist::Chatlist, + chatlist::{get_chatlistitem_for_chat, Chatlist}, config::Config, constants::DC_MSG_ID_DAYMARKER, contact::{may_be_valid_addr, Contact, ContactId, Origin}, @@ -439,12 +439,27 @@ impl CommandApi { for i in 0..list.len() { l.push(ChatListEntry( list.get_chat_id(i)?.to_u32(), - list.get_msg_id(i)?.unwrap_or_default().to_u32(), + list.get_msg_id(i)?.map(|msg_id| msg_id.to_u32()), )); } Ok(l) } + /// Get a chat list entry for a specific chat, + /// you should prefer using `get_chatlist_entries` unless you need this function for your virtual list needs like desktop + async fn get_chatlist_entry_by_chat( + &self, + account_id: u32, + chat_id: u32, + ) -> Result { + let ctx = self.get_context(account_id).await?; + let (chat_id, message_id) = get_chatlistitem_for_chat(&ctx, ChatId::new(chat_id)).await?; + Ok(ChatListEntry( + chat_id.to_u32(), + message_id.map(|msg_id| msg_id.to_u32()), + )) + } + async fn get_chatlist_items_by_entries( &self, account_id: u32, diff --git a/deltachat-jsonrpc/src/api/types/chat_list.rs b/deltachat-jsonrpc/src/api/types/chat_list.rs index 83b84dd3d..844b56261 100644 --- a/deltachat-jsonrpc/src/api/types/chat_list.rs +++ b/deltachat-jsonrpc/src/api/types/chat_list.rs @@ -16,7 +16,7 @@ use typescript_type_def::TypeDef; use super::color_int_to_hex_string; #[derive(Deserialize, Serialize, TypeDef)] -pub struct ChatListEntry(pub u32, pub u32); +pub struct ChatListEntry(pub u32, pub Option); #[derive(Serialize, TypeDef)] #[serde(tag = "type")] @@ -59,10 +59,7 @@ pub(crate) async fn get_chat_list_item_by_id( entry: &ChatListEntry, ) -> Result { let chat_id = ChatId::new(entry.0); - let last_msgid = match entry.1 { - 0 => None, - _ => Some(MsgId::new(entry.1)), - }; + let last_msgid = entry.1.map(|msg_id| MsgId::new(msg_id)); let fresh_message_counter = chat_id.get_fresh_msg_cnt(ctx).await?; diff --git a/src/chatlist.rs b/src/chatlist.rs index df80b15e2..452b5dc39 100644 --- a/src/chatlist.rs +++ b/src/chatlist.rs @@ -362,6 +362,38 @@ pub async fn get_archived_cnt(context: &Context) -> Result { Ok(count) } +/// Returns a single chatlistitem (chatId and messageid), used by desktop to partially update the chatlist on specific events +pub async fn get_chatlistitem_for_chat( + context: &Context, + chat_id: ChatId, +) -> Result<(ChatId, Option)> { + // Similar result as normal chatlist, only one item though and: + // archived and blocked chats are included + context + .sql + .query_row( + "SELECT c.id, m.id + FROM chats c + LEFT JOIN msgs m + ON c.id=m.chat_id + AND m.id=( + SELECT id + FROM msgs + WHERE chat_id=c.id + AND (hidden=0 OR state=?1) + ORDER BY timestamp DESC, id DESC LIMIT 1) + WHERE c.id=?2 + GROUP BY c.id", + paramsv![MessageState::OutDraft, chat_id], + |row: &rusqlite::Row| { + let chat_id: ChatId = row.get(0)?; + let msg_id: Option = row.get(1)?; + Ok((chat_id, msg_id)) + }, + ) + .await +} + #[cfg(test)] mod tests { use super::*;