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 7c8a37855e..57bef553a2 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
@@ -14,7 +14,6 @@ import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
-import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
@@ -38,9 +37,12 @@ class SetupFragment : Fragment() {
private lateinit var mainActivity: MainActivity
+ private lateinit var hasBeenWarned: BooleanArray
+
companion object {
const val KEY_NEXT_VISIBILITY = "NextButtonVisibility"
const val KEY_BACK_VISIBILITY = "BackButtonVisibility"
+ const val KEY_HAS_BEEN_WARNED = "HasBeenWarned"
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -84,36 +86,51 @@ class SetupFragment : Fragment() {
R.string.welcome_description,
0,
true,
- R.string.get_started
- ) { pageForward() },
+ R.string.get_started,
+ { pageForward() },
+ false
+ ),
SetupPage(
R.drawable.ic_key,
R.string.keys,
R.string.keys_description,
R.drawable.ic_add,
true,
- R.string.select_keys
- ) { mainActivity.getProdKey.launch(arrayOf("*/*")) },
+ R.string.select_keys,
+ { mainActivity.getProdKey.launch(arrayOf("*/*")) },
+ true,
+ R.string.install_prod_keys_warning,
+ R.string.install_prod_keys_warning_description,
+ R.string.install_prod_keys_warning_help
+ ),
SetupPage(
R.drawable.ic_controller,
R.string.games,
R.string.games_description,
R.drawable.ic_add,
true,
- R.string.add_games
- ) { mainActivity.getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data) },
+ R.string.add_games,
+ { mainActivity.getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data) },
+ true,
+ R.string.add_games_warning,
+ R.string.add_games_warning_description,
+ 0
+ ),
SetupPage(
R.drawable.ic_check,
R.string.done,
R.string.done_description,
R.drawable.ic_arrow_forward,
false,
- R.string.text_continue
- ) { finishSetup() }
+ R.string.text_continue,
+ { finishSetup() },
+ false
+ )
)
binding.viewPager2.apply {
adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages)
offscreenPageLimit = 2
+ isUserInputEnabled = false
}
binding.viewPager2.registerOnPageChangeCallback(object : OnPageChangeCallback() {
@@ -138,12 +155,26 @@ class SetupFragment : Fragment() {
}
})
- binding.buttonNext.setOnClickListener { pageForward() }
+ binding.buttonNext.setOnClickListener {
+ val index = binding.viewPager2.currentItem
+ val currentPage = pages[index]
+ if (currentPage.hasWarning && !hasBeenWarned[index]) {
+ SetupWarningDialogFragment.newInstance(
+ currentPage.warningTitleId,
+ currentPage.warningDescriptionId,
+ currentPage.warningHelpLinkId,
+ index
+ ).show(childFragmentManager, SetupWarningDialogFragment.TAG)
+ } else {
+ pageForward()
+ }
+ }
binding.buttonBack.setOnClickListener { pageBackward() }
if (savedInstanceState != null) {
val nextIsVisible = savedInstanceState.getBoolean(KEY_NEXT_VISIBILITY)
val backIsVisible = savedInstanceState.getBoolean(KEY_BACK_VISIBILITY)
+ hasBeenWarned = savedInstanceState.getBooleanArray(KEY_HAS_BEEN_WARNED)!!
if (nextIsVisible) {
binding.buttonNext.visibility = View.VISIBLE
@@ -151,6 +182,8 @@ class SetupFragment : Fragment() {
if (backIsVisible) {
binding.buttonBack.visibility = View.VISIBLE
}
+ } else {
+ hasBeenWarned = BooleanArray(pages.size)
}
setInsets()
@@ -160,6 +193,7 @@ class SetupFragment : Fragment() {
super.onSaveInstanceState(outState)
outState.putBoolean(KEY_NEXT_VISIBILITY, binding.buttonNext.isVisible)
outState.putBoolean(KEY_BACK_VISIBILITY, binding.buttonBack.isVisible)
+ outState.putBooleanArray(KEY_HAS_BEEN_WARNED, hasBeenWarned)
}
override fun onDestroyView() {
@@ -201,14 +235,18 @@ class SetupFragment : Fragment() {
}
}
- private fun pageForward() {
+ fun pageForward() {
binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1
}
- private fun pageBackward() {
+ fun pageBackward() {
binding.viewPager2.currentItem = binding.viewPager2.currentItem - 1
}
+ fun setPageWarned(page: Int) {
+ hasBeenWarned[page] = true
+ }
+
private fun setInsets() =
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupWarningDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupWarningDialogFragment.kt
new file mode 100644
index 0000000000..b2c1d54af3
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupWarningDialogFragment.kt
@@ -0,0 +1,86 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.fragments
+
+import android.app.Dialog
+import android.content.DialogInterface
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import org.yuzu.yuzu_emu.R
+
+class SetupWarningDialogFragment : DialogFragment() {
+ private var titleId: Int = 0
+ private var descriptionId: Int = 0
+ private var helpLinkId: Int = 0
+ private var page: Int = 0
+
+ private lateinit var setupFragment: SetupFragment
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ titleId = requireArguments().getInt(TITLE)
+ descriptionId = requireArguments().getInt(DESCRIPTION)
+ helpLinkId = requireArguments().getInt(HELP_LINK)
+ page = requireArguments().getInt(PAGE)
+
+ setupFragment = requireParentFragment() as SetupFragment
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val builder = MaterialAlertDialogBuilder(requireContext())
+ .setPositiveButton(R.string.warning_skip) { _: DialogInterface?, _: Int ->
+ setupFragment.pageForward()
+ setupFragment.setPageWarned(page)
+ }
+ .setNegativeButton(R.string.warning_cancel, null)
+
+ if (titleId != 0) {
+ builder.setTitle(titleId)
+ } else {
+ builder.setTitle("")
+ }
+ if (descriptionId != 0) {
+ builder.setMessage(descriptionId)
+ }
+ if (helpLinkId != 0) {
+ builder.setNeutralButton(R.string.warning_help) { _: DialogInterface?, _: Int ->
+ val helpLink = resources.getString(R.string.install_prod_keys_warning_help)
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(helpLink))
+ startActivity(intent)
+ }
+ }
+
+ return builder.show()
+ }
+
+ companion object {
+ const val TAG = "SetupWarningDialogFragment"
+
+ private const val TITLE = "Title"
+ private const val DESCRIPTION = "Description"
+ private const val HELP_LINK = "HelpLink"
+ private const val PAGE = "Page"
+
+ fun newInstance(
+ titleId: Int,
+ descriptionId: Int,
+ helpLinkId: Int,
+ page: Int
+ ): SetupWarningDialogFragment {
+ val dialog = SetupWarningDialogFragment()
+ val bundle = Bundle()
+ bundle.apply {
+ putInt(TITLE, titleId)
+ putInt(DESCRIPTION, descriptionId)
+ putInt(HELP_LINK, helpLinkId)
+ putInt(PAGE, page)
+ }
+ dialog.arguments = bundle
+ return dialog
+ }
+ }
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SetupPage.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SetupPage.kt
index a8a9345526..abe572a020 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SetupPage.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SetupPage.kt
@@ -10,5 +10,9 @@ data class SetupPage(
val buttonIconId: Int,
val leftAlignedIcon: Boolean,
val buttonTextId: Int,
- val buttonAction: () -> Unit
+ val buttonAction: () -> Unit,
+ val hasWarning: Boolean,
+ val warningTitleId: Int = 0,
+ val warningDescriptionId: Int = 0,
+ val warningHelpLinkId: Int = 0
)
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index b0d766e071..6448a8d3f7 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -29,10 +29,18 @@
Settings
Add Games
Select your games folder
+ Skip selecting games folder?
+ Games won\'t be displayed in the Games list if a folder isn\'t selected.
Search Games
Games directory selected
Install Prod.keys
Required to decrypt retail games
+ Skip adding keys?
+ Valid keys are required to emulate retail games. Only homebrew apps will function if you continue.
+ https://yuzu-emu.org/help/quickstart/#guide-introduction
+ Help
+ Skip
+ Cancel
Install Amiibo Keys
Required to use Amiibo in game
Invalid keys file selected