From 2aea7f9584b95d1a8c8a25411baf15c86ba7a1f7 Mon Sep 17 00:00:00 2001 From: xbzk Date: Fri, 13 Mar 2026 19:46:35 +0100 Subject: [PATCH] [android,settings] addons: fix crash when launching Install addons from per game addons menu (#3727) to fix navigation issues (PR3699), i've bounded all orphaned fragments to SettingsSubscreenActivity. (IIRC that were tested, whatever) Somehow the launching from per-game settings (where addons fragment is bounded to MainActivity got broken). This PR just made ContentTypeSelectionDialogFragment self-sufficient so it lives under both MainActivity and SettingsSubscreenActivity. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3727 Reviewed-by: MaranBr Reviewed-by: CamilleLaVey Co-authored-by: xbzk Co-committed-by: xbzk --- .../ContentTypeSelectionDialogFragment.kt | 68 +++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ContentTypeSelectionDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ContentTypeSelectionDialogFragment.kt index c1d8b9ea5f..880c2ff3bf 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ContentTypeSelectionDialogFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ContentTypeSelectionDialogFragment.kt @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -5,15 +8,18 @@ package org.yuzu.yuzu_emu.fragments import android.app.Dialog import android.content.DialogInterface +import android.net.Uri import android.os.Bundle +import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import androidx.preference.PreferenceManager import com.google.android.material.dialog.MaterialAlertDialogBuilder +import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.model.AddonViewModel -import org.yuzu.yuzu_emu.ui.main.MainActivity +import org.yuzu.yuzu_emu.utils.InstallableActions class ContentTypeSelectionDialogFragment : DialogFragment() { private val addonViewModel: AddonViewModel by activityViewModels() @@ -23,6 +29,52 @@ class ContentTypeSelectionDialogFragment : DialogFragment() { private var selectedItem = 0 + private val installGameUpdateLauncher = + registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { documents -> + if (documents.isEmpty()) { + return@registerForActivityResult + } + + val game = addonViewModel.game + if (game == null) { + installContent(documents) + return@registerForActivityResult + } + + ProgressDialogFragment.newInstance( + requireActivity(), + R.string.verifying_content, + false + ) { _, _ -> + var updatesMatchProgram = true + for (document in documents) { + val valid = NativeLibrary.doesUpdateMatchProgram( + game.programId, + document.toString() + ) + if (!valid) { + updatesMatchProgram = false + break + } + } + + requireActivity().runOnUiThread { + if (updatesMatchProgram) { + installContent(documents) + } else { + MessageDialogFragment.newInstance( + requireActivity(), + titleId = R.string.content_install_notice, + descriptionId = R.string.content_install_notice_description, + positiveAction = { installContent(documents) }, + negativeAction = {} + ).show(parentFragmentManager, MessageDialogFragment.TAG) + } + } + return@newInstance Any() + }.show(parentFragmentManager, ProgressDialogFragment.TAG) + } + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val launchOptions = arrayOf(getString(R.string.updates_and_dlc), getString(R.string.mods_and_cheats)) @@ -31,12 +83,11 @@ class ContentTypeSelectionDialogFragment : DialogFragment() { selectedItem = savedInstanceState.getInt(SELECTED_ITEM) } - val mainActivity = requireActivity() as MainActivity return MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.select_content_type) .setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int -> when (selectedItem) { - 0 -> mainActivity.installGameUpdate.launch(arrayOf("*/*")) + 0 -> installGameUpdateLauncher.launch(arrayOf("*/*")) else -> { if (!preferences.getBoolean(MOD_NOTICE_SEEN, false)) { preferences.edit().putBoolean(MOD_NOTICE_SEEN, true).apply() @@ -47,7 +98,7 @@ class ContentTypeSelectionDialogFragment : DialogFragment() { } } } - .setSingleChoiceItems(launchOptions, 0) { _: DialogInterface, i: Int -> + .setSingleChoiceItems(launchOptions, selectedItem) { _: DialogInterface, i: Int -> selectedItem = i } .setNegativeButton(android.R.string.cancel, null) @@ -65,4 +116,13 @@ class ContentTypeSelectionDialogFragment : DialogFragment() { private const val SELECTED_ITEM = "SelectedItem" private const val MOD_NOTICE_SEEN = "ModNoticeSeen" } + + private fun installContent(documents: List) { + InstallableActions.installContent( + activity = requireActivity(), + fragmentManager = parentFragmentManager, + addonViewModel = addonViewModel, + documents = documents + ) + } }