diff options
28 files changed, 371 insertions, 567 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt index 04ab6a220..9561748cb 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt | |||
| @@ -46,7 +46,7 @@ class YuzuApplication : Application() { | |||
| 46 | super.onCreate() | 46 | super.onCreate() |
| 47 | application = this | 47 | application = this |
| 48 | documentsTree = DocumentsTree() | 48 | documentsTree = DocumentsTree() |
| 49 | DirectoryInitialization.start(applicationContext) | 49 | DirectoryInitialization.start() |
| 50 | GpuDriverHelper.initializeDriverParameters(applicationContext) | 50 | GpuDriverHelper.initializeDriverParameters(applicationContext) |
| 51 | NativeLibrary.logDeviceInfo() | 51 | NativeLibrary.logDeviceInfo() |
| 52 | 52 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index 6f52a7a8d..dbd602a1d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt | |||
| @@ -85,9 +85,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { | |||
| 85 | 85 | ||
| 86 | val navHostFragment = | 86 | val navHostFragment = |
| 87 | supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment | 87 | supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment |
| 88 | val navController = navHostFragment.navController | 88 | navHostFragment.navController.setGraph(R.navigation.emulation_navigation, intent.extras) |
| 89 | navController | ||
| 90 | .setGraph(R.navigation.emulation_navigation, intent.extras) | ||
| 91 | 89 | ||
| 92 | isActivityRecreated = savedInstanceState != null | 90 | isActivityRecreated = savedInstanceState != null |
| 93 | 91 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt index 733a53c8c..7fd83f5f7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt | |||
| @@ -3,10 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.features.settings.ui | 4 | package org.yuzu.yuzu_emu.features.settings.ui |
| 5 | 5 | ||
| 6 | import android.content.Context | ||
| 7 | import android.content.Intent | ||
| 8 | import android.os.Bundle | 6 | import android.os.Bundle |
| 9 | import android.view.Menu | ||
| 10 | import android.view.View | 7 | import android.view.View |
| 11 | import android.view.ViewGroup.MarginLayoutParams | 8 | import android.view.ViewGroup.MarginLayoutParams |
| 12 | import android.widget.Toast | 9 | import android.widget.Toast |
| @@ -16,20 +13,26 @@ import androidx.appcompat.app.AppCompatActivity | |||
| 16 | import androidx.core.view.ViewCompat | 13 | import androidx.core.view.ViewCompat |
| 17 | import androidx.core.view.WindowCompat | 14 | import androidx.core.view.WindowCompat |
| 18 | import androidx.core.view.WindowInsetsCompat | 15 | import androidx.core.view.WindowInsetsCompat |
| 19 | import androidx.core.view.updatePadding | 16 | import androidx.navigation.fragment.NavHostFragment |
| 17 | import androidx.navigation.navArgs | ||
| 20 | import com.google.android.material.color.MaterialColors | 18 | import com.google.android.material.color.MaterialColors |
| 19 | import org.yuzu.yuzu_emu.NativeLibrary | ||
| 21 | import java.io.IOException | 20 | import java.io.IOException |
| 22 | import org.yuzu.yuzu_emu.R | 21 | import org.yuzu.yuzu_emu.R |
| 23 | import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding | 22 | import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding |
| 24 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 23 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 25 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 24 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile |
| 25 | import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment | ||
| 26 | import org.yuzu.yuzu_emu.model.SettingsViewModel | ||
| 26 | import org.yuzu.yuzu_emu.utils.* | 27 | import org.yuzu.yuzu_emu.utils.* |
| 27 | 28 | ||
| 28 | class SettingsActivity : AppCompatActivity(), SettingsActivityView { | 29 | class SettingsActivity : AppCompatActivity() { |
| 29 | private val presenter = SettingsActivityPresenter(this) | ||
| 30 | |||
| 31 | private lateinit var binding: ActivitySettingsBinding | 30 | private lateinit var binding: ActivitySettingsBinding |
| 32 | 31 | ||
| 32 | private val args by navArgs<SettingsActivityArgs>() | ||
| 33 | |||
| 34 | private val settingsViewModel: SettingsViewModel by viewModels() | ||
| 35 | |||
| 33 | override fun onCreate(savedInstanceState: Bundle?) { | 36 | override fun onCreate(savedInstanceState: Bundle?) { |
| 34 | ThemeHelper.setTheme(this) | 37 | ThemeHelper.setTheme(this) |
| 35 | 38 | ||
| @@ -38,16 +41,17 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { | |||
| 38 | binding = ActivitySettingsBinding.inflate(layoutInflater) | 41 | binding = ActivitySettingsBinding.inflate(layoutInflater) |
| 39 | setContentView(binding.root) | 42 | setContentView(binding.root) |
| 40 | 43 | ||
| 41 | WindowCompat.setDecorFitsSystemWindows(window, false) | 44 | settingsViewModel.game = args.game |
| 42 | 45 | ||
| 43 | val launcher = intent | 46 | val navHostFragment = |
| 44 | val gameID = launcher.getStringExtra(ARG_GAME_ID) | 47 | supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment |
| 45 | val menuTag = launcher.getStringExtra(ARG_MENU_TAG) | 48 | navHostFragment.navController.setGraph(R.navigation.settings_navigation, intent.extras) |
| 46 | presenter.onCreate(savedInstanceState, menuTag!!, gameID!!) | ||
| 47 | 49 | ||
| 48 | // Show "Back" button in the action bar for navigation | 50 | WindowCompat.setDecorFitsSystemWindows(window, false) |
| 49 | setSupportActionBar(binding.toolbarSettings) | 51 | |
| 50 | supportActionBar!!.setDisplayHomeAsUpEnabled(true) | 52 | if (savedInstanceState != null) { |
| 53 | settingsViewModel.shouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE) | ||
| 54 | } | ||
| 51 | 55 | ||
| 52 | if (InsetsHelper.getSystemGestureType(applicationContext) != | 56 | if (InsetsHelper.getSystemGestureType(applicationContext) != |
| 53 | InsetsHelper.GESTURE_NAVIGATION | 57 | InsetsHelper.GESTURE_NAVIGATION |
| @@ -63,6 +67,28 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { | |||
| 63 | ) | 67 | ) |
| 64 | } | 68 | } |
| 65 | 69 | ||
| 70 | settingsViewModel.shouldRecreate.observe(this) { | ||
| 71 | if (it) { | ||
| 72 | settingsViewModel.setShouldRecreate(false) | ||
| 73 | recreate() | ||
| 74 | } | ||
| 75 | } | ||
| 76 | settingsViewModel.shouldNavigateBack.observe(this) { | ||
| 77 | if (it) { | ||
| 78 | settingsViewModel.setShouldNavigateBack(false) | ||
| 79 | navigateBack() | ||
| 80 | } | ||
| 81 | } | ||
| 82 | settingsViewModel.shouldShowResetSettingsDialog.observe(this) { | ||
| 83 | if (it) { | ||
| 84 | settingsViewModel.setShouldShowResetSettingsDialog(false) | ||
| 85 | ResetSettingsDialogFragment().show( | ||
| 86 | supportFragmentManager, | ||
| 87 | ResetSettingsDialogFragment.TAG | ||
| 88 | ) | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 66 | onBackPressedDispatcher.addCallback( | 92 | onBackPressedDispatcher.addCallback( |
| 67 | this, | 93 | this, |
| 68 | object : OnBackPressedCallback(true) { | 94 | object : OnBackPressedCallback(true) { |
| @@ -73,34 +99,28 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { | |||
| 73 | setInsets() | 99 | setInsets() |
| 74 | } | 100 | } |
| 75 | 101 | ||
| 76 | override fun onSupportNavigateUp(): Boolean { | 102 | fun navigateBack() { |
| 77 | navigateBack() | 103 | val navHostFragment = |
| 78 | return true | 104 | supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment |
| 79 | } | 105 | if (navHostFragment.childFragmentManager.backStackEntryCount > 0) { |
| 80 | 106 | navHostFragment.navController.popBackStack() | |
| 81 | private fun navigateBack() { | ||
| 82 | if (supportFragmentManager.backStackEntryCount > 0) { | ||
| 83 | supportFragmentManager.popBackStack() | ||
| 84 | } else { | 107 | } else { |
| 85 | finish() | 108 | finish() |
| 86 | } | 109 | } |
| 87 | } | 110 | } |
| 88 | 111 | ||
| 89 | override fun onCreateOptionsMenu(menu: Menu): Boolean { | ||
| 90 | val inflater = menuInflater | ||
| 91 | inflater.inflate(R.menu.menu_settings, menu) | ||
| 92 | return true | ||
| 93 | } | ||
| 94 | |||
| 95 | override fun onSaveInstanceState(outState: Bundle) { | 112 | override fun onSaveInstanceState(outState: Bundle) { |
| 96 | // Critical: If super method is not called, rotations will be busted. | 113 | // Critical: If super method is not called, rotations will be busted. |
| 97 | super.onSaveInstanceState(outState) | 114 | super.onSaveInstanceState(outState) |
| 98 | presenter.saveState(outState) | 115 | outState.putBoolean(KEY_SHOULD_SAVE, settingsViewModel.shouldSave) |
| 99 | } | 116 | } |
| 100 | 117 | ||
| 101 | override fun onStart() { | 118 | override fun onStart() { |
| 102 | super.onStart() | 119 | super.onStart() |
| 103 | presenter.onStart() | 120 | // TODO: Load custom settings contextually |
| 121 | if (!DirectoryInitialization.areDirectoriesReady) { | ||
| 122 | DirectoryInitialization.start() | ||
| 123 | } | ||
| 104 | } | 124 | } |
| 105 | 125 | ||
| 106 | /** | 126 | /** |
| @@ -110,65 +130,21 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { | |||
| 110 | */ | 130 | */ |
| 111 | override fun onStop() { | 131 | override fun onStop() { |
| 112 | super.onStop() | 132 | super.onStop() |
| 113 | presenter.onStop(isFinishing) | 133 | if (isFinishing && settingsViewModel.shouldSave) { |
| 114 | } | 134 | Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...") |
| 115 | 135 | Settings.saveSettings() | |
| 116 | override fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) { | 136 | NativeLibrary.reloadSettings() |
| 117 | if (!addToStack && settingsFragment != null) { | ||
| 118 | return | ||
| 119 | } | ||
| 120 | |||
| 121 | val transaction = supportFragmentManager.beginTransaction() | ||
| 122 | if (addToStack) { | ||
| 123 | if (areSystemAnimationsEnabled()) { | ||
| 124 | transaction.setCustomAnimations( | ||
| 125 | R.anim.anim_settings_fragment_in, | ||
| 126 | R.anim.anim_settings_fragment_out, | ||
| 127 | 0, | ||
| 128 | R.anim.anim_pop_settings_fragment_out | ||
| 129 | ) | ||
| 130 | } | ||
| 131 | transaction.addToBackStack(null) | ||
| 132 | } | 137 | } |
| 133 | transaction.replace( | ||
| 134 | R.id.frame_content, | ||
| 135 | SettingsFragment.newInstance(menuTag, gameId), | ||
| 136 | FRAGMENT_TAG | ||
| 137 | ) | ||
| 138 | transaction.commit() | ||
| 139 | } | ||
| 140 | |||
| 141 | private fun areSystemAnimationsEnabled(): Boolean { | ||
| 142 | val duration = android.provider.Settings.Global.getFloat( | ||
| 143 | contentResolver, | ||
| 144 | android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, | ||
| 145 | 1f | ||
| 146 | ) | ||
| 147 | val transition = android.provider.Settings.Global.getFloat( | ||
| 148 | contentResolver, | ||
| 149 | android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE, | ||
| 150 | 1f | ||
| 151 | ) | ||
| 152 | return duration != 0f && transition != 0f | ||
| 153 | } | 138 | } |
| 154 | 139 | ||
| 155 | override fun onSettingsFileLoaded() { | 140 | override fun onDestroy() { |
| 156 | val fragment: SettingsFragmentView? = settingsFragment | 141 | settingsViewModel.clear() |
| 157 | fragment?.loadSettingsList() | 142 | super.onDestroy() |
| 158 | } | ||
| 159 | |||
| 160 | override fun onSettingsFileNotFound() { | ||
| 161 | val fragment: SettingsFragmentView? = settingsFragment | ||
| 162 | fragment?.loadSettingsList() | ||
| 163 | } | ||
| 164 | |||
| 165 | override fun onSettingChanged() { | ||
| 166 | presenter.onSettingChanged() | ||
| 167 | } | 143 | } |
| 168 | 144 | ||
| 169 | fun onSettingsReset() { | 145 | fun onSettingsReset() { |
| 170 | // Prevents saving to a non-existent settings file | 146 | // Prevents saving to a non-existent settings file |
| 171 | presenter.onSettingsReset() | 147 | settingsViewModel.shouldSave = false |
| 172 | 148 | ||
| 173 | // Delete settings file because the user may have changed values that do not exist in the UI | 149 | // Delete settings file because the user may have changed values that do not exist in the UI |
| 174 | val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG) | 150 | val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG) |
| @@ -185,47 +161,21 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { | |||
| 185 | finish() | 161 | finish() |
| 186 | } | 162 | } |
| 187 | 163 | ||
| 188 | fun setToolbarTitle(title: String) { | ||
| 189 | binding.toolbarSettingsLayout.title = title | ||
| 190 | } | ||
| 191 | |||
| 192 | private val settingsFragment: SettingsFragment? | ||
| 193 | get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment? | ||
| 194 | |||
| 195 | private fun setInsets() { | 164 | private fun setInsets() { |
| 196 | ViewCompat.setOnApplyWindowInsetsListener( | 165 | ViewCompat.setOnApplyWindowInsetsListener( |
| 197 | binding.frameContent | 166 | binding.navigationBarShade |
| 198 | ) { view: View, windowInsets: WindowInsetsCompat -> | 167 | ) { view: View, windowInsets: WindowInsetsCompat -> |
| 199 | val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) | 168 | val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) |
| 200 | val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) | ||
| 201 | view.updatePadding( | ||
| 202 | left = barInsets.left + cutoutInsets.left, | ||
| 203 | right = barInsets.right + cutoutInsets.right | ||
| 204 | ) | ||
| 205 | 169 | ||
| 206 | val mlpAppBar = binding.appbarSettings.layoutParams as MarginLayoutParams | 170 | val mlpShade = view.layoutParams as MarginLayoutParams |
| 207 | mlpAppBar.leftMargin = barInsets.left + cutoutInsets.left | ||
| 208 | mlpAppBar.rightMargin = barInsets.right + cutoutInsets.right | ||
| 209 | binding.appbarSettings.layoutParams = mlpAppBar | ||
| 210 | |||
| 211 | val mlpShade = binding.navigationBarShade.layoutParams as MarginLayoutParams | ||
| 212 | mlpShade.height = barInsets.bottom | 171 | mlpShade.height = barInsets.bottom |
| 213 | binding.navigationBarShade.layoutParams = mlpShade | 172 | view.layoutParams = mlpShade |
| 214 | 173 | ||
| 215 | windowInsets | 174 | windowInsets |
| 216 | } | 175 | } |
| 217 | } | 176 | } |
| 218 | 177 | ||
| 219 | companion object { | 178 | companion object { |
| 220 | private const val ARG_MENU_TAG = "menu_tag" | 179 | private const val KEY_SHOULD_SAVE = "should_save" |
| 221 | private const val ARG_GAME_ID = "game_id" | ||
| 222 | private const val FRAGMENT_TAG = "settings" | ||
| 223 | |||
| 224 | fun launch(context: Context, menuTag: String?, gameId: String?) { | ||
| 225 | val settings = Intent(context, SettingsActivity::class.java) | ||
| 226 | settings.putExtra(ARG_MENU_TAG, menuTag) | ||
| 227 | settings.putExtra(ARG_GAME_ID, gameId) | ||
| 228 | context.startActivity(settings) | ||
| 229 | } | ||
| 230 | } | 180 | } |
| 231 | } | 181 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt deleted file mode 100644 index fdbad32bf..000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt +++ /dev/null | |||
| @@ -1,81 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.features.settings.ui | ||
| 5 | |||
| 6 | import android.content.Context | ||
| 7 | import android.os.Bundle | ||
| 8 | import java.io.File | ||
| 9 | import org.yuzu.yuzu_emu.NativeLibrary | ||
| 10 | import org.yuzu.yuzu_emu.features.settings.model.Settings | ||
| 11 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | ||
| 12 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization | ||
| 13 | import org.yuzu.yuzu_emu.utils.Log | ||
| 14 | |||
| 15 | class SettingsActivityPresenter(private val activityView: SettingsActivityView) { | ||
| 16 | private var shouldSave = false | ||
| 17 | private lateinit var menuTag: String | ||
| 18 | private lateinit var gameId: String | ||
| 19 | |||
| 20 | fun onCreate(savedInstanceState: Bundle?, menuTag: String, gameId: String) { | ||
| 21 | this.menuTag = menuTag | ||
| 22 | this.gameId = gameId | ||
| 23 | if (savedInstanceState != null) { | ||
| 24 | shouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE) | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | fun onStart() { | ||
| 29 | prepareDirectoriesIfNeeded() | ||
| 30 | } | ||
| 31 | |||
| 32 | private fun loadSettingsUI() { | ||
| 33 | // TODO: Load custom settings contextually | ||
| 34 | activityView.showSettingsFragment(menuTag, false, gameId) | ||
| 35 | activityView.onSettingsFileLoaded() | ||
| 36 | } | ||
| 37 | |||
| 38 | private fun prepareDirectoriesIfNeeded() { | ||
| 39 | val configFile = | ||
| 40 | File( | ||
| 41 | "${DirectoryInitialization.userDirectory}/config/" + | ||
| 42 | "${SettingsFile.FILE_NAME_CONFIG}.ini" | ||
| 43 | ) | ||
| 44 | if (!configFile.exists()) { | ||
| 45 | Log.error( | ||
| 46 | "${DirectoryInitialization.userDirectory}/config/" + | ||
| 47 | "${SettingsFile.FILE_NAME_CONFIG}.ini" | ||
| 48 | ) | ||
| 49 | Log.error("yuzu config file could not be found!") | ||
| 50 | } | ||
| 51 | |||
| 52 | if (!DirectoryInitialization.areDirectoriesReady) { | ||
| 53 | DirectoryInitialization.start(activityView as Context) | ||
| 54 | } | ||
| 55 | loadSettingsUI() | ||
| 56 | } | ||
| 57 | |||
| 58 | fun onStop(finishing: Boolean) { | ||
| 59 | if (finishing && shouldSave) { | ||
| 60 | Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...") | ||
| 61 | Settings.saveSettings() | ||
| 62 | NativeLibrary.reloadSettings() | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | fun onSettingChanged() { | ||
| 67 | shouldSave = true | ||
| 68 | } | ||
| 69 | |||
| 70 | fun onSettingsReset() { | ||
| 71 | shouldSave = false | ||
| 72 | } | ||
| 73 | |||
| 74 | fun saveState(outState: Bundle) { | ||
| 75 | outState.putBoolean(KEY_SHOULD_SAVE, shouldSave) | ||
| 76 | } | ||
| 77 | |||
| 78 | companion object { | ||
| 79 | private const val KEY_SHOULD_SAVE = "should_save" | ||
| 80 | } | ||
| 81 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt deleted file mode 100644 index 07a58b4ea..000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt +++ /dev/null | |||
| @@ -1,38 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.features.settings.ui | ||
| 5 | |||
| 6 | /** | ||
| 7 | * Abstraction for the Activity that manages SettingsFragments. | ||
| 8 | */ | ||
| 9 | interface SettingsActivityView { | ||
| 10 | /** | ||
| 11 | * Show a new SettingsFragment. | ||
| 12 | * | ||
| 13 | * @param menuTag Identifier for the settings group that should be displayed. | ||
| 14 | * @param addToStack Whether or not this fragment should replace a previous one. | ||
| 15 | */ | ||
| 16 | fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Called when a load operation completes. | ||
| 20 | */ | ||
| 21 | fun onSettingsFileLoaded() | ||
| 22 | |||
| 23 | /** | ||
| 24 | * Called when a load operation fails. | ||
| 25 | */ | ||
| 26 | fun onSettingsFileNotFound() | ||
| 27 | |||
| 28 | /** | ||
| 29 | * End the activity. | ||
| 30 | */ | ||
| 31 | fun finish() | ||
| 32 | |||
| 33 | /** | ||
| 34 | * Called by a containing Fragment to tell the Activity that a setting was changed; | ||
| 35 | * unless this has been called, the Activity will not save to disk. | ||
| 36 | */ | ||
| 37 | fun onSettingChanged() | ||
| 38 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt index 27eaaa576..9883c2ec7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt | |||
| @@ -12,7 +12,8 @@ import android.view.LayoutInflater | |||
| 12 | import android.view.ViewGroup | 12 | import android.view.ViewGroup |
| 13 | import android.widget.TextView | 13 | import android.widget.TextView |
| 14 | import androidx.appcompat.app.AlertDialog | 14 | import androidx.appcompat.app.AlertDialog |
| 15 | import androidx.appcompat.app.AppCompatActivity | 15 | import androidx.lifecycle.ViewModelProvider |
| 16 | import androidx.navigation.findNavController | ||
| 16 | import androidx.recyclerview.widget.RecyclerView | 17 | import androidx.recyclerview.widget.RecyclerView |
| 17 | import com.google.android.material.datepicker.MaterialDatePicker | 18 | import com.google.android.material.datepicker.MaterialDatePicker |
| 18 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | 19 | import com.google.android.material.dialog.MaterialAlertDialogBuilder |
| @@ -20,6 +21,7 @@ import com.google.android.material.slider.Slider | |||
| 20 | import com.google.android.material.timepicker.MaterialTimePicker | 21 | import com.google.android.material.timepicker.MaterialTimePicker |
| 21 | import com.google.android.material.timepicker.TimeFormat | 22 | import com.google.android.material.timepicker.TimeFormat |
| 22 | import org.yuzu.yuzu_emu.R | 23 | import org.yuzu.yuzu_emu.R |
| 24 | import org.yuzu.yuzu_emu.SettingsNavigationDirections | ||
| 23 | import org.yuzu.yuzu_emu.databinding.DialogSliderBinding | 25 | import org.yuzu.yuzu_emu.databinding.DialogSliderBinding |
| 24 | import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding | 26 | import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding |
| 25 | import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding | 27 | import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding |
| @@ -30,18 +32,22 @@ import org.yuzu.yuzu_emu.features.settings.model.FloatSetting | |||
| 30 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting | 32 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting |
| 31 | import org.yuzu.yuzu_emu.features.settings.model.view.* | 33 | import org.yuzu.yuzu_emu.features.settings.model.view.* |
| 32 | import org.yuzu.yuzu_emu.features.settings.ui.viewholder.* | 34 | import org.yuzu.yuzu_emu.features.settings.ui.viewholder.* |
| 35 | import org.yuzu.yuzu_emu.model.SettingsViewModel | ||
| 33 | 36 | ||
| 34 | class SettingsAdapter( | 37 | class SettingsAdapter( |
| 35 | private val fragmentView: SettingsFragmentView, | 38 | private val fragment: SettingsFragment, |
| 36 | private val context: Context | 39 | private val context: Context |
| 37 | ) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener { | 40 | ) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener { |
| 38 | private var settings: ArrayList<SettingsItem>? = null | 41 | private var settings = ArrayList<SettingsItem>() |
| 39 | private var clickedItem: SettingsItem? = null | 42 | private var clickedItem: SettingsItem? = null |
| 40 | private var clickedPosition: Int | 43 | private var clickedPosition: Int |
| 41 | private var dialog: AlertDialog? = null | 44 | private var dialog: AlertDialog? = null |
| 42 | private var sliderProgress = 0 | 45 | private var sliderProgress = 0 |
| 43 | private var textSliderValue: TextView? = null | 46 | private var textSliderValue: TextView? = null |
| 44 | 47 | ||
| 48 | private val settingsViewModel: SettingsViewModel | ||
| 49 | get() = ViewModelProvider(fragment.requireActivity())[SettingsViewModel::class.java] | ||
| 50 | |||
| 45 | private var defaultCancelListener = | 51 | private var defaultCancelListener = |
| 46 | DialogInterface.OnClickListener { _: DialogInterface?, _: Int -> closeDialog() } | 52 | DialogInterface.OnClickListener { _: DialogInterface?, _: Int -> closeDialog() } |
| 47 | 53 | ||
| @@ -91,30 +97,22 @@ class SettingsAdapter( | |||
| 91 | holder.bind(getItem(position)) | 97 | holder.bind(getItem(position)) |
| 92 | } | 98 | } |
| 93 | 99 | ||
| 94 | private fun getItem(position: Int): SettingsItem { | 100 | private fun getItem(position: Int): SettingsItem = settings[position] |
| 95 | return settings!![position] | ||
| 96 | } | ||
| 97 | 101 | ||
| 98 | override fun getItemCount(): Int { | 102 | override fun getItemCount(): Int = settings.size |
| 99 | return if (settings != null) { | ||
| 100 | settings!!.size | ||
| 101 | } else { | ||
| 102 | 0 | ||
| 103 | } | ||
| 104 | } | ||
| 105 | 103 | ||
| 106 | override fun getItemViewType(position: Int): Int { | 104 | override fun getItemViewType(position: Int): Int { |
| 107 | return getItem(position).type | 105 | return getItem(position).type |
| 108 | } | 106 | } |
| 109 | 107 | ||
| 110 | fun setSettingsList(settings: ArrayList<SettingsItem>?) { | 108 | fun setSettingsList(settings: ArrayList<SettingsItem>) { |
| 111 | this.settings = settings | 109 | this.settings = settings |
| 112 | notifyDataSetChanged() | 110 | notifyDataSetChanged() |
| 113 | } | 111 | } |
| 114 | 112 | ||
| 115 | fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) { | 113 | fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) { |
| 116 | item.checked = checked | 114 | item.checked = checked |
| 117 | fragmentView.onSettingChanged() | 115 | settingsViewModel.shouldSave = true |
| 118 | } | 116 | } |
| 119 | 117 | ||
| 120 | private fun onSingleChoiceClick(item: SingleChoiceSetting) { | 118 | private fun onSingleChoiceClick(item: SingleChoiceSetting) { |
| @@ -155,7 +153,7 @@ class SettingsAdapter( | |||
| 155 | calendar.timeZone = TimeZone.getTimeZone("UTC") | 153 | calendar.timeZone = TimeZone.getTimeZone("UTC") |
| 156 | 154 | ||
| 157 | var timeFormat: Int = TimeFormat.CLOCK_12H | 155 | var timeFormat: Int = TimeFormat.CLOCK_12H |
| 158 | if (DateFormat.is24HourFormat(fragmentView.activityView as AppCompatActivity)) { | 156 | if (DateFormat.is24HourFormat(context)) { |
| 159 | timeFormat = TimeFormat.CLOCK_24H | 157 | timeFormat = TimeFormat.CLOCK_24H |
| 160 | } | 158 | } |
| 161 | 159 | ||
| @@ -172,7 +170,7 @@ class SettingsAdapter( | |||
| 172 | 170 | ||
| 173 | datePicker.addOnPositiveButtonClickListener { | 171 | datePicker.addOnPositiveButtonClickListener { |
| 174 | timePicker.show( | 172 | timePicker.show( |
| 175 | (fragmentView.activityView as AppCompatActivity).supportFragmentManager, | 173 | fragment.childFragmentManager, |
| 176 | "TimePicker" | 174 | "TimePicker" |
| 177 | ) | 175 | ) |
| 178 | } | 176 | } |
| @@ -181,14 +179,14 @@ class SettingsAdapter( | |||
| 181 | epochTime += timePicker.hour.toLong() * 60 * 60 | 179 | epochTime += timePicker.hour.toLong() * 60 * 60 |
| 182 | epochTime += timePicker.minute.toLong() * 60 | 180 | epochTime += timePicker.minute.toLong() * 60 |
| 183 | if (item.value != epochTime) { | 181 | if (item.value != epochTime) { |
| 184 | fragmentView.onSettingChanged() | 182 | settingsViewModel.shouldSave = true |
| 185 | notifyItemChanged(clickedPosition) | 183 | notifyItemChanged(clickedPosition) |
| 186 | item.value = epochTime | 184 | item.value = epochTime |
| 187 | } | 185 | } |
| 188 | clickedItem = null | 186 | clickedItem = null |
| 189 | } | 187 | } |
| 190 | datePicker.show( | 188 | datePicker.show( |
| 191 | (fragmentView.activityView as AppCompatActivity).supportFragmentManager, | 189 | fragment.childFragmentManager, |
| 192 | "DatePicker" | 190 | "DatePicker" |
| 193 | ) | 191 | ) |
| 194 | } | 192 | } |
| @@ -231,7 +229,8 @@ class SettingsAdapter( | |||
| 231 | } | 229 | } |
| 232 | 230 | ||
| 233 | fun onSubmenuClick(item: SubmenuSetting) { | 231 | fun onSubmenuClick(item: SubmenuSetting) { |
| 234 | fragmentView.loadSubMenu(item.menuKey) | 232 | val action = SettingsNavigationDirections.actionGlobalSettingsFragment(item.menuKey, null) |
| 233 | fragment.view?.findNavController()?.navigate(action) | ||
| 235 | } | 234 | } |
| 236 | 235 | ||
| 237 | override fun onClick(dialog: DialogInterface, which: Int) { | 236 | override fun onClick(dialog: DialogInterface, which: Int) { |
| @@ -240,7 +239,7 @@ class SettingsAdapter( | |||
| 240 | val scSetting = clickedItem as SingleChoiceSetting | 239 | val scSetting = clickedItem as SingleChoiceSetting |
| 241 | val value = getValueForSingleChoiceSelection(scSetting, which) | 240 | val value = getValueForSingleChoiceSelection(scSetting, which) |
| 242 | if (scSetting.selectedValue != value) { | 241 | if (scSetting.selectedValue != value) { |
| 243 | fragmentView.onSettingChanged() | 242 | settingsViewModel.shouldSave = true |
| 244 | } | 243 | } |
| 245 | 244 | ||
| 246 | // Get the backing Setting, which may be null (if for example it was missing from the file) | 245 | // Get the backing Setting, which may be null (if for example it was missing from the file) |
| @@ -251,7 +250,7 @@ class SettingsAdapter( | |||
| 251 | is StringSingleChoiceSetting -> { | 250 | is StringSingleChoiceSetting -> { |
| 252 | val scSetting = clickedItem as StringSingleChoiceSetting | 251 | val scSetting = clickedItem as StringSingleChoiceSetting |
| 253 | val value = scSetting.getValueAt(which) | 252 | val value = scSetting.getValueAt(which) |
| 254 | if (scSetting.selectedValue != value) fragmentView.onSettingChanged() | 253 | if (scSetting.selectedValue != value) settingsViewModel.shouldSave = true |
| 255 | scSetting.selectedValue = value!! | 254 | scSetting.selectedValue = value!! |
| 256 | closeDialog() | 255 | closeDialog() |
| 257 | } | 256 | } |
| @@ -259,7 +258,7 @@ class SettingsAdapter( | |||
| 259 | is SliderSetting -> { | 258 | is SliderSetting -> { |
| 260 | val sliderSetting = clickedItem as SliderSetting | 259 | val sliderSetting = clickedItem as SliderSetting |
| 261 | if (sliderSetting.selectedValue != sliderProgress) { | 260 | if (sliderSetting.selectedValue != sliderProgress) { |
| 262 | fragmentView.onSettingChanged() | 261 | settingsViewModel.shouldSave = true |
| 263 | } | 262 | } |
| 264 | when (sliderSetting.setting) { | 263 | when (sliderSetting.setting) { |
| 265 | is ByteSetting -> { | 264 | is ByteSetting -> { |
| @@ -294,7 +293,7 @@ class SettingsAdapter( | |||
| 294 | .setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int -> | 293 | .setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int -> |
| 295 | setting.reset() | 294 | setting.reset() |
| 296 | notifyItemChanged(position) | 295 | notifyItemChanged(position) |
| 297 | fragmentView.onSettingChanged() | 296 | settingsViewModel.shouldSave = true |
| 298 | } | 297 | } |
| 299 | .setNegativeButton(android.R.string.cancel, null) | 298 | .setNegativeButton(android.R.string.cancel, null) |
| 300 | .show() | 299 | .show() |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt index dc1bf6eb1..de6aebd9d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt | |||
| @@ -3,39 +3,41 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.features.settings.ui | 4 | package org.yuzu.yuzu_emu.features.settings.ui |
| 5 | 5 | ||
| 6 | import android.content.Context | ||
| 7 | import android.os.Bundle | 6 | import android.os.Bundle |
| 8 | import android.view.LayoutInflater | 7 | import android.view.LayoutInflater |
| 9 | import android.view.View | 8 | import android.view.View |
| 10 | import android.view.ViewGroup | 9 | import android.view.ViewGroup |
| 10 | import android.view.ViewGroup.MarginLayoutParams | ||
| 11 | import androidx.core.view.ViewCompat | 11 | import androidx.core.view.ViewCompat |
| 12 | import androidx.core.view.WindowInsetsCompat | 12 | import androidx.core.view.WindowInsetsCompat |
| 13 | import androidx.core.view.updatePadding | 13 | import androidx.core.view.updatePadding |
| 14 | import androidx.fragment.app.Fragment | 14 | import androidx.fragment.app.Fragment |
| 15 | import androidx.fragment.app.activityViewModels | ||
| 16 | import androidx.navigation.fragment.navArgs | ||
| 15 | import androidx.recyclerview.widget.LinearLayoutManager | 17 | import androidx.recyclerview.widget.LinearLayoutManager |
| 16 | import com.google.android.material.divider.MaterialDividerItemDecoration | 18 | import com.google.android.material.divider.MaterialDividerItemDecoration |
| 19 | import com.google.android.material.transition.MaterialSharedAxis | ||
| 20 | import org.yuzu.yuzu_emu.R | ||
| 17 | import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding | 21 | import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding |
| 18 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem | 22 | import org.yuzu.yuzu_emu.model.SettingsViewModel |
| 19 | 23 | ||
| 20 | class SettingsFragment : Fragment(), SettingsFragmentView { | 24 | class SettingsFragment : Fragment() { |
| 21 | override var activityView: SettingsActivityView? = null | 25 | private lateinit var presenter: SettingsFragmentPresenter |
| 22 | |||
| 23 | private val fragmentPresenter = SettingsFragmentPresenter(this) | ||
| 24 | private var settingsAdapter: SettingsAdapter? = null | 26 | private var settingsAdapter: SettingsAdapter? = null |
| 25 | 27 | ||
| 26 | private var _binding: FragmentSettingsBinding? = null | 28 | private var _binding: FragmentSettingsBinding? = null |
| 27 | private val binding get() = _binding!! | 29 | private val binding get() = _binding!! |
| 28 | 30 | ||
| 29 | override fun onAttach(context: Context) { | 31 | private val args by navArgs<SettingsFragmentArgs>() |
| 30 | super.onAttach(context) | 32 | |
| 31 | activityView = requireActivity() as SettingsActivityView | 33 | private val settingsViewModel: SettingsViewModel by activityViewModels() |
| 32 | } | ||
| 33 | 34 | ||
| 34 | override fun onCreate(savedInstanceState: Bundle?) { | 35 | override fun onCreate(savedInstanceState: Bundle?) { |
| 35 | super.onCreate(savedInstanceState) | 36 | super.onCreate(savedInstanceState) |
| 36 | val menuTag = requireArguments().getString(ARGUMENT_MENU_TAG) | 37 | enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) |
| 37 | val gameId = requireArguments().getString(ARGUMENT_GAME_ID) | 38 | returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) |
| 38 | fragmentPresenter.onCreate(menuTag!!, gameId!!) | 39 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) |
| 40 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) | ||
| 39 | } | 41 | } |
| 40 | 42 | ||
| 41 | override fun onCreateView( | 43 | override fun onCreateView( |
| @@ -48,7 +50,14 @@ class SettingsFragment : Fragment(), SettingsFragmentView { | |||
| 48 | } | 50 | } |
| 49 | 51 | ||
| 50 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 52 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 51 | settingsAdapter = SettingsAdapter(this, requireActivity()) | 53 | settingsAdapter = SettingsAdapter(this, requireContext()) |
| 54 | presenter = SettingsFragmentPresenter( | ||
| 55 | settingsViewModel, | ||
| 56 | settingsAdapter!!, | ||
| 57 | args.menuTag, | ||
| 58 | args.game?.gameId ?: "" | ||
| 59 | ) | ||
| 60 | |||
| 52 | val dividerDecoration = MaterialDividerItemDecoration( | 61 | val dividerDecoration = MaterialDividerItemDecoration( |
| 53 | requireContext(), | 62 | requireContext(), |
| 54 | LinearLayoutManager.VERTICAL | 63 | LinearLayoutManager.VERTICAL |
| @@ -56,63 +65,52 @@ class SettingsFragment : Fragment(), SettingsFragmentView { | |||
| 56 | dividerDecoration.isLastItemDecorated = false | 65 | dividerDecoration.isLastItemDecorated = false |
| 57 | binding.listSettings.apply { | 66 | binding.listSettings.apply { |
| 58 | adapter = settingsAdapter | 67 | adapter = settingsAdapter |
| 59 | layoutManager = LinearLayoutManager(activity) | 68 | layoutManager = LinearLayoutManager(requireContext()) |
| 60 | addItemDecoration(dividerDecoration) | 69 | addItemDecoration(dividerDecoration) |
| 61 | } | 70 | } |
| 62 | fragmentPresenter.onViewCreated() | ||
| 63 | 71 | ||
| 64 | setInsets() | 72 | binding.toolbarSettings.setNavigationOnClickListener { |
| 65 | } | 73 | settingsViewModel.setShouldNavigateBack(true) |
| 66 | |||
| 67 | override fun onDetach() { | ||
| 68 | super.onDetach() | ||
| 69 | activityView = null | ||
| 70 | if (settingsAdapter != null) { | ||
| 71 | settingsAdapter!!.closeDialog() | ||
| 72 | } | 74 | } |
| 73 | } | ||
| 74 | 75 | ||
| 75 | override fun showSettingsList(settingsList: ArrayList<SettingsItem>) { | 76 | settingsViewModel.toolbarTitle.observe(viewLifecycleOwner) { |
| 76 | settingsAdapter!!.setSettingsList(settingsList) | 77 | if (it.isNotEmpty()) binding.toolbarSettingsLayout.title = it |
| 77 | } | 78 | } |
| 78 | 79 | ||
| 79 | override fun loadSettingsList() { | 80 | presenter.onViewCreated() |
| 80 | fragmentPresenter.loadSettingsList() | ||
| 81 | } | ||
| 82 | 81 | ||
| 83 | override fun loadSubMenu(menuKey: String) { | 82 | setInsets() |
| 84 | activityView!!.showSettingsFragment( | ||
| 85 | menuKey, | ||
| 86 | true, | ||
| 87 | requireArguments().getString(ARGUMENT_GAME_ID)!! | ||
| 88 | ) | ||
| 89 | } | 83 | } |
| 90 | 84 | ||
| 91 | override fun onSettingChanged() { | 85 | override fun onDetach() { |
| 92 | activityView!!.onSettingChanged() | 86 | super.onDetach() |
| 87 | settingsAdapter?.closeDialog() | ||
| 93 | } | 88 | } |
| 94 | 89 | ||
| 95 | private fun setInsets() { | 90 | private fun setInsets() { |
| 96 | ViewCompat.setOnApplyWindowInsetsListener( | 91 | ViewCompat.setOnApplyWindowInsetsListener( |
| 97 | binding.listSettings | 92 | binding.root |
| 98 | ) { view: View, windowInsets: WindowInsetsCompat -> | 93 | ) { _: View, windowInsets: WindowInsetsCompat -> |
| 99 | val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) | 94 | val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) |
| 100 | view.updatePadding(bottom = insets.bottom) | 95 | val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) |
| 96 | |||
| 97 | val leftInsets = barInsets.left + cutoutInsets.left | ||
| 98 | val rightInsets = barInsets.right + cutoutInsets.right | ||
| 99 | |||
| 100 | val sideMargin = resources.getDimensionPixelSize(R.dimen.spacing_medlarge) | ||
| 101 | val mlpSettingsList = binding.listSettings.layoutParams as MarginLayoutParams | ||
| 102 | mlpSettingsList.leftMargin = sideMargin + leftInsets | ||
| 103 | mlpSettingsList.rightMargin = sideMargin + rightInsets | ||
| 104 | binding.listSettings.layoutParams = mlpSettingsList | ||
| 105 | binding.listSettings.updatePadding( | ||
| 106 | bottom = barInsets.bottom | ||
| 107 | ) | ||
| 108 | |||
| 109 | val mlpAppBar = binding.appbarSettings.layoutParams as MarginLayoutParams | ||
| 110 | mlpAppBar.leftMargin = leftInsets | ||
| 111 | mlpAppBar.rightMargin = rightInsets | ||
| 112 | binding.appbarSettings.layoutParams = mlpAppBar | ||
| 101 | windowInsets | 113 | windowInsets |
| 102 | } | 114 | } |
| 103 | } | 115 | } |
| 104 | |||
| 105 | companion object { | ||
| 106 | private const val ARGUMENT_MENU_TAG = "menu_tag" | ||
| 107 | private const val ARGUMENT_GAME_ID = "game_id" | ||
| 108 | |||
| 109 | fun newInstance(menuTag: String?, gameId: String?): Fragment { | ||
| 110 | val fragment = SettingsFragment() | ||
| 111 | val arguments = Bundle() | ||
| 112 | arguments.putString(ARGUMENT_MENU_TAG, menuTag) | ||
| 113 | arguments.putString(ARGUMENT_GAME_ID, gameId) | ||
| 114 | fragment.arguments = arguments | ||
| 115 | return fragment | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | 116 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index dddbf65bb..ba45c317d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.features.settings.ui | 4 | package org.yuzu.yuzu_emu.features.settings.ui |
| 5 | 5 | ||
| 6 | import android.content.Context | ||
| 6 | import android.content.SharedPreferences | 7 | import android.content.SharedPreferences |
| 7 | import android.os.Build | 8 | import android.os.Build |
| 8 | import android.text.TextUtils | 9 | import android.text.TextUtils |
| @@ -20,36 +21,36 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings | |||
| 20 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting | 21 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting |
| 21 | import org.yuzu.yuzu_emu.features.settings.model.view.* | 22 | import org.yuzu.yuzu_emu.features.settings.model.view.* |
| 22 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 23 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile |
| 23 | import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment | 24 | import org.yuzu.yuzu_emu.model.SettingsViewModel |
| 24 | import org.yuzu.yuzu_emu.utils.ThemeHelper | ||
| 25 | 25 | ||
| 26 | class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) { | 26 | class SettingsFragmentPresenter( |
| 27 | private var menuTag: String? = null | 27 | private val settingsViewModel: SettingsViewModel, |
| 28 | private lateinit var gameId: String | 28 | private val adapter: SettingsAdapter, |
| 29 | private var settingsList: ArrayList<SettingsItem>? = null | 29 | private var menuTag: String, |
| 30 | private var gameId: String | ||
| 31 | ) { | ||
| 32 | private var settingsList = ArrayList<SettingsItem>() | ||
| 30 | 33 | ||
| 31 | private val settingsActivity get() = fragmentView.activityView as SettingsActivity | 34 | private val preferences: SharedPreferences |
| 35 | get() = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 32 | 36 | ||
| 33 | private lateinit var preferences: SharedPreferences | 37 | private val context: Context get() = YuzuApplication.appContext |
| 34 | |||
| 35 | fun onCreate(menuTag: String, gameId: String) { | ||
| 36 | this.gameId = gameId | ||
| 37 | this.menuTag = menuTag | ||
| 38 | } | ||
| 39 | 38 | ||
| 40 | fun onViewCreated() { | 39 | fun onViewCreated() { |
| 41 | preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 42 | loadSettingsList() | 40 | loadSettingsList() |
| 43 | } | 41 | } |
| 44 | 42 | ||
| 45 | fun loadSettingsList() { | 43 | private fun loadSettingsList() { |
| 46 | if (!TextUtils.isEmpty(gameId)) { | 44 | if (!TextUtils.isEmpty(gameId)) { |
| 47 | settingsActivity.setToolbarTitle("Game Settings: $gameId") | 45 | settingsViewModel.setToolbarTitle( |
| 46 | context.getString( | ||
| 47 | R.string.advanced_settings_game, | ||
| 48 | gameId | ||
| 49 | ) | ||
| 50 | ) | ||
| 48 | } | 51 | } |
| 52 | |||
| 49 | val sl = ArrayList<SettingsItem>() | 53 | val sl = ArrayList<SettingsItem>() |
| 50 | if (menuTag == null) { | ||
| 51 | return | ||
| 52 | } | ||
| 53 | when (menuTag) { | 54 | when (menuTag) { |
| 54 | SettingsFile.FILE_NAME_CONFIG -> addConfigSettings(sl) | 55 | SettingsFile.FILE_NAME_CONFIG -> addConfigSettings(sl) |
| 55 | Settings.SECTION_GENERAL -> addGeneralSettings(sl) | 56 | Settings.SECTION_GENERAL -> addGeneralSettings(sl) |
| @@ -69,11 +70,11 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 69 | } | 70 | } |
| 70 | } | 71 | } |
| 71 | settingsList = sl | 72 | settingsList = sl |
| 72 | fragmentView.showSettingsList(settingsList!!) | 73 | adapter.setSettingsList(settingsList) |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | private fun addConfigSettings(sl: ArrayList<SettingsItem>) { | 76 | private fun addConfigSettings(sl: ArrayList<SettingsItem>) { |
| 76 | settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.advanced_settings)) | 77 | settingsViewModel.setToolbarTitle(context.getString(R.string.advanced_settings)) |
| 77 | sl.apply { | 78 | sl.apply { |
| 78 | add(SubmenuSetting(R.string.preferences_general, 0, Settings.SECTION_GENERAL)) | 79 | add(SubmenuSetting(R.string.preferences_general, 0, Settings.SECTION_GENERAL)) |
| 79 | add(SubmenuSetting(R.string.preferences_system, 0, Settings.SECTION_SYSTEM)) | 80 | add(SubmenuSetting(R.string.preferences_system, 0, Settings.SECTION_SYSTEM)) |
| @@ -82,17 +83,14 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 82 | add(SubmenuSetting(R.string.preferences_debug, 0, Settings.SECTION_DEBUG)) | 83 | add(SubmenuSetting(R.string.preferences_debug, 0, Settings.SECTION_DEBUG)) |
| 83 | add( | 84 | add( |
| 84 | RunnableSetting(R.string.reset_to_default, 0, false) { | 85 | RunnableSetting(R.string.reset_to_default, 0, false) { |
| 85 | ResetSettingsDialogFragment().show( | 86 | settingsViewModel.setShouldShowResetSettingsDialog(true) |
| 86 | settingsActivity.supportFragmentManager, | ||
| 87 | ResetSettingsDialogFragment.TAG | ||
| 88 | ) | ||
| 89 | } | 87 | } |
| 90 | ) | 88 | ) |
| 91 | } | 89 | } |
| 92 | } | 90 | } |
| 93 | 91 | ||
| 94 | private fun addGeneralSettings(sl: ArrayList<SettingsItem>) { | 92 | private fun addGeneralSettings(sl: ArrayList<SettingsItem>) { |
| 95 | settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_general)) | 93 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_general)) |
| 96 | sl.apply { | 94 | sl.apply { |
| 97 | add( | 95 | add( |
| 98 | SwitchSetting( | 96 | SwitchSetting( |
| @@ -131,7 +129,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 131 | } | 129 | } |
| 132 | 130 | ||
| 133 | private fun addSystemSettings(sl: ArrayList<SettingsItem>) { | 131 | private fun addSystemSettings(sl: ArrayList<SettingsItem>) { |
| 134 | settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_system)) | 132 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_system)) |
| 135 | sl.apply { | 133 | sl.apply { |
| 136 | add( | 134 | add( |
| 137 | SwitchSetting( | 135 | SwitchSetting( |
| @@ -170,7 +168,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 170 | } | 168 | } |
| 171 | 169 | ||
| 172 | private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) { | 170 | private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) { |
| 173 | settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_graphics)) | 171 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_graphics)) |
| 174 | sl.apply { | 172 | sl.apply { |
| 175 | add( | 173 | add( |
| 176 | SingleChoiceSetting( | 174 | SingleChoiceSetting( |
| @@ -267,7 +265,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 267 | } | 265 | } |
| 268 | 266 | ||
| 269 | private fun addAudioSettings(sl: ArrayList<SettingsItem>) { | 267 | private fun addAudioSettings(sl: ArrayList<SettingsItem>) { |
| 270 | settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_audio)) | 268 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_audio)) |
| 271 | sl.apply { | 269 | sl.apply { |
| 272 | add( | 270 | add( |
| 273 | SingleChoiceSetting( | 271 | SingleChoiceSetting( |
| @@ -292,7 +290,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 292 | } | 290 | } |
| 293 | 291 | ||
| 294 | private fun addThemeSettings(sl: ArrayList<SettingsItem>) { | 292 | private fun addThemeSettings(sl: ArrayList<SettingsItem>) { |
| 295 | settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_theme)) | 293 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_theme)) |
| 296 | sl.apply { | 294 | sl.apply { |
| 297 | val theme: AbstractIntSetting = object : AbstractIntSetting { | 295 | val theme: AbstractIntSetting = object : AbstractIntSetting { |
| 298 | override val int: Int | 296 | override val int: Int |
| @@ -302,7 +300,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 302 | preferences.edit() | 300 | preferences.edit() |
| 303 | .putInt(Settings.PREF_THEME, value) | 301 | .putInt(Settings.PREF_THEME, value) |
| 304 | .apply() | 302 | .apply() |
| 305 | settingsActivity.recreate() | 303 | settingsViewModel.setShouldRecreate(true) |
| 306 | } | 304 | } |
| 307 | 305 | ||
| 308 | override val key: String? = null | 306 | override val key: String? = null |
| @@ -346,7 +344,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 346 | preferences.edit() | 344 | preferences.edit() |
| 347 | .putInt(Settings.PREF_THEME_MODE, value) | 345 | .putInt(Settings.PREF_THEME_MODE, value) |
| 348 | .apply() | 346 | .apply() |
| 349 | ThemeHelper.setThemeMode(settingsActivity) | 347 | settingsViewModel.setShouldRecreate(true) |
| 350 | } | 348 | } |
| 351 | 349 | ||
| 352 | override val key: String? = null | 350 | override val key: String? = null |
| @@ -357,6 +355,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 357 | preferences.edit() | 355 | preferences.edit() |
| 358 | .putInt(Settings.PREF_BLACK_BACKGROUNDS, defaultValue) | 356 | .putInt(Settings.PREF_BLACK_BACKGROUNDS, defaultValue) |
| 359 | .apply() | 357 | .apply() |
| 358 | settingsViewModel.setShouldRecreate(true) | ||
| 360 | } | 359 | } |
| 361 | } | 360 | } |
| 362 | 361 | ||
| @@ -378,7 +377,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 378 | preferences.edit() | 377 | preferences.edit() |
| 379 | .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value) | 378 | .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value) |
| 380 | .apply() | 379 | .apply() |
| 381 | settingsActivity.recreate() | 380 | settingsViewModel.setShouldRecreate(true) |
| 382 | } | 381 | } |
| 383 | 382 | ||
| 384 | override val key: String? = null | 383 | override val key: String? = null |
| @@ -389,6 +388,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 389 | preferences.edit() | 388 | preferences.edit() |
| 390 | .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, defaultValue) | 389 | .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, defaultValue) |
| 391 | .apply() | 390 | .apply() |
| 391 | settingsViewModel.setShouldRecreate(true) | ||
| 392 | } | 392 | } |
| 393 | } | 393 | } |
| 394 | 394 | ||
| @@ -403,7 +403,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | |||
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | private fun addDebugSettings(sl: ArrayList<SettingsItem>) { | 405 | private fun addDebugSettings(sl: ArrayList<SettingsItem>) { |
| 406 | settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_debug)) | 406 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_debug)) |
| 407 | sl.apply { | 407 | sl.apply { |
| 408 | add(HeaderSetting(R.string.gpu)) | 408 | add(HeaderSetting(R.string.gpu)) |
| 409 | add( | 409 | add( |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt deleted file mode 100644 index a4d7a80aa..000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt +++ /dev/null | |||
| @@ -1,42 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.features.settings.ui | ||
| 5 | |||
| 6 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem | ||
| 7 | |||
| 8 | /** | ||
| 9 | * Abstraction for a screen showing a list of settings. Instances of | ||
| 10 | * this type of view will each display a layer of the setting hierarchy. | ||
| 11 | */ | ||
| 12 | interface SettingsFragmentView { | ||
| 13 | /** | ||
| 14 | * Pass an ArrayList to the View so that it can be displayed on screen. | ||
| 15 | * | ||
| 16 | * @param settingsList The result of converting the HashMap to an ArrayList | ||
| 17 | */ | ||
| 18 | fun showSettingsList(settingsList: ArrayList<SettingsItem>) | ||
| 19 | |||
| 20 | /** | ||
| 21 | * Instructs the Fragment to load the settings screen. | ||
| 22 | */ | ||
| 23 | fun loadSettingsList() | ||
| 24 | |||
| 25 | /** | ||
| 26 | * @return The Fragment's containing activity. | ||
| 27 | */ | ||
| 28 | val activityView: SettingsActivityView? | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Tell the Fragment to tell the containing Activity to show a new | ||
| 32 | * Fragment containing a submenu of settings. | ||
| 33 | * | ||
| 34 | * @param menuKey Identifier for the settings group that should be shown. | ||
| 35 | */ | ||
| 36 | fun loadSubMenu(menuKey: String) | ||
| 37 | |||
| 38 | /** | ||
| 39 | * Have the fragment tell the containing Activity that a setting was modified. | ||
| 40 | */ | ||
| 41 | fun onSettingChanged() | ||
| 42 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index 09e93a017..70df3af80 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt | |||
| @@ -28,6 +28,7 @@ import androidx.fragment.app.Fragment | |||
| 28 | import androidx.lifecycle.Lifecycle | 28 | import androidx.lifecycle.Lifecycle |
| 29 | import androidx.lifecycle.lifecycleScope | 29 | import androidx.lifecycle.lifecycleScope |
| 30 | import androidx.lifecycle.repeatOnLifecycle | 30 | import androidx.lifecycle.repeatOnLifecycle |
| 31 | import androidx.navigation.findNavController | ||
| 31 | import androidx.navigation.fragment.navArgs | 32 | import androidx.navigation.fragment.navArgs |
| 32 | import androidx.preference.PreferenceManager | 33 | import androidx.preference.PreferenceManager |
| 33 | import androidx.window.layout.FoldingFeature | 34 | import androidx.window.layout.FoldingFeature |
| @@ -37,6 +38,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder | |||
| 37 | import com.google.android.material.slider.Slider | 38 | import com.google.android.material.slider.Slider |
| 38 | import kotlinx.coroutines.Dispatchers | 39 | import kotlinx.coroutines.Dispatchers |
| 39 | import kotlinx.coroutines.launch | 40 | import kotlinx.coroutines.launch |
| 41 | import org.yuzu.yuzu_emu.HomeNavigationDirections | ||
| 40 | import org.yuzu.yuzu_emu.NativeLibrary | 42 | import org.yuzu.yuzu_emu.NativeLibrary |
| 41 | import org.yuzu.yuzu_emu.R | 43 | import org.yuzu.yuzu_emu.R |
| 42 | import org.yuzu.yuzu_emu.YuzuApplication | 44 | import org.yuzu.yuzu_emu.YuzuApplication |
| @@ -45,7 +47,6 @@ import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding | |||
| 45 | import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding | 47 | import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding |
| 46 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting | 48 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting |
| 47 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 49 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 48 | import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity | ||
| 49 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 50 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile |
| 50 | import org.yuzu.yuzu_emu.overlay.InputOverlay | 51 | import org.yuzu.yuzu_emu.overlay.InputOverlay |
| 51 | import org.yuzu.yuzu_emu.utils.* | 52 | import org.yuzu.yuzu_emu.utils.* |
| @@ -139,7 +140,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | R.id.menu_settings -> { | 142 | R.id.menu_settings -> { |
| 142 | SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") | 143 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( |
| 144 | null, | ||
| 145 | SettingsFile.FILE_NAME_CONFIG | ||
| 146 | ) | ||
| 147 | binding.root.findNavController().navigate(action) | ||
| 143 | true | 148 | true |
| 144 | } | 149 | } |
| 145 | 150 | ||
| @@ -211,7 +216,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 211 | override fun onResume() { | 216 | override fun onResume() { |
| 212 | super.onResume() | 217 | super.onResume() |
| 213 | if (!DirectoryInitialization.areDirectoriesReady) { | 218 | if (!DirectoryInitialization.areDirectoriesReady) { |
| 214 | DirectoryInitialization.start(requireContext()) | 219 | DirectoryInitialization.start() |
| 215 | } | 220 | } |
| 216 | 221 | ||
| 217 | updateScreenLayout() | 222 | updateScreenLayout() |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt index d5e793491..cbbe14d22 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt | |||
| @@ -25,17 +25,18 @@ import androidx.core.view.updatePadding | |||
| 25 | import androidx.documentfile.provider.DocumentFile | 25 | import androidx.documentfile.provider.DocumentFile |
| 26 | import androidx.fragment.app.Fragment | 26 | import androidx.fragment.app.Fragment |
| 27 | import androidx.fragment.app.activityViewModels | 27 | import androidx.fragment.app.activityViewModels |
| 28 | import androidx.navigation.findNavController | ||
| 28 | import androidx.navigation.fragment.findNavController | 29 | import androidx.navigation.fragment.findNavController |
| 29 | import androidx.recyclerview.widget.LinearLayoutManager | 30 | import androidx.recyclerview.widget.LinearLayoutManager |
| 30 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | 31 | import com.google.android.material.dialog.MaterialAlertDialogBuilder |
| 31 | import com.google.android.material.transition.MaterialSharedAxis | 32 | import com.google.android.material.transition.MaterialSharedAxis |
| 32 | import org.yuzu.yuzu_emu.BuildConfig | 33 | import org.yuzu.yuzu_emu.BuildConfig |
| 34 | import org.yuzu.yuzu_emu.HomeNavigationDirections | ||
| 33 | import org.yuzu.yuzu_emu.R | 35 | import org.yuzu.yuzu_emu.R |
| 34 | import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter | 36 | import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter |
| 35 | import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding | 37 | import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding |
| 36 | import org.yuzu.yuzu_emu.features.DocumentProvider | 38 | import org.yuzu.yuzu_emu.features.DocumentProvider |
| 37 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 39 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 38 | import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity | ||
| 39 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 40 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile |
| 40 | import org.yuzu.yuzu_emu.model.HomeSetting | 41 | import org.yuzu.yuzu_emu.model.HomeSetting |
| 41 | import org.yuzu.yuzu_emu.model.HomeViewModel | 42 | import org.yuzu.yuzu_emu.model.HomeViewModel |
| @@ -74,7 +75,13 @@ class HomeSettingsFragment : Fragment() { | |||
| 74 | R.string.advanced_settings, | 75 | R.string.advanced_settings, |
| 75 | R.string.settings_description, | 76 | R.string.settings_description, |
| 76 | R.drawable.ic_settings, | 77 | R.drawable.ic_settings, |
| 77 | { SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") } | 78 | { |
| 79 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( | ||
| 80 | null, | ||
| 81 | SettingsFile.FILE_NAME_CONFIG | ||
| 82 | ) | ||
| 83 | binding.root.findNavController().navigate(action) | ||
| 84 | } | ||
| 78 | ) | 85 | ) |
| 79 | ) | 86 | ) |
| 80 | add( | 87 | add( |
| @@ -90,7 +97,13 @@ class HomeSettingsFragment : Fragment() { | |||
| 90 | R.string.preferences_theme, | 97 | R.string.preferences_theme, |
| 91 | R.string.theme_and_color_description, | 98 | R.string.theme_and_color_description, |
| 92 | R.drawable.ic_palette, | 99 | R.drawable.ic_palette, |
| 93 | { SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") } | 100 | { |
| 101 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( | ||
| 102 | null, | ||
| 103 | Settings.SECTION_THEME | ||
| 104 | ) | ||
| 105 | binding.root.findNavController().navigate(action) | ||
| 106 | } | ||
| 94 | ) | 107 | ) |
| 95 | ) | 108 | ) |
| 96 | add( | 109 | add( |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt new file mode 100644 index 000000000..1763341e2 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | import androidx.lifecycle.LiveData | ||
| 7 | import androidx.lifecycle.MutableLiveData | ||
| 8 | import androidx.lifecycle.ViewModel | ||
| 9 | |||
| 10 | class SettingsViewModel : ViewModel() { | ||
| 11 | var game: Game? = null | ||
| 12 | |||
| 13 | var shouldSave = false | ||
| 14 | |||
| 15 | private val _toolbarTitle = MutableLiveData("") | ||
| 16 | val toolbarTitle: LiveData<String> get() = _toolbarTitle | ||
| 17 | |||
| 18 | private val _shouldRecreate = MutableLiveData(false) | ||
| 19 | val shouldRecreate: LiveData<Boolean> get() = _shouldRecreate | ||
| 20 | |||
| 21 | private val _shouldNavigateBack = MutableLiveData(false) | ||
| 22 | val shouldNavigateBack: LiveData<Boolean> get() = _shouldNavigateBack | ||
| 23 | |||
| 24 | private val _shouldShowResetSettingsDialog = MutableLiveData(false) | ||
| 25 | val shouldShowResetSettingsDialog: LiveData<Boolean> get() = _shouldShowResetSettingsDialog | ||
| 26 | |||
| 27 | fun setToolbarTitle(value: String) { | ||
| 28 | _toolbarTitle.value = value | ||
| 29 | } | ||
| 30 | |||
| 31 | fun setShouldRecreate(value: Boolean) { | ||
| 32 | _shouldRecreate.value = value | ||
| 33 | } | ||
| 34 | |||
| 35 | fun setShouldNavigateBack(value: Boolean) { | ||
| 36 | _shouldNavigateBack.value = value | ||
| 37 | } | ||
| 38 | |||
| 39 | fun setShouldShowResetSettingsDialog(value: Boolean) { | ||
| 40 | _shouldShowResetSettingsDialog.value = value | ||
| 41 | } | ||
| 42 | |||
| 43 | fun clear() { | ||
| 44 | game = null | ||
| 45 | shouldSave = false | ||
| 46 | } | ||
| 47 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index d8dbf1f45..7735452e5 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt | |||
| @@ -33,13 +33,13 @@ import java.io.IOException | |||
| 33 | import kotlinx.coroutines.Dispatchers | 33 | import kotlinx.coroutines.Dispatchers |
| 34 | import kotlinx.coroutines.launch | 34 | import kotlinx.coroutines.launch |
| 35 | import kotlinx.coroutines.withContext | 35 | import kotlinx.coroutines.withContext |
| 36 | import org.yuzu.yuzu_emu.HomeNavigationDirections | ||
| 36 | import org.yuzu.yuzu_emu.NativeLibrary | 37 | import org.yuzu.yuzu_emu.NativeLibrary |
| 37 | import org.yuzu.yuzu_emu.R | 38 | import org.yuzu.yuzu_emu.R |
| 38 | import org.yuzu.yuzu_emu.activities.EmulationActivity | 39 | import org.yuzu.yuzu_emu.activities.EmulationActivity |
| 39 | import org.yuzu.yuzu_emu.databinding.ActivityMainBinding | 40 | import org.yuzu.yuzu_emu.databinding.ActivityMainBinding |
| 40 | import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding | 41 | import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding |
| 41 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 42 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 42 | import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity | ||
| 43 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 43 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile |
| 44 | import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment | 44 | import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment |
| 45 | import org.yuzu.yuzu_emu.fragments.LongMessageDialogFragment | 45 | import org.yuzu.yuzu_emu.fragments.LongMessageDialogFragment |
| @@ -105,11 +105,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 105 | when (it.itemId) { | 105 | when (it.itemId) { |
| 106 | R.id.gamesFragment -> gamesViewModel.setShouldScrollToTop(true) | 106 | R.id.gamesFragment -> gamesViewModel.setShouldScrollToTop(true) |
| 107 | R.id.searchFragment -> gamesViewModel.setSearchFocused(true) | 107 | R.id.searchFragment -> gamesViewModel.setSearchFocused(true) |
| 108 | R.id.homeSettingsFragment -> SettingsActivity.launch( | 108 | R.id.homeSettingsFragment -> { |
| 109 | this, | 109 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( |
| 110 | SettingsFile.FILE_NAME_CONFIG, | 110 | null, |
| 111 | "" | 111 | SettingsFile.FILE_NAME_CONFIG |
| 112 | ) | 112 | ) |
| 113 | navHostFragment.navController.navigate(action) | ||
| 114 | } | ||
| 113 | } | 115 | } |
| 114 | } | 116 | } |
| 115 | 117 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt index 2ee63697e..3c9f6bad0 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt | |||
| @@ -3,18 +3,18 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.utils | 4 | package org.yuzu.yuzu_emu.utils |
| 5 | 5 | ||
| 6 | import android.content.Context | ||
| 7 | import java.io.IOException | 6 | import java.io.IOException |
| 8 | import org.yuzu.yuzu_emu.NativeLibrary | 7 | import org.yuzu.yuzu_emu.NativeLibrary |
| 8 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 9 | 9 | ||
| 10 | object DirectoryInitialization { | 10 | object DirectoryInitialization { |
| 11 | private var userPath: String? = null | 11 | private var userPath: String? = null |
| 12 | 12 | ||
| 13 | var areDirectoriesReady: Boolean = false | 13 | var areDirectoriesReady: Boolean = false |
| 14 | 14 | ||
| 15 | fun start(context: Context) { | 15 | fun start() { |
| 16 | if (!areDirectoriesReady) { | 16 | if (!areDirectoriesReady) { |
| 17 | initializeInternalStorage(context) | 17 | initializeInternalStorage() |
| 18 | NativeLibrary.initializeEmulation() | 18 | NativeLibrary.initializeEmulation() |
| 19 | areDirectoriesReady = true | 19 | areDirectoriesReady = true |
| 20 | } | 20 | } |
| @@ -26,9 +26,9 @@ object DirectoryInitialization { | |||
| 26 | return userPath | 26 | return userPath |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | private fun initializeInternalStorage(context: Context) { | 29 | private fun initializeInternalStorage() { |
| 30 | try { | 30 | try { |
| 31 | userPath = context.getExternalFilesDir(null)!!.canonicalPath | 31 | userPath = YuzuApplication.appContext.getExternalFilesDir(null)!!.canonicalPath |
| 32 | NativeLibrary.setAppDirectory(userPath!!) | 32 | NativeLibrary.setAppDirectory(userPath!!) |
| 33 | } catch (e: IOException) { | 33 | } catch (e: IOException) { |
| 34 | e.printStackTrace() | 34 | e.printStackTrace() |
diff --git a/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml b/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml deleted file mode 100644 index 9f49c133a..000000000 --- a/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | |||
| 4 | <alpha | ||
| 5 | android:duration="125" | ||
| 6 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 7 | android:fromAlpha="1" | ||
| 8 | android:toAlpha="0" /> | ||
| 9 | |||
| 10 | <translate | ||
| 11 | android:duration="125" | ||
| 12 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 13 | android:fromXDelta="0" | ||
| 14 | android:toXDelta="-75" /> | ||
| 15 | |||
| 16 | </set> | ||
diff --git a/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml b/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml deleted file mode 100644 index 82fd719db..000000000 --- a/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | |||
| 4 | <alpha | ||
| 5 | android:duration="@android:integer/config_shortAnimTime" | ||
| 6 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 7 | android:fromAlpha="0" | ||
| 8 | android:toAlpha="1" /> | ||
| 9 | |||
| 10 | <translate | ||
| 11 | android:duration="@android:integer/config_shortAnimTime" | ||
| 12 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 13 | android:fromXDelta="-200" | ||
| 14 | android:toXDelta="0" /> | ||
| 15 | |||
| 16 | </set> | ||
diff --git a/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml b/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml deleted file mode 100644 index 5892128f1..000000000 --- a/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | |||
| 4 | <alpha | ||
| 5 | android:duration="125" | ||
| 6 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 7 | android:fromAlpha="1" | ||
| 8 | android:toAlpha="0" /> | ||
| 9 | |||
| 10 | <translate | ||
| 11 | android:duration="125" | ||
| 12 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 13 | android:fromXDelta="0" | ||
| 14 | android:toXDelta="75" /> | ||
| 15 | |||
| 16 | </set> | ||
diff --git a/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml b/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml deleted file mode 100644 index 98e0cf8bd..000000000 --- a/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | |||
| 4 | <alpha | ||
| 5 | android:duration="@android:integer/config_shortAnimTime" | ||
| 6 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 7 | android:fromAlpha="0" | ||
| 8 | android:toAlpha="1" /> | ||
| 9 | |||
| 10 | <translate | ||
| 11 | android:duration="@android:integer/config_shortAnimTime" | ||
| 12 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 13 | android:fromXDelta="200" | ||
| 14 | android:toXDelta="0" /> | ||
| 15 | |||
| 16 | </set> | ||
diff --git a/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml b/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml deleted file mode 100644 index 77a40a4d1..000000000 --- a/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml +++ /dev/null | |||
| @@ -1,10 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | |||
| 4 | <alpha | ||
| 5 | android:duration="@android:integer/config_shortAnimTime" | ||
| 6 | android:interpolator="@android:anim/decelerate_interpolator" | ||
| 7 | android:fromAlpha="1" | ||
| 8 | android:toAlpha="0" /> | ||
| 9 | |||
| 10 | </set> | ||
diff --git a/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml b/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml deleted file mode 100644 index 4612aee13..000000000 --- a/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml +++ /dev/null | |||
| @@ -1,20 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | |||
| 4 | <objectAnimator | ||
| 5 | android:propertyName="translationX" | ||
| 6 | android:valueType="floatType" | ||
| 7 | android:valueFrom="-1280dp" | ||
| 8 | android:valueTo="0" | ||
| 9 | android:interpolator="@android:interpolator/decelerate_quad" | ||
| 10 | android:duration="300"/> | ||
| 11 | |||
| 12 | <objectAnimator | ||
| 13 | android:propertyName="alpha" | ||
| 14 | android:valueType="floatType" | ||
| 15 | android:valueFrom="0" | ||
| 16 | android:valueTo="1" | ||
| 17 | android:interpolator="@android:interpolator/accelerate_quad" | ||
| 18 | android:duration="300"/> | ||
| 19 | |||
| 20 | </set> \ No newline at end of file | ||
diff --git a/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml b/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml deleted file mode 100644 index c00478946..000000000 --- a/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml +++ /dev/null | |||
| @@ -1,21 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <set xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | |||
| 4 | <!-- This animation is used ONLY when a submenu is replaced. --> | ||
| 5 | <objectAnimator | ||
| 6 | android:propertyName="translationX" | ||
| 7 | android:valueType="floatType" | ||
| 8 | android:valueFrom="0" | ||
| 9 | android:valueTo="-1280dp" | ||
| 10 | android:interpolator="@android:interpolator/decelerate_quad" | ||
| 11 | android:duration="200"/> | ||
| 12 | |||
| 13 | <objectAnimator | ||
| 14 | android:propertyName="alpha" | ||
| 15 | android:valueType="floatType" | ||
| 16 | android:valueFrom="1" | ||
| 17 | android:valueTo="0" | ||
| 18 | android:interpolator="@android:interpolator/decelerate_quad" | ||
| 19 | android:duration="200"/> | ||
| 20 | |||
| 21 | </set> \ No newline at end of file | ||
diff --git a/src/android/app/src/main/res/layout/activity_settings.xml b/src/android/app/src/main/res/layout/activity_settings.xml index 14ae83b04..8a026a30a 100644 --- a/src/android/app/src/main/res/layout/activity_settings.xml +++ b/src/android/app/src/main/res/layout/activity_settings.xml | |||
| @@ -1,42 +1,24 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <androidx.coordinatorlayout.widget.CoordinatorLayout | 2 | <androidx.constraintlayout.widget.ConstraintLayout |
| 3 | android:id="@+id/coordinator_main" | ||
| 4 | xmlns:android="http://schemas.android.com/apk/res/android" | 3 | xmlns:android="http://schemas.android.com/apk/res/android" |
| 5 | xmlns:app="http://schemas.android.com/apk/res-auto" | 4 | xmlns:app="http://schemas.android.com/apk/res-auto" |
| 5 | xmlns:tools="http://schemas.android.com/tools" | ||
| 6 | android:id="@+id/constraint_settings" | ||
| 6 | android:layout_width="match_parent" | 7 | android:layout_width="match_parent" |
| 7 | android:layout_height="match_parent" | 8 | android:layout_height="match_parent" |
| 8 | android:background="?attr/colorSurface"> | 9 | android:background="?attr/colorSurface"> |
| 9 | 10 | ||
| 10 | <com.google.android.material.appbar.AppBarLayout | 11 | <androidx.fragment.app.FragmentContainerView |
| 11 | android:id="@+id/appbar_settings" | 12 | android:id="@+id/fragment_container" |
| 12 | android:layout_width="match_parent" | 13 | android:name="androidx.navigation.fragment.NavHostFragment" |
| 13 | android:layout_height="wrap_content" | 14 | android:layout_width="0dp" |
| 14 | android:fitsSystemWindows="true" | 15 | android:layout_height="0dp" |
| 15 | app:elevation="0dp"> | 16 | app:defaultNavHost="true" |
| 16 | 17 | app:layout_constraintBottom_toBottomOf="parent" | |
| 17 | <com.google.android.material.appbar.CollapsingToolbarLayout | 18 | app:layout_constraintLeft_toLeftOf="parent" |
| 18 | style="?attr/collapsingToolbarLayoutMediumStyle" | 19 | app:layout_constraintRight_toRightOf="parent" |
| 19 | android:id="@+id/toolbar_settings_layout" | 20 | app:layout_constraintTop_toTopOf="parent" |
| 20 | android:layout_width="match_parent" | 21 | tools:layout="@layout/fragment_settings" /> |
| 21 | android:layout_height="?attr/collapsingToolbarLayoutMediumSize" | ||
| 22 | app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> | ||
| 23 | |||
| 24 | <com.google.android.material.appbar.MaterialToolbar | ||
| 25 | android:id="@+id/toolbar_settings" | ||
| 26 | android:layout_width="match_parent" | ||
| 27 | android:layout_height="?attr/actionBarSize" | ||
| 28 | app:layout_collapseMode="pin" /> | ||
| 29 | |||
| 30 | </com.google.android.material.appbar.CollapsingToolbarLayout> | ||
| 31 | |||
| 32 | </com.google.android.material.appbar.AppBarLayout> | ||
| 33 | |||
| 34 | <FrameLayout | ||
| 35 | android:id="@+id/frame_content" | ||
| 36 | android:layout_width="match_parent" | ||
| 37 | android:layout_height="match_parent" | ||
| 38 | android:layout_marginHorizontal="12dp" | ||
| 39 | app:layout_behavior="@string/appbar_scrolling_view_behavior" /> | ||
| 40 | 22 | ||
| 41 | <View | 23 | <View |
| 42 | android:id="@+id/navigation_bar_shade" | 24 | android:id="@+id/navigation_bar_shade" |
| @@ -45,6 +27,8 @@ | |||
| 45 | android:background="@android:color/transparent" | 27 | android:background="@android:color/transparent" |
| 46 | android:clickable="false" | 28 | android:clickable="false" |
| 47 | android:focusable="false" | 29 | android:focusable="false" |
| 48 | android:layout_gravity="bottom|center_horizontal" /> | 30 | app:layout_constraintBottom_toBottomOf="parent" |
| 31 | app:layout_constraintEnd_toEndOf="parent" | ||
| 32 | app:layout_constraintStart_toStartOf="parent" /> | ||
| 49 | 33 | ||
| 50 | </androidx.coordinatorlayout.widget.CoordinatorLayout> | 34 | </androidx.constraintlayout.widget.ConstraintLayout> |
diff --git a/src/android/app/src/main/res/layout/fragment_settings.xml b/src/android/app/src/main/res/layout/fragment_settings.xml index 167720347..ebedbf1ec 100644 --- a/src/android/app/src/main/res/layout/fragment_settings.xml +++ b/src/android/app/src/main/res/layout/fragment_settings.xml | |||
| @@ -1,14 +1,41 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <FrameLayout | 2 | <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | xmlns:android="http://schemas.android.com/apk/res/android" | 3 | xmlns:app="http://schemas.android.com/apk/res-auto" |
| 4 | android:id="@+id/coordinator_main" | ||
| 4 | android:layout_width="match_parent" | 5 | android:layout_width="match_parent" |
| 5 | android:layout_height="match_parent"> | 6 | android:layout_height="match_parent" |
| 7 | android:background="?attr/colorSurface"> | ||
| 8 | |||
| 9 | <com.google.android.material.appbar.AppBarLayout | ||
| 10 | android:id="@+id/appbar_settings" | ||
| 11 | android:layout_width="match_parent" | ||
| 12 | android:layout_height="wrap_content" | ||
| 13 | android:fitsSystemWindows="true" | ||
| 14 | app:elevation="0dp"> | ||
| 15 | |||
| 16 | <com.google.android.material.appbar.CollapsingToolbarLayout | ||
| 17 | android:id="@+id/toolbar_settings_layout" | ||
| 18 | style="?attr/collapsingToolbarLayoutMediumStyle" | ||
| 19 | android:layout_width="match_parent" | ||
| 20 | android:layout_height="?attr/collapsingToolbarLayoutMediumSize" | ||
| 21 | app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> | ||
| 22 | |||
| 23 | <com.google.android.material.appbar.MaterialToolbar | ||
| 24 | android:id="@+id/toolbar_settings" | ||
| 25 | android:layout_width="match_parent" | ||
| 26 | android:layout_height="?attr/actionBarSize" | ||
| 27 | app:layout_collapseMode="pin" | ||
| 28 | app:navigationIcon="@drawable/ic_back" /> | ||
| 29 | |||
| 30 | </com.google.android.material.appbar.CollapsingToolbarLayout> | ||
| 31 | |||
| 32 | </com.google.android.material.appbar.AppBarLayout> | ||
| 6 | 33 | ||
| 7 | <androidx.recyclerview.widget.RecyclerView | 34 | <androidx.recyclerview.widget.RecyclerView |
| 8 | android:id="@+id/list_settings" | 35 | android:id="@+id/list_settings" |
| 9 | android:layout_width="match_parent" | 36 | android:layout_width="match_parent" |
| 10 | android:layout_height="match_parent" | 37 | android:layout_height="match_parent" |
| 11 | android:background="?attr/colorSurface" | 38 | android:clipToPadding="false" |
| 12 | android:clipToPadding="false" /> | 39 | app:layout_behavior="@string/appbar_scrolling_view_behavior" /> |
| 13 | 40 | ||
| 14 | </FrameLayout> | 41 | </androidx.coordinatorlayout.widget.CoordinatorLayout> |
diff --git a/src/android/app/src/main/res/menu/menu_settings.xml b/src/android/app/src/main/res/menu/menu_settings.xml deleted file mode 100644 index 1fe7aa6d4..000000000 --- a/src/android/app/src/main/res/menu/menu_settings.xml +++ /dev/null | |||
| @@ -1,2 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <menu /> \ No newline at end of file | ||
diff --git a/src/android/app/src/main/res/navigation/emulation_navigation.xml b/src/android/app/src/main/res/navigation/emulation_navigation.xml index 8208f4c2c..2a3c23d55 100644 --- a/src/android/app/src/main/res/navigation/emulation_navigation.xml +++ b/src/android/app/src/main/res/navigation/emulation_navigation.xml | |||
| @@ -15,4 +15,21 @@ | |||
| 15 | app:argType="org.yuzu.yuzu_emu.model.Game" /> | 15 | app:argType="org.yuzu.yuzu_emu.model.Game" /> |
| 16 | </fragment> | 16 | </fragment> |
| 17 | 17 | ||
| 18 | <activity | ||
| 19 | android:id="@+id/settingsActivity" | ||
| 20 | android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity" | ||
| 21 | android:label="SettingsActivity"> | ||
| 22 | <argument | ||
| 23 | android:name="game" | ||
| 24 | app:argType="org.yuzu.yuzu_emu.model.Game" | ||
| 25 | app:nullable="true" /> | ||
| 26 | <argument | ||
| 27 | android:name="menuTag" | ||
| 28 | app:argType="string" /> | ||
| 29 | </activity> | ||
| 30 | |||
| 31 | <action | ||
| 32 | android:id="@+id/action_global_settingsActivity" | ||
| 33 | app:destination="@id/settingsActivity" /> | ||
| 34 | |||
| 18 | </navigation> | 35 | </navigation> |
diff --git a/src/android/app/src/main/res/navigation/home_navigation.xml b/src/android/app/src/main/res/navigation/home_navigation.xml index fcebba726..fb8e14448 100644 --- a/src/android/app/src/main/res/navigation/home_navigation.xml +++ b/src/android/app/src/main/res/navigation/home_navigation.xml | |||
| @@ -70,4 +70,21 @@ | |||
| 70 | app:destination="@id/emulationActivity" | 70 | app:destination="@id/emulationActivity" |
| 71 | app:launchSingleTop="true" /> | 71 | app:launchSingleTop="true" /> |
| 72 | 72 | ||
| 73 | <activity | ||
| 74 | android:id="@+id/settingsActivity" | ||
| 75 | android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity" | ||
| 76 | android:label="SettingsActivity"> | ||
| 77 | <argument | ||
| 78 | android:name="game" | ||
| 79 | app:argType="org.yuzu.yuzu_emu.model.Game" | ||
| 80 | app:nullable="true" /> | ||
| 81 | <argument | ||
| 82 | android:name="menuTag" | ||
| 83 | app:argType="string" /> | ||
| 84 | </activity> | ||
| 85 | |||
| 86 | <action | ||
| 87 | android:id="@+id/action_global_settingsActivity" | ||
| 88 | app:destination="@id/settingsActivity" /> | ||
| 89 | |||
| 73 | </navigation> | 90 | </navigation> |
diff --git a/src/android/app/src/main/res/navigation/settings_navigation.xml b/src/android/app/src/main/res/navigation/settings_navigation.xml new file mode 100644 index 000000000..b36200c65 --- /dev/null +++ b/src/android/app/src/main/res/navigation/settings_navigation.xml | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <navigation xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | xmlns:app="http://schemas.android.com/apk/res-auto" | ||
| 4 | android:id="@+id/settings_navigation" | ||
| 5 | app:startDestination="@id/settingsFragment"> | ||
| 6 | |||
| 7 | <fragment | ||
| 8 | android:id="@+id/settingsFragment" | ||
| 9 | android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsFragment" | ||
| 10 | android:label="SettingsFragment"> | ||
| 11 | <argument | ||
| 12 | android:name="menuTag" | ||
| 13 | app:argType="string" /> | ||
| 14 | <argument | ||
| 15 | android:name="game" | ||
| 16 | app:argType="org.yuzu.yuzu_emu.model.Game" | ||
| 17 | app:nullable="true" /> | ||
| 18 | </fragment> | ||
| 19 | |||
| 20 | <action | ||
| 21 | android:id="@+id/action_global_settingsFragment" | ||
| 22 | app:destination="@id/settingsFragment" /> | ||
| 23 | |||
| 24 | </navigation> | ||
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index df76563fc..6b782780a 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml | |||
| @@ -74,6 +74,7 @@ | |||
| 74 | <string name="install_gpu_driver">Install GPU driver</string> | 74 | <string name="install_gpu_driver">Install GPU driver</string> |
| 75 | <string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string> | 75 | <string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string> |
| 76 | <string name="advanced_settings">Advanced settings</string> | 76 | <string name="advanced_settings">Advanced settings</string> |
| 77 | <string name="advanced_settings_game">Advanced settings: %1$s</string> | ||
| 77 | <string name="settings_description">Configure emulator settings</string> | 78 | <string name="settings_description">Configure emulator settings</string> |
| 78 | <string name="search_recently_played">Recently played</string> | 79 | <string name="search_recently_played">Recently played</string> |
| 79 | <string name="search_recently_added">Recently added</string> | 80 | <string name="search_recently_added">Recently added</string> |