Feature/soccer scroll support (#186)

* fix: Use plugin.modes instead of manifest.json for available modes

- Display controller now checks plugin_instance.modes first before falling back to manifest
- This allows plugins to dynamically provide modes based on enabled leagues
- Fixes issue where disabled leagues (WNBA, NCAAW) appeared in available modes
- Plugins can now control their available modes at runtime based on config

* fix: Handle permission errors when removing plugin directories

- Added _safe_remove_directory() method to handle permission errors gracefully
- Fixes permissions on __pycache__ directories before removal
- Updates uninstall_plugin() and install methods to use safe removal
- Resolves [Errno 13] Permission denied errors during plugin install/uninstall

* debug(display): Change FPS check logging from debug to info level

- Change FPS check log from DEBUG to INFO to help diagnose scrolling FPS issues
- Add active_mode to log message for clarity
- Helps identify if plugins are being detected for high-FPS mode

* debug(display): Add logging for display_interval in both FPS loops

- Log display_interval when entering high-FPS and normal loops
- Shows expected FPS for high-FPS mode
- Helps diagnose why news ticker shows 50 FPS despite high-FPS detection

* feat: Update soccer-scoreboard submodule with scroll display support

- Submodule now includes full feature parity with football-scoreboard
- Granular display modes for 8 leagues (24 total modes)
- Scroll display mode with game_renderer.py and scroll_display.py
- League registry system with enabled state filtering
- Modernized config_schema.json with per-league scroll settings
- League-aware logo caching to prevent collisions
- Pillow 8.x compatibility for image resampling

Submodule branch: feature/football-feature-parity
Commit: e22a16d

* style(web): Update plugin button colors and reorganize documentation

- Change update button color to yellow-600 in installed plugins section to match plugin config page
- Change refresh plugins button color to blue-600 to match restart display button
- Move DEVELOPMENT.md and MIGRATION_GUIDE.md from root to docs/ directory
- Remove IMPACT_EXPLANATION.md and MERGE_CONFLICT_RESOLUTION_PLAN.md

---------

Co-authored-by: Chuck <chuck@example.com>
This commit is contained in:
Chuck
2026-01-13 13:33:53 -05:00
committed by GitHub
parent fdf09fabd2
commit 4a63ff87cb
7 changed files with 3 additions and 436 deletions

View File

@@ -1,245 +0,0 @@
# Impact Explanation: Config Schema Validation Fixes
## Current Problem (Before Fixes)
### What Users Experience Now
**Scenario**: User wants to configure a plugin (e.g., hockey-scoreboard)
1. User opens web interface → Plugins tab → hockey-scoreboard configuration
2. User changes some settings (e.g., favorite teams, display duration)
3. User clicks "Save Configuration" button
4. **ERROR**: "Configuration validation failed: Missing required field: 'enabled'"
5. **RESULT**: Configuration changes are NOT saved
6. User is frustrated - can't save their configuration
**Why This Happens**:
- Plugin schema has `"required": ["enabled"]`
- `enabled` field is system-managed (controlled by PluginManager/enable toggle)
- Config doesn't have `enabled` field (it's managed separately)
- Validation fails because `enabled` is required but missing
### Real-World Impact
- **186 validation errors** across all 20 plugins
- **ALL plugins** currently fail to save configs via web interface
- Users cannot configure plugins through the UI
- This is a **blocking issue** for plugin configuration
---
## Priority 1 Fix: Remove Core Properties from Required Array
### What Changes Technically
**File**: `src/plugin_system/schema_manager.py`
**Change**: After injecting core properties (`enabled`, `display_duration`, `live_priority`) into schema properties, also remove them from the `required` array.
**Before**:
```python
# Core properties added to properties (allowed)
enhanced_schema["properties"]["enabled"] = {...}
# But still in required array (validation fails if missing)
enhanced_schema["required"] = ["enabled", ...] # ❌ Still requires enabled
```
**After**:
```python
# Core properties added to properties (allowed)
enhanced_schema["properties"]["enabled"] = {...}
# Removed from required array (not required for validation)
enhanced_schema["required"] = [...] # ✅ enabled removed, validation passes
```
### Why This Is Correct
- `enabled` is managed by PluginManager (system-level concern)
- User doesn't set `enabled` in plugin config form (it's a separate toggle)
- Config validation should check user-provided config, not system-managed fields
- Core properties should be **allowed** but not **required**
### User Experience After Fix
**Scenario**: User configures hockey-scoreboard plugin
1. User opens web interface → Plugins tab → hockey-scoreboard configuration
2. User changes settings (favorite teams, display duration)
3. User clicks "Save Configuration" button
4. **SUCCESS**: Configuration saves without errors
5. Changes are persisted and plugin uses new configuration
**Impact**:
- ✅ All 20 plugins can now save configs successfully
- ✅ ~150 validation errors eliminated (all "enabled" related)
- ✅ Users can configure plugins normally
- ✅ This is the **primary fix** that unblocks plugin configuration
### Technical Details
- Issue count: 186 → ~30-40 (most issues resolved)
- No breaking changes - only affects validation logic
- Backward compatible - configs that work will continue to work
- Makes validation logic match the actual architecture
---
## Priority 2 Fix: Verify Default Merging Logic
### What This Addresses
Some plugins have required fields that have default values in their schemas. For example:
- `calendar` plugin requires `credentials_file` but schema provides default: `"credentials.json"`
- When user saves config without this field, the default should be applied automatically
- Then validation passes because the field is present (with default value)
### Current Behavior
The code already has default merging logic:
```python
defaults = schema_mgr.generate_default_config(plugin_id, use_cache=True)
plugin_config = schema_mgr.merge_with_defaults(plugin_config, defaults)
```
**But audit shows some plugins still fail**, which suggests either:
1. Default merging isn't working correctly for all cases, OR
2. Some required fields don't have defaults in schemas (schema design issue)
### What We'll Verify
1. Check if `merge_with_defaults()` handles nested objects correctly
2. Verify defaults are applied before validation runs
3. Test with problematic plugins to see why they still fail
4. Fix any issues found OR identify that schemas need defaults added
### User Experience Impact
**If defaults are working correctly**:
- Users don't need to manually add every field
- Fields with defaults "just work" automatically
- Easier plugin configuration
**If defaults aren't working**:
- After fix, plugins with schema defaults will validate correctly
- Fewer manual field entries required
- Better user experience
### Technical Details
- Issue count: ~30-40 → ~5-10 (after Priority 1)
- Addresses remaining validation failures
- May involve schema updates if defaults are missing
- Improves robustness of config system
---
## Priority 3 Fix: Calendar Plugin Cleanup
### What This Addresses
Calendar plugin has configuration fields that don't match its schema:
- `show_all_day` in config, but schema defines `show_all_day_events` (field name mismatch)
- `date_format` and `time_format` in config but not in schema (deprecated fields)
### Current Problems
1. **Field name mismatch**: `show_all_day` vs `show_all_day_events`
- Schema filtering removes `show_all_day` during save
- User's setting for all-day events doesn't actually work
- This is a **bug** where the setting is ignored
2. **Deprecated fields**: `date_format` and `time_format`
- Not used in plugin code
- Confusing to see in config
- Schema filtering removes them anyway (just creates warnings)
### What We'll Fix
1. **Fix field name**: Rename `show_all_day``show_all_day_events` in config
- Makes config match schema
- Fixes bug where all-day events setting doesn't work
2. **Remove deprecated fields**: Remove `date_format` and `time_format` from config
- Cleans up config file
- Removes confusion
- No functional impact (fields weren't used)
### User Experience Impact
**Before**:
- User sets "show all day events" = true
- Setting doesn't work (field name mismatch)
- User confused why setting isn't applied
**After**:
- User sets "show all day events" = true
- Setting works correctly (field name matches schema)
- Config is cleaner and matches schema
### Technical Details
- Issue count: ~5-10 → ~3-5 (after Priority 1 & 2)
- Fixes a bug (show_all_day_events not working)
- Cleanup/improvement, not critical
- Only affects calendar plugin
---
## Summary: Real-World Impact
### Before All Fixes
**User tries to configure any plugin**:
- ❌ Config save fails with validation errors
- ❌ Cannot configure plugins via web interface
- ❌ 186 validation errors across all plugins
- ❌ System is essentially broken for plugin configuration
### After Priority 1 Fix
**When configuring a plugin**:
- ✅ Config saves successfully for most plugins
- ✅ Can configure plugins via web interface
- ✅ ~150 errors resolved (enabled field issues)
- ✅ System is functional for plugin configuration
**Remaining issues**: ~30-40 validation errors
- Mostly fields without defaults that need user input
- Still some plugins that can't save (but most work)
### After Priority 2 Fix
**During plugin configuration**:
- ✅ Config saves successfully for almost all plugins
- ✅ Defaults applied automatically (easier configuration)
- ✅ ~30-40 errors → ~5-10 errors
- ✅ System is robust and user-friendly
**Remaining issues**: ~5-10 edge cases
- Complex validation scenarios
- Possibly some schema design issues
### After Priority 3 Fix
**All plugins**:
- ✅ Configs match schemas exactly
- ✅ No confusing warnings
- ✅ Calendar plugin bug fixed (show_all_day_events works)
- ✅ ~3-5 remaining edge cases only
- ✅ System is clean and fully functional
---
## Bottom Line
**Current State**: Plugin configuration saving is broken (186 errors, all plugins fail)
**After Fixes**: Plugin configuration saving works correctly (3-5 edge cases remain, all plugins functional)
**User Impact**: Users can configure plugins successfully instead of getting validation errors
**Technical Impact**: Validation logic correctly handles system-managed fields and schema defaults

View File

@@ -1,188 +0,0 @@
# Merge Conflict Resolution Plan: plugins → main
## Overview
This document outlines the plan to resolve merge conflicts when merging the `plugins` branch into `main`. The conflicts occur because the plugins branch refactored the architecture from built-in managers to a plugin-based system.
## Conflicted Files
### 1. `src/clock.py`
**Status**: EXISTS in `main`, DELETED in `plugins`
**Reason for Conflict**:
- In `main`: Clock functionality is implemented as a built-in manager (`src/clock.py`)
- In `plugins`: Clock functionality has been migrated to a plugin (`plugins/clock-simple/manager.py`)
**Resolution Strategy**:
-**DELETE** `src/clock.py` from `main` when merging
- The plugin version at `plugins/clock-simple/manager.py` replaces this file
- Functionality is preserved in the plugin architecture
**Action Required**:
```bash
git rm src/clock.py
```
**Verification**:
- Ensure `plugins/clock-simple/` plugin exists and works
- Verify clock functionality works via the plugin system
---
### 2. `src/news_manager.py`
**Status**: EXISTS in `main`, DELETED in `plugins`
**Reason for Conflict**:
- In `main`: News functionality is implemented as a built-in manager (`src/news_manager.py`)
- In `plugins`: News functionality has been migrated to a plugin (`plugins/ledmatrix-news/manager.py`)
**Resolution Strategy**:
-**DELETE** `src/news_manager.py` from `main` when merging
- The plugin version at `plugins/ledmatrix-news/manager.py` replaces this file
- Functionality is preserved in the plugin architecture
**Action Required**:
```bash
git rm src/news_manager.py
```
**Verification**:
- Ensure `plugins/ledmatrix-news/` plugin exists and works
- Verify news functionality works via the plugin system
---
### 3. `README.md`
**Status**: SIGNIFICANTLY DIFFERENT in both branches
**Main Differences**:
| Aspect | `main` branch | `plugins` branch |
|--------|--------------|------------------|
| Introduction | Has detailed "Core Features" section with screenshots | Has "Plugins Version is HERE!" introduction |
| Architecture | Describes built-in managers | Describes plugin-based architecture |
| Website Link | Includes link to website write-up | Removed website link, added ko-fi link |
| Content Focus | Feature showcase with images | Plugin system explanation |
**Resolution Strategy**:
-**KEEP** `plugins` branch version as the base (it's current and accurate for plugin architecture)
- ⚠️ **CONSIDER** preserving valuable content from `main`:
- The detailed "Core Features" section with screenshots might be valuable for documentation
- The website write-up link might be worth preserving
- However, since plugins branch is more current and accurate, prefer plugins version
**Recommended Approach**:
1. Keep plugins branch README.md as-is (it's current and accurate)
2. The old "Core Features" section in main is outdated for the plugin architecture
3. If website link is important, it can be added back to plugins version separately
**Action Required**:
```bash
# Accept plugins branch version
git checkout --theirs README.md
# OR manually review and merge, keeping plugins version as base
```
**Verification**:
- README.md accurately describes the plugin architecture
- All installation and configuration instructions are current
- Links are working
---
## Step-by-Step Resolution Process
### Step 1: Checkout main branch and prepare for merge
```bash
git checkout main
git fetch origin
git merge origin/plugins --no-commit --no-ff
```
### Step 2: Resolve file deletion conflicts
```bash
# Remove files that were migrated to plugins
git rm src/clock.py
git rm src/news_manager.py
```
### Step 3: Resolve README.md conflict
```bash
# Option A: Accept plugins version (recommended)
git checkout --theirs README.md
# Option B: Manually review and merge
# Edit README.md to combine best of both if needed
```
### Step 4: Verify no references to deleted files
```bash
# Check if any code references the deleted files
grep -r "from src.clock import" .
grep -r "from src.news_manager import" .
grep -r "import src.clock" .
grep -r "import src.news_manager" .
# If found, these need to be updated to use plugins instead
```
### Step 5: Test the resolved merge
```bash
# Verify plugins are loaded correctly
python3 -c "from src.plugin_system.plugin_manager import PluginManager; print('OK')"
# Check that clock-simple plugin exists
ls -la plugins/clock-simple/
# Check that ledmatrix-news plugin exists
ls -la plugins/ledmatrix-news/
```
### Step 6: Complete the merge
```bash
git add .
git commit -m "Merge plugins into main: Remove deprecated managers, keep plugin-based README"
```
---
## Verification Checklist
- [ ] `src/clock.py` is deleted (functionality in `plugins/clock-simple/`)
- [ ] `src/news_manager.py` is deleted (functionality in `plugins/ledmatrix-news/`)
- [ ] `README.md` reflects plugin architecture (plugins branch version)
- [ ] No import statements reference deleted files
- [ ] Clock plugin works correctly
- [ ] News plugin works correctly
- [ ] All tests pass (if applicable)
- [ ] Documentation is accurate
---
## Notes
1. **No Code Changes Required**: The deletions are safe because:
- Clock functionality exists in `plugins/clock-simple/manager.py`
- News functionality exists in `plugins/ledmatrix-news/manager.py`
- The plugin system loads these automatically
2. **README.md Decision**: Keeping plugins version is recommended because:
- It accurately describes the current plugin-based architecture
- The old "Core Features" section describes the old architecture
- Users need current installation/configuration instructions
3. **Potential Issues**:
- If any code in `main` still imports these files, those imports need to be removed
- Configuration references to old managers may need updating
- Documentation references may need updating
---
## Related Files to Check (Not Conflicted but Related)
These files might reference the deleted managers and should be checked:
- `display_controller.py` - May have references to Clock or NewsManager
- `config/config.json` - May have config sections for clock/news_manager
- Any test files that might test these managers
- Documentation files that reference these managers

View File

@@ -1385,7 +1385,7 @@ function renderInstalledPlugins(plugins) {
data-action="configure">
<i class="fas fa-cog mr-2"></i>Configure
</button>
<button class="btn bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-md text-sm flex-1 font-semibold"
<button class="btn bg-yellow-600 hover:bg-yellow-700 text-white px-4 py-2 rounded-md text-sm flex-1 font-semibold"
data-plugin-id="${escapedPluginId}"
data-action="update">
<i class="fas fa-sync mr-2"></i>Update

View File

@@ -7,7 +7,7 @@
<!-- Plugin Controls -->
<div class="flex flex-wrap items-center justify-between gap-4 mb-6">
<div class="flex items-center space-x-4">
<button id="refresh-plugins-btn" class="btn bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-md">
<button id="refresh-plugins-btn" class="btn bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md">
<i class="fas fa-sync-alt mr-2"></i>Refresh Plugins
</button>
<button id="update-all-plugins-btn" class="btn bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-md flex items-center">