mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-30 00:12:50 -05:00
docs: update PLUGIN docs (#443)
This commit is contained in:
committed by
GitHub
parent
5f810fe741
commit
f4a4151632
@@ -4,8 +4,9 @@
|
|||||||
"description": "Example plugin with Control Center detail dropdown",
|
"description": "Example plugin with Control Center detail dropdown",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "DankMaterialShell",
|
"author": "DankMaterialShell",
|
||||||
"icon": "settings",
|
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
"capabilities": ["control-center"],
|
||||||
"component": "./DetailExampleWidget.qml",
|
"component": "./DetailExampleWidget.qml",
|
||||||
|
"icon": "settings",
|
||||||
"permissions": ["settings_read", "settings_write"]
|
"permissions": ["settings_read", "settings_write"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
"description": "Example plugin with Control Center toggle widget",
|
"description": "Example plugin with Control Center toggle widget",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "DankMaterialShell",
|
"author": "DankMaterialShell",
|
||||||
"icon": "toggle_on",
|
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
"capabilities": ["control-center"],
|
||||||
"component": "./ControlCenterExampleWidget.qml",
|
"component": "./ControlCenterExampleWidget.qml",
|
||||||
|
"icon": "toggle_on",
|
||||||
"permissions": ["settings_read", "settings_write"]
|
"permissions": ["settings_read", "settings_write"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,10 @@
|
|||||||
"description": "Display cycling emojis in your bar with a handy emoji picker popout",
|
"description": "Display cycling emojis in your bar with a handy emoji picker popout",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "AvengeMedia",
|
"author": "AvengeMedia",
|
||||||
"icon": "mood",
|
"type": "widget",
|
||||||
|
"capabilities": ["emoji-search", "clipboard", "dankbar-widget"],
|
||||||
"component": "./EmojiWidget.qml",
|
"component": "./EmojiWidget.qml",
|
||||||
|
"icon": "mood",
|
||||||
"settings": "./EmojiSettings.qml",
|
"settings": "./EmojiSettings.qml",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"settings_read",
|
"settings_read",
|
||||||
|
|||||||
@@ -4,8 +4,10 @@
|
|||||||
"description": "Demonstrates dynamic variant creation for plugins",
|
"description": "Demonstrates dynamic variant creation for plugins",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "DMS",
|
"author": "DMS",
|
||||||
"icon": "widgets",
|
"type": "widget",
|
||||||
|
"capabilities": ["multiple-usecases", "variants"],
|
||||||
"component": "./VariantWidget.qml",
|
"component": "./VariantWidget.qml",
|
||||||
|
"icon": "widgets",
|
||||||
"settings": "./VariantSettings.qml",
|
"settings": "./VariantSettings.qml",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"settings_read",
|
"settings_read",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -111,13 +112,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function copyToClipboard(text) {
|
function copyToClipboard(text) {
|
||||||
if (typeof globalThis !== "undefined" && globalThis.clipboard) {
|
Quickshell.execDetached(["sh", "-c", "echo -n '" + text + "' | wl-copy"])
|
||||||
globalThis.clipboard.setText(text)
|
showToast("Copied to clipboard: " + text)
|
||||||
showToast("Copied to clipboard: " + text)
|
|
||||||
} else {
|
|
||||||
console.log("LauncherExample: Would copy to clipboard:", text)
|
|
||||||
showToast("Copy feature not available")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function runScript(command) {
|
function runScript(command) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"author": "DMS Team",
|
"author": "DMS Team",
|
||||||
"icon": "extension",
|
"icon": "extension",
|
||||||
"type": "launcher",
|
"type": "launcher",
|
||||||
"capabilities": ["launcher"],
|
"capabilities": ["clipboard", "command-execution"],
|
||||||
"component": "./LauncherExampleLauncher.qml",
|
"component": "./LauncherExampleLauncher.qml",
|
||||||
"settings": "./LauncherExampleSettings.qml",
|
"settings": "./LauncherExampleSettings.qml",
|
||||||
"trigger": "#",
|
"trigger": "#",
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
"description": "Example widget demonstrating PopoutService usage with pillClickAction",
|
"description": "Example widget demonstrating PopoutService usage with pillClickAction",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "DankMaterialShell",
|
"author": "DankMaterialShell",
|
||||||
"icon": "widgets",
|
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
"capabilities": ["dankbar-widget"],
|
||||||
"component": "./PopoutControlWidget.qml",
|
"component": "./PopoutControlWidget.qml",
|
||||||
|
"icon": "widgets",
|
||||||
"settings": "./PopoutControlSettings.qml",
|
"settings": "./PopoutControlSettings.qml",
|
||||||
"permissions": ["settings_read", "settings_write"]
|
"permissions": ["settings_read", "settings_write"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
Create widgets for DankBar and Control Center using dynamically-loaded QML components.
|
Create widgets for DankBar and Control Center using dynamically-loaded QML components.
|
||||||
|
|
||||||
|
## Plugin Registry
|
||||||
|
|
||||||
|
Browse and discover community plugins at **https://plugins.danklinux.com/**
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Plugins let you add custom widgets to DankBar and Control Center. They're discovered from `~/.config/DankMaterialShell/plugins/` and managed via PluginService.
|
Plugins let you add custom widgets to DankBar and Control Center. They're discovered from `~/.config/DankMaterialShell/plugins/` and managed via PluginService.
|
||||||
@@ -45,7 +49,9 @@ $CONFIGPATH/DankMaterialShell/plugins/YourPlugin/
|
|||||||
|
|
||||||
### Plugin Manifest (plugin.json)
|
### Plugin Manifest (plugin.json)
|
||||||
|
|
||||||
The manifest file defines plugin metadata and configuration:
|
The manifest file defines plugin metadata and configuration.
|
||||||
|
|
||||||
|
**JSON Schema:** See `plugin-schema.json` for the complete specification and validation schema.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -54,9 +60,13 @@ The manifest file defines plugin metadata and configuration:
|
|||||||
"description": "Brief description of what your plugin does",
|
"description": "Brief description of what your plugin does",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Your Name",
|
"author": "Your Name",
|
||||||
"icon": "material_icon_name",
|
"type": "widget",
|
||||||
|
"capabilities": ["thing-my-plugin-does"],
|
||||||
"component": "./YourWidget.qml",
|
"component": "./YourWidget.qml",
|
||||||
|
"icon": "material_icon_name",
|
||||||
"settings": "./YourSettings.qml",
|
"settings": "./YourSettings.qml",
|
||||||
|
"requires_dms": ">=0.1.0",
|
||||||
|
"requires": ["some-system-tool"],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"settings_read",
|
"settings_read",
|
||||||
"settings_write"
|
"settings_write"
|
||||||
@@ -67,15 +77,22 @@ The manifest file defines plugin metadata and configuration:
|
|||||||
**Required Fields:**
|
**Required Fields:**
|
||||||
- `id`: Unique plugin identifier (camelCase, no spaces)
|
- `id`: Unique plugin identifier (camelCase, no spaces)
|
||||||
- `name`: Human-readable plugin name
|
- `name`: Human-readable plugin name
|
||||||
- `component`: Relative path to widget QML file
|
- `description`: Short description of plugin functionality (displayed in UI)
|
||||||
|
- `version`: Semantic version string (e.g., "1.0.0")
|
||||||
|
- `author`: Plugin creator name or email
|
||||||
|
- `type`: Plugin type - "widget", "daemon", or "launcher"
|
||||||
|
- `capabilities`: Array of plugin capabilities (e.g., ["dankbar-widget"], ["control-center"], ["monitoring"])
|
||||||
|
- `component`: Relative path to main QML component file
|
||||||
|
|
||||||
|
**Required for Launcher Type:**
|
||||||
|
- `trigger`: Trigger string for launcher activation (e.g., "=", "#", "!")
|
||||||
|
|
||||||
**Optional Fields:**
|
**Optional Fields:**
|
||||||
- `description`: Short description of plugin functionality (displayed in UI)
|
|
||||||
- `version`: Semantic version string (displayed in UI)
|
|
||||||
- `author`: Plugin creator name (displayed in UI)
|
|
||||||
- `icon`: Material Design icon name (displayed in UI)
|
- `icon`: Material Design icon name (displayed in UI)
|
||||||
- `settings`: Path to settings component (enables settings UI)
|
- `settings`: Path to settings component (enables settings UI)
|
||||||
- `permissions`: Required capabilities (enforced by PluginSettings component)
|
- `requires_dms`: Minimum DMS version requirement (e.g., ">=0.1.18", ">0.1.0")
|
||||||
|
- `requires`: Array of required system tools/dependencies (e.g., ["wl-copy", "curl"])
|
||||||
|
- `permissions`: Required DMS permissions (e.g., ["settings_read", "settings_write"])
|
||||||
|
|
||||||
**Permissions:**
|
**Permissions:**
|
||||||
|
|
||||||
@@ -574,9 +591,12 @@ Create `plugin.json`:
|
|||||||
"description": "A sample plugin",
|
"description": "A sample plugin",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Your Name",
|
"author": "Your Name",
|
||||||
"icon": "extension",
|
"type": "widget",
|
||||||
|
"capabilities": ["my-functionality"],
|
||||||
"component": "./MyWidget.qml",
|
"component": "./MyWidget.qml",
|
||||||
|
"icon": "extension",
|
||||||
"settings": "./MySettings.qml",
|
"settings": "./MySettings.qml",
|
||||||
|
"requires_dms": ">=0.1.0",
|
||||||
"permissions": ["settings_read", "settings_write"]
|
"permissions": ["settings_read", "settings_write"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -709,6 +729,231 @@ Or edit `$CONFIGPATH/quickshell/dms/config.json`:
|
|||||||
8. **Versioning**: Use semantic versioning for updates
|
8. **Versioning**: Use semantic versioning for updates
|
||||||
9. **Dependencies**: Document external library requirements
|
9. **Dependencies**: Document external library requirements
|
||||||
|
|
||||||
|
## Clipboard Access
|
||||||
|
|
||||||
|
Plugins that need to copy text to the clipboard **must** use the Wayland clipboard utility `wl-copy` through Quickshell's `execDetached` function.
|
||||||
|
|
||||||
|
### Correct Method
|
||||||
|
|
||||||
|
Import Quickshell and use `execDetached` with `wl-copy`:
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
Item {
|
||||||
|
function copyToClipboard(text) {
|
||||||
|
Quickshell.execDetached(["sh", "-c", "echo -n '" + text + "' | wl-copy"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Usage
|
||||||
|
|
||||||
|
From the ExampleEmojiPlugin (EmojiWidget.qml:136):
|
||||||
|
|
||||||
|
```qml
|
||||||
|
MouseArea {
|
||||||
|
onClicked: {
|
||||||
|
Quickshell.execDetached(["sh", "-c", "echo -n '" + modelData + "' | wl-copy"])
|
||||||
|
ToastService.showInfo("Copied " + modelData + " to clipboard")
|
||||||
|
popoutColumn.closePopout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Important Notes
|
||||||
|
|
||||||
|
1. **Do NOT** use `globalThis.clipboard` or similar JavaScript APIs - they don't exist in the QML runtime
|
||||||
|
2. **Always** import `Quickshell` at the top of your QML file
|
||||||
|
3. **Use** `echo -n` to prevent adding a trailing newline to the clipboard content
|
||||||
|
4. The `-c` flag for `sh` is required to execute the pipe command properly
|
||||||
|
5. Consider showing a toast notification to confirm the copy action to users
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
This method requires `wl-copy` from the `wl-clipboard` package, which is standard on Wayland systems.
|
||||||
|
|
||||||
|
## Running External Commands
|
||||||
|
|
||||||
|
Plugins that need to execute external commands and capture their output should use the `Proc` singleton, which provides debounced command execution with automatic cleanup.
|
||||||
|
|
||||||
|
### Correct Method
|
||||||
|
|
||||||
|
Import the `Proc` singleton from `qs.Common` and use `runCommand`:
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
|
Item {
|
||||||
|
function fetchData() {
|
||||||
|
Proc.runCommand(
|
||||||
|
"myPlugin.fetchData",
|
||||||
|
["curl", "-s", "https://api.example.com/data"],
|
||||||
|
(stdout, exitCode) => {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
console.log("Success:", stdout)
|
||||||
|
processData(stdout)
|
||||||
|
} else {
|
||||||
|
console.error("Command failed with exit code:", exitCode)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
100
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Function Signature
|
||||||
|
|
||||||
|
```qml
|
||||||
|
Proc.runCommand(id, command, callback, debounceMs)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `id` (string): Unique identifier for this command. Used for debouncing - multiple calls with the same ID within the debounce window will only execute the last one
|
||||||
|
- `command` (array): Command and arguments as an array (e.g., `["sh", "-c", "echo hello"]`)
|
||||||
|
- `callback` (function): Callback function receiving `(stdout, exitCode)` when the command completes
|
||||||
|
- `stdout` (string): Captured standard output from the command
|
||||||
|
- `exitCode` (number): Exit code of the process (0 typically means success)
|
||||||
|
- `debounceMs` (number, optional): Debounce delay in milliseconds. Defaults to 50ms if not specified
|
||||||
|
|
||||||
|
### Key Features
|
||||||
|
|
||||||
|
1. **Automatic Cleanup**: Process objects are automatically destroyed after completion
|
||||||
|
2. **Debouncing**: Rapid successive calls with the same ID are debounced, only executing the last one
|
||||||
|
3. **Output Capture**: Automatically captures stdout for processing
|
||||||
|
4. **Error Handling**: Exit codes are passed to the callback for error detection
|
||||||
|
|
||||||
|
### Example Usage
|
||||||
|
|
||||||
|
#### Simple Command Execution
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
|
Item {
|
||||||
|
function checkNetwork() {
|
||||||
|
Proc.runCommand(
|
||||||
|
"myPlugin.ping",
|
||||||
|
["ping", "-c", "1", "8.8.8.8"],
|
||||||
|
(output, exitCode) => {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
console.log("Network is up")
|
||||||
|
} else {
|
||||||
|
console.log("Network is down")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Parsing Command Output
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property var diskUsage: ({})
|
||||||
|
|
||||||
|
function updateDiskUsage() {
|
||||||
|
Proc.runCommand(
|
||||||
|
"myPlugin.df",
|
||||||
|
["df", "-h", "/home"],
|
||||||
|
(output, exitCode) => {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
const lines = output.trim().split("\n")
|
||||||
|
if (lines.length > 1) {
|
||||||
|
const parts = lines[1].split(/\s+/)
|
||||||
|
diskUsage = {
|
||||||
|
total: parts[1],
|
||||||
|
used: parts[2],
|
||||||
|
available: parts[3],
|
||||||
|
percent: parts[4]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Shell Commands with Pipes
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
|
Item {
|
||||||
|
function getTopProcess() {
|
||||||
|
Proc.runCommand(
|
||||||
|
"myPlugin.topProcess",
|
||||||
|
["sh", "-c", "ps aux | sort -nrk 3,3 | head -n 1"],
|
||||||
|
(output, exitCode) => {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
console.log("Top process:", output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Debouncing Rapid Updates
|
||||||
|
|
||||||
|
```qml
|
||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
DankTextField {
|
||||||
|
id: searchField
|
||||||
|
placeholderText: "Search files..."
|
||||||
|
|
||||||
|
onTextChanged: {
|
||||||
|
Proc.runCommand(
|
||||||
|
"myPlugin.search",
|
||||||
|
["find", "/home", "-name", "*" + text + "*"],
|
||||||
|
(output, exitCode) => {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
updateSearchResults(output)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
500
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Important Notes
|
||||||
|
|
||||||
|
1. **Unique IDs**: Use descriptive, namespaced IDs (e.g., `"myPlugin.actionName"`) to avoid conflicts
|
||||||
|
2. **Debouncing**: Use appropriate debounce delays for your use case:
|
||||||
|
- Fast updates (50-100ms): System monitoring, real-time data
|
||||||
|
- User input (300-500ms): Search fields, text input processing
|
||||||
|
- Network requests (500-1000ms): API calls, web scraping
|
||||||
|
3. **Error Handling**: Always check the exit code in your callback before processing output
|
||||||
|
4. **Shell Commands**: Use `["sh", "-c", "command"]` for complex shell commands with pipes or redirects
|
||||||
|
5. **Security**: Sanitize user input before passing to commands to prevent command injection
|
||||||
|
6. **Performance**: Avoid running expensive commands too frequently - use debouncing wisely
|
||||||
|
|
||||||
|
### Comparison with Other Methods
|
||||||
|
|
||||||
|
**Proc.runCommand** vs **Quickshell.execDetached**:
|
||||||
|
- Use `Proc.runCommand` when you need to capture output or check exit codes
|
||||||
|
- Use `Quickshell.execDetached` for fire-and-forget operations (like clipboard copy)
|
||||||
|
|
||||||
|
**Proc.runCommand** vs **Process component**:
|
||||||
|
- Use `Proc.runCommand` for simple, one-off command executions with automatic cleanup
|
||||||
|
- Use `Process` component for long-running processes or when you need fine-grained control
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
### Console Logging
|
### Console Logging
|
||||||
@@ -792,10 +1037,16 @@ To create a launcher plugin, set the plugin type in `plugin.json`:
|
|||||||
{
|
{
|
||||||
"id": "myLauncher",
|
"id": "myLauncher",
|
||||||
"name": "My Launcher Plugin",
|
"name": "My Launcher Plugin",
|
||||||
|
"description": "A custom launcher plugin for quick actions",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Your Name",
|
||||||
"type": "launcher",
|
"type": "launcher",
|
||||||
"capabilities": ["launcher"],
|
"capabilities": ["show-thing"],
|
||||||
"component": "./MyLauncher.qml",
|
"component": "./MyLauncher.qml",
|
||||||
|
"trigger": "#",
|
||||||
|
"icon": "search",
|
||||||
"settings": "./MySettings.qml",
|
"settings": "./MySettings.qml",
|
||||||
|
"requires_dms": ">=0.1.18",
|
||||||
"permissions": ["settings_read", "settings_write"]
|
"permissions": ["settings_read", "settings_write"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -1022,6 +1273,7 @@ See `PLUGINS/LauncherExample/` for a complete working example demonstrating:
|
|||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
|
- **Plugin Schema**: `plugin-schema.json` - JSON Schema for validation
|
||||||
- **Example Plugins**:
|
- **Example Plugins**:
|
||||||
- [Emoji Picker](./ExampleEmojiPlugin/)
|
- [Emoji Picker](./ExampleEmojiPlugin/)
|
||||||
- [WorldClock](https://github.com/rochacbruno/WorldClock)
|
- [WorldClock](https://github.com/rochacbruno/WorldClock)
|
||||||
@@ -1039,7 +1291,8 @@ See `PLUGINS/LauncherExample/` for a complete working example demonstrating:
|
|||||||
Share your plugins with the community:
|
Share your plugins with the community:
|
||||||
|
|
||||||
1. Create a public repository with your plugin
|
1. Create a public repository with your plugin
|
||||||
2. Include comprehensive README.md
|
2. Validate your `plugin.json` against `plugin-schema.json`
|
||||||
|
3. Include comprehensive README.md
|
||||||
4. Add example screenshots
|
4. Add example screenshots
|
||||||
5. Document dependencies and permissions
|
5. Document dependencies and permissions
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
"description": "Background daemon that monitors wallpaper changes and logs them",
|
"description": "Background daemon that monitors wallpaper changes and logs them",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "DankMaterialShell",
|
"author": "DankMaterialShell",
|
||||||
"icon": "wallpaper",
|
|
||||||
"type": "daemon",
|
"type": "daemon",
|
||||||
|
"capabilities": ["wallpaper", "monitoring"],
|
||||||
"component": "./WallpaperWatcherDaemon.qml",
|
"component": "./WallpaperWatcherDaemon.qml",
|
||||||
|
"icon": "wallpaper",
|
||||||
"settings": "./WallpaperWatcherSettings.qml",
|
"settings": "./WallpaperWatcherSettings.qml",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"settings_read",
|
"settings_read",
|
||||||
|
|||||||
115
PLUGINS/plugin-schema.json
Normal file
115
PLUGINS/plugin-schema.json
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "https://danklinux.com/schemas/plugin.json",
|
||||||
|
"title": "DankMaterialShell Plugin Manifest",
|
||||||
|
"description": "Schema for DankMaterialShell plugin.json manifest files",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"description",
|
||||||
|
"version",
|
||||||
|
"author",
|
||||||
|
"type",
|
||||||
|
"capabilities",
|
||||||
|
"component"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Unique plugin identifier (camelCase, no spaces)",
|
||||||
|
"pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Human-readable plugin name",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Short description of plugin functionality",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Semantic version string (e.g., '1.0.0')",
|
||||||
|
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Plugin creator name or email",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Plugin type",
|
||||||
|
"enum": ["widget", "daemon", "launcher"]
|
||||||
|
},
|
||||||
|
"capabilities": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Array of plugin capabilities",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"minItems": 1
|
||||||
|
},
|
||||||
|
"component": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Relative path to main QML component file",
|
||||||
|
"pattern": "^\\./.*\\.qml$"
|
||||||
|
},
|
||||||
|
"trigger": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Trigger string for launcher activation (required for launcher type)"
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Material Design icon name"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path to settings component QML file",
|
||||||
|
"pattern": "^\\./.*\\.qml$"
|
||||||
|
},
|
||||||
|
"requires_dms": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Minimum DMS version requirement (e.g., '>=0.1.18', '>0.1.0')",
|
||||||
|
"pattern": "^(>=?|<=?|=|>|<)\\d+\\.\\d+\\.\\d+$"
|
||||||
|
},
|
||||||
|
"requires": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Array of required system tools/dependencies",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Required capabilities",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"settings_read",
|
||||||
|
"settings_write",
|
||||||
|
"process",
|
||||||
|
"network"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"const": "launcher"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"required": ["trigger"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user