diff --git a/docs/PLUGIN_CONFIGURATION_GUIDE.md b/docs/PLUGIN_CONFIGURATION_GUIDE.md index 5c4956fa..1a28c04f 100644 --- a/docs/PLUGIN_CONFIGURATION_GUIDE.md +++ b/docs/PLUGIN_CONFIGURATION_GUIDE.md @@ -9,7 +9,7 @@ The LEDMatrix system uses a plugin-based architecture where each plugin manages 1. **Install a plugin** from the Plugin Store in the web interface 2. **Navigate to the plugin's configuration tab** (automatically created when installed) 3. **Configure settings** using the auto-generated form -4. **Save configuration** and restart the display service +4. **Save configuration**; the running display applies it without a restart For detailed information, see the sections below. @@ -189,19 +189,20 @@ plugin-repos/ "author": "Your Name", "entry_point": "manager.py", "class_name": "MyPlugin", - "display_modes": ["my_plugin"], - "config_schema": "config_schema.json" + "display_modes": ["my_plugin"] } ``` -The required fields the plugin loader will check for are `id`, -`name`, `version`, `class_name`, and `display_modes`. `entry_point` -defaults to `manager.py` if omitted. `config_schema` must be a -**file path** (relative to the plugin directory) — the schema itself -lives in a separate JSON file, not inline in the manifest. The -`class_name` value must match the actual class defined in the entry -point file **exactly** (case-sensitive, no spaces); otherwise the -loader fails with `AttributeError` at load time. +The Plugin Store refuses a manifest that lacks any of `id`, `name`, +`class_name` or `display_modes` (`store_manager.py`); the loader itself +needs `class_name`. `version` is not required, but the store compares it +with the registry's `latest_version` to offer updates, so set it. +`entry_point` defaults to `manager.py` if omitted. The config schema is not +named in the manifest: it is always the file `config_schema.json` in the +plugin directory. The `class_name` value must match the actual class +defined in the entry point file **exactly** (case-sensitive, no spaces); +otherwise the loader fails with a `PluginError` ("Class ... not found in +module") at load time. ### Plugin Manager Class @@ -223,9 +224,11 @@ class MyPlugin(BasePlugin): """Render plugin content to the LED matrix.""" pass - def get_duration(self): - """Get display duration for this plugin""" - return self.config.get('duration', 30) + # BasePlugin.get_display_duration() already returns + # self.config['display_duration'] (default 15s); override it only to + # vary the duration with the content. + def get_display_duration(self): + return self.config.get('display_duration', 30) ``` ### Dynamic Duration Configuration @@ -259,7 +262,7 @@ Each installed plugin automatically gets its own dedicated configuration tab in ### Accessing Plugin Configuration -1. Navigate to the **Plugins** tab to see all installed plugins +1. Navigate to the **Plugin Manager** tab to see all installed plugins 2. Click the **Configure** button on any plugin card, or 3. Click directly on the plugin's tab button in the navigation bar @@ -278,7 +281,6 @@ Configuration forms are automatically generated from each plugin's `config_schem - **Type-safe inputs**: Form inputs match JSON Schema types - **Default values**: Fields show current values or schema defaults - **Real-time validation**: Input constraints enforced (min, max, maxLength, etc.) -- **Reset to defaults**: One-click reset to restore original settings - **Help text**: Each field shows description from schema For more details, see [Plugin Configuration Tabs](PLUGIN_CONFIGURATION_TABS.md). @@ -337,20 +339,16 @@ The configuration system uses JSON Schema Draft-07 for validation: 2. **Configuration errors**: Validate plugin configuration against schema 3. **Display issues**: Check display durations and plugin display methods 4. **Performance**: Monitor plugin update intervals and resource usage -5. **Tab not showing**: Verify `config_schema.json` exists and is referenced in manifest +5. **Form missing or wrong**: Verify `config_schema.json` exists in the plugin directory and is valid JSON Schema 6. **Settings not saving**: Check validation errors and ensure all required fields are filled ### Debug Mode -Enable debug logging to troubleshoot plugin issues: +There is no config key for debug logging. Run the display with debug +logging instead: -```json -{ - "plugin_system": { - "debug": true, - "log_level": "debug" - } -} +```bash +python3 run.py -d # or: LEDMATRIX_DEBUG=true python3 run.py ``` ## See Also diff --git a/docs/PLUGIN_CONFIGURATION_TABS.md b/docs/PLUGIN_CONFIGURATION_TABS.md index 9fcecef4..332c114a 100644 --- a/docs/PLUGIN_CONFIGURATION_TABS.md +++ b/docs/PLUGIN_CONFIGURATION_TABS.md @@ -1,19 +1,8 @@ # Plugin Configuration Tabs -> **Status note:** this doc was written during the rollout of the -> per-plugin configuration tab feature. The feature itself is shipped -> and working in the current v3 web interface, but a few file paths -> in the "Implementation Details" section below still reference the -> pre-v3 file layout (`web_interface_v2.py`, `templates/index_v2.html`). -> The current implementation lives in `web_interface/app.py`, -> `web_interface/blueprints/api_v3/` (plugin config handlers in -> `plugins.py`), and `web_interface/templates/v3/`. -> The user-facing description (Overview, Features, Form Generation -> Process) is still accurate. - ## Overview -Each installed plugin now gets its own dedicated configuration tab in the web interface. This provides a clean, organized way to configure plugins without cluttering the main Plugins management tab. +Each installed plugin now gets its own dedicated configuration tab in the web interface. This provides a clean, organized way to configure plugins without cluttering the **Plugin Manager** tab. ## Features @@ -21,24 +10,27 @@ Each installed plugin now gets its own dedicated configuration tab in the web in - **JSON Schema-Based Forms**: Configuration forms are automatically generated based on each plugin's `config_schema.json` - **Type-Safe Inputs**: Form inputs are created based on the JSON Schema type (boolean, number, string, array, enum) - **Default Values**: All fields show current values or fallback to schema defaults -- **Reset Functionality**: Users can reset all settings to defaults with one click - **Real-Time Validation**: Input constraints from JSON Schema are enforced (min, max, maxLength, etc.) ## User Experience ### Accessing Plugin Configuration -1. Navigate to the **Plugins** tab to see all installed plugins +1. Navigate to the **Plugin Manager** tab to see all installed plugins 2. Click the **Configure** button on any plugin card 3. You'll be automatically taken to that plugin's configuration tab -4. Alternatively, click directly on the plugin's tab button (marked with a puzzle piece icon) +4. Alternatively, click directly on the plugin's tab button in the second nav row ### Configuring a Plugin 1. Open the plugin's configuration tab 2. Modify settings using the generated form -3. Click **Save Configuration** -4. Restart the display service to apply changes +3. Click **Save Configuration**. The settings apply to the running display + without a restart: the display service reloads `config.json` when it + changes and calls the plugin's `on_config_change()` + +The tab also has **Refresh** (reload the form), **Update** (update the +plugin) and **Uninstall** buttons. ### Plugin Manager vs Per-Plugin Configuration @@ -53,22 +45,13 @@ Each installed plugin now gets its own dedicated configuration tab in the web in ### Requirements -To enable automatic configuration tab generation, your plugin must: +Every installed plugin gets a tab. To get a generated form in it, include a +`config_schema.json` file in the plugin's directory. The name is fixed: the +web interface finds the schema by that file name (`SchemaManager` in +`src/plugin_system/schema_manager.py`), and no manifest field points to it. -1. Include a `config_schema.json` file -2. Reference it in your `manifest.json`: - -```json -{ - "id": "your-plugin", - "name": "Your Plugin", - "icon": "fas fa-star", // Optional: Custom tab icon - ... - "config_schema": "config_schema.json" -} -``` - -**Note:** You can optionally specify a custom `icon` for your plugin tab. See [Plugin Custom Icons Guide](PLUGIN_CUSTOM_ICONS.md) for details. +**Note:** You can optionally specify a Font Awesome `icon` class for your +plugin tab in `manifest.json`. See [Plugin Custom Icons Guide](PLUGIN_CUSTOM_ICONS.md) for details. ### Supported JSON Schema Types @@ -209,69 +192,32 @@ Renders as: Dropdown select ### Form Generation Process -1. Web UI loads installed plugins via `/api/v3/plugins/installed` -2. For each plugin, the backend loads its `config_schema.json` -3. Frontend generates a tab button with plugin name -4. Frontend generates a form based on the JSON Schema -5. Current config values from `config.json` are populated -6. When saved, each field is sent to `/api/v3/plugins/config` endpoint +Forms are rendered on the server, not generated in the browser: -## Implementation Details - -### Backend Changes - -**File**: `web_interface_v2.py` - -- Modified `/api/v3/plugins/installed` endpoint to include `config_schema_data` -- Loads each plugin's `config_schema.json` if it exists -- Returns schema data along with plugin info - -### Frontend Changes - -**File**: `templates/index_v2.html` - -New Functions: -- `generatePluginTabs(plugins)` - Creates tab buttons and content for each plugin -- `generatePluginConfigForm(plugin)` - Generates HTML form from JSON Schema -- `savePluginConfiguration(pluginId)` - Saves form data to backend -- `resetPluginConfig(pluginId)` - Resets all settings to defaults -- `configurePlugin(pluginId)` - Navigates to plugin's tab - -### Data Flow - -``` -Page Load - → refreshPlugins() - → /api/v3/plugins/installed - → Returns plugins with config_schema_data - → generatePluginTabs() - → Creates tab buttons - → Creates tab content - → generatePluginConfigForm() - → Reads JSON Schema - → Creates form inputs - → Populates current values - -User Saves - → savePluginConfiguration() - → Reads form data - → Converts types per schema - → Sends to /api/v3/plugins/config - → Updates config.json - → Shows success notification -``` +1. The web UI loads installed plugins via `/api/v3/plugins/installed` and adds + a tab button for each one +2. Opening a tab loads `/v3/partials/plugin-config/` + (`web_interface/blueprints/pages_v3.py`), which loads the plugin's schema + through `SchemaManager` and its current values from `config.json` +3. `web_interface/templates/v3/partials/plugin_config.html` renders the form + from the schema (widgets named by `x-widget` are rendered by the scripts in + `web_interface/static/v3/js/widgets/`) +4. **Save Configuration** posts the form to `/api/v3/plugins/config` + (`web_interface/blueprints/api_v3/plugins.py`), which validates it against + the schema, writes `config.json` (secret fields go to + `config_secrets.json`) and shows a notification ## Troubleshooting ### Plugin Tab Not Appearing -- Ensure `config_schema.json` exists in plugin directory -- Verify `config_schema` field in `manifest.json` +- Check that the plugin is installed and appears in the **Plugin Manager** tab - Check browser console for errors -- Try refreshing plugins (Plugins tab → Refresh button) +- Reload the page ### Form Not Generating Correctly +- Ensure `config_schema.json` exists in the plugin directory - Validate your `config_schema.json` against JSON Schema Draft 07 - Check that all properties have a `type` field - Ensure `default` values match the specified type @@ -283,7 +229,6 @@ User Saves - Check that config keys match schema properties - Verify backend API is accessible - Check browser network tab for API errors -- Ensure display service is restarted after config changes ## Migration Guide @@ -301,26 +246,21 @@ If your plugin doesn't have a config schema: 2. Add descriptions for each property 3. Set appropriate defaults 4. Add validation constraints (min, max, etc.) -5. Reference the schema in your `manifest.json` ### Backward Compatibility - Plugins without `config_schema.json` still work normally -- They simply won't have a configuration tab +- Their tab shows plain text, number and checkbox inputs for the keys already + in their `config.json` section, or "No configuration options available for + this plugin." when there are none - Users can still edit config via the Raw JSON editor -- The Configure button will navigate to a tab with a friendly message -## Future Enhancements +## Beyond the Basic Types -Potential improvements for future versions: - -- **Advanced Schema Features**: Support for nested objects, conditional fields -- **Visual Validation**: Real-time validation feedback as user types -- **Color Pickers**: Special input for RGB/color array types -- **File Uploads**: Support for image/asset uploads -- **Import/Export**: Save and share plugin configurations -- **Presets**: Quick-switch between saved configurations -- **Documentation Links**: Link schema fields to plugin documentation +Nested objects (rendered as collapsible sections), `x-widget` widgets such as +`color-picker` and `file-upload`, and more are supported; see +[PLUGIN_CONFIGURATION_GUIDE.md](PLUGIN_CONFIGURATION_GUIDE.md) and +`web_interface/static/v3/js/widgets/README.md`. ## Example Plugins diff --git a/docs/PLUGIN_CONFIG_CORE_PROPERTIES.md b/docs/PLUGIN_CONFIG_CORE_PROPERTIES.md index 2e004c05..f887dff4 100644 --- a/docs/PLUGIN_CONFIG_CORE_PROPERTIES.md +++ b/docs/PLUGIN_CONFIG_CORE_PROPERTIES.md @@ -6,7 +6,8 @@ The LEDMatrix plugin system automatically manages certain core properties that a ## Core Properties -The following properties are automatically managed by the system: +The following properties are automatically managed by the system (the list +is `CORE_PLUGIN_PROPERTIES` in `src/plugin_system/schema_manager.py`): 1. **`enabled`** (boolean) - Default: `true` @@ -24,6 +25,24 @@ The following properties are automatically managed by the system: - Description: Enable live priority takeover when plugin has live content - Used by DisplayController for priority scheduling +4. **`skin`** (string, object or null; no default) + - Description: Visual skin id, or a per-mode mapping like `{"live": "my-skin"}` + - Not an enum, so a stored value keeps validating after the skin is + uninstalled. Skins do not render with the current scoreboard plugins yet + (see [SKIN_SYSTEM.md](SKIN_SYSTEM.md)); the key is kept so stored values + keep loading and saving + +5. **`skin_options`** (object; no default) + - Description: Options passed through to the selected skin + +6. **`vegas_width_pct`**, **`vegas_overflow`**, **`vegas_max_width_screens`** + (untyped; no default) + - Description: Vegas mode tuning for this plugin — card width as a + percentage of the panel, `"rotate"` or `"truncate"` on overflow, and the + widest the card may be in screens + - Read by `src/vegas_mode/plugin_adapter.py` and `BasePlugin`, which + validate the values themselves and ignore a bad one with a log line + ## How Core Properties Work ### Schema Validation diff --git a/docs/PLUGIN_CONFIG_QUICK_START.md b/docs/PLUGIN_CONFIG_QUICK_START.md index 16113ccc..568ffc94 100644 --- a/docs/PLUGIN_CONFIG_QUICK_START.md +++ b/docs/PLUGIN_CONFIG_QUICK_START.md @@ -10,8 +10,8 @@ and click **Install** 4. Notice a new tab appears in the second nav row with the plugin's name 5. Click that tab to configure the plugin -6. Modify settings and click **Save** -7. From **Overview**, click **Restart Display Service** to see changes +6. Modify settings and click **Save Configuration**. The running display + picks the change up by itself; no restart is needed That's it! Each installed plugin automatically gets its own configuration tab. @@ -29,7 +29,6 @@ That's it! Each installed plugin automatically gets its own configuration tab. - ✅ Proper input types (toggles, numbers, dropdowns) - ✅ Help text explaining each setting - ✅ Input validation (min/max, length, etc.) -- ✅ One-click reset to defaults ## 📋 Example Walkthrough @@ -40,7 +39,7 @@ Let's configure the "Hello World" plugin: After installing the plugin, you'll see a new tab: ``` -[Overview] [General] [...] [Plugins] [Hello World] ← New tab! +[Plugin Manager] [Hello World] ← New tab! (second nav row) ``` ### Step 2: Configure Settings @@ -70,15 +69,16 @@ Display Duration How long to display in seconds [10 ] -[Save Configuration] [Back] [Reset to Defaults] +[Refresh] [Update] [Uninstall] [Save Configuration] ``` ### Step 3: Save and Apply 1. Modify any settings 2. Click **Save Configuration** -3. See confirmation: "Configuration saved for hello-world. Restart display to apply changes." -4. Restart the display service +3. See the confirmation notification. Plugin settings apply live: the + display service reloads `config.json` when it changes and passes the new + settings to the plugin's `on_config_change()` ## 🛠️ For Plugin Developers @@ -105,19 +105,14 @@ Create `config_schema.json` in your plugin directory: } ``` -Reference it in `manifest.json`: +**Done!** The file name is fixed: the web interface looks for +`config_schema.json` in the plugin's directory; there is no manifest field +for it. Every installed plugin gets a tab; the schema is what turns it into a +form. -```json -{ - "id": "my-plugin", - "icon": "fas fa-star", // Optional: add a custom icon! - "config_schema": "config_schema.json" -} -``` - -**Done!** Your plugin now has a configuration tab. - -**Bonus:** Add an `icon` field for a custom tab icon! Use Font Awesome icons (`fas fa-star`), emoji (⭐), or custom images. See [PLUGIN_CUSTOM_ICONS.md](PLUGIN_CUSTOM_ICONS.md) for the full guide. +**Bonus:** an `icon` field in `manifest.json` names a Font Awesome class for +the tab (`"icon": "fas fa-star"`). See +[PLUGIN_CUSTOM_ICONS.md](PLUGIN_CUSTOM_ICONS.md). ## 🎨 Supported Input Types @@ -171,12 +166,10 @@ User enters: `255, 0, 0` ### For Users -1. **Reset Anytime**: Use "Reset to Defaults" to restore original settings -2. **Navigate Back**: Switch to the **Plugin Manager** tab to see the +1. **Navigate Back**: Switch to the **Plugin Manager** tab to see the full list of installed plugins -3. **Check Help Text**: Each field has a description explaining what it does -4. **Restart Required**: Remember to restart the display service from - **Overview** after saving +2. **Check Help Text**: Each field has a description explaining what it does +3. **No Restart Needed**: Saved plugin settings apply to the running display ### For Developers @@ -189,18 +182,17 @@ User enters: `255, 0, 0` ## 🔧 Troubleshooting ### Tab Not Showing -- Check that `config_schema.json` exists -- Verify `config_schema` is in `manifest.json` +- Check that the plugin is installed and listed under **Plugin Manager** - Refresh the page - Check browser console for errors ### Settings Not Saving - Ensure plugin is properly installed -- Restart the display service after saving - Check that all required fields are filled - Look for validation errors in browser console ### Form Looks Wrong +- Check that `config_schema.json` is in the plugin's directory - Validate your JSON Schema - Check that types match your defaults - Ensure descriptions are strings diff --git a/docs/PLUGIN_CUSTOM_ICONS.md b/docs/PLUGIN_CUSTOM_ICONS.md index 79cabc5b..0d7c761a 100644 --- a/docs/PLUGIN_CUSTOM_ICONS.md +++ b/docs/PLUGIN_CUSTOM_ICONS.md @@ -2,17 +2,28 @@ ## Overview -Plugins can specify custom icons that appear next to their name in the web interface tabs. This makes your plugin instantly recognizable and adds visual polish to the UI. +A plugin can name an icon for its tab in the web interface's second nav row +(next to **Plugin Manager**) with the `icon` field in `manifest.json`. -## Icon Types Supported +> **Status:** the tab code honors `icon`, but `GET /api/v3/plugins/installed` +> (`web_interface/blueprints/api_v3/plugins.py`) does not currently include +> the manifest's `icon` in its response, so every tab shows the default +> puzzle piece. Setting `icon` is harmless and will take effect once the API +> passes it through again. -The system supports three types of icons: +## Font Awesome classes only -### 1. Font Awesome Icons (Recommended) +`icon` is used verbatim as the CSS class of an `` element +(`iconEl.className = plugin.icon || 'fas fa-puzzle-piece'` in +`web_interface/static/v3/js/app-shell.js` and the same fallback in +`app-early.js`). So it must be a Font Awesome class string. Emoji, image +paths and URLs are not supported: they would end up as a meaningless class +name and render nothing. -The web interface uses Font Awesome 6, giving you access to thousands of icons. +The web interface bundles Font Awesome Free 6 +(`web_interface/static/v3/vendor/fontawesome/`), so any free `fas`, `far` or +`fab` icon works. -**Example:** ```json { "id": "my-plugin", @@ -21,292 +32,33 @@ The web interface uses Font Awesome 6, giving you access to thousands of icons. } ``` -**Common Font Awesome Icons:** -- Clock: `fas fa-clock` +Some common choices: + +- Clock / calendar: `fas fa-clock`, `fas fa-calendar-alt` - Weather: `fas fa-cloud-sun`, `fas fa-cloud-rain` -- Calendar: `fas fa-calendar`, `fas fa-calendar-alt` -- Sports: `fas fa-football-ball`, `fas fa-basketball-ball` +- Sports: `fas fa-football-ball`, `fas fa-basketball-ball`, `fas fa-trophy` - Music: `fas fa-music`, `fas fa-headphones` - Finance: `fas fa-chart-line`, `fas fa-dollar-sign` - News: `fas fa-newspaper`, `fas fa-rss` -- Settings: `fas fa-cog`, `fas fa-sliders-h` -- Timer: `fas fa-stopwatch`, `fas fa-hourglass` -- Alert: `fas fa-bell`, `fas fa-exclamation-triangle` -- Heart: `fas fa-heart`, `far fa-heart` (outline) -- Star: `fas fa-star`, `far fa-star` (outline) -- Image: `fas fa-image`, `fas fa-camera` -- Video: `fas fa-video`, `fas fa-film` -- Game: `fas fa-gamepad`, `fas fa-dice` +- Games: `fas fa-gamepad`, `fas fa-dice` -**Browse all icons:** [Font Awesome Icon Gallery](https://fontawesome.com/icons) +Browse the rest in the [Font Awesome gallery](https://fontawesome.com/icons) +(filter to Free, version 6). -### 2. Emoji Icons (Fun & Simple) +## Default -Use any emoji character for a colorful, fun icon. - -**Example:** -```json -{ - "id": "hello-world", - "name": "Hello World", - "icon": "👋" -} -``` - -**Popular Emojis:** -- Time: ⏰ 🕐 ⏱️ ⏲️ -- Weather: ☀️ ⛅ 🌤️ 🌧️ ⛈️ 🌩️ ❄️ -- Sports: ⚽ 🏀 🏈 ⚾ 🎾 🏐 -- Music: 🎵 🎶 🎸 🎹 🎤 -- Money: 💰 💵 💴 💶 💷 -- Calendar: 📅 📆 -- News: 📰 📻 📡 -- Fun: 🎮 🎲 🎯 🎨 🎭 -- Nature: 🌍 🌎 🌏 🌳 🌺 🌸 -- Food: 🍕 🍔 🍟 🍦 ☕ 🍰 - -### 3. Custom Image URLs (Advanced) - -Use a custom image file for ultimate branding. - -**Example:** -```json -{ - "id": "my-plugin", - "name": "My Plugin", - "icon": "/plugins/my-plugin/icon.png" -} -``` - -**Requirements:** -- Image should be 16x16 to 32x32 pixels -- Supported formats: PNG, SVG, JPG, GIF -- Can be a relative path, absolute path, or external URL -- SVG recommended for best quality at any size - -## How to Add an Icon - -### Step 1: Choose Your Icon - -Decide which type suits your plugin: -- **Font Awesome**: Professional, consistent with UI -- **Emoji**: Fun, colorful, no setup needed -- **Custom Image**: Unique branding, requires image file - -### Step 2: Add to manifest.json - -Add the `icon` field to your plugin's `manifest.json`: - -```json -{ - "id": "my-weather-plugin", - "name": "Weather Display", - "version": "1.0.0", - "author": "Your Name", - "description": "Shows weather information", - "icon": "fas fa-cloud-sun", // ← Add this line - "entry_point": "manager.py", - ... -} -``` - -### Step 3: Test Your Plugin - -1. Install or update your plugin -2. Open the web interface -3. Look for your plugin's tab -4. The icon should appear next to the plugin name - -## Examples - -### Weather Plugin -```json -{ - "id": "weather-advanced", - "name": "Weather Advanced", - "icon": "fas fa-cloud-sun", - "description": "Advanced weather display with forecasts" -} -``` -**Result:** Tab shows: `☁️ Weather Advanced` - -### Clock Plugin -```json -{ - "id": "digital-clock", - "name": "Digital Clock", - "icon": "⏰", - "description": "A beautiful digital clock" -} -``` -**Result:** Tab shows: `⏰ Digital Clock` - -### Sports Scores Plugin -```json -{ - "id": "sports-scores", - "name": "Sports Scores", - "icon": "fas fa-trophy", - "description": "Live sports scores" -} -``` -**Result:** Tab shows: `🏆 Sports Scores` - -### Custom Branding -```json -{ - "id": "company-dashboard", - "name": "Company Dashboard", - "icon": "/plugins/company-dashboard/logo.svg", - "description": "Company metrics display" -} -``` -**Result:** Tab shows: `[logo] Company Dashboard` - -## Best Practices - -### 1. Choose Meaningful Icons -- Icon should relate to plugin functionality -- Users should understand what the plugin does at a glance -- Avoid generic icons for specific functionality - -### 2. Keep It Simple -- Simpler icons work better at small sizes -- Avoid icons with too much detail -- Test how your icon looks at 16x16 pixels - -### 3. Match the UI Style -- Font Awesome icons match the interface best -- If using emoji, consider contrast with background -- Custom images should use similar color schemes - -### 4. Consider Accessibility -- Icons should be recognizable without color -- Don't rely solely on color to convey meaning -- The plugin name should be descriptive - -### 5. Test on Different Displays -- Check icon clarity on various screen sizes -- Ensure emoji render correctly on target devices -- Custom images should have good contrast - -## Icon Categories - -Here are recommended icons by plugin category: - -### Time & Calendar -- `fas fa-clock`, `fas fa-calendar`, `fas fa-hourglass` -- Emoji: ⏰ 📅 ⏱️ - -### Weather -- `fas fa-cloud-sun`, `fas fa-temperature-high`, `fas fa-wind` -- Emoji: ☀️ 🌧️ ⛈️ - -### Finance & Stocks -- `fas fa-chart-line`, `fas fa-dollar-sign`, `fas fa-coins` -- Emoji: 💰 📈 💵 - -### Sports & Games -- `fas fa-football-ball`, `fas fa-trophy`, `fas fa-gamepad` -- Emoji: ⚽ 🏀 🎮 - -### Entertainment -- `fas fa-music`, `fas fa-film`, `fas fa-tv` -- Emoji: 🎵 🎬 📺 - -### News & Information -- `fas fa-newspaper`, `fas fa-rss`, `fas fa-info-circle` -- Emoji: 📰 📡 ℹ️ - -### Utilities -- `fas fa-tools`, `fas fa-cog`, `fas fa-wrench` -- Emoji: 🔧 ⚙️ 🛠️ - -### Social Media -- `fab fa-twitter`, `fab fa-facebook`, `fab fa-instagram` -- Emoji: 📱 💬 📧 +With no `icon` (or an empty one) the tab shows `fas fa-puzzle-piece`. ## Troubleshooting -### Icon Not Showing -1. Check that the `icon` field is correctly spelled in `manifest.json` -2. For Font Awesome icons, verify the class name is correct -3. For custom images, check that the file path is accessible -4. Refresh the plugins in the web interface -5. Check browser console for errors - -### Emoji Looks Wrong -- Some emojis render differently on different platforms -- Try a different emoji if one doesn't work well -- Consider using Font Awesome instead for consistency - -### Custom Image Not Loading -- Verify the image file exists in the specified path -- Check file permissions (should be readable) -- Try using an absolute path or URL -- Ensure image format is supported (PNG, SVG, JPG, GIF) -- Check image dimensions (16x16 to 32x32 recommended) - -### Icon Too Large/Small -- Font Awesome and emoji icons automatically size correctly -- For custom images, adjust the image file dimensions -- SVG images scale best - -## Default Behavior - -If you don't specify an `icon` field in your manifest: -- The plugin tab will show a default puzzle piece icon: 🧩 -- This is the fallback for all plugins without custom icons - -## Technical Details - -The icon system works as follows: - -1. **Frontend reads manifest**: When plugins load, the web interface reads each plugin's `manifest.json` -2. **Icon detection**: The `getPluginIcon()` function determines icon type: - - Contains `fa-` → Font Awesome icon - - 1-4 characters → Emoji - - Starts with `http://`, `https://`, or `/` → Custom image - - Otherwise → Default puzzle piece -3. **Rendering**: Icon HTML is generated and inserted into: - - Tab button in navigation bar - - Configuration page header - -## Advanced: Dynamic Icons - -Want to change icons programmatically? While not officially supported, you could: - -1. Store multiple icon options in your manifest -2. Use JavaScript to swap icons based on plugin state -3. Update the manifest dynamically and refresh plugins - -**Example (advanced):** -```json -{ - "id": "status-display", - "icon": "fas fa-circle", - "icon_states": { - "active": "fas fa-check-circle", - "error": "fas fa-exclamation-circle", - "warning": "fas fa-exclamation-triangle" - } -} -``` +1. Check the class name against the Font Awesome 6 Free gallery; a Pro-only + or misspelled class renders as a blank space. +2. Include the style prefix (`fas`, `far` or `fab`) as well as the icon + class. +3. See the status note above: the icon is currently not passed through by + the API. ## Related Documentation -- [Plugin Configuration Tabs](PLUGIN_CONFIGURATION_TABS.md) - Main plugin tabs documentation -- [Plugin Development Guide](PLUGIN_DEVELOPMENT_GUIDE.md) - How to create plugins -- [Font Awesome Icons](https://fontawesome.com/icons) - Browse all available icons -- [Emoji Reference](https://unicode.org/emoji/charts/full-emoji-list.html) - All emoji options - -## Summary - -Adding a custom icon to your plugin: - -1. **Choose** your icon (Font Awesome, emoji, or custom image) -2. **Add** the `icon` field to `manifest.json` -3. **Test** in the web interface - -That's it! Your plugin now has a professional, recognizable icon in the UI. 🎨 - +- [Plugin Configuration Tabs](PLUGIN_CONFIGURATION_TABS.md) +- [Plugin Development Guide](PLUGIN_DEVELOPMENT_GUIDE.md) diff --git a/docs/PLUGIN_WEB_UI_ACTIONS.md b/docs/PLUGIN_WEB_UI_ACTIONS.md index 3d0d79d4..1b472147 100644 --- a/docs/PLUGIN_WEB_UI_ACTIONS.md +++ b/docs/PLUGIN_WEB_UI_ACTIONS.md @@ -25,9 +25,6 @@ Add a `web_ui_actions` array to your plugin's `manifest.json`: "script": "path/to/script.py", "oauth_flow": false, "section_description": "Optional section description", - "success_message": "Action completed successfully", - "error_message": "Action failed", - "step1_message": "Authorization URL generated", "step2_prompt": "Please paste the full redirect URL:", "step2_button_text": "Complete Authentication" } @@ -52,12 +49,13 @@ Add a `web_ui_actions` array to your plugin's `manifest.json`: - **`color`**: Color theme - `"blue"`, `"green"`, `"red"`, `"yellow"`, `"purple"`, etc. (defaults to `"blue"`) - **`oauth_flow`**: Set to `true` for OAuth-style two-step authentication flows - **`section_description`**: Description shown at the top of the actions section -- **`success_message`**: Message shown on successful completion -- **`error_message`**: Message shown on failure -- **`step1_message`**: Message shown after step 1 (for OAuth flows) - **`step2_prompt`**: Prompt text for step 2 redirect URL input - **`step2_button_text`**: Button text for step 2 (defaults to "Complete Authentication") +The status messages shown after an action runs come from the action's +response (`message`), with built-in fallbacks such as "Action completed +successfully"; there are no manifest fields for them. + ## Action Types ### Script Actions (`type: "script"`) @@ -98,7 +96,6 @@ For two-step OAuth flows (e.g., Spotify): "color": "green", "script": "authenticate_spotify.py", "oauth_flow": true, - "step1_message": "Authorization URL generated", "step2_prompt": "Please paste the full redirect URL from Spotify after authorization:", "step2_button_text": "Complete Authentication" } @@ -131,9 +128,6 @@ Here's a complete example for the `ledmatrix-music` plugin: "script": "authenticate_spotify.py", "oauth_flow": true, "section_description": "Authenticate with Spotify or YouTube Music to enable music playback display.", - "success_message": "Spotify authentication completed successfully", - "error_message": "Spotify authentication failed", - "step1_message": "Authorization URL generated", "step2_prompt": "Please paste the full redirect URL from Spotify after authorization:", "step2_button_text": "Complete Authentication" }, @@ -145,9 +139,7 @@ Here's a complete example for the `ledmatrix-music` plugin: "button_text": "Authenticate YTM", "icon": "fab fa-youtube", "color": "red", - "script": "authenticate_ytm.py", - "success_message": "YouTube Music authentication completed successfully", - "error_message": "YouTube Music authentication failed" + "script": "authenticate_ytm.py" } ] } diff --git a/docs/PLUGIN_WEB_UI_ACTIONS_EXAMPLE.json b/docs/PLUGIN_WEB_UI_ACTIONS_EXAMPLE.json index 25e171b6..e05e1de1 100644 --- a/docs/PLUGIN_WEB_UI_ACTIONS_EXAMPLE.json +++ b/docs/PLUGIN_WEB_UI_ACTIONS_EXAMPLE.json @@ -37,9 +37,6 @@ "script": "authenticate_spotify.py", "oauth_flow": true, "section_description": "Authenticate with Spotify or YouTube Music to enable music playback display.", - "success_message": "Spotify authentication completed successfully", - "error_message": "Spotify authentication failed", - "step1_message": "Authorization URL generated", "step2_prompt": "Please paste the full redirect URL from Spotify after authorization:", "step2_button_text": "Complete Authentication" }, @@ -51,9 +48,7 @@ "button_text": "Authenticate YTM", "icon": "fab fa-youtube", "color": "red", - "script": "authenticate_ytm.py", - "success_message": "YouTube Music authentication completed successfully", - "error_message": "YouTube Music authentication failed" + "script": "authenticate_ytm.py" } ], "versions": [