Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4744106
WIP dependency manager
sylae Feb 7, 2023
385b099
pull plugin list on startup to get ident <=> siteid conversion
sylae Feb 7, 2023
863efab
clean up dependency view
sylae Feb 7, 2023
196dd69
store directly in the object instead of making a middleman
sylae Feb 7, 2023
094ec9d
better formatting
sylae Feb 7, 2023
be91ba8
make it more accessible
sylae Feb 7, 2023
37a5eae
make the legend suck less
sylae Feb 7, 2023
b5c9c58
refactor dependency code to make it less fucking miserable
sylae Feb 8, 2023
e4a5c20
dont do leaf, its hiding THE PROBLEM
sylae Feb 8, 2023
1d08bf9
why do i keep doing this
sylae Feb 8, 2023
6333a5a
nicer formatting, only show plugins with dependencies
sylae Feb 8, 2023
092662b
openplanet doesnt need to parse an infinite chain of color codes, act…
sylae Feb 8, 2023
f238ea5
pretty up the tab color
sylae Feb 8, 2023
a967f0f
formatting
sylae Feb 8, 2023
3cd5fed
i hate IDs i hate IDs
sylae Feb 8, 2023
ca56d82
Merge branch 'master' into dependency-helper
sylae Feb 8, 2023
8f49d59
differentiate top-level and bundled plugins
sylae Feb 8, 2023
0539887
Merge remote-tracking branch 'upstream/master' into dependency-helper
sylae Feb 8, 2023
53255f3
formatting
sylae Feb 8, 2023
bef7df6
lose the v
sylae Feb 8, 2023
f101cee
whitespace
sylae Feb 8, 2023
0870562
missing dependency helper funcs
sylae Feb 8, 2023
1823755
make DependencyManager its own window rather than a tab
sylae Feb 8, 2023
2f6a342
Merge remote-tracking branch 'upstream/master' into dependency-helper
sylae Jun 11, 2023
bb79aec
use better website api
sylae Jun 11, 2023
18b8b47
show deps on plugin tab
sylae Jun 11, 2023
2cc69ee
install required deps alongside plugin
sylae Jun 11, 2023
b77577e
remove dep auditor stuff
sylae Jun 11, 2023
c50c2bc
move getCachedPluginInfo to API ns
sylae Jun 11, 2023
9a036db
install missing deps on update
sylae Jun 11, 2023
458d0bd
remove unused setting
sylae Jun 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions src/Interface/Tabs/Plugin.as
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class PluginTab : Tab
{
Net::HttpRequest@ m_requestMain;
Net::HttpRequest@ m_requestChangelog;
Net::HttpRequest@ m_requestDependencies;

bool m_error = false;
string m_errorMessage;
Expand Down Expand Up @@ -61,6 +62,15 @@ class PluginTab : Tab
}
}

void CheckRequestDependencies()
{
// If there's a request, check if it has finished
if (m_requestDependencies !is null && m_requestDependencies.Finished()) {
API::GetPluginListPost(m_requestDependencies);
@m_requestDependencies = null;
}
}

void CheckRequestChangelog()
{
// If there's a request, check if it has finished
Expand Down Expand Up @@ -88,6 +98,10 @@ class PluginTab : Tab
void HandleResponse(const Json::Value &in js)
{
@m_plugin = PluginInfo(js);
string[] missingDeps = m_plugin.GetMissingDeps();
if (missingDeps.Length > 0) {
@m_requestDependencies = API::GetPluginList(missingDeps);
}
}

void HandleErrorResponse(const string &in message, int code)
Expand Down Expand Up @@ -121,15 +135,43 @@ class PluginTab : Tab
return true;
}

bool HasMissingRequirements()
{
if (m_plugin.m_dep_req.Length == 0) return false;

for (uint i = 0; i < m_plugin.m_dep_req.Length; i++) {
auto plug = Meta::GetPluginFromID(m_plugin.m_dep_req[i]);
if (plug is null) return true;
}
return false;
}

void InstallAsync()
{
m_updating = true;

// install any required dependents first
string[] missingDeps = m_plugin.GetMissingDeps();
for (uint i = 0; i < missingDeps.Length; i++) {
PluginInfo@ dep = API::getCachedPluginInfo(missingDeps[i]);

if (dep is null) {
error("Unable to find required plugin info: " + missingDeps[i]);
continue;
}

PluginInstallAsync(dep.m_siteID, dep.m_id, dep.m_version);
}

PluginInstallAsync(m_plugin.m_siteID, m_plugin.m_id, m_plugin.m_version);

m_plugin.m_downloads++;
m_plugin.CheckIfInstalled();
m_updating = false;

if (missingDeps.Length > 0) {
@m_requestDependencies = API::GetPluginList(missingDeps);
}
}

void UpdateAsync()
Expand Down Expand Up @@ -195,6 +237,11 @@ class PluginTab : Tab
if (UI::GreenButton(Icons::Download + " Install")) {
startnew(CoroutineFunc(InstallAsync));
}
if (UI::IsItemHovered() && HasMissingRequirements()) {
UI::BeginTooltip();
UI::Text("Note: this will also install any missing required dependencies listed below.");
UI::EndTooltip();
}
return;
}

Expand All @@ -212,12 +259,58 @@ class PluginTab : Tab
}
}

void RenderDependency(const string &in dep)
{
// is the plugin installed?
auto plug = Meta::GetPluginFromID(dep);
if (plug !is null) {
if (plug.Source == Meta::PluginSource::ApplicationFolder) { // openplanet bundled
UI::Text("\\$f39" + Icons::Heartbeat + "\\$z" + plug.Name + " \\$666(built-in)");
} else {
UI::Text(plug.Name + " \\$666(installed)");
if (UI::IsItemClicked()) {
g_window.AddTab(PluginTab(plug.SiteID), true);
}
if (UI::IsItemHovered()) {
UI::SetMouseCursor(UI::MouseCursor::Hand);
UI::BeginTooltip();
UI::Text(plug.Name + " \\$999by " + plug.Author + " \\$666(" + plug.Version + " installed)");
UI::Text("Click to open this plugin in a new tab.");
UI::EndTooltip();
}
}
} else {
// plugin not installed, let's see what info we have on it...
PluginInfo@ x = API::getCachedPluginInfo(dep);
if (x !is null) {
// not installed but we have info
UI::Text("\\$999"+x.m_name);
if (UI::IsItemClicked()) {
g_window.AddTab(PluginTab(x.m_siteID), true);
}
if (UI::IsItemHovered()) {
UI::SetMouseCursor(UI::MouseCursor::Hand);
UI::BeginTooltip();
UI::Text(x.m_name + " \\$999by " + x.m_author);
UI::Text("Click to open this plugin in a new tab.");
UI::EndTooltip();
}

} else {
// no fukken clue
UI::Text("Unknown plugin '"+dep+"'");
}

}
}

void Render() override
{
float scale = UI::GetScale();

CheckRequestMain();
CheckRequestChangelog();
CheckRequestDependencies();

if (m_requestMain !is null) {
UI::Text("Loading plugin..");
Expand Down Expand Up @@ -271,6 +364,36 @@ class PluginTab : Tab
OpenBrowserURL(m_plugin.m_donateURL);
}

if (m_plugin.m_dep_req.Length + m_plugin.m_dep_opt.Length > 0) {
UI::Separator();
if (m_plugin.m_dep_req.Length > 0) {
if (UI::TreeNode("Required dependencies:", UI::TreeNodeFlags::DefaultOpen)) {
if (UI::IsItemHovered()) {
UI::BeginTooltip();
UI::Text("This plugin will not work without all of these plugins installed");
UI::EndTooltip();
}
for (uint i = 0; i < m_plugin.m_dep_req.Length; i++) {
RenderDependency(m_plugin.m_dep_req[i]);
}
UI::TreePop();
}
}
if (m_plugin.m_dep_opt.Length > 0) {
if (UI::TreeNode("Optional dependencies:", UI::TreeNodeFlags::DefaultOpen)) {
if (UI::IsItemHovered()) {
UI::BeginTooltip();
UI::Text("This plugin provides enhanced functionality if these plugins are installed");
UI::EndTooltip();
}
for (uint i = 0; i < m_plugin.m_dep_opt.Length; i++) {
RenderDependency(m_plugin.m_dep_opt[i]);
}
UI::TreePop();
}
}
}

UI::EndChild();

// Right side of the window
Expand Down
12 changes: 12 additions & 0 deletions src/Update.as
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ void PluginUpdateAsync(ref@ update)
return;
}

// install any unmet dependencies
for (uint i = 0; i < au.m_requirements.Length; i++) {
auto plug = Meta::GetPluginFromID(au.m_requirements[i]);
if (plug is null) {
PluginInfo@ dep = API::getCachedPluginInfo(au.m_requirements[i]);
if (dep is null) {
error("Unable to find required plugin info: " + au.m_requirements[i]);
continue;
}
PluginInstallAsync(dep.m_siteID, dep.m_id, dep.m_version);
}
}
// If the plugin is currently loaded
auto installedPlugin = Meta::GetPluginFromSiteID(au.m_siteID);
if (installedPlugin !is null) {
Expand Down
28 changes: 28 additions & 0 deletions src/UpdateCheck.as
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ class AvailableUpdate
string m_identifier;
string m_oldVersion;
string m_newVersion;
string[] m_requirements;

bool HasMissingRequirements()
{
if (m_requirements.Length == 0) return false;

for (uint i = 0; i < m_requirements.Length; i++) {
auto plug = Meta::GetPluginFromID(m_requirements[i]);
if (plug is null) return true;
}
return false;
}
}

array<AvailableUpdate@> g_availableUpdates;
Expand Down Expand Up @@ -65,6 +77,8 @@ void CheckForUpdatesAsync()
return;
}

string[] needDepInfo;

// Go through returned list of versions
for (uint i = 0; i < js.Length; i++) {
auto jsVersion = js[i];
Expand Down Expand Up @@ -97,9 +111,23 @@ void CheckForUpdatesAsync()
au.m_identifier = siteIdentifier;
au.m_oldVersion = info.m_version.ToString();
au.m_newVersion = siteVersion;

if (jsVersion["required_dependencies"] == Json::Type::Array) {
for (uint d = 0; d < jsVersion["required_dependencies"].Length; d++) {
au.m_requirements.InsertLast(jsVersion["required_dependencies"][d]);
if (API::getCachedPluginInfo(jsVersion["required_dependencies"][d]) is null) {
needDepInfo.InsertLast(jsVersion["required_dependencies"][d]);
}
}
}

g_availableUpdates.InsertLast(au);
}

if (needDepInfo.Length > 0) {
API::GetPluginListAsync(needDepInfo);
}

if (g_availableUpdates.Length == 0) {
trace("No plugin updates found!");
}
Expand Down
74 changes: 74 additions & 0 deletions src/Utils/API.as
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,78 @@ namespace API
}
return Json::Parse(req.String());
}

void GetPluginListAsync(string[] missing)
{
uint pages = 1;

string fetchMissing = string::Join(missing, ',');
if (fetchMissing.Length > 0) {
for (uint i = 0; i < pages; i++) {
Json::Value req = GetAsync("plugins?idents=" + fetchMissing + "&page=" + i);

if (pages == 1 && req["pages"] != 1) {
pages = req["pages"];
}

for (uint ii = 0; ii < req["items"].Length; ii++) {
// kill any existing values
for (uint iii = 0; iii < g_cachedAPIPluginList.Length; iii++) { // how deep can we go
if (string(g_cachedAPIPluginList[iii]['identifier']) == string(req["items"][ii]['identifier'])) {
g_cachedAPIPluginList.RemoveAt(iii);
}
}

g_cachedAPIPluginList.InsertLast(req["items"][ii]);
}

// nap a bit so we dont wreck the Openplanet API...
sleep(500);
}
}
}

/**
* special version of GetPluginListAsync for use in Render contexts
*
* only supports a single page, but its only use case is in PluginTab
* and if there's enough deps to cause pagination you can fuck right off.
*/
Net::HttpRequest@ GetPluginList(string[] missing)
{
string fetchMissing = string::Join(missing, ',');
Net::HttpRequest@ req = Get("plugins?idents=" + fetchMissing);
return req;
}

void GetPluginListPost(Net::HttpRequest@ request)
{
Json::Value req = Json::Parse(request.String());
for (uint ii = 0; ii < req["items"].Length; ii++) {
// kill any existing values
for (uint iii = 0; iii < g_cachedAPIPluginList.Length; iii++) { // how deep can we go
if (string(g_cachedAPIPluginList[iii]['identifier']) == string(req["items"][ii]['identifier'])) {
g_cachedAPIPluginList.RemoveAt(iii);
}
}

g_cachedAPIPluginList.InsertLast(req["items"][ii]);
}
}

PluginInfo@ getCachedPluginInfo(const string &in ident)
{
Json::Value@ js;
for (uint i = 0; i < g_cachedAPIPluginList.Length; i++) {
if (string(g_cachedAPIPluginList[i]['identifier']).ToLower() == ident.ToLower()) {
@js = g_cachedAPIPluginList[i];
}
}
if (js !is null) {
// not installed but we have info
return PluginInfo(js);
} else {
return null;
}
}
}
Loading