diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index f552417edd..861ec18483 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -44,7 +44,10 @@ mods.browser = Mod Browser mods.browser.selected = Selected mod mods.browser.add = Install mods.browser.reinstall = Reinstall +mods.browser.latest = +mods.browser.releases = Releases mods.github.open = Repo +mods.github.open-release = Release Page mods.browser.sortdate = Sort by recent mods.browser.sortstars = Sort by stars diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index 0fed5ec1f5..656dbdcaf3 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -16,6 +16,7 @@ import arc.struct.*; import arc.util.*; import arc.util.io.*; import arc.util.serialization.*; +import arc.util.serialization.Jval.*; import mindustry.*; import mindustry.core.*; import mindustry.ctype.*; @@ -192,7 +193,7 @@ public class ModsDialog extends BaseDialog{ Core.settings.put("lastmod", text); //there's no good way to know if it's a java mod here, so assume it's not - githubImportMod(text, false); + githubImportMod(text, false, null); }); }).margin(12f); }); @@ -348,7 +349,7 @@ public class ModsDialog extends BaseDialog{ boolean showImport = !mod.hasSteamID(); dialog.buttons.button("@mods.github.open", Icon.link, () -> Core.app.openURI("https://github.com/" + mod.getRepo())); if(mobile && showImport) dialog.buttons.row(); - if(showImport) dialog.buttons.button("@mods.browser.reinstall", Icon.download, () -> githubImportMod(mod.getRepo(), mod.isJava())); + if(showImport) dialog.buttons.button("@mods.browser.reinstall", Icon.download, () -> githubImportMod(mod.getRepo(), mod.isJava(), null)); } dialog.cont.pane(desc -> { @@ -494,8 +495,54 @@ public class ModsDialog extends BaseDialog{ var found = mods.list().find(l -> mod.repo != null && mod.repo.equals(l.getRepo())); sel.buttons.button(found == null ? "@mods.browser.add" : "@mods.browser.reinstall", Icon.download, () -> { - sel.hide(); - githubImportMod(mod.repo, mod.hasJava); + BaseDialog load = new BaseDialog(""); + load.cont.add("[accent]Fetching Releases..."); + load.show(); + Http.get(ghApi + "/repos/" + mod.repo + "/releases", res -> { + load.hide(); + var json = Jval.read(res.getResultAsString()); + JsonArray releases = json.asArray(); + + if(releases.size < 2){ + //just import the mod + sel.hide(); + githubImportMod(mod.repo, mod.hasJava, null); + }else{ + sel.hide(); + BaseDialog downloads = new BaseDialog("@mods.browser.releases"); + downloads.cont.pane(p -> { + for(int j = 0; j < releases.size; j++){ + var release = releases.get(j); + + int index = j; + p.table(((TextureRegionDrawable) Tex.whiteui).tint(Pal.darkestGray), t -> { + t.add((index == 0 ? Core.bundle.get("mods.browser.latest") + " " : "") + release.getString("name")).top().left().growX().wrap().pad(5f).color(Pal.accent); + t.row(); + t.add((release.getString("published_at")).substring(0, 10).replaceAll("-", "/")).top().left().growX().wrap().pad(5f).color(Color.gray); + t.table(b -> { + b.defaults().size(150f, 54f).pad(2f); + b.button("@mods.github.open-release", Icon.link, () -> Core.app.openURI(release.getString("html_url"))); + b.button("@mods.browser.add", Icon.download, () -> { + String releaseUrl = release.getString("url"); + githubImportMod(mod.repo, mod.hasJava, releaseUrl.substring(releaseUrl.lastIndexOf("/") + 1)); + }); + }).right(); + }).margin(5f).growX().pad(5f); + + if(j < releases.size - 1) p.row(); + } + }).width(600f).scrollX(false).fillY(); + downloads.buttons.button("@back", Icon.left, () -> { + downloads.clear(); + downloads.hide(); + sel.show(); + }).size(150f, 54f).pad(2f); + downloads.keyDown(KeyCode.escape, downloads::hide); + downloads.keyDown(KeyCode.back, downloads::hide); + downloads.hidden(sel::show); + downloads.show(); + } + }); }); sel.buttons.button("@mods.github.open", Icon.link, () -> { Core.app.openURI("https://github.com/" + mod.repo); @@ -547,13 +594,13 @@ public class ModsDialog extends BaseDialog{ Core.app.post(() -> modError(t)); } - private void githubImportMod(String repo, boolean isJava){ + private void githubImportMod(String repo, boolean isJava, @Nullable String release){ modImportProgress = 0f; ui.loadfrag.show("@downloading"); ui.loadfrag.setProgress(() -> modImportProgress); if(isJava){ - githubImportJavaMod(repo); + githubImportJavaMod(repo, release); }else{ Http.get(ghApi + "/repos/" + repo, res -> { var json = Jval.read(res.getResultAsString()); @@ -563,17 +610,17 @@ public class ModsDialog extends BaseDialog{ //this is a crude heuristic for class mods; only required for direct github import //TODO make a more reliable way to distinguish java mod repos if(language.equals("Java") || language.equals("Kotlin")){ - githubImportJavaMod(repo); + githubImportJavaMod(repo, release); }else{ - githubImportBranch(mainBranch, repo); + githubImportBranch(mainBranch, repo, release); } }, this::importFail); } } - private void githubImportJavaMod(String repo){ + private void githubImportJavaMod(String repo, @Nullable String release){ //grab latest release - Http.get(ghApi + "/repos/" + repo + "/releases/latest", res -> { + Http.get(ghApi + "/repos/" + repo + "/releases/" + (release == null ? "latest" : release), res -> { var json = Jval.read(res.getResultAsString()); var assets = json.get("assets").asArray(); @@ -592,15 +639,30 @@ public class ModsDialog extends BaseDialog{ }, this::importFail); } - private void githubImportBranch(String branch, String repo){ - Http.get(ghApi + "/repos/" + repo + "/zipball/" + branch, loc -> { - if(loc.getHeader("Location") != null){ - Http.get(loc.getHeader("Location"), result -> { - handleMod(repo, result); + private void githubImportBranch(String branch, String repo, @Nullable String release){ + if(release != null) { + Http.get(ghApi + "/repos/" + repo + "/releases/" + release, res -> { + String zipUrl = Jval.read(res.getResultAsString()).getString("zipball_url"); + Http.get(zipUrl, loc -> { + if(loc.getHeader("Location") != null){ + Http.get(loc.getHeader("Location"), result -> { + handleMod(repo, result); + }, this::importFail); + }else{ + handleMod(repo, loc); + } }, this::importFail); - }else{ - handleMod(repo, loc); - } - }, this::importFail); + }); + }else{ + Http.get(ghApi + "/repos/" + repo + "/zipball/" + branch, loc -> { + if(loc.getHeader("Location") != null){ + Http.get(loc.getHeader("Location"), result -> { + handleMod(repo, result); + }, this::importFail); + }else{ + handleMod(repo, loc); + } + }, this::importFail); + } } }