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.
This commit is contained in:
Nik Clayton 2023-12-11 14:41:36 +01:00 committed by GitHub
parent 2a7eda667b
commit 60cfa99f17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 36 additions and 32 deletions

View File

@ -37,15 +37,13 @@ import app.pachli.adapter.AccountSelectionAdapter
import app.pachli.core.accounts.AccountManager import app.pachli.core.accounts.AccountManager
import app.pachli.core.database.model.AccountEntity import app.pachli.core.database.model.AccountEntity
import app.pachli.core.navigation.LoginActivityIntent import app.pachli.core.navigation.LoginActivityIntent
import app.pachli.core.preferences.AppTheme
import app.pachli.core.preferences.PrefKeys import app.pachli.core.preferences.PrefKeys
import app.pachli.core.preferences.PrefKeys.APP_THEME
import app.pachli.core.preferences.SharedPreferencesRepository import app.pachli.core.preferences.SharedPreferencesRepository
import app.pachli.interfaces.AccountSelectionListener import app.pachli.interfaces.AccountSelectionListener
import app.pachli.interfaces.PermissionRequester import app.pachli.interfaces.PermissionRequester
import app.pachli.util.APP_THEME_DEFAULT
import app.pachli.util.EmbeddedFontFamily import app.pachli.util.EmbeddedFontFamily
import app.pachli.util.EmbeddedFontFamily.Companion.from 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.color.MaterialColors
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import dagger.hilt.EntryPoint import dagger.hilt.EntryPoint
@ -84,9 +82,9 @@ abstract class BaseActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// Set the theme from preferences // Set the theme from preferences
val theme = sharedPreferencesRepository.getString(APP_THEME, APP_THEME_DEFAULT) val theme = AppTheme.from(sharedPreferencesRepository)
Timber.d("activeTheme: %s", theme) Timber.d("activeTheme: %s", theme)
if (theme == THEME_BLACK) { if (theme == AppTheme.BLACK) {
setTheme(R.style.Theme_Pachli_Black) setTheme(R.style.Theme_Pachli_Black)
} }

View File

@ -24,12 +24,11 @@ import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import app.pachli.components.notifications.createWorkerNotificationChannel 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.NEW_INSTALL_SCHEMA_VERSION
import app.pachli.core.preferences.PrefKeys 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.SCHEMA_VERSION
import app.pachli.core.preferences.SharedPreferencesRepository import app.pachli.core.preferences.SharedPreferencesRepository
import app.pachli.util.APP_THEME_DEFAULT
import app.pachli.util.LocaleManager import app.pachli.util.LocaleManager
import app.pachli.util.setAppNightMode import app.pachli.util.setAppNightMode
import app.pachli.worker.PruneCacheWorker import app.pachli.worker.PruneCacheWorker
@ -88,7 +87,7 @@ class PachliApplication : Application() {
EmojiPackHelper.init(this, DefaultEmojiPackList.get(this), allowPackImports = false) EmojiPackHelper.init(this, DefaultEmojiPackList.get(this), allowPackImports = false)
// init night mode // init night mode
val theme = sharedPreferencesRepository.getString(APP_THEME, APP_THEME_DEFAULT) val theme = AppTheme.from(sharedPreferencesRepository)
setAppNightMode(theme) setAppNightMode(theme)
localeManager.setLocale() localeManager.setLocale()

View File

@ -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.Attachment
import app.pachli.core.network.model.Emoji import app.pachli.core.network.model.Emoji
import app.pachli.core.network.model.Status 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
import app.pachli.core.preferences.PrefKeys.APP_THEME
import app.pachli.core.preferences.SharedPreferencesRepository import app.pachli.core.preferences.SharedPreferencesRepository
import app.pachli.databinding.ActivityComposeBinding import app.pachli.databinding.ActivityComposeBinding
import app.pachli.util.APP_THEME_DEFAULT
import app.pachli.util.MentionSpan import app.pachli.util.MentionSpan
import app.pachli.util.PickMediaFiles import app.pachli.util.PickMediaFiles
import app.pachli.util.THEME_BLACK
import app.pachli.util.getInitialLanguages import app.pachli.util.getInitialLanguages
import app.pachli.util.getLocaleList import app.pachli.util.getLocaleList
import app.pachli.util.getMediaSize import app.pachli.util.getMediaSize
@ -205,8 +203,8 @@ class ComposeActivity :
activeAccount = accountManager.activeAccount ?: return activeAccount = accountManager.activeAccount ?: return
val theme = sharedPreferencesRepository.getString(APP_THEME, APP_THEME_DEFAULT) val theme = AppTheme.from(sharedPreferencesRepository)
if (theme == THEME_BLACK) { if (theme == AppTheme.BLACK) {
setTheme(R.style.AppDialogActivityBlackTheme) setTheme(R.style.AppDialogActivityBlackTheme)
} }
setContentView(binding.root) setContentView(binding.root)

View File

@ -30,11 +30,10 @@ import app.pachli.appstore.EventHub
import app.pachli.core.navigation.MainActivityIntent import app.pachli.core.navigation.MainActivityIntent
import app.pachli.core.navigation.PreferencesActivityIntent import app.pachli.core.navigation.PreferencesActivityIntent
import app.pachli.core.navigation.PreferencesActivityIntent.PreferenceScreen 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
import app.pachli.core.preferences.PrefKeys.APP_THEME import app.pachli.core.preferences.PrefKeys.APP_THEME
import app.pachli.core.preferences.getNonNullString
import app.pachli.databinding.ActivityPreferencesBinding import app.pachli.databinding.ActivityPreferencesBinding
import app.pachli.util.APP_THEME_DEFAULT
import app.pachli.util.setAppNightMode import app.pachli.util.setAppNightMode
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
@ -102,7 +101,7 @@ class PreferencesActivity :
sharedPreferencesRepository.changes.filterNotNull().collect { key -> sharedPreferencesRepository.changes.filterNotNull().collect { key ->
when (key) { when (key) {
APP_THEME -> { APP_THEME -> {
val theme = sharedPreferencesRepository.getNonNullString(APP_THEME, APP_THEME_DEFAULT) val theme = AppTheme.from(sharedPreferencesRepository)
Timber.d("activeTheme: %s", theme) Timber.d("activeTheme: %s", theme)
setAppNightMode(theme) setAppNightMode(theme)

View File

@ -23,6 +23,7 @@ import app.pachli.R
import app.pachli.core.accounts.AccountManager import app.pachli.core.accounts.AccountManager
import app.pachli.core.network.model.Notification import app.pachli.core.network.model.Notification
import app.pachli.core.preferences.AppTheme 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.core.preferences.PrefKeys
import app.pachli.settings.emojiPreference import app.pachli.settings.emojiPreference
import app.pachli.settings.listPreference import app.pachli.settings.listPreference
@ -32,7 +33,6 @@ import app.pachli.settings.preferenceCategory
import app.pachli.settings.sliderPreference import app.pachli.settings.sliderPreference
import app.pachli.settings.switchPreference import app.pachli.settings.switchPreference
import app.pachli.updatecheck.UpdateNotificationFrequency import app.pachli.updatecheck.UpdateNotificationFrequency
import app.pachli.util.APP_THEME_DEFAULT
import app.pachli.util.LocaleManager import app.pachli.util.LocaleManager
import app.pachli.util.deserialize import app.pachli.util.deserialize
import app.pachli.util.makeIcon import app.pachli.util.makeIcon
@ -60,7 +60,7 @@ class PreferencesFragment : PreferenceFragmentCompat() {
makePreferenceScreen { makePreferenceScreen {
preferenceCategory(R.string.pref_title_appearance_settings) { preferenceCategory(R.string.pref_title_appearance_settings) {
listPreference { listPreference {
setDefaultValue(APP_THEME_DEFAULT) setDefaultValue(APP_THEME_DEFAULT.value)
setEntries(R.array.app_theme_names) setEntries(R.array.app_theme_names)
entryValues = AppTheme.stringValues() entryValues = AppTheme.stringValues()
key = PrefKeys.APP_THEME key = PrefKeys.APP_THEME

View File

@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.res.use import androidx.core.content.res.use
import app.pachli.core.preferences.AppTheme
import com.google.android.material.color.MaterialColors 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. * 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 { fun getDimension(context: Context, @AttrRes attribute: Int): Int {
return context.obtainStyledAttributes(intArrayOf(attribute)).use { array -> return context.obtainStyledAttributes(intArrayOf(attribute)).use { array ->
array.getDimensionPixelSize(0, -1) 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) { when (flavor) {
THEME_NIGHT, THEME_BLACK -> AppCompatDelegate.setDefaultNightMode( AppTheme.NIGHT, AppTheme.BLACK -> AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES, AppCompatDelegate.MODE_NIGHT_YES,
) )
THEME_DAY -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) AppTheme.DAY -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
THEME_AUTO -> AppCompatDelegate.setDefaultNightMode( AppTheme.AUTO -> AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_AUTO_TIME, AppCompatDelegate.MODE_NIGHT_AUTO_TIME,
) )
THEME_SYSTEM -> AppCompatDelegate.setDefaultNightMode( AppTheme.AUTO_SYSTEM -> AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM,
) )
else -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
} }
} }

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Modifications to this list or order must be kept in sync with
SettingsConstants.AppTheme -->
<string-array name="app_theme_names"> <string-array name="app_theme_names">
<item>@string/app_them_dark</item> <item>@string/app_them_dark</item>
<item>@string/app_theme_light</item> <item>@string/app_theme_light</item>

View File

@ -1,5 +1,11 @@
package app.pachli.core.preferences 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) { enum class AppTheme(val value: String) {
NIGHT("night"), NIGHT("night"),
DAY("day"), DAY("day"),
@ -9,7 +15,16 @@ enum class AppTheme(val value: String) {
; ;
companion object { 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())
}
} }
} }