project(externals): Make the external manager more robust

This commit is contained in:
Owain van Brakel
2022-04-30 01:58:56 +02:00
parent f41b93d94d
commit 7df799e173
6 changed files with 673 additions and 29 deletions

View File

@@ -88,10 +88,9 @@ import org.pf4j.DependencyResolver;
import org.pf4j.PluginDependency;
import org.pf4j.PluginRuntimeException;
import org.pf4j.PluginWrapper;
import org.pf4j.update.DefaultUpdateRepository;
import org.pf4j.update.PluginInfo;
import org.pf4j.update.UpdateManager;
import org.pf4j.update.UpdateRepository;
import org.pf4j.update.VerifyException;
@SuppressWarnings("UnstableApiUsage")
@Slf4j
@@ -107,7 +106,7 @@ public class OPRSExternalPluginManager
@Getter(AccessLevel.PUBLIC)
private org.pf4j.PluginManager externalPluginManager;
@Getter(AccessLevel.PUBLIC)
private final List<UpdateRepository> repositories = new ArrayList<>();
private final List<OPRSUpdateRepository> repositories = new ArrayList<>();
@Inject
private OpenOSRSConfig openOSRSConfig;
@Inject
@@ -124,7 +123,7 @@ public class OPRSExternalPluginManager
@Inject
private Groups groups;
@Getter(AccessLevel.PUBLIC)
private UpdateManager updateManager;
private OPRSUpdateManager updateManager;
@Inject
@Named("safeMode")
private boolean safeMode;
@@ -160,7 +159,7 @@ public class OPRSExternalPluginManager
}
/**
* Note that {@link UpdateManager#addRepository} checks if the repo exists, however it throws an exception which is bad
* Note that {@link OPRSUpdateManager#addRepository} checks if the repo exists, however it throws an exception which is bad
*/
public boolean doesRepoExist(String id)
{
@@ -192,17 +191,17 @@ public class OPRSExternalPluginManager
public static boolean testRepository(URL url, String pluginsJson)
{
final List<UpdateRepository> repositories = new ArrayList<>();
final List<OPRSUpdateRepository> repositories = new ArrayList<>();
if (pluginsJson != null)
{
repositories.add(new DefaultUpdateRepository("repository-testing", url, pluginsJson));
repositories.add(new OPRSUpdateRepository("repository-testing", url, pluginsJson));
}
else
{
repositories.add(new DefaultUpdateRepository("repository-testing", url));
repositories.add(new OPRSUpdateRepository("repository-testing", url));
}
DefaultPluginManager testPluginManager = new DefaultPluginManager(EXTERNALPLUGIN_DIR.toPath());
UpdateManager updateManager = new UpdateManager(testPluginManager, repositories);
OPRSUpdateManager updateManager = new OPRSUpdateManager(testPluginManager, repositories);
return updateManager.getPlugins().size() <= 0;
}
@@ -258,7 +257,7 @@ public class OPRSExternalPluginManager
loadOldFormat();
}
updateManager = new UpdateManager(externalPluginManager, repositories);
updateManager = new OPRSUpdateManager(externalPluginManager, repositories);
saveConfig();
}
@@ -310,11 +309,11 @@ public class OPRSExternalPluginManager
if (pluginJson == null)
{
repositories.add(new DefaultUpdateRepository(id, new URL(url)));
repositories.add(new OPRSUpdateRepository(id, new URL(url)));
}
else
{
repositories.add(new DefaultUpdateRepository(id, new URL(url), pluginJson));
repositories.add(new OPRSUpdateRepository(id, new URL(url), pluginJson));
}
}
}
@@ -340,7 +339,7 @@ public class OPRSExternalPluginManager
String id = keyval.substring(0, keyval.lastIndexOf(":https"));
String url = keyval.substring(keyval.lastIndexOf("https"));
DefaultUpdateRepository defaultRepo = new DefaultUpdateRepository(id, new URL(url));
OPRSUpdateRepository defaultRepo = new OPRSUpdateRepository(id, new URL(url));
repositories.add(defaultRepo);
log.debug("Added Repo: {}", defaultRepo.getUrl());
}
@@ -355,7 +354,7 @@ public class OPRSExternalPluginManager
openOSRSConfig.setExternalRepositories(DEFAULT_PLUGIN_REPOS);
}
updateManager = new UpdateManager(externalPluginManager, repositories);
updateManager = new OPRSUpdateManager(externalPluginManager, repositories);
}
public void addGHRepository(String owner, String name)
@@ -377,15 +376,15 @@ public class OPRSExternalPluginManager
public void addRepository(String key, URL url, String pluginsJson)
{
DefaultUpdateRepository respository;
OPRSUpdateRepository respository;
if (pluginsJson != null)
{
respository = new DefaultUpdateRepository(key, url, pluginsJson);
respository = new OPRSUpdateRepository(key, url, pluginsJson);
}
else
{
respository = new DefaultUpdateRepository(key, url);
respository = new OPRSUpdateRepository(key, url);
}
updateManager.addRepository(respository);
@@ -1030,10 +1029,18 @@ public class OPRSExternalPluginManager
error = true;
}
}
catch (VerifyException ex)
{
// This should never happen but can crash the client
log.error("Cannot update plugin '{}', the SHA512 hash mismatches! {}", plugin.id, ex.getMessage());
error = true;
break;
}
catch (PluginRuntimeException ex)
{
// This should never happen but can crash the client
log.warn("Cannot update plugin '{}', the user probably has another client open", plugin.id);
log.error(String.valueOf(ex));
error = true;
break;
}
@@ -1181,8 +1188,6 @@ public class OPRSExternalPluginManager
}
/**
* Mostly stolen from {@link java.net.URLStreamHandler#toExternalForm(URL)}
*
* @param url URL to encode
* @return URL, with path, query and ref encoded
*/

View File

@@ -0,0 +1,463 @@
package net.runelite.client.plugins;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.pf4j.PluginManager;
import org.pf4j.PluginRuntimeException;
import org.pf4j.PluginState;
import org.pf4j.PluginWrapper;
import org.pf4j.VersionManager;
import org.pf4j.update.DefaultUpdateRepository;
import org.pf4j.update.FileDownloader;
import org.pf4j.update.FileVerifier;
import org.pf4j.update.PluginInfo;
import org.pf4j.update.SimpleFileDownloader;
import org.pf4j.update.UpdateManager;
import org.pf4j.update.verifier.CompoundVerifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OPRSUpdateManager
{
private static final Logger log = LoggerFactory.getLogger(UpdateManager.class);
private final PluginManager pluginManager;
private final VersionManager versionManager;
private final String systemVersion;
private final Path repositoriesJson;
// cache last plugin release per plugin id (the key)
private final Map<String, PluginInfo.PluginRelease> lastPluginRelease = new HashMap<>();
protected List<OPRSUpdateRepository> repositories;
public OPRSUpdateManager(PluginManager pluginManager)
{
this.pluginManager = pluginManager;
versionManager = pluginManager.getVersionManager();
systemVersion = pluginManager.getSystemVersion();
repositoriesJson = Paths.get("repositories.json");
}
public OPRSUpdateManager(PluginManager pluginManager, List<OPRSUpdateRepository> repos)
{
this(pluginManager);
repositories = repos == null ? new ArrayList<>() : repos;
}
public List<PluginInfo> getAvailablePlugins()
{
List<PluginInfo> availablePlugins = new ArrayList<>();
for (PluginInfo plugin : getPlugins())
{
if (pluginManager.getPlugin(plugin.id) == null)
{
availablePlugins.add(plugin);
}
}
return availablePlugins;
}
/**
* Return a list of plugins that are newer versions of already installed plugins.
*
* @return list of plugins that have updates
*/
public List<PluginInfo> getUpdates()
{
List<PluginInfo> updates = new ArrayList<>();
for (PluginWrapper installed : pluginManager.getPlugins())
{
String pluginId = installed.getPluginId();
if (hasPluginUpdate(pluginId))
{
updates.add(getPluginsMap().get(pluginId));
}
}
return updates;
}
/**
* Checks if Update Repositories has newer versions of some of the installed plugins.
*
* @return true if updates exist
*/
public boolean hasUpdates()
{
return getUpdates().size() > 0;
}
/**
* Get the list of plugins from all repos.
*
* @return List of plugin info
*/
public List<PluginInfo> getPlugins()
{
List<PluginInfo> list = new ArrayList<>(getPluginsMap().values());
Collections.sort(list);
return list;
}
/**
* Get a map of all plugins from all repos where key is plugin id.
*
* @return List of plugin info
*/
public Map<String, PluginInfo> getPluginsMap()
{
Map<String, PluginInfo> pluginsMap = new HashMap<>();
for (OPRSUpdateRepository repository : getRepositories())
{
pluginsMap.putAll(repository.getPlugins());
}
return pluginsMap;
}
public List<OPRSUpdateRepository> getRepositories()
{
if (repositories == null && repositoriesJson != null)
{
refresh();
}
return repositories;
}
/**
* Add one {@link DefaultUpdateRepository}.
*
* @param id of repo
* @param url of repo
*/
public void addRepository(String id, URL url)
{
for (OPRSUpdateRepository ur : repositories)
{
if (ur.getId().equals(id))
{
throw new RuntimeException("Repository with id " + id + " already exists");
}
}
repositories.add(new OPRSUpdateRepository(id, url));
}
/**
* Add a repo that was created by client.
*
* @param newRepo the new UpdateRepository to add to the list
*/
public void addRepository(OPRSUpdateRepository newRepo)
{
for (OPRSUpdateRepository ur : repositories)
{
if (ur.getId().equals(newRepo.getId()))
{
throw new RuntimeException("Repository with id " + newRepo.getId() + " already exists");
}
}
newRepo.refresh();
repositories.add(newRepo);
}
/**
* Remove a repository by id.
*
* @param id of repository to remove
*/
public void removeRepository(String id)
{
for (OPRSUpdateRepository repo : getRepositories())
{
if (id.equals(repo.getId()))
{
repositories.remove(repo);
break;
}
}
log.warn("Repository with id " + id + " not found, doing nothing");
}
/**
* Refreshes all repositories, so they are forced to refresh list of plugins.
*/
public synchronized void refresh()
{
if (repositoriesJson != null && Files.exists(repositoriesJson))
{
initRepositoriesFromJson();
}
for (OPRSUpdateRepository updateRepository : repositories)
{
updateRepository.refresh();
}
lastPluginRelease.clear();
}
/**
* Installs a plugin by id and version.
*
* @param id the id of plugin to install
* @param version the version of plugin to install, on SemVer format, or null for latest
* @return true if installation successful and plugin started
* @throws PluginRuntimeException if plugin does not exist in repos or problems during
*/
public synchronized boolean installPlugin(String id, String version)
{
// Download to temporary location
Path downloaded = downloadPlugin(id, version);
Path pluginsRoot = pluginManager.getPluginsRoot();
Path file = pluginsRoot.resolve(downloaded.getFileName());
try
{
Files.move(downloaded, file, REPLACE_EXISTING);
}
catch (IOException e)
{
throw new PluginRuntimeException(e, "Failed to write file '{}' to plugins folder", file);
}
String pluginId = pluginManager.loadPlugin(file);
PluginState state = pluginManager.startPlugin(pluginId);
return PluginState.STARTED.equals(state);
}
/**
* Downloads a plugin with given coordinates, runs all {@link FileVerifier}s
* and returns a path to the downloaded file.
*
* @param id of plugin
* @param version of plugin or null to download latest
* @return Path to file which will reside in a temporary folder in the system default temp area
* @throws PluginRuntimeException if download failed
*/
protected Path downloadPlugin(String id, String version)
{
try
{
PluginInfo.PluginRelease release = findReleaseForPlugin(id, version);
Path downloaded = getFileDownloader(id).downloadFile(new URL(release.url));
getFileVerifier(id).verify(new FileVerifier.Context(id, release), downloaded);
return downloaded;
}
catch (IOException e)
{
throw new PluginRuntimeException(e, "Error during download of plugin {}", id);
}
}
/**
* Finds the {@link FileDownloader} to use for this repository.
*
* @param pluginId the plugin we wish to download
* @return FileDownloader instance
*/
protected FileDownloader getFileDownloader(String pluginId)
{
for (OPRSUpdateRepository ur : repositories)
{
if (ur.getPlugin(pluginId) != null && ur.getFileDownloader() != null)
{
return ur.getFileDownloader();
}
}
return new SimpleFileDownloader();
}
/**
* Gets a file verifier to use for this plugin. First tries to use custom verifier
* configured for the repository, then fallback to the default {@link CompoundVerifier}
*
* @param pluginId the plugin we wish to download
* @return FileVerifier instance
*/
protected FileVerifier getFileVerifier(String pluginId)
{
for (OPRSUpdateRepository ur : repositories)
{
if (ur.getPlugin(pluginId) != null && ur.getFileVerifier() != null)
{
return ur.getFileVerifier();
}
}
return new CompoundVerifier();
}
/**
* Resolves Release from id and version.
*
* @param id of plugin
* @param version of plugin or null to locate latest version
* @return PluginRelease for downloading
* @throws PluginRuntimeException if id or version does not exist
*/
protected PluginInfo.PluginRelease findReleaseForPlugin(String id, String version)
{
PluginInfo pluginInfo = getPluginsMap().get(id);
if (pluginInfo == null)
{
log.info("Plugin with id {} does not exist in any repository", id);
throw new PluginRuntimeException("Plugin with id {} not found in any repository", id);
}
if (version == null)
{
return getLastPluginRelease(id);
}
for (PluginInfo.PluginRelease release : pluginInfo.releases)
{
if (versionManager.compareVersions(version, release.version) == 0 && release.url != null)
{
return release;
}
}
throw new PluginRuntimeException("Plugin {} with version @{} does not exist in the repository", id, version);
}
/**
* Updates a plugin id to given version or to latest version if {@code version == null}.
*
* @param id the id of plugin to update
* @param version the version to update to, on SemVer format, or null for latest
* @return true if update successful
* @throws PluginRuntimeException in case the given version is not available, plugin id not already installed etc
*/
public boolean updatePlugin(String id, String version)
{
if (pluginManager.getPlugin(id) == null)
{
throw new PluginRuntimeException("Plugin {} cannot be updated since it is not installed", id);
}
PluginInfo pluginInfo = getPluginsMap().get(id);
if (pluginInfo == null)
{
throw new PluginRuntimeException("Plugin {} does not exist in any repository", id);
}
if (!hasPluginUpdate(id))
{
log.warn("Plugin {} does not have an update available which is compatible with system version {}", id, systemVersion);
return false;
}
// Download to temp folder
Path downloaded = downloadPlugin(id, version);
if (!pluginManager.deletePlugin(id))
{
return false;
}
Path pluginsRoot = pluginManager.getPluginsRoot();
Path file = pluginsRoot.resolve(downloaded.getFileName());
try
{
Files.move(downloaded, file, REPLACE_EXISTING);
}
catch (IOException e)
{
throw new PluginRuntimeException("Failed to write plugin file {} to plugin folder", file);
}
String newPluginId = pluginManager.loadPlugin(file);
PluginState state = pluginManager.startPlugin(newPluginId);
return PluginState.STARTED.equals(state);
}
/**
* Returns the last release version of this plugin for given system version, regardless of release date.
*
* @return PluginRelease which has the highest version number
*/
public PluginInfo.PluginRelease getLastPluginRelease(String id)
{
PluginInfo pluginInfo = getPluginsMap().get(id);
if (pluginInfo == null)
{
return null;
}
if (!lastPluginRelease.containsKey(id))
{
for (PluginInfo.PluginRelease release : pluginInfo.releases)
{
if (systemVersion.equals("0.0.0") || versionManager.checkVersionConstraint(systemVersion, release.requires))
{
if (lastPluginRelease.get(id) == null)
{
lastPluginRelease.put(id, release);
}
else if (versionManager.compareVersions(release.version, lastPluginRelease.get(id).version) > 0)
{
lastPluginRelease.put(id, release);
}
}
}
}
return lastPluginRelease.get(id);
}
/**
* Finds whether the newer version of the plugin.
*
* @return true if there is a newer version available which is compatible with system
*/
public boolean hasPluginUpdate(String id)
{
PluginInfo pluginInfo = getPluginsMap().get(id);
if (pluginInfo == null)
{
return false;
}
String installedVersion = pluginManager.getPlugin(id).getDescriptor().getVersion();
PluginInfo.PluginRelease last = getLastPluginRelease(id);
return last != null && versionManager.compareVersions(last.version, installedVersion) > 0;
}
protected synchronized void initRepositoriesFromJson()
{
log.debug("Read repositories from '{}'", repositoriesJson);
try (FileReader reader = new FileReader(repositoriesJson.toFile()))
{
Gson gson = new GsonBuilder().create();
OPRSUpdateRepository[] items = gson.fromJson(reader, OPRSUpdateRepository[].class);
repositories = Arrays.asList(items);
}
catch (IOException e)
{
e.printStackTrace();
repositories = Collections.emptyList();
}
}
}

View File

@@ -0,0 +1,176 @@
package net.runelite.client.plugins;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.pf4j.update.DefaultUpdateRepository;
import org.pf4j.update.FileDownloader;
import org.pf4j.update.FileVerifier;
import org.pf4j.update.PluginInfo;
import org.pf4j.update.SimpleFileDownloader;
import org.pf4j.update.UpdateRepository;
import org.pf4j.update.util.LenientDateTypeAdapter;
import org.pf4j.update.verifier.CompoundVerifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OPRSUpdateRepository implements UpdateRepository
{
private static final String DEFAULT_PLUGINS_JSON_FILENAME = "plugins.json";
private static final Logger log = LoggerFactory.getLogger(DefaultUpdateRepository.class);
private final String id;
private final URL url;
private String pluginsJsonFileName;
private Map<String, PluginInfo> plugins;
public OPRSUpdateRepository(String id, URL url)
{
this(id, url, DEFAULT_PLUGINS_JSON_FILENAME);
}
public OPRSUpdateRepository(String id, URL url, String pluginsJsonFileName)
{
this.id = id;
this.url = url;
this.pluginsJsonFileName = pluginsJsonFileName;
}
@Override
public String getId()
{
return id;
}
@Override
public URL getUrl()
{
return url;
}
@Override
public Map<String, PluginInfo> getPlugins()
{
if (plugins == null)
{
initPlugins();
}
return plugins;
}
@Override
public PluginInfo getPlugin(String id)
{
return getPlugins().get(id);
}
private void initPlugins()
{
Reader pluginsJsonReader;
try
{
URL pluginsUrl = new URL(getUrl(), getPluginsJsonFileName());
log.debug("Read plugins of '{}' repository from '{}'", id, pluginsUrl);
pluginsJsonReader = new InputStreamReader(pluginsUrl.openStream());
}
catch (FileNotFoundException e)
{
log.error("{}{} could not be loaded (file missing)", getUrl(), getPluginsJsonFileName());
plugins = Collections.emptyMap();
return;
}
catch (Exception e)
{
log.error(e.getMessage(), e);
plugins = Collections.emptyMap();
return;
}
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new LenientDateTypeAdapter()).create();
PluginInfo[] items;
try
{
items = gson.fromJson(pluginsJsonReader, PluginInfo[].class);
}
catch (IllegalStateException | JsonSyntaxException ex)
{
items = new PluginInfo[]{};
}
plugins = new HashMap<>(items.length);
for (PluginInfo p : items)
{
for (PluginInfo.PluginRelease r : p.releases)
{
try
{
r.url = new URL(getUrl(), r.url).toString();
if (r.date.getTime() == 0)
{
log.warn("Illegal release date when parsing {}@{}, setting to epoch", p.id, r.version);
}
}
catch (MalformedURLException e)
{
log.warn("Skipping release {} of plugin {} due to failure to build valid absolute URL. Url was {}{}", r.version, p.id, getUrl(), r.url);
}
}
p.setRepositoryId(getId());
plugins.put(p.id, p);
}
log.debug("Found {} plugins in repository '{}'", plugins.size(), id);
}
/**
* Causes {@code plugins.json} to be read again to look for new updates from repositories.
*/
@Override
public void refresh()
{
plugins = null;
}
@Override
public FileDownloader getFileDownloader()
{
return new SimpleFileDownloader();
}
/**
* Gets a file verifier to execute on the downloaded file for it to be claimed valid.
* May be a CompoundVerifier in order to chain several verifiers.
*
* @return list of {@link FileVerifier}s
*/
@Override
public FileVerifier getFileVerifier()
{
return new CompoundVerifier();
}
/**
* Gets the plugins json file name. Returns {@code plugins.json} if null.
*
* @return the plugins json file name
*/
public String getPluginsJsonFileName()
{
if (pluginsJsonFileName == null)
{
pluginsJsonFileName = DEFAULT_PLUGINS_JSON_FILENAME;
}
return pluginsJsonFileName;
}
}

View File

@@ -4,6 +4,8 @@ import net.runelite.client.plugins.OPRSExternalPluginManager;
import com.google.gson.JsonSyntaxException;
import com.openosrs.client.events.OPRSPluginChanged;
import com.openosrs.client.events.OPRSRepositoryChanged;
import net.runelite.client.plugins.OPRSUpdateManager;
import net.runelite.client.plugins.OPRSUpdateRepository;
import net.runelite.client.util.DeferredDocumentChangedListener;
import java.awt.BorderLayout;
import java.awt.Color;
@@ -46,8 +48,6 @@ import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.SwingUtil;
import org.pf4j.VersionManager;
import org.pf4j.update.PluginInfo;
import org.pf4j.update.UpdateManager;
import org.pf4j.update.UpdateRepository;
import org.pf4j.update.VerifyException;
@Slf4j
@@ -84,7 +84,7 @@ public class PluginsPanel extends JPanel
private final OPRSExternalPluginManager externalPluginManager;
private final VersionManager versionManager;
private final UpdateManager updateManager;
private final OPRSUpdateManager updateManager;
private final IconTextField searchBar = new IconTextField();
private final JPanel filterwrapper = new JPanel(new BorderLayout(0, 10));
@@ -167,7 +167,7 @@ public class PluginsPanel extends JPanel
{
List<String> repositories = new ArrayList<>();
repositories.add("All");
for (UpdateRepository updateRepository : this.updateManager.getRepositories())
for (OPRSUpdateRepository updateRepository : this.updateManager.getRepositories())
{
repositories.add(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", ""));
}
@@ -366,7 +366,7 @@ public class PluginsPanel extends JPanel
{
boolean filtered = true;
String filter = String.valueOf(filterComboBox.getSelectedItem());
for (UpdateRepository updateRepository : updateManager.getRepositories())
for (OPRSUpdateRepository updateRepository : updateManager.getRepositories())
{
if (filter.equals(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", "")) &&
pluginInfo.getRepositoryId().equals(updateRepository.getId()))
@@ -424,7 +424,7 @@ public class PluginsPanel extends JPanel
{
boolean filtered = true;
String filter = String.valueOf(filterComboBox.getSelectedItem());
for (UpdateRepository updateRepository : updateManager.getRepositories())
for (OPRSUpdateRepository updateRepository : updateManager.getRepositories())
{
if (filter.equals(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", "")) &&
pluginInfo.getRepositoryId().equals(updateRepository.getId()))

View File

@@ -16,12 +16,12 @@ import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import net.runelite.client.plugins.OPRSUpdateRepository;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.LinkBrowser;
import org.pf4j.update.PluginInfo;
import org.pf4j.update.UpdateRepository;
public class RepositoryBox extends JPanel
{
@@ -53,7 +53,7 @@ public class RepositoryBox extends JPanel
DISCORD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(discordImg, 0.53f));
}
RepositoryBox(OPRSExternalPluginManager externalPluginManager, UpdateRepository updateRepository)
RepositoryBox(OPRSExternalPluginManager externalPluginManager, OPRSUpdateRepository updateRepository)
{
setLayout(new BorderLayout());
setBackground(ColorScheme.DARKER_GRAY_COLOR);

View File

@@ -10,8 +10,8 @@ import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.OPRSUpdateRepository;
import net.runelite.client.ui.ColorScheme;
import org.pf4j.update.UpdateRepository;
public class RepositoryPanel extends JPanel
{
@@ -45,7 +45,7 @@ public class RepositoryPanel extends JPanel
c.gridy = 0;
c.insets = new Insets(5, 0, 0, 0);
for (UpdateRepository repository : externalPluginManager.getRepositories())
for (OPRSUpdateRepository repository : externalPluginManager.getRepositories())
{
final RepositoryBox p = new RepositoryBox(externalPluginManager, repository);
add(p, c);