0
0
mirror of https://github.com/thunderbird/thunderbird-android.git synced 2024-09-19 19:52:14 +02:00

[DO NOT MERGE] Messy patch to remove folder classes

This is just an exploration to get a feeling for how much work it is to get rid of folder classes.
This commit is contained in:
cketti 2023-10-19 23:37:28 +02:00
parent ab7d680111
commit 560f6b2fae
43 changed files with 431 additions and 733 deletions

View File

@ -81,10 +81,6 @@ class Account(override val uuid: String) : BaseAccount {
@set:Synchronized
var isNotifyNewMail = false
@get:Synchronized
@set:Synchronized
var folderNotifyNewMailMode = FolderMode.ALL
@get:Synchronized
@set:Synchronized
var isNotifySelfNewMail = false
@ -179,19 +175,7 @@ class Account(override val uuid: String) : BaseAccount {
@get:Synchronized
@set:Synchronized
var folderDisplayMode = FolderMode.NOT_SECOND_CLASS
@get:Synchronized
@set:Synchronized
var folderSyncMode = FolderMode.FIRST_CLASS
@get:Synchronized
@set:Synchronized
var folderPushMode = FolderMode.NONE
@get:Synchronized
@set:Synchronized
var folderTargetMode = FolderMode.NOT_SECOND_CLASS
var isPushEnabled = false
@get:Synchronized
@set:Synchronized
@ -495,15 +479,6 @@ class Account(override val uuid: String) : BaseAccount {
return spamFolderId != null
}
@Synchronized
fun updateFolderSyncMode(syncMode: FolderMode): Boolean {
val oldSyncMode = folderSyncMode
folderSyncMode = syncMode
return (oldSyncMode == FolderMode.NONE && syncMode != FolderMode.NONE) ||
(oldSyncMode != FolderMode.NONE && syncMode == FolderMode.NONE)
}
@Synchronized
fun isSortAscending(sortType: SortType): Boolean {
return sortAscending.getOrPut(sortType) { sortType.isDefaultAscending }
@ -612,14 +587,6 @@ class Account(override val uuid: String) : BaseAccount {
return uuid.hashCode()
}
enum class FolderMode {
NONE,
ALL,
FIRST_CLASS,
FIRST_AND_SECOND_CLASS,
NOT_SECOND_CLASS,
}
enum class SpecialFolderSelection {
AUTOMATIC,
MANUAL,

View File

@ -7,7 +7,6 @@ import com.fsck.k9.Account.Companion.NO_OPENPGP_KEY
import com.fsck.k9.Account.Companion.UNASSIGNED_ACCOUNT_NUMBER
import com.fsck.k9.Account.DeletePolicy
import com.fsck.k9.Account.Expunge
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.Account.MessageFormat
import com.fsck.k9.Account.QuoteStyle
import com.fsck.k9.Account.Searchable
@ -55,11 +54,6 @@ class AccountPreferenceSerializer(
}
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)
isIgnoreChatMessages = storage.getBoolean("$accountUuid.ignoreChatMessages", false)
@ -167,16 +161,7 @@ class AccountPreferenceSerializer(
)
}
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.NONE)
folderTargetMode =
getEnumStringPref<FolderMode>(storage, "$accountUuid.folderTargetMode", FolderMode.NOT_SECOND_CLASS)
isPushEnabled = storage.getBoolean("$accountUuid.isPushEnabled", false)
searchableFolders = getEnumStringPref<Searchable>(storage, "$accountUuid.searchableFolders", Searchable.ALL)
@ -282,7 +267,6 @@ class AccountPreferenceSerializer(
editor.putInt("$accountUuid.idleRefreshMinutes", idleRefreshMinutes)
editor.putInt("$accountUuid.displayCount", displayCount)
editor.putBoolean("$accountUuid.notifyNewMail", isNotifyNewMail)
editor.putString("$accountUuid.folderNotifyNewMailMode", folderNotifyNewMailMode.name)
editor.putBoolean("$accountUuid.notifySelfNewMail", isNotifySelfNewMail)
editor.putBoolean("$accountUuid.notifyContactsMailOnly", isNotifyContactsMailOnly)
editor.putBoolean("$accountUuid.ignoreChatMessages", isIgnoreChatMessages)
@ -313,10 +297,7 @@ class AccountPreferenceSerializer(
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.isPushEnabled", isPushEnabled)
editor.putBoolean("$accountUuid.signatureBeforeQuotedText", isSignatureBeforeQuotedText)
editor.putString("$accountUuid.expungePolicy", expungePolicy.name)
editor.putBoolean("$accountUuid.syncRemoteDeletions", isSyncRemoteDeletions)
@ -577,16 +558,12 @@ class AccountPreferenceSerializer(
displayCount = K9.DEFAULT_VISIBLE_LIMIT
accountNumber = UNASSIGNED_ACCOUNT_NUMBER
isNotifyNewMail = true
folderNotifyNewMailMode = FolderMode.ALL
isNotifySync = false
isNotifySelfNewMail = true
isNotifyContactsMailOnly = false
isIgnoreChatMessages = false
messagesNotificationChannelVersion = 0
folderDisplayMode = FolderMode.NOT_SECOND_CLASS
folderSyncMode = FolderMode.FIRST_CLASS
folderPushMode = FolderMode.NONE
folderTargetMode = FolderMode.NOT_SECOND_CLASS
isPushEnabled = false
sortType = DEFAULT_SORT_TYPE
setSortAscending(DEFAULT_SORT_TYPE, DEFAULT_SORT_ASCENDING)
showPictures = ShowPictures.NEVER

View File

@ -26,7 +26,7 @@ internal class DefaultMessageCountsProvider(
override fun getMessageCounts(account: Account): MessageCounts {
val search = LocalSearch().apply {
excludeSpecialFolders(account)
limitToDisplayableFolders(account)
limitToDisplayableFolders()
}
return getMessageCounts(account, search.conditions)

View File

@ -56,7 +56,6 @@ import com.fsck.k9.mail.AuthenticationFailedException;
import com.fsck.k9.mail.CertificateValidationException;
import com.fsck.k9.mail.FetchProfile;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.FolderClass;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessageDownloadState;
import com.fsck.k9.mail.MessagingException;
@ -2283,26 +2282,16 @@ public class MessagingController {
refreshFolderListIfStale(account);
try {
Account.FolderMode aDisplayMode = account.getFolderDisplayMode();
Account.FolderMode aSyncMode = account.getFolderSyncMode();
LocalStore localStore = localStoreProvider.getInstance(account);
for (final LocalFolder folder : localStore.getPersonalNamespaces(false)) {
folder.open();
FolderClass fDisplayClass = folder.getDisplayClass();
FolderClass fSyncClass = folder.getSyncClass();
boolean isFolderHidden = folder.getHidden();
boolean isAutoSyncViaPollEnabled = folder.getAutoSyncViaPollEnabled();
if (LocalFolder.isModeMismatch(aDisplayMode, fDisplayClass)) {
// Never sync a folder that isn't displayed
continue;
if (!isFolderHidden && isAutoSyncViaPollEnabled) {
synchronizeFolder(account, folder, ignoreLastCheckedTime, notify, listener, notificationState);
}
if (LocalFolder.isModeMismatch(aSyncMode, fSyncClass)) {
// Do not sync folders in the wrong class
continue;
}
synchronizeFolder(account, folder, ignoreLastCheckedTime, notify, listener, notificationState);
}
} catch (MessagingException e) {
Timber.e(e, "Unable to synchronize account %s", account);

View File

@ -1,7 +1,6 @@
package com.fsck.k9.controller.push
import com.fsck.k9.Account
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.Preferences
import com.fsck.k9.backend.BackendManager
import com.fsck.k9.backend.api.BackendPusher
@ -96,7 +95,7 @@ internal class AccountPushController(
}
private fun disablePush() {
account.folderPushMode = FolderMode.NONE
account.isPushEnabled = false
preferences.saveAccount(account)
}
}

View File

@ -1,7 +1,6 @@
package com.fsck.k9.controller.push
import com.fsck.k9.Account
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.Preferences
import com.fsck.k9.backend.BackendManager
import com.fsck.k9.network.ConnectivityChangeListener
@ -75,7 +74,7 @@ class PushController internal constructor(
coroutineScope.launch(coroutineDispatcher) {
for (account in preferences.accounts) {
account.folderPushMode = FolderMode.NONE
account.isPushEnabled = false
preferences.saveAccount(account)
}
}
@ -211,7 +210,7 @@ class PushController internal constructor(
private fun getPushAccounts(): List<Account> {
return preferences.accounts.filter { account ->
account.folderPushMode != FolderMode.NONE && backendManager.getBackend(account).isPushCapable
account.isPushEnabled && backendManager.getBackend(account).isPushCapable
}
}

View File

@ -1,6 +1,5 @@
package com.fsck.k9.mailstore
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.mail.FolderType
fun interface FolderMapper<T> {
@ -15,10 +14,10 @@ interface FolderDetailsAccessor {
val isLocalOnly: Boolean
val isInTopGroup: Boolean
val isIntegrate: Boolean
val syncClass: FolderClass
val displayClass: FolderClass
val notifyClass: FolderClass
val pushClass: FolderClass
val isAutoSyncViaPollEnabled: Boolean
val isHidden: Boolean
val isNotificationEnabled: Boolean
val isAutoSyncViaPushEnabled: Boolean
val visibleLimit: Int
val moreMessages: MoreMessages
val lastChecked: Long?

View File

@ -1,11 +1,9 @@
package com.fsck.k9.mailstore
import com.fsck.k9.Account
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.DI
import com.fsck.k9.controller.MessagingController
import com.fsck.k9.controller.SimpleMessagingListener
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.preferences.AccountManager
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
@ -18,6 +16,7 @@ import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import com.fsck.k9.mail.FolderType as RemoteFolderType
@ -35,12 +34,9 @@ class FolderRepository(
.thenByDescending { it.isInTopGroup }
.thenBy(String.CASE_INSENSITIVE_ORDER) { it.folder.name }
fun getDisplayFolders(account: Account, displayMode: FolderMode?): List<DisplayFolder> {
fun getDisplayFolders(account: Account, showHiddenFolders: Boolean): List<DisplayFolder> {
val messageStore = messageStoreManager.getMessageStore(account)
return messageStore.getDisplayFolders(
displayMode = displayMode ?: account.folderDisplayMode,
outboxFolderId = account.outboxFolderId,
) { folder ->
return messageStore.getDisplayFolders(showHiddenFolders, outboxFolderId = account.outboxFolderId) { folder ->
DisplayFolder(
folder = Folder(
id = folder.id,
@ -55,24 +51,24 @@ class FolderRepository(
}.sortedWith(sortForDisplay)
}
fun getDisplayFoldersFlow(account: Account, displayMode: FolderMode): Flow<List<DisplayFolder>> {
fun getDisplayFoldersFlow(account: Account, showHiddenFolders: Boolean = false): Flow<List<DisplayFolder>> {
val messagingController = DI.get<MessagingController>()
val messageStore = messageStoreManager.getMessageStore(account)
return callbackFlow {
send(getDisplayFolders(account, displayMode))
send(getDisplayFolders(account, showHiddenFolders))
val folderStatusChangedListener = object : SimpleMessagingListener() {
override fun folderStatusChanged(statusChangedAccount: Account, folderId: Long) {
if (statusChangedAccount.uuid == account.uuid) {
trySendBlocking(getDisplayFolders(account, displayMode))
trySendBlocking(getDisplayFolders(account, showHiddenFolders))
}
}
}
messagingController.addListener(folderStatusChangedListener)
val folderSettingsChangedListener = FolderSettingsChangedListener {
trySendBlocking(getDisplayFolders(account, displayMode))
trySendBlocking(getDisplayFolders(account, showHiddenFolders))
}
messageStore.addFolderSettingsChangedListener(folderSettingsChangedListener)
@ -85,17 +81,6 @@ class FolderRepository(
.flowOn(ioDispatcher)
}
fun getDisplayFoldersFlow(account: Account): Flow<List<DisplayFolder>> {
return accountManager.getAccountFlow(account.uuid)
.map { latestAccount ->
AccountContainer(latestAccount, latestAccount.folderDisplayMode)
}
.distinctUntilChanged()
.flatMapLatest { (account, folderDisplayMode) ->
getDisplayFoldersFlow(account, folderDisplayMode)
}
}
fun getFolder(account: Account, folderId: Long): Folder? {
val messageStore = messageStoreManager.getMessageStore(account)
return messageStore.getFolder(folderId) { folder ->
@ -118,12 +103,12 @@ class FolderRepository(
type = folderTypeOf(account, folder.id),
isLocalOnly = folder.isLocalOnly,
),
isInTopGroup = folder.isInTopGroup,
isIntegrate = folder.isIntegrate,
syncClass = folder.syncClass,
displayClass = folder.displayClass,
notifyClass = folder.notifyClass,
pushClass = folder.pushClass,
isHidden = folder.isHidden,
isInTopGroup = folder.isInTopGroup,
isAutoSyncViaPollEnabled = folder.isAutoSyncViaPollEnabled,
isAutoSyncViaPushEnabled = folder.isAutoSyncViaPushEnabled,
isNotificationEnabled = folder.isNotificationEnabled,
)
}
}
@ -150,30 +135,34 @@ class FolderRepository(
name = folder.name,
type = folder.type.toFolderType(),
),
isInTopGroup = folder.isInTopGroup,
isIntegrate = folder.isIntegrate,
syncClass = folder.syncClass,
displayClass = folder.displayClass,
notifyClass = folder.notifyClass,
pushClass = folder.pushClass,
isHidden = folder.isHidden,
isInTopGroup = folder.isInTopGroup,
isAutoSyncViaPollEnabled = folder.isAutoSyncViaPollEnabled,
isAutoSyncViaPushEnabled = folder.isAutoSyncViaPushEnabled,
isNotificationEnabled = folder.isNotificationEnabled,
)
}
}
fun getPushFoldersFlow(account: Account): Flow<List<RemoteFolder>> {
return account.getFolderPushModeFlow()
.flatMapLatest { pushMode ->
getPushFoldersFlow(account, pushMode)
return account.getPushEnabledFlow()
.flatMapLatest { isPushEnabled ->
if (isPushEnabled) {
getPushFoldersFlowInternal(account)
} else {
flowOf(emptyList())
}
}
}
private fun getPushFoldersFlow(account: Account, folderMode: FolderMode): Flow<List<RemoteFolder>> {
private fun getPushFoldersFlowInternal(account: Account): Flow<List<RemoteFolder>> {
val messageStore = messageStoreManager.getMessageStore(account)
return callbackFlow {
send(getPushFolders(account, folderMode))
send(getPushFolders(account))
val listener = FolderSettingsChangedListener {
trySendBlocking(getPushFolders(account, folderMode))
trySendBlocking(getPushFolders(account))
}
messageStore.addFolderSettingsChangedListener(listener)
@ -185,23 +174,10 @@ class FolderRepository(
.flowOn(ioDispatcher)
}
private fun getPushFolders(account: Account, folderMode: FolderMode): List<RemoteFolder> {
if (folderMode == FolderMode.NONE) return emptyList()
private fun getPushFolders(account: Account): List<RemoteFolder> {
return getRemoteFolderDetails(account)
.asSequence()
.filter { folderDetails ->
val pushClass = folderDetails.effectivePushClass
when (folderMode) {
FolderMode.NONE -> false
FolderMode.ALL -> true
FolderMode.FIRST_CLASS -> pushClass == FolderClass.FIRST_CLASS
FolderMode.FIRST_AND_SECOND_CLASS -> {
pushClass == FolderClass.FIRST_CLASS || pushClass == FolderClass.SECOND_CLASS
}
FolderMode.NOT_SECOND_CLASS -> pushClass != FolderClass.SECOND_CLASS
}
}
.filter { it.isAutoSyncViaPushEnabled }
.map { folderDetails -> folderDetails.folder }
.toList()
}
@ -233,24 +209,24 @@ class FolderRepository(
messageStore.setIncludeInUnifiedInbox(folderId, includeInUnifiedInbox)
}
fun setDisplayClass(account: Account, folderId: Long, folderClass: FolderClass) {
fun setHidden(account: Account, folderId: Long, hidden: Boolean) {
val messageStore = messageStoreManager.getMessageStore(account)
messageStore.setDisplayClass(folderId, folderClass)
messageStore.setHidden(folderId, hidden)
}
fun setSyncClass(account: Account, folderId: Long, folderClass: FolderClass) {
fun setAutoSyncViaPollEnabled(account: Account, folderId: Long, enable: Boolean) {
val messageStore = messageStoreManager.getMessageStore(account)
messageStore.setSyncClass(folderId, folderClass)
messageStore.setAutoSyncViaPollEnabled(folderId, enable)
}
fun setPushClass(account: Account, folderId: Long, folderClass: FolderClass) {
fun setAutoSyncViaPushEnabled(account: Account, folderId: Long, enable: Boolean) {
val messageStore = messageStoreManager.getMessageStore(account)
messageStore.setPushClass(folderId, folderClass)
messageStore.setAutoSyncViaPushEnabled(folderId, enable)
}
fun setNotificationClass(account: Account, folderId: Long, folderClass: FolderClass) {
fun setNotificationEnabled(account: Account, folderId: Long, enable: Boolean) {
val messageStore = messageStoreManager.getMessageStore(account)
messageStore.setNotificationClass(folderId, folderClass)
messageStore.setNotificationEnabled(folderId, enable)
}
private fun folderTypeOf(account: Account, folderId: Long) = when (folderId) {
@ -275,44 +251,33 @@ class FolderRepository(
RemoteFolderType.ARCHIVE -> FolderType.ARCHIVE
}
private fun Account.getFolderPushModeFlow(): Flow<FolderMode> {
return accountManager.getAccountFlow(uuid).map { it.folderPushMode }
private fun Account.getPushEnabledFlow(): Flow<Boolean> {
return accountManager.getAccountFlow(uuid).map { it.isPushEnabled }
}
private val RemoteFolderDetails.effectivePushClass: FolderClass
get() = if (pushClass == FolderClass.INHERITED) effectiveSyncClass else pushClass
private val RemoteFolderDetails.effectiveSyncClass: FolderClass
get() = if (syncClass == FolderClass.INHERITED) displayClass else syncClass
}
private data class AccountContainer(
val account: Account,
val folderDisplayMode: FolderMode,
)
data class Folder(val id: Long, val name: String, val type: FolderType, val isLocalOnly: Boolean)
data class RemoteFolder(val id: Long, val serverId: String, val name: String, val type: FolderType)
data class FolderDetails(
val folder: Folder,
val isInTopGroup: Boolean,
val isIntegrate: Boolean,
val syncClass: FolderClass,
val displayClass: FolderClass,
val notifyClass: FolderClass,
val pushClass: FolderClass,
val isHidden: Boolean,
val isInTopGroup: Boolean,
val isAutoSyncViaPollEnabled: Boolean,
val isAutoSyncViaPushEnabled: Boolean,
val isNotificationEnabled: Boolean,
)
data class RemoteFolderDetails(
val folder: RemoteFolder,
val isInTopGroup: Boolean,
val isIntegrate: Boolean,
val syncClass: FolderClass,
val displayClass: FolderClass,
val notifyClass: FolderClass,
val pushClass: FolderClass,
val isHidden: Boolean,
val isInTopGroup: Boolean,
val isAutoSyncViaPollEnabled: Boolean,
val isAutoSyncViaPushEnabled: Boolean,
val isNotificationEnabled: Boolean,
)
data class DisplayFolder(

View File

@ -1,13 +1,11 @@
package com.fsck.k9.mailstore
import com.fsck.k9.mail.FolderClass
data class FolderSettings(
val visibleLimit: Int,
val displayClass: FolderClass,
val syncClass: FolderClass,
val notifyClass: FolderClass,
val pushClass: FolderClass,
val inTopGroup: Boolean,
val integrate: Boolean,
val isHidden: Boolean,
val inTopGroup: Boolean,
val isAutoSyncViaPollEnabled: Boolean,
val isAutoSyncViaPushEnabled: Boolean,
val isNotificationEnabled: Boolean,
)

View File

@ -2,7 +2,6 @@ package com.fsck.k9.mailstore
import com.fsck.k9.Account
import com.fsck.k9.Preferences
import com.fsck.k9.mail.FolderClass
/**
* Provides imported folder settings if available, otherwise default values.
@ -12,14 +11,15 @@ class FolderSettingsProvider(val preferences: Preferences, val account: Account)
val storage = preferences.storage
val prefix = "${account.uuid}.$folderServerId"
//FIXME
return FolderSettings(
visibleLimit = account.displayCount,
displayClass = storage.getString("$prefix.displayMode", null).toFolderClass(FolderClass.NO_CLASS),
syncClass = storage.getString("$prefix.syncMode", null).toFolderClass(FolderClass.INHERITED),
notifyClass = storage.getString("$prefix.notifyMode", null).toFolderClass(FolderClass.INHERITED),
pushClass = storage.getString("$prefix.pushMode", null).toFolderClass(FolderClass.SECOND_CLASS),
inTopGroup = storage.getBoolean("$prefix.inTopGroup", false),
integrate = storage.getBoolean("$prefix.integrate", false),
integrate = false,
isHidden = false,
inTopGroup = false,
isAutoSyncViaPollEnabled = false,
isAutoSyncViaPushEnabled = false,
isNotificationEnabled = false,
).also {
removeImportedFolderSettings(prefix)
}
@ -37,8 +37,4 @@ class FolderSettingsProvider(val preferences: Preferences, val account: Account)
editor.commit()
}
private fun String?.toFolderClass(defaultValue: FolderClass): FolderClass {
return if (this == null) defaultValue else FolderClass.valueOf(this)
}
}

View File

@ -1,6 +1,5 @@
package com.fsck.k9.mailstore
import com.fsck.k9.mail.FolderClass
import java.util.concurrent.CopyOnWriteArraySet
class ListenableMessageStore(private val messageStore: MessageStore) : MessageStore by messageStore {
@ -26,23 +25,23 @@ class ListenableMessageStore(private val messageStore: MessageStore) : MessageSt
notifyFolderSettingsChanged()
}
override fun setDisplayClass(folderId: Long, folderClass: FolderClass) {
messageStore.setDisplayClass(folderId, folderClass)
override fun setHidden(folderId: Long, hidden: Boolean) {
messageStore.setHidden(folderId, hidden)
notifyFolderSettingsChanged()
}
override fun setSyncClass(folderId: Long, folderClass: FolderClass) {
messageStore.setSyncClass(folderId, folderClass)
override fun setAutoSyncViaPollEnabled(folderId: Long, enable: Boolean) {
messageStore.setAutoSyncViaPollEnabled(folderId, enable)
notifyFolderSettingsChanged()
}
override fun setPushClass(folderId: Long, folderClass: FolderClass) {
messageStore.setPushClass(folderId, folderClass)
override fun setAutoSyncViaPushEnabled(folderId: Long, enable: Boolean) {
messageStore.setAutoSyncViaPushEnabled(folderId, enable)
notifyFolderSettingsChanged()
}
override fun setNotificationClass(folderId: Long, folderClass: FolderClass) {
messageStore.setNotificationClass(folderId, folderClass)
override fun setNotificationEnabled(folderId: Long, enable: Boolean) {
messageStore.setNotificationEnabled(folderId, enable)
notifyFolderSettingsChanged()
}

View File

@ -18,7 +18,6 @@ import com.fsck.k9.mail.BodyPart;
import com.fsck.k9.mail.BoundaryGenerator;
import com.fsck.k9.mail.FetchProfile;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.FolderClass;
import com.fsck.k9.mail.FolderType;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessageRetrievalListener;
@ -74,10 +73,10 @@ public class LocalFolder {
private long databaseId = -1L;
private int visibleLimit = -1;
private FolderClass displayClass = FolderClass.NO_CLASS;
private FolderClass syncClass = FolderClass.INHERITED;
private FolderClass pushClass = FolderClass.SECOND_CLASS;
private FolderClass notifyClass = FolderClass.INHERITED;
private boolean hidden = false;
private boolean autoSyncViaPollEnabled = false;
private boolean autoSyncViaPushEnabled = false;
private boolean notificationEnabled = false;
private boolean isInTopGroup = false;
private boolean isIntegrate = false;
@ -173,15 +172,10 @@ public class LocalFolder {
lastChecked = cursor.getLong(LocalStore.FOLDER_LAST_CHECKED_INDEX);
isInTopGroup = cursor.getInt(LocalStore.FOLDER_TOP_GROUP_INDEX) == 1;
isIntegrate = cursor.getInt(LocalStore.FOLDER_INTEGRATE_INDEX) == 1;
String noClass = FolderClass.NO_CLASS.toString();
String displayClass = cursor.getString(LocalStore.FOLDER_DISPLAY_CLASS_INDEX);
this.displayClass = FolderClass.valueOf((displayClass == null) ? noClass : displayClass);
String notifyClass = cursor.getString(LocalStore.FOLDER_NOTIFY_CLASS_INDEX);
this.notifyClass = FolderClass.valueOf((notifyClass == null) ? noClass : notifyClass);
String pushClass = cursor.getString(LocalStore.FOLDER_PUSH_CLASS_INDEX);
this.pushClass = FolderClass.valueOf((pushClass == null) ? noClass : pushClass);
String syncClass = cursor.getString(LocalStore.FOLDER_SYNC_CLASS_INDEX);
this.syncClass = FolderClass.valueOf((syncClass == null) ? noClass : syncClass);
this.hidden = cursor.getInt(LocalStore.FOLDER_HIDDEN_INDEX) == 1;
this.notificationEnabled = cursor.getInt(LocalStore.FOLDER_NOTIFICATION_ENABLED_INDEX) == 1;
this.autoSyncViaPushEnabled = cursor.getInt(LocalStore.FOLDER_AUTO_SYNC_POLL_INDEX) == 1;
this.autoSyncViaPollEnabled = cursor.getInt(LocalStore.FOLDER_AUTO_SYNC_PUSH_INDEX) == 1;
String moreMessagesValue = cursor.getString(LocalStore.MORE_MESSAGES_INDEX);
moreMessages = MoreMessages.fromDatabaseName(moreMessagesValue);
name = cursor.getString(LocalStore.FOLDER_NAME_INDEX);
@ -299,40 +293,40 @@ public class LocalFolder {
});
}
public FolderClass getDisplayClass() {
return displayClass;
public boolean getHidden() {
return hidden;
}
public FolderClass getSyncClass() {
return (FolderClass.INHERITED == syncClass) ? getDisplayClass() : syncClass;
public boolean getAutoSyncViaPollEnabled() {
return autoSyncViaPollEnabled;
}
public FolderClass getNotifyClass() {
return (FolderClass.INHERITED == notifyClass) ? getPushClass() : notifyClass;
public boolean getNotificationEnabled() {
return notificationEnabled;
}
public FolderClass getPushClass() {
return (FolderClass.INHERITED == pushClass) ? getSyncClass() : pushClass;
public boolean getAutoSyncViaPushEnabled() {
return autoSyncViaPushEnabled;
}
public void setDisplayClass(FolderClass displayClass) throws MessagingException {
this.displayClass = displayClass;
updateFolderColumn("display_class", this.displayClass.name());
public void setHidden(boolean hidden) throws MessagingException {
this.hidden = hidden;
updateFolderColumn("hidden", hidden);
}
public void setSyncClass(FolderClass syncClass) throws MessagingException {
this.syncClass = syncClass;
updateFolderColumn("poll_class", this.syncClass.name());
public void setAutoSyncViaPollEnabled(boolean enable) throws MessagingException {
this.autoSyncViaPollEnabled = enable;
updateFolderColumn("auto_sync_poll", enable);
}
public void setPushClass(FolderClass pushClass) throws MessagingException {
this.pushClass = pushClass;
updateFolderColumn("push_class", this.pushClass.name());
public void setAutoSyncViaPushEnabled(boolean enable) throws MessagingException {
this.autoSyncViaPushEnabled = enable;
updateFolderColumn("auto_sync_push", enable);
}
public void setNotifyClass(FolderClass notifyClass) throws MessagingException {
this.notifyClass = notifyClass;
updateFolderColumn("notify_class", this.notifyClass.name());
public void setNotificationEnabled(boolean enable) throws MessagingException {
this.notificationEnabled = enable;
updateFolderColumn("notify", enable);
}
public boolean isIntegrate() {
@ -1246,15 +1240,4 @@ public class LocalFolder {
static final int ON_DISK = 2;
static final int CHILD_PART_CONTAINS_DATA = 3;
}
public static boolean isModeMismatch(Account.FolderMode aMode, FolderClass fMode) {
return aMode == Account.FolderMode.NONE
|| (aMode == Account.FolderMode.FIRST_CLASS &&
fMode != FolderClass.FIRST_CLASS)
|| (aMode == Account.FolderMode.FIRST_AND_SECOND_CLASS &&
fMode != FolderClass.FIRST_CLASS &&
fMode != FolderClass.SECOND_CLASS)
|| (aMode == Account.FolderMode.NOT_SECOND_CLASS &&
fMode == FolderClass.SECOND_CLASS);
}
}

View File

@ -37,7 +37,6 @@ import com.fsck.k9.mail.BodyPart;
import com.fsck.k9.mail.FetchProfile;
import com.fsck.k9.mail.FetchProfile.Item;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.FolderClass;
import com.fsck.k9.mail.FolderType;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Multipart;
@ -110,7 +109,7 @@ public class LocalStore {
static final String GET_FOLDER_COLS =
"folders.id, name, visible_limit, last_updated, status, " +
"integrate, top_group, poll_class, push_class, display_class, notify_class, more_messages, server_id, " +
"integrate, top_group, auto_sync_poll, auto_sync_push, hidden, notify, more_messages, server_id, " +
"local_only, type";
static final int FOLDER_ID_INDEX = 0;
@ -120,10 +119,10 @@ public class LocalStore {
static final int FOLDER_STATUS_INDEX = 4;
static final int FOLDER_INTEGRATE_INDEX = 5;
static final int FOLDER_TOP_GROUP_INDEX = 6;
static final int FOLDER_SYNC_CLASS_INDEX = 7;
static final int FOLDER_PUSH_CLASS_INDEX = 8;
static final int FOLDER_DISPLAY_CLASS_INDEX = 9;
static final int FOLDER_NOTIFY_CLASS_INDEX = 10;
static final int FOLDER_AUTO_SYNC_POLL_INDEX = 7;
static final int FOLDER_AUTO_SYNC_PUSH_INDEX = 8;
static final int FOLDER_HIDDEN_INDEX = 9;
static final int FOLDER_NOTIFICATION_ENABLED_INDEX = 10;
static final int MORE_MESSAGES_INDEX = 11;
static final int FOLDER_SERVER_ID_INDEX = 12;
static final int LOCAL_ONLY_INDEX = 13;
@ -686,7 +685,7 @@ public class LocalStore {
values.put("type", FolderTypeConverter.toDatabaseFolderType(type));
values.put("visible_limit", 0);
values.put("more_messages", MoreMessages.FALSE.getDatabaseName());
values.put("display_class", FolderClass.FIRST_CLASS.name());
values.put("hidden", false);
return db.insert("folders", null, values);
});

View File

@ -1,8 +1,6 @@
package com.fsck.k9.mailstore
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.mail.Flag
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.mail.FolderType
import com.fsck.k9.mail.Header
import com.fsck.k9.search.ConditionsTreeNode
@ -201,11 +199,11 @@ interface MessageStore {
fun <T> getFolders(excludeLocalOnly: Boolean, mapper: FolderMapper<T>): List<T>
/**
* Retrieve folders for the given display mode along with their unread count.
* Retrieve visible folders along with their unread count.
*
* For the Outbox the total number of messages will be returned.
*/
fun <T> getDisplayFolders(displayMode: FolderMode, outboxFolderId: Long?, mapper: FolderMapper<T>): List<T>
fun <T> getDisplayFolders(showHiddenFolders: Boolean, outboxFolderId: Long?, mapper: FolderMapper<T>): List<T>
/**
* Check if all given folders are included in the Unified Inbox.
@ -260,22 +258,22 @@ interface MessageStore {
/**
* Update the display class of a folder.
*/
fun setDisplayClass(folderId: Long, folderClass: FolderClass)
fun setHidden(folderId: Long, hidden: Boolean)
/**
* Update the sync class of a folder.
*/
fun setSyncClass(folderId: Long, folderClass: FolderClass)
fun setAutoSyncViaPollEnabled(folderId: Long, enable: Boolean)
/**
* Update the push class of a folder.
*/
fun setPushClass(folderId: Long, folderClass: FolderClass)
fun setAutoSyncViaPushEnabled(folderId: Long, enable: Boolean)
/**
* Update the notification class of a folder.
*/
fun setNotificationClass(folderId: Long, folderClass: FolderClass)
fun setNotificationEnabled(folderId: Long, enable: Boolean)
/**
* Get the 'more messages' state of a folder.

View File

@ -4,7 +4,6 @@ import app.k9mail.core.common.mail.Protocols
import com.fsck.k9.Account
import com.fsck.k9.Account.SpecialFolderSelection
import com.fsck.k9.Preferences
import com.fsck.k9.mail.FolderClass
/**
* Updates special folders in [Account] if they are marked as [SpecialFolderSelection.AUTOMATIC] or if they are marked
@ -47,10 +46,10 @@ class SpecialFolderUpdater(
if (newInboxId != null) {
folderRepository.setIncludeInUnifiedInbox(account, newInboxId, true)
folderRepository.setDisplayClass(account, newInboxId, FolderClass.FIRST_CLASS)
folderRepository.setSyncClass(account, newInboxId, FolderClass.FIRST_CLASS)
folderRepository.setPushClass(account, newInboxId, FolderClass.FIRST_CLASS)
folderRepository.setNotificationClass(account, newInboxId, FolderClass.FIRST_CLASS)
folderRepository.setHidden(account, newInboxId, false)
folderRepository.setAutoSyncViaPollEnabled(account, newInboxId, true)
folderRepository.setAutoSyncViaPushEnabled(account, newInboxId, true)
folderRepository.setNotificationEnabled(account, newInboxId, true)
}
}
@ -117,8 +116,8 @@ class SpecialFolderUpdater(
}
if (folderId != null) {
folderRepository.setDisplayClass(account, folderId, FolderClass.FIRST_CLASS)
folderRepository.setSyncClass(account, folderId, FolderClass.NO_CLASS)
folderRepository.setHidden(account, folderId, false)
folderRepository.setAutoSyncViaPollEnabled(account, folderId, false)
}
}

View File

@ -13,7 +13,6 @@ import android.content.Context;
import com.fsck.k9.Account;
import com.fsck.k9.Account.DeletePolicy;
import com.fsck.k9.Account.Expunge;
import com.fsck.k9.Account.FolderMode;
import com.fsck.k9.Account.MessageFormat;
import com.fsck.k9.Account.QuoteStyle;
import com.fsck.k9.Account.Searchable;
@ -96,19 +95,19 @@ public class AccountSettingsDescriptions {
new V(1, new StringResourceSetting(Expunge.EXPUNGE_IMMEDIATELY.name(),
R.array.expunge_policy_values))
));
s.put("folderDisplayMode", Settings.versions(
new V(1, new EnumSetting<>(FolderMode.class, FolderMode.NOT_SECOND_CLASS))
));
s.put("folderPushMode", Settings.versions(
new V(1, new EnumSetting<>(FolderMode.class, FolderMode.FIRST_CLASS)),
new V(72, new EnumSetting<>(FolderMode.class, FolderMode.NONE))
));
s.put("folderSyncMode", Settings.versions(
new V(1, new EnumSetting<>(FolderMode.class, FolderMode.FIRST_CLASS))
));
s.put("folderTargetMode", Settings.versions(
new V(1, new EnumSetting<>(FolderMode.class, FolderMode.NOT_SECOND_CLASS))
));
// s.put("folderDisplayMode", Settings.versions(
// new V(1, new EnumSetting<>(FolderMode.class, FolderMode.NOT_SECOND_CLASS))
// ));
// s.put("folderPushMode", Settings.versions(
// new V(1, new EnumSetting<>(FolderMode.class, FolderMode.FIRST_CLASS)),
// new V(72, new EnumSetting<>(FolderMode.class, FolderMode.NONE))
// ));
// s.put("folderSyncMode", Settings.versions(
// new V(1, new EnumSetting<>(FolderMode.class, FolderMode.FIRST_CLASS))
// ));
// s.put("folderTargetMode", Settings.versions(
// new V(1, new EnumSetting<>(FolderMode.class, FolderMode.NOT_SECOND_CLASS))
// ));
s.put("idleRefreshMinutes", Settings.versions(
new V(1, new IntegerArraySetting(24, new int[] { 1, 2, 3, 6, 12, 24, 36, 48, 60 })),
new V(74, new IntegerResourceSetting(24, R.array.idle_refresh_period_values))
@ -154,9 +153,9 @@ public class AccountSettingsDescriptions {
s.put("notifyNewMail", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("folderNotifyNewMailMode", Settings.versions(
new V(34, new EnumSetting<>(FolderMode.class, FolderMode.ALL))
));
// s.put("folderNotifyNewMailMode", Settings.versions(
// new V(34, new EnumSetting<>(FolderMode.class, FolderMode.ALL))
// ));
s.put("notifySelfNewMail", Settings.versions(
new V(1, new BooleanSetting(true))
));

View File

@ -8,7 +8,6 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import com.fsck.k9.mail.FolderClass;
import com.fsck.k9.preferences.Settings.BooleanSetting;
import com.fsck.k9.preferences.Settings.EnumSetting;
import com.fsck.k9.preferences.Settings.SettingsDescription;
@ -28,19 +27,19 @@ class FolderSettingsDescriptions {
* and use that for whatever you add here.
*/
s.put("displayMode", Settings.versions(
new V(1, new EnumSetting<>(FolderClass.class, FolderClass.NO_CLASS))
));
s.put("notifyMode", Settings.versions(
new V(34, new EnumSetting<>(FolderClass.class, FolderClass.INHERITED))
));
s.put("syncMode", Settings.versions(
new V(1, new EnumSetting<>(FolderClass.class, FolderClass.INHERITED))
));
s.put("pushMode", Settings.versions(
new V(1, new EnumSetting<>(FolderClass.class, FolderClass.INHERITED)),
new V(66, new EnumSetting<>(FolderClass.class, FolderClass.SECOND_CLASS))
));
// s.put("displayMode", Settings.versions(
// new V(1, new EnumSetting<>(FolderClass.class, FolderClass.NO_CLASS))
// ));
// s.put("notifyMode", Settings.versions(
// new V(34, new EnumSetting<>(FolderClass.class, FolderClass.INHERITED))
// ));
// s.put("syncMode", Settings.versions(
// new V(1, new EnumSetting<>(FolderClass.class, FolderClass.INHERITED))
// ));
// s.put("pushMode", Settings.versions(
// new V(1, new EnumSetting<>(FolderClass.class, FolderClass.INHERITED)),
// new V(66, new EnumSetting<>(FolderClass.class, FolderClass.SECOND_CLASS))
// ));
s.put("inTopGroup", Settings.versions(
new V(1, new BooleanSetting(false))
));

View File

@ -1,7 +1,6 @@
package com.fsck.k9.preferences
import com.fsck.k9.Account
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.mailstore.FolderRepository
import com.fsck.k9.mailstore.RemoteFolderDetails
@ -15,10 +14,10 @@ class FolderSettingsProvider(private val folderRepository: FolderRepository) {
private fun RemoteFolderDetails.containsOnlyDefaultValues(): Boolean {
return isInTopGroup == getDefaultValue("inTopGroup") &&
isIntegrate == getDefaultValue("integrate") &&
syncClass == getDefaultValue("syncMode") &&
displayClass == getDefaultValue("displayMode") &&
notifyClass == getDefaultValue("notifyMode") &&
pushClass == getDefaultValue("pushMode")
isAutoSyncViaPollEnabled == getDefaultValue("syncMode") &&
isHidden == getDefaultValue("displayMode") &&
isNotificationEnabled == getDefaultValue("notifyMode") &&
isAutoSyncViaPushEnabled == getDefaultValue("pushMode")
}
private fun getDefaultValue(key: String): Any? {
@ -31,22 +30,22 @@ class FolderSettingsProvider(private val folderRepository: FolderRepository) {
private fun RemoteFolderDetails.toFolderSettings(): FolderSettings {
return FolderSettings(
folder.serverId,
isInTopGroup,
isIntegrate,
syncClass,
displayClass,
notifyClass,
pushClass,
isHidden,
isInTopGroup,
isAutoSyncViaPollEnabled,
isAutoSyncViaPushEnabled,
isNotificationEnabled,
)
}
}
data class FolderSettings(
val serverId: String,
val isInTopGroup: Boolean,
val isIntegrate: Boolean,
val syncClass: FolderClass,
val displayClass: FolderClass,
val notifyClass: FolderClass,
val pushClass: FolderClass,
val isHidden: Boolean,
val isInTopGroup: Boolean,
val isAutoSyncViaPollEnabled: Boolean,
val isAutoSyncViaPushEnabled: Boolean,
val isNotificationEnabled: Boolean,
)

View File

@ -399,10 +399,10 @@ class SettingsExporter(
// Write folder settings
writeFolderSetting(serializer, "integrate", folder.isIntegrate.toString())
writeFolderSetting(serializer, "inTopGroup", folder.isInTopGroup.toString())
writeFolderSetting(serializer, "syncMode", folder.syncClass.name)
writeFolderSetting(serializer, "displayMode", folder.displayClass.name)
writeFolderSetting(serializer, "notifyMode", folder.notifyClass.name)
writeFolderSetting(serializer, "pushMode", folder.pushClass.name)
// writeFolderSetting(serializer, "syncMode", folder.isAutoSyncViaPollEnabled.name)
// writeFolderSetting(serializer, "displayMode", folder.isHidden.name)
// writeFolderSetting(serializer, "notifyMode", folder.isNotificationEnabled.name)
// writeFolderSetting(serializer, "pushMode", folder.isAutoSyncViaPushEnabled.name)
serializer.endTag(null, FOLDER_ELEMENT)
}

View File

@ -1,49 +1,15 @@
package com.fsck.k9.search
import com.fsck.k9.Account
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.search.SearchSpecification.Attribute
import com.fsck.k9.search.SearchSpecification.SearchCondition
import com.fsck.k9.search.SearchSpecification.SearchField
/**
* Modify the supplied [LocalSearch] instance to limit the search to displayable folders.
*
* This method uses the current [folder display mode][Account.folderDisplayMode] to decide what folders to
* include/exclude.
*/
fun LocalSearch.limitToDisplayableFolders(account: Account) {
when (account.folderDisplayMode) {
FolderMode.FIRST_CLASS -> {
// Count messages in the INBOX and non-special first class folders
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
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 = conditions
if (root.mRight != null) {
root.mRight.or(searchCondition)
} else {
or(searchCondition)
}
}
FolderMode.NOT_SECOND_CLASS -> {
// Count messages in the INBOX and non-special non-second-class folders
and(SearchField.DISPLAY_CLASS, FolderClass.SECOND_CLASS.name, Attribute.NOT_EQUALS)
}
FolderMode.ALL, FolderMode.NONE -> {
// Count messages in the INBOX and non-special folders
}
}
fun LocalSearch.limitToDisplayableFolders() {
and(SearchField.FOLDER_HIDDEN, false.toString(), Attribute.EQUALS)
}
/**

View File

@ -71,7 +71,7 @@ public interface SearchSpecification extends Parcelable {
NEW_MESSAGE,
READ,
FLAGGED,
DISPLAY_CLASS
FOLDER_HIDDEN
}

View File

@ -122,7 +122,7 @@ public class SqlQueryBuilder {
columnName = "flagged";
break;
}
case DISPLAY_CLASS: {
case FOLDER_HIDDEN: {
columnName = "display_class";
break;
}

View File

@ -80,12 +80,12 @@ internal fun createFolderSettingsProvider(): FolderSettingsProvider {
on { getFolderSettings(any()) } doReturn
FolderSettings(
visibleLimit = 25,
displayClass = FolderClass.NO_CLASS,
syncClass = FolderClass.INHERITED,
notifyClass = FolderClass.INHERITED,
pushClass = FolderClass.SECOND_CLASS,
inTopGroup = false,
integrate = false,
isHidden = FolderClass.NO_CLASS,
inTopGroup = false,
isAutoSyncViaPollEnabled = FolderClass.INHERITED,
isAutoSyncViaPushEnabled = FolderClass.SECOND_CLASS,
isNotificationEnabled = FolderClass.INHERITED,
)
}
}

View File

@ -5,7 +5,6 @@ import app.k9mail.core.common.mail.Protocols
import app.k9mail.feature.account.common.domain.entity.Account
import app.k9mail.feature.account.setup.AccountSetupExternalContract
import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.Core
import com.fsck.k9.Preferences
import com.fsck.k9.logging.Timber
@ -72,7 +71,7 @@ class AccountCreator(
newAccount.automaticCheckIntervalMinutes = account.options.checkFrequencyInMinutes
newAccount.displayCount = account.options.messageDisplayCount
newAccount.folderPushMode = FolderMode.NONE
newAccount.isPushEnabled = false
newAccount.deletePolicy = accountCreatorHelper.getDefaultDeletePolicy(incomingServerSettings.type)
newAccount.chipColor = accountCreatorHelper.pickColor()

View File

@ -8,7 +8,6 @@ import com.fsck.k9.mail.Flag
import com.fsck.k9.mail.K9MailLib
import com.fsck.k9.mail.Message
import com.fsck.k9.mailstore.LocalFolder
import com.fsck.k9.mailstore.LocalFolder.isModeMismatch
import com.fsck.k9.mailstore.LocalMessage
import timber.log.Timber
@ -57,13 +56,13 @@ class K9NotificationStrategy(
}
}
if (isModeMismatch(account.folderDisplayMode, localFolder.displayClass)) {
if (localFolder.hidden) {
Timber.v("No notification: Message is in folder not being displayed")
return false
}
if (isModeMismatch(account.folderNotifyNewMailMode, localFolder.notifyClass)) {
Timber.v("No notification: Notifications are disabled for this folder class")
if (!localFolder.notificationEnabled) {
Timber.v("No notification: Notifications are disabled for this folder")
return false
}

View File

@ -4,7 +4,6 @@ package com.fsck.k9.storage;
import android.database.sqlite.SQLiteDatabase;
import com.fsck.k9.K9;
import com.fsck.k9.mail.FolderClass;
import com.fsck.k9.mailstore.LockableDatabase.SchemaDefinition;
import com.fsck.k9.mailstore.MigrationsHelper;
import com.fsck.k9.storage.migrations.Migrations;
@ -89,12 +88,12 @@ class StoreSchemaDefinition implements SchemaDefinition {
"visible_limit INTEGER, " +
"status TEXT, " +
"flagged_count INTEGER default 0, " +
"integrate INTEGER, " +
"top_group INTEGER, " +
"poll_class TEXT, " +
"push_class TEXT, " +
"display_class TEXT, " +
"notify_class TEXT default '"+ FolderClass.INHERITED.name() + "', " +
"integrate INTEGER DEFAULT 0, " +
"hidden INTEGER DEFAULT 0, " +
"top_group INTEGER DEFAULT 0, " +
"auto_sync_poll INTEGER DEFAULT 0, " +
"auto_sync_push INTEGER DEFAULT 0, " +
"notify INTEGER DEFAULT 0, " +
"more_messages TEXT default \"unknown\", " +
"server_id TEXT, " +
"local_only INTEGER, " +

View File

@ -15,10 +15,10 @@ internal class CreateFolderOperations(private val lockableDatabase: LockableData
put("visible_limit", folderSettings.visibleLimit)
put("integrate", folderSettings.integrate)
put("top_group", folderSettings.inTopGroup)
put("poll_class", folderSettings.syncClass.name)
put("push_class", folderSettings.pushClass.name)
put("display_class", folderSettings.displayClass.name)
put("notify_class", folderSettings.notifyClass.name)
put("auto_sync_poll", folderSettings.isAutoSyncViaPollEnabled)
put("auto_sync_push", folderSettings.isAutoSyncViaPushEnabled)
put("hidden", folderSettings.isHidden)
put("notify", folderSettings.isNotificationEnabled)
put("server_id", folder.serverId)
put("local_only", false)
put("type", folder.type.toDatabaseFolderType())

View File

@ -1,8 +1,6 @@
package com.fsck.k9.storage.messages
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.mail.Flag
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.mail.FolderType
import com.fsck.k9.mail.Header
import com.fsck.k9.mailstore.CreateFolderInfo
@ -158,11 +156,11 @@ class K9MessageStore(
}
override fun <T> getDisplayFolders(
displayMode: FolderMode,
showHiddenFolders: Boolean,
outboxFolderId: Long?,
mapper: FolderMapper<T>,
): List<T> {
return retrieveFolderOperations.getDisplayFolders(displayMode, outboxFolderId, mapper)
return retrieveFolderOperations.getDisplayFolders(showHiddenFolders, outboxFolderId, mapper)
}
override fun areAllIncludedInUnifiedInbox(folderIds: Collection<Long>): Boolean {
@ -209,20 +207,20 @@ class K9MessageStore(
updateFolderOperations.setIncludeInUnifiedInbox(folderId, includeInUnifiedInbox)
}
override fun setDisplayClass(folderId: Long, folderClass: FolderClass) {
updateFolderOperations.setDisplayClass(folderId, folderClass)
override fun setHidden(folderId: Long, hidden: Boolean) {
updateFolderOperations.setHidden(folderId, hidden)
}
override fun setSyncClass(folderId: Long, folderClass: FolderClass) {
updateFolderOperations.setSyncClass(folderId, folderClass)
override fun setAutoSyncViaPollEnabled(folderId: Long, enable: Boolean) {
updateFolderOperations.setAutoSyncViaPollEnabled(folderId, enable)
}
override fun setPushClass(folderId: Long, folderClass: FolderClass) {
updateFolderOperations.setPushClass(folderId, folderClass)
override fun setAutoSyncViaPushEnabled(folderId: Long, enable: Boolean) {
updateFolderOperations.setAutoSyncViaPushEnabled(folderId, enable)
}
override fun setNotificationClass(folderId: Long, folderClass: FolderClass) {
updateFolderOperations.setNotificationClass(folderId, folderClass)
override fun setNotificationEnabled(folderId: Long, enable: Boolean) {
updateFolderOperations.setNotificationEnabled(folderId, enable)
}
override fun hasMoreMessages(folderId: Long): MoreMessages {

View File

@ -3,8 +3,6 @@ package com.fsck.k9.storage.messages
import android.database.Cursor
import androidx.core.database.getLongOrNull
import app.k9mail.core.android.common.database.map
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.mail.FolderType
import com.fsck.k9.mailstore.FolderDetailsAccessor
import com.fsck.k9.mailstore.FolderMapper
@ -65,10 +63,10 @@ internal class RetrieveFolderOperations(private val lockableDatabase: LockableDa
}
}
fun <T> getDisplayFolders(displayMode: FolderMode, outboxFolderId: Long?, mapper: FolderMapper<T>): List<T> {
fun <T> getDisplayFolders(showHiddenFolders: Boolean, outboxFolderId: Long?, mapper: FolderMapper<T>): List<T> {
return lockableDatabase.execute(false) { db ->
val displayModeSelection = getDisplayModeSelection(displayMode)
val outboxFolderIdOrZero = outboxFolderId ?: 0
val hiddenFolderSelection = if (showHiddenFolders) "" else "WHERE hidden = 0"
val query =
"""
@ -86,7 +84,7 @@ SELECT ${FOLDER_COLUMNS.joinToString()}, (
AND messages.flagged = 1
)
FROM folders
$displayModeSelection
$hiddenFolderSelection
"""
db.rawQuery(query, arrayOf(outboxFolderIdOrZero.toString())).use { cursor ->
@ -98,26 +96,6 @@ $displayModeSelection
}
}
private fun getDisplayModeSelection(displayMode: FolderMode): String {
return when (displayMode) {
FolderMode.ALL -> {
""
}
FolderMode.FIRST_CLASS -> {
"WHERE display_class = '${FolderClass.FIRST_CLASS.name}'"
}
FolderMode.FIRST_AND_SECOND_CLASS -> {
"WHERE display_class IN ('${FolderClass.FIRST_CLASS.name}', '${FolderClass.SECOND_CLASS.name}')"
}
FolderMode.NOT_SECOND_CLASS -> {
"WHERE display_class != '${FolderClass.SECOND_CLASS.name}'"
}
FolderMode.NONE -> {
throw AssertionError("Invalid folder display mode: $displayMode")
}
}
}
fun getFolderId(folderServerId: String): Long? {
return lockableDatabase.execute(false) { db ->
db.query(
@ -230,17 +208,17 @@ private class CursorFolderAccessor(val cursor: Cursor) : FolderDetailsAccessor {
override val isIntegrate: Boolean
get() = cursor.getInt(6) == 1
override val syncClass: FolderClass
get() = cursor.getString(7).toFolderClass(FolderClass.INHERITED)
override val isAutoSyncViaPollEnabled: Boolean
get() = cursor.getInt(7) == 1
override val displayClass: FolderClass
get() = cursor.getString(8).toFolderClass(FolderClass.NO_CLASS)
override val isHidden: Boolean
get() = cursor.getInt(8) == 1
override val notifyClass: FolderClass
get() = cursor.getString(9).toFolderClass(FolderClass.INHERITED)
override val isNotificationEnabled: Boolean
get() = cursor.getInt(9) == 1
override val pushClass: FolderClass
get() = cursor.getString(10).toFolderClass(FolderClass.SECOND_CLASS)
override val isAutoSyncViaPushEnabled: Boolean
get() = cursor.getInt(10) == 1
override val visibleLimit: Int
get() = cursor.getInt(11)
@ -262,10 +240,6 @@ private class CursorFolderAccessor(val cursor: Cursor) : FolderDetailsAccessor {
}
}
private fun String?.toFolderClass(defaultValue: FolderClass): FolderClass {
return if (this == null) defaultValue else FolderClass.valueOf(this)
}
private val FOLDER_COLUMNS = arrayOf(
"id",
"name",
@ -274,10 +248,10 @@ private val FOLDER_COLUMNS = arrayOf(
"local_only",
"top_group",
"integrate",
"poll_class",
"display_class",
"notify_class",
"push_class",
"auto_sync_poll",
"hidden",
"notify",
"auto_sync_push",
"visible_limit",
"more_messages",
"last_updated",

View File

@ -1,7 +1,6 @@
package com.fsck.k9.storage.messages
import android.content.ContentValues
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.mail.FolderType
import com.fsck.k9.mailstore.FolderDetails
import com.fsck.k9.mailstore.LockableDatabase
@ -23,12 +22,12 @@ internal class UpdateFolderOperations(private val lockableDatabase: LockableData
fun updateFolderSettings(folderDetails: FolderDetails) {
lockableDatabase.execute(false) { db ->
val contentValues = ContentValues().apply {
put("top_group", folderDetails.isInTopGroup)
put("integrate", folderDetails.isIntegrate)
put("poll_class", folderDetails.syncClass.name)
put("display_class", folderDetails.displayClass.name)
put("notify_class", folderDetails.notifyClass.name)
put("push_class", folderDetails.pushClass.name)
put("hidden", folderDetails.isHidden)
put("top_group", folderDetails.isInTopGroup)
put("auto_sync_poll", folderDetails.isAutoSyncViaPollEnabled)
put("auto_sync_push", folderDetails.isAutoSyncViaPushEnabled)
put("notify", folderDetails.isNotificationEnabled)
}
db.update("folders", contentValues, "id = ?", arrayOf(folderDetails.folder.id.toString()))
@ -36,29 +35,23 @@ internal class UpdateFolderOperations(private val lockableDatabase: LockableData
}
fun setIncludeInUnifiedInbox(folderId: Long, includeInUnifiedInbox: Boolean) {
lockableDatabase.execute(false) { db ->
val contentValues = ContentValues().apply {
put("integrate", includeInUnifiedInbox)
}
db.update("folders", contentValues, "id = ?", arrayOf(folderId.toString()))
}
setBoolean(folderId = folderId, columnName = "integrate", value = includeInUnifiedInbox)
}
fun setDisplayClass(folderId: Long, folderClass: FolderClass) {
setString(folderId = folderId, columnName = "display_class", value = folderClass.name)
fun setHidden(folderId: Long, hidden: Boolean) {
setBoolean(folderId = folderId, columnName = "hidden", value = hidden)
}
fun setSyncClass(folderId: Long, folderClass: FolderClass) {
setString(folderId = folderId, columnName = "poll_class", value = folderClass.name)
fun setAutoSyncViaPollEnabled(folderId: Long, enable: Boolean) {
setBoolean(folderId = folderId, columnName = "auto_sync_poll", value = enable)
}
fun setPushClass(folderId: Long, folderClass: FolderClass) {
setString(folderId = folderId, columnName = "push_class", value = folderClass.name)
fun setAutoSyncViaPushEnabled(folderId: Long, enable: Boolean) {
setBoolean(folderId = folderId, columnName = "auto_sync_push", value = enable)
}
fun setNotificationClass(folderId: Long, folderClass: FolderClass) {
setString(folderId = folderId, columnName = "notify_class", value = folderClass.name)
fun setNotificationEnabled(folderId: Long, enable: Boolean) {
setBoolean(folderId = folderId, columnName = "notify", value = enable)
}
fun setMoreMessages(folderId: Long, moreMessages: MoreMessages) {
@ -102,4 +95,14 @@ internal class UpdateFolderOperations(private val lockableDatabase: LockableData
db.update("folders", contentValues, "id = ?", arrayOf(folderId.toString()))
}
}
private fun setBoolean(folderId: Long, columnName: String, value: Boolean) {
lockableDatabase.execute(false) { db ->
val contentValues = ContentValues().apply {
put(columnName, value)
}
db.update("folders", contentValues, "id = ?", arrayOf(folderId.toString()))
}
}
}

View File

@ -1,93 +1,92 @@
package com.fsck.k9.storage.migrations
import android.database.sqlite.SQLiteDatabase
import com.fsck.k9.mail.FolderClass
internal class MigrationTo70(private val db: SQLiteDatabase) {
fun removePushState() {
renameFoldersTable()
createNewFoldersTable()
copyFoldersData()
dropOldFoldersTable()
recreateFoldersIndex()
recreateFoldersTriggers()
// renameFoldersTable()
// createNewFoldersTable()
// copyFoldersData()
// dropOldFoldersTable()
// recreateFoldersIndex()
// recreateFoldersTriggers()
}
private fun renameFoldersTable() {
db.execSQL("ALTER TABLE folders RENAME TO folders_old")
}
private fun createNewFoldersTable() {
db.execSQL(
"CREATE TABLE folders (" +
"id INTEGER PRIMARY KEY," +
"name TEXT, " +
"last_updated INTEGER, " +
"unread_count INTEGER, " +
"visible_limit INTEGER, " +
"status TEXT, " +
"flagged_count INTEGER default 0, " +
"integrate INTEGER, " +
"top_group INTEGER, " +
"poll_class TEXT, " +
"push_class TEXT, " +
"display_class TEXT, " +
"notify_class TEXT default '" + FolderClass.INHERITED.name + "', " +
"more_messages TEXT default \"unknown\", " +
"server_id TEXT, " +
"local_only INTEGER, " +
"type TEXT DEFAULT \"regular\"" +
")",
)
}
private fun copyFoldersData() {
db.execSQL(
"""
INSERT INTO folders
SELECT
id,
name,
last_updated,
unread_count,
visible_limit,
status,
flagged_count,
integrate,
top_group,
poll_class,
push_class,
display_class,
notify_class,
more_messages,
server_id,
local_only,
type
FROM folders_old
""".trimIndent(),
)
}
private fun dropOldFoldersTable() {
db.execSQL("DROP TABLE folders_old")
}
private fun recreateFoldersIndex() {
db.execSQL("DROP INDEX IF EXISTS folder_server_id")
db.execSQL("CREATE INDEX folder_server_id ON folders (server_id)")
}
private fun recreateFoldersTriggers() {
db.execSQL("DROP TRIGGER IF EXISTS delete_folder")
db.execSQL("CREATE TRIGGER delete_folder BEFORE DELETE ON folders BEGIN DELETE FROM messages WHERE old.id = folder_id; END;")
db.execSQL("DROP TRIGGER IF EXISTS delete_folder_extra_values")
db.execSQL(
"CREATE TRIGGER delete_folder_extra_values " +
"BEFORE DELETE ON folders " +
"BEGIN " +
"DELETE FROM folder_extra_values WHERE old.id = folder_id; " +
"END;",
)
}
// private fun renameFoldersTable() {
// db.execSQL("ALTER TABLE folders RENAME TO folders_old")
// }
//
// private fun createNewFoldersTable() {
// db.execSQL(
// "CREATE TABLE folders (" +
// "id INTEGER PRIMARY KEY," +
// "name TEXT, " +
// "last_updated INTEGER, " +
// "unread_count INTEGER, " +
// "visible_limit INTEGER, " +
// "status TEXT, " +
// "flagged_count INTEGER default 0, " +
// "integrate INTEGER, " +
// "top_group INTEGER, " +
// "poll_class TEXT, " +
// "push_class TEXT, " +
// "display_class TEXT, " +
// "notify_class TEXT default '" + FolderClass.INHERITED.name + "', " +
// "more_messages TEXT default \"unknown\", " +
// "server_id TEXT, " +
// "local_only INTEGER, " +
// "type TEXT DEFAULT \"regular\"" +
// ")",
// )
// }
//
// private fun copyFoldersData() {
// db.execSQL(
// """
// INSERT INTO folders
// SELECT
// id,
// name,
// last_updated,
// unread_count,
// visible_limit,
// status,
// flagged_count,
// integrate,
// top_group,
// poll_class,
// push_class,
// display_class,
// notify_class,
// more_messages,
// server_id,
// local_only,
// type
// FROM folders_old
// """.trimIndent(),
// )
// }
//
// private fun dropOldFoldersTable() {
// db.execSQL("DROP TABLE folders_old")
// }
//
// private fun recreateFoldersIndex() {
// db.execSQL("DROP INDEX IF EXISTS folder_server_id")
// db.execSQL("CREATE INDEX folder_server_id ON folders (server_id)")
// }
//
// private fun recreateFoldersTriggers() {
// db.execSQL("DROP TRIGGER IF EXISTS delete_folder")
// db.execSQL("CREATE TRIGGER delete_folder BEFORE DELETE ON folders BEGIN DELETE FROM messages WHERE old.id = folder_id; END;")
//
// db.execSQL("DROP TRIGGER IF EXISTS delete_folder_extra_values")
// db.execSQL(
// "CREATE TRIGGER delete_folder_extra_values " +
// "BEFORE DELETE ON folders " +
// "BEGIN " +
// "DELETE FROM folder_extra_values WHERE old.id = folder_id; " +
// "END;",
// )
// }
}

View File

@ -25,12 +25,12 @@ class CreateFolderOperationsTest : RobolectricTest() {
type = FolderType.ARCHIVE,
settings = FolderSettings(
visibleLimit = 10,
displayClass = FolderClass.FIRST_CLASS,
syncClass = FolderClass.SECOND_CLASS,
notifyClass = FolderClass.NO_CLASS,
pushClass = FolderClass.NO_CLASS,
inTopGroup = true,
integrate = false,
isHidden = FolderClass.FIRST_CLASS,
inTopGroup = true,
isAutoSyncViaPollEnabled = FolderClass.SECOND_CLASS,
isAutoSyncViaPushEnabled = FolderClass.NO_CLASS,
isNotificationEnabled = FolderClass.NO_CLASS,
),
),
),
@ -79,12 +79,12 @@ class CreateFolderOperationsTest : RobolectricTest() {
type = FolderType.REGULAR,
settings = FolderSettings(
visibleLimit = 25,
displayClass = FolderClass.NO_CLASS,
syncClass = FolderClass.INHERITED,
notifyClass = FolderClass.INHERITED,
pushClass = FolderClass.NO_CLASS,
inTopGroup = false,
integrate = false,
isHidden = FolderClass.NO_CLASS,
inTopGroup = false,
isAutoSyncViaPollEnabled = FolderClass.INHERITED,
isAutoSyncViaPushEnabled = FolderClass.NO_CLASS,
isNotificationEnabled = FolderClass.INHERITED,
),
)
}

View File

@ -9,7 +9,6 @@ import assertk.assertions.isInstanceOf
import assertk.assertions.isNotNull
import assertk.assertions.isNull
import assertk.assertions.isTrue
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.mail.FolderType
import com.fsck.k9.mailstore.FolderNotFoundException
@ -48,10 +47,10 @@ class RetrieveFolderOperationsTest : RobolectricTest() {
assertThat(folder.isLocalOnly).isEqualTo(false)
assertThat(folder.isIntegrate).isEqualTo(true)
assertThat(folder.isInTopGroup).isEqualTo(true)
assertThat(folder.displayClass).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.syncClass).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.notifyClass).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.pushClass).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.isHidden).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.isAutoSyncViaPollEnabled).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.isNotificationEnabled).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.isAutoSyncViaPushEnabled).isEqualTo(FolderClass.NO_CLASS)
true
}
@ -82,10 +81,10 @@ class RetrieveFolderOperationsTest : RobolectricTest() {
assertThat(folder.isLocalOnly).isEqualTo(true)
assertThat(folder.isIntegrate).isEqualTo(true)
assertThat(folder.isInTopGroup).isEqualTo(true)
assertThat(folder.displayClass).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.syncClass).isEqualTo(FolderClass.INHERITED)
assertThat(folder.notifyClass).isEqualTo(FolderClass.INHERITED)
assertThat(folder.pushClass).isEqualTo(FolderClass.SECOND_CLASS)
assertThat(folder.isHidden).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.isAutoSyncViaPollEnabled).isEqualTo(FolderClass.INHERITED)
assertThat(folder.isNotificationEnabled).isEqualTo(FolderClass.INHERITED)
assertThat(folder.isAutoSyncViaPushEnabled).isEqualTo(FolderClass.SECOND_CLASS)
true
}
@ -122,10 +121,10 @@ class RetrieveFolderOperationsTest : RobolectricTest() {
assertThat(folder.isLocalOnly).isEqualTo(false)
assertThat(folder.isIntegrate).isEqualTo(true)
assertThat(folder.isInTopGroup).isEqualTo(true)
assertThat(folder.displayClass).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.syncClass).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.notifyClass).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.pushClass).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.isHidden).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.isAutoSyncViaPollEnabled).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.isNotificationEnabled).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.isAutoSyncViaPushEnabled).isEqualTo(FolderClass.NO_CLASS)
true
}
@ -162,10 +161,10 @@ class RetrieveFolderOperationsTest : RobolectricTest() {
assertThat(folder.isLocalOnly).isEqualTo(false)
assertThat(folder.isIntegrate).isEqualTo(true)
assertThat(folder.isInTopGroup).isEqualTo(true)
assertThat(folder.displayClass).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.syncClass).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.notifyClass).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.pushClass).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.isHidden).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.isAutoSyncViaPollEnabled).isEqualTo(FolderClass.FIRST_CLASS)
assertThat(folder.isNotificationEnabled).isEqualTo(FolderClass.NO_CLASS)
assertThat(folder.isAutoSyncViaPushEnabled).isEqualTo(FolderClass.NO_CLASS)
true
}
@ -208,7 +207,7 @@ class RetrieveFolderOperationsTest : RobolectricTest() {
)
val result = retrieveFolderOperations.getDisplayFolders(
displayMode = FolderMode.FIRST_CLASS,
showHiddenFolders,
outboxFolderId = folderId2,
) { folder ->
folder.id to folder.name
@ -226,7 +225,7 @@ class RetrieveFolderOperationsTest : RobolectricTest() {
)
val result = retrieveFolderOperations.getDisplayFolders(
displayMode = FolderMode.NOT_SECOND_CLASS,
showHiddenFolders,
outboxFolderId = folderId1,
) { folder ->
folder.id to folder.name
@ -249,7 +248,7 @@ class RetrieveFolderOperationsTest : RobolectricTest() {
)
val result = retrieveFolderOperations.getDisplayFolders(
displayMode = FolderMode.FIRST_AND_SECOND_CLASS,
showHiddenFolders,
outboxFolderId = folderId1,
) { folder ->
folder.id to folder.name
@ -278,7 +277,7 @@ class RetrieveFolderOperationsTest : RobolectricTest() {
sqliteDatabase.createMessage(uid = "msg5", folderId = folderId3, read = false)
val result = retrieveFolderOperations.getDisplayFolders(
displayMode = FolderMode.ALL,
showHiddenFolders,
outboxFolderId = folderId2,
) { folder ->
Triple(folder.id, folder.name, folder.unreadMessageCount)

View File

@ -47,12 +47,12 @@ class UpdateFolderOperationsTest : RobolectricTest() {
type = FolderType.REGULAR,
isLocalOnly = false,
),
isInTopGroup = true,
isIntegrate = true,
displayClass = FolderClass.FIRST_CLASS,
syncClass = FolderClass.FIRST_CLASS,
notifyClass = FolderClass.FIRST_CLASS,
pushClass = FolderClass.FIRST_CLASS,
isHidden = FolderClass.FIRST_CLASS,
isInTopGroup = true,
isAutoSyncViaPollEnabled = FolderClass.FIRST_CLASS,
isAutoSyncViaPushEnabled = FolderClass.FIRST_CLASS,
isNotificationEnabled = FolderClass.FIRST_CLASS,
),
)
@ -81,7 +81,7 @@ class UpdateFolderOperationsTest : RobolectricTest() {
fun `update display class`() {
val folderId = sqliteDatabase.createFolder(displayClass = "FIRST_CLASS")
updateFolderOperations.setDisplayClass(folderId = folderId, folderClass = FolderClass.SECOND_CLASS)
updateFolderOperations.setHidden(folderId = folderId, folderClass = FolderClass.SECOND_CLASS)
val folder = sqliteDatabase.readFolders().first()
assertThat(folder.id).isEqualTo(folderId)
@ -92,7 +92,7 @@ class UpdateFolderOperationsTest : RobolectricTest() {
fun `update sync class`() {
val folderId = sqliteDatabase.createFolder(syncClass = "FIRST_CLASS")
updateFolderOperations.setSyncClass(folderId = folderId, folderClass = FolderClass.NO_CLASS)
updateFolderOperations.setAutoSyncViaPollEnabled(folderId = folderId, enable = FolderClass.NO_CLASS)
val folder = sqliteDatabase.readFolders().first()
assertThat(folder.id).isEqualTo(folderId)
@ -103,7 +103,7 @@ class UpdateFolderOperationsTest : RobolectricTest() {
fun `update push class`() {
val folderId = sqliteDatabase.createFolder(pushClass = "FIRST_CLASS")
updateFolderOperations.setPushClass(folderId = folderId, folderClass = FolderClass.NO_CLASS)
updateFolderOperations.setAutoSyncViaPushEnabled(folderId = folderId, enable = FolderClass.NO_CLASS)
val folder = sqliteDatabase.readFolders().first()
assertThat(folder.id).isEqualTo(folderId)
@ -114,7 +114,7 @@ class UpdateFolderOperationsTest : RobolectricTest() {
fun `update notification class`() {
val folderId = sqliteDatabase.createFolder(syncClass = "FIRST_CLASS")
updateFolderOperations.setNotificationClass(folderId = folderId, folderClass = FolderClass.INHERITED)
updateFolderOperations.setNotificationEnabled(folderId = folderId, enable = FolderClass.INHERITED)
val folder = sqliteDatabase.readFolders().first()
assertThat(folder.id).isEqualTo(folderId)

View File

@ -9,7 +9,6 @@ import android.view.MenuItem
import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.RecyclerView
import com.fsck.k9.Account
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.Preferences
import com.fsck.k9.controller.MessageReference
import com.fsck.k9.controller.MessagingController
@ -64,10 +63,10 @@ class ChooseFolderActivity : K9Activity() {
updateFolderList(folders)
}
val savedDisplayMode = savedInstanceState?.getString(STATE_DISPLAY_MODE)?.let { FolderMode.valueOf(it) }
val displayMode = savedDisplayMode ?: getInitialDisplayMode()
val savedShowHiddenFolders = savedInstanceState?.getBoolean(STATE_SHOW_HIDDEN_FOLDERS)
val showHiddenFolders = savedShowHiddenFolders ?: getInitialShowHiddenFolders()
viewModel.setDisplayMode(account, displayMode)
viewModel.setShowHiddenFolders(account, showHiddenFolders)
}
private fun decodeArguments(savedInstanceState: Bundle?): Boolean {
@ -89,8 +88,8 @@ class ChooseFolderActivity : K9Activity() {
return true
}
private fun getInitialDisplayMode(): FolderMode {
return if (showDisplayableOnly) account.folderDisplayMode else account.folderTargetMode
private fun getInitialShowHiddenFolders(): Boolean {
return !showDisplayableOnly
}
private fun initializeActionBar() {
@ -147,7 +146,7 @@ class ChooseFolderActivity : K9Activity() {
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
scrollToFolderId?.let { folderId -> outState.putLong(STATE_SCROLL_TO_FOLDER_ID, folderId) }
outState.putString(STATE_DISPLAY_MODE, viewModel.currentDisplayMode?.name)
outState.putBoolean(STATE_SHOW_HIDDEN_FOLDERS, viewModel.showHiddenFolders)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@ -177,10 +176,10 @@ class ChooseFolderActivity : K9Activity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> finish()
R.id.display_1st_class -> setDisplayMode(FolderMode.FIRST_CLASS)
R.id.display_1st_and_2nd_class -> setDisplayMode(FolderMode.FIRST_AND_SECOND_CLASS)
R.id.display_not_second_class -> setDisplayMode(FolderMode.NOT_SECOND_CLASS)
R.id.display_all -> setDisplayMode(FolderMode.ALL)
R.id.display_1st_class -> setShowHiddenFolders(false)
R.id.display_1st_and_2nd_class -> setShowHiddenFolders(false)
R.id.display_not_second_class -> setShowHiddenFolders(false)
R.id.display_all -> setShowHiddenFolders(true)
R.id.list_folders -> refreshFolderList()
else -> return super.onOptionsItemSelected(item)
}
@ -191,8 +190,8 @@ class ChooseFolderActivity : K9Activity() {
messagingController.refreshFolderList(account)
}
private fun setDisplayMode(displayMode: FolderMode) {
viewModel.setDisplayMode(account, displayMode)
private fun setShowHiddenFolders(show: Boolean) {
viewModel.setShowHiddenFolders(account, show)
}
private fun returnResult(folderId: Long, displayName: String) {
@ -238,7 +237,7 @@ class ChooseFolderActivity : K9Activity() {
companion object {
private const val STATE_SCROLL_TO_FOLDER_ID = "scrollToFolderId"
private const val STATE_DISPLAY_MODE = "displayMode"
private const val STATE_SHOW_HIDDEN_FOLDERS = "showHiddenFolders"
private const val EXTRA_ACCOUNT = "accountUuid"
private const val EXTRA_CURRENT_FOLDER_ID = "currentFolderId"
private const val EXTRA_SCROLL_TO_FOLDER_ID = "scrollToFolderId"

View File

@ -5,7 +5,6 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import com.fsck.k9.Account
import com.fsck.k9.Account.FolderMode
import com.fsck.k9.mailstore.DisplayFolder
import com.fsck.k9.mailstore.FolderRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -17,23 +16,23 @@ import kotlinx.coroutines.launch
class ChooseFolderViewModel(private val folderRepository: FolderRepository) : ViewModel() {
private val inputFlow = MutableSharedFlow<DisplayMode>(replay = 1)
private val foldersFlow = inputFlow
.flatMapLatest { (account, displayMode) ->
folderRepository.getDisplayFoldersFlow(account, displayMode)
.flatMapLatest { (account, showHiddenFolders) ->
folderRepository.getDisplayFoldersFlow(account, showHiddenFolders)
}
var currentDisplayMode: FolderMode? = null
var showHiddenFolders: Boolean = false
private set
fun getFolders(): LiveData<List<DisplayFolder>> {
return foldersFlow.asLiveData()
}
fun setDisplayMode(account: Account, displayMode: FolderMode) {
currentDisplayMode = displayMode
fun setShowHiddenFolders(account: Account, show: Boolean) {
showHiddenFolders = show
viewModelScope.launch {
inputFlow.emit(DisplayMode(account, displayMode))
inputFlow.emit(DisplayMode(account, show))
}
}
}
private data class DisplayMode(val account: Account, val displayMode: FolderMode)
private data class DisplayMode(val account: Account, val showHiddenFolders: Boolean)

View File

@ -2,7 +2,6 @@ package com.fsck.k9.ui.managefolders
import androidx.preference.PreferenceDataStore
import com.fsck.k9.Account
import com.fsck.k9.mail.FolderClass
import com.fsck.k9.mailstore.FolderDetails
import com.fsck.k9.mailstore.FolderRepository
import kotlinx.coroutines.CoroutineScope
@ -21,6 +20,10 @@ class FolderSettingsDataStore(
return when (key) {
"folder_settings_in_top_group" -> folder.isInTopGroup
"folder_settings_include_in_integrated_inbox" -> folder.isIntegrate
"folder_settings_folder_display_mode" -> folder.isHidden
"folder_settings_folder_sync_mode" -> folder.isAutoSyncViaPollEnabled
"folder_settings_folder_notify_mode" -> folder.isNotificationEnabled
"folder_settings_folder_push_mode" -> folder.isAutoSyncViaPushEnabled
else -> error("Unknown key: $key")
}
}
@ -29,36 +32,10 @@ class FolderSettingsDataStore(
return when (key) {
"folder_settings_in_top_group" -> updateFolder(folder.copy(isInTopGroup = value))
"folder_settings_include_in_integrated_inbox" -> updateFolder(folder.copy(isIntegrate = value))
else -> error("Unknown key: $key")
}
}
override fun getString(key: String?, defValue: String?): String? {
return when (key) {
"folder_settings_folder_display_mode" -> folder.displayClass.name
"folder_settings_folder_sync_mode" -> folder.syncClass.name
"folder_settings_folder_notify_mode" -> folder.notifyClass.name
"folder_settings_folder_push_mode" -> folder.pushClass.name
else -> error("Unknown key: $key")
}
}
override fun putString(key: String?, value: String?) {
val newValue = requireNotNull(value) { "'value' can't be null" }
when (key) {
"folder_settings_folder_display_mode" -> {
updateFolder(folder.copy(displayClass = FolderClass.valueOf(newValue)))
}
"folder_settings_folder_sync_mode" -> {
updateFolder(folder.copy(syncClass = FolderClass.valueOf(newValue)))
}
"folder_settings_folder_notify_mode" -> {
updateFolder(folder.copy(notifyClass = FolderClass.valueOf(newValue)))
}
"folder_settings_folder_push_mode" -> {
updateFolder(folder.copy(pushClass = FolderClass.valueOf(newValue)))
}
"folder_settings_folder_display_mode" -> updateFolder(folder.copy(isHidden = value))
"folder_settings_folder_sync_mode" -> updateFolder(folder.copy(isAutoSyncViaPollEnabled = value))
"folder_settings_folder_notify_mode" -> updateFolder(folder.copy(isNotificationEnabled = value))
"folder_settings_folder_push_mode" -> updateFolder(folder.copy(isAutoSyncViaPushEnabled = value))
else -> error("Unknown key: $key")
}
}

View File

@ -121,10 +121,6 @@ class ManageFoldersFragment : Fragment() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.list_folders -> refreshFolderList()
R.id.display_1st_class -> setDisplayMode(Account.FolderMode.FIRST_CLASS)
R.id.display_1st_and_2nd_class -> setDisplayMode(Account.FolderMode.FIRST_AND_SECOND_CLASS)
R.id.display_not_second_class -> setDisplayMode(Account.FolderMode.NOT_SECOND_CLASS)
R.id.display_all -> setDisplayMode(Account.FolderMode.ALL)
else -> return super.onOptionsItemSelected(item)
}
@ -135,13 +131,6 @@ class ManageFoldersFragment : Fragment() {
messagingController.refreshFolderList(account)
}
private fun setDisplayMode(newMode: Account.FolderMode) {
account.folderDisplayMode = newMode
preferences.saveAccount(account)
itemAdapter.filter(null)
}
private fun folderListFilter(item: FolderListItem, constraint: CharSequence?): Boolean {
if (constraint.isNullOrEmpty()) return true

View File

@ -9,6 +9,6 @@ import com.fsck.k9.mailstore.FolderRepository
class ManageFoldersViewModel(private val folderRepository: FolderRepository) : ViewModel() {
fun getFolders(account: Account): LiveData<List<DisplayFolder>> {
return folderRepository.getDisplayFoldersFlow(account).asLiveData()
return folderRepository.getDisplayFoldersFlow(account, showHiddenFolders = true).asLiveData()
}
}

View File

@ -44,6 +44,7 @@ class AccountSettingsDataStore(
"upload_sent_messages" -> account.isUploadSentMessages
"ignore_chat_messages" -> account.isIgnoreChatMessages
"subscribed_folders_only" -> account.isSubscribedFoldersOnly
"folder_push_mode" -> account.isPushEnabled
else -> defValue
}
}
@ -69,6 +70,7 @@ class AccountSettingsDataStore(
"upload_sent_messages" -> account.isUploadSentMessages = value
"ignore_chat_messages" -> account.isIgnoreChatMessages = value
"subscribed_folders_only" -> updateSubscribedFoldersOnly(value)
"folder_push_mode" -> account.isPushEnabled = value
else -> return
}
@ -115,8 +117,6 @@ class AccountSettingsDataStore(
"account_message_age" -> account.maximumPolledMessageAge.toString()
"account_autodownload_size" -> account.maximumAutoDownloadMessageSize.toString()
"account_check_frequency" -> account.automaticCheckIntervalMinutes.toString()
"folder_sync_mode" -> account.folderSyncMode.name
"folder_push_mode" -> account.folderPushMode.name
"delete_policy" -> account.deletePolicy.name
"expunge_policy" -> account.expungePolicy.name
"max_push_folders" -> account.maxPushFolders.toString()
@ -127,15 +127,12 @@ class AccountSettingsDataStore(
"account_setup_auto_expand_folder" -> {
loadSpecialFolder(account.autoExpandFolderId, SpecialFolderSelection.MANUAL)
}
"folder_display_mode" -> account.folderDisplayMode.name
"folder_target_mode" -> account.folderTargetMode.name
"searchable_folders" -> account.searchableFolders.name
"archive_folder" -> loadSpecialFolder(account.archiveFolderId, account.archiveFolderSelection)
"drafts_folder" -> loadSpecialFolder(account.draftsFolderId, account.draftsFolderSelection)
"sent_folder" -> loadSpecialFolder(account.sentFolderId, account.sentFolderSelection)
"spam_folder" -> loadSpecialFolder(account.spamFolderId, account.spamFolderSelection)
"trash_folder" -> loadSpecialFolder(account.trashFolderId, account.trashFolderSelection)
"folder_notify_new_mail_mode" -> account.folderNotifyNewMailMode.name
"account_combined_vibration" -> getCombinedVibrationValue()
"account_remote_search_num_results" -> account.remoteSearchNumResults.toString()
"account_ringtone" -> account.notificationSettings.ringtone
@ -158,12 +155,6 @@ class AccountSettingsDataStore(
reschedulePoll()
}
}
"folder_sync_mode" -> {
if (account.updateFolderSyncMode(Account.FolderMode.valueOf(value))) {
reschedulePoll()
}
}
"folder_push_mode" -> account.folderPushMode = Account.FolderMode.valueOf(value)
"delete_policy" -> account.deletePolicy = Account.DeletePolicy.valueOf(value)
"expunge_policy" -> account.expungePolicy = Account.Expunge.valueOf(value)
"max_push_folders" -> account.maxPushFolders = value.toInt()
@ -172,15 +163,12 @@ class AccountSettingsDataStore(
"quote_style" -> account.quoteStyle = Account.QuoteStyle.valueOf(value)
"account_quote_prefix" -> account.quotePrefix = value
"account_setup_auto_expand_folder" -> account.autoExpandFolderId = extractFolderId(value)
"folder_display_mode" -> account.folderDisplayMode = Account.FolderMode.valueOf(value)
"folder_target_mode" -> account.folderTargetMode = Account.FolderMode.valueOf(value)
"searchable_folders" -> account.searchableFolders = Account.Searchable.valueOf(value)
"archive_folder" -> saveSpecialFolderSelection(value, account::setArchiveFolderId)
"drafts_folder" -> saveSpecialFolderSelection(value, account::setDraftsFolderId)
"sent_folder" -> saveSpecialFolderSelection(value, account::setSentFolderId)
"spam_folder" -> saveSpecialFolderSelection(value, account::setSpamFolderId)
"trash_folder" -> saveSpecialFolderSelection(value, account::setTrashFolderId)
"folder_notify_new_mail_mode" -> account.folderNotifyNewMailMode = Account.FolderMode.valueOf(value)
"account_combined_vibration" -> setCombinedVibrationValue(value)
"account_remote_search_num_results" -> account.remoteSearchNumResults = value.toInt()
"account_ringtone" -> setNotificationSound(value)

View File

@ -81,21 +81,9 @@
app:useSimpleSummaryProvider="true"
android:title="@string/account_settings_mail_check_frequency_label" />
<ListPreference
android:dialogTitle="@string/account_settings_folder_sync_mode_label"
android:entries="@array/folder_sync_mode_entries"
android:entryValues="@array/folder_sync_mode_values"
android:key="folder_sync_mode"
app:useSimpleSummaryProvider="true"
android:title="@string/account_settings_folder_sync_mode_label" />
<ListPreference
android:dialogTitle="@string/account_settings_folder_push_mode_label"
android:entries="@array/folder_push_mode_entries"
android:entryValues="@array/folder_push_mode_values"
<SwitchPreference
android:key="folder_push_mode"
app:useSimpleSummaryProvider="true"
android:title="@string/account_settings_folder_push_mode_label" />
android:title="Use Push" />
<CheckBoxPreference
android:defaultValue="true"
@ -237,26 +225,10 @@
app:useSimpleSummaryProvider="true"
android:title="@string/account_setup_auto_expand_folder" />
<ListPreference
android:dialogTitle="@string/account_settings_folder_display_mode_label"
android:entries="@array/folder_display_mode_entries"
android:entryValues="@array/folder_display_mode_values"
android:key="folder_display_mode"
app:useSimpleSummaryProvider="true"
android:title="@string/account_settings_folder_display_mode_label" />
<CheckBoxPreference
android:key="subscribed_folders_only"
android:title="@string/account_setup_incoming_subscribed_folders_only_label" />
<ListPreference
android:dialogTitle="@string/account_settings_folder_target_mode_label"
android:entries="@array/folder_target_mode_entries"
android:entryValues="@array/folder_target_mode_values"
android:key="folder_target_mode"
app:useSimpleSummaryProvider="true"
android:title="@string/account_settings_folder_target_mode_label" />
<ListPreference
android:dialogTitle="@string/account_settings_searchable_label"
android:entries="@array/searchable_entries"
@ -303,15 +275,6 @@
android:summary="@string/account_settings_notify_summary"
android:title="@string/account_settings_notify_label" />
<ListPreference
android:dependency="account_notify"
android:dialogTitle="@string/account_settings_folder_notify_new_mail_mode_label"
android:entries="@array/folder_notify_new_mail_mode_entries"
android:entryValues="@array/folder_notify_new_mail_mode_values"
android:key="folder_notify_new_mail_mode"
app:useSimpleSummaryProvider="true"
android:title="@string/account_settings_folder_notify_new_mail_mode_label" />
<CheckBoxPreference
android:defaultValue="true"
android:dependency="account_notify"

View File

@ -20,47 +20,35 @@
<PreferenceCategory
android:key="folder_settings">
<CheckBoxPreference
android:key="folder_settings_in_top_group"
android:title="@string/folder_settings_in_top_group_label"
android:summary="@string/folder_settings_in_top_group_summary" />
<ListPreference
<SwitchPreference
android:disableDependentsState="true"
android:key="folder_settings_folder_display_mode"
android:title="@string/folder_settings_folder_display_mode_label"
app:useSimpleSummaryProvider="true"
android:entries="@array/folder_settings_folder_display_mode_entries"
android:entryValues="@array/folder_settings_folder_display_mode_values"
android:dialogTitle="@string/folder_settings_folder_display_mode_label" />
android:title="Hide folder"/>
<ListPreference
android:key="folder_settings_folder_sync_mode"
android:title="@string/folder_settings_folder_sync_mode_label"
app:useSimpleSummaryProvider="true"
android:entries="@array/folder_settings_folder_sync_mode_entries"
android:entryValues="@array/folder_settings_folder_sync_mode_values"
android:dialogTitle="@string/folder_settings_folder_sync_mode_label" />
<ListPreference
android:key="folder_settings_folder_push_mode"
android:title="@string/folder_settings_folder_push_mode_label"
app:useSimpleSummaryProvider="true"
android:entries="@array/folder_settings_folder_push_mode_entries"
android:entryValues="@array/folder_settings_folder_push_mode_values"
android:dialogTitle="@string/folder_settings_folder_push_mode_label" />
<ListPreference
android:key="folder_settings_folder_notify_mode"
android:title="@string/folder_settings_folder_notify_mode_label"
app:useSimpleSummaryProvider="true"
android:entries="@array/folder_settings_folder_notify_mode_entries"
android:entryValues="@array/folder_settings_folder_notify_mode_values"
android:dialogTitle="@string/folder_settings_folder_notify_mode_label" />
<CheckBoxPreference
<SwitchPreference
android:dependency="folder_settings_folder_display_mode"
android:key="folder_settings_include_in_integrated_inbox"
android:title="@string/folder_settings_include_in_integrated_inbox_label"
android:summary="@string/folder_settings_include_in_integrated_inbox_summary" />
android:title="@string/folder_settings_include_in_integrated_inbox_label" />
<SwitchPreference
android:dependency="folder_settings_folder_display_mode"
android:key="folder_settings_in_top_group"
android:title="@string/folder_settings_in_top_group_label"/>
<SwitchPreference
android:dependency="folder_settings_folder_display_mode"
android:key="folder_settings_folder_sync_mode"
android:title="Automatically sync messages"/>
<SwitchPreference
android:dependency="folder_settings_folder_display_mode"
android:key="folder_settings_folder_push_mode"
android:title="Check folder via Push"/>
<SwitchPreference
android:dependency="folder_settings_folder_display_mode"
android:key="folder_settings_folder_notify_mode"
android:title="Create notification for new messages"/>
</PreferenceCategory>

View File

@ -1,5 +0,0 @@
package com.fsck.k9.mail;
public enum FolderClass {
NO_CLASS, INHERITED, FIRST_CLASS, SECOND_CLASS
}