feat: add account ordering functionality (#6993)

New public API `set_accounts_order` allows setting the order of accounts.

The account order is stored as a list of account IDs in `accounts.toml`
under a new `accounts_order: Vec<u32>` field.
This commit is contained in:
Alireza Sadraii
2025-07-11 00:59:27 +02:00
committed by GitHub
parent 22258f7269
commit ce5697c5f7
2 changed files with 66 additions and 3 deletions

View File

@@ -224,6 +224,14 @@ impl CommandApi {
self.accounts.read().await.get_selected_account_id() 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<u32>) -> Result<()> {
self.accounts.write().await.set_accounts_order(order).await
}
/// Get a list of all configured accounts. /// Get a list of all configured accounts.
async fn get_all_accounts(&self) -> Result<Vec<Account>> { async fn get_all_accounts(&self) -> Result<Vec<Account>> {
let mut accounts = Vec::new(); let mut accounts = Vec::new();

View File

@@ -1,6 +1,6 @@
//! # Account manager module. //! # Account manager module.
use std::collections::BTreeMap; use std::collections::{BTreeMap, BTreeSet};
use std::future::Future; use std::future::Future;
use std::path::{Path, PathBuf}; 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<u32> { pub fn get_all(&self) -> Vec<u32> {
self.accounts.keys().copied().collect() let mut ordered_ids = Vec::new();
let mut all_ids: BTreeSet<u32> = 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<u32>) -> Result<()> {
let existing_ids: BTreeSet<u32> = self.accounts.keys().copied().collect();
// Filter out non-existent account IDs
let mut filtered_order: Vec<u32> = 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. /// Starts background tasks such as IMAP and SMTP loops for all accounts.
@@ -415,6 +457,10 @@ struct InnerConfig {
pub selected_account: u32, pub selected_account: u32,
pub next_id: u32, pub next_id: u32,
pub accounts: Vec<AccountConfig>, pub accounts: Vec<AccountConfig>,
/// 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<u32>,
} }
impl Drop for Config { impl Drop for Config {
@@ -481,6 +527,7 @@ impl Config {
accounts: Vec::new(), accounts: Vec::new(),
selected_account: 0, selected_account: 0,
next_id: 1, next_id: 1,
accounts_order: Vec::new(),
}; };
if !lock { if !lock {
let cfg = Self { let cfg = Self {
@@ -613,6 +660,10 @@ impl Config {
uuid, uuid,
}); });
self.inner.next_id += 1; self.inner.next_id += 1;
// Add new account to the end of the order list
self.inner.accounts_order.push(id);
id id
}; };
@@ -634,6 +685,10 @@ impl Config {
// remove account from the configs // remove account from the configs
self.inner.accounts.remove(idx); 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 { if self.inner.selected_account == id {
// reset selected account // reset selected account
self.inner.selected_account = self self.inner.selected_account = self