diff options
3 files changed, 154 insertions, 40 deletions
| diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/LongMessageDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/LongMessageDialogFragment.kt new file mode 100644 index 000000000..b29b627e9 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/LongMessageDialogFragment.kt @@ -0,0 +1,62 @@ +// 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.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 LongMessageDialogFragment : DialogFragment() { +    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { +        val titleId = requireArguments().getInt(TITLE) +        val description = requireArguments().getString(DESCRIPTION) +        val helpLinkId = requireArguments().getInt(HELP_LINK) + +        val dialog = MaterialAlertDialogBuilder(requireContext()) +            .setPositiveButton(R.string.close, null) +            .setTitle(titleId) +            .setMessage(description) + +        if (helpLinkId != 0) { +            dialog.setNeutralButton(R.string.learn_more) { _, _ -> +                openLink(getString(helpLinkId)) +            } +        } + +        return dialog.show() +    } + +    private fun openLink(link: String) { +        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(link)) +        startActivity(intent) +    } + +    companion object { +        const val TAG = "LongMessageDialogFragment" + +        private const val TITLE = "Title" +        private const val DESCRIPTION = "Description" +        private const val HELP_LINK = "Link" + +        fun newInstance( +            titleId: Int, +            description: String, +            helpLinkId: Int = 0 +        ): LongMessageDialogFragment { +            val dialog = LongMessageDialogFragment() +            val bundle = Bundle() +            bundle.apply { +                putInt(TITLE, titleId) +                putString(DESCRIPTION, description) +                putInt(HELP_LINK, helpLinkId) +            } +            dialog.arguments = bundle +            return dialog +        } +    } +} 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 cc1d87f1b..3086cfad3 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 @@ -4,6 +4,7 @@  package org.yuzu.yuzu_emu.ui.main  import android.content.Intent +import android.net.Uri  import android.os.Bundle  import android.view.View  import android.view.ViewGroup.MarginLayoutParams @@ -42,6 +43,7 @@ import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel  import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity  import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile  import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment +import org.yuzu.yuzu_emu.fragments.LongMessageDialogFragment  import org.yuzu.yuzu_emu.fragments.MessageDialogFragment  import org.yuzu.yuzu_emu.model.GamesViewModel  import org.yuzu.yuzu_emu.model.HomeViewModel @@ -481,62 +483,110 @@ class MainActivity : AppCompatActivity(), ThemeProvider {              }          } -    val installGameUpdate = -        registerForActivityResult(ActivityResultContracts.OpenDocument()) { -            if (it == null) { -                return@registerForActivityResult -            } - +    val installGameUpdate = registerForActivityResult( +        ActivityResultContracts.OpenMultipleDocuments() +    ) { documents: List<Uri> -> +        if (documents.isNotEmpty()) {              IndeterminateProgressDialogFragment.newInstance(                  this@MainActivity,                  R.string.install_game_content              ) { -                val result = NativeLibrary.installFileToNand(it.toString()) +                var installSuccess = 0 +                var installOverwrite = 0 +                var errorBaseGame = 0 +                var errorExtension = 0 +                var errorOther = 0 +                var errorTotal = 0                  lifecycleScope.launch { -                    withContext(Dispatchers.Main) { -                        when (result) { +                    documents.forEach { +                        when (NativeLibrary.installFileToNand(it.toString())) {                              NativeLibrary.InstallFileToNandResult.Success -> { -                                Toast.makeText( -                                    applicationContext, -                                    R.string.install_game_content_success, -                                    Toast.LENGTH_SHORT -                                ).show() +                                installSuccess += 1                              }                              NativeLibrary.InstallFileToNandResult.SuccessFileOverwritten -> { -                                Toast.makeText( -                                    applicationContext, -                                    R.string.install_game_content_success_overwrite, -                                    Toast.LENGTH_SHORT -                                ).show() +                                installOverwrite += 1                              }                              NativeLibrary.InstallFileToNandResult.ErrorBaseGame -> { -                                MessageDialogFragment.newInstance( -                                    R.string.install_game_content_failure, -                                    R.string.install_game_content_failure_base -                                ).show(supportFragmentManager, MessageDialogFragment.TAG) +                                errorBaseGame += 1                              }                              NativeLibrary.InstallFileToNandResult.ErrorFilenameExtension -> { -                                MessageDialogFragment.newInstance( -                                    R.string.install_game_content_failure, -                                    R.string.install_game_content_failure_file_extension, -                                    R.string.install_game_content_help_link -                                ).show(supportFragmentManager, MessageDialogFragment.TAG) +                                errorExtension += 1                              }                              else -> { -                                MessageDialogFragment.newInstance( -                                    R.string.install_game_content_failure, -                                    R.string.install_game_content_failure_description, -                                    R.string.install_game_content_help_link -                                ).show(supportFragmentManager, MessageDialogFragment.TAG) +                                errorOther += 1                              }                          }                      } +                    withContext(Dispatchers.Main) { +                        val separator = System.getProperty("line.separator") ?: "\n" +                        val installResult = StringBuilder() +                        if (installSuccess > 0) { +                            installResult.append( +                                getString( +                                    R.string.install_game_content_success_install, +                                    installSuccess +                                ) +                            ) +                            installResult.append(separator) +                        } +                        if (installOverwrite > 0) { +                            installResult.append( +                                getString( +                                    R.string.install_game_content_success_overwrite, +                                    installOverwrite +                                ) +                            ) +                            installResult.append(separator) +                        } +                        errorTotal = errorBaseGame + errorExtension + errorOther +                        if (errorTotal > 0) { +                            installResult.append(separator) +                            installResult.append( +                                getString( +                                    R.string.install_game_content_failed_count, +                                    errorTotal +                                ) +                            ) +                            installResult.append(separator) +                            if (errorBaseGame > 0) { +                                installResult.append(separator) +                                installResult.append( +                                    getString(R.string.install_game_content_failure_base) +                                ) +                                installResult.append(separator) +                            } +                            if (errorExtension > 0) { +                                installResult.append(separator) +                                installResult.append( +                                    getString(R.string.install_game_content_failure_file_extension) +                                ) +                                installResult.append(separator) +                            } +                            if (errorOther > 0) { +                                installResult.append( +                                    getString(R.string.install_game_content_failure_description) +                                ) +                                installResult.append(separator) +                            } +                            LongMessageDialogFragment.newInstance( +                                R.string.install_game_content_failure, +                                installResult.toString().trim(), +                                R.string.install_game_content_help_link +                            ).show(supportFragmentManager, LongMessageDialogFragment.TAG) +                        } else { +                            LongMessageDialogFragment.newInstance( +                                R.string.install_game_content_success, +                                installResult.toString().trim() +                            ).show(supportFragmentManager, LongMessageDialogFragment.TAG) +                        } +                    }                  } -                return@newInstance result +                return@newInstance installSuccess + installOverwrite + errorTotal              }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)          } +    }  } diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 85fc682f2..21805d274 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -104,12 +104,14 @@      <string name="share_log_missing">No log file found</string>      <string name="install_game_content">Install game content</string>      <string name="install_game_content_description">Install game updates or DLC</string> -    <string name="install_game_content_failure">Error installing file to NAND</string> -    <string name="install_game_content_failure_description">Game content installation failed. Please ensure content is valid and that the prod.keys file is installed.</string> -    <string name="install_game_content_failure_base">Installation of base games isn\'t permitted in order to avoid possible conflicts. Please select an update or DLC instead.</string> -    <string name="install_game_content_failure_file_extension">The selected file type is not supported. Only NSP and XCI content is supported for this action. Please verify the game content is valid.</string> -    <string name="install_game_content_success">Game content installed successfully</string> -    <string name="install_game_content_success_overwrite">Game content was overwritten successfully</string> +    <string name="install_game_content_failure">Error installing file(s) to NAND</string> +    <string name="install_game_content_failure_description">Please ensure content(s) are valid and that the prod.keys file is installed.</string> +    <string name="install_game_content_failure_base">Installation of base games isn\'t permitted in order to avoid possible conflicts.</string> +    <string name="install_game_content_failure_file_extension">Only NSP and XCI content is supported. Please verify the game content(s) are valid.</string> +    <string name="install_game_content_failed_count">%1$d installation error(s)</string> +    <string name="install_game_content_success">Game content(s) installed successfully</string> +    <string name="install_game_content_success_install">%1$d installed successfully</string> +    <string name="install_game_content_success_overwrite">%1$d overwritten successfully</string>      <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>      <!-- About screen strings --> | 
