Merge pull request #5209 from k9mail/convert_to_kotlin
This commit is contained in:
commit
cc2413a180
14 changed files with 316 additions and 385 deletions
|
@ -13,7 +13,15 @@ import com.fsck.k9.setup.ServerNameSuggester
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val mainModule = module {
|
val mainModule = module {
|
||||||
single { Preferences.getPreferences(get()) }
|
single {
|
||||||
|
Preferences(
|
||||||
|
context = get(),
|
||||||
|
storagePersister = get(),
|
||||||
|
localStoreProvider = get(),
|
||||||
|
localKeyStoreManager = get(),
|
||||||
|
accountPreferenceSerializer = get()
|
||||||
|
)
|
||||||
|
}
|
||||||
single { get<Context>().resources }
|
single { get<Context>().resources }
|
||||||
single { get<Context>().contentResolver }
|
single { get<Context>().contentResolver }
|
||||||
single { LocalStoreProvider() }
|
single { LocalStoreProvider() }
|
||||||
|
|
|
@ -1,329 +0,0 @@
|
||||||
|
|
||||||
package com.fsck.k9;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import androidx.annotation.GuardedBy;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.RestrictTo;
|
|
||||||
import androidx.annotation.RestrictTo.Scope;
|
|
||||||
|
|
||||||
import com.fsck.k9.backend.BackendManager;
|
|
||||||
import com.fsck.k9.mail.MessagingException;
|
|
||||||
import com.fsck.k9.mailstore.LocalStore;
|
|
||||||
import com.fsck.k9.mailstore.LocalStoreProvider;
|
|
||||||
import com.fsck.k9.preferences.Storage;
|
|
||||||
import com.fsck.k9.preferences.StorageEditor;
|
|
||||||
import com.fsck.k9.preferences.StoragePersister;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
|
|
||||||
public class Preferences {
|
|
||||||
|
|
||||||
private static Preferences preferences;
|
|
||||||
private AccountPreferenceSerializer accountPreferenceSerializer;
|
|
||||||
|
|
||||||
public static synchronized Preferences getPreferences(Context context) {
|
|
||||||
if (preferences == null) {
|
|
||||||
Context appContext = context.getApplicationContext();
|
|
||||||
CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
|
|
||||||
LocalKeyStoreManager localKeyStoreManager = DI.get(LocalKeyStoreManager.class);
|
|
||||||
AccountPreferenceSerializer accountPreferenceSerializer = DI.get(AccountPreferenceSerializer.class);
|
|
||||||
LocalStoreProvider localStoreProvider = DI.get(LocalStoreProvider.class);
|
|
||||||
StoragePersister storagePersister = DI.get(StoragePersister.class);
|
|
||||||
|
|
||||||
preferences = new Preferences(appContext, resourceProvider, storagePersister, localStoreProvider, localKeyStoreManager, accountPreferenceSerializer);
|
|
||||||
}
|
|
||||||
return preferences;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Storage storage;
|
|
||||||
@GuardedBy("accountLock")
|
|
||||||
private Map<String, Account> accounts = null;
|
|
||||||
@GuardedBy("accountLock")
|
|
||||||
private List<Account> accountsInOrder = null;
|
|
||||||
@GuardedBy("accountLock")
|
|
||||||
private Account newAccount;
|
|
||||||
|
|
||||||
private final List<AccountsChangeListener> accountsChangeListeners = new CopyOnWriteArrayList<>();
|
|
||||||
private final Context context;
|
|
||||||
private final LocalStoreProvider localStoreProvider;
|
|
||||||
private final CoreResourceProvider resourceProvider;
|
|
||||||
private final LocalKeyStoreManager localKeyStoreManager;
|
|
||||||
private final StoragePersister storagePersister;
|
|
||||||
|
|
||||||
private final Object accountLock = new Object();
|
|
||||||
|
|
||||||
private Preferences(Context context, CoreResourceProvider resourceProvider,
|
|
||||||
StoragePersister storagePersister, LocalStoreProvider localStoreProvider,
|
|
||||||
LocalKeyStoreManager localKeyStoreManager,
|
|
||||||
AccountPreferenceSerializer accountPreferenceSerializer) {
|
|
||||||
this.storage = new Storage();
|
|
||||||
this.storagePersister = storagePersister;
|
|
||||||
this.context = context;
|
|
||||||
this.resourceProvider = resourceProvider;
|
|
||||||
this.localStoreProvider = localStoreProvider;
|
|
||||||
this.localKeyStoreManager = localKeyStoreManager;
|
|
||||||
this.accountPreferenceSerializer = accountPreferenceSerializer;
|
|
||||||
|
|
||||||
Map<String, String> persistedStorageValues = storagePersister.loadValues();
|
|
||||||
storage.replaceAll(persistedStorageValues);
|
|
||||||
|
|
||||||
if (storage.isEmpty()) {
|
|
||||||
Timber.i("Preferences storage is zero-size, importing from Android-style preferences");
|
|
||||||
StorageEditor editor = createStorageEditor();
|
|
||||||
editor.copy(context.getSharedPreferences("AndroidMail.Main", Context.MODE_PRIVATE));
|
|
||||||
editor.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StorageEditor createStorageEditor() {
|
|
||||||
return storagePersister.createStorageEditor(storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RestrictTo(Scope.TESTS)
|
|
||||||
public void clearAccounts() {
|
|
||||||
synchronized (accountLock) {
|
|
||||||
accounts = new HashMap<>();
|
|
||||||
accountsInOrder = new LinkedList<>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadAccounts() {
|
|
||||||
synchronized (accountLock) {
|
|
||||||
accounts = new HashMap<>();
|
|
||||||
accountsInOrder = new LinkedList<>();
|
|
||||||
String accountUuids = getStorage().getString("accountUuids", null);
|
|
||||||
if ((accountUuids != null) && (accountUuids.length() != 0)) {
|
|
||||||
String[] uuids = accountUuids.split(",");
|
|
||||||
for (String uuid : uuids) {
|
|
||||||
Account newAccount = new Account(uuid);
|
|
||||||
accountPreferenceSerializer.loadAccount(newAccount, storage);
|
|
||||||
accounts.put(uuid, newAccount);
|
|
||||||
accountsInOrder.add(newAccount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((newAccount != null) && newAccount.getAccountNumber() != -1) {
|
|
||||||
accounts.put(newAccount.getUuid(), newAccount);
|
|
||||||
if (!accountsInOrder.contains(newAccount)) {
|
|
||||||
accountsInOrder.add(newAccount);
|
|
||||||
}
|
|
||||||
newAccount = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of the accounts on the system. If no accounts are
|
|
||||||
* registered the method returns an empty array.
|
|
||||||
*
|
|
||||||
* @return all accounts
|
|
||||||
*/
|
|
||||||
public List<Account> getAccounts() {
|
|
||||||
synchronized (accountLock) {
|
|
||||||
if (accounts == null) {
|
|
||||||
loadAccounts();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(new ArrayList<>(accountsInOrder));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of the accounts on the system. If no accounts are
|
|
||||||
* registered the method returns an empty array.
|
|
||||||
*
|
|
||||||
* @return all accounts with {@link Account#isAvailable(Context)}
|
|
||||||
*/
|
|
||||||
public Collection<Account> getAvailableAccounts() {
|
|
||||||
List<Account> allAccounts = getAccounts();
|
|
||||||
Collection<Account> result = new ArrayList<>(allAccounts.size());
|
|
||||||
for (Account account : allAccounts) {
|
|
||||||
if (account.isAvailable(context)) {
|
|
||||||
result.add(account);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Account getAccount(String uuid) {
|
|
||||||
synchronized (accountLock) {
|
|
||||||
if (accounts == null) {
|
|
||||||
loadAccounts();
|
|
||||||
}
|
|
||||||
|
|
||||||
return accounts.get(uuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Account newAccount() {
|
|
||||||
synchronized (accountLock) {
|
|
||||||
String accountUuid = UUID.randomUUID().toString();
|
|
||||||
newAccount = new Account(accountUuid);
|
|
||||||
accountPreferenceSerializer.loadDefaults(newAccount);
|
|
||||||
accounts.put(newAccount.getUuid(), newAccount);
|
|
||||||
accountsInOrder.add(newAccount);
|
|
||||||
|
|
||||||
return newAccount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteAccount(Account account) {
|
|
||||||
synchronized (accountLock) {
|
|
||||||
if (accounts != null) {
|
|
||||||
accounts.remove(account.getUuid());
|
|
||||||
}
|
|
||||||
if (accountsInOrder != null) {
|
|
||||||
accountsInOrder.remove(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
getBackendManager().removeBackend(account);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Timber.e(e, "Failed to reset remote store for account %s", account.getUuid());
|
|
||||||
}
|
|
||||||
LocalStore.removeAccount(account);
|
|
||||||
|
|
||||||
StorageEditor storageEditor = createStorageEditor();
|
|
||||||
accountPreferenceSerializer.delete(storageEditor, storage, account);
|
|
||||||
storageEditor.commit();
|
|
||||||
localKeyStoreManager.deleteCertificates(account);
|
|
||||||
|
|
||||||
if (newAccount == account) {
|
|
||||||
newAccount = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Account marked as default. If no account is marked as default
|
|
||||||
* the first account in the list is marked as default and then returned. If
|
|
||||||
* there are no accounts on the system the method returns null.
|
|
||||||
*/
|
|
||||||
public Account getDefaultAccount() {
|
|
||||||
Account defaultAccount;
|
|
||||||
synchronized (accountLock) {
|
|
||||||
String defaultAccountUuid = getStorage().getString("defaultAccountUuid", null);
|
|
||||||
defaultAccount = getAccount(defaultAccountUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defaultAccount == null) {
|
|
||||||
Collection<Account> accounts = getAvailableAccounts();
|
|
||||||
if (!accounts.isEmpty()) {
|
|
||||||
defaultAccount = accounts.iterator().next();
|
|
||||||
setDefaultAccount(defaultAccount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultAccount(Account account) {
|
|
||||||
createStorageEditor().putString("defaultAccountUuid", account.getUuid()).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Storage getStorage() {
|
|
||||||
return storage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BackendManager getBackendManager() {
|
|
||||||
return DI.get(BackendManager.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveAccount(Account account) {
|
|
||||||
ensureAssignedAccountNumber(account);
|
|
||||||
processChangedValues(account);
|
|
||||||
|
|
||||||
StorageEditor editor = createStorageEditor();
|
|
||||||
accountPreferenceSerializer.save(editor, storage, account);
|
|
||||||
editor.commit();
|
|
||||||
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureAssignedAccountNumber(Account account) {
|
|
||||||
if (account.getAccountNumber() != Account.UNASSIGNED_ACCOUNT_NUMBER) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int accountNumber = generateAccountNumber();
|
|
||||||
account.setAccountNumber(accountNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processChangedValues(Account account) {
|
|
||||||
if (account.isChangedVisibleLimits()) {
|
|
||||||
try {
|
|
||||||
localStoreProvider.getInstance(account).resetVisibleLimits(account.getDisplayCount());
|
|
||||||
} catch (MessagingException e) {
|
|
||||||
Timber.e(e, "Failed to load LocalStore!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
account.resetChangeMarkers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int generateAccountNumber() {
|
|
||||||
List<Integer> accountNumbers = getExistingAccountNumbers();
|
|
||||||
return findNewAccountNumber(accountNumbers);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Integer> getExistingAccountNumbers() {
|
|
||||||
List<Account> accounts = getAccounts();
|
|
||||||
List<Integer> accountNumbers = new ArrayList<>(accounts.size());
|
|
||||||
for (Account a : accounts) {
|
|
||||||
accountNumbers.add(a.getAccountNumber());
|
|
||||||
}
|
|
||||||
return accountNumbers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int findNewAccountNumber(List<Integer> accountNumbers) {
|
|
||||||
int newAccountNumber = -1;
|
|
||||||
Collections.sort(accountNumbers);
|
|
||||||
for (int accountNumber : accountNumbers) {
|
|
||||||
if (accountNumber > newAccountNumber + 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
newAccountNumber = accountNumber;
|
|
||||||
}
|
|
||||||
newAccountNumber++;
|
|
||||||
return newAccountNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void move(Account account, boolean mUp) {
|
|
||||||
synchronized (accountLock) {
|
|
||||||
StorageEditor storageEditor = createStorageEditor();
|
|
||||||
accountPreferenceSerializer.move(storageEditor, account, storage, mUp);
|
|
||||||
storageEditor.commit();
|
|
||||||
loadAccounts();
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void notifyListeners() {
|
|
||||||
for (AccountsChangeListener listener : accountsChangeListeners) {
|
|
||||||
listener.onAccountsChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addOnAccountsChangeListener(@NonNull AccountsChangeListener accountsChangeListener) {
|
|
||||||
accountsChangeListeners.add(accountsChangeListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeOnAccountsChangeListener(@NonNull AccountsChangeListener accountsChangeListener) {
|
|
||||||
accountsChangeListeners.remove(accountsChangeListener);
|
|
||||||
}
|
|
||||||
}
|
|
263
app/core/src/main/java/com/fsck/k9/Preferences.kt
Normal file
263
app/core/src/main/java/com/fsck/k9/Preferences.kt
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
package com.fsck.k9
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.annotation.GuardedBy
|
||||||
|
import androidx.annotation.RestrictTo
|
||||||
|
import com.fsck.k9.backend.BackendManager
|
||||||
|
import com.fsck.k9.mail.MessagingException
|
||||||
|
import com.fsck.k9.mailstore.LocalStore
|
||||||
|
import com.fsck.k9.mailstore.LocalStoreProvider
|
||||||
|
import com.fsck.k9.preferences.Storage
|
||||||
|
import com.fsck.k9.preferences.StorageEditor
|
||||||
|
import com.fsck.k9.preferences.StoragePersister
|
||||||
|
import java.util.HashMap
|
||||||
|
import java.util.LinkedList
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.inject
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
class Preferences internal constructor(
|
||||||
|
private val context: Context,
|
||||||
|
private val storagePersister: StoragePersister,
|
||||||
|
private val localStoreProvider: LocalStoreProvider,
|
||||||
|
private val localKeyStoreManager: LocalKeyStoreManager,
|
||||||
|
private val accountPreferenceSerializer: AccountPreferenceSerializer
|
||||||
|
) : KoinComponent {
|
||||||
|
private val backendManager: BackendManager by inject()
|
||||||
|
|
||||||
|
private val accountLock = Any()
|
||||||
|
|
||||||
|
@GuardedBy("accountLock")
|
||||||
|
private var accountsMap: MutableMap<String, Account>? = null
|
||||||
|
|
||||||
|
@GuardedBy("accountLock")
|
||||||
|
private var accountsInOrder = mutableListOf<Account>()
|
||||||
|
|
||||||
|
@GuardedBy("accountLock")
|
||||||
|
private var newAccount: Account? = null
|
||||||
|
private val accountsChangeListeners = CopyOnWriteArrayList<AccountsChangeListener>()
|
||||||
|
|
||||||
|
val storage = Storage()
|
||||||
|
|
||||||
|
init {
|
||||||
|
val persistedStorageValues = storagePersister.loadValues()
|
||||||
|
storage.replaceAll(persistedStorageValues)
|
||||||
|
|
||||||
|
if (storage.isEmpty) {
|
||||||
|
Timber.i("Preferences storage is zero-size, importing from Android-style preferences")
|
||||||
|
|
||||||
|
val editor = createStorageEditor()
|
||||||
|
editor.copy(context.getSharedPreferences("AndroidMail.Main", Context.MODE_PRIVATE))
|
||||||
|
editor.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createStorageEditor(): StorageEditor {
|
||||||
|
return storagePersister.createStorageEditor(storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestrictTo(RestrictTo.Scope.TESTS)
|
||||||
|
fun clearAccounts() {
|
||||||
|
synchronized(accountLock) {
|
||||||
|
accountsMap = HashMap()
|
||||||
|
accountsInOrder = LinkedList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadAccounts() {
|
||||||
|
synchronized(accountLock) {
|
||||||
|
val accounts = mutableMapOf<String, Account>()
|
||||||
|
val accountsInOrder = mutableListOf<Account>()
|
||||||
|
|
||||||
|
val accountUuids = storage.getString("accountUuids", null)
|
||||||
|
if (!accountUuids.isNullOrEmpty()) {
|
||||||
|
accountUuids.split(",").forEach { uuid ->
|
||||||
|
val newAccount = Account(uuid)
|
||||||
|
accountPreferenceSerializer.loadAccount(newAccount, storage)
|
||||||
|
|
||||||
|
accounts[uuid] = newAccount
|
||||||
|
accountsInOrder.add(newAccount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newAccount?.takeIf { it.accountNumber != -1 }?.let { newAccount ->
|
||||||
|
accounts[newAccount.uuid] = newAccount
|
||||||
|
if (newAccount !in accountsInOrder) {
|
||||||
|
accountsInOrder.add(newAccount)
|
||||||
|
}
|
||||||
|
this.newAccount = null
|
||||||
|
}
|
||||||
|
|
||||||
|
this.accountsMap = accounts
|
||||||
|
this.accountsInOrder = accountsInOrder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val accounts: List<Account>
|
||||||
|
get() {
|
||||||
|
synchronized(accountLock) {
|
||||||
|
if (accountsMap == null) {
|
||||||
|
loadAccounts()
|
||||||
|
}
|
||||||
|
|
||||||
|
return accountsInOrder.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val availableAccounts: Collection<Account>
|
||||||
|
get() = accounts.filter { it.isAvailable(context) }
|
||||||
|
|
||||||
|
fun getAccount(uuid: String): Account? {
|
||||||
|
synchronized(accountLock) {
|
||||||
|
if (accountsMap == null) {
|
||||||
|
loadAccounts()
|
||||||
|
}
|
||||||
|
|
||||||
|
return accountsMap!![uuid]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun newAccount(): Account {
|
||||||
|
val accountUuid = UUID.randomUUID().toString()
|
||||||
|
val account = Account(accountUuid)
|
||||||
|
accountPreferenceSerializer.loadDefaults(account)
|
||||||
|
|
||||||
|
synchronized(accountLock) {
|
||||||
|
newAccount = account
|
||||||
|
accountsMap!![account.uuid] = account
|
||||||
|
accountsInOrder.add(account)
|
||||||
|
}
|
||||||
|
|
||||||
|
return account
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteAccount(account: Account) {
|
||||||
|
synchronized(accountLock) {
|
||||||
|
accountsMap?.remove(account.uuid)
|
||||||
|
accountsInOrder.remove(account)
|
||||||
|
|
||||||
|
try {
|
||||||
|
backendManager.removeBackend(account)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "Failed to reset remote store for account %s", account.uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalStore.removeAccount(account)
|
||||||
|
|
||||||
|
val storageEditor = createStorageEditor()
|
||||||
|
accountPreferenceSerializer.delete(storageEditor, storage, account)
|
||||||
|
storageEditor.commit()
|
||||||
|
|
||||||
|
localKeyStoreManager.deleteCertificates(account)
|
||||||
|
|
||||||
|
if (account === newAccount) {
|
||||||
|
newAccount = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyListeners()
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultAccount: Account?
|
||||||
|
get() {
|
||||||
|
return getDefaultAccountOrNull() ?: availableAccounts.firstOrNull()?.also { newDefaultAccount ->
|
||||||
|
defaultAccount = newDefaultAccount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set(account) {
|
||||||
|
requireNotNull(account)
|
||||||
|
|
||||||
|
createStorageEditor()
|
||||||
|
.putString("defaultAccountUuid", account.uuid)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getDefaultAccountOrNull(): Account? {
|
||||||
|
return synchronized(accountLock) {
|
||||||
|
storage.getString("defaultAccountUuid", null)?.let { defaultAccountUuid ->
|
||||||
|
getAccount(defaultAccountUuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveAccount(account: Account) {
|
||||||
|
ensureAssignedAccountNumber(account)
|
||||||
|
processChangedValues(account)
|
||||||
|
|
||||||
|
val editor = createStorageEditor()
|
||||||
|
accountPreferenceSerializer.save(editor, storage, account)
|
||||||
|
editor.commit()
|
||||||
|
|
||||||
|
notifyListeners()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ensureAssignedAccountNumber(account: Account) {
|
||||||
|
if (account.accountNumber != Account.UNASSIGNED_ACCOUNT_NUMBER) return
|
||||||
|
|
||||||
|
account.accountNumber = generateAccountNumber()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processChangedValues(account: Account) {
|
||||||
|
if (account.isChangedVisibleLimits) {
|
||||||
|
try {
|
||||||
|
localStoreProvider.getInstance(account).resetVisibleLimits(account.displayCount)
|
||||||
|
} catch (e: MessagingException) {
|
||||||
|
Timber.e(e, "Failed to load LocalStore!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
account.resetChangeMarkers()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateAccountNumber(): Int {
|
||||||
|
val accountNumbers = accounts.map { it.accountNumber }
|
||||||
|
return findNewAccountNumber(accountNumbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findNewAccountNumber(accountNumbers: List<Int>): Int {
|
||||||
|
var newAccountNumber = -1
|
||||||
|
for (accountNumber in accountNumbers.sorted()) {
|
||||||
|
if (accountNumber > newAccountNumber + 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
newAccountNumber = accountNumber
|
||||||
|
}
|
||||||
|
newAccountNumber++
|
||||||
|
|
||||||
|
return newAccountNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
fun move(account: Account, up: Boolean) {
|
||||||
|
synchronized(accountLock) {
|
||||||
|
val storageEditor = createStorageEditor()
|
||||||
|
accountPreferenceSerializer.move(storageEditor, account, storage, up)
|
||||||
|
storageEditor.commit()
|
||||||
|
|
||||||
|
loadAccounts()
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyListeners()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun notifyListeners() {
|
||||||
|
for (listener in accountsChangeListeners) {
|
||||||
|
listener.onAccountsChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addOnAccountsChangeListener(accountsChangeListener: AccountsChangeListener) {
|
||||||
|
accountsChangeListeners.add(accountsChangeListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeOnAccountsChangeListener(accountsChangeListener: AccountsChangeListener) {
|
||||||
|
accountsChangeListeners.remove(accountsChangeListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun getPreferences(context: Context): Preferences {
|
||||||
|
return DI.get(Preferences::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ class K9JobManager(
|
||||||
private fun scheduleMailSync() {
|
private fun scheduleMailSync() {
|
||||||
cancelAllMailSyncJobs()
|
cancelAllMailSyncJobs()
|
||||||
|
|
||||||
preferences.availableAccounts?.forEach { account ->
|
preferences.availableAccounts.forEach { account ->
|
||||||
mailSyncWorkerManager.scheduleMailSync(account)
|
mailSyncWorkerManager.scheduleMailSync(account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,8 +65,9 @@ class SettingsExporter(
|
||||||
|
|
||||||
serializer.startTag(null, ACCOUNTS_ELEMENT)
|
serializer.startTag(null, ACCOUNTS_ELEMENT)
|
||||||
for (accountUuid in accountUuids) {
|
for (accountUuid in accountUuids) {
|
||||||
val account = preferences.getAccount(accountUuid)
|
preferences.getAccount(accountUuid)?.let { account ->
|
||||||
writeAccount(serializer, account, prefs)
|
writeAccount(serializer, account, prefs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.endTag(null, ACCOUNTS_ELEMENT)
|
serializer.endTag(null, ACCOUNTS_ELEMENT)
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
package com.fsck.k9.controller;
|
package com.fsck.k9.controller;
|
||||||
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.fsck.k9.Account;
|
import com.fsck.k9.Account;
|
||||||
import com.fsck.k9.AccountPreferenceSerializer;
|
|
||||||
import com.fsck.k9.DI;
|
|
||||||
import com.fsck.k9.K9;
|
import com.fsck.k9.K9;
|
||||||
import com.fsck.k9.K9RobolectricTest;
|
import com.fsck.k9.K9RobolectricTest;
|
||||||
import com.fsck.k9.Preferences;
|
import com.fsck.k9.Preferences;
|
||||||
|
@ -46,7 +42,6 @@ import org.mockito.ArgumentMatchers;
|
||||||
import org.mockito.Captor;
|
import org.mockito.Captor;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
@ -62,7 +57,6 @@ import static org.mockito.Mockito.doThrow;
|
||||||
import static org.mockito.Mockito.inOrder;
|
import static org.mockito.Mockito.inOrder;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
@ -74,7 +68,6 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
private static final String FOLDER_NAME = "Folder";
|
private static final String FOLDER_NAME = "Folder";
|
||||||
private static final long SENT_FOLDER_ID = 10;
|
private static final long SENT_FOLDER_ID = 10;
|
||||||
private static final int MAXIMUM_SMALL_MESSAGE_SIZE = 1000;
|
private static final int MAXIMUM_SMALL_MESSAGE_SIZE = 1000;
|
||||||
private static final String ACCOUNT_UUID = "1";
|
|
||||||
|
|
||||||
private MessagingController controller;
|
private MessagingController controller;
|
||||||
private Account account;
|
private Account account;
|
||||||
|
@ -130,6 +123,9 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private Preferences preferences;
|
||||||
|
private String accountUuid;
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws MessagingException {
|
public void setUp() throws MessagingException {
|
||||||
|
@ -137,7 +133,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
appContext = RuntimeEnvironment.application;
|
appContext = RuntimeEnvironment.application;
|
||||||
|
|
||||||
Preferences preferences = Preferences.getPreferences(appContext);
|
preferences = Preferences.getPreferences(appContext);
|
||||||
|
|
||||||
controller = new MessagingController(appContext, notificationController, notificationStrategy,
|
controller = new MessagingController(appContext, notificationController, notificationStrategy,
|
||||||
localStoreProvider, unreadMessageCountProvider, backendManager, preferences, messageStoreProvider,
|
localStoreProvider, unreadMessageCountProvider, backendManager, preferences, messageStoreProvider,
|
||||||
|
@ -186,7 +182,6 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
@Test
|
@Test
|
||||||
public void searchLocalMessagesSynchronous_shouldCallSearchForMessagesOnLocalStore()
|
public void searchLocalMessagesSynchronous_shouldCallSearchForMessagesOnLocalStore()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
setAccountsInPreferences(Collections.singletonMap(ACCOUNT_UUID, account));
|
|
||||||
when(search.searchAllAccounts()).thenReturn(true);
|
when(search.searchAllAccounts()).thenReturn(true);
|
||||||
when(search.getAccountUuids()).thenReturn(new String[0]);
|
when(search.getAccountUuids()).thenReturn(new String[0]);
|
||||||
|
|
||||||
|
@ -198,7 +193,6 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
@Test
|
@Test
|
||||||
public void searchLocalMessagesSynchronous_shouldNotifyWhenStoreFinishesRetrievingAMessage()
|
public void searchLocalMessagesSynchronous_shouldNotifyWhenStoreFinishesRetrievingAMessage()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
setAccountsInPreferences(Collections.singletonMap(ACCOUNT_UUID, account));
|
|
||||||
LocalMessage localMessage = mock(LocalMessage.class);
|
LocalMessage localMessage = mock(LocalMessage.class);
|
||||||
when(localMessage.getFolder()).thenReturn(localFolder);
|
when(localMessage.getFolder()).thenReturn(localFolder);
|
||||||
when(search.searchAllAccounts()).thenReturn(true);
|
when(search.searchAllAccounts()).thenReturn(true);
|
||||||
|
@ -215,8 +209,6 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupRemoteSearch() throws Exception {
|
private void setupRemoteSearch() throws Exception {
|
||||||
setAccountsInPreferences(Collections.singletonMap(ACCOUNT_UUID, account));
|
|
||||||
|
|
||||||
remoteMessages = new ArrayList<>();
|
remoteMessages = new ArrayList<>();
|
||||||
Collections.addAll(remoteMessages, "oldMessageUid", "newMessageUid1", "newMessageUid2");
|
Collections.addAll(remoteMessages, "oldMessageUid", "newMessageUid1", "newMessageUid2");
|
||||||
List<String> newRemoteMessages = new ArrayList<>();
|
List<String> newRemoteMessages = new ArrayList<>();
|
||||||
|
@ -261,7 +253,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
public void searchRemoteMessagesSynchronous_shouldNotifyStartedListingRemoteMessages() throws Exception {
|
public void searchRemoteMessagesSynchronous_shouldNotifyStartedListingRemoteMessages() throws Exception {
|
||||||
setupRemoteSearch();
|
setupRemoteSearch();
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(listener).remoteSearchStarted(FOLDER_ID);
|
verify(listener).remoteSearchStarted(FOLDER_ID);
|
||||||
}
|
}
|
||||||
|
@ -270,7 +262,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
public void searchRemoteMessagesSynchronous_shouldQueryRemoteFolder() throws Exception {
|
public void searchRemoteMessagesSynchronous_shouldQueryRemoteFolder() throws Exception {
|
||||||
setupRemoteSearch();
|
setupRemoteSearch();
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(backend).search(FOLDER_NAME, "query", reqFlags, forbiddenFlags, false);
|
verify(backend).search(FOLDER_NAME, "query", reqFlags, forbiddenFlags, false);
|
||||||
}
|
}
|
||||||
|
@ -279,7 +271,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
public void searchRemoteMessagesSynchronous_shouldAskLocalFolderToDetermineNewMessages() throws Exception {
|
public void searchRemoteMessagesSynchronous_shouldAskLocalFolderToDetermineNewMessages() throws Exception {
|
||||||
setupRemoteSearch();
|
setupRemoteSearch();
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(localFolder).extractNewMessages(remoteMessages);
|
verify(localFolder).extractNewMessages(remoteMessages);
|
||||||
}
|
}
|
||||||
|
@ -288,7 +280,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
public void searchRemoteMessagesSynchronous_shouldTryAndGetNewMessages() throws Exception {
|
public void searchRemoteMessagesSynchronous_shouldTryAndGetNewMessages() throws Exception {
|
||||||
setupRemoteSearch();
|
setupRemoteSearch();
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(localFolder).getMessage("newMessageUid1");
|
verify(localFolder).getMessage("newMessageUid1");
|
||||||
}
|
}
|
||||||
|
@ -297,7 +289,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
public void searchRemoteMessagesSynchronous_shouldNotTryAndGetOldMessages() throws Exception {
|
public void searchRemoteMessagesSynchronous_shouldNotTryAndGetOldMessages() throws Exception {
|
||||||
setupRemoteSearch();
|
setupRemoteSearch();
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(localFolder, never()).getMessage("oldMessageUid");
|
verify(localFolder, never()).getMessage("oldMessageUid");
|
||||||
}
|
}
|
||||||
|
@ -306,7 +298,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
public void searchRemoteMessagesSynchronous_shouldFetchNewMessages() throws Exception {
|
public void searchRemoteMessagesSynchronous_shouldFetchNewMessages() throws Exception {
|
||||||
setupRemoteSearch();
|
setupRemoteSearch();
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(backend).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid2"), fetchProfileCaptor.capture(),
|
verify(backend).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid2"), fetchProfileCaptor.capture(),
|
||||||
eq(MAXIMUM_SMALL_MESSAGE_SIZE));
|
eq(MAXIMUM_SMALL_MESSAGE_SIZE));
|
||||||
|
@ -316,7 +308,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
public void searchRemoteMessagesSynchronous_shouldNotFetchExistingMessages() throws Exception {
|
public void searchRemoteMessagesSynchronous_shouldNotFetchExistingMessages() throws Exception {
|
||||||
setupRemoteSearch();
|
setupRemoteSearch();
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(backend, never()).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid1"), fetchProfileCaptor.capture(),
|
verify(backend, never()).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid1"), fetchProfileCaptor.capture(),
|
||||||
eq(MAXIMUM_SMALL_MESSAGE_SIZE));
|
eq(MAXIMUM_SMALL_MESSAGE_SIZE));
|
||||||
|
@ -328,7 +320,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
when(backend.search(anyString(), anyString(), nullable(Set.class), nullable(Set.class), eq(false)))
|
when(backend.search(anyString(), anyString(), nullable(Set.class), nullable(Set.class), eq(false)))
|
||||||
.thenThrow(new MessagingException("Test"));
|
.thenThrow(new MessagingException("Test"));
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(listener).remoteSearchFailed(null, "Test");
|
verify(listener).remoteSearchFailed(null, "Test");
|
||||||
}
|
}
|
||||||
|
@ -339,14 +331,14 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
when(backend.search(anyString(), nullable(String.class), nullable(Set.class), nullable(Set.class), eq(false)))
|
when(backend.search(anyString(), nullable(String.class), nullable(Set.class), nullable(Set.class), eq(false)))
|
||||||
.thenThrow(new MessagingException("Test"));
|
.thenThrow(new MessagingException("Test"));
|
||||||
|
|
||||||
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
controller.searchRemoteMessagesSynchronous(accountUuid, FOLDER_ID, "query", reqFlags, forbiddenFlags, listener);
|
||||||
|
|
||||||
verify(listener).remoteSearchFinished(FOLDER_ID, 0, 50, Collections.<String>emptyList());
|
verify(listener).remoteSearchFinished(FOLDER_ID, 0, 50, Collections.<String>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendPendingMessagesSynchronous_withNonExistentOutbox_shouldNotStartSync() throws MessagingException {
|
public void sendPendingMessagesSynchronous_withNonExistentOutbox_shouldNotStartSync() throws MessagingException {
|
||||||
when(account.getOutboxFolderId()).thenReturn(FOLDER_ID);
|
account.setOutboxFolderId(FOLDER_ID);
|
||||||
when(localFolder.exists()).thenReturn(false);
|
when(localFolder.exists()).thenReturn(false);
|
||||||
controller.addListener(listener);
|
controller.addListener(listener);
|
||||||
|
|
||||||
|
@ -433,7 +425,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupAccountWithMessageToSend() throws MessagingException {
|
private void setupAccountWithMessageToSend() throws MessagingException {
|
||||||
when(account.getOutboxFolderId()).thenReturn(FOLDER_ID);
|
account.setOutboxFolderId(FOLDER_ID);
|
||||||
account.setSentFolderId(SENT_FOLDER_ID);
|
account.setSentFolderId(SENT_FOLDER_ID);
|
||||||
when(localStore.getFolder(SENT_FOLDER_ID)).thenReturn(sentFolder);
|
when(localStore.getFolder(SENT_FOLDER_ID)).thenReturn(sentFolder);
|
||||||
when(sentFolder.getDatabaseId()).thenReturn(SENT_FOLDER_ID);
|
when(sentFolder.getDatabaseId()).thenReturn(SENT_FOLDER_ID);
|
||||||
|
@ -455,13 +447,12 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
when(backendManager.getBackend(account)).thenReturn(backend);
|
when(backendManager.getBackend(account)).thenReturn(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureAccount() throws MessagingException {
|
private void configureAccount() {
|
||||||
// TODO use simple account object without mocks
|
account = preferences.newAccount();
|
||||||
account = spy(new Account(ACCOUNT_UUID));
|
accountUuid = account.getUuid();
|
||||||
DI.get(AccountPreferenceSerializer.class).loadDefaults(account);
|
|
||||||
account.setMaximumAutoDownloadMessageSize(MAXIMUM_SMALL_MESSAGE_SIZE);
|
account.setMaximumAutoDownloadMessageSize(MAXIMUM_SMALL_MESSAGE_SIZE);
|
||||||
account.setEmail("user@host.com");
|
account.setEmail("user@host.com");
|
||||||
Mockito.doReturn(true).when(account).isAvailable(appContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureLocalStore() throws MessagingException {
|
private void configureLocalStore() throws MessagingException {
|
||||||
|
@ -474,20 +465,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
|
||||||
when(localStoreProvider.getInstance(account)).thenReturn(localStore);
|
when(localStoreProvider.getInstance(account)).thenReturn(localStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAccountsInPreferences(Map<String, Account> newAccounts)
|
|
||||||
throws Exception {
|
|
||||||
// TODO this affects other tests, try to get rid of it
|
|
||||||
Field accounts = Preferences.class.getDeclaredField("accounts");
|
|
||||||
accounts.setAccessible(true);
|
|
||||||
accounts.set(Preferences.getPreferences(appContext), newAccounts);
|
|
||||||
|
|
||||||
Field accountsInOrder = Preferences.class.getDeclaredField("accountsInOrder");
|
|
||||||
accountsInOrder.setAccessible(true);
|
|
||||||
ArrayList<Account> newAccountsInOrder = new ArrayList<>(newAccounts.values());
|
|
||||||
accountsInOrder.set(Preferences.getPreferences(appContext), newAccountsInOrder);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeAccountsFromPreferences() {
|
private void removeAccountsFromPreferences() {
|
||||||
Preferences.getPreferences(appContext).clearAccounts();
|
preferences.clearAccounts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,9 @@ class UnreadWidgetConfigurationFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRegularAccount() {
|
private fun handleRegularAccount() {
|
||||||
val selectedAccount = preferences.getAccount(selectedAccountUuid)
|
val selectedAccount = preferences.getAccount(selectedAccountUuid!!)
|
||||||
|
?: error("Account $selectedAccountUuid not found")
|
||||||
|
|
||||||
val accountDescription: String? = selectedAccount.description
|
val accountDescription: String? = selectedAccount.description
|
||||||
val summary = if (accountDescription.isNullOrEmpty()) selectedAccount.email else accountDescription
|
val summary = if (accountDescription.isNullOrEmpty()) selectedAccount.email else accountDescription
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,8 @@ class EditIdentity : K9Activity() {
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
identityIndex = intent.getIntExtra(EXTRA_IDENTITY_INDEX, -1)
|
identityIndex = intent.getIntExtra(EXTRA_IDENTITY_INDEX, -1)
|
||||||
val accountUuid = intent.getStringExtra(EXTRA_ACCOUNT)
|
val accountUuid = intent.getStringExtra(EXTRA_ACCOUNT) ?: error("Missing account UUID")
|
||||||
account = Preferences.getPreferences(this).getAccount(accountUuid)
|
account = Preferences.getPreferences(this).getAccount(accountUuid) ?: error("Couldn't find account")
|
||||||
|
|
||||||
identity = when {
|
identity = when {
|
||||||
savedInstanceState != null -> savedInstanceState.getParcelable(EXTRA_IDENTITY) ?: error("Missing state")
|
savedInstanceState != null -> savedInstanceState.getParcelable(EXTRA_IDENTITY) ?: error("Missing state")
|
||||||
|
|
|
@ -434,6 +434,11 @@ open class MessageList :
|
||||||
if (accountUuid != null) {
|
if (accountUuid != null) {
|
||||||
// We've most likely been started by an old unread widget or accounts shortcut
|
// We've most likely been started by an old unread widget or accounts shortcut
|
||||||
val account = preferences.getAccount(accountUuid)
|
val account = preferences.getAccount(accountUuid)
|
||||||
|
if (account == null) {
|
||||||
|
Timber.d("Account %s not found.", accountUuid)
|
||||||
|
return LaunchData(createDefaultLocalSearch())
|
||||||
|
}
|
||||||
|
|
||||||
val folderId = defaultFolderProvider.getDefaultFolder(account)
|
val folderId = defaultFolderProvider.getDefaultFolder(account)
|
||||||
val search = LocalSearch().apply {
|
val search = LocalSearch().apply {
|
||||||
addAccountUuid(accountUuid)
|
addAccountUuid(accountUuid)
|
||||||
|
@ -455,7 +460,7 @@ open class MessageList :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createDefaultLocalSearch(): LocalSearch {
|
private fun createDefaultLocalSearch(): LocalSearch {
|
||||||
val account = preferences.defaultAccount
|
val account = preferences.defaultAccount ?: error("No default account available")
|
||||||
return LocalSearch().apply {
|
return LocalSearch().apply {
|
||||||
addAccountUuid(account.uuid)
|
addAccountUuid(account.uuid)
|
||||||
addAllowedFolder(defaultFolderProvider.getDefaultFolder(account))
|
addAllowedFolder(defaultFolderProvider.getDefaultFolder(account))
|
||||||
|
@ -1141,7 +1146,7 @@ open class MessageList :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openMessage(messageReference: MessageReference) {
|
override fun openMessage(messageReference: MessageReference) {
|
||||||
val account = preferences.getAccount(messageReference.accountUuid)
|
val account = preferences.getAccount(messageReference.accountUuid) ?: error("Account not found")
|
||||||
val folderId = messageReference.folderId
|
val folderId = messageReference.folderId
|
||||||
|
|
||||||
val draftsFolderId = account.draftsFolderId
|
val draftsFolderId = account.draftsFolderId
|
||||||
|
|
|
@ -1048,7 +1048,7 @@ class MessageListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun groupMessagesByAccount(messages: List<MessageReference>): Map<Account, List<MessageReference>> {
|
private fun groupMessagesByAccount(messages: List<MessageReference>): Map<Account, List<MessageReference>> {
|
||||||
return messages.groupBy { preferences.getAccount(it.accountUuid) }
|
return messages.groupBy { preferences.getAccount(it.accountUuid)!! }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onSpam(messages: List<MessageReference>) {
|
private fun onSpam(messages: List<MessageReference>) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ class AutocryptKeyTransferPresenter internal constructor(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
account = preferences.getAccount(accountUuid)
|
account = preferences.getAccount(accountUuid) ?: error("Account $accountUuid not found")
|
||||||
|
|
||||||
openPgpApiManager.setOpenPgpProvider(
|
openPgpApiManager.setOpenPgpProvider(
|
||||||
account.openPgpProvider,
|
account.openPgpProvider,
|
||||||
|
|
|
@ -24,7 +24,8 @@ class MessageListExtractor(
|
||||||
): MessageListItem {
|
): MessageListItem {
|
||||||
val position = cursor.position
|
val position = cursor.position
|
||||||
val accountUuid = cursor.getString(MLFProjectionInfo.ACCOUNT_UUID_COLUMN)
|
val accountUuid = cursor.getString(MLFProjectionInfo.ACCOUNT_UUID_COLUMN)
|
||||||
val account = preferences.getAccount(accountUuid)
|
val account = preferences.getAccount(accountUuid) ?: error("Account $accountUuid not found")
|
||||||
|
|
||||||
val fromList = cursor.getString(MLFProjectionInfo.SENDER_LIST_COLUMN)
|
val fromList = cursor.getString(MLFProjectionInfo.SENDER_LIST_COLUMN)
|
||||||
val toList = cursor.getString(MLFProjectionInfo.TO_LIST_COLUMN)
|
val toList = cursor.getString(MLFProjectionInfo.TO_LIST_COLUMN)
|
||||||
val ccList = cursor.getString(MLFProjectionInfo.CC_LIST_COLUMN)
|
val ccList = cursor.getString(MLFProjectionInfo.CC_LIST_COLUMN)
|
||||||
|
|
|
@ -47,7 +47,9 @@ class AccountSettingsViewModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAccount(accountUuid: String) = preferences.getAccount(accountUuid)
|
private fun loadAccount(accountUuid: String): Account {
|
||||||
|
return preferences.getAccount(accountUuid) ?: error("Account $accountUuid not found")
|
||||||
|
}
|
||||||
|
|
||||||
fun getFolders(account: Account): LiveData<RemoteFolderInfo> {
|
fun getFolders(account: Account): LiveData<RemoteFolderInfo> {
|
||||||
if (foldersLiveData.value == null) {
|
if (foldersLiveData.value == null) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ class AccountActivator(
|
||||||
private val messagingController: MessagingController
|
private val messagingController: MessagingController
|
||||||
) {
|
) {
|
||||||
fun enableAccount(accountUuid: String, incomingServerPassword: String?, outgoingServerPassword: String?) {
|
fun enableAccount(accountUuid: String, incomingServerPassword: String?, outgoingServerPassword: String?) {
|
||||||
val account = preferences.getAccount(accountUuid)
|
val account = preferences.getAccount(accountUuid) ?: error("Account $accountUuid not found")
|
||||||
|
|
||||||
setAccountPasswords(account, incomingServerPassword, outgoingServerPassword)
|
setAccountPasswords(account, incomingServerPassword, outgoingServerPassword)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue