forked from 1b-agent/opencadstudio-upstream
feat(plugin): enable/disable plugins from the Plugin Manager
The manager was a read-only inventory. Each plugin now has an Enable/Disable toggle: a disabled plugin keeps its manifest listed but drops its ribbon tab and command dispatch. The disabled-id set persists in settings.txt (disabled_plugins=) and the ribbon rebuilds on toggle. Part of the #100 extensibility epic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
195415af84
commit
844069b4ef
9 files changed
+157
-23
No files matched your search
+1
-1
@@ -8,6 +8,6 @@ pub mod host;
|
||||
pub mod manifest;
|
||||
pub mod registry;
|
||||
|
||||
pub use registry::all_ribbon_modules;
|
||||
pub use registry::{all_ribbon_modules, ribbon_modules_enabled};
|
||||
pub(crate) use host::BuiltinPlugin;
|
||||
pub(crate) use registry::{installed_manifests, try_dispatch};
|
||||
+32
-2
@@ -28,11 +28,20 @@ pub fn installed_manifests() -> Vec<&'static PluginManifest> {
|
||||
manifests
|
||||
}
|
||||
|
||||
/// Core ribbon tabs plus add-on tabs (sorted by `manifest.ribbon_order`).
|
||||
/// Core ribbon tabs plus *every* add-on tab (sorted by `manifest.ribbon_order`).
|
||||
pub fn all_ribbon_modules() -> Vec<Box<dyn CadModule>> {
|
||||
ribbon_modules_enabled(&rustc_hash::FxHashSet::default())
|
||||
}
|
||||
|
||||
/// Core ribbon tabs plus add-on tabs whose plugin id is **not** in `disabled`
|
||||
/// (sorted by `manifest.ribbon_order`). Used by the Plugin Manager toggle.
|
||||
pub fn ribbon_modules_enabled(
|
||||
disabled: &rustc_hash::FxHashSet<String>,
|
||||
) -> Vec<Box<dyn CadModule>> {
|
||||
let mut core = core_registry::all_modules();
|
||||
let mut addons: Vec<(i32, Box<dyn CadModule>)> = all_plugins()
|
||||
.into_iter()
|
||||
.filter(|p| !disabled.contains(p.manifest().id))
|
||||
.map(|p| (p.manifest().ribbon_order, p.ribbon()))
|
||||
.collect();
|
||||
addons.sort_by_key(|(order, _)| *order);
|
||||
@@ -40,10 +49,15 @@ pub fn all_ribbon_modules() -> Vec<Box<dyn CadModule>> {
|
||||
core
|
||||
}
|
||||
|
||||
/// Try each plugin until one handles `cmd`. Returns true if handled.
|
||||
/// Try each *enabled* plugin until one handles `cmd`. Returns true if handled.
|
||||
/// Disabled plugins (toggled off in the Plugin Manager) are skipped.
|
||||
pub(crate) fn try_dispatch(app: &mut OpenCADStudio, tab: usize, cmd: &str) -> bool {
|
||||
let disabled = app.disabled_plugin_ids();
|
||||
let mut host = HostSession::new(app, tab);
|
||||
for plugin in all_plugins() {
|
||||
if disabled.contains(plugin.manifest().id) {
|
||||
continue;
|
||||
}
|
||||
if plugin.dispatch(&mut host, cmd) {
|
||||
return true;
|
||||
}
|
||||
@@ -98,6 +112,22 @@ mod tests {
|
||||
assert_eq!(titles.len(), core.len() + all_plugins().len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disabled_plugin_drops_its_ribbon_tab() {
|
||||
let mut disabled = rustc_hash::FxHashSet::default();
|
||||
disabled.insert("opencad.demo_plugin".to_string());
|
||||
let titles: Vec<&str> = ribbon_modules_enabled(&disabled)
|
||||
.iter()
|
||||
.map(|m| m.title())
|
||||
.collect();
|
||||
assert!(
|
||||
!titles.contains(&"Demo Plugin"),
|
||||
"disabled plugin still present: {titles:?}"
|
||||
);
|
||||
// Only the add-on tab is dropped; core tabs stay.
|
||||
assert_eq!(titles.len(), core_registry::all_modules().len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_dispatch_routes_demo_command() {
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
|
||||
Reference in new issue
Block a user