mirror of https://github.com/yuzu-emu/yuzu.git
257 lines
8.9 KiB
Kotlin
257 lines
8.9 KiB
Kotlin
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
package org.yuzu.yuzu_emu.features.settings.ui
|
|
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.os.Bundle
|
|
import android.view.Menu
|
|
import android.view.View
|
|
import android.widget.Toast
|
|
import androidx.activity.viewModels
|
|
import androidx.appcompat.app.AppCompatActivity
|
|
import androidx.core.view.ViewCompat
|
|
import androidx.core.view.WindowCompat
|
|
import androidx.core.view.WindowInsetsCompat
|
|
import android.view.ViewGroup.MarginLayoutParams
|
|
import androidx.activity.OnBackPressedCallback
|
|
import androidx.activity.result.ActivityResultLauncher
|
|
import androidx.core.view.updatePadding
|
|
import com.google.android.material.color.MaterialColors
|
|
import org.yuzu.yuzu_emu.NativeLibrary
|
|
import org.yuzu.yuzu_emu.R
|
|
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
|
|
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
|
import org.yuzu.yuzu_emu.features.settings.model.FloatSetting
|
|
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
|
import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
|
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
|
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
|
import org.yuzu.yuzu_emu.utils.*
|
|
import java.io.IOException
|
|
|
|
class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
|
private val presenter = SettingsActivityPresenter(this)
|
|
|
|
private lateinit var binding: ActivitySettingsBinding
|
|
|
|
private val settingsViewModel: SettingsViewModel by viewModels()
|
|
|
|
override val settings: Settings get() = settingsViewModel.settings
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
ThemeHelper.setTheme(this)
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
|
setContentView(binding.root)
|
|
|
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
|
|
|
val launcher = intent
|
|
val gameID = launcher.getStringExtra(ARG_GAME_ID)
|
|
val menuTag = launcher.getStringExtra(ARG_MENU_TAG)
|
|
presenter.onCreate(savedInstanceState, menuTag!!, gameID!!)
|
|
|
|
// Show "Back" button in the action bar for navigation
|
|
setSupportActionBar(binding.toolbarSettings)
|
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
|
|
|
if (InsetsHelper.getSystemGestureType(applicationContext) != InsetsHelper.GESTURE_NAVIGATION) {
|
|
binding.navigationBarShade.setBackgroundColor(
|
|
ThemeHelper.getColorWithOpacity(
|
|
MaterialColors.getColor(
|
|
binding.navigationBarShade,
|
|
com.google.android.material.R.attr.colorSurface
|
|
),
|
|
ThemeHelper.SYSTEM_BAR_ALPHA
|
|
)
|
|
)
|
|
}
|
|
|
|
onBackPressedDispatcher.addCallback(
|
|
this,
|
|
object : OnBackPressedCallback(true) {
|
|
override fun handleOnBackPressed() = navigateBack()
|
|
})
|
|
|
|
setInsets()
|
|
}
|
|
|
|
override fun onSupportNavigateUp(): Boolean {
|
|
navigateBack()
|
|
return true
|
|
}
|
|
|
|
private fun navigateBack() {
|
|
if (supportFragmentManager.backStackEntryCount > 0) {
|
|
supportFragmentManager.popBackStack()
|
|
} else {
|
|
finish()
|
|
}
|
|
}
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
val inflater = menuInflater
|
|
inflater.inflate(R.menu.menu_settings, menu)
|
|
return true
|
|
}
|
|
|
|
override fun onSaveInstanceState(outState: Bundle) {
|
|
// Critical: If super method is not called, rotations will be busted.
|
|
super.onSaveInstanceState(outState)
|
|
presenter.saveState(outState)
|
|
}
|
|
|
|
override fun onStart() {
|
|
super.onStart()
|
|
presenter.onStart()
|
|
}
|
|
|
|
/**
|
|
* If this is called, the user has left the settings screen (potentially through the
|
|
* home button) and will expect their changes to be persisted. So we kick off an
|
|
* IntentService which will do so on a background thread.
|
|
*/
|
|
override fun onStop() {
|
|
super.onStop()
|
|
presenter.onStop(isFinishing)
|
|
}
|
|
|
|
override fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) {
|
|
if (!addToStack && settingsFragment != null) {
|
|
return
|
|
}
|
|
|
|
val transaction = supportFragmentManager.beginTransaction()
|
|
if (addToStack) {
|
|
if (areSystemAnimationsEnabled()) {
|
|
transaction.setCustomAnimations(
|
|
R.anim.anim_settings_fragment_in,
|
|
R.anim.anim_settings_fragment_out,
|
|
0,
|
|
R.anim.anim_pop_settings_fragment_out
|
|
)
|
|
}
|
|
transaction.addToBackStack(null)
|
|
}
|
|
transaction.replace(
|
|
R.id.frame_content,
|
|
SettingsFragment.newInstance(menuTag, gameId),
|
|
FRAGMENT_TAG
|
|
)
|
|
transaction.commit()
|
|
}
|
|
|
|
private fun areSystemAnimationsEnabled(): Boolean {
|
|
val duration = android.provider.Settings.Global.getFloat(
|
|
contentResolver,
|
|
android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, 1f
|
|
)
|
|
val transition = android.provider.Settings.Global.getFloat(
|
|
contentResolver,
|
|
android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE, 1f
|
|
)
|
|
return duration != 0f && transition != 0f
|
|
}
|
|
|
|
override fun onSettingsFileLoaded() {
|
|
val fragment: SettingsFragmentView? = settingsFragment
|
|
fragment?.loadSettingsList()
|
|
}
|
|
|
|
override fun onSettingsFileNotFound() {
|
|
val fragment: SettingsFragmentView? = settingsFragment
|
|
fragment?.loadSettingsList()
|
|
}
|
|
|
|
override fun showToastMessage(message: String, is_long: Boolean) {
|
|
Toast.makeText(
|
|
this,
|
|
message,
|
|
if (is_long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT
|
|
).show()
|
|
}
|
|
|
|
override fun onSettingChanged() {
|
|
presenter.onSettingChanged()
|
|
}
|
|
|
|
fun onSettingsReset() {
|
|
// Prevents saving to a non-existent settings file
|
|
presenter.onSettingsReset()
|
|
|
|
// Reset the static memory representation of each setting
|
|
BooleanSetting.clear()
|
|
FloatSetting.clear()
|
|
IntSetting.clear()
|
|
StringSetting.clear()
|
|
|
|
// Delete settings file because the user may have changed values that do not exist in the UI
|
|
val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG)
|
|
if (!settingsFile.delete()) {
|
|
throw IOException("Failed to delete $settingsFile")
|
|
}
|
|
|
|
showToastMessage(getString(R.string.settings_reset), true)
|
|
finish()
|
|
}
|
|
|
|
fun setToolbarTitle(title: String) {
|
|
binding.toolbarSettingsLayout.title = title
|
|
}
|
|
|
|
private val settingsFragment: SettingsFragment?
|
|
get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment?
|
|
|
|
private fun setInsets() {
|
|
ViewCompat.setOnApplyWindowInsetsListener(binding.frameContent) { view: View, windowInsets: WindowInsetsCompat ->
|
|
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
|
view.updatePadding(
|
|
left = barInsets.left + cutoutInsets.left,
|
|
right = barInsets.right + cutoutInsets.right
|
|
)
|
|
|
|
val mlpAppBar = binding.appbarSettings.layoutParams as MarginLayoutParams
|
|
mlpAppBar.leftMargin = barInsets.left + cutoutInsets.left
|
|
mlpAppBar.rightMargin = barInsets.right + cutoutInsets.right
|
|
binding.appbarSettings.layoutParams = mlpAppBar
|
|
|
|
val mlpShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
|
|
mlpShade.height = barInsets.bottom
|
|
binding.navigationBarShade.layoutParams = mlpShade
|
|
|
|
windowInsets
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
private const val ARG_MENU_TAG = "menu_tag"
|
|
private const val ARG_GAME_ID = "game_id"
|
|
private const val FRAGMENT_TAG = "settings"
|
|
|
|
fun launch(context: Context, menuTag: String?, gameId: String?) {
|
|
val settings = Intent(context, SettingsActivity::class.java)
|
|
settings.putExtra(ARG_MENU_TAG, menuTag)
|
|
settings.putExtra(ARG_GAME_ID, gameId)
|
|
context.startActivity(settings)
|
|
}
|
|
|
|
fun launch(
|
|
context: Context,
|
|
launcher: ActivityResultLauncher<Intent>,
|
|
menuTag: String?,
|
|
gameId: String?
|
|
) {
|
|
val settings = Intent(context, SettingsActivity::class.java)
|
|
settings.putExtra(ARG_MENU_TAG, menuTag)
|
|
settings.putExtra(ARG_GAME_ID, gameId)
|
|
launcher.launch(settings)
|
|
}
|
|
}
|
|
}
|