diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index a7f21f9bd..0b6eda8f8 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -224,6 +224,14 @@ impl CommandApi { self.accounts.read().await.get_selected_account_id() } + /// Set the order of accounts. + /// The provided list should contain all account IDs in the desired order. + /// If an account ID is missing from the list, it will be appended at the end. + /// If the list contains non-existent account IDs, they will be ignored. + async fn set_accounts_order(&self, order: Vec) -> Result<()> { + self.accounts.write().await.set_accounts_order(order).await + } + /// Get a list of all configured accounts. async fn get_all_accounts(&self) -> Result> { let mut accounts = Vec::new(); diff --git a/src/accounts.rs b/src/accounts.rs index ad3266e28..1b1408b08 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -1,6 +1,6 @@ //! # Account manager module. -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; use std::future::Future; use std::path::{Path, PathBuf}; @@ -270,9 +270,51 @@ impl Accounts { } } - /// Get a list of all account ids. + /// Gets a list of all account ids in the user-configured order. pub fn get_all(&self) -> Vec { - self.accounts.keys().copied().collect() + let mut ordered_ids = Vec::new(); + let mut all_ids: BTreeSet = self.accounts.keys().copied().collect(); + + // First, add accounts in the configured order + for &id in &self.config.inner.accounts_order { + if all_ids.remove(&id) { + ordered_ids.push(id); + } + } + + // Then add any accounts not in the order list (newly added accounts) + for id in all_ids { + ordered_ids.push(id); + } + + ordered_ids + } + + /// Sets the order of accounts. + /// + /// The provided list should contain all account IDs in the desired order. + /// If an account ID is missing from the list, it will be appended at the end. + /// If the list contains non-existent account IDs, they will be ignored. + pub async fn set_accounts_order(&mut self, order: Vec) -> Result<()> { + let existing_ids: BTreeSet = self.accounts.keys().copied().collect(); + + // Filter out non-existent account IDs + let mut filtered_order: Vec = order + .into_iter() + .filter(|id| existing_ids.contains(id)) + .collect(); + + // Add any missing account IDs at the end + for &id in &existing_ids { + if !filtered_order.contains(&id) { + filtered_order.push(id); + } + } + + self.config.inner.accounts_order = filtered_order; + self.config.sync().await?; + self.emit_event(EventType::AccountsChanged); + Ok(()) } /// Starts background tasks such as IMAP and SMTP loops for all accounts. @@ -415,6 +457,10 @@ struct InnerConfig { pub selected_account: u32, pub next_id: u32, pub accounts: Vec, + /// Ordered list of account IDs, representing the user's preferred order. + /// If an account ID is not in this list, it will be appended at the end. + #[serde(default)] + pub accounts_order: Vec, } impl Drop for Config { @@ -481,6 +527,7 @@ impl Config { accounts: Vec::new(), selected_account: 0, next_id: 1, + accounts_order: Vec::new(), }; if !lock { let cfg = Self { @@ -613,6 +660,10 @@ impl Config { uuid, }); self.inner.next_id += 1; + + // Add new account to the end of the order list + self.inner.accounts_order.push(id); + id }; @@ -634,6 +685,10 @@ impl Config { // remove account from the configs self.inner.accounts.remove(idx); } + + // Remove from order list as well + self.inner.accounts_order.retain(|&x| x != id); + if self.inner.selected_account == id { // reset selected account self.inner.selected_account = self