diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample')
4 files changed, 645 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/LauncherExampleLauncher.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/LauncherExampleLauncher.qml new file mode 100644 index 0000000..81040b6 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/LauncherExampleLauncher.qml @@ -0,0 +1,140 @@ +import QtQuick +import Quickshell +import qs.Services + +Item { + id: root + + // Plugin properties + property var pluginService: null + property string trigger: "#" + + // Plugin interface signals + signal itemsChanged() + + Component.onCompleted: { + console.info("LauncherExample: Plugin loaded") + + // Load custom trigger from settings + if (pluginService) { + trigger = pluginService.loadPluginData("launcherExample", "trigger", "#") + } + } + + // Required function: Get items for launcher + function getItems(query) { + const baseItems = [ + { + name: "Test Item 1", + icon: "material:lightbulb", + comment: "This is a test item that shows a toast notification", + action: "toast:Test Item 1 executed!", + categories: ["LauncherExample"] + }, + { + name: "Test Item 2", + icon: "material:star", + comment: "Another test item with different action", + action: "toast:Test Item 2 clicked!", + categories: ["LauncherExample"] + }, + { + name: "Test Item 3", + icon: "material:favorite", + comment: "Third test item for demonstration", + action: "toast:Test Item 3 activated!", + categories: ["LauncherExample"] + }, + { + name: "Unicode Icon Example", + icon: "unicode:๐", + comment: "Demonstrates unicode/emoji icon support", + action: "toast:Unicode icons work great!", + categories: ["LauncherExample"] + }, + { + name: "Example Copy Action", + icon: "material:content_copy", + comment: "Demonstrates copying text to clipboard", + action: "copy:This text was copied by the launcher plugin!", + categories: ["LauncherExample"] + }, + { + name: "Example Script Action", + icon: "material:terminal", + comment: "Demonstrates running a simple command", + action: "script:echo 'Hello from launcher plugin!'", + categories: ["LauncherExample"] + } + ] + + if (!query || query.length === 0) { + return baseItems + } + + // Filter items based on query + const lowerQuery = query.toLowerCase() + return baseItems.filter(item => { + return item.name.toLowerCase().includes(lowerQuery) || + item.comment.toLowerCase().includes(lowerQuery) + }) + } + + // Required function: Execute item action + function executeItem(item) { + if (!item || !item.action) { + console.warn("LauncherExample: Invalid item or action") + return + } + + console.log("LauncherExample: Executing item:", item.name, "with action:", item.action) + + const actionParts = item.action.split(":") + const actionType = actionParts[0] + const actionData = actionParts.slice(1).join(":") + + switch (actionType) { + case "toast": + showToast(actionData) + break + case "copy": + copyToClipboard(actionData) + break + case "script": + runScript(actionData) + break + default: + console.warn("LauncherExample: Unknown action type:", actionType) + showToast("Unknown action: " + actionType) + } + } + + // Helper functions for different action types + function showToast(message) { + if (typeof ToastService !== "undefined") { + ToastService.showInfo("LauncherExample", message) + } else { + console.log("LauncherExample Toast:", message) + } + } + + function copyToClipboard(text) { + Quickshell.execDetached(["dms", "cl", "copy", text]) + showToast("Copied to clipboard: " + text) + } + + function runScript(command) { + console.log("LauncherExample: Would run script:", command) + showToast("Script executed: " + command) + + // In a real plugin, you might create a Process component here + // For demo purposes, we just show what would happen + } + + // Watch for trigger changes + onTriggerChanged: { + if (pluginService) { + pluginService.savePluginData("launcherExample", "trigger", trigger) + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/LauncherExampleSettings.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/LauncherExampleSettings.qml new file mode 100644 index 0000000..e30aaa8 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/LauncherExampleSettings.qml @@ -0,0 +1,244 @@ +import QtQuick +import QtQuick.Controls +import qs.Widgets + +FocusScope { + id: root + + property var pluginService: null + + implicitHeight: settingsColumn.implicitHeight + height: implicitHeight + + Column { + id: settingsColumn + anchors.fill: parent + anchors.margins: 16 + spacing: 16 + + Text { + text: "Launcher Example Plugin Settings" + font.pixelSize: 18 + font.weight: Font.Bold + color: "#FFFFFF" + } + + Text { + text: "This plugin demonstrates the launcher plugin system with example items and actions." + font.pixelSize: 14 + color: "#CCFFFFFF" + wrapMode: Text.WordWrap + width: parent.width - 32 + } + + Rectangle { + width: parent.width - 32 + height: 1 + color: "#30FFFFFF" + } + + Column { + spacing: 12 + width: parent.width - 32 + + Text { + text: "Trigger Configuration" + font.pixelSize: 16 + font.weight: Font.Medium + color: "#FFFFFF" + } + + Text { + text: noTriggerToggle.checked ? "Items will always show in the launcher (no trigger needed)." : "Set the trigger text to activate this plugin. Type the trigger in the launcher to filter to this plugin's items." + font.pixelSize: 12 + color: "#CCFFFFFF" + wrapMode: Text.WordWrap + width: parent.width + } + + Row { + spacing: 12 + + CheckBox { + id: noTriggerToggle + text: "No trigger (always show)" + checked: loadSettings("noTrigger", false) + + contentItem: Text { + text: noTriggerToggle.text + font.pixelSize: 14 + color: "#FFFFFF" + leftPadding: noTriggerToggle.indicator.width + 8 + verticalAlignment: Text.AlignVCenter + } + + indicator: Rectangle { + implicitWidth: 20 + implicitHeight: 20 + radius: 4 + border.color: noTriggerToggle.checked ? "#4CAF50" : "#60FFFFFF" + border.width: 2 + color: noTriggerToggle.checked ? "#4CAF50" : "transparent" + + Rectangle { + width: 12 + height: 12 + anchors.centerIn: parent + radius: 2 + color: "#FFFFFF" + visible: noTriggerToggle.checked + } + } + + onCheckedChanged: { + saveSettings("noTrigger", checked) + if (checked) { + saveSettings("trigger", "") + } else { + saveSettings("trigger", triggerField.text || "#") + } + } + } + } + + Row { + spacing: 12 + anchors.left: parent.left + anchors.right: parent.right + visible: !noTriggerToggle.checked + + Text { + text: "Trigger:" + font.pixelSize: 14 + color: "#FFFFFF" + anchors.verticalCenter: parent.verticalCenter + } + + DankTextField { + id: triggerField + width: 100 + height: 40 + text: loadSettings("trigger", "#") + placeholderText: "#" + backgroundColor: "#30FFFFFF" + textColor: "#FFFFFF" + + onTextEdited: { + const newTrigger = text.trim() + saveSettings("trigger", newTrigger || "#") + saveSettings("noTrigger", newTrigger === "") + } + } + + Text { + text: "Examples: #, !, @, !ex, etc." + font.pixelSize: 12 + color: "#AAFFFFFF" + anchors.verticalCenter: parent.verticalCenter + } + } + } + + Rectangle { + width: parent.width - 32 + height: 1 + color: "#30FFFFFF" + } + + Column { + spacing: 8 + width: parent.width - 32 + + Text { + text: "Example Items:" + font.pixelSize: 14 + font.weight: Font.Medium + color: "#FFFFFF" + } + + Column { + spacing: 4 + leftPadding: 16 + + Text { + text: "โข Test Item 1, 2, 3 - Show toast notifications" + font.pixelSize: 12 + color: "#CCFFFFFF" + } + + Text { + text: "โข Example Copy Action - Copy text to clipboard" + font.pixelSize: 12 + color: "#CCFFFFFF" + } + + Text { + text: "โข Example Script Action - Demonstrate script execution" + font.pixelSize: 12 + color: "#CCFFFFFF" + } + } + } + + Rectangle { + width: parent.width - 32 + height: 1 + color: "#30FFFFFF" + } + + Column { + spacing: 8 + width: parent.width - 32 + + Text { + text: "Usage:" + font.pixelSize: 14 + font.weight: Font.Medium + color: "#FFFFFF" + } + + Column { + spacing: 4 + leftPadding: 16 + bottomPadding: 24 + + Text { + text: "1. Open Launcher (Ctrl+Space or click launcher button)" + font.pixelSize: 12 + color: "#CCFFFFFF" + } + + Text { + text: noTriggerToggle.checked ? "2. Items are always visible in the launcher" : "2. Type your trigger (default: #) to filter to this plugin" + font.pixelSize: 12 + color: "#CCFFFFFF" + } + + Text { + text: noTriggerToggle.checked ? "3. Search works normally with plugin items included" : "3. Optionally add search terms: '# test' to find test items" + font.pixelSize: 12 + color: "#CCFFFFFF" + } + + Text { + text: "4. Select an item and press Enter to execute its action" + font.pixelSize: 12 + color: "#CCFFFFFF" + } + } + } + } + + function saveSettings(key, value) { + if (pluginService) { + pluginService.savePluginData("launcherExample", key, value) + } + } + + function loadSettings(key, defaultValue) { + if (pluginService) { + return pluginService.loadPluginData("launcherExample", key, defaultValue) + } + return defaultValue + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/README.md b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/README.md new file mode 100644 index 0000000..db34b83 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/README.md @@ -0,0 +1,244 @@ +# LauncherExample Plugin + +A demonstration plugin that showcases the DMS launcher plugin system capabilities. + +## Purpose + +This plugin serves as a comprehensive example for developers creating launcher plugins for DMS. It demonstrates: + +- **Plugin Structure**: Proper manifest, launcher, and settings components +- **Trigger System**: Customizable trigger strings for plugin activation (including empty triggers) +- **Item Management**: Providing searchable items to the launcher +- **Action Execution**: Handling different types of actions (toast, copy, script) +- **Settings Integration**: Configurable plugin settings with persistence + +## Features + +### Example Items +- **Test Items 1-3**: Demonstrate toast notifications +- **Copy Action**: Shows clipboard integration +- **Script Action**: Demonstrates command execution + +### Trigger System +- **Default Trigger**: `#` (configurable in settings) +- **Empty Trigger Option**: Items can always be visible without needing a trigger +- **Usage**: Type `#` in launcher to filter to this plugin (when trigger is set) +- **Search**: Type `# test` to search within plugin items + +### Action Types +- `toast:message` - Shows toast notification +- `copy:text` - Copies text to clipboard +- `script:command` - Executes shell command (demo only) + +## File Structure + +``` +PLUGINS/LauncherExample/ +โโโ plugin.json # Plugin manifest +โโโ LauncherExampleLauncher.qml # Main launcher component +โโโ LauncherExampleSettings.qml # Settings interface +โโโ README.md # This documentation +``` + +## Installation + +1. **Plugin Directory**: Copy to `~/.config/DankMaterialShell/plugins/LauncherExample` +2. **Enable Plugin**: Settings โ Plugins โ Enable "LauncherExample" +3. **Configure**: Set custom trigger in plugin settings if desired + +## Usage + +### With Trigger (Default) +1. Open launcher (Ctrl+Space or launcher button) +2. Type `#` to activate plugin trigger +3. Browse available items or add search terms +4. Press Enter to execute selected item + +### Without Trigger (Empty Trigger Mode) +1. Enable "No trigger (always show)" in plugin settings +2. Open launcher - plugin items are always visible +3. Search works normally with plugin items included +4. Press Enter to execute selected item + +### Search Examples +- `#` - Show all plugin items (with trigger enabled) +- `# test` - Show items matching "test" +- `# copy` - Show items matching "copy" +- `test` - Show all items matching "test" (with empty trigger enabled) + +## Developer Guide + +### Plugin Contract + +**Launcher Component Requirements**: +```qml +// Required properties +property var pluginService: null +property string trigger: "#" + +// Required signals +signal itemsChanged() + +// Required functions +function getItems(query): array +function executeItem(item): void + +// Optional functions (for Shift+Enter paste support) +function getPasteText(item): string|null +function getPasteArgs(item): array|null +``` + +**Item Structure**: +```javascript +{ + name: "Item Name", // Display name + icon: "icon_name", // Icon (optional, see Icon Types below) + comment: "Description", // Subtitle text + action: "type:data", // Action to execute + categories: ["PluginName"] // Category array +} +``` + +**Icon Types**: + +The `icon` field supports four formats: + +1. **Material Design Icons** - Use `material:` prefix: + ```javascript + icon: "material:lightbulb" // Material Symbols Rounded font + ``` + Examples: `material:star`, `material:favorite`, `material:settings` + +2. **Unicode/Emoji Icons** - Use `unicode:` prefix: + ```javascript + icon: "unicode:๐" // Unicode character or emoji + ``` + Display any Unicode character or emoji as the icon. Examples: `unicode:๐`, `unicode:โก`, `unicode:๐จ` + +3. **Desktop Theme Icons** - Use icon name directly: + ```javascript + icon: "firefox" // Uses system icon theme + ``` + Examples: `firefox`, `chrome`, `folder`, `text-editor` + +4. **No Icon** - Omit the `icon` field entirely: + ```javascript + { + name: "๐ Grinning Face", + // No icon field + comment: "Copy emoji", + action: "copy:๐", + categories: ["MyPlugin"] + } + ``` + When icon is omitted, the launcher hides the icon area and displays only text + +**Action Format**: `type:data` where: +- `type` - Action handler (toast, copy, script, etc.) +- `data` - Action-specific data + +### Settings Integration +```qml +// Save setting +pluginService.savePluginData("pluginId", "key", value) + +// Load setting +pluginService.loadPluginData("pluginId", "key", defaultValue) +``` + +### Trigger Configuration + +The trigger can be configured in two ways: + +1. **Empty Trigger** (No Trigger Mode): + - Check "No trigger (always show)" in settings + - Saves `trigger: ""` and `noTrigger: true` + - Items always appear in launcher alongside regular apps + +2. **Custom Trigger**: + - Enter any string (e.g., `#`, `!`, `@`, `!ex`) + - Uncheck "No trigger" checkbox + - Items only appear when trigger is typed + +### Manifest Structure +```json +{ + "id": "launcherExample", + "name": "LauncherExample", + "type": "launcher", + "capabilities": ["launcher"], + "component": "./LauncherExampleLauncher.qml", + "settings": "./LauncherExampleSettings.qml", + "permissions": ["settings_read", "settings_write"] +} +``` + +Note: The `trigger` field in the manifest is optional and serves as the default trigger value. + +## Extending This Plugin + +### Adding New Items +```qml +function getItems(query) { + return [ + { + name: "My Item", + icon: "custom_icon", + comment: "Does something cool", + action: "custom:action_data", + categories: ["LauncherExample"] + } + ] +} +``` + +### Adding New Actions +```qml +function executeItem(item) { + const actionParts = item.action.split(":") + const actionType = actionParts[0] + const actionData = actionParts.slice(1).join(":") + + switch (actionType) { + case "custom": + handleCustomAction(actionData) + break + } +} +``` + +### Custom Trigger Logic +```qml +Component.onCompleted: { + if (pluginService) { + trigger = pluginService.loadPluginData("launcherExample", "trigger", "#") + } +} + +onTriggerChanged: { + if (pluginService) { + pluginService.savePluginData("launcherExample", "trigger", trigger) + } +} +``` + +## Best Practices + +1. **Unique Triggers**: Choose triggers that don't conflict with other plugins +2. **Clear Descriptions**: Write helpful item comments +3. **Error Handling**: Gracefully handle action failures +4. **Performance**: Return results quickly in getItems() +5. **Cleanup**: Destroy temporary objects in executeItem() +6. **Empty Trigger Support**: Consider if your plugin should support empty trigger mode + +## Testing + +Test the plugin by: +1. Installing and enabling in DMS +2. Testing with trigger enabled +3. Testing with empty trigger (no trigger mode) +4. Trying each action type +5. Testing search functionality +6. Verifying settings persistence + +This plugin provides a solid foundation for building more sophisticated launcher plugins with custom functionality! diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/plugin.json b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/plugin.json new file mode 100644 index 0000000..c95b302 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/PLUGINS/LauncherExample/plugin.json @@ -0,0 +1,17 @@ +{ + "id": "launcherExample", + "name": "LauncherExample", + "description": "Example launcher plugin demonstrating the launcher plugin system", + "version": "1.0.0", + "author": "DMS Team", + "icon": "extension", + "type": "launcher", + "capabilities": ["clipboard", "command-execution"], + "component": "./LauncherExampleLauncher.qml", + "settings": "./LauncherExampleSettings.qml", + "trigger": "#", + "permissions": [ + "settings_read", + "settings_write" + ] +} |