Merge pull request #3744 from k9mail/dumb-account-1

Move logic out of Account class (1)
This commit is contained in:
cketti 2018-11-30 01:45:53 +01:00 committed by GitHub
commit bb6427cec0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
69 changed files with 1293 additions and 1189 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,598 @@
package com.fsck.k9
import com.fsck.k9.Account.*
import com.fsck.k9.helper.Utility
import com.fsck.k9.mail.NetworkType
import com.fsck.k9.mail.filter.Base64
import com.fsck.k9.mailstore.StorageManager
import com.fsck.k9.preferences.Storage
import com.fsck.k9.preferences.StorageEditor
import timber.log.Timber
import java.util.*
class AccountPreferenceSerializer(
private val storageManager: StorageManager,
private val resourceProvider: CoreResourceProvider
) {
@Synchronized
fun loadAccount(account: Account, storage: Storage) {
val accountUuid = account.uuid
with (account) {
storeUri = Base64.decode(storage.getString("$accountUuid.storeUri", null))
localStorageProviderId = storage.getString("$accountUuid.localStorageProvider", storageManager.defaultProviderId)
transportUri = Base64.decode(storage.getString("$accountUuid.transportUri", null))
description = storage.getString("$accountUuid.description", null)
alwaysBcc = storage.getString("$accountUuid.alwaysBcc", alwaysBcc)
automaticCheckIntervalMinutes = storage.getInt("$accountUuid.automaticCheckIntervalMinutes", -1)
idleRefreshMinutes = storage.getInt("$accountUuid.idleRefreshMinutes", 24)
isPushPollOnConnect = storage.getBoolean("$accountUuid.pushPollOnConnect", true)
displayCount = storage.getInt("$accountUuid.displayCount", K9.DEFAULT_VISIBLE_LIMIT)
if (displayCount < 0) {
displayCount = K9.DEFAULT_VISIBLE_LIMIT
}
latestOldMessageSeenTime = storage.getLong("$accountUuid.latestOldMessageSeenTime", 0)
isNotifyNewMail = storage.getBoolean("$accountUuid.notifyNewMail", false)
folderNotifyNewMailMode = getEnumStringPref<FolderMode>(storage, "$accountUuid.folderNotifyNewMailMode", FolderMode.ALL)
isNotifySelfNewMail = storage.getBoolean("$accountUuid.notifySelfNewMail", true)
isNotifyContactsMailOnly = storage.getBoolean("$accountUuid.notifyContactsMailOnly", false)
isNotifySync = storage.getBoolean("$accountUuid.notifyMailCheck", false)
deletePolicy = DeletePolicy.fromInt(storage.getInt("$accountUuid.deletePolicy", DeletePolicy.NEVER.setting))
inboxFolder = storage.getString("$accountUuid.inboxFolderName", INBOX)
val draftsFolder = storage.getString("$accountUuid.draftsFolderName", null)
val draftsFolderSelection = getEnumStringPref<SpecialFolderSelection>(storage, "$accountUuid.draftsFolderSelection",
SpecialFolderSelection.AUTOMATIC)
setDraftsFolder(draftsFolder, draftsFolderSelection)
val sentFolder = storage.getString("$accountUuid.sentFolderName", null)
val sentFolderSelection = getEnumStringPref<SpecialFolderSelection>(storage, "$accountUuid.sentFolderSelection",
SpecialFolderSelection.AUTOMATIC)
setSentFolder(sentFolder, sentFolderSelection)
val trashFolder = storage.getString("$accountUuid.trashFolderName", null)
val trashFolderSelection = getEnumStringPref<SpecialFolderSelection>(storage, "$accountUuid.trashFolderSelection",
SpecialFolderSelection.AUTOMATIC)
setTrashFolder(trashFolder, trashFolderSelection)
val archiveFolder = storage.getString("$accountUuid.archiveFolderName", null)
val archiveFolderSelection = getEnumStringPref<SpecialFolderSelection>(storage, "$accountUuid.archiveFolderSelection",
SpecialFolderSelection.AUTOMATIC)
setArchiveFolder(archiveFolder, archiveFolderSelection)
val spamFolder = storage.getString("$accountUuid.spamFolderName", null)
val spamFolderSelection = getEnumStringPref<SpecialFolderSelection>(storage, "$accountUuid.spamFolderSelection",
SpecialFolderSelection.AUTOMATIC)
setSpamFolder(spamFolder, spamFolderSelection)
expungePolicy = getEnumStringPref<Expunge>(storage, "$accountUuid.expungePolicy", Expunge.EXPUNGE_IMMEDIATELY)
isSyncRemoteDeletions = storage.getBoolean("$accountUuid.syncRemoteDeletions", true)
maxPushFolders = storage.getInt("$accountUuid.maxPushFolders", 10)
isGoToUnreadMessageSearch = storage.getBoolean("$accountUuid.goToUnreadMessageSearch", false)
isSubscribedFoldersOnly = storage.getBoolean("$accountUuid.subscribedFoldersOnly", false)
maximumPolledMessageAge = storage.getInt("$accountUuid.maximumPolledMessageAge", -1)
maximumAutoDownloadMessageSize = storage.getInt("$accountUuid.maximumAutoDownloadMessageSize", 32768)
messageFormat = getEnumStringPref<MessageFormat>(storage, "$accountUuid.messageFormat", DEFAULT_MESSAGE_FORMAT)
val messageFormatAuto = storage.getBoolean("$accountUuid.messageFormatAuto", DEFAULT_MESSAGE_FORMAT_AUTO)
if (messageFormatAuto && messageFormat == MessageFormat.TEXT) {
messageFormat = MessageFormat.AUTO
}
isMessageReadReceipt = storage.getBoolean("$accountUuid.messageReadReceipt", DEFAULT_MESSAGE_READ_RECEIPT)
quoteStyle = getEnumStringPref<QuoteStyle>(storage, "$accountUuid.quoteStyle", DEFAULT_QUOTE_STYLE)
quotePrefix = storage.getString("$accountUuid.quotePrefix", DEFAULT_QUOTE_PREFIX)
isDefaultQuotedTextShown = storage.getBoolean("$accountUuid.defaultQuotedTextShown", DEFAULT_QUOTED_TEXT_SHOWN)
isReplyAfterQuote = storage.getBoolean("$accountUuid.replyAfterQuote", DEFAULT_REPLY_AFTER_QUOTE)
isStripSignature = storage.getBoolean("$accountUuid.stripSignature", DEFAULT_STRIP_SIGNATURE)
for (type in NetworkType.values()) {
val useCompression = storage.getBoolean("$accountUuid.useCompression.$type",
true)
setCompression(type, useCompression)
}
autoExpandFolder = storage.getString("$accountUuid.autoExpandFolderName", INBOX)
accountNumber = storage.getInt("$accountUuid.accountNumber", 0)
chipColor = storage.getInt("$accountUuid.chipColor", FALLBACK_ACCOUNT_COLOR)
sortType = getEnumStringPref<SortType>(storage, "$accountUuid.sortTypeEnum", SortType.SORT_DATE)
setSortAscending(sortType, storage.getBoolean("$accountUuid.sortAscending", false))
showPictures = getEnumStringPref<ShowPictures>(storage, "$accountUuid.showPicturesEnum", ShowPictures.NEVER)
notificationSetting.setVibrateEnabled(storage.getBoolean("$accountUuid.vibrate", false))
notificationSetting.vibratePattern = storage.getInt("$accountUuid.vibratePattern", 0)
notificationSetting.vibrateTimes = storage.getInt("$accountUuid.vibrateTimes", 5)
notificationSetting.isRingEnabled = storage.getBoolean("$accountUuid.ring", true)
notificationSetting.ringtone = storage.getString("$accountUuid.ringtone",
"content://settings/system/notification_sound")
notificationSetting.setLed(storage.getBoolean("$accountUuid.led", true))
notificationSetting.ledColor = storage.getInt("$accountUuid.ledColor", chipColor)
folderDisplayMode = getEnumStringPref<FolderMode>(storage, "$accountUuid.folderDisplayMode", FolderMode.NOT_SECOND_CLASS)
folderSyncMode = getEnumStringPref<FolderMode>(storage, "$accountUuid.folderSyncMode", FolderMode.FIRST_CLASS)
folderPushMode = getEnumStringPref<FolderMode>(storage, "$accountUuid.folderPushMode", FolderMode.FIRST_CLASS)
folderTargetMode = getEnumStringPref<FolderMode>(storage, "$accountUuid.folderTargetMode", FolderMode.NOT_SECOND_CLASS)
searchableFolders = getEnumStringPref<Searchable>(storage, "$accountUuid.searchableFolders", Searchable.ALL)
isSignatureBeforeQuotedText = storage.getBoolean("$accountUuid.signatureBeforeQuotedText", false)
identities = loadIdentities(accountUuid, storage)
openPgpProvider = storage.getString("$accountUuid.openPgpProvider", "")
openPgpKey = storage.getLong("$accountUuid.cryptoKey", NO_OPENPGP_KEY)
isOpenPgpHideSignOnly = storage.getBoolean("$accountUuid.openPgpHideSignOnly", true)
isOpenPgpEncryptSubject = storage.getBoolean("$accountUuid.openPgpEncryptSubject", true)
isOpenPgpEncryptAllDrafts = storage.getBoolean("$accountUuid.openPgpEncryptAllDrafts", true)
autocryptPreferEncryptMutual = storage.getBoolean("$accountUuid.autocryptMutualMode", false)
isAllowRemoteSearch = storage.getBoolean("$accountUuid.allowRemoteSearch", false)
isRemoteSearchFullText = storage.getBoolean("$accountUuid.remoteSearchFullText", false)
remoteSearchNumResults = storage.getInt("$accountUuid.remoteSearchNumResults", DEFAULT_REMOTE_SEARCH_NUM_RESULTS)
isUploadSentMessages = storage.getBoolean("$accountUuid.uploadSentMessages", true)
isEnabled = storage.getBoolean("$accountUuid.enabled", true)
isMarkMessageAsReadOnView = storage.getBoolean("$accountUuid.markMessageAsReadOnView", true)
isAlwaysShowCcBcc = storage.getBoolean("$accountUuid.alwaysShowCcBcc", false)
// Use email address as account description if necessary
if (description == null) {
description = email
}
}
}
@Synchronized
private fun loadIdentities(accountUuid: String, storage: Storage): List<Identity> {
val newIdentities = ArrayList<Identity>()
var ident = 0
var gotOne: Boolean
do {
gotOne = false
val name = storage.getString("$accountUuid.$IDENTITY_NAME_KEY.$ident", null)
val email = storage.getString("$accountUuid.$IDENTITY_EMAIL_KEY.$ident", null)
val signatureUse = storage.getBoolean("$accountUuid.signatureUse.$ident", true)
val signature = storage.getString("$accountUuid.signature.$ident", null)
val description = storage.getString("$accountUuid.$IDENTITY_DESCRIPTION_KEY.$ident", null)
val replyTo = storage.getString("$accountUuid.replyTo.$ident", null)
if (email != null) {
val identity = Identity()
identity.name = name
identity.email = email
identity.signatureUse = signatureUse
identity.signature = signature
identity.description = description
identity.replyTo = replyTo
newIdentities.add(identity)
gotOne = true
}
ident++
} while (gotOne)
if (newIdentities.isEmpty()) {
val name = storage.getString("$accountUuid.name", null)
val email = storage.getString("$accountUuid.email", null)
val signatureUse = storage.getBoolean("$accountUuid.signatureUse", true)
val signature = storage.getString("$accountUuid.signature", null)
val identity = Identity()
identity.name = name
identity.email = email
identity.signatureUse = signatureUse
identity.signature = signature
identity.description = email
newIdentities.add(identity)
}
return newIdentities
}
@Synchronized
fun save(storage: Storage, editor: StorageEditor, account: Account) {
val accountUuid = account.uuid
if (!storage.getString("accountUuids", "").contains(account.uuid)) {
var accountUuids = storage.getString("accountUuids", "")
accountUuids += (if (accountUuids.isNotEmpty()) "," else "") + account.uuid
editor.putString("accountUuids", accountUuids)
}
with (account) {
editor.putString("$accountUuid.storeUri", Base64.encode(storeUri))
editor.putString("$accountUuid.localStorageProvider", localStorageProviderId)
editor.putString("$accountUuid.transportUri", Base64.encode(transportUri))
editor.putString("$accountUuid.description", description)
editor.putString("$accountUuid.alwaysBcc", alwaysBcc)
editor.putInt("$accountUuid.automaticCheckIntervalMinutes", automaticCheckIntervalMinutes)
editor.putInt("$accountUuid.idleRefreshMinutes", idleRefreshMinutes)
editor.putBoolean("$accountUuid.pushPollOnConnect", isPushPollOnConnect)
editor.putInt("$accountUuid.displayCount", displayCount)
editor.putLong("$accountUuid.latestOldMessageSeenTime", latestOldMessageSeenTime)
editor.putBoolean("$accountUuid.notifyNewMail", isNotifyNewMail)
editor.putString("$accountUuid.folderNotifyNewMailMode", folderNotifyNewMailMode.name)
editor.putBoolean("$accountUuid.notifySelfNewMail", isNotifySelfNewMail)
editor.putBoolean("$accountUuid.notifyContactsMailOnly", isNotifyContactsMailOnly)
editor.putBoolean("$accountUuid.notifyMailCheck", isNotifySync)
editor.putInt("$accountUuid.deletePolicy", deletePolicy.setting)
editor.putString("$accountUuid.inboxFolderName", inboxFolder)
editor.putString("$accountUuid.draftsFolderName", draftsFolder)
editor.putString("$accountUuid.sentFolderName", sentFolder)
editor.putString("$accountUuid.trashFolderName", trashFolder)
editor.putString("$accountUuid.archiveFolderName", archiveFolder)
editor.putString("$accountUuid.spamFolderName", spamFolder)
editor.putString("$accountUuid.archiveFolderSelection", archiveFolderSelection.name)
editor.putString("$accountUuid.draftsFolderSelection", draftsFolderSelection.name)
editor.putString("$accountUuid.sentFolderSelection", sentFolderSelection.name)
editor.putString("$accountUuid.spamFolderSelection", spamFolderSelection.name)
editor.putString("$accountUuid.trashFolderSelection", trashFolderSelection.name)
editor.putString("$accountUuid.autoExpandFolderName", autoExpandFolder)
editor.putInt("$accountUuid.accountNumber", accountNumber)
editor.putString("$accountUuid.sortTypeEnum", sortType.name)
editor.putBoolean("$accountUuid.sortAscending", isSortAscending(sortType))
editor.putString("$accountUuid.showPicturesEnum", showPictures.name)
editor.putString("$accountUuid.folderDisplayMode", folderDisplayMode.name)
editor.putString("$accountUuid.folderSyncMode", folderSyncMode.name)
editor.putString("$accountUuid.folderPushMode", folderPushMode.name)
editor.putString("$accountUuid.folderTargetMode", folderTargetMode.name)
editor.putBoolean("$accountUuid.signatureBeforeQuotedText", isSignatureBeforeQuotedText)
editor.putString("$accountUuid.expungePolicy", expungePolicy.name)
editor.putBoolean("$accountUuid.syncRemoteDeletions", isSyncRemoteDeletions)
editor.putInt("$accountUuid.maxPushFolders", maxPushFolders)
editor.putString("$accountUuid.searchableFolders", searchableFolders.name)
editor.putInt("$accountUuid.chipColor", chipColor)
editor.putBoolean("$accountUuid.goToUnreadMessageSearch", isGoToUnreadMessageSearch)
editor.putBoolean("$accountUuid.subscribedFoldersOnly", isSubscribedFoldersOnly)
editor.putInt("$accountUuid.maximumPolledMessageAge", maximumPolledMessageAge)
editor.putInt("$accountUuid.maximumAutoDownloadMessageSize", maximumAutoDownloadMessageSize)
val messageFormatAuto = if (Account.MessageFormat.AUTO == messageFormat) {
// saving MessageFormat.AUTO as is to the database will cause downgrades to crash on
// startup, so we save as MessageFormat.TEXT instead with a separate flag for auto.
editor.putString("$accountUuid.messageFormat", Account.MessageFormat.TEXT.name)
true
} else {
editor.putString("$accountUuid.messageFormat", messageFormat.name)
false
}
editor.putBoolean("$accountUuid.messageFormatAuto", messageFormatAuto)
editor.putBoolean("$accountUuid.messageReadReceipt", isMessageReadReceipt)
editor.putString("$accountUuid.quoteStyle", quoteStyle.name)
editor.putString("$accountUuid.quotePrefix", quotePrefix)
editor.putBoolean("$accountUuid.defaultQuotedTextShown", isDefaultQuotedTextShown)
editor.putBoolean("$accountUuid.replyAfterQuote", isReplyAfterQuote)
editor.putBoolean("$accountUuid.stripSignature", isStripSignature)
editor.putLong("$accountUuid.cryptoKey", openPgpKey)
editor.putBoolean("$accountUuid.openPgpHideSignOnly", isOpenPgpHideSignOnly)
editor.putBoolean("$accountUuid.openPgpEncryptSubject", isOpenPgpEncryptSubject)
editor.putBoolean("$accountUuid.openPgpEncryptAllDrafts", isOpenPgpEncryptAllDrafts)
editor.putString("$accountUuid.openPgpProvider", openPgpProvider)
editor.putBoolean("$accountUuid.autocryptMutualMode", autocryptPreferEncryptMutual)
editor.putBoolean("$accountUuid.allowRemoteSearch", isAllowRemoteSearch)
editor.putBoolean("$accountUuid.remoteSearchFullText", isRemoteSearchFullText)
editor.putInt("$accountUuid.remoteSearchNumResults", remoteSearchNumResults)
editor.putBoolean("$accountUuid.enabled", isEnabled)
editor.putBoolean("$accountUuid.markMessageAsReadOnView", isMarkMessageAsReadOnView)
editor.putBoolean("$accountUuid.alwaysShowCcBcc", isAlwaysShowCcBcc)
editor.putBoolean("$accountUuid.vibrate", notificationSetting.isVibrateEnabled)
editor.putInt("$accountUuid.vibratePattern", notificationSetting.vibratePattern)
editor.putInt("$accountUuid.vibrateTimes", notificationSetting.vibrateTimes)
editor.putBoolean("$accountUuid.ring", notificationSetting.isRingEnabled)
editor.putString("$accountUuid.ringtone", notificationSetting.ringtone)
editor.putBoolean("$accountUuid.led", notificationSetting.isLedEnabled)
editor.putInt("$accountUuid.ledColor", notificationSetting.ledColor)
for (type in NetworkType.values()) {
val useCompression = compressionMap[type]
if (useCompression != null) {
editor.putBoolean("$accountUuid.useCompression.$type", useCompression)
}
}
}
saveIdentities(account, storage, editor)
editor.commit()
}
@Synchronized
fun delete(storage: Storage, account: Account) {
val accountUuid = account.uuid
// Get the list of account UUIDs
val uuids = storage.getString("accountUuids", "").split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
// Create a list of all account UUIDs excluding this account
val newUuids = ArrayList<String>(uuids.size)
for (uuid in uuids) {
if (uuid != accountUuid) {
newUuids.add(uuid)
}
}
val editor = storage.edit()
// Only change the 'accountUuids' value if this account's UUID was listed before
if (newUuids.size < uuids.size) {
val accountUuids = Utility.combine(newUuids.toTypedArray(), ',')
editor.putString("accountUuids", accountUuids)
}
editor.remove("$accountUuid.storeUri")
editor.remove("$accountUuid.transportUri")
editor.remove("$accountUuid.description")
editor.remove("$accountUuid.name")
editor.remove("$accountUuid.email")
editor.remove("$accountUuid.alwaysBcc")
editor.remove("$accountUuid.automaticCheckIntervalMinutes")
editor.remove("$accountUuid.pushPollOnConnect")
editor.remove("$accountUuid.idleRefreshMinutes")
editor.remove("$accountUuid.lastAutomaticCheckTime")
editor.remove("$accountUuid.latestOldMessageSeenTime")
editor.remove("$accountUuid.notifyNewMail")
editor.remove("$accountUuid.notifySelfNewMail")
editor.remove("$accountUuid.deletePolicy")
editor.remove("$accountUuid.draftsFolderName")
editor.remove("$accountUuid.sentFolderName")
editor.remove("$accountUuid.trashFolderName")
editor.remove("$accountUuid.archiveFolderName")
editor.remove("$accountUuid.spamFolderName")
editor.remove("$accountUuid.archiveFolderSelection")
editor.remove("$accountUuid.draftsFolderSelection")
editor.remove("$accountUuid.sentFolderSelection")
editor.remove("$accountUuid.spamFolderSelection")
editor.remove("$accountUuid.trashFolderSelection")
editor.remove("$accountUuid.autoExpandFolderName")
editor.remove("$accountUuid.accountNumber")
editor.remove("$accountUuid.vibrate")
editor.remove("$accountUuid.vibratePattern")
editor.remove("$accountUuid.vibrateTimes")
editor.remove("$accountUuid.ring")
editor.remove("$accountUuid.ringtone")
editor.remove("$accountUuid.folderDisplayMode")
editor.remove("$accountUuid.folderSyncMode")
editor.remove("$accountUuid.folderPushMode")
editor.remove("$accountUuid.folderTargetMode")
editor.remove("$accountUuid.signatureBeforeQuotedText")
editor.remove("$accountUuid.expungePolicy")
editor.remove("$accountUuid.syncRemoteDeletions")
editor.remove("$accountUuid.maxPushFolders")
editor.remove("$accountUuid.searchableFolders")
editor.remove("$accountUuid.chipColor")
editor.remove("$accountUuid.led")
editor.remove("$accountUuid.ledColor")
editor.remove("$accountUuid.goToUnreadMessageSearch")
editor.remove("$accountUuid.subscribedFoldersOnly")
editor.remove("$accountUuid.maximumPolledMessageAge")
editor.remove("$accountUuid.maximumAutoDownloadMessageSize")
editor.remove("$accountUuid.messageFormatAuto")
editor.remove("$accountUuid.quoteStyle")
editor.remove("$accountUuid.quotePrefix")
editor.remove("$accountUuid.sortTypeEnum")
editor.remove("$accountUuid.sortAscending")
editor.remove("$accountUuid.showPicturesEnum")
editor.remove("$accountUuid.replyAfterQuote")
editor.remove("$accountUuid.stripSignature")
editor.remove("$accountUuid.cryptoApp") // this is no longer set, but cleans up legacy values
editor.remove("$accountUuid.cryptoAutoSignature")
editor.remove("$accountUuid.cryptoAutoEncrypt")
editor.remove("$accountUuid.cryptoApp")
editor.remove("$accountUuid.cryptoKey")
editor.remove("$accountUuid.cryptoSupportSignOnly")
editor.remove("$accountUuid.openPgpProvider")
editor.remove("$accountUuid.openPgpHideSignOnly")
editor.remove("$accountUuid.openPgpEncryptSubject")
editor.remove("$accountUuid.openPgpEncryptAllDrafts")
editor.remove("$accountUuid.autocryptMutualMode")
editor.remove("$accountUuid.enabled")
editor.remove("$accountUuid.markMessageAsReadOnView")
editor.remove("$accountUuid.alwaysShowCcBcc")
editor.remove("$accountUuid.allowRemoteSearch")
editor.remove("$accountUuid.remoteSearchFullText")
editor.remove("$accountUuid.remoteSearchNumResults")
editor.remove("$accountUuid.uploadSentMessages")
editor.remove("$accountUuid.defaultQuotedTextShown")
editor.remove("$accountUuid.displayCount")
editor.remove("$accountUuid.inboxFolderName")
editor.remove("$accountUuid.localStorageProvider")
editor.remove("$accountUuid.messageFormat")
editor.remove("$accountUuid.messageReadReceipt")
editor.remove("$accountUuid.notifyMailCheck")
for (type in NetworkType.values()) {
editor.remove("$accountUuid.useCompression." + type.name)
}
deleteIdentities(account, storage, editor)
// TODO: Remove preference settings that may exist for individual folders in the account.
editor.commit()
}
@Synchronized
private fun saveIdentities(account: Account, storage: Storage, editor: StorageEditor) {
deleteIdentities(account, storage, editor)
var ident = 0
with (account) {
for (identity in identities) {
editor.putString("$uuid.$IDENTITY_NAME_KEY.$ident", identity.name)
editor.putString("$uuid.$IDENTITY_EMAIL_KEY.$ident", identity.email)
editor.putBoolean("$uuid.signatureUse.$ident", identity.signatureUse)
editor.putString("$uuid.signature.$ident", identity.signature)
editor.putString("$uuid.$IDENTITY_DESCRIPTION_KEY.$ident", identity.description)
editor.putString("$uuid.replyTo.$ident", identity.replyTo)
ident++
}
}
}
@Synchronized
private fun deleteIdentities(account: Account, storage: Storage, editor: StorageEditor) {
val accountUuid = account.uuid
var identityIndex = 0
var gotOne: Boolean
do {
gotOne = false
val email = storage.getString("$accountUuid.$IDENTITY_EMAIL_KEY.$identityIndex", null)
if (email != null) {
editor.remove("$accountUuid.$IDENTITY_NAME_KEY.$identityIndex")
editor.remove("$accountUuid.$IDENTITY_EMAIL_KEY.$identityIndex")
editor.remove("$accountUuid.signatureUse.$identityIndex")
editor.remove("$accountUuid.signature.$identityIndex")
editor.remove("$accountUuid.$IDENTITY_DESCRIPTION_KEY.$identityIndex")
editor.remove("$accountUuid.replyTo.$identityIndex")
gotOne = true
}
identityIndex++
} while (gotOne)
}
fun move(account: Account, storage: Storage, moveUp: Boolean) {
val uuids = storage.getString("accountUuids", "").split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val editor = storage.edit()
val newUuids = arrayOfNulls<String>(uuids.size)
if (moveUp) {
for (i in uuids.indices) {
if (i > 0 && uuids[i] == account.uuid) {
newUuids[i] = newUuids[i - 1]
newUuids[i - 1] = account.uuid
} else {
newUuids[i] = uuids[i]
}
}
} else {
for (i in uuids.indices.reversed()) {
if (i < uuids.size - 1 && uuids[i] == account.uuid) {
newUuids[i] = newUuids[i + 1]
newUuids[i + 1] = account.uuid
} else {
newUuids[i] = uuids[i]
}
}
}
val accountUuids = Utility.combine(newUuids, ',')
editor.putString("accountUuids", accountUuids)
editor.commit()
}
private fun <T : Enum<T>> getEnumStringPref(storage: Storage, key: String, defaultEnum: T): T {
val stringPref = storage.getString(key, null)
return if (stringPref == null) {
defaultEnum
} else {
try {
java.lang.Enum.valueOf<T>(defaultEnum.declaringClass, stringPref)
} catch (ex: IllegalArgumentException) {
Timber.w(ex, "Unable to convert preference key [%s] value [%s] to enum of type %s",
key, stringPref, defaultEnum.declaringClass)
defaultEnum
}
}
}
fun loadDefaults(account: Account) {
with (account) {
localStorageProviderId = storageManager.defaultProviderId
automaticCheckIntervalMinutes = -1
idleRefreshMinutes = 24
isPushPollOnConnect = true
displayCount = K9.DEFAULT_VISIBLE_LIMIT
accountNumber = -1
isNotifyNewMail = true
folderNotifyNewMailMode = FolderMode.ALL
isNotifySync = true
isNotifySelfNewMail = true
isNotifyContactsMailOnly = false
folderDisplayMode = FolderMode.NOT_SECOND_CLASS
folderSyncMode = FolderMode.FIRST_CLASS
folderPushMode = FolderMode.FIRST_CLASS
folderTargetMode = FolderMode.NOT_SECOND_CLASS
sortType = DEFAULT_SORT_TYPE
setSortAscending(DEFAULT_SORT_TYPE, DEFAULT_SORT_ASCENDING)
showPictures = ShowPictures.NEVER
isSignatureBeforeQuotedText = false
expungePolicy = Expunge.EXPUNGE_IMMEDIATELY
autoExpandFolder = INBOX
inboxFolder = INBOX
maxPushFolders = 10
isGoToUnreadMessageSearch = false
isSubscribedFoldersOnly = false
maximumPolledMessageAge = -1
maximumAutoDownloadMessageSize = 32768
messageFormat = DEFAULT_MESSAGE_FORMAT
isMessageFormatAuto = DEFAULT_MESSAGE_FORMAT_AUTO
isMessageReadReceipt = DEFAULT_MESSAGE_READ_RECEIPT
quoteStyle = DEFAULT_QUOTE_STYLE
quotePrefix = DEFAULT_QUOTE_PREFIX
isDefaultQuotedTextShown = DEFAULT_QUOTED_TEXT_SHOWN
isReplyAfterQuote = DEFAULT_REPLY_AFTER_QUOTE
isStripSignature = DEFAULT_STRIP_SIGNATURE
isSyncRemoteDeletions = true
openPgpKey = NO_OPENPGP_KEY
isAllowRemoteSearch = false
isRemoteSearchFullText = false
remoteSearchNumResults = DEFAULT_REMOTE_SEARCH_NUM_RESULTS
isUploadSentMessages = true
isEnabled = true
isMarkMessageAsReadOnView = true
isAlwaysShowCcBcc = false
setArchiveFolder(null, SpecialFolderSelection.AUTOMATIC)
setDraftsFolder(null, SpecialFolderSelection.AUTOMATIC)
setSentFolder(null, SpecialFolderSelection.AUTOMATIC)
setSpamFolder(null, SpecialFolderSelection.AUTOMATIC)
setTrashFolder(null, SpecialFolderSelection.AUTOMATIC)
setArchiveFolder(null, SpecialFolderSelection.AUTOMATIC)
searchableFolders = Searchable.ALL
identities = ArrayList<Identity>()
val identity = Identity().apply {
signatureUse = true
signature = resourceProvider.defaultSignature()
description = resourceProvider.defaultIdentityDescription()
}
identities.add(identity)
with (notificationSetting) {
isVibrateEnabled = false
vibratePattern = 0
vibrateTimes = 5
isRingEnabled = true
ringtone = "content://settings/system/notification_sound"
ledColor = chipColor
}
}
}
companion object {
const val ACCOUNT_DESCRIPTION_KEY = "description"
const val STORE_URI_KEY = "storeUri"
const val TRANSPORT_URI_KEY = "transportUri"
const val IDENTITY_NAME_KEY = "name"
const val IDENTITY_EMAIL_KEY = "email"
const val IDENTITY_DESCRIPTION_KEY = "description"
const val FALLBACK_ACCOUNT_COLOR = 0x0099CC
@JvmField
val DEFAULT_MESSAGE_FORMAT = MessageFormat.HTML
@JvmField
val DEFAULT_QUOTE_STYLE = QuoteStyle.PREFIX
const val DEFAULT_MESSAGE_FORMAT_AUTO = false
const val DEFAULT_MESSAGE_READ_RECEIPT = false
const val DEFAULT_QUOTE_PREFIX = ">"
const val DEFAULT_QUOTED_TEXT_SHOWN = true
const val DEFAULT_REPLY_AFTER_QUOTE = false
const val DEFAULT_STRIP_SIGNATURE = true
const val DEFAULT_REMOTE_SEARCH_NUM_RESULTS = 25
}
}

View file

@ -19,6 +19,7 @@ import com.fsck.k9.message.html.htmlModule
import com.fsck.k9.message.quote.quoteModule
import com.fsck.k9.notification.coreNotificationModule
import com.fsck.k9.power.DeviceIdleManager
import com.fsck.k9.search.searchModule
import com.fsck.k9.service.BootReceiver
import com.fsck.k9.service.MailService
import com.fsck.k9.service.ShutdownReceiver
@ -39,6 +40,7 @@ object Core : KoinComponent {
openPgpModule,
autocryptModule,
mailStoreModule,
searchModule,
extractorModule,
htmlModule,
quoteModule,

View file

@ -382,7 +382,7 @@ public class K9 {
for (Account account : preferences.getAccounts()) {
account.setOpenPgpProvider(openPgpProvider);
account.setOpenPgpHideSignOnly(!openPgpSupportSignOnly);
account.save(preferences);
preferences.saveAccount(account);
}
storage.edit()

View file

@ -3,6 +3,7 @@ package com.fsck.k9
import android.content.Context
import com.fsck.k9.helper.Contacts
import com.fsck.k9.mail.power.PowerManager
import com.fsck.k9.mailstore.LocalStoreProvider
import com.fsck.k9.mailstore.StorageManager
import com.fsck.k9.power.TracingPowerManager
import org.koin.dsl.module.applicationContext
@ -11,6 +12,7 @@ val mainModule = applicationContext {
bean { Preferences.getPreferences(get()) }
bean { get<Context>().resources }
bean { StorageManager.getInstance(get()) }
bean { LocalStoreProvider() }
bean { TracingPowerManager.getPowerManager(get()) as PowerManager }
bean { Contacts.getInstance(get()) }
}

View file

@ -0,0 +1,65 @@
package com.fsck.k9
import android.net.Uri
import com.fsck.k9.mail.MailServerDirection
import com.fsck.k9.mail.ssl.LocalKeyStore
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
class LocalKeyStoreManager(
val localKeyStore: LocalKeyStore
) {
/**
* Add a new certificate for the incoming or outgoing server to the local key store.
*/
@Throws(CertificateException::class)
fun addCertificate(account: Account, direction: MailServerDirection, certificate: X509Certificate) {
val uri: Uri
if (direction === MailServerDirection.INCOMING) {
uri = Uri.parse(account.storeUri)
} else {
uri = Uri.parse(account.transportUri)
}
localKeyStore.addCertificate(uri.host, uri.port, certificate)
}
/**
* Examine the existing settings for an account. If the old host/port is different from the
* new host/port, then try and delete any (possibly non-existent) certificate stored for the
* old host/port.
*/
fun deleteCertificate(account: Account, newHost: String, newPort: Int, direction: MailServerDirection) {
val uri: Uri
if (direction === MailServerDirection.INCOMING) {
uri = Uri.parse(account.storeUri)
} else {
uri = Uri.parse(account.transportUri)
}
val oldHost = uri.host
val oldPort = uri.port
if (oldPort == -1) {
// This occurs when a new account is created
return
}
if (newHost != oldHost || newPort != oldPort) {
localKeyStore.deleteCertificate(oldHost, oldPort)
}
}
/**
* Examine the settings for the account and attempt to delete (possibly non-existent)
* certificates for the incoming and outgoing servers.
*/
fun deleteCertificates(account: Account) {
val storeUri = account.storeUri
if (storeUri != null) {
val uri = Uri.parse(storeUri)
localKeyStore.deleteCertificate(uri.host, uri.port)
}
val transportUri = account.transportUri
if (transportUri != null) {
val uri = Uri.parse(transportUri)
localKeyStore.deleteCertificate(uri.host, uri.port)
}
}
}

View file

@ -63,7 +63,7 @@ public class NotificationSetting {
return vibrateEnabled;
}
public synchronized void setVibrate(boolean vibrate) {
public synchronized void setVibrateEnabled(boolean vibrate) {
vibrateEnabled = vibrate;
}

View file

@ -9,11 +9,16 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import android.content.Context;
import android.support.annotation.RestrictTo;
import android.support.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 timber.log.Timber;
@ -22,12 +27,16 @@ import timber.log.Timber;
public class Preferences {
private static Preferences preferences;
private AccountPreferenceSerializer accountPreferenceSerializer;
public static synchronized Preferences getPreferences(Context context) {
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);
if (preferences == null) {
preferences = new Preferences(appContext, resourceProvider);
preferences = new Preferences(appContext, resourceProvider, localStoreProvider, localKeyStoreManager, accountPreferenceSerializer);
}
return preferences;
}
@ -37,12 +46,19 @@ public class Preferences {
private List<Account> accountsInOrder = null;
private Account newAccount;
private Context context;
private final LocalStoreProvider localStoreProvider;
private final CoreResourceProvider resourceProvider;
private final LocalKeyStoreManager localKeyStoreManager;
private Preferences(Context context, CoreResourceProvider resourceProvider) {
private Preferences(Context context, CoreResourceProvider resourceProvider,
LocalStoreProvider localStoreProvider, LocalKeyStoreManager localKeyStoreManager,
AccountPreferenceSerializer accountPreferenceSerializer) {
storage = Storage.getStorage(context);
this.context = context;
this.resourceProvider = resourceProvider;
this.localStoreProvider = localStoreProvider;
this.localKeyStoreManager = localKeyStoreManager;
this.accountPreferenceSerializer = accountPreferenceSerializer;
if (storage.isEmpty()) {
Timber.i("Preferences storage is zero-size, importing from Android-style preferences");
StorageEditor editor = storage.edit();
@ -51,6 +67,12 @@ public class Preferences {
}
}
@RestrictTo(Scope.TESTS)
public void clearAccounts() {
accounts = new HashMap<>();
accountsInOrder = new LinkedList<>();
}
public synchronized void loadAccounts() {
accounts = new HashMap<>();
accountsInOrder = new LinkedList<>();
@ -58,7 +80,8 @@ public class Preferences {
if ((accountUuids != null) && (accountUuids.length() != 0)) {
String[] uuids = accountUuids.split(",");
for (String uuid : uuids) {
Account newAccount = new Account(this, uuid);
Account newAccount = new Account(uuid);
accountPreferenceSerializer.loadAccount(newAccount, storage);
accounts.put(uuid, newAccount);
accountsInOrder.add(newAccount);
}
@ -113,7 +136,9 @@ public class Preferences {
}
public synchronized Account newAccount() {
newAccount = new Account(context, resourceProvider);
String accountUuid = UUID.randomUUID().toString();
newAccount = new Account(accountUuid);
accountPreferenceSerializer.loadDefaults(newAccount);
accounts.put(newAccount.getUuid(), newAccount);
accountsInOrder.add(newAccount);
@ -135,7 +160,8 @@ public class Preferences {
}
LocalStore.removeAccount(account);
account.delete(this);
DI.get(AccountPreferenceSerializer.class).delete(storage, account);
localKeyStoreManager.deleteCertificates(account);
if (newAccount == account) {
newAccount = null;
@ -170,24 +196,72 @@ public class Preferences {
return storage;
}
static <T extends Enum<T>> T getEnumStringPref(Storage storage, String key, T defaultEnum) {
String stringPref = storage.getString(key, null);
if (stringPref == null) {
return defaultEnum;
} else {
try {
return Enum.valueOf(defaultEnum.getDeclaringClass(), stringPref);
} catch (IllegalArgumentException ex) {
Timber.w(ex, "Unable to convert preference key [%s] value [%s] to enum of type %s",
key, stringPref, defaultEnum.getDeclaringClass());
return defaultEnum;
}
}
}
private BackendManager getBackendManager() {
return DI.get(BackendManager.class);
}
public void saveAccount(Account account) {
StorageEditor editor = storage.edit();
if (!accounts.containsKey(account.getUuid())) {
int accountNumber = generateAccountNumber();
account.setAccountNumber(accountNumber);
}
processChangedValues(account);
accountPreferenceSerializer.save(storage, editor, account);
}
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!");
}
}
if (account.isChangedLocalStorageProviderId()) {
try {
localStoreProvider.getInstance(account).switchLocalStorage(account.getLocalStorageProviderId());
} 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) {
accountPreferenceSerializer.move(account, storage, mUp);
loadAccounts();
}
}

View file

@ -6,6 +6,8 @@ import com.fsck.k9.AccountStats
import com.fsck.k9.K9
import com.fsck.k9.Preferences
import com.fsck.k9.mail.MessagingException
import com.fsck.k9.mailstore.LocalStoreProvider
import com.fsck.k9.search.AccountSearchConditions
import com.fsck.k9.search.LocalSearch
import com.fsck.k9.search.SearchAccount
@ -16,7 +18,11 @@ interface AccountStatsCollector {
fun getSearchAccountStats(searchAccount: SearchAccount): AccountStats
}
internal class DefaultAccountStatsCollector(private val context: Context) : AccountStatsCollector {
internal class DefaultAccountStatsCollector(
private val context: Context,
private val accountSearchConditions: AccountSearchConditions,
private val localStoreProvider: LocalStoreProvider
) : AccountStatsCollector {
private val preferences = Preferences.getPreferences(context)
@ -25,11 +31,11 @@ internal class DefaultAccountStatsCollector(private val context: Context) : Acco
return null
}
val localStore = account.localStore
val localStore = localStoreProvider.getInstance(account)
val search = LocalSearch()
account.excludeSpecialFolders(search)
account.limitToDisplayableFolders(search)
accountSearchConditions.excludeSpecialFolders(account, search)
accountSearchConditions.limitToDisplayableFolders(account, search)
val accountStats = localStore.getAccountStats(search)
if (K9.measureAccounts()) {
@ -45,7 +51,7 @@ internal class DefaultAccountStatsCollector(private val context: Context) : Acco
val aggregatedAccountStats = AccountStats()
for (account in accounts) {
val accountStats = account.localStore.getAccountStats(search)
val accountStats = localStoreProvider.getInstance(account).getAccountStats(search)
aggregatedAccountStats.unreadMessageCount += accountStats.unreadMessageCount
aggregatedAccountStats.flaggedMessageCount += accountStats.flaggedMessageCount
}

View file

@ -3,6 +3,6 @@ package com.fsck.k9.controller
import org.koin.dsl.module.applicationContext
val controllerModule = applicationContext {
bean { MessagingController(get(), get(), get(), get(), get(), get(), get("controllerExtensions")) }
bean { DefaultAccountStatsCollector(get()) as AccountStatsCollector }
bean { MessagingController(get(), get(), get(), get(), get(), get(), get(), get("controllerExtensions")) }
bean { DefaultAccountStatsCollector(get(), get(), get()) as AccountStatsCollector }
}

View file

@ -76,6 +76,7 @@ import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.mailstore.UnavailableStorageException;
import com.fsck.k9.notification.NotificationController;
import com.fsck.k9.power.TracingPowerManager;
@ -114,6 +115,7 @@ public class MessagingController {
private final Context context;
private final Contacts contacts;
private final NotificationController notificationController;
private final LocalStoreProvider localStoreProvider;
private final BackendManager backendManager;
private final Thread controllerThread;
@ -137,11 +139,13 @@ public class MessagingController {
}
MessagingController(Context context, NotificationController notificationController, Contacts contacts,
MessagingController(Context context, NotificationController notificationController,
LocalStoreProvider localStoreProvider, Contacts contacts,
AccountStatsCollector accountStatsCollector, CoreResourceProvider resourceProvider,
BackendManager backendManager, List<ControllerExtension> controllerExtensions) {
this.context = context;
this.notificationController = notificationController;
this.localStoreProvider = localStoreProvider;
this.contacts = contacts;
this.accountStatsCollector = accountStatsCollector;
this.resourceProvider = resourceProvider;
@ -267,7 +271,7 @@ public class MessagingController {
private LocalStore getLocalStoreOrThrow(Account account) {
try {
return account.getLocalStore();
return localStoreProvider.getInstance(account);
} catch (MessagingException e) {
throw new IllegalStateException("Couldn't get LocalStore for account " + account.getDescription());
}
@ -393,7 +397,7 @@ public class MessagingController {
Timber.i("not listing folders of unavailable account");
} else {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolders = localStore.getPersonalNamespaces(false);
if (refreshRemote || localFolders.isEmpty()) {
@ -441,7 +445,7 @@ public class MessagingController {
Backend backend = getBackend(account);
backend.refreshFolderList();
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolders = localStore.getPersonalNamespaces(false);
for (MessagingListener l : getListeners(listener)) {
@ -517,7 +521,7 @@ public class MessagingController {
// build and do the query in the localstore
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localStore.searchForMessages(retrievalListener, search);
} catch (Exception e) {
Timber.e(e);
@ -554,7 +558,7 @@ public class MessagingController {
List<String> extraResults = new ArrayList<>();
try {
LocalStore localStore = acct.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(acct);
LocalFolder localFolder = localStore.getFolder(folderServerId);
if (localFolder == null) {
@ -609,7 +613,7 @@ public class MessagingController {
listener.enableProgressIndicator(true);
}
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
if (localStore == null) {
throw new MessagingException("Could not get store");
@ -656,7 +660,7 @@ public class MessagingController {
public void loadMoreMessages(Account account, String folder, MessagingListener listener) {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
LocalFolder localFolder = localStore.getFolder(folder);
if (localFolder.getVisibleLimit() > 0) {
localFolder.setVisibleLimit(localFolder.getVisibleLimit() + account.getDisplayCount());
@ -726,7 +730,7 @@ public class MessagingController {
return new SyncConfig(
account.getExpungePolicy().toBackendExpungePolicy(),
account.getEarliestPollDate(),
account.syncRemoteDeletions(),
account.isSyncRemoteDeletions(),
account.getMaximumAutoDownloadMessageSize(),
K9.DEFAULT_VISIBLE_LIMIT,
SYNC_FLAGS);
@ -734,7 +738,7 @@ public class MessagingController {
private void updateFolderStatus(Account account, String folderServerId, String status) {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
LocalFolder localFolder = localStore.getFolder(folderServerId);
localFolder.setStatus(status);
} catch (MessagingException e) {
@ -754,7 +758,7 @@ public class MessagingController {
private void queuePendingCommand(Account account, PendingCommand command) {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localStore.addPendingCommand(command);
} catch (Exception e) {
throw new RuntimeException("Unable to enqueue pending command", e);
@ -784,7 +788,7 @@ public class MessagingController {
}
public void processPendingCommandsSynchronous(Account account) throws MessagingException {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
List<PendingCommand> commands = localStore.getPendingCommands();
int progress = 0;
@ -859,7 +863,7 @@ public class MessagingController {
String folder = command.folder;
String uid = command.uid;
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(folder);
LocalMessage localMessage = localFolder.getMessage(uid);
@ -959,7 +963,7 @@ public class MessagingController {
boolean isCopy, Map<String, String> newUidMap) throws MessagingException {
LocalFolder localDestFolder;
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localDestFolder = localStore.getFolder(destFolder);
Backend backend = getBackend(account);
@ -1042,7 +1046,7 @@ public class MessagingController {
String folder = command.folder;
LocalFolder localFolder = null;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(folder);
localFolder.open(Folder.OPEN_MODE_RW);
List<? extends Message> messages = localFolder.getMessages(null, false);
@ -1104,7 +1108,7 @@ public class MessagingController {
LocalStore localStore;
try {
localStore = account.getLocalStore();
localStore = localStoreProvider.getInstance(account);
} catch (MessagingException e) {
Timber.e(e, "Couldn't get LocalStore instance");
return;
@ -1180,7 +1184,7 @@ public class MessagingController {
// objects being modified right after this method returns.
Folder localFolder = null;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(folderServerId);
localFolder.open(Folder.OPEN_MODE_RW);
@ -1238,7 +1242,7 @@ public class MessagingController {
boolean newState) {
Folder localFolder = null;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(folderServerId);
localFolder.open(Folder.OPEN_MODE_RW);
@ -1256,7 +1260,7 @@ public class MessagingController {
public void clearAllPending(final Account account) {
try {
Timber.w("Clearing pending commands!");
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localStore.removePendingCommands();
} catch (MessagingException me) {
Timber.e(me, "Unable to clear pending command");
@ -1288,7 +1292,7 @@ public class MessagingController {
final String uid, final MessagingListener listener, final boolean loadPartialFromSearch) {
LocalFolder localFolder = null;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(folder);
localFolder.open(Folder.OPEN_MODE_RW);
@ -1344,7 +1348,7 @@ public class MessagingController {
}
public LocalMessage loadMessage(Account account, String folderServerId, String uid) throws MessagingException {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
LocalFolder localFolder = localStore.getFolder(folderServerId);
localFolder.open(Folder.OPEN_MODE_RW);
@ -1365,7 +1369,7 @@ public class MessagingController {
}
public LocalMessage loadMessageMetadata(Account account, String folderServerId, String uid) throws MessagingException {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
LocalFolder localFolder = localStore.getFolder(folderServerId);
localFolder.open(Folder.OPEN_MODE_RW);
@ -1403,7 +1407,7 @@ public class MessagingController {
try {
String folderServerId = message.getFolder().getServerId();
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(folderServerId);
ProgressBodyFactory bodyFactory = new ProgressBodyFactory(new ProgressListener() {
@ -1446,7 +1450,7 @@ public class MessagingController {
String plaintextSubject,
MessagingListener listener) {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
LocalFolder localFolder = localStore.getFolder(account.getOutboxFolder());
localFolder.open(Folder.OPEN_MODE_RW);
localFolder.appendMessages(Collections.singletonList(message));
@ -1506,13 +1510,13 @@ public class MessagingController {
}
private void showSendingNotificationIfNecessary(Account account) {
if (account.isShowOngoing()) {
if (account.isNotifySync()) {
notificationController.showSendingNotification(account);
}
}
private void clearSendingNotificationIfNecessary(Account account) {
if (account.isShowOngoing()) {
if (account.isNotifySync()) {
notificationController.clearSendingNotification(account);
}
}
@ -1520,7 +1524,7 @@ public class MessagingController {
private boolean messagesPendingSend(final Account account) {
Folder localFolder = null;
try {
localFolder = account.getLocalStore().getFolder(
localFolder = localStoreProvider.getInstance(account).getFolder(
account.getOutboxFolder());
if (!localFolder.exists()) {
return false;
@ -1548,7 +1552,7 @@ public class MessagingController {
Exception lastFailure = null;
boolean wasPermanentFailure = false;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(
account.getOutboxFolder());
if (!localFolder.exists()) {
@ -1793,7 +1797,7 @@ public class MessagingController {
}
public int getFolderUnreadMessageCount(Account account, String folderServerId) throws MessagingException {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
Folder localFolder = localStore.getFolder(folderServerId);
return localFolder.getUnreadMessageCount();
}
@ -1932,7 +1936,7 @@ public class MessagingController {
final List<? extends Message> inMessages, final String destFolder, final boolean isCopy) {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
if (!isCopy && !isMoveCapable(account)) {
return;
}
@ -2032,7 +2036,7 @@ public class MessagingController {
public void deleteDraft(final Account account, long id) {
LocalFolder localFolder = null;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(account.getDraftsFolder());
localFolder.open(Folder.OPEN_MODE_RW);
String uid = localFolder.getMessageUidById(id);
@ -2076,10 +2080,10 @@ public class MessagingController {
}
}
private static List<Message> collectMessagesInThreads(Account account, List<? extends Message> messages)
private List<Message> collectMessagesInThreads(Account account, List<? extends Message> messages)
throws MessagingException {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
List<Message> messagesInThreads = new ArrayList<>();
for (Message message : messages) {
@ -2175,7 +2179,7 @@ public class MessagingController {
}
}
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(folder);
Map<String, String> uidMap = null;
if (folder.equals(account.getTrashFolder()) || !account.hasTrashFolder()) {
@ -2264,7 +2268,7 @@ public class MessagingController {
// When we empty trash, we need to actually synchronize the folder
// or local deletes will never get cleaned up
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
LocalFolder folder = localStore.getFolder(trashFolderServerId);
folder.open(Folder.OPEN_MODE_RW);
synchronizeFolder(account, folder, true, 0, null);
@ -2278,7 +2282,7 @@ public class MessagingController {
public void run() {
LocalFolder localFolder = null;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(account.getTrashFolder());
localFolder.open(Folder.OPEN_MODE_RW);
@ -2323,7 +2327,7 @@ public class MessagingController {
protected void clearFolderSynchronous(Account account, String folderServerId, MessagingListener listener) {
LocalFolder localFolder = null;
try {
localFolder = account.getLocalStore().getFolder(folderServerId);
localFolder = localStoreProvider.getInstance(account).getFolder(folderServerId);
localFolder.open(Folder.OPEN_MODE_RW);
localFolder.clearAllMessages();
} catch (UnavailableStorageException e) {
@ -2489,7 +2493,7 @@ public class MessagingController {
Account.FolderMode aDisplayMode = account.getFolderDisplayMode();
Account.FolderMode aSyncMode = account.getFolderSyncMode();
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
for (final Folder folder : localStore.getPersonalNamespaces(false)) {
folder.open(Folder.OPEN_MODE_RW);
@ -2569,7 +2573,7 @@ public class MessagingController {
try {
// In case multiple Commands get enqueued, don't run more than
// once
final LocalStore localStore = account.getLocalStore();
final LocalStore localStore = localStoreProvider.getInstance(account);
tLocalFolder = localStore.getFolder(folder.getServerId());
tLocalFolder.open(Folder.OPEN_MODE_RW);
@ -2600,13 +2604,13 @@ public class MessagingController {
}
private void showFetchingMailNotificationIfNecessary(Account account, Folder folder) {
if (account.isShowOngoing()) {
if (account.isNotifySync()) {
notificationController.showFetchingMailNotification(account, folder);
}
}
private void clearFetchingMailNotificationIfNecessary(Account account) {
if (account.isShowOngoing()) {
if (account.isNotifySync()) {
notificationController.clearFetchingMailNotification(account);
}
}
@ -2617,7 +2621,7 @@ public class MessagingController {
@Override
public void run() {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
long oldSize = localStore.getSize();
localStore.compact();
long newSize = localStore.getSize();
@ -2639,7 +2643,7 @@ public class MessagingController {
@Override
public void run() {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
long oldSize = localStore.getSize();
localStore.clear();
localStore.resetVisibleLimits(account.getDisplayCount());
@ -2667,7 +2671,7 @@ public class MessagingController {
@Override
public void run() {
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
long oldSize = localStore.getSize();
localStore.recreate();
localStore.resetVisibleLimits(account.getDisplayCount());
@ -2765,7 +2769,7 @@ public class MessagingController {
public Message saveDraft(final Account account, final Message message, long existingDraftId, String plaintextSubject, boolean saveRemotely) {
LocalMessage localMessage = null;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
LocalFolder localFolder = localStore.getFolder(account.getDraftsFolder());
localFolder.open(Folder.OPEN_MODE_RW);
@ -2870,7 +2874,7 @@ public class MessagingController {
List<String> names = new ArrayList<>();
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
for (final Folder folder : localStore.getPersonalNamespaces(false)) {
if (folder.getServerId().equals(account.getOutboxFolder())) {
continue;
@ -2910,7 +2914,7 @@ public class MessagingController {
}
if (!names.isEmpty()) {
PushReceiver receiver = new MessagingControllerPushReceiver(context, account, this);
PushReceiver receiver = new MessagingControllerPushReceiver(context, localStoreProvider, account, this);
int maxPushFolders = account.getMaxPushFolders();
if (names.size() > maxPushFolders) {
@ -3038,7 +3042,7 @@ public class MessagingController {
private void actOnMessageGroup(
Account account, String folderServerId, List<MessageReference> messageReferences, MessageActor actor) {
try {
LocalFolder messageFolder = account.getLocalStore().getFolder(folderServerId);
LocalFolder messageFolder = localStoreProvider.getInstance(account).getFolder(folderServerId);
List<LocalMessage> localMessages = messageFolder.getMessagesByReference(messageReferences);
actor.act(account, messageFolder, localMessages);
} catch (MessagingException e) {

View file

@ -1,31 +1,34 @@
package com.fsck.k9.controller;
import android.content.Context;
import com.fsck.k9.mail.power.WakeLock;
import timber.log.Timber;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import android.content.Context;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.mail.Folder;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.PushReceiver;
import com.fsck.k9.mail.power.WakeLock;
import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.service.SleepService;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import timber.log.Timber;
public class MessagingControllerPushReceiver implements PushReceiver {
final Account account;
final MessagingController controller;
final Context context;
final LocalStoreProvider localStoreProvider;
public MessagingControllerPushReceiver(Context context, Account nAccount, MessagingController nController) {
public MessagingControllerPushReceiver(Context context, LocalStoreProvider localStoreProvider,
Account nAccount, MessagingController nController) {
account = nAccount;
controller = nController;
this.localStoreProvider = localStoreProvider;
this.context = context;
}
@ -90,7 +93,7 @@ public class MessagingControllerPushReceiver implements PushReceiver {
public String getPushState(String folderServerId) {
LocalFolder localFolder = null;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = localStoreProvider.getInstance(account);
localFolder = localStore.getFolder(folderServerId);
localFolder.open(Folder.OPEN_MODE_RW);
return localFolder.getPushState();

View file

@ -6,6 +6,7 @@ import com.fsck.k9.mail.Folder.FolderClass
import com.fsck.k9.mail.Folder.FolderType as RemoteFolderType
class FolderRepository(
private val localStoreProvider: LocalStoreProvider,
private val specialFolderSelectionStrategy: SpecialFolderSelectionStrategy,
private val account: Account
) {
@ -30,7 +31,7 @@ class FolderRepository(
}
private fun getRemoteFolders(): List<Folder> {
val folders = account.localStore.getPersonalNamespaces(false)
val folders = localStoreProvider.getInstance(account).getPersonalNamespaces(false)
return folders
.filterNot { it.isLocalOnly }
@ -38,7 +39,7 @@ class FolderRepository(
}
fun getDisplayFolders(): List<Folder> {
val folders = account.localStore.getPersonalNamespaces(false)
val folders = localStoreProvider.getInstance(account).getPersonalNamespaces(false)
return folders
.filter(::shouldDisplayFolder)
.sortedWith(sortForDisplay)

View file

@ -2,6 +2,9 @@ package com.fsck.k9.mailstore
import com.fsck.k9.Account
class FolderRepositoryManager(private val specialFolderSelectionStrategy: SpecialFolderSelectionStrategy) {
fun getFolderRepository(account: Account) = FolderRepository(specialFolderSelectionStrategy, account)
class FolderRepositoryManager(
private val localStoreProvider: LocalStoreProvider,
private val specialFolderSelectionStrategy: SpecialFolderSelectionStrategy
) {
fun getFolderRepository(account: Account) = FolderRepository(localStoreProvider, specialFolderSelectionStrategy, account)
}

View file

@ -230,7 +230,7 @@ class K9BackendFolder(
override fun setLatestOldMessageSeenTime(date: Date) {
account.latestOldMessageSeenTime = date.time
account.save(preferences)
preferences.saveAccount(account)
}
override fun getOldestMessageDate(): Date? {

View file

@ -5,11 +5,13 @@ import com.fsck.k9.Preferences
class K9BackendStorageFactory(
private val preferences: Preferences,
private val folderRepositoryManager: FolderRepositoryManager
private val folderRepositoryManager: FolderRepositoryManager,
private val localStoreProvider: LocalStoreProvider
) {
fun createBackendStorage(account: Account): K9BackendStorage {
val folderRepository = folderRepositoryManager.getFolderRepository(account)
val localStore = localStoreProvider.getInstance(account)
val specialFolderUpdater = SpecialFolderUpdater(preferences, folderRepository, account)
return K9BackendStorage(preferences, account, account.localStore, specialFolderUpdater)
return K9BackendStorage(preferences, account, localStore, specialFolderUpdater)
}
}

View file

@ -3,10 +3,10 @@ package com.fsck.k9.mailstore
import org.koin.dsl.module.applicationContext
val mailStoreModule = applicationContext {
bean { FolderRepositoryManager(get()) }
bean { FolderRepositoryManager(get(), get()) }
bean { MessageViewInfoExtractor(get(), get(), get()) }
bean { StorageManager.getInstance(get()) }
bean { SearchStatusManager() }
bean { SpecialFolderSelectionStrategy() }
bean { K9BackendStorageFactory(get(), get()) }
bean { K9BackendStorageFactory(get(), get(), get()) }
}

View file

@ -147,7 +147,7 @@ public class LocalFolder extends Folder<LocalMessage> {
}
public boolean syncRemoteDeletions() {
return getAccount().syncRemoteDeletions();
return getAccount().isSyncRemoteDeletions();
}
@Override

View file

@ -17,8 +17,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import android.content.ContentResolver;
import android.content.ContentValues;
@ -81,18 +79,6 @@ public class LocalStore {
static final String[] EMPTY_STRING_ARRAY = new String[0];
static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
/**
* Lock objects indexed by account UUID.
*
* @see #getInstance(Account, Context)
*/
private static ConcurrentMap<String, Object> sAccountLocks = new ConcurrentHashMap<>();
/**
* Local stores indexed by UUID because the Uri may change due to migration to/from SD-card.
*/
private static ConcurrentMap<String, LocalStore> sLocalStores = new ConcurrentHashMap<>();
/*
* a String containing the columns getMessages expects to work with
* in the correct order.
@ -195,9 +181,13 @@ public class LocalStore {
private final Account account;
private final LockableDatabase database;
static LocalStore createInstance(Account account, Context context) throws MessagingException {
return new LocalStore(account, context);
}
/**
* local://localhost/path/to/database/uuid.db
* This constructor is only used by {@link LocalStore#getInstance(Account, Context)}
* This constructor is only used by {@link LocalStoreProvider#getInstance(Account)}
* @throws UnavailableStorageException if not {@link StorageProvider#isReady(Context)}
*/
private LocalStore(final Account account, final Context context) throws MessagingException {
@ -221,37 +211,6 @@ public class LocalStore {
database.open();
}
/**
* Get an instance of a local mail store.
*
* @throws UnavailableStorageException
* if not {@link StorageProvider#isReady(Context)}
*/
public static LocalStore getInstance(Account account, Context context)
throws MessagingException {
String accountUuid = account.getUuid();
// Create new per-account lock object if necessary
sAccountLocks.putIfAbsent(accountUuid, new Object());
// Use per-account locks so DatabaseUpgradeService always knows which account database is
// currently upgraded.
synchronized (sAccountLocks.get(accountUuid)) {
LocalStore store = sLocalStores.get(accountUuid);
if (store == null) {
// Creating a LocalStore instance will create or upgrade the database if
// necessary. This could take some time.
store = new LocalStore(account, context);
sLocalStores.put(accountUuid, store);
}
return store;
}
}
public static int getDbVersion() {
SchemaDefinitionFactory schemaDefinitionFactory = DI.get(SchemaDefinitionFactory.class);
return schemaDefinitionFactory.getDatabaseVersion();
@ -266,8 +225,7 @@ public class LocalStore {
}
private static void removeInstance(Account account) {
String accountUuid = account.getUuid();
sLocalStores.remove(accountUuid);
DI.get(LocalStoreProvider.class).removeInstance(account);
}
public void switchLocalStorage(final String newStorageProviderId) throws MessagingException {

View file

@ -0,0 +1,30 @@
package com.fsck.k9.mailstore
import android.content.Context
import com.fsck.k9.Account
import com.fsck.k9.DI
import com.fsck.k9.mail.MessagingException
import java.util.concurrent.ConcurrentHashMap
class LocalStoreProvider {
private val localStores = ConcurrentHashMap<String, LocalStore>()
private val accountLocks = ConcurrentHashMap<String, Any>()
@Throws(MessagingException::class)
fun getInstance(account: Account): LocalStore {
val context = DI.get(Context::class.java)
val accountUuid = account.uuid
// Use per-account locks so DatabaseUpgradeService always knows which account database is currently upgraded.
synchronized(accountLocks.getOrPut(accountUuid) { Any() }) {
// Creating a LocalStore instance will create or upgrade the database if
// necessary. This could take some time.
return localStores.getOrPut(accountUuid) { LocalStore.createInstance(account, context) }
}
}
fun removeInstance(account: Account) {
val accountUuid = account.uuid
localStores.remove(accountUuid)
}
}

View file

@ -77,6 +77,6 @@ class SpecialFolderUpdater(
}
private fun saveAccount() {
account.save(preferences)
preferences.saveAccount(account)
}
}

View file

@ -3,6 +3,9 @@ package com.fsck.k9.notification
import android.app.NotificationManager
import android.content.Context
import android.support.v4.app.NotificationManagerCompat
import com.fsck.k9.AccountPreferenceSerializer
import com.fsck.k9.LocalKeyStoreManager
import com.fsck.k9.mail.ssl.LocalKeyStore
import org.koin.dsl.module.applicationContext
import java.util.concurrent.Executors
@ -18,6 +21,9 @@ val coreNotificationModule = applicationContext {
get()
)
}
bean { AccountPreferenceSerializer(get(), get()) }
bean { LocalKeyStore.getInstance() }
bean { LocalKeyStoreManager(get()) }
bean { CertificateErrorNotifications(get(), get(), get()) }
bean { AuthenticationErrorNotifications(get(), get(), get()) }
bean { SyncNotifications(get(), get(), get()) }

View file

@ -20,6 +20,7 @@ import com.fsck.k9.Account.Searchable;
import com.fsck.k9.Account.ShowPictures;
import com.fsck.k9.Account.SortType;
import com.fsck.k9.Account.SpecialFolderSelection;
import com.fsck.k9.AccountPreferenceSerializer;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.core.R;
@ -68,7 +69,7 @@ public class AccountSettings {
new V(1, new ColorSetting(0xFF0000FF))
));
s.put("defaultQuotedTextShown", Settings.versions(
new V(1, new BooleanSetting(Account.DEFAULT_QUOTED_TEXT_SHOWN))
new V(1, new BooleanSetting(AccountPreferenceSerializer.DEFAULT_QUOTED_TEXT_SHOWN))
));
s.put("deletePolicy", Settings.versions(
new V(1, new DeletePolicySetting(DeletePolicy.NEVER))
@ -128,13 +129,13 @@ public class AccountSettings {
new V(1, new IntegerResourceSetting(-1, R.array.message_age_values))
));
s.put("messageFormat", Settings.versions(
new V(1, new EnumSetting<>(MessageFormat.class, Account.DEFAULT_MESSAGE_FORMAT))
new V(1, new EnumSetting<>(MessageFormat.class, AccountPreferenceSerializer.DEFAULT_MESSAGE_FORMAT))
));
s.put("messageFormatAuto", Settings.versions(
new V(2, new BooleanSetting(Account.DEFAULT_MESSAGE_FORMAT_AUTO))
new V(2, new BooleanSetting(AccountPreferenceSerializer.DEFAULT_MESSAGE_FORMAT_AUTO))
));
s.put("messageReadReceipt", Settings.versions(
new V(1, new BooleanSetting(Account.DEFAULT_MESSAGE_READ_RECEIPT))
new V(1, new BooleanSetting(AccountPreferenceSerializer.DEFAULT_MESSAGE_READ_RECEIPT))
));
s.put("notifyMailCheck", Settings.versions(
new V(1, new BooleanSetting(false))
@ -152,13 +153,13 @@ public class AccountSettings {
new V(1, new BooleanSetting(true))
));
s.put("quotePrefix", Settings.versions(
new V(1, new StringSetting(Account.DEFAULT_QUOTE_PREFIX))
new V(1, new StringSetting(AccountPreferenceSerializer.DEFAULT_QUOTE_PREFIX))
));
s.put("quoteStyle", Settings.versions(
new V(1, new EnumSetting<>(QuoteStyle.class, Account.DEFAULT_QUOTE_STYLE))
new V(1, new EnumSetting<>(QuoteStyle.class, AccountPreferenceSerializer.DEFAULT_QUOTE_STYLE))
));
s.put("replyAfterQuote", Settings.versions(
new V(1, new BooleanSetting(Account.DEFAULT_REPLY_AFTER_QUOTE))
new V(1, new BooleanSetting(AccountPreferenceSerializer.DEFAULT_REPLY_AFTER_QUOTE))
));
s.put("ring", Settings.versions(
new V(1, new BooleanSetting(true))
@ -190,7 +191,7 @@ public class AccountSettings {
new V(53, new StringSetting(null))
));
s.put("stripSignature", Settings.versions(
new V(2, new BooleanSetting(Account.DEFAULT_STRIP_SIGNATURE))
new V(2, new BooleanSetting(AccountPreferenceSerializer.DEFAULT_STRIP_SIGNATURE))
));
s.put("subscribedFoldersOnly", Settings.versions(
new V(1, new BooleanSetting(false))
@ -224,7 +225,7 @@ public class AccountSettings {
new V(18, new BooleanSetting(true))
));
s.put("remoteSearchNumResults", Settings.versions(
new V(18, new IntegerResourceSetting(Account.DEFAULT_REMOTE_SEARCH_NUM_RESULTS,
new V(18, new IntegerResourceSetting(AccountPreferenceSerializer.DEFAULT_REMOTE_SEARCH_NUM_RESULTS,
R.array.remote_search_num_results_values))
));
s.put("remoteSearchFullText", Settings.versions(

View file

@ -23,6 +23,7 @@ import android.os.Environment;
import android.util.Xml;
import com.fsck.k9.Account;
import com.fsck.k9.AccountPreferenceSerializer;
import com.fsck.k9.DI;
import com.fsck.k9.Preferences;
import com.fsck.k9.backend.BackendManager;
@ -226,7 +227,7 @@ public class SettingsExporter {
serializer.startTag(null, ACCOUNT_ELEMENT);
serializer.attribute(null, UUID_ATTRIBUTE, accountUuid);
String name = (String) prefs.get(accountUuid + "." + Account.ACCOUNT_DESCRIPTION_KEY);
String name = (String) prefs.get(accountUuid + "." + AccountPreferenceSerializer.ACCOUNT_DESCRIPTION_KEY);
if (name != null) {
serializer.startTag(null, NAME_ELEMENT);
serializer.text(name);
@ -324,7 +325,7 @@ public class SettingsExporter {
String secondPart = keyPart.substring(0, indexOfLastDot);
String thirdPart = keyPart.substring(indexOfLastDot + 1);
if (Account.IDENTITY_DESCRIPTION_KEY.equals(secondPart)) {
if (AccountPreferenceSerializer.IDENTITY_DESCRIPTION_KEY.equals(secondPart)) {
// This is an identity key. Save identity index for later...
try {
identities.add(Integer.parseInt(thirdPart));
@ -393,19 +394,19 @@ public class SettingsExporter {
String suffix = "." + identity;
// Write name belonging to the identity
String name = (String) prefs.get(prefix + Account.IDENTITY_NAME_KEY + suffix);
String name = (String) prefs.get(prefix + AccountPreferenceSerializer.IDENTITY_NAME_KEY + suffix);
serializer.startTag(null, NAME_ELEMENT);
serializer.text(name);
serializer.endTag(null, NAME_ELEMENT);
// Write email address belonging to the identity
String email = (String) prefs.get(prefix + Account.IDENTITY_EMAIL_KEY + suffix);
String email = (String) prefs.get(prefix + AccountPreferenceSerializer.IDENTITY_EMAIL_KEY + suffix);
serializer.startTag(null, EMAIL_ELEMENT);
serializer.text(email);
serializer.endTag(null, EMAIL_ELEMENT);
// Write identity description
String description = (String) prefs.get(prefix + Account.IDENTITY_DESCRIPTION_KEY + suffix);
String description = (String) prefs.get(prefix + AccountPreferenceSerializer.IDENTITY_DESCRIPTION_KEY + suffix);
if (description != null) {
serializer.startTag(null, DESCRIPTION_ELEMENT);
serializer.text(description);

View file

@ -18,6 +18,7 @@ import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import com.fsck.k9.Account;
import com.fsck.k9.AccountPreferenceSerializer;
import com.fsck.k9.Core;
import com.fsck.k9.DI;
import com.fsck.k9.Identity;
@ -338,7 +339,7 @@ public class SettingsImporter {
// Write account name
String accountKeyPrefix = uuid + ".";
putString(editor, accountKeyPrefix + Account.ACCOUNT_DESCRIPTION_KEY, accountName);
putString(editor, accountKeyPrefix + AccountPreferenceSerializer.ACCOUNT_DESCRIPTION_KEY, accountName);
if (account.incoming == null) {
// We don't import accounts without incoming server settings
@ -349,7 +350,7 @@ public class SettingsImporter {
ServerSettings incoming = new ImportedServerSettings(account.incoming);
BackendManager backendManager = DI.get(BackendManager.class);
String storeUri = backendManager.createStoreUri(incoming);
putString(editor, accountKeyPrefix + Account.STORE_URI_KEY, Base64.encode(storeUri));
putString(editor, accountKeyPrefix + AccountPreferenceSerializer.STORE_URI_KEY, Base64.encode(storeUri));
// Mark account as disabled if the AuthType isn't EXTERNAL and the
// settings file didn't contain a password
@ -366,7 +367,7 @@ public class SettingsImporter {
// Write outgoing server settings (transportUri)
ServerSettings outgoing = new ImportedServerSettings(account.outgoing);
String transportUri = backendManager.createTransportUri(outgoing);
putString(editor, accountKeyPrefix + Account.TRANSPORT_URI_KEY, Base64.encode(transportUri));
putString(editor, accountKeyPrefix + AccountPreferenceSerializer.TRANSPORT_URI_KEY, Base64.encode(transportUri));
/*
* Mark account as disabled if the settings file contained a username but no password. However, no password
@ -417,7 +418,7 @@ public class SettingsImporter {
// If it's a new account generate and write a new "accountNumber"
if (!mergeImportedAccount) {
int newAccountNumber = Account.generateAccountNumber(prefs);
int newAccountNumber = prefs.generateAccountNumber();
putString(editor, accountKeyPrefix + "accountNumber", Integer.toString(newAccountNumber));
}
@ -522,7 +523,7 @@ public class SettingsImporter {
// Write name used in identity
String identityName = (identity.name == null) ? "" : identity.name;
putString(editor, accountKeyPrefix + Account.IDENTITY_NAME_KEY + identitySuffix, identityName);
putString(editor, accountKeyPrefix + AccountPreferenceSerializer.IDENTITY_NAME_KEY + identitySuffix, identityName);
// Validate email address
if (!IdentitySettings.isEmailAddressValid(identity.email)) {
@ -530,10 +531,10 @@ public class SettingsImporter {
}
// Write email address
putString(editor, accountKeyPrefix + Account.IDENTITY_EMAIL_KEY + identitySuffix, identity.email);
putString(editor, accountKeyPrefix + AccountPreferenceSerializer.IDENTITY_EMAIL_KEY + identitySuffix, identity.email);
// Write identity description
putString(editor, accountKeyPrefix + Account.IDENTITY_DESCRIPTION_KEY + identitySuffix,
putString(editor, accountKeyPrefix + AccountPreferenceSerializer.IDENTITY_DESCRIPTION_KEY + identitySuffix,
identityDescription);
if (identity.settings != null) {

View file

@ -13,6 +13,9 @@ import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fsck.k9.DI;
import com.fsck.k9.mailstore.LocalStoreProvider;
import timber.log.Timber;
import com.fsck.k9.Account;
@ -94,7 +97,7 @@ public class AttachmentProvider extends ContentProvider {
final AttachmentInfo attachmentInfo;
try {
final Account account = Preferences.getPreferences(getContext()).getAccount(accountUuid);
attachmentInfo = LocalStore.getInstance(account, getContext()).getAttachmentInfo(id);
attachmentInfo = DI.get(LocalStoreProvider.class).getInstance(account).getAttachmentInfo(id);
} catch (MessagingException e) {
Timber.e(e, "Unable to retrieve attachment info from local store for ID: %s", id);
return null;
@ -143,7 +146,7 @@ public class AttachmentProvider extends ContentProvider {
final Account account = Preferences.getPreferences(getContext()).getAccount(accountUuid);
try {
final LocalStore localStore = LocalStore.getInstance(account, getContext());
final LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
AttachmentInfo attachmentInfo = localStore.getAttachmentInfo(id);
if (mimeType != null) {
@ -180,7 +183,7 @@ public class AttachmentProvider extends ContentProvider {
@Nullable
private OpenPgpDataSource getAttachmentDataSource(String accountUuid, String attachmentId) throws MessagingException {
final Account account = Preferences.getPreferences(getContext()).getAccount(accountUuid);
LocalStore localStore = LocalStore.getInstance(account, getContext());
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
return localStore.getAttachmentDataSource(attachmentId);
}
}

View file

@ -18,11 +18,13 @@ import android.net.Uri;
import android.text.TextUtils;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.Preferences;
import com.fsck.k9.cache.EmailProviderCacheCursor;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.mailstore.LockableDatabase;
import com.fsck.k9.mailstore.LockableDatabase.DbCallback;
import com.fsck.k9.mailstore.LockableDatabase.WrappedException;
@ -527,7 +529,7 @@ public class EmailProvider extends ContentProvider {
private LockableDatabase getDatabase(Account account) {
LocalStore localStore;
try {
localStore = account.getLocalStore();
localStore = DI.get(LocalStoreProvider.class).getInstance(account);
} catch (MessagingException e) {
throw new RuntimeException("Couldn't get LocalStore", e);
}

View file

@ -18,6 +18,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.Preferences;
import com.fsck.k9.controller.MessageReference;
import com.fsck.k9.mail.FetchProfile;
@ -27,6 +28,7 @@ import com.fsck.k9.mail.filter.CountingOutputStream;
import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.LocalStoreProvider;
import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSource;
import timber.log.Timber;
@ -181,7 +183,7 @@ public class RawMessageProvider extends ContentProvider {
}
try {
LocalStore localStore = LocalStore.getInstance(account, getContext());
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalFolder localFolder = localStore.getFolder(folderServerId);
localFolder.open(Folder.OPEN_MODE_RW);

View file

@ -0,0 +1,124 @@
package com.fsck.k9.search
import com.fsck.k9.Account
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.BaseAccount
import com.fsck.k9.mail.Folder.FolderClass
import com.fsck.k9.search.SearchSpecification.*
class AccountSearchConditions {
/**
* Modify the supplied [LocalSearch] instance to limit the search to displayable folders.
*
* This method uses the current folder display mode to decide what folders to include/exclude.
*
* @param search
* The `LocalSearch` instance to modify.
*
* @see .getFolderDisplayMode
*/
fun limitToDisplayableFolders(account: Account, search: LocalSearch) {
val displayMode = account.folderDisplayMode
when (displayMode) {
FolderMode.FIRST_CLASS -> {
// Count messages in the INBOX and non-special first class folders
search.and(SearchField.DISPLAY_CLASS, FolderClass.FIRST_CLASS.name, Attribute.EQUALS)
}
FolderMode.FIRST_AND_SECOND_CLASS -> {
// Count messages in the INBOX and non-special first and second class folders
search.and(SearchField.DISPLAY_CLASS, FolderClass.FIRST_CLASS.name, Attribute.EQUALS)
// TODO: Create a proper interface for creating arbitrary condition trees
val searchCondition = SearchCondition(
SearchField.DISPLAY_CLASS, Attribute.EQUALS, FolderClass.SECOND_CLASS.name)
val root = search.conditions
if (root.mRight != null) {
root.mRight.or(searchCondition)
} else {
search.or(searchCondition)
}
}
FolderMode.NOT_SECOND_CLASS -> {
// Count messages in the INBOX and non-special non-second-class folders
search.and(SearchField.DISPLAY_CLASS, FolderClass.SECOND_CLASS.name, Attribute.NOT_EQUALS)
}
FolderMode.ALL, FolderMode.NONE -> {
// Count messages in the INBOX and non-special folders
}
}
}
/**
* Modify the supplied [LocalSearch] instance to exclude special folders.
*
* Currently the following folders are excluded:
*
* * Trash
* * Drafts
* * Spam
* * Outbox
* * Sent
*
* The Inbox will always be included even if one of the special folders is configured to point
* to the Inbox.
*
* @param search
* The `LocalSearch` instance to modify.
*/
fun excludeSpecialFolders(account: Account, search: LocalSearch) {
excludeSpecialFolder(search, account.trashFolder)
excludeSpecialFolder(search, account.draftsFolder)
excludeSpecialFolder(search, account.spamFolder)
excludeSpecialFolder(search, account.outboxFolder)
excludeSpecialFolder(search, account.sentFolder)
search.or(SearchCondition(SearchField.FOLDER, Attribute.EQUALS, account.getInboxFolder()))
}
/**
* Modify the supplied [LocalSearch] instance to exclude "unwanted" folders.
*
* Currently the following folders are excluded:
*
* * Trash
* * Spam
* * Outbox
*
* The Inbox will always be included even if one of the special folders is configured to point
* to the Inbox.
*
* @param search
* The `LocalSearch` instance to modify.
*/
fun excludeUnwantedFolders(account: Account, search: LocalSearch) {
excludeSpecialFolder(search, account.trashFolder)
excludeSpecialFolder(search, account.spamFolder)
excludeSpecialFolder(search, account.outboxFolder)
search.or(SearchCondition(SearchField.FOLDER, Attribute.EQUALS, account.inboxFolder))
}
private fun excludeSpecialFolder(search: LocalSearch, folderServerId: String?) {
if (folderServerId != null) {
search.and(SearchField.FOLDER, folderServerId, Attribute.NOT_EQUALS)
}
}
fun createUnreadSearch(account: BaseAccount, searchTitle: String): LocalSearch {
val search: LocalSearch
if (account is SearchAccount) {
search = account.relatedSearch.clone()
search.name = searchTitle
} else {
search = LocalSearch(searchTitle)
search.addAccountUuid(account.uuid)
val realAccount = account as Account
excludeSpecialFolders(realAccount, search)
limitToDisplayableFolders(realAccount, search)
}
search.and(SearchField.READ, "1", Attribute.NOT_EQUALS)
return search
}
}

View file

@ -0,0 +1,8 @@
package com.fsck.k9.search
import com.fsck.k9.mailstore.*
import org.koin.dsl.module.applicationContext
val searchModule = applicationContext {
bean { AccountSearchConditions() }
}

View file

@ -2,6 +2,8 @@ package com.fsck.k9.search;
import java.util.List;
import com.fsck.k9.DI;
import com.fsck.k9.mailstore.LocalStoreProvider;
import timber.log.Timber;
import com.fsck.k9.Account;
@ -28,6 +30,7 @@ public class SqlQueryBuilder {
}
if (node.mLeft == null && node.mRight == null) {
AccountSearchConditions accountSearchConditions = DI.get(AccountSearchConditions.class);
SearchCondition condition = node.mCondition;
switch (condition.field) {
case FOLDER: {
@ -48,7 +51,7 @@ public class SqlQueryBuilder {
LocalSearch tempSearch = new LocalSearch();
// ...the helper methods in Account to create the necessary conditions
// to exclude "unwanted" folders.
account.excludeUnwantedFolders(tempSearch);
accountSearchConditions.excludeUnwantedFolders(account, tempSearch);
buildWhereClauseInternal(account, tempSearch.getConditions(), query,
selectionArgs);
@ -59,8 +62,8 @@ public class SqlQueryBuilder {
LocalSearch tempSearch = new LocalSearch();
// ...the helper methods in Account to create the necessary conditions
// to limit the selection to displayable, non-special folders.
account.excludeSpecialFolders(tempSearch);
account.limitToDisplayableFolders(tempSearch);
accountSearchConditions.excludeSpecialFolders(account, tempSearch);
accountSearchConditions.limitToDisplayableFolders(account, tempSearch);
buildWhereClauseInternal(account, tempSearch.getConditions(), query,
selectionArgs);
@ -107,7 +110,7 @@ public class SqlQueryBuilder {
private static long getFolderId(Account account, String folderServerId) {
long folderId = 0;
try {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalFolder folder = localStore.getFolder(folderServerId);
folder.open(Folder.OPEN_MODE_RO);
folderId = folder.getDatabaseId();

View file

@ -12,8 +12,10 @@ import android.os.PowerManager;
import android.support.v4.content.LocalBroadcastManager;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.mailstore.UnavailableStorageException;
import com.fsck.k9.power.TracingPowerManager;
import com.fsck.k9.power.TracingPowerManager.TracingWakeLock;
@ -192,7 +194,7 @@ public class DatabaseUpgradeService extends Service {
try {
// Account.getLocalStore() is blocking and will upgrade the database if necessary
account.getLocalStore();
DI.get(LocalStoreProvider.class).getInstance(account);
} catch (UnavailableStorageException e) {
Timber.e("Database unavailable");
} catch (Exception e) {

View file

@ -1,13 +1,9 @@
package com.fsck.k9
class TestCoreResourceProvider : CoreResourceProvider {
override fun defaultSignature(): String {
throw UnsupportedOperationException("not implemented")
}
override fun defaultSignature() = "\n--\nbrevity!"
override fun defaultIdentityDescription(): String {
throw UnsupportedOperationException("not implemented")
}
override fun defaultIdentityDescription() = "initial identity"
override fun sendAlternateChooserTitle(): String {
throw UnsupportedOperationException("not implemented")

View file

@ -11,8 +11,11 @@ import java.util.Set;
import android.content.Context;
import com.fsck.k9.Account;
import com.fsck.k9.Account.SpecialFolderSelection;
import com.fsck.k9.AccountPreferenceSerializer;
import com.fsck.k9.AccountStats;
import com.fsck.k9.CoreResourceProvider;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.K9RobolectricTest;
import com.fsck.k9.Preferences;
@ -29,6 +32,7 @@ import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.mailstore.UnavailableStorageException;
import com.fsck.k9.notification.NotificationController;
import com.fsck.k9.search.LocalSearch;
@ -44,6 +48,7 @@ import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@ -61,6 +66,7 @@ import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@ -71,17 +77,18 @@ public class MessagingControllerTest extends K9RobolectricTest {
private static final String FOLDER_NAME = "Folder";
private static final String SENT_FOLDER_NAME = "Sent";
private static final int MAXIMUM_SMALL_MESSAGE_SIZE = 1000;
private static final String ACCOUNT_UUID = "1";
private MessagingController controller;
private Account account;
@Mock
private BackendManager backendManager;
@Mock
private Backend backend;
@Mock
private Contacts contacts;
private LocalStoreProvider localStoreProvider;
@Mock
private Account account;
private Contacts contacts;
@Mock
private AccountStats accountStats;
@Mock
@ -137,17 +144,18 @@ public class MessagingControllerTest extends K9RobolectricTest {
MockitoAnnotations.initMocks(this);
appContext = RuntimeEnvironment.application;
controller = new MessagingController(appContext, notificationController, contacts,
controller = new MessagingController(appContext, notificationController, localStoreProvider, contacts,
accountStatsCollector, mock(CoreResourceProvider.class), backendManager,
Collections.<ControllerExtension>emptyList());
configureBackendManager();
configureAccount();
configureBackendManager();
configureLocalStore();
}
@After
public void tearDown() throws Exception {
removeAccountsFromPreferences();
controller.stop();
StandAloneContext.INSTANCE.closeKoin();
}
@ -258,7 +266,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
@Test
public void searchLocalMessagesSynchronous_shouldCallSearchForMessagesOnLocalStore()
throws Exception {
setAccountsInPreferences(Collections.singletonMap("1", account));
setAccountsInPreferences(Collections.singletonMap(ACCOUNT_UUID, account));
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
controller.searchLocalMessagesSynchronous(search, listener);
@ -269,7 +277,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
@Test
public void searchLocalMessagesSynchronous_shouldNotifyWhenStoreFinishesRetrievingAMessage()
throws Exception {
setAccountsInPreferences(Collections.singletonMap("1", account));
setAccountsInPreferences(Collections.singletonMap(ACCOUNT_UUID, account));
LocalMessage localMessage = mock(LocalMessage.class);
when(localMessage.getFolder()).thenReturn(localFolder);
when(search.getAccountUuids()).thenReturn(new String[]{"allAccounts"});
@ -285,7 +293,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
}
private void setupRemoteSearch() throws Exception {
setAccountsInPreferences(Collections.singletonMap("1", account));
setAccountsInPreferences(Collections.singletonMap(ACCOUNT_UUID, account));
remoteMessages = new ArrayList<>();
Collections.addAll(remoteMessages, "oldMessageUid", "newMessageUid1", "newMessageUid2");
@ -323,14 +331,14 @@ public class MessagingControllerTest extends K9RobolectricTest {
reqFlags = Collections.singleton(Flag.ANSWERED);
forbiddenFlags = Collections.singleton(Flag.DELETED);
when(account.getRemoteSearchNumResults()).thenReturn(50);
account.setRemoteSearchNumResults(50);
}
@Test
public void searchRemoteMessagesSynchronous_shouldNotifyStartedListingRemoteMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(listener).remoteSearchStarted(FOLDER_NAME);
}
@ -339,7 +347,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
public void searchRemoteMessagesSynchronous_shouldQueryRemoteFolder() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(backend).search(FOLDER_NAME, "query", reqFlags, forbiddenFlags);
}
@ -348,7 +356,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
public void searchRemoteMessagesSynchronous_shouldAskLocalFolderToDetermineNewMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(localFolder).extractNewMessages(remoteMessages);
}
@ -357,7 +365,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
public void searchRemoteMessagesSynchronous_shouldTryAndGetNewMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(localFolder).getMessage("newMessageUid1");
}
@ -366,7 +374,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
public void searchRemoteMessagesSynchronous_shouldNotTryAndGetOldMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(localFolder, never()).getMessage("oldMessageUid");
}
@ -375,7 +383,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
public void searchRemoteMessagesSynchronous_shouldFetchNewMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(backend).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid2"), fetchProfileCaptor.capture());
}
@ -384,7 +392,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
public void searchRemoteMessagesSynchronous_shouldNotFetchExistingMessages() throws Exception {
setupRemoteSearch();
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(backend, never()).fetchMessage(eq(FOLDER_NAME), eq("newMessageUid1"), fetchProfileCaptor.capture());
}
@ -395,7 +403,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
when(backend.search(anyString(), anyString(), nullable(Set.class), nullable(Set.class)))
.thenThrow(new MessagingException("Test"));
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(listener).remoteSearchFailed(null, "Test");
}
@ -406,7 +414,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
when(backend.search(anyString(), nullable(String.class), nullable(Set.class), nullable(Set.class)))
.thenThrow(new MessagingException("Test"));
controller.searchRemoteMessagesSynchronous("1", FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
controller.searchRemoteMessagesSynchronous(ACCOUNT_UUID, FOLDER_NAME, "query", reqFlags, forbiddenFlags, listener);
verify(listener).remoteSearchFinished(FOLDER_NAME, 0, 50, Collections.<String>emptyList());
}
@ -519,8 +527,7 @@ public class MessagingControllerTest extends K9RobolectricTest {
private void setupAccountWithMessageToSend() throws MessagingException {
when(account.getOutboxFolder()).thenReturn(FOLDER_NAME);
when(account.hasSentFolder()).thenReturn(true);
when(account.getSentFolder()).thenReturn(SENT_FOLDER_NAME);
account.setSentFolder(SENT_FOLDER_NAME, SpecialFolderSelection.AUTOMATIC);
when(localStore.getFolder(SENT_FOLDER_NAME)).thenReturn(sentFolder);
when(sentFolder.getDatabaseId()).thenReturn(1L);
when(localFolder.exists()).thenReturn(true);
@ -535,20 +542,24 @@ public class MessagingControllerTest extends K9RobolectricTest {
}
private void configureAccount() throws MessagingException {
when(account.isAvailable(appContext)).thenReturn(true);
when(account.getLocalStore()).thenReturn(localStore);
when(account.getMaximumAutoDownloadMessageSize()).thenReturn(MAXIMUM_SMALL_MESSAGE_SIZE);
when(account.getEmail()).thenReturn("user@host.com");
// TODO use simple account object without mocks
account = spy(new Account(ACCOUNT_UUID));
DI.get(AccountPreferenceSerializer.class).loadDefaults(account);
account.setMaximumAutoDownloadMessageSize(MAXIMUM_SMALL_MESSAGE_SIZE);
account.setEmail("user@host.com");
Mockito.doReturn(true).when(account).isAvailable(appContext);
}
private void configureLocalStore() throws MessagingException {
when(localStore.getFolder(FOLDER_NAME)).thenReturn(localFolder);
when(localFolder.getServerId()).thenReturn(FOLDER_NAME);
when(localStore.getPersonalNamespaces(false)).thenReturn(Collections.singletonList(localFolder));
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);
@ -558,4 +569,8 @@ public class MessagingControllerTest extends K9RobolectricTest {
ArrayList<Account> newAccountsInOrder = new ArrayList<>(newAccounts.values());
accountsInOrder.set(Preferences.getPreferences(appContext), newAccountsInOrder);
}
private void removeAccountsFromPreferences() {
Preferences.getPreferences(appContext).clearAccounts();
}
}

View file

@ -9,9 +9,8 @@ import com.fsck.k9.mail.Message
import com.fsck.k9.mail.Message.RecipientType
import com.fsck.k9.mail.internet.MimeMessage
import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockito_kotlin.mock
import org.junit.Test
import org.robolectric.RuntimeEnvironment
import java.util.*
class IdentityHelperTest : RobolectricTest() {
private val account = createDummyAccount()
@ -110,7 +109,7 @@ class IdentityHelperTest : RobolectricTest() {
}
private fun createDummyAccount() = DummyAccount().apply {
private fun createDummyAccount() = Account(UUID.randomUUID().toString()).apply {
identities = listOf(
newIdentity("Default", DEFAULT_ADDRESS),
newIdentity("Identity 1", IDENTITY_1_ADDRESS),
@ -142,7 +141,4 @@ class IdentityHelperTest : RobolectricTest() {
const val IDENTITY_4_ADDRESS = "identity4@example.org"
const val IDENTITY_5_ADDRESS = "identity5@example.org"
}
class DummyAccount : Account(RuntimeEnvironment.application, mock())
}

View file

@ -27,10 +27,11 @@ import org.koin.standalone.inject
class K9BackendFolderTest : K9RobolectricTest() {
val preferences: Preferences by inject()
val folderRepositoryManager: FolderRepositoryManager by inject()
val localStoreProvider: LocalStoreProvider by inject()
val account: Account = createAccount()
val backendFolder = createBackendFolder()
val database: LockableDatabase = account.localStore.database
val database: LockableDatabase = localStoreProvider.getInstance(account).database
@Before
@ -78,13 +79,13 @@ class K9BackendFolderTest : K9RobolectricTest() {
fun createAccount(): Account {
//FIXME: This is a hack to get Preferences into a state where it's safe to call newAccount()
preferences.loadAccounts()
preferences.clearAccounts()
return preferences.newAccount()
}
fun createBackendFolder(): BackendFolder {
val localStore: LocalStore = account.localStore
val localStore: LocalStore = localStoreProvider.getInstance(account)
val folderRepository = folderRepositoryManager.getFolderRepository(account)
val specialFolderUpdater = SpecialFolderUpdater(preferences, folderRepository, account)
val backendStorage = K9BackendStorage(preferences, account, localStore, specialFolderUpdater)

View file

@ -6,7 +6,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.fsck.k9.Account;
import com.fsck.k9.K9RobolectricTest;
import com.fsck.k9.Preferences;
import com.fsck.k9.mail.AuthType;
@ -32,9 +31,7 @@ public class SettingsImporterTest extends K9RobolectricTest {
private void deletePreExistingAccounts() {
Preferences preferences = Preferences.getPreferences(RuntimeEnvironment.application);
for (Account account : preferences.getAccounts()) {
preferences.deleteAccount(account);
}
preferences.clearAccounts();
}
@Test(expected = SettingsImportExportException.class)

View file

@ -55,7 +55,7 @@ public class MessageProviderTest extends ProviderTestCase2 {
account.setDescription("TestAccount");
account.setChipColor(10);
account.setStoreUri("imap://user@domain.com/");
account.save(preferences);
preferences.saveAccount(account);
}
@Test

View file

@ -12,6 +12,7 @@ import android.test.ApplicationTestCase;
import android.test.RenamingDelegatingContext;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.mail.Body;
import com.fsck.k9.mail.FetchProfile;
@ -134,7 +135,7 @@ public class ReconstructMessageFromDatabaseTest extends ApplicationTestCase<K9>
}
protected LocalFolder createFolderInDatabase() throws MessagingException {
LocalStore localStore = LocalStore.getInstance(account, getApplication());
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalFolder inbox = localStore.getFolder("INBOX");
localStore.createFolders(Collections.singletonList(inbox), 10);
return inbox;

View file

@ -13,10 +13,12 @@ import android.support.test.runner.AndroidJUnit4;
import android.test.ProviderTestCase2;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.Preferences;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.internet.MimeMessage;
import com.fsck.k9.mailstore.LocalStoreProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -157,7 +159,7 @@ public class EmailProviderTest extends ProviderTestCase2<EmailProvider> {
public void query_forMessagesWithAccountAndRequiredFieldsAndOrderBy_providesResult() throws MessagingException {
Account account = Preferences.getPreferences(getContext()).newAccount();
account.getUuid();
account.getLocalStore().getFolder("Inbox").appendMessages(Collections.singletonList(message));
DI.get(LocalStoreProvider.class).getInstance(account).getFolder("Inbox").appendMessages(Collections.singletonList(message));
Cursor cursor = getProvider().query(
Uri.parse("content://" + EmailProvider.AUTHORITY + "/account/" + account.getUuid() + "/messages"),
@ -179,7 +181,8 @@ public class EmailProviderTest extends ProviderTestCase2<EmailProvider> {
public void query_forMessagesWithAccountAndRequiredFieldsAndOrderBy_sortsCorrectly() throws MessagingException {
Account account = Preferences.getPreferences(getContext()).newAccount();
account.getUuid();
account.getLocalStore().getFolder("Inbox").appendMessages(Arrays.asList(message, laterMessage));
DI.get(LocalStoreProvider.class).getInstance(account)
.getFolder("Inbox").appendMessages(Arrays.asList(message, laterMessage));
Cursor cursor = getProvider().query(
Uri.parse("content://" + EmailProvider.AUTHORITY + "/account/" + account.getUuid() + "/messages"),
@ -204,7 +207,8 @@ public class EmailProviderTest extends ProviderTestCase2<EmailProvider> {
public void query_forThreadedMessages_sortsCorrectly() throws MessagingException {
Account account = Preferences.getPreferences(getContext()).newAccount();
account.getUuid();
account.getLocalStore().getFolder("Inbox").appendMessages(Arrays.asList(message, laterMessage));
DI.get(LocalStoreProvider.class).getInstance(account)
.getFolder("Inbox").appendMessages(Arrays.asList(message, laterMessage));
Cursor cursor = getProvider().query(
Uri.parse("content://" + EmailProvider.AUTHORITY + "/account/" + account.getUuid() +
@ -230,8 +234,8 @@ public class EmailProviderTest extends ProviderTestCase2<EmailProvider> {
public void query_forThreadedMessages_showsThreadOfEmailOnce() throws MessagingException {
Account account = Preferences.getPreferences(getContext()).newAccount();
account.getUuid();
account.getLocalStore().getFolder("Inbox").appendMessages(Collections.singletonList(message));
account.getLocalStore().getFolder("Inbox").appendMessages(Collections.singletonList(reply));
DI.get(LocalStoreProvider.class).getInstance(account).getFolder("Inbox").appendMessages(Collections.singletonList(message));
DI.get(LocalStoreProvider.class).getInstance(account).getFolder("Inbox").appendMessages(Collections.singletonList(reply));
Cursor cursor = getProvider().query(
Uri.parse("content://" + EmailProvider.AUTHORITY + "/account/" + account.getUuid() +
@ -258,8 +262,8 @@ public class EmailProviderTest extends ProviderTestCase2<EmailProvider> {
public void query_forThreadedMessages_showsThreadOfEmailWithSameSendTimeOnce() throws MessagingException {
Account account = Preferences.getPreferences(getContext()).newAccount();
account.getUuid();
account.getLocalStore().getFolder("Inbox").appendMessages(Collections.singletonList(message));
account.getLocalStore().getFolder("Inbox").appendMessages(Collections.singletonList(replyAtSameTime));
DI.get(LocalStoreProvider.class).getInstance(account).getFolder("Inbox").appendMessages(Collections.singletonList(message));
DI.get(LocalStoreProvider.class).getInstance(account).getFolder("Inbox").appendMessages(Collections.singletonList(replyAtSameTime));
Cursor cursor = getProvider().query(
Uri.parse("content://" + EmailProvider.AUTHORITY + "/account/" + account.getUuid() +
@ -289,7 +293,7 @@ public class EmailProviderTest extends ProviderTestCase2<EmailProvider> {
Message message = new MimeMessage();
message.setSubject("Test Subject");
message.setSentDate(new GregorianCalendar(2016, 1, 2).getTime(), false);
account.getLocalStore().getFolder("Inbox").appendMessages(Collections.singletonList(message));
DI.get(LocalStoreProvider.class).getInstance(account).getFolder("Inbox").appendMessages(Collections.singletonList(message));
//Now get the thread id we just put in.
Cursor cursor = getProvider().query(

View file

@ -97,7 +97,7 @@ public class RemoteControlService extends CoreService {
account.getNotificationSetting().setRingEnabled(Boolean.parseBoolean(ringEnabled));
}
if (vibrateEnabled != null) {
account.getNotificationSetting().setVibrate(Boolean.parseBoolean(vibrateEnabled));
account.getNotificationSetting().setVibrateEnabled(Boolean.parseBoolean(vibrateEnabled));
}
if (pushClasses != null) {
needsPushRestart |= account.setFolderPushMode(FolderMode.valueOf(pushClasses));
@ -114,7 +114,7 @@ public class RemoteControlService extends CoreService {
}
}
}
account.save(Preferences.getPreferences(RemoteControlService.this));
Preferences.getPreferences(getApplicationContext()).saveAccount(account);
}
}

View file

@ -10,8 +10,10 @@ import android.support.v4.app.TaskStackBuilder;
import android.text.TextUtils;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.R;
import com.fsck.k9.activity.Accounts;
import com.fsck.k9.activity.FolderList;
import com.fsck.k9.activity.MessageList;
@ -20,6 +22,7 @@ import com.fsck.k9.activity.NotificationDeleteConfirmation;
import com.fsck.k9.activity.compose.MessageActions;
import com.fsck.k9.activity.setup.AccountSetupIncoming;
import com.fsck.k9.activity.setup.AccountSetupOutgoing;
import com.fsck.k9.search.AccountSearchConditions;
import com.fsck.k9.search.LocalSearch;
@ -35,6 +38,7 @@ import com.fsck.k9.search.LocalSearch;
*/
class K9NotificationActionCreator implements NotificationActionCreator {
private final Context context;
private final AccountSearchConditions accountSearchConditions = DI.get(AccountSearchConditions.class);
public K9NotificationActionCreator(Context context) {
@ -58,7 +62,7 @@ class K9NotificationActionCreator implements NotificationActionCreator {
int notificationId) {
TaskStackBuilder stack;
if (account.goToUnreadMessageSearch()) {
if (account.isGoToUnreadMessageSearch()) {
stack = buildUnreadBackStack(account);
} else {
String folderServerId = getFolderServerIdOfAllMessages(messageReferences);
@ -227,7 +231,8 @@ class K9NotificationActionCreator implements NotificationActionCreator {
private TaskStackBuilder buildUnreadBackStack(final Account account) {
TaskStackBuilder stack = buildAccountsBackStack();
LocalSearch search = Accounts.createUnreadSearch(context, account);
String searchTitle = context.getString(R.string.search_title, account.getDescription(), context.getString(R.string.unread_modifier));
LocalSearch search = accountSearchConditions.createUnreadSearch(account, searchTitle);
Intent intent = MessageList.intentDisplaySearch(context, search, true, false, false);
stack.addNextIntent(intent);

View file

@ -8,13 +8,15 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.UUID;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import com.fsck.k9.Account;
import com.fsck.k9.AccountPreferenceSerializer;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.mail.BodyPart;
import com.fsck.k9.mail.FetchProfile;
import com.fsck.k9.mail.Multipart;
@ -26,6 +28,7 @@ import com.fsck.k9.mailstore.FileBackedBody;
import com.fsck.k9.mailstore.LocalBodyPart;
import com.fsck.k9.mailstore.LocalMessage;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.mailstore.StorageManager;
import org.apache.commons.io.IOUtils;
import org.apache.james.mime4j.util.MimeUtil;
@ -159,7 +162,7 @@ public class MigrationTest extends K9RobolectricTest {
insertSimplePlaintextMessage(db);
db.close();
LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalMessage msg = localStore.getFolder("dev").getMessage("3");
FetchProfile fp = new FetchProfile();
@ -226,7 +229,7 @@ public class MigrationTest extends K9RobolectricTest {
insertMixedWithAttachments(db);
db.close();
LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalMessage msg = localStore.getFolder("dev").getMessage("4");
FetchProfile fp = new FetchProfile();
@ -298,7 +301,7 @@ public class MigrationTest extends K9RobolectricTest {
insertPgpMimeSignedMessage(db);
db.close();
LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalMessage msg = localStore.getFolder("dev").getMessage("5");
FetchProfile fp = new FetchProfile();
@ -357,7 +360,7 @@ public class MigrationTest extends K9RobolectricTest {
insertPgpMimeEncryptedMessage(db);
db.close();
LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalMessage msg = localStore.getFolder("dev").getMessage("6");
FetchProfile fp = new FetchProfile();
@ -475,7 +478,7 @@ public class MigrationTest extends K9RobolectricTest {
insertPgpInlineEncryptedMessage(db);
db.close();
LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalMessage msg = localStore.getFolder("dev").getMessage("7");
FetchProfile fp = new FetchProfile();
@ -562,7 +565,7 @@ public class MigrationTest extends K9RobolectricTest {
insertPgpInlineClearsignedMessage(db);
db.close();
LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalMessage msg = localStore.getFolder("dev").getMessage("8");
FetchProfile fp = new FetchProfile();
@ -620,7 +623,7 @@ public class MigrationTest extends K9RobolectricTest {
insertMultipartAlternativeMessage(db);
db.close();
LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalMessage msg = localStore.getFolder("dev").getMessage("9");
FetchProfile fp = new FetchProfile();
@ -685,7 +688,7 @@ public class MigrationTest extends K9RobolectricTest {
insertHtmlWithRelatedMessage(db);
db.close();
LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalMessage msg = localStore.getFolder("dev").getMessage("10");
FetchProfile fp = new FetchProfile();
@ -721,14 +724,9 @@ public class MigrationTest extends K9RobolectricTest {
}
private Account getNewAccount() {
Preferences preferences = Preferences.getPreferences(RuntimeEnvironment.application);
//FIXME: This is a hack to get Preferences into a state where it's safe to call newAccount()
preferences.loadAccounts();
Account account = preferences.newAccount();
Account account = new Account(UUID.randomUUID().toString());
DI.get(AccountPreferenceSerializer.class).loadDefaults(account);
account.setStoreUri("imap+tls+://user:password@imap.example.org");
return account;
}
}

View file

@ -66,19 +66,18 @@ import com.fsck.k9.DI;
import com.fsck.k9.FontSizes;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.backend.BackendManager;
import com.fsck.k9.preferences.Protocols;
import com.fsck.k9.ui.R;
import com.fsck.k9.activity.compose.MessageActions;
import com.fsck.k9.activity.misc.ExtendedAsyncTask;
import com.fsck.k9.activity.misc.NonConfigurationInstance;
import com.fsck.k9.activity.setup.AccountSetupBasics;
import com.fsck.k9.activity.setup.WelcomeMessage;
import com.fsck.k9.backend.BackendManager;
import com.fsck.k9.controller.MessagingController;
import com.fsck.k9.ui.helper.SizeFormatter;
import com.fsck.k9.mail.AuthType;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.mailstore.StorageManager;
import com.fsck.k9.preferences.Protocols;
import com.fsck.k9.preferences.SettingsExporter;
import com.fsck.k9.preferences.SettingsImportExportException;
import com.fsck.k9.preferences.SettingsImporter;
@ -86,10 +85,13 @@ import com.fsck.k9.preferences.SettingsImporter.AccountDescription;
import com.fsck.k9.preferences.SettingsImporter.AccountDescriptionPair;
import com.fsck.k9.preferences.SettingsImporter.ImportContents;
import com.fsck.k9.preferences.SettingsImporter.ImportResults;
import com.fsck.k9.search.AccountSearchConditions;
import com.fsck.k9.search.LocalSearch;
import com.fsck.k9.search.SearchAccount;
import com.fsck.k9.search.SearchSpecification.Attribute;
import com.fsck.k9.search.SearchSpecification.SearchField;
import com.fsck.k9.ui.R;
import com.fsck.k9.ui.helper.SizeFormatter;
import com.fsck.k9.ui.settings.SettingsActivity;
import com.fsck.k9.ui.settings.account.AccountSettingsActivity;
import com.fsck.k9.view.ColorChip;
@ -115,6 +117,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
private static final int DIALOG_NO_FILE_MANAGER = 4;
private final ColorChipProvider colorChipProvider = DI.get(ColorChipProvider.class);
private final AccountSearchConditions accountSearchConditions = DI.get(AccountSearchConditions.class);
private MessagingController controller;
/*
@ -341,28 +344,6 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
context.startActivity(intent);
}
public static LocalSearch createUnreadSearch(Context context, BaseAccount account) {
String searchTitle = context.getString(R.string.search_title, account.getDescription(),
context.getString(R.string.unread_modifier));
LocalSearch search;
if (account instanceof SearchAccount) {
search = ((SearchAccount) account).getRelatedSearch().clone();
search.setName(searchTitle);
} else {
search = new LocalSearch(searchTitle);
search.addAccountUuid(account.getUuid());
Account realAccount = (Account) account;
realAccount.excludeSpecialFolders(search);
realAccount.limitToDisplayableFolders(search);
}
search.and(SearchField.READ, "1", Attribute.NOT_EQUALS);
return search;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@ -988,7 +969,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
mAccount.setEnabled(true);
// Save the account settings
mAccount.save(Preferences.getPreferences(mContext));
Preferences.getPreferences(mContext).saveAccount(mAccount);
// Start services if necessary
Core.setServicesEnabled(mContext);
@ -1048,7 +1029,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
if (selectedContextAccount instanceof Account) {
Account realAccount = (Account) selectedContextAccount;
try {
realAccount.getLocalStore().delete();
DI.get(LocalStoreProvider.class).getInstance(realAccount).delete();
} catch (Exception e) {
// Ignore, this may lead to localStores on sd-cards that
// are currently not inserted to be left
@ -1739,8 +1720,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
search.addAccountUuid(account.getUuid());
Account realAccount = (Account) account;
realAccount.excludeSpecialFolders(search);
realAccount.limitToDisplayableFolders(search);
accountSearchConditions.excludeSpecialFolders(realAccount, search);
accountSearchConditions.limitToDisplayableFolders(realAccount, search);
}
search.and(SearchField.FLAGGED, "1", Attribute.EQUALS);
@ -1749,7 +1730,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
}
private OnClickListener createUnreadSearchListener(BaseAccount account) {
LocalSearch search = createUnreadSearch(Accounts.this, account);
String searchTitle = getString(R.string.search_title, account.getDescription(), getString(R.string.unread_modifier));
LocalSearch search = accountSearchConditions.createUnreadSearch(account, searchTitle);
return new AccountClickListener(search);
}
@ -2048,7 +2031,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
@Override
protected Void doInBackground(Void... args) {
mAccount.move(Preferences.getPreferences(mContext), mUp);
Preferences.getPreferences(mContext).move(mAccount, mUp);
return null;
}

View file

@ -113,7 +113,7 @@ public class EditIdentity extends K9Activity {
identities.add(mIdentityIndex, mIdentity);
}
mAccount.save(Preferences.getPreferences(getApplication().getApplicationContext()));
Preferences.getPreferences(getApplicationContext()).saveAccount(mAccount);
finish();
}

View file

@ -44,6 +44,7 @@ import com.fsck.k9.DI;
import com.fsck.k9.FontSizes;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.ui.R;
import com.fsck.k9.activity.compose.MessageActions;
import com.fsck.k9.activity.setup.FolderSettings;
@ -420,7 +421,7 @@ public class FolderList extends K9ListActivity {
private void setDisplayMode(FolderMode newMode) {
account.setFolderDisplayMode(newMode);
account.save(Preferences.getPreferences(this));
Preferences.getPreferences(getApplicationContext()).saveAccount(account);
if (account.getFolderPushMode() != FolderMode.NONE) {
MailService.actionRestartPushers(this, null);
}
@ -742,7 +743,7 @@ public class FolderList extends K9ListActivity {
Timber.i("not refreshing folder of unavailable account");
return;
}
localFolder = account.getLocalStore().getFolder(folderServerId);
localFolder = DI.get(LocalStoreProvider.class).getInstance(account).getFolder(folderServerId);
FolderInfoHolder folderHolder = getFolder(folderServerId);
if (folderHolder != null) {
folderHolder.populate(context, localFolder, FolderList.this.account, -1);

View file

@ -129,7 +129,7 @@ public class ManageIdentities extends ChooseIdentity {
private void saveIdentities() {
if (mIdentitiesChanged) {
mAccount.setIdentities(identities);
mAccount.save(Preferences.getPreferences(getApplication().getApplicationContext()));
Preferences.getPreferences(getApplicationContext()).saveAccount(mAccount);
}
finish();
}

View file

@ -393,7 +393,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
signatureView.setVisibility(View.GONE);
}
requestReadReceipt = account.isMessageReadReceiptAlways();
requestReadReceipt = account.isMessageReadReceipt();
updateFrom();

View file

@ -300,7 +300,7 @@ public class MessageLoaderHelper {
retainCryptoHelperFragment.setData(messageCryptoHelper);
}
messageCryptoHelper.asyncStartOrResumeProcessingMessage(
localMessage, messageCryptoCallback, cachedDecryptionResult, !account.getOpenPgpHideSignOnly());
localMessage, messageCryptoCallback, cachedDecryptionResult, !account.isOpenPgpHideSignOnly());
}
private void cancelAndClearCryptoOperation() {

View file

@ -51,9 +51,9 @@ import com.fsck.k9.service.DatabaseUpgradeService;
* Currently we make no attempts to stop the background code (e.g. {@link MessagingController}) from
* opening the accounts' databases. If this happens the upgrade is performed in one of the
* background threads and not by {@link DatabaseUpgradeService}. But this is not a problem. Due to
* the locking in {@link LocalStore#getInstance(Account, Context)} the upgrade
* service will block in the {@link Account#getLocalStore()} call and from the outside (especially
* for this activity) it will appear as if {@link DatabaseUpgradeService} is performing the upgrade.
* the locking in {@link com.fsck.k9.mailstore.LocalStoreProvider#getInstance(Account)} the upgrade service will block
* and from the outside (especially for this activity) it will appear as if
* {@link DatabaseUpgradeService} is performing the upgrade.
* </p>
*/
public class UpgradeDatabases extends K9Activity {

View file

@ -35,7 +35,6 @@ import com.fsck.k9.mail.Address;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.Message.RecipientType;
import com.fsck.k9.mail.Part;
import com.fsck.k9.message.AutocryptStatusInteractor;
import com.fsck.k9.message.AutocryptStatusInteractor.RecipientAutocryptStatus;
import com.fsck.k9.message.ComposePgpEnableByDefaultDecider;
@ -307,7 +306,7 @@ public class RecipientPresenter {
menu.findItem(R.id.openpgp_encrypt_enable).setVisible(!isEncrypting);
menu.findItem(R.id.openpgp_encrypt_disable).setVisible(isEncrypting);
boolean showSignOnly = !account.getOpenPgpHideSignOnly();
boolean showSignOnly = !account.isOpenPgpHideSignOnly();
boolean isSignOnly = currentCryptoStatus.isSignOnly();
menu.findItem(R.id.openpgp_sign_only).setVisible(showSignOnly && !isSignOnly);
menu.findItem(R.id.openpgp_sign_only_disable).setVisible(showSignOnly && isSignOnly);
@ -429,8 +428,8 @@ public class RecipientPresenter {
cryptoEnablePgpInline,
account.getAutocryptPreferEncryptMutual(),
isReplyToEncryptedMessage,
account.getOpenPgpEncryptAllDrafts(),
account.getOpenPgpEncryptSubject(),
account.isOpenPgpEncryptAllDrafts(),
account.isOpenPgpEncryptSubject(),
currentCryptoMode);
if (openPgpProviderState != OpenPgpProviderState.OK) {

View file

@ -376,7 +376,7 @@ public class AccountSetupBasics extends K9Activity
} else {
//We've successfully checked outgoing as well.
mAccount.setDescription(mAccount.getEmail());
mAccount.save(Preferences.getPreferences(this));
Preferences.getPreferences(this).saveAccount(mAccount);
Core.setServicesEnabled(this);
AccountSetupNames.actionSetNames(this, mAccount);
finish();

View file

@ -29,6 +29,7 @@ import android.widget.TextView;
import com.fsck.k9.Account;
import com.fsck.k9.Account.SpecialFolderSelection;
import com.fsck.k9.DI;
import com.fsck.k9.LocalKeyStoreManager;
import com.fsck.k9.Preferences;
import com.fsck.k9.activity.K9Activity;
import com.fsck.k9.controller.MessagingController;
@ -42,6 +43,7 @@ import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.filter.Hex;
import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.ui.R;
import timber.log.Timber;
@ -301,7 +303,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
*/
private void acceptCertificate(X509Certificate certificate) {
try {
mAccount.addCertificate(mDirection.toMailServerDirection(), certificate);
DI.get(LocalKeyStoreManager.class).addCertificate(mAccount, mDirection.toMailServerDirection(), certificate);
} catch (CertificateException e) {
showErrorDialog(
R.string.account_setup_failed_dlg_certificate_message_fmt,
@ -517,7 +519,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
return;
}
LocalStore localStore = account.getLocalStore();
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
createLocalFolder(localStore, Account.OUTBOX, getString(R.string.special_mailbox_name_outbox));
if (!account.getStoreUri().startsWith("pop3")) {

View file

@ -117,7 +117,7 @@ public class AccountSetupComposition extends K9Activity {
mAccount.setSignatureBeforeQuotedText(isSignatureBeforeQuotedText);
}
mAccount.save(Preferences.getPreferences(this));
Preferences.getPreferences(getApplicationContext()).saveAccount(mAccount);
}
@Override
@ -134,7 +134,7 @@ public class AccountSetupComposition extends K9Activity {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mAccount.save(Preferences.getPreferences(this));
Preferences.getPreferences(getApplicationContext()).saveAccount(mAccount);
finish();
}
}

View file

@ -30,6 +30,7 @@ import android.widget.Toast;
import com.fsck.k9.Account;
import com.fsck.k9.Account.FolderMode;
import com.fsck.k9.DI;
import com.fsck.k9.LocalKeyStoreManager;
import com.fsck.k9.Preferences;
import com.fsck.k9.backend.BackendManager;
import com.fsck.k9.preferences.Protocols;
@ -304,7 +305,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
}
mCurrentPortViewSetting = mPortView.getText().toString();
mSubscribedFoldersOnly.setChecked(mAccount.subscribedFoldersOnly());
mSubscribedFoldersOnly.setChecked(mAccount.isSubscribedFoldersOnly());
} catch (Exception e) {
failure(e);
}
@ -515,7 +516,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
if (isPushCapable && mAccount.getFolderPushMode() != FolderMode.NONE) {
MailService.actionRestartPushers(this, null);
}
mAccount.save(Preferences.getPreferences(this));
Preferences.getPreferences(getApplicationContext()).saveAccount(mAccount);
finish();
} else {
/*
@ -588,7 +589,7 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
mWebdavMailboxPathView.getText().toString());
}
mAccount.deleteCertificate(host, port, MailServerDirection.INCOMING);
DI.get(LocalKeyStoreManager.class).deleteCertificate(mAccount, host, port, MailServerDirection.INCOMING);
ServerSettings settings = new ServerSettings(mStoreType, host, port,
connectionSecurity, authType, username, password, clientCertificateAlias, extra);

View file

@ -89,7 +89,7 @@ public class AccountSetupNames extends K9Activity implements OnClickListener {
mAccount.setDescription(mDescription.getText().toString());
}
mAccount.setName(mName.getText().toString());
mAccount.save(Preferences.getPreferences(this));
Preferences.getPreferences(getApplicationContext()).saveAccount(mAccount);
Accounts.listAccounts(this);
finish();
}

View file

@ -111,7 +111,7 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
mAccount = Preferences.getPreferences(this).getAccount(accountUuid);
mNotifyView.setChecked(mAccount.isNotifyNewMail());
mNotifySyncView.setChecked(mAccount.isShowOngoing());
mNotifySyncView.setChecked(mAccount.isNotifySync());
SpinnerOption.setSpinnerOptionValue(mCheckFrequencyView, mAccount
.getAutomaticCheckIntervalMinutes());
SpinnerOption.setSpinnerOptionValue(mDisplayCountView, mAccount
@ -131,7 +131,7 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
private void onDone() {
mAccount.setDescription(mAccount.getEmail());
mAccount.setNotifyNewMail(mNotifyView.isChecked());
mAccount.setShowOngoing(mNotifySyncView.isChecked());
mAccount.setNotifySync(mNotifySyncView.isChecked());
mAccount.setAutomaticCheckIntervalMinutes((Integer)((SpinnerOption)mCheckFrequencyView
.getSelectedItem()).value);
mAccount.setDisplayCount((Integer)((SpinnerOption)mDisplayCountView
@ -143,7 +143,7 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
mAccount.setFolderPushMode(Account.FolderMode.NONE);
}
mAccount.save(Preferences.getPreferences(this));
Preferences.getPreferences(getApplicationContext()).saveAccount(mAccount);
if (mAccount.equals(Preferences.getPreferences(this).getDefaultAccount()) ||
getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false)) {
Preferences.getPreferences(this).setDefaultAccount(mAccount);

View file

@ -27,6 +27,7 @@ import android.widget.Toast;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.LocalKeyStoreManager;
import com.fsck.k9.Preferences;
import com.fsck.k9.backend.BackendManager;
import com.fsck.k9.preferences.Protocols;
@ -459,7 +460,7 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (Intent.ACTION_EDIT.equals(getIntent().getAction())) {
mAccount.save(Preferences.getPreferences(this));
Preferences.getPreferences(getApplicationContext()).saveAccount(mAccount);
finish();
} else {
AccountSetupOptions.actionOptions(this, mAccount, mMakeDefault);
@ -490,7 +491,7 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
int newPort = Integer.parseInt(mPortView.getText().toString());
ServerSettings server = new ServerSettings(Protocols.SMTP, newHost, newPort, securityType, authType, username, password, clientCertificateAlias);
uri = backendManager.createTransportUri(server);
mAccount.deleteCertificate(newHost, newPort, MailServerDirection.OUTGOING);
DI.get(LocalKeyStoreManager.class).deleteCertificate(mAccount, newHost, newPort, MailServerDirection.OUTGOING);
mAccount.setTransportUri(uri);
AccountSetupCheckSettings.actionCheckSettings(this, mAccount, CheckDirection.OUTGOING);
}

View file

@ -12,6 +12,7 @@ import android.preference.Preference;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.Preferences;
import com.fsck.k9.mailstore.LocalStoreProvider;
import com.fsck.k9.ui.R;
import com.fsck.k9.activity.FolderInfoHolder;
import com.fsck.k9.activity.K9PreferenceActivity;
@ -64,7 +65,7 @@ public class FolderSettings extends K9PreferenceActivity {
Account mAccount = Preferences.getPreferences(this).getAccount(accountUuid);
try {
LocalStore localStore = mAccount.getLocalStore();
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(mAccount);
mFolder = localStore.getFolder(folderServerId);
mFolder.open(Folder.OPEN_MODE_RW);
} catch (MessagingException me) {

View file

@ -838,7 +838,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
account.setSortAscending(this.sortType, this.sortAscending);
sortDateAscending = account.isSortAscending(SortType.SORT_DATE);
account.save(preferences);
Preferences.getPreferences(getContext()).saveAccount(account);
} else {
K9.setSortType(this.sortType);
@ -2442,7 +2442,7 @@ public class MessageListFragment extends Fragment implements OnItemClickListener
boolean allowRemoteSearch = false;
final Account searchAccount = account;
if (searchAccount != null) {
allowRemoteSearch = searchAccount.allowRemoteSearch();
allowRemoteSearch = searchAccount.isAllowRemoteSearch();
}
return allowRemoteSearch;

View file

@ -7,6 +7,7 @@ import android.database.Cursor;
import android.text.TextUtils;
import com.fsck.k9.Account;
import com.fsck.k9.DI;
import com.fsck.k9.Preferences;
import com.fsck.k9.controller.MessageReference;
import com.fsck.k9.helper.Utility;
@ -15,6 +16,7 @@ import com.fsck.k9.mail.Folder;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mailstore.LocalFolder;
import com.fsck.k9.mailstore.LocalStore;
import com.fsck.k9.mailstore.LocalStoreProvider;
import static com.fsck.k9.fragment.MLFProjectionInfo.SENDER_LIST_COLUMN;
@ -22,7 +24,7 @@ import static com.fsck.k9.fragment.MLFProjectionInfo.SENDER_LIST_COLUMN;
public class MlfUtils {
static LocalFolder getOpenFolder(String folderServerId, Account account) throws MessagingException {
LocalStore localStore = account.getLocalStore();
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalFolder localFolder = localStore.getFolder(folderServerId);
localFolder.open(Folder.OPEN_MODE_RO);
return localFolder;

View file

@ -118,7 +118,7 @@ public class MessageTopView extends LinearLayout {
containerView, false);
containerView.addView(view);
boolean hideUnsignedTextDivider = account.getOpenPgpHideSignOnly();
boolean hideUnsignedTextDivider = account.isOpenPgpHideSignOnly();
view.displayMessageViewContainer(messageViewInfo, new OnRenderingFinishedListener() {
@Override
public void onLoadFinished() {

View file

@ -19,10 +19,10 @@ class AccountSettingsDataStore(
return when (key) {
"account_default" -> account == preferences.defaultAccount
"mark_message_as_read_on_view" -> account.isMarkMessageAsReadOnView
"account_sync_remote_deletetions" -> account.syncRemoteDeletions()
"account_sync_remote_deletetions" -> account.isSyncRemoteDeletions
"push_poll_on_connect" -> account.isPushPollOnConnect
"always_show_cc_bcc" -> account.isAlwaysShowCcBcc
"message_read_receipt" -> account.isMessageReadReceiptAlways
"message_read_receipt" -> account.isMessageReadReceipt
"default_quoted_text_shown" -> account.isDefaultQuotedTextShown
"reply_after_quote" -> account.isReplyAfterQuote
"strip_signature" -> account.isStripSignature
@ -31,12 +31,12 @@ class AccountSettingsDataStore(
"account_notify_contacts_mail_only" -> account.isNotifyContactsMailOnly
"account_vibrate" -> account.notificationSetting.isVibrateEnabled
"account_led" -> account.notificationSetting.isLedEnabled
"account_notify_sync" -> account.isShowOngoing
"notification_opens_unread" -> account.goToUnreadMessageSearch()
"remote_search_enabled" -> account.allowRemoteSearch()
"openpgp_hide_sign_only" -> account.openPgpHideSignOnly
"openpgp_encrypt_subject" -> account.openPgpEncryptSubject
"openpgp_encrypt_all_drafts" -> account.openPgpEncryptAllDrafts
"account_notify_sync" -> account.isNotifySync
"notification_opens_unread" -> account.isGoToUnreadMessageSearch
"openpgp_hide_sign_only" -> account.isOpenPgpHideSignOnly
"openpgp_encrypt_subject" -> account.isOpenPgpEncryptSubject
"openpgp_encrypt_all_drafts" -> account.isOpenPgpEncryptAllDrafts
"remote_search_enabled" -> account.isAllowRemoteSearch
"autocrypt_prefer_encrypt" -> account.autocryptPreferEncryptMutual
"upload_sent_messages" -> account.isUploadSentMessages
else -> defValue
@ -52,24 +52,24 @@ class AccountSettingsDataStore(
return
}
"mark_message_as_read_on_view" -> account.isMarkMessageAsReadOnView = value
"account_sync_remote_deletetions" -> account.setSyncRemoteDeletions(value)
"account_sync_remote_deletetions" -> account.isSyncRemoteDeletions = value
"push_poll_on_connect" -> account.isPushPollOnConnect = value
"always_show_cc_bcc" -> account.isAlwaysShowCcBcc = value
"message_read_receipt" -> account.setMessageReadReceipt(value)
"message_read_receipt" -> account.isMessageReadReceipt = value
"default_quoted_text_shown" -> account.isDefaultQuotedTextShown = value
"reply_after_quote" -> account.isReplyAfterQuote = value
"strip_signature" -> account.isStripSignature = value
"account_notify" -> account.isNotifyNewMail = value
"account_notify_self" -> account.isNotifySelfNewMail = value
"account_notify_contacts_mail_only" -> account.isNotifyContactsMailOnly = value
"account_vibrate" -> account.notificationSetting.setVibrate(value)
"account_vibrate" -> account.notificationSetting.isVibrateEnabled = value
"account_led" -> account.notificationSetting.setLed(value)
"account_notify_sync" -> account.isShowOngoing = value
"notification_opens_unread" -> account.setGoToUnreadMessageSearch(value)
"remote_search_enabled" -> account.setAllowRemoteSearch(value)
"openpgp_hide_sign_only" -> account.openPgpHideSignOnly = value
"openpgp_encrypt_subject" -> account.openPgpEncryptSubject = value
"openpgp_encrypt_all_drafts" -> account.openPgpEncryptAllDrafts = value
"account_notify_sync" -> account.isNotifySync = value
"notification_opens_unread" -> account.isGoToUnreadMessageSearch = value
"remote_search_enabled" -> account.isAllowRemoteSearch = value
"openpgp_hide_sign_only" -> account.isOpenPgpHideSignOnly = value
"openpgp_encrypt_subject" -> account.isOpenPgpEncryptSubject = value
"openpgp_encrypt_all_drafts" -> account.isOpenPgpEncryptAllDrafts = value
"autocrypt_prefer_encrypt" -> account.autocryptPreferEncryptMutual = value
"upload_sent_messages" -> account.isUploadSentMessages = value
else -> return
@ -194,13 +194,7 @@ class AccountSettingsDataStore(
"account_vibrate_pattern" -> account.notificationSetting.vibratePattern = value.toInt()
"account_vibrate_times" -> account.notificationSetting.vibrateTimes = value.toInt()
"account_remote_search_num_results" -> account.remoteSearchNumResults = value.toInt()
"local_storage_provider" -> {
executorService.execute {
account.localStorageProviderId = value
saveSettings()
}
return
}
"local_storage_provider" -> account.localStorageProviderId = value
"account_ringtone" -> with(account.notificationSetting) {
isRingEnabled = true
ringtone = value
@ -218,7 +212,7 @@ class AccountSettingsDataStore(
}
private fun saveSettings() {
account.save(preferences)
preferences.saveAccount(account)
}
private fun reschedulePoll() {

View file

@ -332,7 +332,7 @@ public class OpenPgpAppSelectDialog extends FragmentActivity {
private void persistOpenPgpProviderSetting(String selectedPackage) {
account.setOpenPgpProvider(selectedPackage);
account.save(Preferences.getPreferences(this));
Preferences.getPreferences(getApplicationContext()).saveAccount(account);
}
public void onDismissApgDialog() {

View file

@ -4,7 +4,7 @@ package com.fsck.k9.mail.store;
import com.fsck.k9.mail.NetworkType;
public interface StoreConfig {
boolean subscribedFoldersOnly();
boolean isSubscribedFoldersOnly();
boolean useCompression(NetworkType type);
String getInboxFolder();
@ -13,7 +13,7 @@ public interface StoreConfig {
int getMaximumAutoDownloadMessageSize();
boolean allowRemoteSearch();
boolean isAllowRemoteSearch();
boolean isRemoteSearchFullText();
boolean isPushPollOnConnect();

View file

@ -1399,7 +1399,7 @@ public class ImapFolder extends Folder<ImapMessage> {
public List<ImapMessage> search(final String queryString, final Set<Flag> requiredFlags,
final Set<Flag> forbiddenFlags) throws MessagingException {
if (!store.getStoreConfig().allowRemoteSearch()) {
if (!store.getStoreConfig().isAllowRemoteSearch()) {
throw new MessagingException("Your settings do not allow remote searching of this account");
}

View file

@ -126,7 +126,7 @@ public class ImapStore extends RemoteStore {
try {
List<FolderListItem> folders = listFolders(connection, false);
if (!mStoreConfig.subscribedFoldersOnly()) {
if (!mStoreConfig.isSubscribedFoldersOnly()) {
return getFolders(folders);
}

View file

@ -1067,7 +1067,7 @@ public class ImapFolderTest {
public void search_withFullTextSearchEnabled_shouldIssueRespectiveCommand() throws Exception {
ImapFolder folder = createFolder("Folder");
prepareImapFolderForOpen(OPEN_MODE_RO);
when(storeConfig.allowRemoteSearch()).thenReturn(true);
when(storeConfig.isAllowRemoteSearch()).thenReturn(true);
when(storeConfig.isRemoteSearchFullText()).thenReturn(true);
setupUidSearchResponses("1 OK SEARCH completed");
@ -1080,7 +1080,7 @@ public class ImapFolderTest {
public void search_withFullTextSearchDisabled_shouldIssueRespectiveCommand() throws Exception {
ImapFolder folder = createFolder("Folder");
prepareImapFolderForOpen(OPEN_MODE_RO);
when(storeConfig.allowRemoteSearch()).thenReturn(true);
when(storeConfig.isAllowRemoteSearch()).thenReturn(true);
when(storeConfig.isRemoteSearchFullText()).thenReturn(false);
setupUidSearchResponses("1 OK SEARCH completed");
@ -1092,7 +1092,7 @@ public class ImapFolderTest {
@Test
public void search_withRemoteSearchDisabled_shouldThrow() throws Exception {
ImapFolder folder = createFolder("Folder");
when(storeConfig.allowRemoteSearch()).thenReturn(false);
when(storeConfig.isAllowRemoteSearch()).thenReturn(false);
try {
folder.search("query", Collections.<Flag>emptySet(), Collections.<Flag>emptySet());

View file

@ -142,7 +142,7 @@ public class ImapStoreTest {
@Test
public void getPersonalNamespaces_withoutSubscribedFoldersOnly() throws Exception {
when(storeConfig.subscribedFoldersOnly()).thenReturn(false);
when(storeConfig.isSubscribedFoldersOnly()).thenReturn(false);
ImapConnection imapConnection = mock(ImapConnection.class);
List<ImapResponse> imapResponses = Arrays.asList(
createImapResponse("* LIST (\\HasNoChildren) \".\" \"INBOX\""),
@ -162,7 +162,7 @@ public class ImapStoreTest {
@Test
public void getPersonalNamespaces_withSubscribedFoldersOnly_shouldOnlyReturnExistingSubscribedFolders()
throws Exception {
when(storeConfig.subscribedFoldersOnly()).thenReturn(true);
when(storeConfig.isSubscribedFoldersOnly()).thenReturn(true);
ImapConnection imapConnection = mock(ImapConnection.class);
List<ImapResponse> lsubResponses = Arrays.asList(
createImapResponse("* LSUB (\\HasNoChildren) \".\" \"INBOX\""),