android: Migrate theme settings to ini
This commit is contained in:
parent
b2b4742e61
commit
d3f38ce56c
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Reference in New Issue