Fix graphic packs download error

This commit is contained in:
SSimco
2025-08-16 17:27:42 +03:00
parent f209413051
commit 58d1625672
5 changed files with 60 additions and 30 deletions
-1
View File
@@ -231,7 +231,6 @@ dependencies {
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.compose.material3)
testImplementation(libs.junit)
testImplementation(libs.kotlin.reflect)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
@@ -1,6 +1,7 @@
package info.cemu.cemu.graphicpacks
import android.content.Context
import info.cemu.cemu.BuildConfig
import info.cemu.cemu.nativeinterface.NativeGraphicPacks
import info.cemu.cemu.utils.unzip
import kotlinx.coroutines.Dispatchers
@@ -14,13 +15,14 @@ import java.io.IOException
import kotlin.io.path.div
import kotlin.io.path.readText
sealed class GraphicPacksDownloadStatus {
data object CheckingForUpdates : GraphicPacksDownloadStatus()
data object NoUpdatesAvailable : GraphicPacksDownloadStatus()
data object Downloading : GraphicPacksDownloadStatus()
data object FinishedDownloading : GraphicPacksDownloadStatus()
data object Error : GraphicPacksDownloadStatus()
data object Canceled : GraphicPacksDownloadStatus()
enum class GraphicPacksDownloadStatus {
CHECKING_VERSION,
NO_UPDATES_AVAILABLE,
DOWNLOADING,
EXTRACTING,
FINISHED_DOWNLOADING,
ERROR,
CANCELED
}
class GraphicPacksDownloader {
@@ -29,7 +31,7 @@ class GraphicPacksDownloader {
graphicPacksDir.toPath() / "downloadedGraphicPacks" / "version.txt"
return try {
graphicPacksVersionFile.readText()
} catch (ignored: IOException) {
} catch (_: IOException) {
null
}
}
@@ -40,31 +42,53 @@ class GraphicPacksDownloader {
) {
val graphicPacksRootDir = context.getExternalFilesDir(null)
if (graphicPacksRootDir == null) {
updateStatus(GraphicPacksDownloadStatus.Error)
updateStatus(GraphicPacksDownloadStatus.ERROR)
return
}
val graphicPacksDirPath = graphicPacksRootDir.toPath() / "graphicPacks"
checkForNewUpdate(graphicPacksDirPath.toFile(), updateStatus)
}
private suspend fun getUpdateUrl(): String {
val queryUrl = "https://cemu.info/api2/query_graphicpack_url.php?" +
"version=${BuildConfig.VERSION_NAME}" +
"&t=${System.currentTimeMillis()}"
val request = Request.Builder()
.url(queryUrl)
.build()
Client.newCall(request).executeAsync().use { response ->
if (response.isSuccessful) {
val body = response.body.string().trim()
if (body.startsWith("http")) {
return body
}
}
}
return "https://api.github.com/repos/cemu-project/cemu_graphic_packs/releases/latest"
}
private suspend fun checkForNewUpdate(
graphicPacksDir: File,
updateStatus: suspend (GraphicPacksDownloadStatus) -> Unit
) {
updateStatus(GraphicPacksDownloadStatus.CheckingForUpdates)
updateStatus(GraphicPacksDownloadStatus.CHECKING_VERSION)
val request = Request.Builder()
.url(GITHUB_RELEASES_API_URL)
.url(getUpdateUrl())
.build()
Client.newCall(request).executeAsync().use { response ->
withContext(Dispatchers.IO) {
if (!response.isSuccessful) {
updateStatus(GraphicPacksDownloadStatus.Error)
updateStatus(GraphicPacksDownloadStatus.ERROR)
return@withContext
}
val json = JSONObject(response.body.string())
val version = json.getString("name")
if (getCurrentVersion(graphicPacksDir) == version) {
updateStatus(GraphicPacksDownloadStatus.NoUpdatesAvailable)
updateStatus(GraphicPacksDownloadStatus.NO_UPDATES_AVAILABLE)
return@withContext
}
val downloadUrl = json.getJSONArray("assets")
@@ -81,16 +105,21 @@ class GraphicPacksDownloader {
version: String,
updateStatus: suspend (GraphicPacksDownloadStatus) -> Unit
) {
updateStatus(GraphicPacksDownloadStatus.Downloading)
updateStatus(GraphicPacksDownloadStatus.DOWNLOADING)
val request = Request.Builder()
.url(downloadUrl)
.build()
Client.newCall(request).executeAsync().use { response ->
withContext(Dispatchers.IO) {
if (!response.isSuccessful) {
updateStatus(GraphicPacksDownloadStatus.Error)
updateStatus(GraphicPacksDownloadStatus.ERROR)
return@withContext
}
updateStatus(GraphicPacksDownloadStatus.EXTRACTING)
val graphicPacksTempDir = graphicPacksDir.resolve("downloadedGraphicPacksTemp")
graphicPacksTempDir.deleteRecursively()
unzip(
@@ -103,14 +132,13 @@ class GraphicPacksDownloader {
downloadedGraphicPacksDir.deleteRecursively()
graphicPacksTempDir.renameTo(downloadedGraphicPacksDir)
NativeGraphicPacks.refreshGraphicPacks()
updateStatus(GraphicPacksDownloadStatus.FinishedDownloading)
updateStatus(GraphicPacksDownloadStatus.FINISHED_DOWNLOADING)
}
}
}
companion object {
private val Client = OkHttpClient()
private const val GITHUB_RELEASES_API_URL =
"https://api.github.com/repos/cemu-project/cemu_graphic_packs/releases/latest"
}
}
@@ -22,7 +22,7 @@ class GraphicPacksListViewModel : ViewModel() {
private val installedTitleIds = NativeGameTitles.getInstalledGamesTitleIds()
private var rootNode = GraphicPackSectionNode()
private val _installedOnly = MutableStateFlow(true)
private val _installedOnly = MutableStateFlow(installedTitleIds.size > 1)
val installedOnly = _installedOnly.asStateFlow()
fun setInstalledOnly(installedOnly: Boolean) {
_installedOnly.value = installedOnly
@@ -45,7 +45,7 @@ class GraphicPacksListViewModel : ViewModel() {
GraphicPacksDownloader.download(context) { updateDownloadStatus(it) }
refreshGraphicPacks()
} catch (exception: Exception) {
updateDownloadStatus(GraphicPacksDownloadStatus.Error)
updateDownloadStatus(GraphicPacksDownloadStatus.ERROR)
}
}
}
@@ -58,7 +58,7 @@ class GraphicPacksListViewModel : ViewModel() {
downloadJob?.cancel(CancellationException("Canceled by user"))
downloadJob = null
viewModelScope.launch {
updateDownloadStatus(GraphicPacksDownloadStatus.Canceled)
updateDownloadStatus(GraphicPacksDownloadStatus.CANCELED)
}
}
@@ -158,16 +158,17 @@ fun GraphicPacksRootSectionScreen(
private fun downloadStatusToDialogTextString(downloadStatus: GraphicPacksDownloadStatus?): String? =
when (downloadStatus) {
GraphicPacksDownloadStatus.CheckingForUpdates -> tr("Checking version")
GraphicPacksDownloadStatus.Downloading -> tr("Downloading graphic packs")
GraphicPacksDownloadStatus.CHECKING_VERSION -> tr("Checking version...")
GraphicPacksDownloadStatus.DOWNLOADING -> tr("Downloading graphic packs...")
GraphicPacksDownloadStatus.EXTRACTING -> tr("Extracting...")
else -> null
}
private fun downloadStatusToNotificationString(downloadStatus: GraphicPacksDownloadStatus?): String? =
when (downloadStatus) {
GraphicPacksDownloadStatus.Error -> tr("Failed to download graphic packs")
GraphicPacksDownloadStatus.FinishedDownloading -> tr("Downloaded latest graphic packs")
GraphicPacksDownloadStatus.NoUpdatesAvailable -> tr("No updates available")
GraphicPacksDownloadStatus.ERROR -> tr("Failed to download graphic packs")
GraphicPacksDownloadStatus.FINISHED_DOWNLOADING -> tr("Downloaded latest graphic packs")
GraphicPacksDownloadStatus.NO_UPDATES_AVAILABLE -> tr("No updates available.")
else -> null
}
@@ -9,11 +9,13 @@ import java.util.zip.ZipInputStream
fun unzip(stream: InputStream, targetDir: String) {
ZipInputStream(stream).use { zipInputStream ->
var zipEntry: ZipEntry
val buffer = ByteArray(8192)
while ((zipInputStream.nextEntry.also { zipEntry = it }) != null) {
var zipEntry: ZipEntry? = zipInputStream.nextEntry
while (zipEntry != null) {
extractZipEntry(zipInputStream, zipEntry, buffer, targetDir)
zipInputStream.closeEntry()
zipEntry = zipInputStream.nextEntry
}
}
}