android: Migrate theme settings to ini

This commit is contained in:
t895 2023-12-23 19:01:57 -05:00
parent b2b4742e61
commit d3f38ce56c
8 changed files with 128 additions and 62 deletions

View file

@ -18,7 +18,8 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"), RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"),
RENDERER_DEBUG("debug"), RENDERER_DEBUG("debug"),
PICTURE_IN_PICTURE("picture_in_picture"), PICTURE_IN_PICTURE("picture_in_picture"),
USE_CUSTOM_RTC("custom_rtc_enabled"); USE_CUSTOM_RTC("custom_rtc_enabled"),
BLACK_BACKGROUNDS("black_backgrounds");
override fun getBoolean(needsGlobal: Boolean): Boolean = override fun getBoolean(needsGlobal: Boolean): Boolean =
NativeConfig.getBoolean(key, needsGlobal) NativeConfig.getBoolean(key, needsGlobal)

View file

@ -19,7 +19,9 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
RENDERER_SCREEN_LAYOUT("screen_layout"), RENDERER_SCREEN_LAYOUT("screen_layout"),
RENDERER_ASPECT_RATIO("aspect_ratio"), RENDERER_ASPECT_RATIO("aspect_ratio"),
AUDIO_OUTPUT_ENGINE("output_engine"), AUDIO_OUTPUT_ENGINE("output_engine"),
MAX_ANISOTROPY("max_anisotropy"); MAX_ANISOTROPY("max_anisotropy"),
THEME("theme"),
THEME_MODE("theme_mode");
override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal)

View file

@ -54,6 +54,7 @@ object Settings {
const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps" const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps"
const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay" const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay"
// Deprecated theme preference keys
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch" const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
const val PREF_THEME = "Theme" const val PREF_THEME = "Theme"
const val PREF_THEME_MODE = "ThemeMode" const val PREF_THEME_MODE = "ThemeMode"

View file

@ -3,10 +3,8 @@
package org.yuzu.yuzu_emu.features.settings.ui package org.yuzu.yuzu_emu.features.settings.ui
import android.content.SharedPreferences
import android.os.Build import android.os.Build
import android.widget.Toast import android.widget.Toast
import androidx.preference.PreferenceManager
import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
@ -29,9 +27,6 @@ class SettingsFragmentPresenter(
) { ) {
private var settingsList = ArrayList<SettingsItem>() private var settingsList = ArrayList<SettingsItem>()
private val preferences: SharedPreferences
get() = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
// Extension for altering settings list based on each setting's properties // Extension for altering settings list based on each setting's properties
fun ArrayList<SettingsItem>.add(key: String) { fun ArrayList<SettingsItem>.add(key: String) {
val item = SettingsItem.settingsItems[key]!! val item = SettingsItem.settingsItems[key]!!
@ -170,25 +165,19 @@ class SettingsFragmentPresenter(
private fun addThemeSettings(sl: ArrayList<SettingsItem>) { private fun addThemeSettings(sl: ArrayList<SettingsItem>) {
sl.apply { sl.apply {
val theme: AbstractIntSetting = object : AbstractIntSetting { val theme: AbstractIntSetting = object : AbstractIntSetting {
override fun getInt(needsGlobal: Boolean): Int = override fun getInt(needsGlobal: Boolean): Int = IntSetting.THEME.getInt()
preferences.getInt(Settings.PREF_THEME, 0)
override fun setInt(value: Int) { override fun setInt(value: Int) {
preferences.edit() IntSetting.THEME.setInt(value)
.putInt(Settings.PREF_THEME, value)
.apply()
settingsViewModel.setShouldRecreate(true) settingsViewModel.setShouldRecreate(true)
} }
override val key: String = Settings.PREF_THEME override val key: String = IntSetting.THEME.key
override val isRuntimeModifiable: Boolean = false override val isRuntimeModifiable: Boolean = IntSetting.THEME.isRuntimeModifiable
override fun getValueAsString(needsGlobal: Boolean): String = getInt().toString() override fun getValueAsString(needsGlobal: Boolean): String =
override val defaultValue: Int = 0 IntSetting.THEME.getValueAsString()
override fun reset() {
preferences.edit() override val defaultValue: Int = IntSetting.THEME.defaultValue
.putInt(Settings.PREF_THEME, defaultValue) override fun reset() = IntSetting.THEME.setInt(defaultValue)
.apply()
}
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@ -214,24 +203,22 @@ class SettingsFragmentPresenter(
} }
val themeMode: AbstractIntSetting = object : AbstractIntSetting { val themeMode: AbstractIntSetting = object : AbstractIntSetting {
override fun getInt(needsGlobal: Boolean): Int = override fun getInt(needsGlobal: Boolean): Int = IntSetting.THEME_MODE.getInt()
preferences.getInt(Settings.PREF_THEME_MODE, -1)
override fun setInt(value: Int) { override fun setInt(value: Int) {
preferences.edit() IntSetting.THEME_MODE.setInt(value)
.putInt(Settings.PREF_THEME_MODE, value)
.apply()
settingsViewModel.setShouldRecreate(true) settingsViewModel.setShouldRecreate(true)
} }
override val key: String = Settings.PREF_THEME_MODE override val key: String = IntSetting.THEME_MODE.key
override val isRuntimeModifiable: Boolean = false override val isRuntimeModifiable: Boolean =
override fun getValueAsString(needsGlobal: Boolean): String = getInt().toString() IntSetting.THEME_MODE.isRuntimeModifiable
override val defaultValue: Int = -1
override fun getValueAsString(needsGlobal: Boolean): String =
IntSetting.THEME_MODE.getValueAsString()
override val defaultValue: Int = IntSetting.THEME_MODE.defaultValue
override fun reset() { override fun reset() {
preferences.edit() IntSetting.THEME_MODE.setInt(defaultValue)
.putInt(Settings.PREF_BLACK_BACKGROUNDS, defaultValue)
.apply()
settingsViewModel.setShouldRecreate(true) settingsViewModel.setShouldRecreate(true)
} }
} }
@ -248,25 +235,24 @@ class SettingsFragmentPresenter(
val blackBackgrounds: AbstractBooleanSetting = object : AbstractBooleanSetting { val blackBackgrounds: AbstractBooleanSetting = object : AbstractBooleanSetting {
override fun getBoolean(needsGlobal: Boolean): Boolean = override fun getBoolean(needsGlobal: Boolean): Boolean =
preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false) BooleanSetting.BLACK_BACKGROUNDS.getBoolean()
override fun setBoolean(value: Boolean) { override fun setBoolean(value: Boolean) {
preferences.edit() BooleanSetting.BLACK_BACKGROUNDS.setBoolean(value)
.putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value)
.apply()
settingsViewModel.setShouldRecreate(true) settingsViewModel.setShouldRecreate(true)
} }
override val key: String = Settings.PREF_BLACK_BACKGROUNDS override val key: String = BooleanSetting.BLACK_BACKGROUNDS.key
override val isRuntimeModifiable: Boolean = false override val isRuntimeModifiable: Boolean =
override fun getValueAsString(needsGlobal: Boolean): String = BooleanSetting.BLACK_BACKGROUNDS.isRuntimeModifiable
getBoolean().toString()
override val defaultValue: Boolean = false override fun getValueAsString(needsGlobal: Boolean): String =
BooleanSetting.BLACK_BACKGROUNDS.getValueAsString()
override val defaultValue: Boolean = BooleanSetting.BLACK_BACKGROUNDS.defaultValue
override fun reset() { override fun reset() {
preferences.edit() BooleanSetting.BLACK_BACKGROUNDS
.putBoolean(Settings.PREF_BLACK_BACKGROUNDS, defaultValue) .setBoolean(BooleanSetting.BLACK_BACKGROUNDS.defaultValue)
.apply()
settingsViewModel.setShouldRecreate(true) settingsViewModel.setShouldRecreate(true)
} }
} }

View file

@ -3,9 +3,14 @@
package org.yuzu.yuzu_emu.utils package org.yuzu.yuzu_emu.utils
import androidx.preference.PreferenceManager
import java.io.IOException import java.io.IOException
import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.utils.PreferenceUtil.migratePreference
object DirectoryInitialization { object DirectoryInitialization {
private var userPath: String? = null private var userPath: String? = null
@ -17,6 +22,7 @@ object DirectoryInitialization {
initializeInternalStorage() initializeInternalStorage()
NativeLibrary.initializeSystem(false) NativeLibrary.initializeSystem(false)
NativeConfig.initializeGlobalConfig() NativeConfig.initializeGlobalConfig()
migrateSettings()
areDirectoriesReady = true areDirectoriesReady = true
} }
} }
@ -35,4 +41,31 @@ object DirectoryInitialization {
e.printStackTrace() e.printStackTrace()
} }
} }
private fun migrateSettings() {
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
var saveConfig = false
val theme = preferences.migratePreference<Int>(Settings.PREF_THEME)
if (theme != null) {
IntSetting.THEME.setInt(theme)
saveConfig = true
}
val themeMode = preferences.migratePreference<Int>(Settings.PREF_THEME_MODE)
if (themeMode != null) {
IntSetting.THEME_MODE.setInt(themeMode)
saveConfig = true
}
val blackBackgrounds =
preferences.migratePreference<Boolean>(Settings.PREF_BLACK_BACKGROUNDS)
if (blackBackgrounds != null) {
BooleanSetting.BLACK_BACKGROUNDS.setBoolean(blackBackgrounds)
saveConfig = true
}
if (saveConfig) {
NativeConfig.saveGlobalConfig()
}
}
} }

View file

@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.utils
import android.content.SharedPreferences
object PreferenceUtil {
/**
* Retrieves a shared preference value and then deletes the value in storage.
* @param key Associated key for the value in this preferences instance
* @return Typed value associated with [key]. Null if no such key exists.
*/
inline fun <reified T> SharedPreferences.migratePreference(key: String): T? {
if (!this.contains(key)) {
return null
}
val value: Any = when (T::class) {
String::class -> this.getString(key, "")!!
Boolean::class -> this.getBoolean(key, false)
Int::class -> this.getInt(key, 0)
Float::class -> this.getFloat(key, 0f)
Long::class -> this.getLong(key, 0)
else -> throw IllegalStateException("Tried to migrate preference with invalid type!")
}
deletePreference(key)
return value as T
}
fun SharedPreferences.deletePreference(key: String) = this.edit().remove(key).apply()
}

View file

@ -10,33 +10,26 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import androidx.preference.PreferenceManager
import kotlin.math.roundToInt import kotlin.math.roundToInt
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.ui.main.ThemeProvider import org.yuzu.yuzu_emu.ui.main.ThemeProvider
object ThemeHelper { object ThemeHelper {
const val SYSTEM_BAR_ALPHA = 0.9f const val SYSTEM_BAR_ALPHA = 0.9f
private const val DEFAULT = 0
private const val MATERIAL_YOU = 1
fun setTheme(activity: AppCompatActivity) { fun setTheme(activity: AppCompatActivity) {
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
setThemeMode(activity) setThemeMode(activity)
when (preferences.getInt(Settings.PREF_THEME, 0)) { when (Theme.from(IntSetting.THEME.getInt())) {
DEFAULT -> activity.setTheme(R.style.Theme_Yuzu_Main) Theme.Default -> activity.setTheme(R.style.Theme_Yuzu_Main)
MATERIAL_YOU -> activity.setTheme(R.style.Theme_Yuzu_Main_MaterialYou) Theme.MaterialYou -> activity.setTheme(R.style.Theme_Yuzu_Main_MaterialYou)
} }
// Using a specific night mode check because this could apply incorrectly when using the // Using a specific night mode check because this could apply incorrectly when using the
// light app mode, dark system mode, and black backgrounds. Launching the settings activity // light app mode, dark system mode, and black backgrounds. Launching the settings activity
// will then show light mode colors/navigation bars but with black backgrounds. // will then show light mode colors/navigation bars but with black backgrounds.
if (preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false) && if (BooleanSetting.BLACK_BACKGROUNDS.getBoolean() && isNightMode(activity)) {
isNightMode(activity)
) {
activity.setTheme(R.style.ThemeOverlay_Yuzu_Dark) activity.setTheme(R.style.ThemeOverlay_Yuzu_Dark)
} }
} }
@ -60,8 +53,7 @@ object ThemeHelper {
} }
fun setThemeMode(activity: AppCompatActivity) { fun setThemeMode(activity: AppCompatActivity) {
val themeMode = PreferenceManager.getDefaultSharedPreferences(activity.applicationContext) val themeMode = IntSetting.THEME_MODE.getInt()
.getInt(Settings.PREF_THEME_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
activity.delegate.localNightMode = themeMode activity.delegate.localNightMode = themeMode
val windowController = WindowCompat.getInsetsController( val windowController = WindowCompat.getInsetsController(
activity.window, activity.window,
@ -95,3 +87,12 @@ object ThemeHelper {
windowController.isAppearanceLightNavigationBars = false windowController.isAppearanceLightNavigationBars = false
} }
} }
enum class Theme(val int: Int) {
Default(0),
MaterialYou(1);
companion object {
fun from(int: Int): Theme = entries.firstOrNull { it.int == int } ?: Default
}
}

View file

@ -33,6 +33,11 @@ struct Values {
Settings::SwitchableSetting<std::string, false> driver_path{linkage, "", "driver_path", Settings::SwitchableSetting<std::string, false> driver_path{linkage, "", "driver_path",
Settings::Category::GpuDriver}; Settings::Category::GpuDriver};
Settings::Setting<s32> theme{linkage, 0, "theme", Settings::Category::Android};
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
Settings::Category::Android};
}; };
extern Values values; extern Values values;