diff --git a/res/menu/accounts_context.xml b/res/menu/accounts_context.xml
index e55d13a94..798d32d20 100644
--- a/res/menu/accounts_context.xml
+++ b/res/menu/accounts_context.xml
@@ -21,6 +21,10 @@
android:title="@string/remove_account_action" />
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fd36f1509..830ccf0a6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1073,4 +1073,7 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
Save attachment
No file browser found. Where would you like to save this attachment?
+ Move up
+ Move down
+
diff --git a/src/com/fsck/k9/Account.java b/src/com/fsck/k9/Account.java
index 9c9d23584..fb9b93869 100644
--- a/src/com/fsck/k9/Account.java
+++ b/src/com/fsck/k9/Account.java
@@ -21,7 +21,9 @@ import com.fsck.k9.view.ColorChip;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
+import java.util.Collections;
import java.util.Date;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -376,20 +378,30 @@ public class Account implements BaseAccount {
mCryptoApp = prefs.getString(mUuid + ".cryptoApp", Apg.NAME);
mCryptoAutoSignature = prefs.getBoolean(mUuid + ".cryptoAutoSignature", false);
}
-
-
- protected synchronized void delete(Preferences preferences) {
- String[] uuids = preferences.getPreferences().getString("accountUuids", "").split(",");
+
+ private String combineUuids(String[] uuids) {
StringBuffer sb = new StringBuffer();
for (int i = 0, length = uuids.length; i < length; i++) {
- if (!uuids[i].equals(mUuid)) {
- if (sb.length() > 0) {
- sb.append(',');
- }
- sb.append(uuids[i]);
+ if (sb.length() > 0) {
+ sb.append(',');
}
+ sb.append(uuids[i]);
}
String accountUuids = sb.toString();
+ return accountUuids;
+ }
+
+ protected synchronized void delete(Preferences preferences) {
+ String[] uuids = preferences.getPreferences().getString("accountUuids", "").split(",");
+ String[] newUuids = new String[uuids.length - 1];
+ int i = 0;
+ for (String uuid : uuids) {
+ if (uuid.equals(mUuid) == false) {
+ newUuids[i++] = uuid;
+ }
+ }
+
+ String accountUuids = combineUuids(newUuids);
SharedPreferences.Editor editor = preferences.getPreferences().edit();
editor.putString("accountUuids", accountUuids);
@@ -455,6 +467,64 @@ public class Account implements BaseAccount {
editor.commit();
}
+ public static int findNewAccountNumber(List accountNumbers) {
+ int newAccountNumber = -1;
+ Collections.sort(accountNumbers);
+ for (int accountNumber : accountNumbers) {
+ if (accountNumber > newAccountNumber + 1) {
+ break;
+ }
+ newAccountNumber = accountNumber;
+ }
+ newAccountNumber++;
+ return newAccountNumber;
+ }
+
+ public static List getExistingAccountNumbers(Preferences preferences) {
+ Account[] accounts = preferences.getAccounts();
+ List accountNumbers = new LinkedList();
+ for (int i = 0; i < accounts.length; i++) {
+ accountNumbers.add(accounts[i].getAccountNumber());
+ }
+ return accountNumbers;
+ }
+ public static int generateAccountNumber(Preferences preferences) {
+ List accountNumbers = getExistingAccountNumbers(preferences);
+ return findNewAccountNumber(accountNumbers);
+ }
+
+ public void move(Preferences preferences, boolean moveUp) {
+ String[] uuids = preferences.getPreferences().getString("accountUuids", "").split(",");
+ SharedPreferences.Editor editor = preferences.getPreferences().edit();
+ String[] newUuids = new String[uuids.length];
+ if (moveUp) {
+ for (int i = 0; i < uuids.length; i++) {
+ if (i > 0 && uuids[i].equals(mUuid)) {
+ newUuids[i] = newUuids[i-1];
+ newUuids[i-1] = mUuid;
+ }
+ else {
+ newUuids[i] = uuids[i];
+ }
+ }
+ }
+ else {
+ for (int i = uuids.length - 1; i >= 0; i--) {
+ if (i < uuids.length - 1 && uuids[i].equals(mUuid)) {
+ newUuids[i] = newUuids[i+1];
+ newUuids[i+1] = mUuid;
+ }
+ else {
+ newUuids[i] = uuids[i];
+ }
+ }
+ }
+ String accountUuids = combineUuids(newUuids);
+ editor.putString("accountUuids", accountUuids);
+ editor.commit();
+ preferences.refreshAccounts();
+ }
+
public synchronized void save(Preferences preferences) {
SharedPreferences.Editor editor = preferences.getPreferences().edit();
diff --git a/src/com/fsck/k9/Preferences.java b/src/com/fsck/k9/Preferences.java
index dece28412..6ee07f538 100644
--- a/src/com/fsck/k9/Preferences.java
+++ b/src/com/fsck/k9/Preferences.java
@@ -3,7 +3,11 @@ package com.fsck.k9;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Config;
@@ -29,7 +33,8 @@ public class Preferences {
private Storage mStorage;
- private List accounts;
+ private Map accounts = null;
+ private List accountsInOrder = null;
private Account newAccount;
private Context mContext;
@@ -45,16 +50,35 @@ public class Preferences {
}
private synchronized void loadAccounts() {
+ accounts = new HashMap();
+ refreshAccounts();
+ }
+
+ public synchronized void refreshAccounts() {
+ Map newAccountMap = new HashMap();
+ accountsInOrder = new LinkedList();
String accountUuids = getPreferences().getString("accountUuids", null);
if ((accountUuids != null) && (accountUuids.length() != 0)) {
String[] uuids = accountUuids.split(",");
- accounts = new ArrayList(uuids.length);
for (String uuid : uuids) {
- accounts.add(new Account(this, uuid));
+ Account account = accounts.get(uuid);
+ if (account != null) {
+ newAccountMap.put(uuid, account);
+ accountsInOrder.add(account);
+ } else {
+ Account newAccount = new Account(this, uuid);
+ newAccountMap.put(uuid, newAccount);
+ accountsInOrder.add(newAccount);
+ }
}
- } else {
- accounts = new ArrayList();
}
+ if ((newAccount != null) && newAccount.getAccountNumber() != -1) {
+ newAccountMap.put(newAccount.getUuid(), newAccount);
+ accountsInOrder.add(newAccount);
+ newAccount = null;
+ }
+
+ accounts = newAccountMap;
}
/**
@@ -67,12 +91,7 @@ public class Preferences {
loadAccounts();
}
- if ((newAccount != null) && newAccount.getAccountNumber() != -1) {
- accounts.add(newAccount);
- newAccount = null;
- }
-
- return accounts.toArray(EMPTY_ACCOUNT_ARRAY);
+ return accountsInOrder.toArray(EMPTY_ACCOUNT_ARRAY);
}
/**
@@ -81,16 +100,9 @@ public class Preferences {
* @return all accounts with {@link Account#isAvailable(Context)}
*/
public synchronized Collection getAvailableAccounts() {
- if (accounts == null) {
- loadAccounts();
- }
-
- if ((newAccount != null) && newAccount.getAccountNumber() != -1) {
- accounts.add(newAccount);
- newAccount = null;
- }
+ Account[] allAccounts = getAccounts();
Collection retval = new ArrayList(accounts.size());
- for (Account account : accounts) {
+ for (Account account : allAccounts) {
if (account.isAvailable(mContext)) {
retval.add(account);
}
@@ -103,28 +115,22 @@ public class Preferences {
if (accounts == null) {
loadAccounts();
}
+ Account account = accounts.get(uuid);
- for (Account account : accounts) {
- if (account.getUuid().equals(uuid)) {
- return account;
- }
- }
-
- if ((newAccount != null) && newAccount.getUuid().equals(uuid)) {
- return newAccount;
- }
-
- return null;
+ return account;
}
public synchronized Account newAccount() {
newAccount = new Account(K9.app);
+ accounts.put(newAccount.getUuid(), newAccount);
+ accountsInOrder.add(newAccount);
return newAccount;
}
public synchronized void deleteAccount(Account account) {
- accounts.remove(account);
+ accounts.remove(account.getUuid());
+ accountsInOrder.remove(account);
account.delete(this);
if (newAccount == account) {
diff --git a/src/com/fsck/k9/activity/Accounts.java b/src/com/fsck/k9/activity/Accounts.java
index 7053707fe..4b804b009 100644
--- a/src/com/fsck/k9/activity/Accounts.java
+++ b/src/com/fsck/k9/activity/Accounts.java
@@ -584,6 +584,12 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
case R.id.recreate:
onRecreate(realAccount);
break;
+ case R.id.move_up:
+ onMove(realAccount, true);
+ break;
+ case R.id.move_down:
+ onMove(realAccount, false);
+ break;
}
return true;
}
@@ -602,7 +608,22 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
private void onRecreate(Account account) {
showDialog(DIALOG_RECREATE_ACCOUNT);
}
-
+ private void onMove(final Account account, final boolean up) {
+ AsyncUIProcessor.getInstance(getApplication()).execute(
+ new Runnable()
+ {
+ @Override
+ public void run() {
+ account.move(Preferences.getPreferences(Accounts.this), up);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ refresh();
+ }
+ });
+ }
+ });
+ }
public void onItemClick(AdapterView> parent, View view, int position, long id) {
BaseAccount account = (BaseAccount)parent.getItemAtPosition(position);
diff --git a/src/com/fsck/k9/activity/AsyncUIProcessor.java b/src/com/fsck/k9/activity/AsyncUIProcessor.java
new file mode 100644
index 000000000..55947b2c4
--- /dev/null
+++ b/src/com/fsck/k9/activity/AsyncUIProcessor.java
@@ -0,0 +1,33 @@
+package com.fsck.k9.activity;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import android.app.Application;
+
+/**
+ * The class should be used to run long-running processes invoked from the UI that
+ * do not affect the Stores. There are probably pieces of MessagingController
+ * that can be moved here. There is no wakelock used here. Any network activity, or
+ * true background activity, that is invoked from here should wakelock itself. UI-centric
+ * activity does not need to be wakelocked, as it will simply continue when the phone wakes
+ * without disruption.
+ *
+ */
+public class AsyncUIProcessor {
+
+ private final ExecutorService threadPool = Executors.newCachedThreadPool();
+ private static AsyncUIProcessor inst = null;
+ private AsyncUIProcessor() {
+ }
+
+ public synchronized static AsyncUIProcessor getInstance(Application application) {
+ if (inst == null) {
+ inst = new AsyncUIProcessor();
+ }
+ return inst;
+ }
+ public void execute(Runnable runnable) {
+ threadPool.execute(runnable);
+ }
+}