diff options
| author | 2023-08-31 13:32:48 -0400 | |
|---|---|---|
| committer | 2023-09-14 15:18:56 -0400 | |
| commit | 4a3cbf00216918a53b143f6bbfc4b22a49761770 (patch) | |
| tree | 6e75e7bd037fef538a054d07496f407d2d4a6997 | |
| parent | Merge pull request #11496 from liamwhite/ngc (diff) | |
| download | yuzu-4a3cbf00216918a53b143f6bbfc4b22a49761770.tar.gz yuzu-4a3cbf00216918a53b143f6bbfc4b22a49761770.tar.xz yuzu-4a3cbf00216918a53b143f6bbfc4b22a49761770.zip | |
android: Use StateFlow instead of LiveData
Diffstat (limited to '')
16 files changed, 367 insertions, 249 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/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..2a816183a 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 | |||
| @@ -13,11 +13,15 @@ import androidx.core.view.WindowInsetsCompat | |||
| 13 | import androidx.core.view.updatePadding | 13 | import androidx.core.view.updatePadding |
| 14 | import androidx.fragment.app.Fragment | 14 | import androidx.fragment.app.Fragment |
| 15 | import androidx.fragment.app.activityViewModels | 15 | import androidx.fragment.app.activityViewModels |
| 16 | import androidx.lifecycle.Lifecycle | ||
| 17 | import androidx.lifecycle.lifecycleScope | ||
| 18 | import androidx.lifecycle.repeatOnLifecycle | ||
| 16 | import androidx.navigation.findNavController | 19 | import androidx.navigation.findNavController |
| 17 | import androidx.navigation.fragment.navArgs | 20 | import androidx.navigation.fragment.navArgs |
| 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 |
| 24 | import kotlinx.coroutines.launch | ||
| 21 | import org.yuzu.yuzu_emu.R | 25 | import org.yuzu.yuzu_emu.R |
| 22 | import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding | 26 | import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding |
| 23 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 27 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile |
| @@ -51,6 +55,8 @@ class SettingsFragment : Fragment() { | |||
| 51 | return binding.root | 55 | return binding.root |
| 52 | } | 56 | } |
| 53 | 57 | ||
| 58 | // This is using the correct scope, lint is just acting up | ||
| 59 | @SuppressLint("UnsafeRepeatOnLifecycleDetector") | ||
| 54 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 60 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 55 | settingsAdapter = SettingsAdapter(this, requireContext()) | 61 | settingsAdapter = SettingsAdapter(this, requireContext()) |
| 56 | presenter = SettingsFragmentPresenter( | 62 | presenter = SettingsFragmentPresenter( |
| @@ -75,24 +81,27 @@ class SettingsFragment : Fragment() { | |||
| 75 | settingsViewModel.setShouldNavigateBack(true) | 81 | settingsViewModel.setShouldNavigateBack(true) |
| 76 | } | 82 | } |
| 77 | 83 | ||
| 78 | settingsViewModel.toolbarTitle.observe(viewLifecycleOwner) { | 84 | viewLifecycleOwner.lifecycleScope.apply { |
| 79 | if (it.isNotEmpty()) binding.toolbarSettingsLayout.title = it | 85 | launch { |
| 80 | } | 86 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 81 | 87 | settingsViewModel.shouldReloadSettingsList.collectLatest { | |
| 82 | settingsViewModel.shouldReloadSettingsList.observe(viewLifecycleOwner) { | 88 | if (it) { |
| 83 | if (it) { | 89 | settingsViewModel.setShouldReloadSettingsList(false) |
| 84 | settingsViewModel.setShouldReloadSettingsList(false) | 90 | presenter.loadSettingsList() |
| 85 | presenter.loadSettingsList() | 91 | } |
| 92 | } | ||
| 93 | } | ||
| 86 | } | 94 | } |
| 87 | } | 95 | launch { |
| 88 | 96 | settingsViewModel.isUsingSearch.collectLatest { | |
| 89 | settingsViewModel.isUsingSearch.observe(viewLifecycleOwner) { | 97 | if (it) { |
| 90 | if (it) { | 98 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true) |
| 91 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true) | 99 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) |
| 92 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) | 100 | } else { |
| 93 | } else { | 101 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) |
| 94 | reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) | 102 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) |
| 95 | exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) | 103 | } |
| 104 | } | ||
| 96 | } | 105 | } |
| 97 | } | 106 | } |
| 98 | 107 | ||
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..1addb2326 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 |
| @@ -129,6 +130,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 129 | return binding.root | 130 | return binding.root |
| 130 | } | 131 | } |
| 131 | 132 | ||
| 133 | // This is using the correct scope, lint is just acting up | ||
| 134 | @SuppressLint("UnsafeRepeatOnLifecycleDetector") | ||
| 132 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 135 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 133 | binding.surfaceEmulation.holder.addCallback(this) | 136 | binding.surfaceEmulation.holder.addCallback(this) |
| 134 | binding.showFpsText.setTextColor(Color.YELLOW) | 137 | binding.showFpsText.setTextColor(Color.YELLOW) |
| @@ -205,59 +208,80 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 205 | } | 208 | } |
| 206 | ) | 209 | ) |
| 207 | 210 | ||
| 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) | 211 | GameIconUtils.loadGameIcon(game, binding.loadingImage) |
| 217 | binding.loadingTitle.text = game.title | 212 | binding.loadingTitle.text = game.title |
| 218 | binding.loadingTitle.isSelected = true | 213 | binding.loadingTitle.isSelected = true |
| 219 | binding.loadingText.isSelected = true | 214 | binding.loadingText.isSelected = true |
| 220 | 215 | ||
| 221 | emulationViewModel.shaderProgress.observe(viewLifecycleOwner) { | 216 | viewLifecycleOwner.lifecycleScope.apply { |
| 222 | if (it > 0 && it != emulationViewModel.totalShaders.value!!) { | 217 | launch { |
| 223 | binding.loadingProgressIndicator.isIndeterminate = false | 218 | repeatOnLifecycle(Lifecycle.State.STARTED) { |
| 224 | 219 | WindowInfoTracker.getOrCreate(requireContext()) | |
| 225 | if (it < binding.loadingProgressIndicator.max) { | 220 | .windowLayoutInfo(requireActivity()) |
| 226 | binding.loadingProgressIndicator.progress = it | 221 | .collect { |
| 222 | updateFoldableLayout(requireActivity() as EmulationActivity, it) | ||
| 223 | } | ||
| 227 | } | 224 | } |
| 228 | } | 225 | } |
| 226 | launch { | ||
| 227 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 228 | emulationViewModel.shaderProgress.collectLatest { | ||
| 229 | if (it > 0 && it != emulationViewModel.totalShaders.value) { | ||
| 230 | binding.loadingProgressIndicator.isIndeterminate = false | ||
| 231 | |||
| 232 | if (it < binding.loadingProgressIndicator.max) { | ||
| 233 | binding.loadingProgressIndicator.progress = it | ||
| 234 | } | ||
| 235 | } | ||
| 229 | 236 | ||
| 230 | if (it == emulationViewModel.totalShaders.value!!) { | 237 | if (it == emulationViewModel.totalShaders.value) { |
| 231 | binding.loadingText.setText(R.string.loading) | 238 | binding.loadingText.setText(R.string.loading) |
| 232 | binding.loadingProgressIndicator.isIndeterminate = true | 239 | binding.loadingProgressIndicator.isIndeterminate = true |
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 233 | } | 243 | } |
| 234 | } | 244 | launch { |
| 235 | emulationViewModel.totalShaders.observe(viewLifecycleOwner) { | 245 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 236 | binding.loadingProgressIndicator.max = it | 246 | emulationViewModel.totalShaders.collectLatest { |
| 237 | } | 247 | binding.loadingProgressIndicator.max = it |
| 238 | emulationViewModel.shaderMessage.observe(viewLifecycleOwner) { | 248 | } |
| 239 | if (it.isNotEmpty()) { | 249 | } |
| 240 | binding.loadingText.text = it | ||
| 241 | } | 250 | } |
| 242 | } | 251 | launch { |
| 243 | 252 | repeatOnLifecycle(Lifecycle.State.CREATED) { | |
| 244 | emulationViewModel.emulationStarted.observe(viewLifecycleOwner) { started -> | 253 | emulationViewModel.shaderMessage.collectLatest { |
| 245 | if (started) { | 254 | if (it.isNotEmpty()) { |
| 246 | binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) | 255 | binding.loadingText.text = it |
| 247 | ViewUtils.showView(binding.surfaceInputOverlay) | 256 | } |
| 248 | ViewUtils.hideView(binding.loadingIndicator) | 257 | } |
| 249 | 258 | } | |
| 250 | // Setup overlay | ||
| 251 | updateShowFpsOverlay() | ||
| 252 | } | 259 | } |
| 253 | } | 260 | launch { |
| 261 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 262 | emulationViewModel.emulationStarted.collectLatest { | ||
| 263 | if (it) { | ||
| 264 | binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) | ||
| 265 | ViewUtils.showView(binding.surfaceInputOverlay) | ||
| 266 | ViewUtils.hideView(binding.loadingIndicator) | ||
| 254 | 267 | ||
| 255 | emulationViewModel.isEmulationStopping.observe(viewLifecycleOwner) { | 268 | // Setup overlay |
| 256 | if (it) { | 269 | updateShowFpsOverlay() |
| 257 | binding.loadingText.setText(R.string.shutting_down) | 270 | } |
| 258 | ViewUtils.showView(binding.loadingIndicator) | 271 | } |
| 259 | ViewUtils.hideView(binding.inputContainer) | 272 | } |
| 260 | ViewUtils.hideView(binding.showFpsText) | 273 | } |
| 274 | launch { | ||
| 275 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 276 | emulationViewModel.isEmulationStopping.collectLatest { | ||
| 277 | if (it) { | ||
| 278 | binding.loadingText.setText(R.string.shutting_down) | ||
| 279 | ViewUtils.showView(binding.loadingIndicator) | ||
| 280 | ViewUtils.hideView(binding.inputContainer) | ||
| 281 | ViewUtils.hideView(binding.showFpsText) | ||
| 282 | } | ||
| 283 | } | ||
| 284 | } | ||
| 261 | } | 285 | } |
| 262 | } | 286 | } |
| 263 | } | 287 | } |
| @@ -274,9 +298,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 274 | } | 298 | } |
| 275 | } | 299 | } |
| 276 | } else { | 300 | } else { |
| 277 | if (EmulationMenuSettings.showOverlay && | 301 | if (EmulationMenuSettings.showOverlay && emulationViewModel.emulationStarted.value) { |
| 278 | emulationViewModel.emulationStarted.value == true | ||
| 279 | ) { | ||
| 280 | binding.surfaceInputOverlay.post { | 302 | binding.surfaceInputOverlay.post { |
| 281 | binding.surfaceInputOverlay.visibility = View.VISIBLE | 303 | binding.surfaceInputOverlay.visibility = View.VISIBLE |
| 282 | } | 304 | } |
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..1ee833cf6 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 |
| @@ -115,16 +117,22 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 115 | } | 117 | } |
| 116 | 118 | ||
| 117 | // Prevents navigation from being drawn for a short time on recreation if set to hidden | 119 | // Prevents navigation from being drawn for a short time on recreation if set to hidden |
| 118 | if (!homeViewModel.navigationVisible.value?.first!!) { | 120 | if (!homeViewModel.navigationVisible.value.first) { |
| 119 | binding.navigationView.visibility = View.INVISIBLE | 121 | binding.navigationView.visibility = View.INVISIBLE |
| 120 | binding.statusBarShade.visibility = View.INVISIBLE | 122 | binding.statusBarShade.visibility = View.INVISIBLE |
| 121 | } | 123 | } |
| 122 | 124 | ||
| 123 | homeViewModel.navigationVisible.observe(this) { | 125 | lifecycleScope.apply { |
| 124 | showNavigation(it.first, it.second) | 126 | launch { |
| 125 | } | 127 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 126 | homeViewModel.statusBarShadeVisible.observe(this) { visible -> | 128 | homeViewModel.navigationVisible.collect { showNavigation(it.first, it.second) } |
| 127 | showStatusBarShade(visible) | 129 | } |
| 130 | } | ||
| 131 | launch { | ||
| 132 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 133 | homeViewModel.statusBarShadeVisible.collect { showStatusBarShade(it) } | ||
| 134 | } | ||
| 135 | } | ||
| 128 | } | 136 | } |
| 129 | 137 | ||
| 130 | // Dismiss previous notifications (should not happen unless a crash occurred) | 138 | // Dismiss previous notifications (should not happen unless a crash occurred) |