1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-08 12:13:31 -04:00

plugins: add support for composite plugins

- single plugin can register multiple types - e.g. daemon, bar widget,
  desktop widget
This commit is contained in:
bbedward
2026-06-05 10:33:34 -04:00
parent d3c23ba737
commit bcb5617194
10 changed files with 859 additions and 64 deletions
+74
View File
@@ -1635,6 +1635,79 @@ See `PLUGINS/ExampleDesktopClock/` for a complete working example demonstrating:
- Responsive sizing
- Edit mode handling
## Composite Plugins
A single plugin can provide **multiple surfaces at once** — for example a background
daemon (for IPC / monitoring), a bar widget, and a desktop widget. Because each surface
has a different lifecycle (the daemon is instantiated once; bar and desktop widgets are
instantiated per bar/placement per screen), each surface is its own QML file.
### Plugin Type Configuration
Instead of a single `type` + `component`, declare a `components` map. Set `type` to
`composite` (any value works; `composite` is conventional):
```json
{
"id": "myComposite",
"name": "My Composite Plugin",
"description": "A daemon plus a bar widget plus a desktop widget",
"version": "1.0.0",
"author": "Your Name",
"type": "composite",
"capabilities": ["daemon", "dankbar-widget", "desktop-widget"],
"components": {
"daemon": "./MyDaemon.qml",
"widget": "./MyBarWidget.qml",
"desktop": "./MyDesktopWidget.qml",
"launcher": "./MyLauncher.qml"
},
"trigger": "#",
"settings": "./MySettings.qml",
"requires_dms": ">=1.5.0",
"permissions": ["settings_read", "settings_write"]
}
```
### Surfaces
Provide any subset of these keys in `components`:
| Surface | Component contract | Notes |
|---------|--------------------|-------|
| `widget` | `PluginComponent` (bar pills + optional Control Center widget) | see [Widget Component](#widget-component) |
| `desktop` | `DesktopPluginComponent` (or an `Item` following the desktop contract) | see [Desktop Plugins](#desktop-plugins) |
| `daemon` | any `Item` exposing `pluginService` / `pluginId` | instantiated once; ideal for IPC handlers and background monitoring |
| `launcher` | launcher contract (`getItems` / `executeItem`) | requires `trigger` (or empty-trigger mode); see [Launcher Plugins](#launcher-plugins) |
Each surface is loaded independently into its own registry, so the same plugin can show
up in the bar **and** on the desktop **and** run a daemon simultaneously.
### Shared State
Each surface is a separate object, so share runtime state through:
- `PluginService.getGlobalVar(pluginId, name, default)` / `setGlobalVar(...)` — reactive,
in-process, namespaced per plugin (see [Plugin Global Variables](#plugin-global-variables)).
- The daemon instance — register `IpcHandler`s or expose data other surfaces read via
global vars.
- `savePluginData` / `loadPluginData` for persisted settings (all surfaces of a plugin
share one settings namespace, so one `settings` component configures them all).
### Settings, Enabling, and Backwards Compatibility
- Declare a single top-level `settings` component; it configures every surface.
- Composite plugins respect the **enable toggle** in Settings → Plugins (they are not
auto-loaded). A pure `desktop` plugin still auto-loads for backwards compatibility.
- The legacy single `type` + `component` form is unchanged and fully supported — it is
treated internally as a one-entry `components` map.
### Example Plugin
See `PLUGINS/ExampleCompositePlugin/` for a working composite that combines the
WallpaperWatcher daemon, the Emoji Cycler bar widget, and the Desktop Clock into one
plugin.
## Resources
- **Plugin Schema**: `plugin-schema.json` - JSON Schema for validation
@@ -1644,6 +1717,7 @@ See `PLUGINS/ExampleDesktopClock/` for a complete working example demonstrating:
- [LauncherExample](./LauncherExample/)
- [Calculator](https://github.com/rochacbruno/DankCalculator)
- [Desktop Clock](./ExampleDesktopClock/)
- [Composite Example](./ExampleCompositePlugin/)
- **PluginService**: `Services/PluginService.qml`
- **Settings UI**: `Modules/Settings/PluginsTab.qml`
- **DankBar Integration**: `Modules/DankBar/DankBar.qml`