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)
This commit is contained in:
Simon Laux
2023-01-07 02:00:48 +01:00
parent 087b4289e5
commit 0eb67cff7e
3 changed files with 51 additions and 7 deletions

View File

@@ -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<ChatListEntry> {
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,

View File

@@ -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<u32>);
#[derive(Serialize, TypeDef)]
#[serde(tag = "type")]
@@ -59,10 +59,7 @@ pub(crate) async fn get_chat_list_item_by_id(
entry: &ChatListEntry,
) -> Result<ChatListItemFetchResult> {
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?;

View File

@@ -362,6 +362,38 @@ pub async fn get_archived_cnt(context: &Context) -> Result<usize> {
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<MsgId>)> {
// 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<MsgId> = row.get(1)?;
Ok((chat_id, msg_id))
},
)
.await
}
#[cfg(test)]
mod tests {
use super::*;