diff options
| author | 2023-08-22 19:46:07 -0400 | |
|---|---|---|
| committer | 2023-08-29 19:42:41 -0400 | |
| commit | 95a939a49f798c2b4b04d6f8eae33c1d093d43b4 (patch) | |
| tree | f06b71c8330d743f9951da78547b9448417a9048 /src | |
| parent | android: Trim settings enums and items (diff) | |
| download | yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.tar.gz yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.tar.xz yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.zip | |
android: Migrate settings to navigation component
Consolidates all of the settings components to the fragment and activity with no interfaces and only the settings fragment presenter. This also includes new material animations and new viewmodel usage to prevent the fragment and activity directly interacting with one another.
Diffstat (limited to 'src')
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> |