diff options
author | Charles Lombardo <clombardo169@gmail.com> | 2023-08-23 01:46:07 +0200 |
---|---|---|
committer | Charles Lombardo <clombardo169@gmail.com> | 2023-08-30 01:42:41 +0200 |
commit | 95a939a49f798c2b4b04d6f8eae33c1d093d43b4 (patch) | |
tree | f06b71c8330d743f9951da78547b9448417a9048 /src/android | |
parent | android: Trim settings enums and items (diff) | |
download | yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.tar yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.tar.gz yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.tar.bz2 yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.tar.lz yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.tar.xz yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.tar.zst yuzu-95a939a49f798c2b4b04d6f8eae33c1d093d43b4.zip |
Diffstat (limited to 'src/android')
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() { super.onCreate() application = this documentsTree = DocumentsTree() - DirectoryInitialization.start(applicationContext) + DirectoryInitialization.start() GpuDriverHelper.initializeDriverParameters(applicationContext) NativeLibrary.logDeviceInfo() 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 { val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment - val navController = navHostFragment.navController - navController - .setGraph(R.navigation.emulation_navigation, intent.extras) + navHostFragment.navController.setGraph(R.navigation.emulation_navigation, intent.extras) isActivityRecreated = savedInstanceState != null 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 @@ package org.yuzu.yuzu_emu.features.settings.ui -import android.content.Context -import android.content.Intent import android.os.Bundle -import android.view.Menu import android.view.View import android.view.ViewGroup.MarginLayoutParams import android.widget.Toast @@ -16,20 +13,26 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat -import androidx.core.view.updatePadding +import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.navArgs import com.google.android.material.color.MaterialColors +import org.yuzu.yuzu_emu.NativeLibrary import java.io.IOException import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding import org.yuzu.yuzu_emu.features.settings.model.Settings import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile +import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment +import org.yuzu.yuzu_emu.model.SettingsViewModel import org.yuzu.yuzu_emu.utils.* -class SettingsActivity : AppCompatActivity(), SettingsActivityView { - private val presenter = SettingsActivityPresenter(this) - +class SettingsActivity : AppCompatActivity() { private lateinit var binding: ActivitySettingsBinding + private val args by navArgs<SettingsActivityArgs>() + + private val settingsViewModel: SettingsViewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { ThemeHelper.setTheme(this) @@ -38,16 +41,17 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { binding = ActivitySettingsBinding.inflate(layoutInflater) setContentView(binding.root) - WindowCompat.setDecorFitsSystemWindows(window, false) + settingsViewModel.game = args.game - val launcher = intent - val gameID = launcher.getStringExtra(ARG_GAME_ID) - val menuTag = launcher.getStringExtra(ARG_MENU_TAG) - presenter.onCreate(savedInstanceState, menuTag!!, gameID!!) + val navHostFragment = + supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment + navHostFragment.navController.setGraph(R.navigation.settings_navigation, intent.extras) - // Show "Back" button in the action bar for navigation - setSupportActionBar(binding.toolbarSettings) - supportActionBar!!.setDisplayHomeAsUpEnabled(true) + WindowCompat.setDecorFitsSystemWindows(window, false) + + if (savedInstanceState != null) { + settingsViewModel.shouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE) + } if (InsetsHelper.getSystemGestureType(applicationContext) != InsetsHelper.GESTURE_NAVIGATION @@ -63,6 +67,28 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { ) } + settingsViewModel.shouldRecreate.observe(this) { + if (it) { + settingsViewModel.setShouldRecreate(false) + recreate() + } + } + settingsViewModel.shouldNavigateBack.observe(this) { + if (it) { + settingsViewModel.setShouldNavigateBack(false) + navigateBack() + } + } + settingsViewModel.shouldShowResetSettingsDialog.observe(this) { + if (it) { + settingsViewModel.setShouldShowResetSettingsDialog(false) + ResetSettingsDialogFragment().show( + supportFragmentManager, + ResetSettingsDialogFragment.TAG + ) + } + } + onBackPressedDispatcher.addCallback( this, object : OnBackPressedCallback(true) { @@ -73,34 +99,28 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { setInsets() } - override fun onSupportNavigateUp(): Boolean { - navigateBack() - return true - } - - private fun navigateBack() { - if (supportFragmentManager.backStackEntryCount > 0) { - supportFragmentManager.popBackStack() + fun navigateBack() { + val navHostFragment = + supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment + if (navHostFragment.childFragmentManager.backStackEntryCount > 0) { + navHostFragment.navController.popBackStack() } else { finish() } } - override fun onCreateOptionsMenu(menu: Menu): Boolean { - val inflater = menuInflater - inflater.inflate(R.menu.menu_settings, menu) - return true - } - override fun onSaveInstanceState(outState: Bundle) { // Critical: If super method is not called, rotations will be busted. super.onSaveInstanceState(outState) - presenter.saveState(outState) + outState.putBoolean(KEY_SHOULD_SAVE, settingsViewModel.shouldSave) } override fun onStart() { super.onStart() - presenter.onStart() + // TODO: Load custom settings contextually + if (!DirectoryInitialization.areDirectoriesReady) { + DirectoryInitialization.start() + } } /** @@ -110,65 +130,21 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { */ override fun onStop() { super.onStop() - presenter.onStop(isFinishing) - } - - override fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) { - if (!addToStack && settingsFragment != null) { - return - } - - val transaction = supportFragmentManager.beginTransaction() - if (addToStack) { - if (areSystemAnimationsEnabled()) { - transaction.setCustomAnimations( - R.anim.anim_settings_fragment_in, - R.anim.anim_settings_fragment_out, - 0, - R.anim.anim_pop_settings_fragment_out - ) - } - transaction.addToBackStack(null) + if (isFinishing && settingsViewModel.shouldSave) { + Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...") + Settings.saveSettings() + NativeLibrary.reloadSettings() } - transaction.replace( - R.id.frame_content, - SettingsFragment.newInstance(menuTag, gameId), - FRAGMENT_TAG - ) - transaction.commit() - } - - private fun areSystemAnimationsEnabled(): Boolean { - val duration = android.provider.Settings.Global.getFloat( - contentResolver, - android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, - 1f - ) - val transition = android.provider.Settings.Global.getFloat( - contentResolver, - android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE, - 1f - ) - return duration != 0f && transition != 0f } - override fun onSettingsFileLoaded() { - val fragment: SettingsFragmentView? = settingsFragment - fragment?.loadSettingsList() - } - - override fun onSettingsFileNotFound() { - val fragment: SettingsFragmentView? = settingsFragment - fragment?.loadSettingsList() - } - - override fun onSettingChanged() { - presenter.onSettingChanged() + override fun onDestroy() { + settingsViewModel.clear() + super.onDestroy() } fun onSettingsReset() { // Prevents saving to a non-existent settings file - presenter.onSettingsReset() + settingsViewModel.shouldSave = false // Delete settings file because the user may have changed values that do not exist in the UI val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG) @@ -185,47 +161,21 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { finish() } - fun setToolbarTitle(title: String) { - binding.toolbarSettingsLayout.title = title - } - - private val settingsFragment: SettingsFragment? - get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment? - private fun setInsets() { ViewCompat.setOnApplyWindowInsetsListener( - binding.frameContent + binding.navigationBarShade ) { view: View, windowInsets: WindowInsetsCompat -> val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) - val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) - view.updatePadding( - left = barInsets.left + cutoutInsets.left, - right = barInsets.right + cutoutInsets.right - ) - val mlpAppBar = binding.appbarSettings.layoutParams as MarginLayoutParams - mlpAppBar.leftMargin = barInsets.left + cutoutInsets.left - mlpAppBar.rightMargin = barInsets.right + cutoutInsets.right - binding.appbarSettings.layoutParams = mlpAppBar - - val mlpShade = binding.navigationBarShade.layoutParams as MarginLayoutParams + val mlpShade = view.layoutParams as MarginLayoutParams mlpShade.height = barInsets.bottom - binding.navigationBarShade.layoutParams = mlpShade + view.layoutParams = mlpShade windowInsets } } companion object { - private const val ARG_MENU_TAG = "menu_tag" - private const val ARG_GAME_ID = "game_id" - private const val FRAGMENT_TAG = "settings" - - fun launch(context: Context, menuTag: String?, gameId: String?) { - val settings = Intent(context, SettingsActivity::class.java) - settings.putExtra(ARG_MENU_TAG, menuTag) - settings.putExtra(ARG_GAME_ID, gameId) - context.startActivity(settings) - } + private const val KEY_SHOULD_SAVE = "should_save" } } 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 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.features.settings.ui - -import android.content.Context -import android.os.Bundle -import java.io.File -import org.yuzu.yuzu_emu.NativeLibrary -import org.yuzu.yuzu_emu.features.settings.model.Settings -import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile -import org.yuzu.yuzu_emu.utils.DirectoryInitialization -import org.yuzu.yuzu_emu.utils.Log - -class SettingsActivityPresenter(private val activityView: SettingsActivityView) { - private var shouldSave = false - private lateinit var menuTag: String - private lateinit var gameId: String - - fun onCreate(savedInstanceState: Bundle?, menuTag: String, gameId: String) { - this.menuTag = menuTag - this.gameId = gameId - if (savedInstanceState != null) { - shouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE) - } - } - - fun onStart() { - prepareDirectoriesIfNeeded() - } - - private fun loadSettingsUI() { - // TODO: Load custom settings contextually - activityView.showSettingsFragment(menuTag, false, gameId) - activityView.onSettingsFileLoaded() - } - - private fun prepareDirectoriesIfNeeded() { - val configFile = - File( - "${DirectoryInitialization.userDirectory}/config/" + - "${SettingsFile.FILE_NAME_CONFIG}.ini" - ) - if (!configFile.exists()) { - Log.error( - "${DirectoryInitialization.userDirectory}/config/" + - "${SettingsFile.FILE_NAME_CONFIG}.ini" - ) - Log.error("yuzu config file could not be found!") - } - - if (!DirectoryInitialization.areDirectoriesReady) { - DirectoryInitialization.start(activityView as Context) - } - loadSettingsUI() - } - - fun onStop(finishing: Boolean) { - if (finishing && shouldSave) { - Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...") - Settings.saveSettings() - NativeLibrary.reloadSettings() - } - } - - fun onSettingChanged() { - shouldSave = true - } - - fun onSettingsReset() { - shouldSave = false - } - - fun saveState(outState: Bundle) { - outState.putBoolean(KEY_SHOULD_SAVE, shouldSave) - } - - companion object { - private const val KEY_SHOULD_SAVE = "should_save" - } -} 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 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.features.settings.ui - -/** - * Abstraction for the Activity that manages SettingsFragments. - */ -interface SettingsActivityView { - /** - * Show a new SettingsFragment. - * - * @param menuTag Identifier for the settings group that should be displayed. - * @param addToStack Whether or not this fragment should replace a previous one. - */ - fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) - - /** - * Called when a load operation completes. - */ - fun onSettingsFileLoaded() - - /** - * Called when a load operation fails. - */ - fun onSettingsFileNotFound() - - /** - * End the activity. - */ - fun finish() - - /** - * Called by a containing Fragment to tell the Activity that a setting was changed; - * unless this has been called, the Activity will not save to disk. - */ - fun onSettingChanged() -} 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 import android.view.ViewGroup import android.widget.TextView import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProvider +import androidx.navigation.findNavController import androidx.recyclerview.widget.RecyclerView import com.google.android.material.datepicker.MaterialDatePicker import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -20,6 +21,7 @@ import com.google.android.material.slider.Slider import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.SettingsNavigationDirections import org.yuzu.yuzu_emu.databinding.DialogSliderBinding import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding @@ -30,18 +32,22 @@ import org.yuzu.yuzu_emu.features.settings.model.FloatSetting import org.yuzu.yuzu_emu.features.settings.model.ShortSetting import org.yuzu.yuzu_emu.features.settings.model.view.* import org.yuzu.yuzu_emu.features.settings.ui.viewholder.* +import org.yuzu.yuzu_emu.model.SettingsViewModel class SettingsAdapter( - private val fragmentView: SettingsFragmentView, + private val fragment: SettingsFragment, private val context: Context ) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener { - private var settings: ArrayList<SettingsItem>? = null + private var settings = ArrayList<SettingsItem>() private var clickedItem: SettingsItem? = null private var clickedPosition: Int private var dialog: AlertDialog? = null private var sliderProgress = 0 private var textSliderValue: TextView? = null + private val settingsViewModel: SettingsViewModel + get() = ViewModelProvider(fragment.requireActivity())[SettingsViewModel::class.java] + private var defaultCancelListener = DialogInterface.OnClickListener { _: DialogInterface?, _: Int -> closeDialog() } @@ -91,30 +97,22 @@ class SettingsAdapter( holder.bind(getItem(position)) } - private fun getItem(position: Int): SettingsItem { - return settings!![position] - } + private fun getItem(position: Int): SettingsItem = settings[position] - override fun getItemCount(): Int { - return if (settings != null) { - settings!!.size - } else { - 0 - } - } + override fun getItemCount(): Int = settings.size override fun getItemViewType(position: Int): Int { return getItem(position).type } - fun setSettingsList(settings: ArrayList<SettingsItem>?) { + fun setSettingsList(settings: ArrayList<SettingsItem>) { this.settings = settings notifyDataSetChanged() } fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) { item.checked = checked - fragmentView.onSettingChanged() + settingsViewModel.shouldSave = true } private fun onSingleChoiceClick(item: SingleChoiceSetting) { @@ -155,7 +153,7 @@ class SettingsAdapter( calendar.timeZone = TimeZone.getTimeZone("UTC") var timeFormat: Int = TimeFormat.CLOCK_12H - if (DateFormat.is24HourFormat(fragmentView.activityView as AppCompatActivity)) { + if (DateFormat.is24HourFormat(context)) { timeFormat = TimeFormat.CLOCK_24H } @@ -172,7 +170,7 @@ class SettingsAdapter( datePicker.addOnPositiveButtonClickListener { timePicker.show( - (fragmentView.activityView as AppCompatActivity).supportFragmentManager, + fragment.childFragmentManager, "TimePicker" ) } @@ -181,14 +179,14 @@ class SettingsAdapter( epochTime += timePicker.hour.toLong() * 60 * 60 epochTime += timePicker.minute.toLong() * 60 if (item.value != epochTime) { - fragmentView.onSettingChanged() + settingsViewModel.shouldSave = true notifyItemChanged(clickedPosition) item.value = epochTime } clickedItem = null } datePicker.show( - (fragmentView.activityView as AppCompatActivity).supportFragmentManager, + fragment.childFragmentManager, "DatePicker" ) } @@ -231,7 +229,8 @@ class SettingsAdapter( } fun onSubmenuClick(item: SubmenuSetting) { - fragmentView.loadSubMenu(item.menuKey) + val action = SettingsNavigationDirections.actionGlobalSettingsFragment(item.menuKey, null) + fragment.view?.findNavController()?.navigate(action) } override fun onClick(dialog: DialogInterface, which: Int) { @@ -240,7 +239,7 @@ class SettingsAdapter( val scSetting = clickedItem as SingleChoiceSetting val value = getValueForSingleChoiceSelection(scSetting, which) if (scSetting.selectedValue != value) { - fragmentView.onSettingChanged() + settingsViewModel.shouldSave = true } // Get the backing Setting, which may be null (if for example it was missing from the file) @@ -251,7 +250,7 @@ class SettingsAdapter( is StringSingleChoiceSetting -> { val scSetting = clickedItem as StringSingleChoiceSetting val value = scSetting.getValueAt(which) - if (scSetting.selectedValue != value) fragmentView.onSettingChanged() + if (scSetting.selectedValue != value) settingsViewModel.shouldSave = true scSetting.selectedValue = value!! closeDialog() } @@ -259,7 +258,7 @@ class SettingsAdapter( is SliderSetting -> { val sliderSetting = clickedItem as SliderSetting if (sliderSetting.selectedValue != sliderProgress) { - fragmentView.onSettingChanged() + settingsViewModel.shouldSave = true } when (sliderSetting.setting) { is ByteSetting -> { @@ -294,7 +293,7 @@ class SettingsAdapter( .setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int -> setting.reset() notifyItemChanged(position) - fragmentView.onSettingChanged() + settingsViewModel.shouldSave = true } .setNegativeButton(android.R.string.cancel, null) .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 @@ package org.yuzu.yuzu_emu.features.settings.ui -import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.ViewGroup.MarginLayoutParams import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.updatePadding import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.divider.MaterialDividerItemDecoration +import com.google.android.material.transition.MaterialSharedAxis +import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding -import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem +import org.yuzu.yuzu_emu.model.SettingsViewModel -class SettingsFragment : Fragment(), SettingsFragmentView { - override var activityView: SettingsActivityView? = null - - private val fragmentPresenter = SettingsFragmentPresenter(this) +class SettingsFragment : Fragment() { + private lateinit var presenter: SettingsFragmentPresenter private var settingsAdapter: SettingsAdapter? = null private var _binding: FragmentSettingsBinding? = null private val binding get() = _binding!! - override fun onAttach(context: Context) { - super.onAttach(context) - activityView = requireActivity() as SettingsActivityView - } + private val args by navArgs<SettingsFragmentArgs>() + + private val settingsViewModel: SettingsViewModel by activityViewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val menuTag = requireArguments().getString(ARGUMENT_MENU_TAG) - val gameId = requireArguments().getString(ARGUMENT_GAME_ID) - fragmentPresenter.onCreate(menuTag!!, gameId!!) + enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) + returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) + reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) + exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) } override fun onCreateView( @@ -48,7 +50,14 @@ class SettingsFragment : Fragment(), SettingsFragmentView { } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - settingsAdapter = SettingsAdapter(this, requireActivity()) + settingsAdapter = SettingsAdapter(this, requireContext()) + presenter = SettingsFragmentPresenter( + settingsViewModel, + settingsAdapter!!, + args.menuTag, + args.game?.gameId ?: "" + ) + val dividerDecoration = MaterialDividerItemDecoration( requireContext(), LinearLayoutManager.VERTICAL @@ -56,63 +65,52 @@ class SettingsFragment : Fragment(), SettingsFragmentView { dividerDecoration.isLastItemDecorated = false binding.listSettings.apply { adapter = settingsAdapter - layoutManager = LinearLayoutManager(activity) + layoutManager = LinearLayoutManager(requireContext()) addItemDecoration(dividerDecoration) } - fragmentPresenter.onViewCreated() - setInsets() - } - - override fun onDetach() { - super.onDetach() - activityView = null - if (settingsAdapter != null) { - settingsAdapter!!.closeDialog() + binding.toolbarSettings.setNavigationOnClickListener { + settingsViewModel.setShouldNavigateBack(true) } - } - override fun showSettingsList(settingsList: ArrayList<SettingsItem>) { - settingsAdapter!!.setSettingsList(settingsList) - } + settingsViewModel.toolbarTitle.observe(viewLifecycleOwner) { + if (it.isNotEmpty()) binding.toolbarSettingsLayout.title = it + } - override fun loadSettingsList() { - fragmentPresenter.loadSettingsList() - } + presenter.onViewCreated() - override fun loadSubMenu(menuKey: String) { - activityView!!.showSettingsFragment( - menuKey, - true, - requireArguments().getString(ARGUMENT_GAME_ID)!! - ) + setInsets() } - override fun onSettingChanged() { - activityView!!.onSettingChanged() + override fun onDetach() { + super.onDetach() + settingsAdapter?.closeDialog() } private fun setInsets() { ViewCompat.setOnApplyWindowInsetsListener( - binding.listSettings - ) { view: View, windowInsets: WindowInsetsCompat -> - val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) - view.updatePadding(bottom = insets.bottom) + binding.root + ) { _: View, windowInsets: WindowInsetsCompat -> + val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) + + val leftInsets = barInsets.left + cutoutInsets.left + val rightInsets = barInsets.right + cutoutInsets.right + + val sideMargin = resources.getDimensionPixelSize(R.dimen.spacing_medlarge) + val mlpSettingsList = binding.listSettings.layoutParams as MarginLayoutParams + mlpSettingsList.leftMargin = sideMargin + leftInsets + mlpSettingsList.rightMargin = sideMargin + rightInsets + binding.listSettings.layoutParams = mlpSettingsList + binding.listSettings.updatePadding( + bottom = barInsets.bottom + ) + + val mlpAppBar = binding.appbarSettings.layoutParams as MarginLayoutParams + mlpAppBar.leftMargin = leftInsets + mlpAppBar.rightMargin = rightInsets + binding.appbarSettings.layoutParams = mlpAppBar windowInsets } } - - companion object { - private const val ARGUMENT_MENU_TAG = "menu_tag" - private const val ARGUMENT_GAME_ID = "game_id" - - fun newInstance(menuTag: String?, gameId: String?): Fragment { - val fragment = SettingsFragment() - val arguments = Bundle() - arguments.putString(ARGUMENT_MENU_TAG, menuTag) - arguments.putString(ARGUMENT_GAME_ID, gameId) - fragment.arguments = arguments - return fragment - } - } } 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 @@ package org.yuzu.yuzu_emu.features.settings.ui +import android.content.Context import android.content.SharedPreferences import android.os.Build import android.text.TextUtils @@ -20,36 +21,36 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings import org.yuzu.yuzu_emu.features.settings.model.ShortSetting import org.yuzu.yuzu_emu.features.settings.model.view.* import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile -import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment -import org.yuzu.yuzu_emu.utils.ThemeHelper +import org.yuzu.yuzu_emu.model.SettingsViewModel -class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) { - private var menuTag: String? = null - private lateinit var gameId: String - private var settingsList: ArrayList<SettingsItem>? = null +class SettingsFragmentPresenter( + private val settingsViewModel: SettingsViewModel, + private val adapter: SettingsAdapter, + private var menuTag: String, + private var gameId: String +) { + private var settingsList = ArrayList<SettingsItem>() - private val settingsActivity get() = fragmentView.activityView as SettingsActivity + private val preferences: SharedPreferences + get() = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) - private lateinit var preferences: SharedPreferences - - fun onCreate(menuTag: String, gameId: String) { - this.gameId = gameId - this.menuTag = menuTag - } + private val context: Context get() = YuzuApplication.appContext fun onViewCreated() { - preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) loadSettingsList() } - fun loadSettingsList() { + private fun loadSettingsList() { if (!TextUtils.isEmpty(gameId)) { - settingsActivity.setToolbarTitle("Game Settings: $gameId") + settingsViewModel.setToolbarTitle( + context.getString( + R.string.advanced_settings_game, + gameId + ) + ) } + val sl = ArrayList<SettingsItem>() - if (menuTag == null) { - return - } when (menuTag) { SettingsFile.FILE_NAME_CONFIG -> addConfigSettings(sl) Settings.SECTION_GENERAL -> addGeneralSettings(sl) @@ -69,11 +70,11 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } } settingsList = sl - fragmentView.showSettingsList(settingsList!!) + adapter.setSettingsList(settingsList) } private fun addConfigSettings(sl: ArrayList<SettingsItem>) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.advanced_settings)) + settingsViewModel.setToolbarTitle(context.getString(R.string.advanced_settings)) sl.apply { add(SubmenuSetting(R.string.preferences_general, 0, Settings.SECTION_GENERAL)) add(SubmenuSetting(R.string.preferences_system, 0, Settings.SECTION_SYSTEM)) @@ -82,17 +83,14 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) add(SubmenuSetting(R.string.preferences_debug, 0, Settings.SECTION_DEBUG)) add( RunnableSetting(R.string.reset_to_default, 0, false) { - ResetSettingsDialogFragment().show( - settingsActivity.supportFragmentManager, - ResetSettingsDialogFragment.TAG - ) + settingsViewModel.setShouldShowResetSettingsDialog(true) } ) } } private fun addGeneralSettings(sl: ArrayList<SettingsItem>) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_general)) + settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_general)) sl.apply { add( SwitchSetting( @@ -131,7 +129,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } private fun addSystemSettings(sl: ArrayList<SettingsItem>) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_system)) + settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_system)) sl.apply { add( SwitchSetting( @@ -170,7 +168,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_graphics)) + settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_graphics)) sl.apply { add( SingleChoiceSetting( @@ -267,7 +265,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } private fun addAudioSettings(sl: ArrayList<SettingsItem>) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_audio)) + settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_audio)) sl.apply { add( SingleChoiceSetting( @@ -292,7 +290,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } private fun addThemeSettings(sl: ArrayList<SettingsItem>) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_theme)) + settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_theme)) sl.apply { val theme: AbstractIntSetting = object : AbstractIntSetting { override val int: Int @@ -302,7 +300,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) preferences.edit() .putInt(Settings.PREF_THEME, value) .apply() - settingsActivity.recreate() + settingsViewModel.setShouldRecreate(true) } override val key: String? = null @@ -346,7 +344,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) preferences.edit() .putInt(Settings.PREF_THEME_MODE, value) .apply() - ThemeHelper.setThemeMode(settingsActivity) + settingsViewModel.setShouldRecreate(true) } override val key: String? = null @@ -357,6 +355,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) preferences.edit() .putInt(Settings.PREF_BLACK_BACKGROUNDS, defaultValue) .apply() + settingsViewModel.setShouldRecreate(true) } } @@ -378,7 +377,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) preferences.edit() .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value) .apply() - settingsActivity.recreate() + settingsViewModel.setShouldRecreate(true) } override val key: String? = null @@ -389,6 +388,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) preferences.edit() .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, defaultValue) .apply() + settingsViewModel.setShouldRecreate(true) } } @@ -403,7 +403,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } private fun addDebugSettings(sl: ArrayList<SettingsItem>) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_debug)) + settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_debug)) sl.apply { add(HeaderSetting(R.string.gpu)) 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 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.features.settings.ui - -import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem - -/** - * Abstraction for a screen showing a list of settings. Instances of - * this type of view will each display a layer of the setting hierarchy. - */ -interface SettingsFragmentView { - /** - * Pass an ArrayList to the View so that it can be displayed on screen. - * - * @param settingsList The result of converting the HashMap to an ArrayList - */ - fun showSettingsList(settingsList: ArrayList<SettingsItem>) - - /** - * Instructs the Fragment to load the settings screen. - */ - fun loadSettingsList() - - /** - * @return The Fragment's containing activity. - */ - val activityView: SettingsActivityView? - - /** - * Tell the Fragment to tell the containing Activity to show a new - * Fragment containing a submenu of settings. - * - * @param menuKey Identifier for the settings group that should be shown. - */ - fun loadSubMenu(menuKey: String) - - /** - * Have the fragment tell the containing Activity that a setting was modified. - */ - fun onSettingChanged() -} 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 import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import androidx.navigation.findNavController import androidx.navigation.fragment.navArgs import androidx.preference.PreferenceManager import androidx.window.layout.FoldingFeature @@ -37,6 +38,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.slider.Slider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.yuzu.yuzu_emu.HomeNavigationDirections import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication @@ -45,7 +47,6 @@ import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding import org.yuzu.yuzu_emu.features.settings.model.IntSetting import org.yuzu.yuzu_emu.features.settings.model.Settings -import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile import org.yuzu.yuzu_emu.overlay.InputOverlay import org.yuzu.yuzu_emu.utils.* @@ -139,7 +140,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } R.id.menu_settings -> { - SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") + val action = HomeNavigationDirections.actionGlobalSettingsActivity( + null, + SettingsFile.FILE_NAME_CONFIG + ) + binding.root.findNavController().navigate(action) true } @@ -211,7 +216,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { override fun onResume() { super.onResume() if (!DirectoryInitialization.areDirectoriesReady) { - DirectoryInitialization.start(requireContext()) + DirectoryInitialization.start() } 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 import androidx.documentfile.provider.DocumentFile import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels +import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.transition.MaterialSharedAxis import org.yuzu.yuzu_emu.BuildConfig +import org.yuzu.yuzu_emu.HomeNavigationDirections import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding import org.yuzu.yuzu_emu.features.DocumentProvider import org.yuzu.yuzu_emu.features.settings.model.Settings -import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile import org.yuzu.yuzu_emu.model.HomeSetting import org.yuzu.yuzu_emu.model.HomeViewModel @@ -74,7 +75,13 @@ class HomeSettingsFragment : Fragment() { R.string.advanced_settings, R.string.settings_description, R.drawable.ic_settings, - { SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") } + { + val action = HomeNavigationDirections.actionGlobalSettingsActivity( + null, + SettingsFile.FILE_NAME_CONFIG + ) + binding.root.findNavController().navigate(action) + } ) ) add( @@ -90,7 +97,13 @@ class HomeSettingsFragment : Fragment() { R.string.preferences_theme, R.string.theme_and_color_description, R.drawable.ic_palette, - { SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") } + { + val action = HomeNavigationDirections.actionGlobalSettingsActivity( + null, + Settings.SECTION_THEME + ) + binding.root.findNavController().navigate(action) + } ) ) 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 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.model + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class SettingsViewModel : ViewModel() { + var game: Game? = null + + var shouldSave = false + + private val _toolbarTitle = MutableLiveData("") + val toolbarTitle: LiveData<String> get() = _toolbarTitle + + private val _shouldRecreate = MutableLiveData(false) + val shouldRecreate: LiveData<Boolean> get() = _shouldRecreate + + private val _shouldNavigateBack = MutableLiveData(false) + val shouldNavigateBack: LiveData<Boolean> get() = _shouldNavigateBack + + private val _shouldShowResetSettingsDialog = MutableLiveData(false) + val shouldShowResetSettingsDialog: LiveData<Boolean> get() = _shouldShowResetSettingsDialog + + fun setToolbarTitle(value: String) { + _toolbarTitle.value = value + } + + fun setShouldRecreate(value: Boolean) { + _shouldRecreate.value = value + } + + fun setShouldNavigateBack(value: Boolean) { + _shouldNavigateBack.value = value + } + + fun setShouldShowResetSettingsDialog(value: Boolean) { + _shouldShowResetSettingsDialog.value = value + } + + fun clear() { + game = null + shouldSave = false + } +} 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 import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.yuzu.yuzu_emu.HomeNavigationDirections import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.activities.EmulationActivity import org.yuzu.yuzu_emu.databinding.ActivityMainBinding import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding import org.yuzu.yuzu_emu.features.settings.model.Settings -import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment import org.yuzu.yuzu_emu.fragments.LongMessageDialogFragment @@ -105,11 +105,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider { when (it.itemId) { R.id.gamesFragment -> gamesViewModel.setShouldScrollToTop(true) R.id.searchFragment -> gamesViewModel.setSearchFocused(true) - R.id.homeSettingsFragment -> SettingsActivity.launch( - this, - SettingsFile.FILE_NAME_CONFIG, - "" - ) + R.id.homeSettingsFragment -> { + val action = HomeNavigationDirections.actionGlobalSettingsActivity( + null, + SettingsFile.FILE_NAME_CONFIG + ) + navHostFragment.navController.navigate(action) + } } } 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 @@ package org.yuzu.yuzu_emu.utils -import android.content.Context import java.io.IOException import org.yuzu.yuzu_emu.NativeLibrary +import org.yuzu.yuzu_emu.YuzuApplication object DirectoryInitialization { private var userPath: String? = null var areDirectoriesReady: Boolean = false - fun start(context: Context) { + fun start() { if (!areDirectoriesReady) { - initializeInternalStorage(context) + initializeInternalStorage() NativeLibrary.initializeEmulation() areDirectoriesReady = true } @@ -26,9 +26,9 @@ object DirectoryInitialization { return userPath } - private fun initializeInternalStorage(context: Context) { + private fun initializeInternalStorage() { try { - userPath = context.getExternalFilesDir(null)!!.canonicalPath + userPath = YuzuApplication.appContext.getExternalFilesDir(null)!!.canonicalPath NativeLibrary.setAppDirectory(userPath!!) } catch (e: IOException) { 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 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <alpha - android:duration="125" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromAlpha="1" - android:toAlpha="0" /> - - <translate - android:duration="125" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromXDelta="0" - android:toXDelta="-75" /> - -</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 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <alpha - android:duration="@android:integer/config_shortAnimTime" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromAlpha="0" - android:toAlpha="1" /> - - <translate - android:duration="@android:integer/config_shortAnimTime" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromXDelta="-200" - android:toXDelta="0" /> - -</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 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <alpha - android:duration="125" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromAlpha="1" - android:toAlpha="0" /> - - <translate - android:duration="125" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromXDelta="0" - android:toXDelta="75" /> - -</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 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <alpha - android:duration="@android:integer/config_shortAnimTime" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromAlpha="0" - android:toAlpha="1" /> - - <translate - android:duration="@android:integer/config_shortAnimTime" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromXDelta="200" - android:toXDelta="0" /> - -</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 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <alpha - android:duration="@android:integer/config_shortAnimTime" - android:interpolator="@android:anim/decelerate_interpolator" - android:fromAlpha="1" - android:toAlpha="0" /> - -</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 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <objectAnimator - android:propertyName="translationX" - android:valueType="floatType" - android:valueFrom="-1280dp" - android:valueTo="0" - android:interpolator="@android:interpolator/decelerate_quad" - android:duration="300"/> - - <objectAnimator - android:propertyName="alpha" - android:valueType="floatType" - android:valueFrom="0" - android:valueTo="1" - android:interpolator="@android:interpolator/accelerate_quad" - android:duration="300"/> - -</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 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <!-- This animation is used ONLY when a submenu is replaced. --> - <objectAnimator - android:propertyName="translationX" - android:valueType="floatType" - android:valueFrom="0" - android:valueTo="-1280dp" - android:interpolator="@android:interpolator/decelerate_quad" - android:duration="200"/> - - <objectAnimator - android:propertyName="alpha" - android:valueType="floatType" - android:valueFrom="1" - android:valueTo="0" - android:interpolator="@android:interpolator/decelerate_quad" - android:duration="200"/> - -</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 @@ <?xml version="1.0" encoding="utf-8"?> -<androidx.coordinatorlayout.widget.CoordinatorLayout - android:id="@+id/coordinator_main" +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/constraint_settings" android:layout_width="match_parent" android:layout_height="match_parent" android:background="?attr/colorSurface"> - <com.google.android.material.appbar.AppBarLayout - android:id="@+id/appbar_settings" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:fitsSystemWindows="true" - app:elevation="0dp"> - - <com.google.android.material.appbar.CollapsingToolbarLayout - style="?attr/collapsingToolbarLayoutMediumStyle" - android:id="@+id/toolbar_settings_layout" - android:layout_width="match_parent" - android:layout_height="?attr/collapsingToolbarLayoutMediumSize" - app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> - - <com.google.android.material.appbar.MaterialToolbar - android:id="@+id/toolbar_settings" - android:layout_width="match_parent" - android:layout_height="?attr/actionBarSize" - app:layout_collapseMode="pin" /> - - </com.google.android.material.appbar.CollapsingToolbarLayout> - - </com.google.android.material.appbar.AppBarLayout> - - <FrameLayout - android:id="@+id/frame_content" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginHorizontal="12dp" - app:layout_behavior="@string/appbar_scrolling_view_behavior" /> + <androidx.fragment.app.FragmentContainerView + android:id="@+id/fragment_container" + android:name="androidx.navigation.fragment.NavHostFragment" + android:layout_width="0dp" + android:layout_height="0dp" + app:defaultNavHost="true" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:layout="@layout/fragment_settings" /> <View android:id="@+id/navigation_bar_shade" @@ -45,6 +27,8 @@ android:background="@android:color/transparent" android:clickable="false" android:focusable="false" - android:layout_gravity="bottom|center_horizontal" /> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> -</androidx.coordinatorlayout.widget.CoordinatorLayout> +</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 @@ <?xml version="1.0" encoding="utf-8"?> -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/coordinator_main" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:background="?attr/colorSurface"> + + <com.google.android.material.appbar.AppBarLayout + android:id="@+id/appbar_settings" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fitsSystemWindows="true" + app:elevation="0dp"> + + <com.google.android.material.appbar.CollapsingToolbarLayout + android:id="@+id/toolbar_settings_layout" + style="?attr/collapsingToolbarLayoutMediumStyle" + android:layout_width="match_parent" + android:layout_height="?attr/collapsingToolbarLayoutMediumSize" + app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> + + <com.google.android.material.appbar.MaterialToolbar + android:id="@+id/toolbar_settings" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + app:layout_collapseMode="pin" + app:navigationIcon="@drawable/ic_back" /> + + </com.google.android.material.appbar.CollapsingToolbarLayout> + + </com.google.android.material.appbar.AppBarLayout> <androidx.recyclerview.widget.RecyclerView android:id="@+id/list_settings" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="?attr/colorSurface" - android:clipToPadding="false" /> + android:clipToPadding="false" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> -</FrameLayout> +</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 @@ -<?xml version="1.0" encoding="utf-8"?> -<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 @@ app:argType="org.yuzu.yuzu_emu.model.Game" /> </fragment> + <activity + android:id="@+id/settingsActivity" + android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity" + android:label="SettingsActivity"> + <argument + android:name="game" + app:argType="org.yuzu.yuzu_emu.model.Game" + app:nullable="true" /> + <argument + android:name="menuTag" + app:argType="string" /> + </activity> + + <action + android:id="@+id/action_global_settingsActivity" + app:destination="@id/settingsActivity" /> + </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 @@ app:destination="@id/emulationActivity" app:launchSingleTop="true" /> + <activity + android:id="@+id/settingsActivity" + android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity" + android:label="SettingsActivity"> + <argument + android:name="game" + app:argType="org.yuzu.yuzu_emu.model.Game" + app:nullable="true" /> + <argument + android:name="menuTag" + app:argType="string" /> + </activity> + + <action + android:id="@+id/action_global_settingsActivity" + app:destination="@id/settingsActivity" /> + </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 @@ +<?xml version="1.0" encoding="utf-8"?> +<navigation xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/settings_navigation" + app:startDestination="@id/settingsFragment"> + + <fragment + android:id="@+id/settingsFragment" + android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsFragment" + android:label="SettingsFragment"> + <argument + android:name="menuTag" + app:argType="string" /> + <argument + android:name="game" + app:argType="org.yuzu.yuzu_emu.model.Game" + app:nullable="true" /> + </fragment> + + <action + android:id="@+id/action_global_settingsFragment" + app:destination="@id/settingsFragment" /> + +</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 @@ <string name="install_gpu_driver">Install GPU driver</string> <string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string> <string name="advanced_settings">Advanced settings</string> + <string name="advanced_settings_game">Advanced settings: %1$s</string> <string name="settings_description">Configure emulator settings</string> <string name="search_recently_played">Recently played</string> <string name="search_recently_added">Recently added</string> |