feat: driver installation dialogs with string resources

This commit is contained in:
Producdevity 2025-07-25 18:38:02 +02:00
parent 6b65f95cfa
commit 0ea1870bbc
2 changed files with 33 additions and 26 deletions

View file

@ -14,6 +14,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.fragments.DriverFetcherFragment import org.yuzu.yuzu_emu.fragments.DriverFetcherFragment
import org.yuzu.yuzu_emu.fragments.DriverFetcherFragment.SortMode import org.yuzu.yuzu_emu.fragments.DriverFetcherFragment.SortMode
import org.yuzu.yuzu_emu.model.DriverViewModel import org.yuzu.yuzu_emu.model.DriverViewModel
@ -31,7 +32,7 @@ object DriverResolver {
DriverRepo("Mr. Purple Turnip", "MrPurple666/purple-turnip", 0), DriverRepo("Mr. Purple Turnip", "MrPurple666/purple-turnip", 0),
DriverRepo("GameHub Adreno 8xx", "crueter/GameHub-8Elite-Drivers", 1), DriverRepo("GameHub Adreno 8xx", "crueter/GameHub-8Elite-Drivers", 1),
DriverRepo("KIMCHI Turnip", "K11MCH1/AdrenoToolsDrivers", 2, true), DriverRepo("KIMCHI Turnip", "K11MCH1/AdrenoToolsDrivers", 2, true),
DriverRepo("Weab-Chan Freedreno", "Weab-chan/freedreno_turnip-CI", 3), DriverRepo("Weab-Chan Freedreno", "Weab-chan/freedreno_turnip-CI", 3)
) )
private data class DriverRepo( private data class DriverRepo(
@ -144,10 +145,10 @@ object DriverResolver {
// Try partial match // Try partial match
availableDrivers.find { (path, metadata) -> availableDrivers.find { (path, metadata) ->
path.contains(driverName, ignoreCase = true) || path.contains(driverName, ignoreCase = true) ||
metadata.name?.contains( metadata.name?.contains(
extractKeywords(driverName).first(), extractKeywords(driverName).first(),
ignoreCase = true ignoreCase = true
) == true ) == true
}?.let { return it } }?.let { return it }
return null return null
@ -188,7 +189,7 @@ object DriverResolver {
// Check if this repo is relevant based on driver name // Check if this repo is relevant based on driver name
val isRelevant = keywords.any { keyword -> val isRelevant = keywords.any { keyword ->
repo.name.contains(keyword, ignoreCase = true) || repo.name.contains(keyword, ignoreCase = true) ||
keyword.contains(repo.name.split(" ").first(), ignoreCase = true) keyword.contains(repo.name.split(" ").first(), ignoreCase = true)
} }
if (!isRelevant) continue if (!isRelevant) continue
@ -203,7 +204,9 @@ object DriverResolver {
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.error("[DriverResolver] Failed to fetch releases for ${repo.name}: ${e.message}") Log.error(
"[DriverResolver] Failed to fetch releases for ${repo.name}: ${e.message}"
)
} }
} }
@ -257,15 +260,12 @@ object DriverResolver {
return suspendCoroutine { continuation -> return suspendCoroutine { continuation ->
activity.runOnUiThread { activity.runOnUiThread {
MaterialAlertDialogBuilder(activity) MaterialAlertDialogBuilder(activity)
.setTitle("Missing GPU Driver") .setTitle(activity.getString(R.string.missing_gpu_driver_title))
.setMessage( .setMessage(activity.getString(R.string.missing_gpu_driver_message, driverName))
"The custom settings require the GPU driver '$driverName' which is not installed.\n\n" + .setPositiveButton(activity.getString(R.string.install)) { _, _ ->
"Would you like to download and install it automatically?"
)
.setPositiveButton("Install") { _, _ ->
continuation.resume(true) continuation.resume(true)
} }
.setNegativeButton("Cancel") { _, _ -> .setNegativeButton(activity.getString(R.string.cancel)) { _, _ ->
continuation.resume(false) continuation.resume(false)
} }
.setCancelable(false) .setCancelable(false)
@ -284,7 +284,11 @@ object DriverResolver {
): Boolean { ): Boolean {
return try { return try {
Log.info("[DriverResolver] Downloading driver: ${artifact.name}") Log.info("[DriverResolver] Downloading driver: ${artifact.name}")
Toast.makeText(activity, "Downloading driver...", Toast.LENGTH_SHORT).show() Toast.makeText(
activity,
activity.getString(R.string.downloading_driver),
Toast.LENGTH_SHORT
).show()
val cacheDir = val cacheDir =
activity.externalCacheDir ?: throw IOException("Cache directory not available") activity.externalCacheDir ?: throw IOException("Cache directory not available")
@ -328,7 +332,11 @@ object DriverResolver {
if (GpuDriverHelper.copyDriverToInternalStorage(file.toUri())) { if (GpuDriverHelper.copyDriverToInternalStorage(file.toUri())) {
driverViewModel.onDriverAdded(Pair(driverPath, driverData)) driverViewModel.onDriverAdded(Pair(driverPath, driverData))
Log.info("[DriverResolver] Successfully installed driver: ${driverData.name}") Log.info("[DriverResolver] Successfully installed driver: ${driverData.name}")
Toast.makeText(activity, "Driver installed", Toast.LENGTH_SHORT).show() Toast.makeText(
activity,
activity.getString(R.string.driver_installed),
Toast.LENGTH_SHORT
).show()
true true
} else { } else {
throw IOException("Failed to install driver") throw IOException("Failed to install driver")
@ -338,9 +346,11 @@ object DriverResolver {
Log.error("[DriverResolver] Failed to download/install driver: ${e.message}") Log.error("[DriverResolver] Failed to download/install driver: ${e.message}")
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
MaterialAlertDialogBuilder(activity) MaterialAlertDialogBuilder(activity)
.setTitle("Installation Failed") .setTitle(activity.getString(R.string.driver_installation_failed_title))
.setMessage("Failed to download and install the driver: ${e.message}") .setMessage(
.setPositiveButton("OK") { dialog, _ -> dialog.dismiss() } activity.getString(R.string.driver_installation_failed_message, e.message)
)
.setPositiveButton(activity.getString(R.string.ok)) { dialog, _ -> dialog.dismiss() }
.show() .show()
} }
false false
@ -353,12 +363,9 @@ object DriverResolver {
private fun showDriverNotFoundDialog(activity: FragmentActivity, driverName: String) { private fun showDriverNotFoundDialog(activity: FragmentActivity, driverName: String) {
activity.runOnUiThread { activity.runOnUiThread {
MaterialAlertDialogBuilder(activity) MaterialAlertDialogBuilder(activity)
.setTitle("Driver Not Available") .setTitle(activity.getString(R.string.driver_not_available_title))
.setMessage( .setMessage(activity.getString(R.string.driver_not_available_message, driverName))
"The required GPU driver '$driverName' is not available for automatic download.\n\n" + .setPositiveButton(activity.getString(R.string.ok)) { dialog, _ -> dialog.dismiss() }
"Please manually install the driver or launch the game with default settings."
)
.setPositiveButton("OK") { dialog, _ -> dialog.dismiss() }
.show() .show()
} }
} }

View file

@ -795,7 +795,7 @@
<!-- Driver strings --> <!-- Driver strings -->
<string name="missing_gpu_driver_title">GPU Driver Missing</string> <string name="missing_gpu_driver_title">GPU Driver Missing</string>
<string name="missing_gpu_driver_message">The selected custom driver is not installed. Would you like to download and install it now?</string> <string name="missing_gpu_driver_message">The selected custom driver \"%s\" is not installed. Would you like to download and install it now?</string>
<string name="downloading_driver">Downloading driver...</string> <string name="downloading_driver">Downloading driver...</string>
<string name="driver_installed">Driver installed successfully</string> <string name="driver_installed">Driver installed successfully</string>
<string name="driver_installation_failed_title">Driver Installation Failed</string> <string name="driver_installation_failed_title">Driver Installation Failed</string>