diff --git a/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClient.java b/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClient.java index 0df12bf1ed..e6bda75032 100644 --- a/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClient.java +++ b/runelite-client/src/main/java/net/runelite/client/externalplugins/ExternalPluginClient.java @@ -25,9 +25,11 @@ package net.runelite.client.externalplugins; import com.google.common.reflect.TypeToken; +import com.google.gson.JsonSyntaxException; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -37,6 +39,7 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.util.List; +import java.util.Map; import javax.imageio.ImageIO; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; @@ -172,4 +175,27 @@ public class ExternalPluginClient } }); } + + public Map getPluginCounts() throws IOException + { + HttpUrl url = RuneLiteAPI.getApiBase() + .newBuilder() + .addPathSegments("pluginhub") + .build(); + try (Response res = okHttpClient.newCall(new Request.Builder().url(url).build()).execute()) + { + if (res.code() != 200) + { + throw new IOException("Non-OK response code: " + res.code()); + } + + // CHECKSTYLE:OFF + return RuneLiteAPI.GSON.fromJson(new InputStreamReader(res.body().byteStream()), new TypeToken>(){}.getType()); + // CHECKSTYLE:ON + } + catch (JsonSyntaxException ex) + { + throw new IOException(ex); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java index 562a8517e2..7f9bbceb05 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginHubPanel.java @@ -125,10 +125,13 @@ class PluginHubPanel extends PluginPanel @Getter private final List keywords = new ArrayList<>(); + @Getter + private final int userCount; + @Getter private final boolean installed; - PluginItem(ExternalPluginManifest newManifest, Collection loadedPlugins, boolean installed) + PluginItem(ExternalPluginManifest newManifest, Collection loadedPlugins, int userCount, boolean installed) { ExternalPluginManifest loaded = null; if (!loadedPlugins.isEmpty()) @@ -137,6 +140,7 @@ class PluginHubPanel extends PluginPanel } manifest = newManifest == null ? loaded : newManifest; + this.userCount = userCount; this.installed = installed; if (manifest != null) @@ -194,10 +198,7 @@ class PluginHubPanel extends PluginPanel { BufferedImage img = externalPluginClient.downloadIcon(manifest); - SwingUtilities.invokeLater(() -> - { - icon.setIcon(new ImageIcon(img)); - }); + SwingUtilities.invokeLater(() -> icon.setIcon(new ImageIcon(img))); } catch (IOException e) { @@ -521,11 +522,21 @@ class PluginHubPanel extends PluginPanel return; } - reloadPluginList(manifest); + Map pluginCounts = Collections.emptyMap(); + try + { + pluginCounts = externalPluginClient.getPluginCounts(); + } + catch (IOException e) + { + log.warn("unable to download plugin counts", e); + } + + reloadPluginList(manifest, pluginCounts); }); } - private void reloadPluginList(List manifest) + private void reloadPluginList(List manifest, Map pluginCounts) { Map manifests = manifest.stream() .collect(ImmutableMap.toImmutableMap(ExternalPluginManifest::getInternalName, Function.identity())); @@ -547,7 +558,8 @@ class PluginHubPanel extends PluginPanel { plugins = Sets.union(manifests.keySet(), loadedPlugins.keySet()) .stream() - .map(id -> new PluginItem(manifests.get(id), loadedPlugins.get(id), installed.contains(id))) + .map(id -> new PluginItem(manifests.get(id), loadedPlugins.get(id), + pluginCounts.getOrDefault(id, -1), installed.contains(id))) .collect(Collectors.toList()); refreshing.setVisible(false); @@ -575,7 +587,11 @@ class PluginHubPanel extends PluginPanel else { stream - .sorted(Comparator.comparing(PluginItem::isInstalled).thenComparing(p -> p.manifest.getDisplayName())) + .sorted(Comparator.comparing(PluginItem::isInstalled) + .thenComparingInt(PluginItem::getUserCount) + .reversed() + .thenComparing(p -> p.manifest.getDisplayName()) + ) .forEach(mainPanel::add); } @@ -594,6 +610,13 @@ class PluginHubPanel extends PluginPanel @Subscribe private void onExternalPluginsChanged(ExternalPluginsChanged ev) { - SwingUtilities.invokeLater(() -> reloadPluginList(ev.getLoadedManifest())); + Map pluginCounts = Collections.emptyMap(); + if (plugins != null) + { + pluginCounts = plugins.stream() + .collect(Collectors.toMap(pi -> pi.manifest.getInternalName(), PluginItem::getUserCount)); + } + + reloadPluginList(ev.getLoadedManifest(), pluginCounts); } }