diff --git a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/GeneralSettings.kt b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/GeneralSettings.kt index 3ae144259a7..16c50fe669a 100644 --- a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/GeneralSettings.kt +++ b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/GeneralSettings.kt @@ -81,3 +81,9 @@ enum class LockScreenNotificationVisibility { APP_NAME, NOTHING, } + +enum class AnimationPreference { + ON, + OFF, + FOLLOW_SYSTEM, +} diff --git a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/display/visualSettings/DisplayVisualSettings.kt b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/display/visualSettings/DisplayVisualSettings.kt index 67f59f444f2..c9ce03da823 100644 --- a/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/display/visualSettings/DisplayVisualSettings.kt +++ b/core/preference/api/src/commonMain/kotlin/net/thunderbird/core/preference/display/visualSettings/DisplayVisualSettings.kt @@ -1,11 +1,12 @@ package net.thunderbird.core.preference.display.visualSettings +import net.thunderbird.core.preference.AnimationPreference import net.thunderbird.core.preference.BodyContentType import net.thunderbird.core.preference.display.visualSettings.message.list.DisplayMessageListSettings const val DISPLAY_SETTINGS_DEFAULT_IS_USE_MESSAGE_VIEW_FIXED_WIDTH_FONT = false const val DISPLAY_SETTINGS_DEFAULT_IS_AUTO_FIT_WIDTH = true -const val DISPLAY_SETTINGS_DEFAULT_IS_SHOW_ANIMATION = true +val DISPLAY_SETTINGS_DEFAULT_ANIMATION_PREFERENCE = AnimationPreference.FOLLOW_SYSTEM val DISPLAY_SETTINGS_DEFAULT_BODY_CONTENT_TYPE = BodyContentType.TEXT_HTML const val DISPLAY_SETTINGS_DEFAULT_DRAWER_EXPAND_ALL_FOLDER = false const val DISPLAY_SETTINGS_DEFAULT_MESSAGE_VIEW_ARCHIVE_ACTION_VISIBLE = false @@ -15,7 +16,7 @@ const val DISPLAY_SETTINGS_DEFAULT_MESSAGE_VIEW_COPY_ACTION_VISIBLE = false const val DISPLAY_SETTINGS_DEFAULT_MESSAGE_VIEW_SPAM_ACTION_VISIBLE = false data class DisplayVisualSettings( - val isShowAnimations: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_SHOW_ANIMATION, + val animationPreference: AnimationPreference = DISPLAY_SETTINGS_DEFAULT_ANIMATION_PREFERENCE, val isUseMessageViewFixedWidthFont: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_USE_MESSAGE_VIEW_FIXED_WIDTH_FONT, val isAutoFitWidth: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_AUTO_FIT_WIDTH, val bodyContentType: BodyContentType = DISPLAY_SETTINGS_DEFAULT_BODY_CONTENT_TYPE, diff --git a/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/display/visualSettings/DefaultDisplayVisualSettingsPreferenceManager.kt b/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/display/visualSettings/DefaultDisplayVisualSettingsPreferenceManager.kt index 594129673bb..4b482bbda12 100644 --- a/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/display/visualSettings/DefaultDisplayVisualSettingsPreferenceManager.kt +++ b/core/preference/impl/src/commonMain/kotlin/net/thunderbird/core/preference/display/visualSettings/DefaultDisplayVisualSettingsPreferenceManager.kt @@ -65,9 +65,9 @@ class DefaultDisplayVisualSettingsPreferenceManager( KEY_AUTO_FIT_WIDTH, DISPLAY_SETTINGS_DEFAULT_IS_AUTO_FIT_WIDTH, ), - isShowAnimations = storage.getBoolean( + animationPreference = storage.getEnumOrDefault( KEY_ANIMATION, - DISPLAY_SETTINGS_DEFAULT_IS_SHOW_ANIMATION, + DISPLAY_SETTINGS_DEFAULT_ANIMATION_PREFERENCE, ), bodyContentType = storage.getEnumOrDefault( KEY_MESSAGE_VIEW_BODY_CONTENT_TYPE, @@ -103,7 +103,7 @@ class DefaultDisplayVisualSettingsPreferenceManager( logger.debug(TAG) { "writeConfig() called with: config = $config" } scope.launch(ioDispatcher) { mutex.withLock { - storageEditor.putBoolean(KEY_ANIMATION, config.isShowAnimations) + storageEditor.putEnum(KEY_ANIMATION, config.animationPreference) storageEditor.putBoolean( KEY_MESSAGE_VIEW_FIXED_WIDTH_FONT, config.isUseMessageViewFixedWidthFont, diff --git a/core/ui/animation/manager/build.gradle.kts b/core/ui/animation/manager/build.gradle.kts new file mode 100644 index 00000000000..f6810eb26cc --- /dev/null +++ b/core/ui/animation/manager/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id(ThunderbirdPlugins.Library.android) +} + +android { + namespace = "net.thunderbird.core.ui.animation.manager" +} + +dependencies { + implementation(projects.core.preference.api) +} diff --git a/core/ui/animation/manager/src/main/kotlin/net/thunderbird/core/ui/animation/manager/AnimationManager.kt b/core/ui/animation/manager/src/main/kotlin/net/thunderbird/core/ui/animation/manager/AnimationManager.kt new file mode 100644 index 00000000000..1605adaf7f1 --- /dev/null +++ b/core/ui/animation/manager/src/main/kotlin/net/thunderbird/core/ui/animation/manager/AnimationManager.kt @@ -0,0 +1,26 @@ +package net.thunderbird.core.ui.animation.manager + +import android.animation.ValueAnimator +import android.os.Build +import net.thunderbird.core.preference.AnimationPreference +import net.thunderbird.core.preference.display.visualSettings.DisplayVisualSettingsPreferenceManager + +interface AnimationManager { + fun shouldShowAnimations(): Boolean +} + +class DefaultAnimationManager( + private val visualSettingsPreferenceManager: DisplayVisualSettingsPreferenceManager, +) : AnimationManager { + override fun shouldShowAnimations(): Boolean { + return when (visualSettingsPreferenceManager.getConfig().animationPreference) { + AnimationPreference.ON -> true + AnimationPreference.OFF -> false + AnimationPreference.FOLLOW_SYSTEM -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + ValueAnimator.areAnimatorsEnabled() + } else { + true + } + } + } +} diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsDescriptions.java b/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsDescriptions.java index 6de2a3f845b..f6eb86ef6e1 100644 --- a/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsDescriptions.java +++ b/legacy/core/src/main/java/com/fsck/k9/preferences/GeneralSettingsDescriptions.java @@ -30,9 +30,11 @@ import com.fsck.k9.preferences.upgrader.GeneralSettingsUpgraderTo69; import com.fsck.k9.preferences.upgrader.GeneralSettingsUpgraderTo79; import com.fsck.k9.preferences.upgrader.GeneralSettingsUpgraderTo89; +import com.fsck.k9.preferences.upgrader.GeneralSettingsUpgraderTo111; import net.thunderbird.core.android.account.AccountDefaultsProvider; import net.thunderbird.core.android.account.SortType; import net.thunderbird.core.common.action.SwipeAction; +import net.thunderbird.core.preference.AnimationPreference; import net.thunderbird.core.preference.AppTheme; import net.thunderbird.core.preference.BackgroundOps; import net.thunderbird.core.preference.GeneralSettingsManager; @@ -42,6 +44,7 @@ import net.thunderbird.core.preference.SplitViewMode; import net.thunderbird.core.preference.SubTheme; import net.thunderbird.core.preference.display.coreSettings.DisplayCoreSettingsKt; +import net.thunderbird.core.preference.display.visualSettings.DisplayVisualSettingsKt; import net.thunderbird.core.preference.display.visualSettings.message.list.MessageListDateTimeFormat; import net.thunderbird.core.preference.interaction.PostRemoveNavigation; import net.thunderbird.core.preference.network.NetworkSettingsKt; @@ -57,7 +60,6 @@ import static net.thunderbird.core.preference.display.miscSettings.DisplayMiscSettingsKt.DISPLAY_SETTINGS_DEFAULT_SHOW_RECENT_CHANGES; import static net.thunderbird.core.preference.display.visualSettings.DisplayVisualSettingsKt.DISPLAY_SETTINGS_DEFAULT_IS_AUTO_FIT_WIDTH; import static net.thunderbird.core.preference.display.visualSettings.message.list.DisplayMessageListSettingsKt.MESSAGE_LIST_SETTINGS_DEFAULT_IS_CHANGE_CONTACT_NAME_COLOR; -import static net.thunderbird.core.preference.display.visualSettings.DisplayVisualSettingsKt.DISPLAY_SETTINGS_DEFAULT_IS_SHOW_ANIMATION; import static net.thunderbird.core.preference.display.visualSettings.message.list.DisplayMessageListSettingsKt.MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CONTACT_NAME; import static net.thunderbird.core.preference.display.visualSettings.message.list.DisplayMessageListSettingsKt.MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CONTACT_PICTURE; import static net.thunderbird.core.preference.display.visualSettings.message.list.DisplayMessageListSettingsKt.MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CORRESPONDENT_NAMES; @@ -85,7 +87,8 @@ class GeneralSettingsDescriptions { */ s.put("animations", Settings.versions( - new V(1, new BooleanSetting(DISPLAY_SETTINGS_DEFAULT_IS_SHOW_ANIMATION)) + new V(1, new BooleanSetting(true)), + new V(111, new EnumSetting<>(AnimationPreference.class, AnimationPreference.FOLLOW_SYSTEM)) )); s.put("backgroundOperations", Settings.versions( new V(1, new EnumSetting<>(BackgroundOps.class, BackgroundOps.WHEN_CHECKED_AUTO_SYNC)), @@ -361,6 +364,7 @@ class GeneralSettingsDescriptions { u.put(69, new GeneralSettingsUpgraderTo69()); u.put(79, new GeneralSettingsUpgraderTo79()); u.put(89, new GeneralSettingsUpgraderTo89()); + u.put(111, new GeneralSettingsUpgraderTo111()); UPGRADERS = Collections.unmodifiableMap(u); } diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/Settings.java b/legacy/core/src/main/java/com/fsck/k9/preferences/Settings.java index 3a740feea59..ade2857250d 100644 --- a/legacy/core/src/main/java/com/fsck/k9/preferences/Settings.java +++ b/legacy/core/src/main/java/com/fsck/k9/preferences/Settings.java @@ -35,7 +35,7 @@ public class Settings { * * @see SettingsExporter */ - public static final int VERSION = 110; + public static final int VERSION = 111; static Map validate(int version, Map>> settings, Map importedSettings, boolean useDefaultValues) { diff --git a/legacy/core/src/main/java/com/fsck/k9/preferences/upgrader/GeneralSettingsUpgraderTo111.java b/legacy/core/src/main/java/com/fsck/k9/preferences/upgrader/GeneralSettingsUpgraderTo111.java new file mode 100644 index 00000000000..fd0435b0bbd --- /dev/null +++ b/legacy/core/src/main/java/com/fsck/k9/preferences/upgrader/GeneralSettingsUpgraderTo111.java @@ -0,0 +1,25 @@ +package com.fsck.k9.preferences.upgrader; + + +import java.util.Map; + +import com.fsck.k9.preferences.SettingsUpgrader; +import net.thunderbird.core.preference.AnimationPreference; + + +/** + * Convert animations from boolean to {@link AnimationPreference} enum. + * + * {@code true} maps to {@link AnimationPreference#ON}, {@code false} maps to {@link AnimationPreference#OFF}. + */ +public class GeneralSettingsUpgraderTo111 implements SettingsUpgrader { + + @Override + public void upgrade(Map settings) { + Object animations = settings.get("animations"); + if (animations instanceof Boolean) { + boolean value = (Boolean) animations; + settings.put("animations", value ? AnimationPreference.ON : AnimationPreference.OFF); + } + } +} diff --git a/legacy/core/src/main/res/values/arrays_general_settings_values.xml b/legacy/core/src/main/res/values/arrays_general_settings_values.xml index 28137a771f7..09c7515dee2 100644 --- a/legacy/core/src/main/res/values/arrays_general_settings_values.xml +++ b/legacy/core/src/main/res/values/arrays_general_settings_values.xml @@ -152,6 +152,12 @@ follow_system + + ON + OFF + FOLLOW_SYSTEM + + light dark diff --git a/legacy/core/src/test/java/com/fsck/k9/preferences/upgrader/GeneralSettingsUpgraderTo111Test.kt b/legacy/core/src/test/java/com/fsck/k9/preferences/upgrader/GeneralSettingsUpgraderTo111Test.kt new file mode 100644 index 00000000000..52156c4b8da --- /dev/null +++ b/legacy/core/src/test/java/com/fsck/k9/preferences/upgrader/GeneralSettingsUpgraderTo111Test.kt @@ -0,0 +1,52 @@ +package com.fsck.k9.preferences.upgrader + +import assertk.assertThat +import assertk.assertions.doesNotContainKey +import assertk.assertions.isEqualTo +import kotlin.test.Test +import net.thunderbird.core.preference.AnimationPreference + +class GeneralSettingsUpgraderTo111Test { + + private val upgrader = GeneralSettingsUpgraderTo111() + + @Test + fun `should convert animations=true to ON`() { + val settings = mutableMapOf(ANIMATIONS_KEY to true) + + upgrader.upgrade(settings) + + assertThat(settings[ANIMATIONS_KEY]).isEqualTo(AnimationPreference.ON) + } + + @Test + fun `should convert animations=false to OFF`() { + val settings = mutableMapOf(ANIMATIONS_KEY to false) + + upgrader.upgrade(settings) + + assertThat(settings[ANIMATIONS_KEY]).isEqualTo(AnimationPreference.OFF) + } + + @Test + fun `should not insert animations key when missing`() { + val settings = mutableMapOf() + + upgrader.upgrade(settings) + + assertThat(settings).doesNotContainKey(ANIMATIONS_KEY) + } + + @Test + fun `should leave existing AnimationPreference value unchanged`() { + val settings = mutableMapOf(ANIMATIONS_KEY to AnimationPreference.FOLLOW_SYSTEM) + + upgrader.upgrade(settings) + + assertThat(settings[ANIMATIONS_KEY]).isEqualTo(AnimationPreference.FOLLOW_SYSTEM) + } + + private companion object { + const val ANIMATIONS_KEY = "animations" + } +} diff --git a/legacy/storage/src/main/java/com/fsck/k9/preferences/K9StoragePersister.java b/legacy/storage/src/main/java/com/fsck/k9/preferences/K9StoragePersister.java index ccd0bcda357..247f62fa95f 100644 --- a/legacy/storage/src/main/java/com/fsck/k9/preferences/K9StoragePersister.java +++ b/legacy/storage/src/main/java/com/fsck/k9/preferences/K9StoragePersister.java @@ -23,7 +23,7 @@ import net.thunderbird.core.preference.storage.StorageUpdater; public class K9StoragePersister implements StoragePersister { - private static final int DB_VERSION = 29; + private static final int DB_VERSION = 30; private static final String DB_NAME = "preferences_storage"; private final Context context; diff --git a/legacy/storage/src/main/java/com/fsck/k9/preferences/migration/StorageMigrationTo30.kt b/legacy/storage/src/main/java/com/fsck/k9/preferences/migration/StorageMigrationTo30.kt new file mode 100644 index 00000000000..f5982e8ec22 --- /dev/null +++ b/legacy/storage/src/main/java/com/fsck/k9/preferences/migration/StorageMigrationTo30.kt @@ -0,0 +1,26 @@ +package com.fsck.k9.preferences.migration + +import android.database.sqlite.SQLiteDatabase + +private const val ANIMATION_KEY = "animations" + +/** + * Migrate the "animations" setting from boolean string to AnimationPreference enum name. + * + * - "true" -> "ON" (user explicitly enabled animations) + * - "false" -> "OFF" (user explicitly disabled animations) + * - missing -> no change (new default FOLLOW_SYSTEM will apply) + */ +class StorageMigrationTo30( + private val db: SQLiteDatabase, + private val migrationsHelper: StorageMigrationHelper, +) { + fun migrateAnimationSetting() { + val currentValue = migrationsHelper.readValue(db, ANIMATION_KEY) + when (currentValue) { + "true" -> migrationsHelper.writeValue(db, ANIMATION_KEY, "ON") + "false" -> migrationsHelper.writeValue(db, ANIMATION_KEY, "OFF") + // If missing or already migrated, do nothing + } + } +} diff --git a/legacy/storage/src/main/java/com/fsck/k9/preferences/migration/StorageMigrations.kt b/legacy/storage/src/main/java/com/fsck/k9/preferences/migration/StorageMigrations.kt index b47081eb249..b6dc4f600fd 100644 --- a/legacy/storage/src/main/java/com/fsck/k9/preferences/migration/StorageMigrations.kt +++ b/legacy/storage/src/main/java/com/fsck/k9/preferences/migration/StorageMigrations.kt @@ -36,5 +36,6 @@ internal object StorageMigrations { if (oldVersion < 27) StorageMigrationTo27(db, migrationsHelper).addAvatarMonogram() if (oldVersion < 28) StorageMigrationTo28(db, migrationsHelper).ensureAvatarSet() if (oldVersion < 29) StorageMigrationTo29(db, migrationsHelper).renameAutoSelectFolderPreference() + if (oldVersion < 30) StorageMigrationTo30(db, migrationsHelper).migrateAnimationSetting() } } diff --git a/legacy/storage/src/test/java/com/fsck/k9/preferences/migration/StorageMigrationTo30Test.kt b/legacy/storage/src/test/java/com/fsck/k9/preferences/migration/StorageMigrationTo30Test.kt new file mode 100644 index 00000000000..a8368c972da --- /dev/null +++ b/legacy/storage/src/test/java/com/fsck/k9/preferences/migration/StorageMigrationTo30Test.kt @@ -0,0 +1,78 @@ +package com.fsck.k9.preferences.migration + +import assertk.assertThat +import assertk.assertions.doesNotContainKey +import assertk.assertions.isEqualTo +import assertk.assertions.key +import com.fsck.k9.preferences.createPreferencesDatabase +import kotlin.test.Test +import net.thunderbird.core.logging.legacy.Log +import net.thunderbird.core.logging.testing.TestLogger +import org.junit.After +import org.junit.Before +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class StorageMigrationTo30Test { + private val database = createPreferencesDatabase() + private val migrationHelper = DefaultStorageMigrationHelper() + private val migration = StorageMigrationTo30(database, migrationHelper) + + @Before + fun setUp() { + Log.logger = TestLogger() + } + + @After + fun tearDown() { + database.close() + } + + @Test + fun `migration should convert animations=true to ON`() { + migrationHelper.insertValue(database, ANIMATIONS_KEY, "true") + + migration.migrateAnimationSetting() + + assertThat(migrationHelper.readAllValues(database)).key(ANIMATIONS_KEY).isEqualTo("ON") + } + + @Test + fun `migration should convert animations=false to OFF`() { + migrationHelper.insertValue(database, ANIMATIONS_KEY, "false") + + migration.migrateAnimationSetting() + + assertThat(migrationHelper.readAllValues(database)).key(ANIMATIONS_KEY).isEqualTo("OFF") + } + + @Test + fun `migration should not insert animations key when missing`() { + migration.migrateAnimationSetting() + + assertThat(migrationHelper.readAllValues(database)).doesNotContainKey(ANIMATIONS_KEY) + } + + @Test + fun `migration should leave already migrated ON value unchanged`() { + migrationHelper.insertValue(database, ANIMATIONS_KEY, "ON") + + migration.migrateAnimationSetting() + + assertThat(migrationHelper.readAllValues(database)).key(ANIMATIONS_KEY).isEqualTo("ON") + } + + @Test + fun `migration should leave already migrated OFF value unchanged`() { + migrationHelper.insertValue(database, ANIMATIONS_KEY, "OFF") + + migration.migrateAnimationSetting() + + assertThat(migrationHelper.readAllValues(database)).key(ANIMATIONS_KEY).isEqualTo("OFF") + } + + private companion object { + const val ANIMATIONS_KEY = "animations" + } +} diff --git a/legacy/ui/base/build.gradle.kts b/legacy/ui/base/build.gradle.kts index 607e8c9b3e4..9e0e6708ce0 100644 --- a/legacy/ui/base/build.gradle.kts +++ b/legacy/ui/base/build.gradle.kts @@ -6,6 +6,7 @@ dependencies { implementation(projects.legacy.core) api(projects.core.ui.theme.manager) + api(projects.core.ui.animation.manager) api(libs.androidx.appcompat) api(libs.androidx.activity) diff --git a/legacy/ui/base/src/main/java/com/fsck/k9/ui/base/KoinModule.kt b/legacy/ui/base/src/main/java/com/fsck/k9/ui/base/KoinModule.kt index bf5f3fff9cb..aceebcd6357 100644 --- a/legacy/ui/base/src/main/java/com/fsck/k9/ui/base/KoinModule.kt +++ b/legacy/ui/base/src/main/java/com/fsck/k9/ui/base/KoinModule.kt @@ -1,6 +1,8 @@ package com.fsck.k9.ui.base import com.fsck.k9.ui.base.locale.SystemLocaleManager +import net.thunderbird.core.ui.animation.manager.AnimationManager +import net.thunderbird.core.ui.animation.manager.DefaultAnimationManager import net.thunderbird.core.ui.theme.manager.ThemeManager import org.koin.core.qualifier.named import org.koin.dsl.bind @@ -16,6 +18,9 @@ val uiBaseModule = module { appCoroutineScope = get(named("AppCoroutineScope")), ) } bind ThemeManagerApi::class + single { + DefaultAnimationManager(visualSettingsPreferenceManager = get()) + } single { AppLanguageManager(systemLocaleManager = get(), displayCoreSettingsPreferenceManager = get()) } single { SystemLocaleManager(context = get()) } } diff --git a/legacy/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt b/legacy/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt index f85704b2ee8..7254d4037a2 100644 --- a/legacy/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt +++ b/legacy/ui/legacy/src/main/java/com/fsck/k9/ui/settings/general/GeneralSettingsDataStore.kt @@ -8,6 +8,7 @@ import com.fsck.k9.job.K9JobManager import com.fsck.k9.ui.base.AppLanguageManager import net.thunderbird.core.common.action.SwipeAction import net.thunderbird.core.common.action.SwipeActions +import net.thunderbird.core.preference.AnimationPreference import net.thunderbird.core.preference.AppTheme import net.thunderbird.core.preference.BackgroundOps import net.thunderbird.core.preference.BodyContentType @@ -42,7 +43,6 @@ class GeneralSettingsDataStore( val messageListSettings = visualSettings.messageListSettings return when (key) { "fixed_message_view_theme" -> coreSettings.fixedMessageViewTheme - "animations" -> visualSettings.isShowAnimations "show_unified_inbox" -> inboxSettings.isShowUnifiedInbox "show_starred_count" -> inboxSettings.isShowStarredCount "messagelist_stars" -> inboxSettings.isShowMessageListStars @@ -75,7 +75,6 @@ class GeneralSettingsDataStore( override fun putBoolean(key: String, value: Boolean) { when (key) { "fixed_message_view_theme" -> setFixedMessageViewTheme(value) - "animations" -> setIsShowAnimations(isShowAnimations = value) "drawerExpandAllFolder" -> setDrawerExpandAllFolder(drawerExpandAllFolder = value) "show_unified_inbox" -> setIsShowUnifiedInbox(value) "show_starred_count" -> setIsShowStarredCount(isShowStarredCount = value) @@ -148,6 +147,7 @@ class GeneralSettingsDataStore( return when (key) { "language" -> appLanguageManager.getAppLanguage() "theme" -> appThemeToString(coreSettings.appTheme) + "animations" -> animationPreferenceToString(visualSettings.animationPreference) "message_compose_theme" -> subThemeToString(coreSettings.messageComposeTheme) "messageViewTheme" -> subThemeToString(coreSettings.messageViewTheme) "messagelist_preview_lines" -> messageListSettings.previewLines.toString() @@ -188,6 +188,7 @@ class GeneralSettingsDataStore( } "theme" -> setTheme(value) + "animations" -> setAnimationPreference(stringToAnimationPreference(value)) "message_compose_theme" -> setMessageComposeTheme(value) "messageViewTheme" -> setMessageViewTheme(value) "messagelist_preview_lines" -> setMessageListPreviewLines(value.toInt()) @@ -428,13 +429,13 @@ class GeneralSettingsDataStore( } } - private fun setIsShowAnimations(isShowAnimations: Boolean) { + private fun setAnimationPreference(animationPreference: AnimationPreference) { skipSaveSettings = true generalSettingsManager.update { settings -> settings.copy( display = settings.display.copy( visualSettings = settings.display.visualSettings.copy( - isShowAnimations = isShowAnimations, + animationPreference = animationPreference, ), ), ) @@ -773,6 +774,19 @@ class GeneralSettingsDataStore( else -> throw AssertionError() } + private fun animationPreferenceToString(pref: AnimationPreference) = when (pref) { + AnimationPreference.ON -> "ON" + AnimationPreference.OFF -> "OFF" + AnimationPreference.FOLLOW_SYSTEM -> "FOLLOW_SYSTEM" + } + + private fun stringToAnimationPreference(value: String) = when (value) { + "ON" -> AnimationPreference.ON + "OFF" -> AnimationPreference.OFF + "FOLLOW_SYSTEM" -> AnimationPreference.FOLLOW_SYSTEM + else -> throw AssertionError() + } + private fun setBackgroundOps(value: String) { val newBackgroundOps = BackgroundOps.valueOf(value) if (newBackgroundOps != generalSettingsManager.getConfig().network.backgroundOps) { diff --git a/legacy/ui/legacy/src/main/java/com/fsck/k9/view/ViewSwitcher.java b/legacy/ui/legacy/src/main/java/com/fsck/k9/view/ViewSwitcher.java index 2008a1a4389..bb72b68cc41 100644 --- a/legacy/ui/legacy/src/main/java/com/fsck/k9/view/ViewSwitcher.java +++ b/legacy/ui/legacy/src/main/java/com/fsck/k9/view/ViewSwitcher.java @@ -1,15 +1,15 @@ package com.fsck.k9.view; -import app.k9mail.legacy.di.DI; -import net.thunderbird.core.preference.GeneralSettingsManager; - import android.content.Context; import android.util.AttributeSet; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.widget.ViewAnimator; +import app.k9mail.legacy.di.DI; +import net.thunderbird.core.ui.animation.manager.AnimationManager; + /** * A {@link ViewAnimator} that animates between two child views using different animations depending on which view is @@ -22,7 +22,7 @@ public class ViewSwitcher extends ViewAnimator implements AnimationListener { private Animation mSecondOutAnimation; private OnSwitchCompleteListener mListener; - private GeneralSettingsManager generalSettingsManager = DI.get(GeneralSettingsManager.class); + private AnimationManager animationManager = DI.get(AnimationManager.class); public ViewSwitcher(Context context) { @@ -56,7 +56,7 @@ public void showSecondView() { } private void setupAnimations(Animation in, Animation out) { - if (generalSettingsManager.getConfig().getDisplay().getVisualSettings().isShowAnimations()) { + if (animationManager.shouldShowAnimations()) { setInAnimation(in); setOutAnimation(out); out.setAnimationListener(this); @@ -67,7 +67,7 @@ private void setupAnimations(Animation in, Animation out) { } private void handleSwitchCompleteCallback() { - if (!generalSettingsManager.getConfig().getDisplay().getVisualSettings().isShowAnimations()) { + if (!animationManager.shouldShowAnimations()) { onAnimationEnd(null); } } @@ -125,12 +125,12 @@ public void onAnimationStart(Animation animation) { // unused } - public GeneralSettingsManager getGeneralSettingsManager() { - return generalSettingsManager; + public AnimationManager getAnimationManager() { + return animationManager; } - public void setGeneralSettingsManager(GeneralSettingsManager generalSettingsManager) { - this.generalSettingsManager = generalSettingsManager; + public void setAnimationManager(AnimationManager animationManager) { + this.animationManager = animationManager; } public interface OnSwitchCompleteListener { diff --git a/legacy/ui/legacy/src/main/res/values/arrays_general_settings_strings.xml b/legacy/ui/legacy/src/main/res/values/arrays_general_settings_strings.xml index 54e86614d0a..5aff7896b0f 100644 --- a/legacy/ui/legacy/src/main/res/values/arrays_general_settings_strings.xml +++ b/legacy/ui/legacy/src/main/res/values/arrays_general_settings_strings.xml @@ -95,6 +95,12 @@ @string/setting_theme_follow_system + + @string/animation_setting_on + @string/animation_setting_off + @string/animation_setting_follow_system + + @string/setting_theme_light @string/setting_theme_dark diff --git a/legacy/ui/legacy/src/main/res/values/strings.xml b/legacy/ui/legacy/src/main/res/values/strings.xml index f76a11b1b88..d1a54368ad2 100644 --- a/legacy/ui/legacy/src/main/res/values/strings.xml +++ b/legacy/ui/legacy/src/main/res/values/strings.xml @@ -700,7 +700,9 @@ 1000 folders Animation - Use gaudy visual effects + On + Off + Use system default Volume key navigation Navigate between messages using the volume keys in message view diff --git a/legacy/ui/legacy/src/main/res/xml/general_settings.xml b/legacy/ui/legacy/src/main/res/xml/general_settings.xml index 9287270ec65..54e1776ec18 100644 --- a/legacy/ui/legacy/src/main/res/xml/general_settings.xml +++ b/legacy/ui/legacy/src/main/res/xml/general_settings.xml @@ -192,9 +192,12 @@ - diff --git a/settings.gradle.kts b/settings.gradle.kts index 68d5bea77d2..f43a5e16102 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -211,6 +211,7 @@ include( ":core:ui:navigation", ":core:ui:theme:api", ":core:ui:theme:manager", + ":core:ui:animation:manager", ) include(