diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a4313a5..b074c36bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Changes +- BREAKING: jsonrpc: + - `get_chatlist_items_by_entries` now takes only chatids instead of `ChatListEntries` + - `get_chatlist_entries` now returns `Vec` of chatids instead of `ChatListEntries` + + ## [1.114.0] - 2023-04-24 ### Changes diff --git a/deltachat-jsonrpc/src/api/mod.rs b/deltachat-jsonrpc/src/api/mod.rs index 19a1ef109..98942a855 100644 --- a/deltachat-jsonrpc/src/api/mod.rs +++ b/deltachat-jsonrpc/src/api/mod.rs @@ -41,7 +41,6 @@ pub mod types; use num_traits::FromPrimitive; use types::account::Account; use types::chat::FullChat; -use types::chat_list::ChatListEntry; use types::contact::ContactObject; use types::http::HttpResponse; use types::message::MessageData; @@ -549,7 +548,7 @@ impl CommandApi { list_flags: Option, query_string: Option, query_contact_id: Option, - ) -> Result> { + ) -> Result> { let ctx = self.get_context(account_id).await?; let list = Chatlist::try_load( &ctx, @@ -558,12 +557,9 @@ impl CommandApi { query_contact_id.map(ContactId::new), ) .await?; - let mut l: Vec = Vec::with_capacity(list.len()); + let mut l: Vec = Vec::with_capacity(list.len()); 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(), - )); + l.push(list.get_chat_id(i)?.to_u32()); } Ok(l) } @@ -571,19 +567,18 @@ impl CommandApi { async fn get_chatlist_items_by_entries( &self, account_id: u32, - entries: Vec, + entries: Vec, ) -> Result> { - // todo custom json deserializer for ChatListEntry? let ctx = self.get_context(account_id).await?; let mut result: HashMap = HashMap::with_capacity(entries.len()); - for entry in entries.iter() { + for &entry in entries.iter() { result.insert( - entry.0, + entry, match get_chat_list_item_by_id(&ctx, entry).await { Ok(res) => res, Err(err) => ChatListItemFetchResult::Error { - id: entry.0, + id: entry, error: format!("{err:#}"), }, }, diff --git a/deltachat-jsonrpc/src/api/types/chat_list.rs b/deltachat-jsonrpc/src/api/types/chat_list.rs index 83b84dd3d..c98b6d932 100644 --- a/deltachat-jsonrpc/src/api/types/chat_list.rs +++ b/deltachat-jsonrpc/src/api/types/chat_list.rs @@ -1,23 +1,18 @@ use anyhow::Result; +use deltachat::chat::{Chat, ChatId}; +use deltachat::chatlist::get_last_message_for_chat; use deltachat::constants::*; use deltachat::contact::{Contact, ContactId}; use deltachat::{ chat::{get_chat_contacts, ChatVisibility}, chatlist::Chatlist, }; -use deltachat::{ - chat::{Chat, ChatId}, - message::MsgId, -}; use num_traits::cast::ToPrimitive; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use typescript_type_def::TypeDef; use super::color_int_to_hex_string; -#[derive(Deserialize, Serialize, TypeDef)] -pub struct ChatListEntry(pub u32, pub u32); - #[derive(Serialize, TypeDef)] #[serde(tag = "type")] pub enum ChatListItemFetchResult { @@ -56,14 +51,9 @@ pub enum ChatListItemFetchResult { pub(crate) async fn get_chat_list_item_by_id( ctx: &deltachat::context::Context, - entry: &ChatListEntry, + entry: u32, ) -> Result { - let chat_id = ChatId::new(entry.0); - let last_msgid = match entry.1 { - 0 => None, - _ => Some(MsgId::new(entry.1)), - }; - + let chat_id = ChatId::new(entry); let fresh_message_counter = chat_id.get_fresh_msg_cnt(ctx).await?; if chat_id.is_archived_link() { @@ -72,6 +62,8 @@ pub(crate) async fn get_chat_list_item_by_id( }); } + let last_msgid = get_last_message_for_chat(ctx, chat_id).await?; + let chat = Chat::load_from_db(ctx, chat_id).await?; let summary = Chatlist::get_summary2(ctx, chat_id, last_msgid, Some(&chat)).await?; diff --git a/deltachat-jsonrpc/typescript/example/example.ts b/deltachat-jsonrpc/typescript/example/example.ts index 0caa2de06..d7b038e0c 100644 --- a/deltachat-jsonrpc/typescript/example/example.ts +++ b/deltachat-jsonrpc/typescript/example/example.ts @@ -67,7 +67,7 @@ async function run() { null, null ); - for (const [chatId, _messageId] of chats) { + for (const chatId of chats) { const chat = await client.rpc.getFullChatById(selectedAccount, chatId); write($main, `

${chat.name}

`); const messageIds = await client.rpc.getMessageIds( diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/account.py b/deltachat-rpc-client/src/deltachat_rpc_client/account.py index 4c44079f7..c3f29995c 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/account.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/account.py @@ -177,7 +177,7 @@ class Account: entries = await self._rpc.get_chatlist_entries(self.id, flags, query, contact and contact.id) if not snapshot: - return [Chat(self, entry[0]) for entry in entries] + return [Chat(self, entry) for entry in entries] items = await self._rpc.get_chatlist_items_by_entries(self.id, entries) chats = [] diff --git a/src/chatlist.rs b/src/chatlist.rs index ddd60c072..718918807 100644 --- a/src/chatlist.rs +++ b/src/chatlist.rs @@ -362,6 +362,25 @@ pub async fn get_archived_cnt(context: &Context) -> Result { Ok(count) } +/// Gets the last message of a chat, the message that would also be displayed in the ChatList +/// Used for passing to `deltachat::chatlist::Chatlist::get_summary2` +pub async fn get_last_message_for_chat( + context: &Context, + chat_id: ChatId, +) -> Result> { + context + .sql + .query_get_value( + "SELECT id + FROM msgs + WHERE chat_id=?2 + AND (hidden=0 OR state=?1) + ORDER BY timestamp DESC, id DESC LIMIT 1", + (MessageState::OutDraft, chat_id), + ) + .await +} + #[cfg(test)] mod tests { use super::*;