diff --git a/CHANGELOG.md b/CHANGELOG.md index 323cfac6a..1ea187ef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ - Add fuzzing tests #3853 - Add mappings for some file types to Viewtype / MIME type #3881 - Buffer IMAP client writes #3888 +- move `DC_CHAT_ID_ARCHIVED_LINK` to the top of chat lists + and make `dc_get_fresh_msg_cnt()` work for `DC_CHAT_ID_ARCHIVED_LINK` #3918 ### API-Changes - jsonrpc: add python API for webxdc updates #3872 diff --git a/assets/icon-archive.png b/assets/icon-archive.png new file mode 100644 index 000000000..95d35e2a5 Binary files /dev/null and b/assets/icon-archive.png differ diff --git a/assets/icon-archive.svg b/assets/icon-archive.svg new file mode 100644 index 000000000..a8ba45d49 --- /dev/null +++ b/assets/icon-archive.svg @@ -0,0 +1,60 @@ + + + + + + + + + + diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 4a03f1a8f..47452f6ac 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -1227,7 +1227,11 @@ int dc_get_msg_cnt (dc_context_t* context, uint32_t ch * Get the number of _fresh_ messages in a chat. * Typically used to implement a badge with a number in the chatlist. * - * If the specified chat is muted, + * As muted archived chats are not unarchived automatically, + * a similar information is needed for the @ref dc_get_chatlist() "archive link" as well: + * here, the number of archived chats containing fresh messages is returned. + * + * If the specified chat is muted or the @ref dc_get_chatlist() "archive link", * the UI should show the badge counter "less obtrusive", * e.g. using "gray" instead of "red" color. * diff --git a/src/chat.rs b/src/chat.rs index 8be73e1ef..4de92e070 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -782,17 +782,35 @@ impl ChatId { // the times are average, no matter if there are fresh messages or not - // and have to be multiplied by the number of items shown at once on the chatlist, // so savings up to 2 seconds are possible on older devices - newer ones will feel "snappier" :) - let count = context - .sql - .count( - "SELECT COUNT(*) + let count = if self.is_archived_link() { + context + .sql + .count( + "SELECT COUNT(DISTINCT(m.chat_id)) + FROM msgs m + LEFT JOIN chats c ON m.chat_id=c.id + WHERE m.state=10 + and m.hidden=0 + AND m.chat_id>9 + AND c.blocked=0 + AND c.archived=1 + ", + paramsv![], + ) + .await? + } else { + context + .sql + .count( + "SELECT COUNT(*) FROM msgs WHERE state=? AND hidden=0 AND chat_id=?;", - paramsv![MessageState::InFresh, self], - ) - .await?; + paramsv![MessageState::InFresh, self], + ) + .await? + }; Ok(count) } @@ -1216,6 +1234,10 @@ impl Chat { if !image_rel.is_empty() { return Ok(Some(get_abs_path(context, image_rel))); } + } else if self.id.is_archived_link() { + if let Ok(image_rel) = get_archive_icon(context).await { + return Ok(Some(get_abs_path(context, image_rel))); + } } else if self.typ == Chattype::Single { let contacts = get_chat_contacts(context, self.id).await?; if let Some(contact_id) = contacts.first() { @@ -1708,6 +1730,21 @@ pub(crate) async fn get_broadcast_icon(context: &Context) -> Result { Ok(icon) } +pub(crate) async fn get_archive_icon(context: &Context) -> Result { + if let Some(icon) = context.sql.get_raw_config("icon-archive").await? { + return Ok(icon); + } + + let icon = include_bytes!("../assets/icon-archive.png"); + let blob = BlobObject::create(context, "icon-archive.png", icon).await?; + let icon = blob.as_name().to_string(); + context + .sql + .set_raw_config("icon-archive", Some(&icon)) + .await?; + Ok(icon) +} + async fn update_special_chat_name( context: &Context, contact_id: ContactId, diff --git a/src/chatlist.rs b/src/chatlist.rs index da7d309a4..df80b15e2 100644 --- a/src/chatlist.rs +++ b/src/chatlist.rs @@ -92,8 +92,6 @@ impl Chatlist { let flag_no_specials = 0 != listflags & DC_GCL_NO_SPECIALS; let flag_add_alldone_hint = 0 != listflags & DC_GCL_ADD_ALLDONE_HINT; - let mut add_archived_link_item = false; - let process_row = |row: &rusqlite::Row| { let chat_id: ChatId = row.get(0)?; let msg_id: Option = row.get(1)?; @@ -123,7 +121,7 @@ impl Chatlist { // // The query shows messages from blocked contacts in // groups. Otherwise it would be hard to follow conversations. - let mut ids = if let Some(query_contact_id) = query_contact_id { + let ids = if let Some(query_contact_id) = query_contact_id { // show chats shared with a given contact context.sql.query_map( "SELECT c.id, m.id @@ -216,7 +214,7 @@ impl Chatlist { } else { ChatId::new(0) }; - let ids = context.sql.query_map( + let mut ids = context.sql.query_map( "SELECT c.id, m.id FROM chats c LEFT JOIN msgs m @@ -236,19 +234,15 @@ impl Chatlist { process_row, process_rows, ).await?; - if !flag_no_specials { - add_archived_link_item = true; + if !flag_no_specials && get_archived_cnt(context).await? > 0 { + if ids.is_empty() && flag_add_alldone_hint { + ids.push((DC_CHAT_ID_ALLDONE_HINT, None)); + } + ids.insert(0, (DC_CHAT_ID_ARCHIVED_LINK, None)); } ids }; - if add_archived_link_item && get_archived_cnt(context).await? > 0 { - if ids.is_empty() && flag_add_alldone_hint { - ids.push((DC_CHAT_ID_ALLDONE_HINT, None)); - } - ids.push((DC_CHAT_ID_ARCHIVED_LINK, None)); - } - Ok(Chatlist { ids }) }