fix(plugins): harden marketplace loading
Use public GitHub metadata to avoid unauthenticated API limits. Read bundled manifests before enabling installs and surface startup load failures.
This commit is contained in:
parent
5116369dec
commit
64d109a614
7 changed files with 203 additions and 41 deletions
|
|
@ -523,6 +523,9 @@ pub(super) struct OpenCADStudio {
|
|||
/// `external_plugins` — compatible, with a library, dlopen'd at startup).
|
||||
#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
|
||||
loaded_plugin_ids: rustc_hash::FxHashSet<String>,
|
||||
/// Startup load failures keyed by plugin id. The Plugin Manager uses these
|
||||
/// to distinguish an installed-but-failed package from one awaiting restart.
|
||||
plugin_load_errors: rustc_hash::FxHashMap<String, String>,
|
||||
/// Curated plugin registry fetched from the OpenCADStudio repo.
|
||||
plugin_registry: Vec<crate::plugin::external::RegistryEntry>,
|
||||
/// True while the curated registry request is in flight.
|
||||
|
|
@ -540,7 +543,8 @@ pub(super) struct OpenCADStudio {
|
|||
/// Live filter for installed and available plugin cards.
|
||||
plugin_search_input: String,
|
||||
/// Installable release tags fetched per linked repo (for the dropdown).
|
||||
repo_release_tags: rustc_hash::FxHashMap<String, Vec<String>>,
|
||||
repo_release_tags:
|
||||
rustc_hash::FxHashMap<String, Vec<crate::plugin::external::ReleaseInfo>>,
|
||||
/// The release tag currently selected per linked repo.
|
||||
repo_selected_tag: rustc_hash::FxHashMap<String, String>,
|
||||
/// Repository currently shown in the Plugin Manager detail pane.
|
||||
|
|
@ -2174,8 +2178,11 @@ pub enum Message {
|
|||
RecentThumbsLoaded(
|
||||
Vec<(std::path::PathBuf, Option<iced::widget::image::Handle>)>,
|
||||
),
|
||||
/// Installable release tags fetched for `owner/repo`.
|
||||
PluginReleasesFetched(String, Result<Vec<String>, String>),
|
||||
/// Installable releases and manifest API versions fetched for `owner/repo`.
|
||||
PluginReleasesFetched(
|
||||
String,
|
||||
Result<Vec<crate::plugin::external::ReleaseInfo>, String>,
|
||||
),
|
||||
/// Choose a release tag for a repo (`repo`, `tag`).
|
||||
PluginReleaseSelect(String, String),
|
||||
/// Select a plugin source and show its GitHub README in the detail pane.
|
||||
|
|
@ -2696,6 +2703,7 @@ impl OpenCADStudio {
|
|||
disabled_plugins: rustc_hash::FxHashSet::default(),
|
||||
external_plugins: Vec::new(),
|
||||
loaded_plugin_ids: rustc_hash::FxHashSet::default(),
|
||||
plugin_load_errors: rustc_hash::FxHashMap::default(),
|
||||
plugin_registry: Vec::new(),
|
||||
plugin_registry_loading: false,
|
||||
plugin_registry_error: None,
|
||||
|
|
@ -2934,6 +2942,7 @@ impl OpenCADStudio {
|
|||
if let Err(e) = res {
|
||||
app.command_line
|
||||
.push_error(&format!("Plugin '{id}' failed to load: {e}"));
|
||||
app.plugin_load_errors.insert(id, e);
|
||||
}
|
||||
}
|
||||
app.loaded_plugin_ids = crate::plugin::external::loaded_ids().into_iter().collect();
|
||||
|
|
|
|||
|
|
@ -273,19 +273,13 @@ impl OpenCADStudio {
|
|||
)
|
||||
}
|
||||
|
||||
/// Background task: fetch `owner/repo`'s installable release tags.
|
||||
/// Background task: fetch `owner/repo`'s installable releases and their
|
||||
/// manifest API versions.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(in crate::app) fn fetch_releases_task(&self, repo: String) -> Task<Message> {
|
||||
let label = repo.clone();
|
||||
Task::perform(
|
||||
async move {
|
||||
crate::plugin::marketplace::fetch_releases(&repo).map(|rs| {
|
||||
rs.into_iter()
|
||||
.filter(|r| r.installable())
|
||||
.map(|r| r.tag)
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
},
|
||||
async move { crate::plugin::marketplace::fetch_release_info(&repo) },
|
||||
move |res| Message::PluginReleasesFetched(label, res),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4699,17 +4699,20 @@ impl OpenCADStudio {
|
|||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::PluginReleasesFetched(repo, Ok(tags)) => {
|
||||
if let Some(first) = tags.first() {
|
||||
Message::PluginReleasesFetched(repo, Ok(releases)) => {
|
||||
if let Some(first) = releases.first() {
|
||||
self.repo_selected_tag
|
||||
.entry(repo.clone())
|
||||
.or_insert_with(|| first.clone());
|
||||
.or_insert_with(|| first.tag.clone());
|
||||
}
|
||||
if self.marketplace_status == format!("Fetching releases for {repo}…") {
|
||||
self.marketplace_status =
|
||||
format!("Repository added. {} installable release(s) found.", tags.len());
|
||||
format!(
|
||||
"Repository added. {} installable release(s) found.",
|
||||
releases.len()
|
||||
);
|
||||
}
|
||||
self.repo_release_tags.insert(repo, tags);
|
||||
self.repo_release_tags.insert(repo, releases);
|
||||
Task::none()
|
||||
}
|
||||
Message::PluginReleasesFetched(repo, Err(e)) => {
|
||||
|
|
@ -4754,6 +4757,7 @@ impl OpenCADStudio {
|
|||
}
|
||||
Message::PluginInstalled(Ok(id)) => {
|
||||
self.marketplace_status = format!("Installed '{id}'. Restart to load it.");
|
||||
self.plugin_load_errors.remove(&id);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
self.external_plugins = crate::plugin::external::discover();
|
||||
|
|
@ -4771,6 +4775,7 @@ impl OpenCADStudio {
|
|||
Ok(()) => {
|
||||
self.marketplace_status =
|
||||
format!("Uninstalled '{id}'. Restart to unload it.");
|
||||
self.plugin_load_errors.remove(&id);
|
||||
self.external_plugins = crate::plugin::external::discover();
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ impl OpenCADStudio {
|
|||
&self.disabled_plugins,
|
||||
&self.external_plugins,
|
||||
&self.loaded_plugin_ids,
|
||||
&self.plugin_load_errors,
|
||||
crate::ui::window::plugin_manager::MarketView {
|
||||
registry: &self.plugin_registry,
|
||||
registry_loading: self.plugin_registry_loading,
|
||||
|
|
|
|||
Loading…
Reference in a new issue