diff --git a/resources/web/dialog/PluginsDialog/index.js b/resources/web/dialog/PluginsDialog/index.js index ad1242e4f9..af2d81639e 100644 --- a/resources/web/dialog/PluginsDialog/index.js +++ b/resources/web/dialog/PluginsDialog/index.js @@ -1347,6 +1347,8 @@ function StatusDescription(plugin) { return "This plugin is still loading."; case "Error": return "This plugin is blocked until its error is fixed."; + case "RuntimeError": + return "This plugin is loaded but a capability reported an error."; case "Inactive": default: return "This plugin is inactive. Activate it to install or load it."; diff --git a/resources/web/dialog/PluginsDialog/styles.css b/resources/web/dialog/PluginsDialog/styles.css index 3d8c18be9e..9eef78760d 100644 --- a/resources/web/dialog/PluginsDialog/styles.css +++ b/resources/web/dialog/PluginsDialog/styles.css @@ -424,6 +424,11 @@ body.pane-resizing { font-weight: 600; } +.status-cell.status-runtimeerror { + color: var(--plugin-status-warn); + font-weight: 600; +} + .status-cell.status-loading { color: var(--plugin-status-warn); font-weight: 600; @@ -680,6 +685,11 @@ body.pane-resizing { color: var(--plugin-status-danger); } +.detail-status-chip.status-runtimeerror { + background: var(--plugin-status-warn-bg); + color: var(--plugin-status-warn); +} + .detail-status-chip.status-loading { background: var(--plugin-status-warn-bg); color: var(--plugin-status-warn); diff --git a/src/slic3r/GUI/PluginStatus.hpp b/src/slic3r/GUI/PluginStatus.hpp index 477e9d99fe..635e35f98a 100644 --- a/src/slic3r/GUI/PluginStatus.hpp +++ b/src/slic3r/GUI/PluginStatus.hpp @@ -11,6 +11,7 @@ namespace Slic3r // IMPORTANT: ordinal order is the Plugins dialog Status sort priority. Activated, Error, + RuntimeError, Inactive, Loading }; @@ -21,11 +22,28 @@ namespace Slic3r { case PluginStatus::Activated: return "Activated"; case PluginStatus::Error: return "Error"; + case PluginStatus::RuntimeError: return "RuntimeError"; case PluginStatus::Inactive: return "Inactive"; case PluginStatus::Loading: return "Loading"; } return "Inactive"; } + + // why: a plugin whose module is live but whose catalog carries an error is a + // RUNTIME fault (e.g. a capability rejected at register time) - it stays + // loaded/checked and is only flagged, distinct from a load-time Error where + // the module never came up. Loading wins over both so an in-flight reload + // never flashes an error. + inline PluginStatus resolve_plugin_status(bool loading, bool has_error, bool is_loaded) + { + if (loading) + return PluginStatus::Loading; + if (has_error) + return is_loaded ? PluginStatus::RuntimeError : PluginStatus::Error; + if (is_loaded) + return PluginStatus::Activated; + return PluginStatus::Inactive; + } } } // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/PluginsDialog.cpp b/src/slic3r/GUI/PluginsDialog.cpp index a39fcbc535..a997bbba3c 100644 --- a/src/slic3r/GUI/PluginsDialog.cpp +++ b/src/slic3r/GUI/PluginsDialog.cpp @@ -380,14 +380,7 @@ PluginDialogItem build_plugin_dialog_item(const PluginDescriptor& descriptor) item.sharing_token = descriptor.sharing_token; item.thumbnail_url = descriptor.thumbnail_url; - if (item.loading) - item.status = PluginStatus::Loading; - else if (item.has_error) - item.status = PluginStatus::Error; - else if (item.is_loaded) - item.status = PluginStatus::Activated; - else - item.status = PluginStatus::Inactive; + item.status = resolve_plugin_status(item.loading, item.has_error, item.is_loaded); item.available_actions = evaluate_action_policy(item); const bool has_enabled_script = std::any_of(item.capabilities.begin(), item.capabilities.end(), @@ -663,6 +656,9 @@ void PluginsDialog::toggle_plugin(const std::string& plugin_key, bool enabled) } BOOST_LOG_TRIVIAL(info) << "Plugin unloaded from Plugins dialog: " << plugin_key; + // A user-disabled plugin has no meaningful error state. + if (!manager.clear_plugin_error(plugin_key)) + BOOST_LOG_TRIVIAL(warning) << "Failed to clear plugin error for " << plugin_key << " (failed to find)"; // A prior activation of this plugin is moot now; drop it so no stale "Activated" arrives later. if (m_activating_plugin_key == plugin_key) m_activating_plugin_key.clear();