Get a list of chats. The list can be filtered by query parameters. The list is already sorted and starts with the most recent chat in use. The sorting takes care of invalid sending dates, drafts and chats without messages. Clients should not try to re-sort the list as this would be an expensive action and would result in inconsistencies between clients. To get information about each entry, use e
(
context: &Context,
listflags: usize,
query: Option<&str>,
query_contact_id: Option<ContactId>,
)
| 91 | /// `query_contact_id`: An optional contact ID for filtering the list. Only chats including this contact ID |
| 92 | /// are returned. |
| 93 | pub async fn try_load( |
| 94 | context: &Context, |
| 95 | listflags: usize, |
| 96 | query: Option<&str>, |
| 97 | query_contact_id: Option<ContactId>, |
| 98 | ) -> Result<Self> { |
| 99 | let flag_archived_only = 0 != listflags & DC_GCL_ARCHIVED_ONLY; |
| 100 | let flag_for_forwarding = 0 != listflags & DC_GCL_FOR_FORWARDING; |
| 101 | let flag_no_specials = 0 != listflags & DC_GCL_NO_SPECIALS; |
| 102 | let flag_add_alldone_hint = 0 != listflags & DC_GCL_ADD_ALLDONE_HINT; |
| 103 | |
| 104 | let process_row = |row: &rusqlite::Row| { |
| 105 | let chat_id: ChatId = row.get(0)?; |
| 106 | let msg_id: Option<MsgId> = row.get(1)?; |
| 107 | Ok((chat_id, msg_id)) |
| 108 | }; |
| 109 | |
| 110 | let skip_id = if flag_for_forwarding { |
| 111 | ChatId::lookup_by_contact(context, ContactId::DEVICE) |
| 112 | .await? |
| 113 | .unwrap_or_default() |
| 114 | } else { |
| 115 | ChatId::new(0) |
| 116 | }; |
| 117 | |
| 118 | // select with left join and minimum: |
| 119 | // |
| 120 | // - the inner select must use `hidden` and _not_ `m.hidden` |
| 121 | // which would refer the outer select and take a lot of time |
| 122 | // - `GROUP BY` is needed several messages may have the same |
| 123 | // timestamp |
| 124 | // - the list starts with the newest chats |
| 125 | // |
| 126 | // The query shows messages from blocked contacts in |
| 127 | // groups. Otherwise it would be hard to follow conversations. |
| 128 | let ids = if let Some(query_contact_id) = query_contact_id { |
| 129 | // show chats shared with a given contact |
| 130 | context.sql.query_map_vec( |
| 131 | "SELECT c.id, m.id |
| 132 | FROM chats c |
| 133 | LEFT JOIN msgs m |
| 134 | ON c.id=m.chat_id |
| 135 | AND m.id=( |
| 136 | SELECT id |
| 137 | FROM msgs |
| 138 | WHERE chat_id=c.id |
| 139 | AND (hidden=0 OR state=?1) |
| 140 | ORDER BY timestamp DESC, id DESC LIMIT 1) |
| 141 | WHERE c.id>9 |
| 142 | AND c.blocked!=1 |
| 143 | AND c.id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?2 AND add_timestamp >= remove_timestamp) |
| 144 | GROUP BY c.id |
| 145 | ORDER BY c.archived=?3 DESC, IFNULL(NULLIF(m.timestamp,0),c.created_timestamp) DESC, m.id DESC;", |
| 146 | (MessageState::OutDraft, query_contact_id, ChatVisibility::Pinned), |
| 147 | process_row, |
| 148 | ).await? |
| 149 | } else if flag_archived_only { |
| 150 | // show archived chats |
nothing calls this directly
no test coverage detected