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 })
}