From 916b8b451d29dace666db07d14566a5c3c3b25ed Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Fri, 10 Nov 2023 08:57:20 +0100 Subject: [PATCH] Fix Mod download issue - github url and indicator refresh (#10449) * Change mod zip download URL for better compatibility * Fix visual/has-update indicators not updating properly after download --- .../screens/modmanager/ModDecoratedButton.kt | 6 ++++- .../screens/modmanager/ModManagementScreen.kt | 23 ++++++++++++++----- .../unciv/ui/screens/pickerscreens/GitHub.kt | 5 +++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/core/src/com/unciv/ui/screens/modmanager/ModDecoratedButton.kt b/core/src/com/unciv/ui/screens/modmanager/ModDecoratedButton.kt index 5f00effa56..f216f5c1c0 100644 --- a/core/src/com/unciv/ui/screens/modmanager/ModDecoratedButton.kt +++ b/core/src/com/unciv/ui/screens/modmanager/ModDecoratedButton.kt @@ -18,7 +18,7 @@ import com.unciv.ui.images.ImageGetter * The "installed" version shows indicators for "Selected as permanent visual mod" and "update available", * as read from the [modInfo] fields, but requires a [updateIndicators] call when those change. */ -internal class ModDecoratedButton(private val modInfo: ModUIData) : Table() { +internal class ModDecoratedButton(private var modInfo: ModUIData) : Table() { private val stateImages: ModStateImages? private val textButton: TextButton @@ -56,6 +56,10 @@ internal class ModDecoratedButton(private val modInfo: ModUIData) : Table() { override fun setColor(color: Color) { textButton.color = color } override fun getColor(): Color = textButton.color + fun updateUIData(newModUIData: ModUIData) { + modInfo = newModUIData + } + /** Helper class keeps references to decoration images of installed mods to enable dynamic visibility * (actually we do not use isVisible but refill thiis container selectively which allows the aggregate height to adapt and the set to center vertically) */ diff --git a/core/src/com/unciv/ui/screens/modmanager/ModManagementScreen.kt b/core/src/com/unciv/ui/screens/modmanager/ModManagementScreen.kt index da9e58ce0f..7394718563 100644 --- a/core/src/com/unciv/ui/screens/modmanager/ModManagementScreen.kt +++ b/core/src/com/unciv/ui/screens/modmanager/ModManagementScreen.kt @@ -17,10 +17,7 @@ import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.RulesetCache import com.unciv.models.tilesets.TileSetCache import com.unciv.models.translations.tr -import com.unciv.ui.components.widgets.AutoScrollPane -import com.unciv.ui.components.widgets.ExpanderTab import com.unciv.ui.components.UncivTextField -import com.unciv.ui.components.widgets.WrappableLabel import com.unciv.ui.components.extensions.addSeparator import com.unciv.ui.components.extensions.disable import com.unciv.ui.components.extensions.enable @@ -33,6 +30,9 @@ import com.unciv.ui.components.input.clearActivationActions import com.unciv.ui.components.input.keyShortcuts import com.unciv.ui.components.input.onActivation import com.unciv.ui.components.input.onClick +import com.unciv.ui.components.widgets.AutoScrollPane +import com.unciv.ui.components.widgets.ExpanderTab +import com.unciv.ui.components.widgets.WrappableLabel import com.unciv.ui.images.ImageGetter import com.unciv.ui.popups.ConfirmPopup import com.unciv.ui.popups.Popup @@ -449,9 +449,7 @@ class ModManagementScreen private constructor( ToastPopup("[$repoName] Downloaded!", this@ModManagementScreen) reloadCachesAfterModChange() UncivGame.Current.translations.tryReadTranslationForCurrentLanguage() - RulesetCache[repoName]?.let { - installedModInfo[repoName] = ModUIData(it, false) - } + updateInstalledModUIData(repoName) refreshInstalledModTable() lastSelectedButton?.let { syncOnlineSelected(repoName, it) } showModDescription(repoName) @@ -468,6 +466,19 @@ class ModManagementScreen private constructor( } } + /** Our data on the Mod needs refreshing description after download or update */ + private fun updateInstalledModUIData(modName: String) { + val ruleset = RulesetCache[modName] + ?: return // Bail if download was not actually successful? + // When someone marks a Mod as 'permanent audiovisual', then deletes it, then redownloads, that + // 'permanent audiovisual' will still be valid - re-evaluate here or remove the setting in the delete code. + val isVisual = game.settings.visualMods.contains(modName) + val newModUIData = ModUIData(ruleset, isVisual) + installedModInfo[modName] = newModUIData + // The ModUIData in the actual button is now out of sync, but can be indexed using the new instance + modButtons[newModUIData]?.updateUIData(newModUIData) + } + /** Remove the visual indicators for an 'updated' mod after re-downloading it. * (" - Updated" on the button text in the online mod list and the icon beside the installed mod's button) * It should be up to date now (unless the repo's date is in the future relative to system time) diff --git a/core/src/com/unciv/ui/screens/pickerscreens/GitHub.kt b/core/src/com/unciv/ui/screens/pickerscreens/GitHub.kt index fdc5b32147..255db4f34e 100644 --- a/core/src/com/unciv/ui/screens/pickerscreens/GitHub.kt +++ b/core/src/com/unciv/ui/screens/pickerscreens/GitHub.kt @@ -81,7 +81,10 @@ object Github { val defaultBranch = repo.default_branch val gitRepoUrl = repo.html_url // Initiate download - the helper returns null when it fails - val zipUrl = "$gitRepoUrl/archive/$defaultBranch.zip" + // URL format see: https://docs.github.com/en/repositories/working-with-files/using-files/downloading-source-code-archives#source-code-archive-urls + // Note: https://api.github.com/repos/owner/mod/zipball would be an alternative. Its response is a redirect, but our lib follows that and delivers the zip just fine. + // Problems with the latter: Internal zip structure different, finalDestinationName would need a patch. Plus, normal URL escaping for owner/reponame does not work. + val zipUrl = "$gitRepoUrl/archive/refs/heads/$defaultBranch.zip" val inputStream = download(zipUrl) ?: return null // Get a mod-specific temp file name