Don't use enum ordinals when saving general settings

This commit is contained in:
cketti 2019-05-22 17:53:08 +02:00
parent 38c3e26921
commit 3db836ee21
5 changed files with 97 additions and 73 deletions

View file

@ -7,6 +7,7 @@ import com.fsck.k9.Account.SortType
import com.fsck.k9.core.BuildConfig
import com.fsck.k9.mail.K9MailLib
import com.fsck.k9.mailstore.LocalStore
import com.fsck.k9.preferences.Storage
import com.fsck.k9.preferences.StorageEditor
import org.koin.standalone.KoinComponent
import org.koin.standalone.inject
@ -419,49 +420,24 @@ object K9 : KoinComponent {
isConfirmDeleteFromNotification = storage.getBoolean("confirmDeleteFromNotification", true)
isConfirmMarkAllRead = storage.getBoolean("confirmMarkAllRead", true)
sortType = try {
val value = storage.getString("sortTypeEnum", Account.DEFAULT_SORT_TYPE.name)
SortType.valueOf(value)
} catch (e: Exception) {
Account.DEFAULT_SORT_TYPE
}
sortType = storage.getEnum("sortTypeEnum", Account.DEFAULT_SORT_TYPE)
val sortAscendingSetting = storage.getBoolean("sortAscending", Account.DEFAULT_SORT_ASCENDING)
sortAscending[sortType] = sortAscendingSetting
val notificationHideSubjectSetting = storage.getString("notificationHideSubject", null)
notificationHideSubject = if (notificationHideSubjectSetting == null) {
NotificationHideSubject.NEVER
} else {
NotificationHideSubject.valueOf(notificationHideSubjectSetting)
}
notificationHideSubject = storage.getEnum("notificationHideSubject", NotificationHideSubject.NEVER)
notificationQuickDeleteBehaviour = storage.getEnum("notificationQuickDelete", NotificationQuickDelete.NEVER)
val notificationQuickDelete = storage.getString("notificationQuickDelete", null)
if (notificationQuickDelete != null) {
notificationQuickDeleteBehaviour = NotificationQuickDelete.valueOf(notificationQuickDelete)
}
lockScreenNotificationVisibility = storage.getEnum("lockScreenNotificationVisibility",
LockScreenNotificationVisibility.MESSAGE_COUNT)
val lockScreenNotificationVisibilitySetting = storage.getString("lockScreenNotificationVisibility", null)
if (lockScreenNotificationVisibilitySetting != null) {
lockScreenNotificationVisibility =
LockScreenNotificationVisibility.valueOf(lockScreenNotificationVisibilitySetting)
}
val splitViewModeSetting = storage.getString("splitViewMode", null)
if (splitViewModeSetting != null) {
splitViewMode = SplitViewMode.valueOf(splitViewModeSetting)
}
splitViewMode = storage.getEnum("splitViewMode", SplitViewMode.NEVER)
isUseBackgroundAsUnreadIndicator = storage.getBoolean("useBackgroundAsUnreadIndicator", true)
isThreadedViewEnabled = storage.getBoolean("threadedView", true)
fontSizes.load(storage)
backgroundOps = try {
val settingValue = storage.getString("backgroundOperations", BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC.name)
BACKGROUND_OPS.valueOf(settingValue)
} catch (e: Exception) {
BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC
}
backgroundOps = storage.getEnum("backgroundOperations", BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC)
isColorizeMissingContactPictures = storage.getBoolean("colorizeMissingContactPictures", true)
@ -476,17 +452,10 @@ object K9 : KoinComponent {
k9Language = storage.getString("language", "")
var themeValue = storage.getInt("theme", Theme.LIGHT.ordinal)
k9Theme = if (themeValue == Theme.DARK.ordinal) {
Theme.DARK
} else {
Theme.LIGHT
}
k9Theme = storage.getEnum("theme", Theme.LIGHT)
themeValue = storage.getInt("messageViewTheme", Theme.USE_GLOBAL.ordinal)
k9MessageViewThemeSetting = Theme.values()[themeValue]
themeValue = storage.getInt("messageComposeTheme", Theme.USE_GLOBAL.ordinal)
k9ComposerThemeSetting = Theme.values()[themeValue]
k9MessageViewThemeSetting = storage.getEnum("messageViewTheme", Theme.USE_GLOBAL)
k9ComposerThemeSetting = storage.getEnum("messageComposeTheme", Theme.USE_GLOBAL)
isFixedMessageViewTheme = storage.getBoolean("fixedMessageViewTheme", true)
}
@ -494,7 +463,7 @@ object K9 : KoinComponent {
fun save(editor: StorageEditor) {
editor.putBoolean("enableDebugLogging", isDebugLoggingEnabled)
editor.putBoolean("enableSensitiveLogging", isSensitiveDebugLoggingEnabled)
editor.putString("backgroundOperations", K9.backgroundOps.name)
editor.putEnum("backgroundOperations", backgroundOps)
editor.putBoolean("animations", isShowAnimations)
editor.putBoolean("gesturesEnabled", isGesturesEnabled)
editor.putBoolean("useVolumeKeysForNavigation", isUseVolumeKeysForNavigation)
@ -526,9 +495,9 @@ object K9 : KoinComponent {
editor.putBoolean("hideTimeZone", isHideTimeZone)
editor.putString("language", k9Language)
editor.putInt("theme", k9Theme.ordinal)
editor.putInt("messageViewTheme", k9MessageViewThemeSetting.ordinal)
editor.putInt("messageComposeTheme", k9ComposerThemeSetting.ordinal)
editor.putEnum("theme", k9Theme)
editor.putEnum("messageViewTheme", k9MessageViewThemeSetting)
editor.putEnum("messageComposeTheme", k9ComposerThemeSetting)
editor.putBoolean("fixedMessageViewTheme", isFixedMessageViewTheme)
editor.putBoolean("confirmDelete", isConfirmDelete)
@ -538,7 +507,7 @@ object K9 : KoinComponent {
editor.putBoolean("confirmDeleteFromNotification", isConfirmDeleteFromNotification)
editor.putBoolean("confirmMarkAllRead", isConfirmMarkAllRead)
editor.putString("sortTypeEnum", sortType.name)
editor.putEnum("sortTypeEnum", sortType)
editor.putBoolean("sortAscending", sortAscending[sortType] ?: false)
editor.putString("notificationHideSubject", notificationHideSubject.toString())
@ -547,7 +516,7 @@ object K9 : KoinComponent {
editor.putBoolean("useBackgroundAsUnreadIndicator", isUseBackgroundAsUnreadIndicator)
editor.putBoolean("threadedView", isThreadedViewEnabled)
editor.putString("splitViewMode", splitViewMode.name)
editor.putEnum("splitViewMode", splitViewMode)
editor.putBoolean("colorizeMissingContactPictures", isColorizeMissingContactPictures)
editor.putBoolean("messageViewArchiveActionVisible", isMessageViewArchiveActionVisible)
@ -582,6 +551,23 @@ object K9 : KoinComponent {
}.execute()
}
private inline fun <reified T : Enum<T>> Storage.getEnum(key: String, defaultValue: T): T {
return try {
val value = getString(key, null)
if (value != null) {
enumValueOf(value)
} else {
defaultValue
}
} catch (e: Exception) {
Timber.e("Couldn't read setting '%s'. Using default value instead.", key)
defaultValue
}
}
private fun <T : Enum<T>> StorageEditor.putEnum(key: String, value: T) {
putString(key, value.name)
}
const val LOCAL_UID_PREFIX = "K9LOCAL:"
@ -613,12 +599,6 @@ object K9 : KoinComponent {
const val BOOT_RECEIVER_WAKE_LOCK_TIMEOUT = 60000
/**
* Possible values for the different theme settings.
*
* **Important:**
* Do not change the order of the items! The ordinal value (position) is used when saving the settings.
*/
enum class Theme {
LIGHT,
DARK,

View file

@ -456,17 +456,11 @@ public class GlobalSettings {
@Override
public K9.Theme fromString(String value) throws InvalidSettingValueException {
try {
Integer theme = Integer.parseInt(value);
if (theme == K9.Theme.LIGHT.ordinal() ||
// We used to store the resource ID of the theme in the preference storage,
// but don't use the database upgrade mechanism to update the values. So
// we have to deal with the old format here.
theme == android.R.style.Theme_Light) {
return K9.Theme.LIGHT;
} else if (theme == K9.Theme.DARK.ordinal() || theme == android.R.style.Theme) {
return K9.Theme.DARK;
K9.Theme theme = Theme.valueOf(value);
if (theme == K9.Theme.LIGHT || theme == K9.Theme.DARK) {
return theme;
}
} catch (NumberFormatException e) { /* do nothing */ }
} catch (IllegalArgumentException e) { /* do nothing */ }
throw new InvalidSettingValueException();
}
@ -496,7 +490,7 @@ public class GlobalSettings {
@Override
public String toString(K9.Theme value) {
return Integer.toString(value.ordinal());
return value.name();
}
}
@ -510,13 +504,8 @@ public class GlobalSettings {
@Override
public K9.Theme fromString(String value) throws InvalidSettingValueException {
try {
Integer theme = Integer.parseInt(value);
if (theme == K9.Theme.USE_GLOBAL.ordinal()) {
return K9.Theme.USE_GLOBAL;
}
return super.fromString(value);
} catch (NumberFormatException e) {
return K9.Theme.valueOf(value);
} catch (IllegalArgumentException e) {
throw new InvalidSettingValueException();
}
}

View file

@ -21,7 +21,7 @@ import timber.log.Timber;
public class K9StoragePersister implements StoragePersister {
private static final int DB_VERSION = 6;
private static final int DB_VERSION = 7;
private static final String DB_NAME = "preferences_storage";
private final Context context;

View file

@ -0,0 +1,54 @@
package com.fsck.k9.preferences.migrations
import android.database.sqlite.SQLiteDatabase
/**
* Rewrite settings to use enum names instead of ordinals.
*/
class StorageMigrationTo7(
private val db: SQLiteDatabase,
private val migrationsHelper: StorageMigrationsHelper
) {
fun rewriteEnumOrdinalsToNames() {
rewriteTheme()
rewriteMessageViewTheme()
rewriteMessageComposeTheme()
}
private fun rewriteTheme() {
val theme = migrationsHelper.readValue(db, "theme")?.toInt()
val newTheme = if (theme == THEME_ORDINAL_DARK) {
THEME_DARK
} else {
THEME_LIGHT
}
migrationsHelper.writeValue(db, "theme", newTheme)
}
private fun rewriteMessageViewTheme() {
rewriteScreenTheme("messageViewTheme")
}
private fun rewriteMessageComposeTheme() {
rewriteScreenTheme("messageComposeTheme")
}
private fun rewriteScreenTheme(key: String) {
val newTheme = when (migrationsHelper.readValue(db, key)?.toInt()) {
THEME_ORDINAL_DARK -> THEME_DARK
THEME_ORDINAL_USE_GLOBAL -> THEME_USE_GLOBAL
else -> THEME_LIGHT
}
migrationsHelper.writeValue(db, key, newTheme)
}
companion object {
private const val THEME_ORDINAL_DARK = 1
private const val THEME_ORDINAL_USE_GLOBAL = 2
private const val THEME_LIGHT = "LIGHT"
private const val THEME_DARK = "DARK"
private const val THEME_USE_GLOBAL = "USE_GLOBAL"
}
}

View file

@ -12,5 +12,6 @@ internal object StorageMigrations {
if (oldVersion <= 3) StorageMigrationTo4(db, migrationsHelper).insertSpecialFolderSelectionValues()
if (oldVersion <= 4) StorageMigrationTo5(db, migrationsHelper).fixMailCheckFrequencies()
if (oldVersion <= 5) StorageMigrationTo6(db, migrationsHelper).performLegacyMigrations()
if (oldVersion <= 6) StorageMigrationTo7(db, migrationsHelper).rewriteEnumOrdinalsToNames()
}
}