From 72247a2324ffe6a37596820e8e4d817076406d0c Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Fri, 28 Apr 2023 18:06:01 -0400 Subject: [PATCH] android: Add warnings to setup screens --- .../yuzu/yuzu_emu/fragments/SetupFragment.kt | 62 ++++++++++--- .../fragments/SetupWarningDialogFragment.kt | 86 +++++++++++++++++++ .../java/org/yuzu/yuzu_emu/model/SetupPage.kt | 6 +- .../app/src/main/res/values/strings.xml | 8 ++ 4 files changed, 149 insertions(+), 13 deletions(-) create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupWarningDialogFragment.kt 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 7c8a37855..57bef553a 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 000000000..b2c1d54af --- /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 a8a934552..abe572a02 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 b0d766e07..6448a8d3f 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