feat(plugin): marketplace — install plugins from a curated registry
Add a Plugin Manager marketplace that installs external add-ons from a GitHub repo's Releases. A curated registry (plugins/registry.json in this repo, extended by PR) lists discoverable plugins; the host fetches it, shows each entry with a release dropdown, and on install downloads the asset matching the user's platform plus plugin.toml into the plugins folder (API-version checked first). Users can also link arbitrary owner/repo manually. Linked repos persist in settings. Desktop only (ureq + serde_json); the install path reuses the phase-2 loader. Part of the #100 extensibility epic (phase 2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
29c71be101
commit
020a3a4c84
12 changed files with 599 additions and 5 deletions
|
|
@ -78,6 +78,9 @@ pub struct UserSettings {
|
|||
/// plugins keep their manifest listed but drop their ribbon tab and command
|
||||
/// dispatch.
|
||||
pub disabled_plugins: Vec<String>,
|
||||
/// Linked plugin source repositories (`owner/repo`) the marketplace installs
|
||||
/// from.
|
||||
pub plugin_repos: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for UserSettings {
|
||||
|
|
@ -101,6 +104,7 @@ impl Default for UserSettings {
|
|||
],
|
||||
default_assoc_prompted: false,
|
||||
disabled_plugins: Vec::new(),
|
||||
plugin_repos: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -143,6 +147,14 @@ impl UserSettings {
|
|||
.map(|t| t.to_string())
|
||||
.collect();
|
||||
}
|
||||
"plugin_repos" => {
|
||||
s.plugin_repos = val
|
||||
.split(',')
|
||||
.map(|t| t.trim())
|
||||
.filter(|t| !t.is_empty())
|
||||
.map(|t| t.to_string())
|
||||
.collect();
|
||||
}
|
||||
"snap_modes" => {
|
||||
let modes: Vec<SnapType> =
|
||||
val.split(',').filter_map(|t| snap_from_id(t.trim())).collect();
|
||||
|
|
@ -168,7 +180,7 @@ impl UserSettings {
|
|||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
let body = format!(
|
||||
"dyn={}\northo={}\npolar={}\npolar_increment_deg={}\ngrid={}\nosnap={}\notrack={}\ndefault_assoc_prompted={}\nsnap_modes={}\ndisabled_plugins={}\n",
|
||||
"dyn={}\northo={}\npolar={}\npolar_increment_deg={}\ngrid={}\nosnap={}\notrack={}\ndefault_assoc_prompted={}\nsnap_modes={}\ndisabled_plugins={}\nplugin_repos={}\n",
|
||||
b(self.dyn_input),
|
||||
b(self.ortho),
|
||||
b(self.polar),
|
||||
|
|
@ -179,6 +191,7 @@ impl UserSettings {
|
|||
b(self.default_assoc_prompted),
|
||||
modes,
|
||||
self.disabled_plugins.join(","),
|
||||
self.plugin_repos.join(","),
|
||||
);
|
||||
let _ = std::fs::write(path, body);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue