From 60cfa99f17d91f8d29c7154e79e612308892a1f8 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Mon, 11 Dec 2023 14:41:36 +0100 Subject: [PATCH] refactor: Use AppTheme enum exclusively (#311) Previous code treated the app theme as a mix of strings and enums. Convert to exclusively use the `AppTheme` enum to improve type safety. --- app/src/main/java/app/pachli/BaseActivity.kt | 8 +++----- .../main/java/app/pachli/PachliApplication.kt | 5 ++--- .../components/compose/ComposeActivity.kt | 8 +++----- .../preference/PreferencesActivity.kt | 5 ++--- .../preference/PreferencesFragment.kt | 4 ++-- .../main/java/app/pachli/util/ThemeUtils.kt | 19 ++++++------------- app/src/main/res/values/string-arrays.xml | 2 ++ .../core/preferences/SettingsConstants.kt | 17 ++++++++++++++++- 8 files changed, 36 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/app/pachli/BaseActivity.kt b/app/src/main/java/app/pachli/BaseActivity.kt index d3a69bc22..eae2f5c79 100644 --- a/app/src/main/java/app/pachli/BaseActivity.kt +++ b/app/src/main/java/app/pachli/BaseActivity.kt @@ -37,15 +37,13 @@ import app.pachli.adapter.AccountSelectionAdapter import app.pachli.core.accounts.AccountManager import app.pachli.core.database.model.AccountEntity import app.pachli.core.navigation.LoginActivityIntent +import app.pachli.core.preferences.AppTheme import app.pachli.core.preferences.PrefKeys -import app.pachli.core.preferences.PrefKeys.APP_THEME import app.pachli.core.preferences.SharedPreferencesRepository import app.pachli.interfaces.AccountSelectionListener import app.pachli.interfaces.PermissionRequester -import app.pachli.util.APP_THEME_DEFAULT import app.pachli.util.EmbeddedFontFamily import app.pachli.util.EmbeddedFontFamily.Companion.from -import app.pachli.util.THEME_BLACK import com.google.android.material.color.MaterialColors import com.google.android.material.snackbar.Snackbar import dagger.hilt.EntryPoint @@ -84,9 +82,9 @@ abstract class BaseActivity : AppCompatActivity() { super.onCreate(savedInstanceState) // Set the theme from preferences - val theme = sharedPreferencesRepository.getString(APP_THEME, APP_THEME_DEFAULT) + val theme = AppTheme.from(sharedPreferencesRepository) Timber.d("activeTheme: %s", theme) - if (theme == THEME_BLACK) { + if (theme == AppTheme.BLACK) { setTheme(R.style.Theme_Pachli_Black) } diff --git a/app/src/main/java/app/pachli/PachliApplication.kt b/app/src/main/java/app/pachli/PachliApplication.kt index 341a0eae7..d492601e3 100644 --- a/app/src/main/java/app/pachli/PachliApplication.kt +++ b/app/src/main/java/app/pachli/PachliApplication.kt @@ -24,12 +24,11 @@ import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.PeriodicWorkRequestBuilder import androidx.work.WorkManager import app.pachli.components.notifications.createWorkerNotificationChannel +import app.pachli.core.preferences.AppTheme import app.pachli.core.preferences.NEW_INSTALL_SCHEMA_VERSION import app.pachli.core.preferences.PrefKeys -import app.pachli.core.preferences.PrefKeys.APP_THEME import app.pachli.core.preferences.SCHEMA_VERSION import app.pachli.core.preferences.SharedPreferencesRepository -import app.pachli.util.APP_THEME_DEFAULT import app.pachli.util.LocaleManager import app.pachli.util.setAppNightMode import app.pachli.worker.PruneCacheWorker @@ -88,7 +87,7 @@ class PachliApplication : Application() { EmojiPackHelper.init(this, DefaultEmojiPackList.get(this), allowPackImports = false) // init night mode - val theme = sharedPreferencesRepository.getString(APP_THEME, APP_THEME_DEFAULT) + val theme = AppTheme.from(sharedPreferencesRepository) setAppNightMode(theme) localeManager.setLocale() diff --git a/app/src/main/java/app/pachli/components/compose/ComposeActivity.kt b/app/src/main/java/app/pachli/components/compose/ComposeActivity.kt index 87cd79cf4..558cf36f5 100644 --- a/app/src/main/java/app/pachli/components/compose/ComposeActivity.kt +++ b/app/src/main/java/app/pachli/components/compose/ComposeActivity.kt @@ -81,14 +81,12 @@ import app.pachli.core.navigation.ComposeActivityIntent.ComposeOptions.InitialCu import app.pachli.core.network.model.Attachment import app.pachli.core.network.model.Emoji import app.pachli.core.network.model.Status +import app.pachli.core.preferences.AppTheme import app.pachli.core.preferences.PrefKeys -import app.pachli.core.preferences.PrefKeys.APP_THEME import app.pachli.core.preferences.SharedPreferencesRepository import app.pachli.databinding.ActivityComposeBinding -import app.pachli.util.APP_THEME_DEFAULT import app.pachli.util.MentionSpan import app.pachli.util.PickMediaFiles -import app.pachli.util.THEME_BLACK import app.pachli.util.getInitialLanguages import app.pachli.util.getLocaleList import app.pachli.util.getMediaSize @@ -205,8 +203,8 @@ class ComposeActivity : activeAccount = accountManager.activeAccount ?: return - val theme = sharedPreferencesRepository.getString(APP_THEME, APP_THEME_DEFAULT) - if (theme == THEME_BLACK) { + val theme = AppTheme.from(sharedPreferencesRepository) + if (theme == AppTheme.BLACK) { setTheme(R.style.AppDialogActivityBlackTheme) } setContentView(binding.root) diff --git a/app/src/main/java/app/pachli/components/preference/PreferencesActivity.kt b/app/src/main/java/app/pachli/components/preference/PreferencesActivity.kt index c73808f70..bfdf2db99 100644 --- a/app/src/main/java/app/pachli/components/preference/PreferencesActivity.kt +++ b/app/src/main/java/app/pachli/components/preference/PreferencesActivity.kt @@ -30,11 +30,10 @@ import app.pachli.appstore.EventHub import app.pachli.core.navigation.MainActivityIntent import app.pachli.core.navigation.PreferencesActivityIntent import app.pachli.core.navigation.PreferencesActivityIntent.PreferenceScreen +import app.pachli.core.preferences.AppTheme import app.pachli.core.preferences.PrefKeys import app.pachli.core.preferences.PrefKeys.APP_THEME -import app.pachli.core.preferences.getNonNullString import app.pachli.databinding.ActivityPreferencesBinding -import app.pachli.util.APP_THEME_DEFAULT import app.pachli.util.setAppNightMode import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.filterNotNull @@ -102,7 +101,7 @@ class PreferencesActivity : sharedPreferencesRepository.changes.filterNotNull().collect { key -> when (key) { APP_THEME -> { - val theme = sharedPreferencesRepository.getNonNullString(APP_THEME, APP_THEME_DEFAULT) + val theme = AppTheme.from(sharedPreferencesRepository) Timber.d("activeTheme: %s", theme) setAppNightMode(theme) diff --git a/app/src/main/java/app/pachli/components/preference/PreferencesFragment.kt b/app/src/main/java/app/pachli/components/preference/PreferencesFragment.kt index ad15c2087..a0d4ee4bc 100644 --- a/app/src/main/java/app/pachli/components/preference/PreferencesFragment.kt +++ b/app/src/main/java/app/pachli/components/preference/PreferencesFragment.kt @@ -23,6 +23,7 @@ import app.pachli.R import app.pachli.core.accounts.AccountManager import app.pachli.core.network.model.Notification import app.pachli.core.preferences.AppTheme +import app.pachli.core.preferences.AppTheme.Companion.APP_THEME_DEFAULT import app.pachli.core.preferences.PrefKeys import app.pachli.settings.emojiPreference import app.pachli.settings.listPreference @@ -32,7 +33,6 @@ import app.pachli.settings.preferenceCategory import app.pachli.settings.sliderPreference import app.pachli.settings.switchPreference import app.pachli.updatecheck.UpdateNotificationFrequency -import app.pachli.util.APP_THEME_DEFAULT import app.pachli.util.LocaleManager import app.pachli.util.deserialize import app.pachli.util.makeIcon @@ -60,7 +60,7 @@ class PreferencesFragment : PreferenceFragmentCompat() { makePreferenceScreen { preferenceCategory(R.string.pref_title_appearance_settings) { listPreference { - setDefaultValue(APP_THEME_DEFAULT) + setDefaultValue(APP_THEME_DEFAULT.value) setEntries(R.array.app_theme_names) entryValues = AppTheme.stringValues() key = PrefKeys.APP_THEME diff --git a/app/src/main/java/app/pachli/util/ThemeUtils.kt b/app/src/main/java/app/pachli/util/ThemeUtils.kt index 2bed86cde..62749c1b7 100644 --- a/app/src/main/java/app/pachli/util/ThemeUtils.kt +++ b/app/src/main/java/app/pachli/util/ThemeUtils.kt @@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable import androidx.annotation.AttrRes import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.res.use +import app.pachli.core.preferences.AppTheme import com.google.android.material.color.MaterialColors /** @@ -31,13 +32,6 @@ import com.google.android.material.color.MaterialColors * the ability to do so is not supported in resource files. */ -const val THEME_NIGHT = "night" -const val THEME_DAY = "day" -const val THEME_BLACK = "black" -const val THEME_AUTO = "auto" -const val THEME_SYSTEM = "auto_system" -const val APP_THEME_DEFAULT = THEME_SYSTEM - fun getDimension(context: Context, @AttrRes attribute: Int): Int { return context.obtainStyledAttributes(intArrayOf(attribute)).use { array -> array.getDimensionPixelSize(0, -1) @@ -51,18 +45,17 @@ fun setDrawableTint(context: Context, drawable: Drawable, @AttrRes attribute: In ) } -fun setAppNightMode(flavor: String?) { +fun setAppNightMode(flavor: AppTheme) { when (flavor) { - THEME_NIGHT, THEME_BLACK -> AppCompatDelegate.setDefaultNightMode( + AppTheme.NIGHT, AppTheme.BLACK -> AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.MODE_NIGHT_YES, ) - THEME_DAY -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) - THEME_AUTO -> AppCompatDelegate.setDefaultNightMode( + AppTheme.DAY -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) + AppTheme.AUTO -> AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.MODE_NIGHT_AUTO_TIME, ) - THEME_SYSTEM -> AppCompatDelegate.setDefaultNightMode( + AppTheme.AUTO_SYSTEM -> AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, ) - else -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) } } diff --git a/app/src/main/res/values/string-arrays.xml b/app/src/main/res/values/string-arrays.xml index a4ee5d888..c0ee4c89a 100644 --- a/app/src/main/res/values/string-arrays.xml +++ b/app/src/main/res/values/string-arrays.xml @@ -1,6 +1,8 @@ + @string/app_them_dark @string/app_theme_light diff --git a/core/preferences/src/main/kotlin/app/pachli/core/preferences/SettingsConstants.kt b/core/preferences/src/main/kotlin/app/pachli/core/preferences/SettingsConstants.kt index a44f0f3ea..b15023f97 100644 --- a/core/preferences/src/main/kotlin/app/pachli/core/preferences/SettingsConstants.kt +++ b/core/preferences/src/main/kotlin/app/pachli/core/preferences/SettingsConstants.kt @@ -1,5 +1,11 @@ package app.pachli.core.preferences +/** + * Possible themes. + * + * The order of the values is important, and must be kept in sync with + * R.array.app_theme_names. + */ enum class AppTheme(val value: String) { NIGHT("night"), DAY("day"), @@ -9,7 +15,16 @@ enum class AppTheme(val value: String) { ; companion object { - fun stringValues() = values().map { it.value }.toTypedArray() + val APP_THEME_DEFAULT = AUTO_SYSTEM + + fun stringValues() = entries.map { it.value }.toTypedArray() + + fun from(sharedPreferencesRepository: SharedPreferencesRepository): AppTheme { + val pref = sharedPreferencesRepository.getString(PrefKeys.APP_THEME, null) + ?: return APP_THEME_DEFAULT + + return enumValueOf(pref.uppercase()) + } } }