Skip to content

fix(plugins): give installed plugins the same enable toggle as bundled ones - #184

Merged
kipavy merged 1 commit into
devfrom
fix/plugin-toggle-consistency
Aug 26, 2026
Merged

fix(plugins): give installed plugins the same enable toggle as bundled ones#184
kipavy merged 1 commit into
devfrom
fix/plugin-toggle-consistency

Conversation

@kipavy

@kipavy kipavy commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

The bug

Whether a plugin could be disabled depended on how it reached the disk, not on what it is.

The Installed tab builds its first list from seededPluginManifests(externalPluginIds), which despite the name returns every loaded plugin that isn't in installedMeta — i.e. the app-bundled ones. Only those rows rendered a <Toggle>. Rows built from installedMeta — anything installed from a catalogue, a URL, or a local scan — rendered Update / Reload / Uninstall and no toggle.

Consequences:

  • Installing a first-party plugin from Browse instead of using the bundled copy moved its id into installedMeta, so loadSeededPlugins then skipped it and it appeared in the external list — the same plugin, silently losing the toggle it had while bundled.
  • Themes, which are only ever installed, never had one at all.

The fix

The rule becomes a property of the plugin rather than of its provenance, in one place both row types call:

function EnableToggle({ manifest, enabled, onToggle }) {
  const themeOnly = manifest.permissions.length === 1 && manifest.permissions[0] === "themes";
  if (themeOnly) return null;
  return <Toggle checked={enabled} onChange={() => onToggle(manifest.id, enabled)} />;
}

A theme-only plugin contributes nothing but themes, so "disabled" and "not installed" would mean the same thing to the user — it stays installed-or-not, which is the behaviour that was already there and worth keeping. Everything else can be turned off without losing it, bundled or installed.

Installed rows compute enabled as isLoaded && isEnabled(meta.id, true), mirroring externalPluginActive from #181, and now dim when disabled the way bundled rows already did.

Tests

PluginsSection.enableToggle.test.tsx — five tests covering the matrix (non-theme installed / non-theme bundled / theme installed / theme bundled) plus one that the toggle actually deactivates the plugin and persists the override.

Written first; three failed for the expected reasons: installed non-theme had no toggle, bundled theme had one it shouldn't, and there was nothing to click. 16 tests across the three PluginsSection files pass now, tsc --noEmit clean.

Live verification

In the headless container on this branch, both installed from the live catalogue:

Installed row Toggle
SSH Config Sync yes
Emerald Night no

Toggling SSH Config Sync off flips aria-checked to false, dims the row to opacity: 0.7, and survives a restart — the override persists and #181's boot path honours it. Toggling back on restores it.

Negative control: reverting just this commit's change to PluginsSection.tsx in the same running build drops SSH Config Sync's toggle count from 1 to 0; restoring brings it back.

Note

seededPluginManifests is misleadingly named — it returns loaded-minus-installed, not "seeded". It misled me into an incorrect claim earlier in this work. Renaming it is not in this PR, but it should probably be unmanagedPluginManifests or similar.

…d ones

Whether a plugin could be disabled depended on how it reached the disk, not
on what it is. The toggle rendered only on rows built from getLoadedPlugins()
minus installedMeta — bundled first-party plugins — so installing that same
plugin from the catalogue moved it to the external list and it lost the
control. Themes, which are only ever installed, therefore never had one.

The rule is now a property of the plugin: a theme-only plugin contributes
nothing but themes, so disabled and not-installed would mean the same thing
and it gets no toggle; everything else gets one, bundled or installed. Both
row types render the same EnableToggle so the two cannot drift apart.

Installed rows now also dim when disabled, matching the bundled rows.
@kipavy
kipavy merged commit 14d8939 into dev Aug 26, 2026
4 checks passed
@kipavy
kipavy deleted the fix/plugin-toggle-consistency branch August 26, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant