diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 61717a32d..e1c7fc9a1 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -3119,6 +3119,18 @@ dc_context_t* dc_accounts_get_selected_account (dc_accounts_t* accounts); int dc_accounts_select_account (dc_accounts_t* accounts, uint32_t account_id); +/** + * Move an account and change the order returned by dc_accounts_get_all(). + * + * @param accounts + * @param to_move_id The account ID to move. + * @param predecessor_id `to_move_id` will be sorted below `predecessor_id`. + * Set to 0 to move `to_move_id` to the top of the list returned by dc_accounts_get_all(). + * @return 1=success, 0=error + */ +int dc_accounts_move_below (dc_accounts_t* accounts, uint32_t to_move_id, uint32_t predecessor_id); + + /** * Start job and IMAP/SMTP tasks for all accounts managed by the account manager. * If IO is already running, nothing happens. diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 6559ab663..c67e305be 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -4703,6 +4703,35 @@ pub unsafe extern "C" fn dc_accounts_select_account( }) } +#[no_mangle] +pub unsafe extern "C" fn dc_accounts_move_below( + accounts: *mut dc_accounts_t, + to_move_id: u32, + predecessor_id: u32, +) -> libc::c_int { + if accounts.is_null() { + eprintln!("ignoring careless call to dc_accounts_move_below()"); + return 0; + } + + let accounts = &*accounts; + let predecessor_id = if predecessor_id == 0 { + None + } else { + Some(predecessor_id) + }; + block_on(async move { + let mut accounts = accounts.write().await; + match accounts.move_below(to_move_id, predecessor_id).await { + Ok(()) => 1, + Err(err) => { + accounts.emit_event(EventType::Error(format!("Failed to move account: {err:#}"))); + 0 + } + } + }) +} + #[no_mangle] pub unsafe extern "C" fn dc_accounts_add_account(accounts: *mut dc_accounts_t) -> u32 { if accounts.is_null() { diff --git a/src/accounts.rs b/src/accounts.rs index 663513ddd..07af09ea8 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -1,5 +1,6 @@ //! # Account manager module. +use std::cmp::Ordering; use std::collections::BTreeMap; use std::future::Future; use std::path::{Path, PathBuf}; @@ -119,6 +120,12 @@ impl Accounts { Ok(()) } + /// Move an account and change the ordering returned by get_all(). + pub async fn move_below(&mut self, _to_move_id: u32, _predecessor_id: Option) -> Result<()> { + // TODO: change priority of affected accounts + Ok(()) + } + /// Adds a new account and opens it. /// /// Returns account ID. @@ -261,9 +268,19 @@ impl Accounts { } } + fn sort_accounts(a: &(&u32, &Context), b: &(&u32, &Context)) -> std::cmp::Ordering { + match a.1.sort_number.cmp(&b.1.sort_number) { + Ordering::Less => Ordering::Less, + Ordering::Equal => a.1.id.cmp(&b.1.id), + Ordering::Greater => Ordering::Greater, + } + } + /// Get a list of all account ids. pub fn get_all(&self) -> Vec { - self.accounts.keys().copied().collect() + let mut accounts_vec: Vec<_> = self.accounts.iter().collect(); + accounts_vec.sort_by(Accounts::sort_accounts); + return accounts_vec.into_iter().map(|(&k, _)| k).collect(); } /// Starts background tasks such as IMAP and SMTP loops for all accounts. diff --git a/src/context.rs b/src/context.rs index 9e9a232d7..bdbc0c130 100644 --- a/src/context.rs +++ b/src/context.rs @@ -272,6 +272,9 @@ pub struct InnerContext { creation_time: tools::Time, + /// Accounts with higher numbers are returned at beginning of get_all(). + pub(crate) sort_number: u32, + /// The text of the last error logged and emitted as an event. /// If the ui wants to display an error after a failure, /// `last_error` should be used to avoid races with the event thread. @@ -427,6 +430,7 @@ impl Context { let inner = InnerContext { id, + sort_number: 0, blobdir, running_state: RwLock::new(Default::default()), sql: Sql::new(dbfile),