Mod sizes are updated to proper values upon selection (#8648)

* Mod sizes are updated to proper values upon selection

---------

Co-authored-by: vegeta1k95 <vfylfhby>
This commit is contained in:
vegeta1k95
2023-02-11 22:48:12 +01:00
committed by GitHub
parent 47bbd996ae
commit aaf06b7589
2 changed files with 77 additions and 6 deletions

View File

@ -250,6 +250,43 @@ object Github {
return null return null
} }
class Tree {
class TreeFile {
var size: Long = 0L
}
var url: String = ""
var tree = ArrayList<TreeFile>()
}
fun getRepoSize(repo: Repo): Float {
val link = "https://api.github.com/repos/${repo.full_name}/git/trees/${repo.default_branch}?recursive=true"
var retries = 2
while (retries > 0) {
retries--
// obey rate limit
if (RateLimit.waitForLimit()) return 0f
// try download
val inputStream = download(link) {
if (it.responseCode == 403 || it.responseCode == 200 && retries == 1) {
// Pass the response headers to the rate limit handler so it can process the rate limit headers
RateLimit.notifyHttpResponse(it)
retries++ // An extra retry so the 403 is ignored in the retry count
}
} ?: continue
val tree = json().fromJson(Tree::class.java, inputStream.bufferedReader().readText())
var totalSizeBytes = 0L
for (file in tree.tree)
totalSizeBytes += file.size
return totalSizeBytes / 1024f
}
return 0f
}
/** /**
* Parsed GitHub repo search response * Parsed GitHub repo search response
* @property total_count Total number of hits for the search (ignoring paging window) * @property total_count Total number of hits for the search (ignoring paging window)
@ -268,6 +305,9 @@ object Github {
/** Part of [RepoSearch] in Github API response - one repository entry in [items][RepoSearch.items] */ /** Part of [RepoSearch] in Github API response - one repository entry in [items][RepoSearch.items] */
@Suppress("PropertyName") @Suppress("PropertyName")
class Repo { class Repo {
var hasUpdatedSize = false
var name = "" var name = ""
var full_name = "" var full_name = ""
var description: String? = null var description: String? = null

View File

@ -10,6 +10,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.badlogic.gdx.utils.Json
import com.badlogic.gdx.utils.SerializationException import com.badlogic.gdx.utils.SerializationException
import com.unciv.MainMenuScreen import com.unciv.MainMenuScreen
import com.unciv.UncivGame import com.unciv.UncivGame
@ -47,8 +48,13 @@ import com.unciv.ui.utils.extensions.toTextButton
import com.unciv.utils.Log import com.unciv.utils.Log
import com.unciv.utils.concurrency.Concurrency import com.unciv.utils.concurrency.Concurrency
import com.unciv.utils.concurrency.launchOnGLThread import com.unciv.utils.concurrency.launchOnGLThread
import com.unciv.utils.concurrency.withGLContext
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLConnection
import kotlin.math.max import kotlin.math.max
/** /**
@ -73,8 +79,7 @@ class ModManagementScreen(
private var lastSelectedButton: Button? = null private var lastSelectedButton: Button? = null
private var lastSyncMarkedButton: Button? = null private var lastSyncMarkedButton: Button? = null
private var selectedModName = "" private var selectedMod: Github.Repo? = null
private var selectedAuthor = ""
private val modDescriptionLabel: WrappableLabel private val modDescriptionLabel: WrappableLabel
@ -357,8 +362,6 @@ class ModManagementScreen(
} }
private fun addModInfoToActionTable(modName: String, repoUrl: String, updatedAt: String, author: String, modSize: Int) { private fun addModInfoToActionTable(modName: String, repoUrl: String, updatedAt: String, author: String, modSize: Int) {
// remember selected mod - for now needed only to display a background-fetched image while the user is watching // remember selected mod - for now needed only to display a background-fetched image while the user is watching
selectedModName = modName
selectedAuthor = author
// Display metadata // Display metadata
if (author.isNotEmpty()) if (author.isNotEmpty())
@ -407,6 +410,13 @@ class ModManagementScreen(
return downloadButton return downloadButton
} }
private fun updateModInfo() {
if (selectedMod != null) {
modActionTable.clear()
addModInfoToActionTable(selectedMod!!)
}
}
/** Used as onClick handler for the online Mod list buttons */ /** Used as onClick handler for the online Mod list buttons */
private fun onlineButtonAction(repo: Github.Repo, button: Button) { private fun onlineButtonAction(repo: Github.Repo, button: Button) {
syncOnlineSelected(repo.name, button) syncOnlineSelected(repo.name, button)
@ -417,6 +427,26 @@ class ModManagementScreen(
val label = if (installedModInfo[repo.name]?.state?.hasUpdate == true) val label = if (installedModInfo[repo.name]?.state?.hasUpdate == true)
"Update [${repo.name}]" "Update [${repo.name}]"
else "Download [${repo.name}]" else "Download [${repo.name}]"
if (!repo.hasUpdatedSize) {
Concurrency.run("GitHubParser") {
try {
val repoSize = Github.getRepoSize(repo)
if (repoSize > 0f) {
launchOnGLThread {
repo.size = repoSize.toInt()
repo.hasUpdatedSize = true
if (selectedMod == repo)
updateModInfo()
}
}
} catch (ignore: IOException) {
/* Parsing of mod size failed, do nothing */
}
}.start()
}
rightSideButton.setText(label.tr()) rightSideButton.setText(label.tr())
rightSideButton.onClick { rightSideButton.onClick {
rightSideButton.setText("Downloading...".tr()) rightSideButton.setText("Downloading...".tr())
@ -426,8 +456,8 @@ class ModManagementScreen(
} }
} }
modActionTable.clear() selectedMod = repo
addModInfoToActionTable(repo) updateModInfo()
} }
/** Download and install a mod in the background, called both from the right-bottom button and the URL entry popup */ /** Download and install a mod in the background, called both from the right-bottom button and the URL entry popup */
@ -481,6 +511,7 @@ class ModManagementScreen(
* Display single mod metadata, offer additional actions (delete is elsewhere) * Display single mod metadata, offer additional actions (delete is elsewhere)
*/ */
private fun refreshInstalledModActions(mod: Ruleset) { private fun refreshInstalledModActions(mod: Ruleset) {
selectedMod = null
modActionTable.clear() modActionTable.clear()
// show mod information first // show mod information first
addModInfoToActionTable(mod.name, mod.modOptions) addModInfoToActionTable(mod.name, mod.modOptions)