diff options
| author | 2023-09-14 16:54:21 -0400 | |
|---|---|---|
| committer | 2023-09-14 16:54:21 -0400 | |
| commit | 5eceab3ce6044fbafd457af6db1404f4ae9f080c (patch) | |
| tree | afeb028033c70ebccf9e15ec3636e2265da34f6a /src | |
| parent | Merge pull request #11496 from liamwhite/ngc (diff) | |
| parent | android: Refactor menu tags to enum (diff) | |
| download | yuzu-5eceab3ce6044fbafd457af6db1404f4ae9f080c.tar.gz yuzu-5eceab3ce6044fbafd457af6db1404f4ae9f080c.tar.xz yuzu-5eceab3ce6044fbafd457af6db1404f4ae9f080c.zip | |
Merge pull request #11425 from t895/stateflows
android: Use StateFlow instead of LiveData
Diffstat (limited to '')
22 files changed, 406 insertions, 295 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/HomeSettingAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/HomeSettingAdapter.kt index 8d87d3bd7..1675627a1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/HomeSettingAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/HomeSettingAdapter.kt | |||
| @@ -10,8 +10,12 @@ import android.view.ViewGroup | |||
| 10 | import androidx.appcompat.app.AppCompatActivity | 10 | import androidx.appcompat.app.AppCompatActivity |
| 11 | import androidx.core.content.ContextCompat | 11 | import androidx.core.content.ContextCompat |
| 12 | import androidx.core.content.res.ResourcesCompat | 12 | import androidx.core.content.res.ResourcesCompat |
| 13 | import androidx.lifecycle.Lifecycle | ||
| 13 | import androidx.lifecycle.LifecycleOwner | 14 | import androidx.lifecycle.LifecycleOwner |
| 15 | import androidx.lifecycle.lifecycleScope | ||
| 16 | import androidx.lifecycle.repeatOnLifecycle | ||
| 14 | import androidx.recyclerview.widget.RecyclerView | 17 | import androidx.recyclerview.widget.RecyclerView |
| 18 | import kotlinx.coroutines.launch | ||
| 15 | import org.yuzu.yuzu_emu.R | 19 | import org.yuzu.yuzu_emu.R |
| 16 | import org.yuzu.yuzu_emu.databinding.CardHomeOptionBinding | 20 | import org.yuzu.yuzu_emu.databinding.CardHomeOptionBinding |
| 17 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment | 21 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment |
| @@ -86,7 +90,11 @@ class HomeSettingAdapter( | |||
| 86 | binding.optionIcon.alpha = 0.5f | 90 | binding.optionIcon.alpha = 0.5f |
| 87 | } | 91 | } |
| 88 | 92 | ||
| 89 | option.details.observe(viewLifecycle) { updateOptionDetails(it) } | 93 | viewLifecycle.lifecycleScope.launch { |
| 94 | viewLifecycle.repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 95 | option.details.collect { updateOptionDetails(it) } | ||
| 96 | } | ||
| 97 | } | ||
| 90 | binding.optionDetail.postDelayed( | 98 | binding.optionDetail.postDelayed( |
| 91 | { | 99 | { |
| 92 | binding.optionDetail.ellipsize = TextUtils.TruncateAt.MARQUEE | 100 | binding.optionDetail.ellipsize = TextUtils.TruncateAt.MARQUEE |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index 0702236e8..08e2a973d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt | |||
| @@ -80,6 +80,17 @@ object Settings { | |||
| 80 | const val SECTION_THEME = "Theme" | 80 | const val SECTION_THEME = "Theme" |
| 81 | const val SECTION_DEBUG = "Debug" | 81 | const val SECTION_DEBUG = "Debug" |
| 82 | 82 | ||
| 83 | enum class MenuTag(val titleId: Int) { | ||
| 84 | SECTION_ROOT(R.string.advanced_settings), | ||
| 85 | SECTION_GENERAL(R.string.preferences_general), | ||
| 86 | SECTION_SYSTEM(R.string.preferences_system), | ||
| 87 | SECTION_RENDERER(R.string.preferences_graphics), | ||
| 88 | SECTION_AUDIO(R.string.preferences_audio), | ||
| 89 | SECTION_CPU(R.string.cpu), | ||
| 90 | SECTION_THEME(R.string.preferences_theme), | ||
| 91 | SECTION_DEBUG(R.string.preferences_debug); | ||
| 92 | } | ||
| 93 | |||
| 83 | const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown" | 94 | const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown" |
| 84 | 95 | ||
| 85 | const val PREF_OVERLAY_VERSION = "OverlayVersion" | 96 | const val PREF_OVERLAY_VERSION = "OverlayVersion" |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SubmenuSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SubmenuSetting.kt index 91c273964..b343e527e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SubmenuSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SubmenuSetting.kt | |||
| @@ -3,10 +3,12 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.features.settings.model.view | 4 | package org.yuzu.yuzu_emu.features.settings.model.view |
| 5 | 5 | ||
| 6 | import org.yuzu.yuzu_emu.features.settings.model.Settings | ||
| 7 | |||
| 6 | class SubmenuSetting( | 8 | class SubmenuSetting( |
| 7 | titleId: Int, | 9 | titleId: Int, |
| 8 | descriptionId: Int, | 10 | descriptionId: Int, |
| 9 | val menuKey: String | 11 | val menuKey: Settings.MenuTag |
| 10 | ) : SettingsItem(emptySetting, titleId, descriptionId) { | 12 | ) : SettingsItem(emptySetting, titleId, descriptionId) { |
| 11 | override val type = TYPE_SUBMENU | 13 | override val type = TYPE_SUBMENU |
| 12 | } | 14 | } |
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 908c01265..4d2f2f604 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 | |||
| @@ -13,9 +13,14 @@ import androidx.appcompat.app.AppCompatActivity | |||
| 13 | import androidx.core.view.ViewCompat | 13 | import androidx.core.view.ViewCompat |
| 14 | import androidx.core.view.WindowCompat | 14 | import androidx.core.view.WindowCompat |
| 15 | import androidx.core.view.WindowInsetsCompat | 15 | import androidx.core.view.WindowInsetsCompat |
| 16 | import androidx.lifecycle.Lifecycle | ||
| 17 | import androidx.lifecycle.lifecycleScope | ||
| 18 | import androidx.lifecycle.repeatOnLifecycle | ||
| 16 | import androidx.navigation.fragment.NavHostFragment | 19 | import androidx.navigation.fragment.NavHostFragment |
| 17 | import androidx.navigation.navArgs | 20 | import androidx.navigation.navArgs |
| 18 | import com.google.android.material.color.MaterialColors | 21 | import com.google.android.material.color.MaterialColors |
| 22 | import kotlinx.coroutines.flow.collectLatest | ||
| 23 | import kotlinx.coroutines.launch | ||
| 19 | import java.io.IOException | 24 | import java.io.IOException |
| 20 | import org.yuzu.yuzu_emu.R | 25 | import org.yuzu.yuzu_emu.R |
| 21 | import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding | 26 | import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding |
| @@ -66,25 +71,39 @@ class SettingsActivity : AppCompatActivity() { | |||
| 66 | ) | 71 | ) |
| 67 | } | 72 | } |
| 68 | 73 | ||
| 69 | settingsViewModel.shouldRecreate.observe(this) { | 74 | lifecycleScope.apply { |
| 70 | if (it) { | 75 | launch { |
| 71 | settingsViewModel.setShouldRecreate(false) | 76 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 72 | recreate() | 77 | settingsViewModel.shouldRecreate.collectLatest { |
| 78 | if (it) { | ||
| 79 | settingsViewModel.setShouldRecreate(false) | ||
| 80 | recreate() | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 73 | } | 84 | } |
| 74 | } | 85 | launch { |
| 75 | settingsViewModel.shouldNavigateBack.observe(this) { | 86 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 76 | if (it) { | 87 | settingsViewModel.shouldNavigateBack.collectLatest { |
| 77 | settingsViewModel.setShouldNavigateBack(false) | 88 | if (it) { |
| 78 | navigateBack() | 89 | settingsViewModel.setShouldNavigateBack(false) |
| 90 | navigateBack() | ||
| 91 | } | ||
| 92 | } | ||
| 93 | } | ||
| 79 | } | 94 | } |
| 80 | } | 95 | launch { |
| 81 | settingsViewModel.shouldShowResetSettingsDialog.observe(this) { | 96 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 82 | if (it) { | 97 | settingsViewModel.shouldShowResetSettingsDialog.collectLatest { |
| 83 | settingsViewModel.setShouldShowResetSettingsDialog(false) | 98 | if (it) { |
| 84 | ResetSettingsDialogFragment().show( | 99 | settingsViewModel.setShouldShowResetSettingsDialog(false) |
| 85 | supportFragmentManager, | 100 | ResetSettingsDialogFragment().show( |
| 86 | ResetSettingsDialogFragment.TAG | 101 | supportFragmentManager, |
| 87 | ) | 102 | ResetSettingsDialogFragment.TAG |
| 103 | ) | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } | ||
| 88 | } | 107 | } |
| 89 | } | 108 | } |
| 90 | 109 | ||
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 bc319714c..70d8ec14b 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,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.annotation.SuppressLint | ||
| 6 | import android.os.Bundle | 7 | import android.os.Bundle |
| 7 | import android.view.LayoutInflater | 8 | import android.view.LayoutInflater |
| 8 | import android.view.View | 9 | import android.view.View |
| @@ -13,14 +14,19 @@ import androidx.core.view.WindowInsetsCompat | |||
| 13 | import androidx.core.view.updatePadding | 14 | import androidx.core.view.updatePadding |
| 14 | import androidx.fragment.app.Fragment | 15 | import androidx.fragment.app.Fragment |
| 15 | import androidx.fragment.app.activityViewModels | 16 | import androidx.fragment.app.activityViewModels |
| 17 | import androidx.lifecycle.Lifecycle | ||
| 18 | import androidx.lifecycle.lifecycleScope | ||
| 19 | import androidx.lifecycle.repeatOnLifecycle | ||
| 16 | import androidx.navigation.findNavController | 20 | import androidx.navigation.findNavController |
| 17 | import androidx.navigation.fragment.navArgs | 21 | import androidx.navigation.fragment.navArgs |
| 18 | import androidx.recyclerview.widget.LinearLayoutManager | 22 | import androidx.recyclerview.widget.LinearLayoutManager |
| 19 | import com.google.android.material.divider.MaterialDividerItemDecoration | 23 | import com.google.android.material.divider.MaterialDividerItemDecoration |
| 20 | import com.google.android.material.transition.MaterialSharedAxis | 24 | import com.google.android.material.transition.MaterialSharedAxis |
| 25 | import kotlinx.coroutines.flow.collectLatest | ||
| 26 | import kotlinx.coroutines.launch | ||
| 21 | import org.yuzu.yuzu_emu.R | 27 | import org.yuzu.yuzu_emu.R |
| 22 | import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding | 28 | import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding |
| 23 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 29 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 24 | import org.yuzu.yuzu_emu.model.SettingsViewModel | 30 | import org.yuzu.yuzu_emu.model.SettingsViewModel |
| 25 | 31 | ||
| 26 | class SettingsFragment : Fragment() { | 32 | class SettingsFragment : Fragment() { |
| @@ -51,15 +57,17 @@ class SettingsFragment : Fragment() { | |||
| 51 | return binding.root | 57 | return binding.root |
| 52 | } | 58 | } |
| 53 | 59 | ||
| 60 | // This is using the correct scope, lint is just acting up | ||
| 61 | @SuppressLint("UnsafeRepeatOnLifecycleDetector") | ||
| 54 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 62 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 55 | settingsAdapter = SettingsAdapter(this, requireContext()) | 63 | settingsAdapter = SettingsAdapter(this, requireContext()) |
| 56 | presenter = SettingsFragmentPresenter( | 64 | presenter = SettingsFragmentPresenter( |
| 57 | settingsViewModel, | 65 | settingsViewModel, |
| 58 | settingsAdapter!!, | 66 | settingsAdapter!!, |
| 59 | args.menuTag, | 67 | args.menuTag |
| 60 | args.game?.gameId ?: "" | ||
| 61 | ) | 68 | ) |
| 62 | 69 | ||
| 70 | binding.toolbarSettingsLayout.title = getString(args.menuTag.titleId) | ||
| 63 | val dividerDecoration = MaterialDividerItemDecoration( | 71 | val dividerDecoration = MaterialDividerItemDecoration( |
| 64 | requireContext(), | 72 | requireContext(), |
| 65 | LinearLayoutManager.VERTICAL | 73 | LinearLayoutManager.VERTICAL |
| @@ -75,28 +83,31 @@ class SettingsFragment : Fragment() { | |||
| 75 | settingsViewModel.setShouldNavigateBack(true) | 83 | settingsViewModel.setShouldNavigateBack(true) |
| 76 | } | 84 | } |
| 77 | 85 | ||
| 78 | settingsViewModel.toolbarTitle.observe(viewLifecycleOwner) { | 86 | viewLifecycleOwner.lifecycleScope.apply { |
| 79 | if (it.isNotEmpty()) binding.toolbarSettingsLayout.title = it | 87 | launch { |
| 80 | } | 88 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 81 | 89 | settingsViewModel.shouldReloadSettingsList.collectLatest { | |
| 82 | settingsViewModel.shouldReloadSettingsList.observe(viewLifecycleOwner) { | 90 | if (it) { |
| 83 | if (it) { | 91 | settingsViewModel.setShouldReloadSettingsList(false) |
| 84 | settingsViewModel.setShouldReloadSettingsList(false) | 92 | presenter.loadSettingsList() |
| 85 | presenter.loadSettingsList() | 93 | } |
| 94 | } | ||
| 95 | } | ||
| 86 | } | 96 | } |
| 87 | } | 97 | launch { |
| 88 | 98 | settingsViewModel.isUsingSearch.collectLatest { | |
| 89 | settingsViewModel.isUsingSearch.observe(viewLifecycleOwner) { | 99 | if (it) { |
| 90 | if (it) { | 100 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true) |
| 91 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true) | 101 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) |
| 92 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) | 102 | } else { |
| 93 | } else { | 103 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) |
| 94 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) | 104 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) |
| 95 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) | 105 | } |
| 106 | } | ||
| 96 | } | 107 | } |
| 97 | } | 108 | } |
| 98 | 109 | ||
| 99 | if (args.menuTag == SettingsFile.FILE_NAME_CONFIG) { | 110 | if (args.menuTag == Settings.MenuTag.SECTION_ROOT) { |
| 100 | binding.toolbarSettings.inflateMenu(R.menu.menu_settings) | 111 | binding.toolbarSettings.inflateMenu(R.menu.menu_settings) |
| 101 | binding.toolbarSettings.setOnMenuItemClickListener { | 112 | binding.toolbarSettings.setOnMenuItemClickListener { |
| 102 | when (it.itemId) { | 113 | when (it.itemId) { |
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 22a529b1b..766414a6c 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 | |||
| @@ -6,7 +6,6 @@ package org.yuzu.yuzu_emu.features.settings.ui | |||
| 6 | import android.content.Context | 6 | import android.content.Context |
| 7 | import android.content.SharedPreferences | 7 | import android.content.SharedPreferences |
| 8 | import android.os.Build | 8 | import android.os.Build |
| 9 | import android.text.TextUtils | ||
| 10 | import android.widget.Toast | 9 | import android.widget.Toast |
| 11 | import androidx.preference.PreferenceManager | 10 | import androidx.preference.PreferenceManager |
| 12 | import org.yuzu.yuzu_emu.R | 11 | import org.yuzu.yuzu_emu.R |
| @@ -20,15 +19,13 @@ import org.yuzu.yuzu_emu.features.settings.model.LongSetting | |||
| 20 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 19 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 21 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting | 20 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting |
| 22 | import org.yuzu.yuzu_emu.features.settings.model.view.* | 21 | import org.yuzu.yuzu_emu.features.settings.model.view.* |
| 23 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | ||
| 24 | import org.yuzu.yuzu_emu.model.SettingsViewModel | 22 | import org.yuzu.yuzu_emu.model.SettingsViewModel |
| 25 | import org.yuzu.yuzu_emu.utils.NativeConfig | 23 | import org.yuzu.yuzu_emu.utils.NativeConfig |
| 26 | 24 | ||
| 27 | class SettingsFragmentPresenter( | 25 | class SettingsFragmentPresenter( |
| 28 | private val settingsViewModel: SettingsViewModel, | 26 | private val settingsViewModel: SettingsViewModel, |
| 29 | private val adapter: SettingsAdapter, | 27 | private val adapter: SettingsAdapter, |
| 30 | private var menuTag: String, | 28 | private var menuTag: Settings.MenuTag |
| 31 | private var gameId: String | ||
| 32 | ) { | 29 | ) { |
| 33 | private var settingsList = ArrayList<SettingsItem>() | 30 | private var settingsList = ArrayList<SettingsItem>() |
| 34 | 31 | ||
| @@ -53,24 +50,15 @@ class SettingsFragmentPresenter( | |||
| 53 | } | 50 | } |
| 54 | 51 | ||
| 55 | fun loadSettingsList() { | 52 | fun loadSettingsList() { |
| 56 | if (!TextUtils.isEmpty(gameId)) { | ||
| 57 | settingsViewModel.setToolbarTitle( | ||
| 58 | context.getString( | ||
| 59 | R.string.advanced_settings_game, | ||
| 60 | gameId | ||
| 61 | ) | ||
| 62 | ) | ||
| 63 | } | ||
| 64 | |||
| 65 | val sl = ArrayList<SettingsItem>() | 53 | val sl = ArrayList<SettingsItem>() |
| 66 | when (menuTag) { | 54 | when (menuTag) { |
| 67 | SettingsFile.FILE_NAME_CONFIG -> addConfigSettings(sl) | 55 | Settings.MenuTag.SECTION_ROOT -> addConfigSettings(sl) |
| 68 | Settings.SECTION_GENERAL -> addGeneralSettings(sl) | 56 | Settings.MenuTag.SECTION_GENERAL -> addGeneralSettings(sl) |
| 69 | Settings.SECTION_SYSTEM -> addSystemSettings(sl) | 57 | Settings.MenuTag.SECTION_SYSTEM -> addSystemSettings(sl) |
| 70 | Settings.SECTION_RENDERER -> addGraphicsSettings(sl) | 58 | Settings.MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl) |
| 71 | Settings.SECTION_AUDIO -> addAudioSettings(sl) | 59 | Settings.MenuTag.SECTION_AUDIO -> addAudioSettings(sl) |
| 72 | Settings.SECTION_THEME -> addThemeSettings(sl) | 60 | Settings.MenuTag.SECTION_THEME -> addThemeSettings(sl) |
| 73 | Settings.SECTION_DEBUG -> addDebugSettings(sl) | 61 | Settings.MenuTag.SECTION_DEBUG -> addDebugSettings(sl) |
| 74 | else -> { | 62 | else -> { |
| 75 | val context = YuzuApplication.appContext | 63 | val context = YuzuApplication.appContext |
| 76 | Toast.makeText( | 64 | Toast.makeText( |
| @@ -86,13 +74,12 @@ class SettingsFragmentPresenter( | |||
| 86 | } | 74 | } |
| 87 | 75 | ||
| 88 | private fun addConfigSettings(sl: ArrayList<SettingsItem>) { | 76 | private fun addConfigSettings(sl: ArrayList<SettingsItem>) { |
| 89 | settingsViewModel.setToolbarTitle(context.getString(R.string.advanced_settings)) | ||
| 90 | sl.apply { | 77 | sl.apply { |
| 91 | add(SubmenuSetting(R.string.preferences_general, 0, Settings.SECTION_GENERAL)) | 78 | add(SubmenuSetting(R.string.preferences_general, 0, Settings.MenuTag.SECTION_GENERAL)) |
| 92 | add(SubmenuSetting(R.string.preferences_system, 0, Settings.SECTION_SYSTEM)) | 79 | add(SubmenuSetting(R.string.preferences_system, 0, Settings.MenuTag.SECTION_SYSTEM)) |
| 93 | add(SubmenuSetting(R.string.preferences_graphics, 0, Settings.SECTION_RENDERER)) | 80 | add(SubmenuSetting(R.string.preferences_graphics, 0, Settings.MenuTag.SECTION_RENDERER)) |
| 94 | add(SubmenuSetting(R.string.preferences_audio, 0, Settings.SECTION_AUDIO)) | 81 | add(SubmenuSetting(R.string.preferences_audio, 0, Settings.MenuTag.SECTION_AUDIO)) |
| 95 | add(SubmenuSetting(R.string.preferences_debug, 0, Settings.SECTION_DEBUG)) | 82 | add(SubmenuSetting(R.string.preferences_debug, 0, Settings.MenuTag.SECTION_DEBUG)) |
| 96 | add( | 83 | add( |
| 97 | RunnableSetting(R.string.reset_to_default, 0, false) { | 84 | RunnableSetting(R.string.reset_to_default, 0, false) { |
| 98 | settingsViewModel.setShouldShowResetSettingsDialog(true) | 85 | settingsViewModel.setShouldShowResetSettingsDialog(true) |
| @@ -102,7 +89,6 @@ class SettingsFragmentPresenter( | |||
| 102 | } | 89 | } |
| 103 | 90 | ||
| 104 | private fun addGeneralSettings(sl: ArrayList<SettingsItem>) { | 91 | private fun addGeneralSettings(sl: ArrayList<SettingsItem>) { |
| 105 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_general)) | ||
| 106 | sl.apply { | 92 | sl.apply { |
| 107 | add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key) | 93 | add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key) |
| 108 | add(ShortSetting.RENDERER_SPEED_LIMIT.key) | 94 | add(ShortSetting.RENDERER_SPEED_LIMIT.key) |
| @@ -112,7 +98,6 @@ class SettingsFragmentPresenter( | |||
| 112 | } | 98 | } |
| 113 | 99 | ||
| 114 | private fun addSystemSettings(sl: ArrayList<SettingsItem>) { | 100 | private fun addSystemSettings(sl: ArrayList<SettingsItem>) { |
| 115 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_system)) | ||
| 116 | sl.apply { | 101 | sl.apply { |
| 117 | add(BooleanSetting.USE_DOCKED_MODE.key) | 102 | add(BooleanSetting.USE_DOCKED_MODE.key) |
| 118 | add(IntSetting.REGION_INDEX.key) | 103 | add(IntSetting.REGION_INDEX.key) |
| @@ -123,7 +108,6 @@ class SettingsFragmentPresenter( | |||
| 123 | } | 108 | } |
| 124 | 109 | ||
| 125 | private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) { | 110 | private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) { |
| 126 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_graphics)) | ||
| 127 | sl.apply { | 111 | sl.apply { |
| 128 | add(IntSetting.RENDERER_ACCURACY.key) | 112 | add(IntSetting.RENDERER_ACCURACY.key) |
| 129 | add(IntSetting.RENDERER_RESOLUTION.key) | 113 | add(IntSetting.RENDERER_RESOLUTION.key) |
| @@ -140,7 +124,6 @@ class SettingsFragmentPresenter( | |||
| 140 | } | 124 | } |
| 141 | 125 | ||
| 142 | private fun addAudioSettings(sl: ArrayList<SettingsItem>) { | 126 | private fun addAudioSettings(sl: ArrayList<SettingsItem>) { |
| 143 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_audio)) | ||
| 144 | sl.apply { | 127 | sl.apply { |
| 145 | add(IntSetting.AUDIO_OUTPUT_ENGINE.key) | 128 | add(IntSetting.AUDIO_OUTPUT_ENGINE.key) |
| 146 | add(ByteSetting.AUDIO_VOLUME.key) | 129 | add(ByteSetting.AUDIO_VOLUME.key) |
| @@ -148,7 +131,6 @@ class SettingsFragmentPresenter( | |||
| 148 | } | 131 | } |
| 149 | 132 | ||
| 150 | private fun addThemeSettings(sl: ArrayList<SettingsItem>) { | 133 | private fun addThemeSettings(sl: ArrayList<SettingsItem>) { |
| 151 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_theme)) | ||
| 152 | sl.apply { | 134 | sl.apply { |
| 153 | val theme: AbstractIntSetting = object : AbstractIntSetting { | 135 | val theme: AbstractIntSetting = object : AbstractIntSetting { |
| 154 | override val int: Int | 136 | override val int: Int |
| @@ -261,7 +243,6 @@ class SettingsFragmentPresenter( | |||
| 261 | } | 243 | } |
| 262 | 244 | ||
| 263 | private fun addDebugSettings(sl: ArrayList<SettingsItem>) { | 245 | private fun addDebugSettings(sl: ArrayList<SettingsItem>) { |
| 264 | settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_debug)) | ||
| 265 | sl.apply { | 246 | sl.apply { |
| 266 | add(HeaderSetting(R.string.gpu)) | 247 | add(HeaderSetting(R.string.gpu)) |
| 267 | add(IntSetting.RENDERER_BACKEND.key) | 248 | add(IntSetting.RENDERER_BACKEND.key) |
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 944ae652e..3e6c157c7 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 | |||
| @@ -39,6 +39,7 @@ import androidx.window.layout.WindowLayoutInfo | |||
| 39 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | 39 | import com.google.android.material.dialog.MaterialAlertDialogBuilder |
| 40 | import com.google.android.material.slider.Slider | 40 | import com.google.android.material.slider.Slider |
| 41 | import kotlinx.coroutines.Dispatchers | 41 | import kotlinx.coroutines.Dispatchers |
| 42 | import kotlinx.coroutines.flow.collectLatest | ||
| 42 | import kotlinx.coroutines.launch | 43 | import kotlinx.coroutines.launch |
| 43 | import org.yuzu.yuzu_emu.HomeNavigationDirections | 44 | import org.yuzu.yuzu_emu.HomeNavigationDirections |
| 44 | import org.yuzu.yuzu_emu.NativeLibrary | 45 | import org.yuzu.yuzu_emu.NativeLibrary |
| @@ -49,7 +50,6 @@ import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding | |||
| 49 | import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding | 50 | import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding |
| 50 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting | 51 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting |
| 51 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 52 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 52 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | ||
| 53 | import org.yuzu.yuzu_emu.model.Game | 53 | import org.yuzu.yuzu_emu.model.Game |
| 54 | import org.yuzu.yuzu_emu.model.EmulationViewModel | 54 | import org.yuzu.yuzu_emu.model.EmulationViewModel |
| 55 | import org.yuzu.yuzu_emu.overlay.InputOverlay | 55 | import org.yuzu.yuzu_emu.overlay.InputOverlay |
| @@ -129,6 +129,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 129 | return binding.root | 129 | return binding.root |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | // This is using the correct scope, lint is just acting up | ||
| 133 | @SuppressLint("UnsafeRepeatOnLifecycleDetector") | ||
| 132 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 134 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 133 | binding.surfaceEmulation.holder.addCallback(this) | 135 | binding.surfaceEmulation.holder.addCallback(this) |
| 134 | binding.showFpsText.setTextColor(Color.YELLOW) | 136 | binding.showFpsText.setTextColor(Color.YELLOW) |
| @@ -163,7 +165,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 163 | R.id.menu_settings -> { | 165 | R.id.menu_settings -> { |
| 164 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( | 166 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( |
| 165 | null, | 167 | null, |
| 166 | SettingsFile.FILE_NAME_CONFIG | 168 | Settings.MenuTag.SECTION_ROOT |
| 167 | ) | 169 | ) |
| 168 | binding.root.findNavController().navigate(action) | 170 | binding.root.findNavController().navigate(action) |
| 169 | true | 171 | true |
| @@ -205,59 +207,80 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 205 | } | 207 | } |
| 206 | ) | 208 | ) |
| 207 | 209 | ||
| 208 | viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) { | ||
| 209 | lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { | ||
| 210 | WindowInfoTracker.getOrCreate(requireContext()) | ||
| 211 | .windowLayoutInfo(requireActivity()) | ||
| 212 | .collect { updateFoldableLayout(requireActivity() as EmulationActivity, it) } | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | GameIconUtils.loadGameIcon(game, binding.loadingImage) | 210 | GameIconUtils.loadGameIcon(game, binding.loadingImage) |
| 217 | binding.loadingTitle.text = game.title | 211 | binding.loadingTitle.text = game.title |
| 218 | binding.loadingTitle.isSelected = true | 212 | binding.loadingTitle.isSelected = true |
| 219 | binding.loadingText.isSelected = true | 213 | binding.loadingText.isSelected = true |
| 220 | 214 | ||
| 221 | emulationViewModel.shaderProgress.observe(viewLifecycleOwner) { | 215 | viewLifecycleOwner.lifecycleScope.apply { |
| 222 | if (it > 0 && it != emulationViewModel.totalShaders.value!!) { | 216 | launch { |
| 223 | binding.loadingProgressIndicator.isIndeterminate = false | 217 | repeatOnLifecycle(Lifecycle.State.STARTED) { |
| 224 | 218 | WindowInfoTracker.getOrCreate(requireContext()) | |
| 225 | if (it < binding.loadingProgressIndicator.max) { | 219 | .windowLayoutInfo(requireActivity()) |
| 226 | binding.loadingProgressIndicator.progress = it | 220 | .collect { |
| 221 | updateFoldableLayout(requireActivity() as EmulationActivity, it) | ||
| 222 | } | ||
| 227 | } | 223 | } |
| 228 | } | 224 | } |
| 225 | launch { | ||
| 226 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 227 | emulationViewModel.shaderProgress.collectLatest { | ||
| 228 | if (it > 0 && it != emulationViewModel.totalShaders.value) { | ||
| 229 | binding.loadingProgressIndicator.isIndeterminate = false | ||
| 230 | |||
| 231 | if (it < binding.loadingProgressIndicator.max) { | ||
| 232 | binding.loadingProgressIndicator.progress = it | ||
| 233 | } | ||
| 234 | } | ||
| 229 | 235 | ||
| 230 | if (it == emulationViewModel.totalShaders.value!!) { | 236 | if (it == emulationViewModel.totalShaders.value) { |
| 231 | binding.loadingText.setText(R.string.loading) | 237 | binding.loadingText.setText(R.string.loading) |
| 232 | binding.loadingProgressIndicator.isIndeterminate = true | 238 | binding.loadingProgressIndicator.isIndeterminate = true |
| 239 | } | ||
| 240 | } | ||
| 241 | } | ||
| 233 | } | 242 | } |
| 234 | } | 243 | launch { |
| 235 | emulationViewModel.totalShaders.observe(viewLifecycleOwner) { | 244 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 236 | binding.loadingProgressIndicator.max = it | 245 | emulationViewModel.totalShaders.collectLatest { |
| 237 | } | 246 | binding.loadingProgressIndicator.max = it |
| 238 | emulationViewModel.shaderMessage.observe(viewLifecycleOwner) { | 247 | } |
| 239 | if (it.isNotEmpty()) { | 248 | } |
| 240 | binding.loadingText.text = it | ||
| 241 | } | 249 | } |
| 242 | } | 250 | launch { |
| 243 | 251 | repeatOnLifecycle(Lifecycle.State.CREATED) { | |
| 244 | emulationViewModel.emulationStarted.observe(viewLifecycleOwner) { started -> | 252 | emulationViewModel.shaderMessage.collectLatest { |
| 245 | if (started) { | 253 | if (it.isNotEmpty()) { |
| 246 | binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) | 254 | binding.loadingText.text = it |
| 247 | ViewUtils.showView(binding.surfaceInputOverlay) | 255 | } |
| 248 | ViewUtils.hideView(binding.loadingIndicator) | 256 | } |
| 249 | 257 | } | |
| 250 | // Setup overlay | ||
| 251 | updateShowFpsOverlay() | ||
| 252 | } | 258 | } |
| 253 | } | 259 | launch { |
| 260 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 261 | emulationViewModel.emulationStarted.collectLatest { | ||
| 262 | if (it) { | ||
| 263 | binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) | ||
| 264 | ViewUtils.showView(binding.surfaceInputOverlay) | ||
| 265 | ViewUtils.hideView(binding.loadingIndicator) | ||
| 254 | 266 | ||
| 255 | emulationViewModel.isEmulationStopping.observe(viewLifecycleOwner) { | 267 | // Setup overlay |
| 256 | if (it) { | 268 | updateShowFpsOverlay() |
| 257 | binding.loadingText.setText(R.string.shutting_down) | 269 | } |
| 258 | ViewUtils.showView(binding.loadingIndicator) | 270 | } |
| 259 | ViewUtils.hideView(binding.inputContainer) | 271 | } |
| 260 | ViewUtils.hideView(binding.showFpsText) | 272 | } |
| 273 | launch { | ||
| 274 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 275 | emulationViewModel.isEmulationStopping.collectLatest { | ||
| 276 | if (it) { | ||
| 277 | binding.loadingText.setText(R.string.shutting_down) | ||
| 278 | ViewUtils.showView(binding.loadingIndicator) | ||
| 279 | ViewUtils.hideView(binding.inputContainer) | ||
| 280 | ViewUtils.hideView(binding.showFpsText) | ||
| 281 | } | ||
| 282 | } | ||
| 283 | } | ||
| 261 | } | 284 | } |
| 262 | } | 285 | } |
| 263 | } | 286 | } |
| @@ -274,9 +297,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 274 | } | 297 | } |
| 275 | } | 298 | } |
| 276 | } else { | 299 | } else { |
| 277 | if (EmulationMenuSettings.showOverlay && | 300 | if (EmulationMenuSettings.showOverlay && emulationViewModel.emulationStarted.value) { |
| 278 | emulationViewModel.emulationStarted.value == true | ||
| 279 | ) { | ||
| 280 | binding.surfaceInputOverlay.post { | 301 | binding.surfaceInputOverlay.post { |
| 281 | binding.surfaceInputOverlay.visibility = View.VISIBLE | 302 | binding.surfaceInputOverlay.visibility = View.VISIBLE |
| 282 | } | 303 | } |
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 cbbe14d22..c119e69c9 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 | |||
| @@ -37,7 +37,6 @@ import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter | |||
| 37 | import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding | 37 | import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding |
| 38 | import org.yuzu.yuzu_emu.features.DocumentProvider | 38 | import org.yuzu.yuzu_emu.features.DocumentProvider |
| 39 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 39 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 40 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | ||
| 41 | import org.yuzu.yuzu_emu.model.HomeSetting | 40 | import org.yuzu.yuzu_emu.model.HomeSetting |
| 42 | import org.yuzu.yuzu_emu.model.HomeViewModel | 41 | import org.yuzu.yuzu_emu.model.HomeViewModel |
| 43 | import org.yuzu.yuzu_emu.ui.main.MainActivity | 42 | import org.yuzu.yuzu_emu.ui.main.MainActivity |
| @@ -78,7 +77,7 @@ class HomeSettingsFragment : Fragment() { | |||
| 78 | { | 77 | { |
| 79 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( | 78 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( |
| 80 | null, | 79 | null, |
| 81 | SettingsFile.FILE_NAME_CONFIG | 80 | Settings.MenuTag.SECTION_ROOT |
| 82 | ) | 81 | ) |
| 83 | binding.root.findNavController().navigate(action) | 82 | binding.root.findNavController().navigate(action) |
| 84 | } | 83 | } |
| @@ -100,7 +99,7 @@ class HomeSettingsFragment : Fragment() { | |||
| 100 | { | 99 | { |
| 101 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( | 100 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( |
| 102 | null, | 101 | null, |
| 103 | Settings.SECTION_THEME | 102 | Settings.MenuTag.SECTION_THEME |
| 104 | ) | 103 | ) |
| 105 | binding.root.findNavController().navigate(action) | 104 | binding.root.findNavController().navigate(action) |
| 106 | } | 105 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt index 181bd983a..ea8eb073a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt | |||
| @@ -9,8 +9,12 @@ import android.widget.Toast | |||
| 9 | import androidx.appcompat.app.AppCompatActivity | 9 | import androidx.appcompat.app.AppCompatActivity |
| 10 | import androidx.fragment.app.DialogFragment | 10 | import androidx.fragment.app.DialogFragment |
| 11 | import androidx.fragment.app.activityViewModels | 11 | import androidx.fragment.app.activityViewModels |
| 12 | import androidx.lifecycle.Lifecycle | ||
| 12 | import androidx.lifecycle.ViewModelProvider | 13 | import androidx.lifecycle.ViewModelProvider |
| 14 | import androidx.lifecycle.lifecycleScope | ||
| 15 | import androidx.lifecycle.repeatOnLifecycle | ||
| 13 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | 16 | import com.google.android.material.dialog.MaterialAlertDialogBuilder |
| 17 | import kotlinx.coroutines.launch | ||
| 14 | import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding | 18 | import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding |
| 15 | import org.yuzu.yuzu_emu.model.TaskViewModel | 19 | import org.yuzu.yuzu_emu.model.TaskViewModel |
| 16 | 20 | ||
| @@ -28,21 +32,27 @@ class IndeterminateProgressDialogFragment : DialogFragment() { | |||
| 28 | .create() | 32 | .create() |
| 29 | dialog.setCanceledOnTouchOutside(false) | 33 | dialog.setCanceledOnTouchOutside(false) |
| 30 | 34 | ||
| 31 | taskViewModel.isComplete.observe(this) { complete -> | 35 | viewLifecycleOwner.lifecycleScope.launch { |
| 32 | if (complete) { | 36 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 33 | dialog.dismiss() | 37 | taskViewModel.isComplete.collect { |
| 34 | when (val result = taskViewModel.result.value) { | 38 | if (it) { |
| 35 | is String -> Toast.makeText(requireContext(), result, Toast.LENGTH_LONG).show() | 39 | dialog.dismiss() |
| 36 | is MessageDialogFragment -> result.show( | 40 | when (val result = taskViewModel.result.value) { |
| 37 | requireActivity().supportFragmentManager, | 41 | is String -> Toast.makeText(requireContext(), result, Toast.LENGTH_LONG) |
| 38 | MessageDialogFragment.TAG | 42 | .show() |
| 39 | ) | 43 | |
| 44 | is MessageDialogFragment -> result.show( | ||
| 45 | requireActivity().supportFragmentManager, | ||
| 46 | MessageDialogFragment.TAG | ||
| 47 | ) | ||
| 48 | } | ||
| 49 | taskViewModel.clear() | ||
| 50 | } | ||
| 40 | } | 51 | } |
| 41 | taskViewModel.clear() | ||
| 42 | } | 52 | } |
| 43 | } | 53 | } |
| 44 | 54 | ||
| 45 | if (taskViewModel.isRunning.value == false) { | 55 | if (!taskViewModel.isRunning.value) { |
| 46 | taskViewModel.runTask() | 56 | taskViewModel.runTask() |
| 47 | } | 57 | } |
| 48 | return dialog | 58 | return dialog |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt index f54dccc69..2dbca76a5 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.fragments | 4 | package org.yuzu.yuzu_emu.fragments |
| 5 | 5 | ||
| 6 | import android.annotation.SuppressLint | ||
| 6 | import android.content.Context | 7 | import android.content.Context |
| 7 | import android.content.SharedPreferences | 8 | import android.content.SharedPreferences |
| 8 | import android.os.Bundle | 9 | import android.os.Bundle |
| @@ -17,9 +18,13 @@ import androidx.core.view.updatePadding | |||
| 17 | import androidx.core.widget.doOnTextChanged | 18 | import androidx.core.widget.doOnTextChanged |
| 18 | import androidx.fragment.app.Fragment | 19 | import androidx.fragment.app.Fragment |
| 19 | import androidx.fragment.app.activityViewModels | 20 | import androidx.fragment.app.activityViewModels |
| 21 | import androidx.lifecycle.Lifecycle | ||
| 22 | import androidx.lifecycle.lifecycleScope | ||
| 23 | import androidx.lifecycle.repeatOnLifecycle | ||
| 20 | import androidx.preference.PreferenceManager | 24 | import androidx.preference.PreferenceManager |
| 21 | import info.debatty.java.stringsimilarity.Jaccard | 25 | import info.debatty.java.stringsimilarity.Jaccard |
| 22 | import info.debatty.java.stringsimilarity.JaroWinkler | 26 | import info.debatty.java.stringsimilarity.JaroWinkler |
| 27 | import kotlinx.coroutines.launch | ||
| 23 | import java.util.Locale | 28 | import java.util.Locale |
| 24 | import org.yuzu.yuzu_emu.R | 29 | import org.yuzu.yuzu_emu.R |
| 25 | import org.yuzu.yuzu_emu.YuzuApplication | 30 | import org.yuzu.yuzu_emu.YuzuApplication |
| @@ -52,6 +57,8 @@ class SearchFragment : Fragment() { | |||
| 52 | return binding.root | 57 | return binding.root |
| 53 | } | 58 | } |
| 54 | 59 | ||
| 60 | // This is using the correct scope, lint is just acting up | ||
| 61 | @SuppressLint("UnsafeRepeatOnLifecycleDetector") | ||
| 55 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 62 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 56 | homeViewModel.setNavigationVisibility(visible = true, animated = false) | 63 | homeViewModel.setNavigationVisibility(visible = true, animated = false) |
| 57 | preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | 64 | preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) |
| @@ -79,21 +86,32 @@ class SearchFragment : Fragment() { | |||
| 79 | filterAndSearch() | 86 | filterAndSearch() |
| 80 | } | 87 | } |
| 81 | 88 | ||
| 82 | gamesViewModel.apply { | 89 | viewLifecycleOwner.lifecycleScope.apply { |
| 83 | searchFocused.observe(viewLifecycleOwner) { searchFocused -> | 90 | launch { |
| 84 | if (searchFocused) { | 91 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 85 | focusSearch() | 92 | gamesViewModel.searchFocused.collect { |
| 86 | gamesViewModel.setSearchFocused(false) | 93 | if (it) { |
| 94 | focusSearch() | ||
| 95 | gamesViewModel.setSearchFocused(false) | ||
| 96 | } | ||
| 97 | } | ||
| 87 | } | 98 | } |
| 88 | } | 99 | } |
| 89 | 100 | launch { | |
| 90 | games.observe(viewLifecycleOwner) { filterAndSearch() } | 101 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 91 | searchedGames.observe(viewLifecycleOwner) { | 102 | gamesViewModel.games.collect { filterAndSearch() } |
| 92 | (binding.gridGamesSearch.adapter as GameAdapter).submitList(it) | 103 | } |
| 93 | if (it.isEmpty()) { | 104 | } |
| 94 | binding.noResultsView.visibility = View.VISIBLE | 105 | launch { |
| 95 | } else { | 106 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 96 | binding.noResultsView.visibility = View.GONE | 107 | gamesViewModel.searchedGames.collect { |
| 108 | (binding.gridGamesSearch.adapter as GameAdapter).submitList(it) | ||
| 109 | if (it.isEmpty()) { | ||
| 110 | binding.noResultsView.visibility = View.VISIBLE | ||
| 111 | } else { | ||
| 112 | binding.noResultsView.visibility = View.GONE | ||
| 113 | } | ||
| 114 | } | ||
| 97 | } | 115 | } |
| 98 | } | 116 | } |
| 99 | } | 117 | } |
| @@ -109,7 +127,7 @@ class SearchFragment : Fragment() { | |||
| 109 | private inner class ScoredGame(val score: Double, val item: Game) | 127 | private inner class ScoredGame(val score: Double, val item: Game) |
| 110 | 128 | ||
| 111 | private fun filterAndSearch() { | 129 | private fun filterAndSearch() { |
| 112 | val baseList = gamesViewModel.games.value!! | 130 | val baseList = gamesViewModel.games.value |
| 113 | val filteredList: List<Game> = when (binding.chipGroup.checkedChipId) { | 131 | val filteredList: List<Game> = when (binding.chipGroup.checkedChipId) { |
| 114 | R.id.chip_recently_played -> { | 132 | R.id.chip_recently_played -> { |
| 115 | baseList.filter { | 133 | baseList.filter { |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsSearchFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsSearchFragment.kt index 55b6a0367..9d0594c6e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsSearchFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsSearchFragment.kt | |||
| @@ -15,10 +15,14 @@ import androidx.core.view.updatePadding | |||
| 15 | import androidx.core.widget.doOnTextChanged | 15 | import androidx.core.widget.doOnTextChanged |
| 16 | import androidx.fragment.app.Fragment | 16 | import androidx.fragment.app.Fragment |
| 17 | import androidx.fragment.app.activityViewModels | 17 | import androidx.fragment.app.activityViewModels |
| 18 | import androidx.lifecycle.Lifecycle | ||
| 19 | import androidx.lifecycle.lifecycleScope | ||
| 20 | import androidx.lifecycle.repeatOnLifecycle | ||
| 18 | import androidx.recyclerview.widget.LinearLayoutManager | 21 | import androidx.recyclerview.widget.LinearLayoutManager |
| 19 | import com.google.android.material.divider.MaterialDividerItemDecoration | 22 | import com.google.android.material.divider.MaterialDividerItemDecoration |
| 20 | import com.google.android.material.transition.MaterialSharedAxis | 23 | import com.google.android.material.transition.MaterialSharedAxis |
| 21 | import info.debatty.java.stringsimilarity.Cosine | 24 | import info.debatty.java.stringsimilarity.Cosine |
| 25 | import kotlinx.coroutines.launch | ||
| 22 | import org.yuzu.yuzu_emu.R | 26 | import org.yuzu.yuzu_emu.R |
| 23 | import org.yuzu.yuzu_emu.databinding.FragmentSettingsSearchBinding | 27 | import org.yuzu.yuzu_emu.databinding.FragmentSettingsSearchBinding |
| 24 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem | 28 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem |
| @@ -79,10 +83,14 @@ class SettingsSearchFragment : Fragment() { | |||
| 79 | search() | 83 | search() |
| 80 | binding.settingsList.smoothScrollToPosition(0) | 84 | binding.settingsList.smoothScrollToPosition(0) |
| 81 | } | 85 | } |
| 82 | settingsViewModel.shouldReloadSettingsList.observe(viewLifecycleOwner) { | 86 | viewLifecycleOwner.lifecycleScope.launch { |
| 83 | if (it) { | 87 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 84 | settingsViewModel.setShouldReloadSettingsList(false) | 88 | settingsViewModel.shouldReloadSettingsList.collect { |
| 85 | search() | 89 | if (it) { |
| 90 | settingsViewModel.setShouldReloadSettingsList(false) | ||
| 91 | search() | ||
| 92 | } | ||
| 93 | } | ||
| 86 | } | 94 | } |
| 87 | } | 95 | } |
| 88 | 96 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt index d50c421a0..fbb2f6e18 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt | |||
| @@ -22,10 +22,14 @@ import androidx.core.view.isVisible | |||
| 22 | import androidx.core.view.updatePadding | 22 | import androidx.core.view.updatePadding |
| 23 | import androidx.fragment.app.Fragment | 23 | import androidx.fragment.app.Fragment |
| 24 | import androidx.fragment.app.activityViewModels | 24 | import androidx.fragment.app.activityViewModels |
| 25 | import androidx.lifecycle.Lifecycle | ||
| 26 | import androidx.lifecycle.lifecycleScope | ||
| 27 | import androidx.lifecycle.repeatOnLifecycle | ||
| 25 | import androidx.navigation.findNavController | 28 | import androidx.navigation.findNavController |
| 26 | import androidx.preference.PreferenceManager | 29 | import androidx.preference.PreferenceManager |
| 27 | import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback | 30 | import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback |
| 28 | import com.google.android.material.transition.MaterialFadeThrough | 31 | import com.google.android.material.transition.MaterialFadeThrough |
| 32 | import kotlinx.coroutines.launch | ||
| 29 | import java.io.File | 33 | import java.io.File |
| 30 | import org.yuzu.yuzu_emu.R | 34 | import org.yuzu.yuzu_emu.R |
| 31 | import org.yuzu.yuzu_emu.YuzuApplication | 35 | import org.yuzu.yuzu_emu.YuzuApplication |
| @@ -206,10 +210,14 @@ class SetupFragment : Fragment() { | |||
| 206 | ) | 210 | ) |
| 207 | } | 211 | } |
| 208 | 212 | ||
| 209 | homeViewModel.shouldPageForward.observe(viewLifecycleOwner) { | 213 | viewLifecycleOwner.lifecycleScope.launch { |
| 210 | if (it) { | 214 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 211 | pageForward() | 215 | homeViewModel.shouldPageForward.collect { |
| 212 | homeViewModel.setShouldPageForward(false) | 216 | if (it) { |
| 217 | pageForward() | ||
| 218 | homeViewModel.setShouldPageForward(false) | ||
| 219 | } | ||
| 220 | } | ||
| 213 | } | 221 | } |
| 214 | } | 222 | } |
| 215 | 223 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt index e35f51bc3..f34870c2d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/EmulationViewModel.kt | |||
| @@ -3,28 +3,28 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.model | 4 | package org.yuzu.yuzu_emu.model |
| 5 | 5 | ||
| 6 | import androidx.lifecycle.LiveData | ||
| 7 | import androidx.lifecycle.MutableLiveData | ||
| 8 | import androidx.lifecycle.ViewModel | 6 | import androidx.lifecycle.ViewModel |
| 7 | import kotlinx.coroutines.flow.MutableStateFlow | ||
| 8 | import kotlinx.coroutines.flow.StateFlow | ||
| 9 | 9 | ||
| 10 | class EmulationViewModel : ViewModel() { | 10 | class EmulationViewModel : ViewModel() { |
| 11 | private val _emulationStarted = MutableLiveData(false) | 11 | val emulationStarted: StateFlow<Boolean> get() = _emulationStarted |
| 12 | val emulationStarted: LiveData<Boolean> get() = _emulationStarted | 12 | private val _emulationStarted = MutableStateFlow(false) |
| 13 | 13 | ||
| 14 | private val _isEmulationStopping = MutableLiveData(false) | 14 | val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping |
| 15 | val isEmulationStopping: LiveData<Boolean> get() = _isEmulationStopping | 15 | private val _isEmulationStopping = MutableStateFlow(false) |
| 16 | 16 | ||
| 17 | private val _shaderProgress = MutableLiveData(0) | 17 | val shaderProgress: StateFlow<Int> get() = _shaderProgress |
| 18 | val shaderProgress: LiveData<Int> get() = _shaderProgress | 18 | private val _shaderProgress = MutableStateFlow(0) |
| 19 | 19 | ||
| 20 | private val _totalShaders = MutableLiveData(0) | 20 | val totalShaders: StateFlow<Int> get() = _totalShaders |
| 21 | val totalShaders: LiveData<Int> get() = _totalShaders | 21 | private val _totalShaders = MutableStateFlow(0) |
| 22 | 22 | ||
| 23 | private val _shaderMessage = MutableLiveData("") | 23 | val shaderMessage: StateFlow<String> get() = _shaderMessage |
| 24 | val shaderMessage: LiveData<String> get() = _shaderMessage | 24 | private val _shaderMessage = MutableStateFlow("") |
| 25 | 25 | ||
| 26 | fun setEmulationStarted(started: Boolean) { | 26 | fun setEmulationStarted(started: Boolean) { |
| 27 | _emulationStarted.postValue(started) | 27 | _emulationStarted.value = started |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | fun setIsEmulationStopping(value: Boolean) { | 30 | fun setIsEmulationStopping(value: Boolean) { |
| @@ -50,10 +50,18 @@ class EmulationViewModel : ViewModel() { | |||
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | fun clear() { | 52 | fun clear() { |
| 53 | _emulationStarted.value = false | 53 | setEmulationStarted(false) |
| 54 | _isEmulationStopping.value = false | 54 | setIsEmulationStopping(false) |
| 55 | _shaderProgress.value = 0 | 55 | setShaderProgress(0) |
| 56 | _totalShaders.value = 0 | 56 | setTotalShaders(0) |
| 57 | _shaderMessage.value = "" | 57 | setShaderMessage("") |
| 58 | } | ||
| 59 | |||
| 60 | companion object { | ||
| 61 | const val KEY_EMULATION_STARTED = "EmulationStarted" | ||
| 62 | const val KEY_IS_EMULATION_STOPPING = "IsEmulationStarting" | ||
| 63 | const val KEY_SHADER_PROGRESS = "ShaderProgress" | ||
| 64 | const val KEY_TOTAL_SHADERS = "TotalShaders" | ||
| 65 | const val KEY_SHADER_MESSAGE = "ShaderMessage" | ||
| 58 | } | 66 | } |
| 59 | } | 67 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt index 1fe42f922..6e09fa81d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt | |||
| @@ -5,13 +5,13 @@ package org.yuzu.yuzu_emu.model | |||
| 5 | 5 | ||
| 6 | import android.net.Uri | 6 | import android.net.Uri |
| 7 | import androidx.documentfile.provider.DocumentFile | 7 | import androidx.documentfile.provider.DocumentFile |
| 8 | import androidx.lifecycle.LiveData | ||
| 9 | import androidx.lifecycle.MutableLiveData | ||
| 10 | import androidx.lifecycle.ViewModel | 8 | import androidx.lifecycle.ViewModel |
| 11 | import androidx.lifecycle.viewModelScope | 9 | import androidx.lifecycle.viewModelScope |
| 12 | import androidx.preference.PreferenceManager | 10 | import androidx.preference.PreferenceManager |
| 13 | import java.util.Locale | 11 | import java.util.Locale |
| 14 | import kotlinx.coroutines.Dispatchers | 12 | import kotlinx.coroutines.Dispatchers |
| 13 | import kotlinx.coroutines.flow.MutableStateFlow | ||
| 14 | import kotlinx.coroutines.flow.StateFlow | ||
| 15 | import kotlinx.coroutines.launch | 15 | import kotlinx.coroutines.launch |
| 16 | import kotlinx.coroutines.withContext | 16 | import kotlinx.coroutines.withContext |
| 17 | import kotlinx.serialization.ExperimentalSerializationApi | 17 | import kotlinx.serialization.ExperimentalSerializationApi |
| @@ -24,23 +24,23 @@ import org.yuzu.yuzu_emu.utils.GameHelper | |||
| 24 | 24 | ||
| 25 | @OptIn(ExperimentalSerializationApi::class) | 25 | @OptIn(ExperimentalSerializationApi::class) |
| 26 | class GamesViewModel : ViewModel() { | 26 | class GamesViewModel : ViewModel() { |
| 27 | private val _games = MutableLiveData<List<Game>>(emptyList()) | 27 | val games: StateFlow<List<Game>> get() = _games |
| 28 | val games: LiveData<List<Game>> get() = _games | 28 | private val _games = MutableStateFlow(emptyList<Game>()) |
| 29 | 29 | ||
| 30 | private val _searchedGames = MutableLiveData<List<Game>>(emptyList()) | 30 | val searchedGames: StateFlow<List<Game>> get() = _searchedGames |
| 31 | val searchedGames: LiveData<List<Game>> get() = _searchedGames | 31 | private val _searchedGames = MutableStateFlow(emptyList<Game>()) |
| 32 | 32 | ||
| 33 | private val _isReloading = MutableLiveData(false) | 33 | val isReloading: StateFlow<Boolean> get() = _isReloading |
| 34 | val isReloading: LiveData<Boolean> get() = _isReloading | 34 | private val _isReloading = MutableStateFlow(false) |
| 35 | 35 | ||
| 36 | private val _shouldSwapData = MutableLiveData(false) | 36 | val shouldSwapData: StateFlow<Boolean> get() = _shouldSwapData |
| 37 | val shouldSwapData: LiveData<Boolean> get() = _shouldSwapData | 37 | private val _shouldSwapData = MutableStateFlow(false) |
| 38 | 38 | ||
| 39 | private val _shouldScrollToTop = MutableLiveData(false) | 39 | val shouldScrollToTop: StateFlow<Boolean> get() = _shouldScrollToTop |
| 40 | val shouldScrollToTop: LiveData<Boolean> get() = _shouldScrollToTop | 40 | private val _shouldScrollToTop = MutableStateFlow(false) |
| 41 | 41 | ||
| 42 | private val _searchFocused = MutableLiveData(false) | 42 | val searchFocused: StateFlow<Boolean> get() = _searchFocused |
| 43 | val searchFocused: LiveData<Boolean> get() = _searchFocused | 43 | private val _searchFocused = MutableStateFlow(false) |
| 44 | 44 | ||
| 45 | init { | 45 | init { |
| 46 | // Ensure keys are loaded so that ROM metadata can be decrypted. | 46 | // Ensure keys are loaded so that ROM metadata can be decrypted. |
| @@ -79,36 +79,36 @@ class GamesViewModel : ViewModel() { | |||
| 79 | ) | 79 | ) |
| 80 | ) | 80 | ) |
| 81 | 81 | ||
| 82 | _games.postValue(sortedList) | 82 | _games.value = sortedList |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | fun setSearchedGames(games: List<Game>) { | 85 | fun setSearchedGames(games: List<Game>) { |
| 86 | _searchedGames.postValue(games) | 86 | _searchedGames.value = games |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | fun setShouldSwapData(shouldSwap: Boolean) { | 89 | fun setShouldSwapData(shouldSwap: Boolean) { |
| 90 | _shouldSwapData.postValue(shouldSwap) | 90 | _shouldSwapData.value = shouldSwap |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | fun setShouldScrollToTop(shouldScroll: Boolean) { | 93 | fun setShouldScrollToTop(shouldScroll: Boolean) { |
| 94 | _shouldScrollToTop.postValue(shouldScroll) | 94 | _shouldScrollToTop.value = shouldScroll |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | fun setSearchFocused(searchFocused: Boolean) { | 97 | fun setSearchFocused(searchFocused: Boolean) { |
| 98 | _searchFocused.postValue(searchFocused) | 98 | _searchFocused.value = searchFocused |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | fun reloadGames(directoryChanged: Boolean) { | 101 | fun reloadGames(directoryChanged: Boolean) { |
| 102 | if (isReloading.value == true) { | 102 | if (isReloading.value) { |
| 103 | return | 103 | return |
| 104 | } | 104 | } |
| 105 | _isReloading.postValue(true) | 105 | _isReloading.value = true |
| 106 | 106 | ||
| 107 | viewModelScope.launch { | 107 | viewModelScope.launch { |
| 108 | withContext(Dispatchers.IO) { | 108 | withContext(Dispatchers.IO) { |
| 109 | NativeLibrary.resetRomMetadata() | 109 | NativeLibrary.resetRomMetadata() |
| 110 | setGames(GameHelper.getGames()) | 110 | setGames(GameHelper.getGames()) |
| 111 | _isReloading.postValue(false) | 111 | _isReloading.value = false |
| 112 | 112 | ||
| 113 | if (directoryChanged) { | 113 | if (directoryChanged) { |
| 114 | setShouldSwapData(true) | 114 | setShouldSwapData(true) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeSetting.kt index 498c222fa..b32e19373 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeSetting.kt | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.model | 4 | package org.yuzu.yuzu_emu.model |
| 5 | 5 | ||
| 6 | import androidx.lifecycle.LiveData | 6 | import kotlinx.coroutines.flow.MutableStateFlow |
| 7 | import androidx.lifecycle.MutableLiveData | 7 | import kotlinx.coroutines.flow.StateFlow |
| 8 | 8 | ||
| 9 | data class HomeSetting( | 9 | data class HomeSetting( |
| 10 | val titleId: Int, | 10 | val titleId: Int, |
| @@ -14,5 +14,5 @@ data class HomeSetting( | |||
| 14 | val isEnabled: () -> Boolean = { true }, | 14 | val isEnabled: () -> Boolean = { true }, |
| 15 | val disabledTitleId: Int = 0, | 15 | val disabledTitleId: Int = 0, |
| 16 | val disabledMessageId: Int = 0, | 16 | val disabledMessageId: Int = 0, |
| 17 | val details: LiveData<String> = MutableLiveData("") | 17 | val details: StateFlow<String> = MutableStateFlow("") |
| 18 | ) | 18 | ) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt index a48ef7a88..756f76721 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt | |||
| @@ -5,47 +5,43 @@ package org.yuzu.yuzu_emu.model | |||
| 5 | 5 | ||
| 6 | import android.net.Uri | 6 | import android.net.Uri |
| 7 | import androidx.fragment.app.FragmentActivity | 7 | import androidx.fragment.app.FragmentActivity |
| 8 | import androidx.lifecycle.LiveData | ||
| 9 | import androidx.lifecycle.MutableLiveData | ||
| 10 | import androidx.lifecycle.ViewModel | 8 | import androidx.lifecycle.ViewModel |
| 11 | import androidx.lifecycle.ViewModelProvider | 9 | import androidx.lifecycle.ViewModelProvider |
| 12 | import androidx.preference.PreferenceManager | 10 | import androidx.preference.PreferenceManager |
| 11 | import kotlinx.coroutines.flow.MutableStateFlow | ||
| 12 | import kotlinx.coroutines.flow.StateFlow | ||
| 13 | import org.yuzu.yuzu_emu.YuzuApplication | 13 | import org.yuzu.yuzu_emu.YuzuApplication |
| 14 | import org.yuzu.yuzu_emu.utils.GameHelper | 14 | import org.yuzu.yuzu_emu.utils.GameHelper |
| 15 | 15 | ||
| 16 | class HomeViewModel : ViewModel() { | 16 | class HomeViewModel : ViewModel() { |
| 17 | private val _navigationVisible = MutableLiveData<Pair<Boolean, Boolean>>() | 17 | val navigationVisible: StateFlow<Pair<Boolean, Boolean>> get() = _navigationVisible |
| 18 | val navigationVisible: LiveData<Pair<Boolean, Boolean>> get() = _navigationVisible | 18 | private val _navigationVisible = MutableStateFlow(Pair(false, false)) |
| 19 | 19 | ||
| 20 | private val _statusBarShadeVisible = MutableLiveData(true) | 20 | val statusBarShadeVisible: StateFlow<Boolean> get() = _statusBarShadeVisible |
| 21 | val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible | 21 | private val _statusBarShadeVisible = MutableStateFlow(true) |
| 22 | 22 | ||
| 23 | private val _shouldPageForward = MutableLiveData(false) | 23 | val shouldPageForward: StateFlow<Boolean> get() = _shouldPageForward |
| 24 | val shouldPageForward: LiveData<Boolean> get() = _shouldPageForward | 24 | private val _shouldPageForward = MutableStateFlow(false) |
| 25 | 25 | ||
| 26 | private val _gamesDir = MutableLiveData( | 26 | val gamesDir: StateFlow<String> get() = _gamesDir |
| 27 | private val _gamesDir = MutableStateFlow( | ||
| 27 | Uri.parse( | 28 | Uri.parse( |
| 28 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | 29 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) |
| 29 | .getString(GameHelper.KEY_GAME_PATH, "") | 30 | .getString(GameHelper.KEY_GAME_PATH, "") |
| 30 | ).path ?: "" | 31 | ).path ?: "" |
| 31 | ) | 32 | ) |
| 32 | val gamesDir: LiveData<String> get() = _gamesDir | ||
| 33 | 33 | ||
| 34 | var navigatedToSetup = false | 34 | var navigatedToSetup = false |
| 35 | 35 | ||
| 36 | init { | ||
| 37 | _navigationVisible.value = Pair(false, false) | ||
| 38 | } | ||
| 39 | |||
| 40 | fun setNavigationVisibility(visible: Boolean, animated: Boolean) { | 36 | fun setNavigationVisibility(visible: Boolean, animated: Boolean) { |
| 41 | if (_navigationVisible.value?.first == visible) { | 37 | if (navigationVisible.value.first == visible) { |
| 42 | return | 38 | return |
| 43 | } | 39 | } |
| 44 | _navigationVisible.value = Pair(visible, animated) | 40 | _navigationVisible.value = Pair(visible, animated) |
| 45 | } | 41 | } |
| 46 | 42 | ||
| 47 | fun setStatusBarShadeVisibility(visible: Boolean) { | 43 | fun setStatusBarShadeVisibility(visible: Boolean) { |
| 48 | if (_statusBarShadeVisible.value == visible) { | 44 | if (statusBarShadeVisible.value == visible) { |
| 49 | return | 45 | return |
| 50 | } | 46 | } |
| 51 | _statusBarShadeVisible.value = visible | 47 | _statusBarShadeVisible.value = visible |
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 index d16d15fa6..53fa7a8de 100644 --- 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 | |||
| @@ -3,48 +3,43 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.model | 4 | package org.yuzu.yuzu_emu.model |
| 5 | 5 | ||
| 6 | import androidx.lifecycle.LiveData | ||
| 7 | import androidx.lifecycle.MutableLiveData | ||
| 8 | import androidx.lifecycle.SavedStateHandle | ||
| 9 | import androidx.lifecycle.ViewModel | 6 | import androidx.lifecycle.ViewModel |
| 7 | import kotlinx.coroutines.flow.MutableStateFlow | ||
| 8 | import kotlinx.coroutines.flow.StateFlow | ||
| 10 | import org.yuzu.yuzu_emu.R | 9 | import org.yuzu.yuzu_emu.R |
| 11 | import org.yuzu.yuzu_emu.YuzuApplication | 10 | import org.yuzu.yuzu_emu.YuzuApplication |
| 12 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem | 11 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem |
| 13 | 12 | ||
| 14 | class SettingsViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() { | 13 | class SettingsViewModel : ViewModel() { |
| 15 | var game: Game? = null | 14 | var game: Game? = null |
| 16 | 15 | ||
| 17 | var shouldSave = false | 16 | var shouldSave = false |
| 18 | 17 | ||
| 19 | var clickedItem: SettingsItem? = null | 18 | var clickedItem: SettingsItem? = null |
| 20 | 19 | ||
| 21 | private val _toolbarTitle = MutableLiveData("") | 20 | val shouldRecreate: StateFlow<Boolean> get() = _shouldRecreate |
| 22 | val toolbarTitle: LiveData<String> get() = _toolbarTitle | 21 | private val _shouldRecreate = MutableStateFlow(false) |
| 23 | 22 | ||
| 24 | private val _shouldRecreate = MutableLiveData(false) | 23 | val shouldNavigateBack: StateFlow<Boolean> get() = _shouldNavigateBack |
| 25 | val shouldRecreate: LiveData<Boolean> get() = _shouldRecreate | 24 | private val _shouldNavigateBack = MutableStateFlow(false) |
| 26 | 25 | ||
| 27 | private val _shouldNavigateBack = MutableLiveData(false) | 26 | val shouldShowResetSettingsDialog: StateFlow<Boolean> get() = _shouldShowResetSettingsDialog |
| 28 | val shouldNavigateBack: LiveData<Boolean> get() = _shouldNavigateBack | 27 | private val _shouldShowResetSettingsDialog = MutableStateFlow(false) |
| 29 | 28 | ||
| 30 | private val _shouldShowResetSettingsDialog = MutableLiveData(false) | 29 | val shouldReloadSettingsList: StateFlow<Boolean> get() = _shouldReloadSettingsList |
| 31 | val shouldShowResetSettingsDialog: LiveData<Boolean> get() = _shouldShowResetSettingsDialog | 30 | private val _shouldReloadSettingsList = MutableStateFlow(false) |
| 32 | 31 | ||
| 33 | private val _shouldReloadSettingsList = MutableLiveData(false) | 32 | val isUsingSearch: StateFlow<Boolean> get() = _isUsingSearch |
| 34 | val shouldReloadSettingsList: LiveData<Boolean> get() = _shouldReloadSettingsList | 33 | private val _isUsingSearch = MutableStateFlow(false) |
| 35 | 34 | ||
| 36 | private val _isUsingSearch = MutableLiveData(false) | 35 | val sliderProgress: StateFlow<Int> get() = _sliderProgress |
| 37 | val isUsingSearch: LiveData<Boolean> get() = _isUsingSearch | 36 | private val _sliderProgress = MutableStateFlow(-1) |
| 38 | 37 | ||
| 39 | val sliderProgress = savedStateHandle.getStateFlow(KEY_SLIDER_PROGRESS, -1) | 38 | val sliderTextValue: StateFlow<String> get() = _sliderTextValue |
| 39 | private val _sliderTextValue = MutableStateFlow("") | ||
| 40 | 40 | ||
| 41 | val sliderTextValue = savedStateHandle.getStateFlow(KEY_SLIDER_TEXT_VALUE, "") | 41 | val adapterItemChanged: StateFlow<Int> get() = _adapterItemChanged |
| 42 | 42 | private val _adapterItemChanged = MutableStateFlow(-1) | |
| 43 | val adapterItemChanged = savedStateHandle.getStateFlow(KEY_ADAPTER_ITEM_CHANGED, -1) | ||
| 44 | |||
| 45 | fun setToolbarTitle(value: String) { | ||
| 46 | _toolbarTitle.value = value | ||
| 47 | } | ||
| 48 | 43 | ||
| 49 | fun setShouldRecreate(value: Boolean) { | 44 | fun setShouldRecreate(value: Boolean) { |
| 50 | _shouldRecreate.value = value | 45 | _shouldRecreate.value = value |
| @@ -67,8 +62,8 @@ class SettingsViewModel(private val savedStateHandle: SavedStateHandle) : ViewMo | |||
| 67 | } | 62 | } |
| 68 | 63 | ||
| 69 | fun setSliderTextValue(value: Float, units: String) { | 64 | fun setSliderTextValue(value: Float, units: String) { |
| 70 | savedStateHandle[KEY_SLIDER_PROGRESS] = value | 65 | _sliderProgress.value = value.toInt() |
| 71 | savedStateHandle[KEY_SLIDER_TEXT_VALUE] = String.format( | 66 | _sliderTextValue.value = String.format( |
| 72 | YuzuApplication.appContext.getString(R.string.value_with_units), | 67 | YuzuApplication.appContext.getString(R.string.value_with_units), |
| 73 | value.toInt().toString(), | 68 | value.toInt().toString(), |
| 74 | units | 69 | units |
| @@ -76,21 +71,15 @@ class SettingsViewModel(private val savedStateHandle: SavedStateHandle) : ViewMo | |||
| 76 | } | 71 | } |
| 77 | 72 | ||
| 78 | fun setSliderProgress(value: Float) { | 73 | fun setSliderProgress(value: Float) { |
| 79 | savedStateHandle[KEY_SLIDER_PROGRESS] = value | 74 | _sliderProgress.value = value.toInt() |
| 80 | } | 75 | } |
| 81 | 76 | ||
| 82 | fun setAdapterItemChanged(value: Int) { | 77 | fun setAdapterItemChanged(value: Int) { |
| 83 | savedStateHandle[KEY_ADAPTER_ITEM_CHANGED] = value | 78 | _adapterItemChanged.value = value |
| 84 | } | 79 | } |
| 85 | 80 | ||
| 86 | fun clear() { | 81 | fun clear() { |
| 87 | game = null | 82 | game = null |
| 88 | shouldSave = false | 83 | shouldSave = false |
| 89 | } | 84 | } |
| 90 | |||
| 91 | companion object { | ||
| 92 | const val KEY_SLIDER_TEXT_VALUE = "SliderTextValue" | ||
| 93 | const val KEY_SLIDER_PROGRESS = "SliderProgress" | ||
| 94 | const val KEY_ADAPTER_ITEM_CHANGED = "AdapterItemChanged" | ||
| 95 | } | ||
| 96 | } | 85 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt index 27ea725a5..531c2aaf0 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt | |||
| @@ -3,29 +3,25 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.model | 4 | package org.yuzu.yuzu_emu.model |
| 5 | 5 | ||
| 6 | import androidx.lifecycle.LiveData | ||
| 7 | import androidx.lifecycle.MutableLiveData | ||
| 8 | import androidx.lifecycle.ViewModel | 6 | import androidx.lifecycle.ViewModel |
| 9 | import androidx.lifecycle.viewModelScope | 7 | import androidx.lifecycle.viewModelScope |
| 10 | import kotlinx.coroutines.Dispatchers | 8 | import kotlinx.coroutines.Dispatchers |
| 9 | import kotlinx.coroutines.flow.MutableStateFlow | ||
| 10 | import kotlinx.coroutines.flow.StateFlow | ||
| 11 | import kotlinx.coroutines.launch | 11 | import kotlinx.coroutines.launch |
| 12 | 12 | ||
| 13 | class TaskViewModel : ViewModel() { | 13 | class TaskViewModel : ViewModel() { |
| 14 | private val _result = MutableLiveData<Any>() | 14 | val result: StateFlow<Any> get() = _result |
| 15 | val result: LiveData<Any> = _result | 15 | private val _result = MutableStateFlow(Any()) |
| 16 | 16 | ||
| 17 | private val _isComplete = MutableLiveData<Boolean>() | 17 | val isComplete: StateFlow<Boolean> get() = _isComplete |
| 18 | val isComplete: LiveData<Boolean> = _isComplete | 18 | private val _isComplete = MutableStateFlow(false) |
| 19 | 19 | ||
| 20 | private val _isRunning = MutableLiveData<Boolean>() | 20 | val isRunning: StateFlow<Boolean> get() = _isRunning |
| 21 | val isRunning: LiveData<Boolean> = _isRunning | 21 | private val _isRunning = MutableStateFlow(false) |
| 22 | 22 | ||
| 23 | lateinit var task: () -> Any | 23 | lateinit var task: () -> Any |
| 24 | 24 | ||
| 25 | init { | ||
| 26 | clear() | ||
| 27 | } | ||
| 28 | |||
| 29 | fun clear() { | 25 | fun clear() { |
| 30 | _result.value = Any() | 26 | _result.value = Any() |
| 31 | _isComplete.value = false | 27 | _isComplete.value = false |
| @@ -33,15 +29,16 @@ class TaskViewModel : ViewModel() { | |||
| 33 | } | 29 | } |
| 34 | 30 | ||
| 35 | fun runTask() { | 31 | fun runTask() { |
| 36 | if (_isRunning.value == true) { | 32 | if (isRunning.value) { |
| 37 | return | 33 | return |
| 38 | } | 34 | } |
| 39 | _isRunning.value = true | 35 | _isRunning.value = true |
| 40 | 36 | ||
| 41 | viewModelScope.launch(Dispatchers.IO) { | 37 | viewModelScope.launch(Dispatchers.IO) { |
| 42 | val res = task() | 38 | val res = task() |
| 43 | _result.postValue(res) | 39 | _result.value = res |
| 44 | _isComplete.postValue(true) | 40 | _isComplete.value = true |
| 41 | _isRunning.value = false | ||
| 45 | } | 42 | } |
| 46 | } | 43 | } |
| 47 | } | 44 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt index b0156dca5..35e365458 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.ui | 4 | package org.yuzu.yuzu_emu.ui |
| 5 | 5 | ||
| 6 | import android.annotation.SuppressLint | ||
| 6 | import android.os.Bundle | 7 | import android.os.Bundle |
| 7 | import android.view.LayoutInflater | 8 | import android.view.LayoutInflater |
| 8 | import android.view.View | 9 | import android.view.View |
| @@ -14,8 +15,12 @@ import androidx.core.view.WindowInsetsCompat | |||
| 14 | import androidx.core.view.updatePadding | 15 | import androidx.core.view.updatePadding |
| 15 | import androidx.fragment.app.Fragment | 16 | import androidx.fragment.app.Fragment |
| 16 | import androidx.fragment.app.activityViewModels | 17 | import androidx.fragment.app.activityViewModels |
| 18 | import androidx.lifecycle.Lifecycle | ||
| 19 | import androidx.lifecycle.lifecycleScope | ||
| 20 | import androidx.lifecycle.repeatOnLifecycle | ||
| 17 | import com.google.android.material.color.MaterialColors | 21 | import com.google.android.material.color.MaterialColors |
| 18 | import com.google.android.material.transition.MaterialFadeThrough | 22 | import com.google.android.material.transition.MaterialFadeThrough |
| 23 | import kotlinx.coroutines.launch | ||
| 19 | import org.yuzu.yuzu_emu.R | 24 | import org.yuzu.yuzu_emu.R |
| 20 | import org.yuzu.yuzu_emu.adapters.GameAdapter | 25 | import org.yuzu.yuzu_emu.adapters.GameAdapter |
| 21 | import org.yuzu.yuzu_emu.databinding.FragmentGamesBinding | 26 | import org.yuzu.yuzu_emu.databinding.FragmentGamesBinding |
| @@ -44,6 +49,8 @@ class GamesFragment : Fragment() { | |||
| 44 | return binding.root | 49 | return binding.root |
| 45 | } | 50 | } |
| 46 | 51 | ||
| 52 | // This is using the correct scope, lint is just acting up | ||
| 53 | @SuppressLint("UnsafeRepeatOnLifecycleDetector") | ||
| 47 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 54 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 48 | homeViewModel.setNavigationVisibility(visible = true, animated = false) | 55 | homeViewModel.setNavigationVisibility(visible = true, animated = false) |
| 49 | 56 | ||
| @@ -80,37 +87,48 @@ class GamesFragment : Fragment() { | |||
| 80 | if (_binding == null) { | 87 | if (_binding == null) { |
| 81 | return@post | 88 | return@post |
| 82 | } | 89 | } |
| 83 | binding.swipeRefresh.isRefreshing = gamesViewModel.isReloading.value!! | 90 | binding.swipeRefresh.isRefreshing = gamesViewModel.isReloading.value |
| 84 | } | 91 | } |
| 85 | } | 92 | } |
| 86 | 93 | ||
| 87 | gamesViewModel.apply { | 94 | viewLifecycleOwner.lifecycleScope.apply { |
| 88 | // Watch for when we get updates to any of our games lists | 95 | launch { |
| 89 | isReloading.observe(viewLifecycleOwner) { isReloading -> | 96 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 90 | binding.swipeRefresh.isRefreshing = isReloading | 97 | gamesViewModel.isReloading.collect { binding.swipeRefresh.isRefreshing = it } |
| 98 | } | ||
| 91 | } | 99 | } |
| 92 | games.observe(viewLifecycleOwner) { | 100 | launch { |
| 93 | (binding.gridGames.adapter as GameAdapter).submitList(it) | 101 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 94 | if (it.isEmpty()) { | 102 | gamesViewModel.games.collect { |
| 95 | binding.noticeText.visibility = View.VISIBLE | 103 | (binding.gridGames.adapter as GameAdapter).submitList(it) |
| 96 | } else { | 104 | if (it.isEmpty()) { |
| 97 | binding.noticeText.visibility = View.GONE | 105 | binding.noticeText.visibility = View.VISIBLE |
| 106 | } else { | ||
| 107 | binding.noticeText.visibility = View.GONE | ||
| 108 | } | ||
| 109 | } | ||
| 98 | } | 110 | } |
| 99 | } | 111 | } |
| 100 | shouldSwapData.observe(viewLifecycleOwner) { shouldSwapData -> | 112 | launch { |
| 101 | if (shouldSwapData) { | 113 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 102 | (binding.gridGames.adapter as GameAdapter).submitList( | 114 | gamesViewModel.shouldSwapData.collect { |
| 103 | gamesViewModel.games.value!! | 115 | if (it) { |
| 104 | ) | 116 | (binding.gridGames.adapter as GameAdapter).submitList( |
| 105 | gamesViewModel.setShouldSwapData(false) | 117 | gamesViewModel.games.value |
| 118 | ) | ||
| 119 | gamesViewModel.setShouldSwapData(false) | ||
| 120 | } | ||
| 121 | } | ||
| 106 | } | 122 | } |
| 107 | } | 123 | } |
| 108 | 124 | launch { | |
| 109 | // Check if the user reselected the games menu item and then scroll to top of the list | 125 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 110 | shouldScrollToTop.observe(viewLifecycleOwner) { shouldScroll -> | 126 | gamesViewModel.shouldScrollToTop.collect { |
| 111 | if (shouldScroll) { | 127 | if (it) { |
| 112 | scrollToTop() | 128 | scrollToTop() |
| 113 | gamesViewModel.setShouldScrollToTop(false) | 129 | gamesViewModel.setShouldScrollToTop(false) |
| 130 | } | ||
| 131 | } | ||
| 114 | } | 132 | } |
| 115 | } | 133 | } |
| 116 | } | 134 | } |
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 7d8e06ad8..b6b6c6c17 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 | |||
| @@ -19,7 +19,9 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen | |||
| 19 | import androidx.core.view.ViewCompat | 19 | import androidx.core.view.ViewCompat |
| 20 | import androidx.core.view.WindowCompat | 20 | import androidx.core.view.WindowCompat |
| 21 | import androidx.core.view.WindowInsetsCompat | 21 | import androidx.core.view.WindowInsetsCompat |
| 22 | import androidx.lifecycle.Lifecycle | ||
| 22 | import androidx.lifecycle.lifecycleScope | 23 | import androidx.lifecycle.lifecycleScope |
| 24 | import androidx.lifecycle.repeatOnLifecycle | ||
| 23 | import androidx.navigation.NavController | 25 | import androidx.navigation.NavController |
| 24 | import androidx.navigation.fragment.NavHostFragment | 26 | import androidx.navigation.fragment.NavHostFragment |
| 25 | import androidx.navigation.ui.setupWithNavController | 27 | import androidx.navigation.ui.setupWithNavController |
| @@ -40,7 +42,6 @@ import org.yuzu.yuzu_emu.activities.EmulationActivity | |||
| 40 | import org.yuzu.yuzu_emu.databinding.ActivityMainBinding | 42 | import org.yuzu.yuzu_emu.databinding.ActivityMainBinding |
| 41 | import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding | 43 | import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding |
| 42 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 44 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 43 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | ||
| 44 | import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment | 45 | import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment |
| 45 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment | 46 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment |
| 46 | import org.yuzu.yuzu_emu.model.GamesViewModel | 47 | import org.yuzu.yuzu_emu.model.GamesViewModel |
| @@ -107,7 +108,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 107 | R.id.homeSettingsFragment -> { | 108 | R.id.homeSettingsFragment -> { |
| 108 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( | 109 | val action = HomeNavigationDirections.actionGlobalSettingsActivity( |
| 109 | null, | 110 | null, |
| 110 | SettingsFile.FILE_NAME_CONFIG | 111 | Settings.MenuTag.SECTION_ROOT |
| 111 | ) | 112 | ) |
| 112 | navHostFragment.navController.navigate(action) | 113 | navHostFragment.navController.navigate(action) |
| 113 | } | 114 | } |
| @@ -115,16 +116,22 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | // Prevents navigation from being drawn for a short time on recreation if set to hidden | 118 | // Prevents navigation from being drawn for a short time on recreation if set to hidden |
| 118 | if (!homeViewModel.navigationVisible.value?.first!!) { | 119 | if (!homeViewModel.navigationVisible.value.first) { |
| 119 | binding.navigationView.visibility = View.INVISIBLE | 120 | binding.navigationView.visibility = View.INVISIBLE |
| 120 | binding.statusBarShade.visibility = View.INVISIBLE | 121 | binding.statusBarShade.visibility = View.INVISIBLE |
| 121 | } | 122 | } |
| 122 | 123 | ||
| 123 | homeViewModel.navigationVisible.observe(this) { | 124 | lifecycleScope.apply { |
| 124 | showNavigation(it.first, it.second) | 125 | launch { |
| 125 | } | 126 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 126 | homeViewModel.statusBarShadeVisible.observe(this) { visible -> | 127 | homeViewModel.navigationVisible.collect { showNavigation(it.first, it.second) } |
| 127 | showStatusBarShade(visible) | 128 | } |
| 129 | } | ||
| 130 | launch { | ||
| 131 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 132 | homeViewModel.statusBarShadeVisible.collect { showStatusBarShade(it) } | ||
| 133 | } | ||
| 134 | } | ||
| 128 | } | 135 | } |
| 129 | 136 | ||
| 130 | // Dismiss previous notifications (should not happen unless a crash occurred) | 137 | // Dismiss previous notifications (should not happen unless a crash occurred) |
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 2085430bf..2e0ce7a3d 100644 --- a/src/android/app/src/main/res/navigation/home_navigation.xml +++ b/src/android/app/src/main/res/navigation/home_navigation.xml | |||
| @@ -82,7 +82,7 @@ | |||
| 82 | app:nullable="true" /> | 82 | app:nullable="true" /> |
| 83 | <argument | 83 | <argument |
| 84 | android:name="menuTag" | 84 | android:name="menuTag" |
| 85 | app:argType="string" /> | 85 | app:argType="org.yuzu.yuzu_emu.features.settings.model.Settings$MenuTag" /> |
| 86 | </activity> | 86 | </activity> |
| 87 | 87 | ||
| 88 | <action | 88 | <action |
diff --git a/src/android/app/src/main/res/navigation/settings_navigation.xml b/src/android/app/src/main/res/navigation/settings_navigation.xml index 88e1b4587..1d87d36b3 100644 --- a/src/android/app/src/main/res/navigation/settings_navigation.xml +++ b/src/android/app/src/main/res/navigation/settings_navigation.xml | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | android:label="SettingsFragment"> | 10 | android:label="SettingsFragment"> |
| 11 | <argument | 11 | <argument |
| 12 | android:name="menuTag" | 12 | android:name="menuTag" |
| 13 | app:argType="string" /> | 13 | app:argType="org.yuzu.yuzu_emu.features.settings.model.Settings$MenuTag" /> |
| 14 | <argument | 14 | <argument |
| 15 | android:name="game" | 15 | android:name="game" |
| 16 | app:argType="org.yuzu.yuzu_emu.model.Game" | 16 | app:argType="org.yuzu.yuzu_emu.model.Game" |