diff options
4 files changed, 151 insertions, 59 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/PermissionDeniedDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/PermissionDeniedDialogFragment.kt new file mode 100644 index 000000000..3478b9250 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/PermissionDeniedDialogFragment.kt @@ -0,0 +1,38 @@ +// 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 android.provider.Settings +import androidx.fragment.app.DialogFragment +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import org.yuzu.yuzu_emu.R + +class PermissionDeniedDialogFragment : DialogFragment() { + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + return MaterialAlertDialogBuilder(requireContext()) + .setPositiveButton(R.string.home_settings) { _: DialogInterface?, _: Int -> + openSettings() + } + .setNegativeButton(android.R.string.cancel, null) + .setTitle(R.string.permission_denied) + .setMessage(R.string.permission_denied_description) + .show() + } + + private fun openSettings() { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + val uri = Uri.fromParts("package", requireActivity().packageName, null) + intent.data = uri + startActivity(intent) + } + + companion object { + const val TAG = "PermissionDeniedDialogFragment" + } +} 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 153622072..258773380 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 @@ -3,6 +3,7 @@ package org.yuzu.yuzu_emu.fragments +import android.Manifest import android.content.Intent import android.os.Build import android.os.Bundle @@ -11,7 +12,9 @@ import android.view.View import android.view.ViewGroup import androidx.activity.OnBackPressedCallback import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat @@ -65,10 +68,6 @@ class SetupFragment : Fragment() { } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - pushNotificationPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS) - } - mainActivity = requireActivity() as MainActivity homeViewModel.setNavigationVisibility(visible = false, animated = false) @@ -88,60 +87,93 @@ class SetupFragment : Fragment() { requireActivity().window.navigationBarColor = ContextCompat.getColor(requireContext(), android.R.color.transparent) - val pages = listOf( - SetupPage( - R.drawable.ic_yuzu_title, - R.string.welcome, - R.string.welcome_description, - 0, - true, - 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("*/*")) }, - true, - R.string.install_prod_keys_warning, - R.string.install_prod_keys_warning_description, - R.string.install_prod_keys_warning_help, - { File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() } - ), - 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) }, - true, - R.string.add_games_warning, - R.string.add_games_warning_description, - R.string.add_games_warning_help, - { - val preferences = - PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) - preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty() - } - ), - SetupPage( - R.drawable.ic_check, - R.string.done, - R.string.done_description, - R.drawable.ic_arrow_forward, - false, - R.string.text_continue, - { finishSetup() }, - false + val pages = mutableListOf<SetupPage>() + pages.apply { + add( + SetupPage( + R.drawable.ic_yuzu_title, + R.string.welcome, + R.string.welcome_description, + 0, + true, + R.string.get_started, + { pageForward() }, + false + ) + ) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + add( + SetupPage( + R.drawable.ic_notification, + R.string.notifications, + R.string.notifications_description, + 0, + false, + R.string.give_permission, + { permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) }, + true, + R.string.notification_warning, + R.string.notification_warning_description, + 0, + { + NotificationManagerCompat.from(requireContext()) + .areNotificationsEnabled() + } + ) + ) + } + + add( + 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("*/*")) }, + true, + R.string.install_prod_keys_warning, + R.string.install_prod_keys_warning_description, + R.string.install_prod_keys_warning_help, + { File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() } + ) ) - ) + add( + 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) }, + true, + R.string.add_games_warning, + R.string.add_games_warning_description, + R.string.add_games_warning_help, + { + val preferences = + PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) + preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty() + } + ) + ) + add( + SetupPage( + R.drawable.ic_check, + R.string.done, + R.string.done_description, + R.drawable.ic_arrow_forward, + false, + R.string.text_continue, + { finishSetup() }, + false + ) + ) + } + binding.viewPager2.apply { adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages) offscreenPageLimit = 2 @@ -225,9 +257,15 @@ class SetupFragment : Fragment() { _binding = null } - private val pushNotificationPermissionLauncher = + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + private val permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { - // TODO: Show proper notification request reason and confirmation + if (!it && !shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) { + PermissionDeniedDialogFragment().show( + childFragmentManager, + PermissionDeniedDialogFragment.TAG + ) + } } private fun finishSetup() { diff --git a/src/android/app/src/main/res/drawable/ic_notification.xml b/src/android/app/src/main/res/drawable/ic_notification.xml new file mode 100644 index 000000000..b413f7585 --- /dev/null +++ b/src/android/app/src/main/res/drawable/ic_notification.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="?attr/colorOnSurface" + android:pathData="M7.58,4.08L6.15,2.65C3.75,4.48 2.17,7.3 2.03,10.5h2c0.15,-2.65 1.51,-4.97 3.55,-6.42zM19.97,10.5h2c-0.15,-3.2 -1.73,-6.02 -4.12,-7.85l-1.42,1.43c2.02,1.45 3.39,3.77 3.54,6.42zM18,11c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2v-5zM12,22c0.14,0 0.27,-0.01 0.4,-0.04 0.65,-0.14 1.18,-0.58 1.44,-1.18 0.1,-0.24 0.15,-0.5 0.15,-0.78h-4c0.01,1.1 0.9,2 2.01,2z" /> +</vector> diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 09b95848f..dd1137b69 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -48,6 +48,13 @@ <string name="install_prod_keys_warning">Skip adding keys?</string> <string name="install_prod_keys_warning_description">Valid keys are required to emulate retail games. Only homebrew apps will function if you continue.</string> <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> + <string name="notifications">Notifications</string> + <string name="notifications_description">Grant the notification permission with the button below.</string> + <string name="give_permission">Grant permission</string> + <string name="notification_warning">Skip granting the notification permission?</string> + <string name="notification_warning_description">yuzu won\'t be able to notify you of important information.</string> + <string name="permission_denied">Permission denied</string> + <string name="permission_denied_description">You denied this permission too many times and now you have to manually grant it in system settings.</string> <string name="about">About</string> <string name="about_description">Build version, credits, and more</string> <string name="warning_help">Help</string> |