492bdb95e3
Receive real-time events from games (CS2, Dota 2, LoL, etc.) and drive LED effects through the existing color strip and value source pipelines. Core: - GameEventBus (thread-safe pub/sub) with standardized 23-type event vocabulary - GameAdapter ABC + AdapterRegistry + MappingAdapter (YAML-driven) - Built-in adapters: CS2 GSI, Dota 2 GSI, LoL Live Client, Generic Webhook - Community YAML adapters: Minecraft, Valorant, Rocket League - GameEventColorStripStream with 5 effects (flash/pulse/sweep/color_shift/breathing) - GameEventValueSource with EMA smoothing and timeout - 4 built-in effect presets (FPS Combat, MOBA Health, Racing, Generic Alert) - Auto-setup for Valve GSI games (Steam path detection, cfg file writing) - Demo capture engine exposed to non-demo mode Frontend: - Game tab in Streams tree navigation with integration cards - Game integration editor modal with adapter picker, config fields, event mappings - game_event source type in CSS and ValueSource editors - Setup instructions overlay (markdown rendered) - Live event monitor and connection test API: - Full CRUD for game integrations - Event ingestion endpoint (adapter-level auth) - Adapter metadata, presets, auto-setup, status/diagnostics endpoints
5.1 KiB
5.1 KiB
Phase 7: Frontend — ColorStrip & ValueSource Game Bindings
Status: ✅ Complete Parent plan: PLAN.md Domain: frontend
Objective
Add "game_event" as a selectable source type in the ColorStrip and ValueSource editors so users can create game-driven LED streams and parameter bindings from the existing entity UIs.
Tasks
- Task 1: Add "game_event" to ColorStripSource type selector (IconSelect)
- New icon + label in the source type grid
- When selected, show game integration picker (EntitySelect) and event mapping editor
- Task 2: Game integration picker in CSS editor
- EntitySelect dropdown listing available game integrations
- When selected, show the integration's supported events
- Task 3: Inline event mapping UI in CSS source editor
- Simplified version of the full mapping editor from Phase 6
- Allows override/supplement of the integration-level mappings
- Idle color picker
- Task 4: Add "game_event" to ValueSource type selector
- New icon + label in the value source type grid
- Task 5: Game value source config fields
- Game integration picker (EntitySelect)
- Event type picker (dropdown of continuous events from the selected integration)
- Min/max game value inputs
- Smoothing slider (0.0-1.0)
- Default value input
- Timeout input (seconds)
- Task 6: Add i18n keys for new source type labels and config fields
- Task 7: Update TypeScript types for new source types
Files to Modify/Create
server/src/wled_controller/static/js/features/streams.ts— CSS editor game_event fieldsserver/src/wled_controller/static/js/features/game-integration.ts— shared helpersserver/src/wled_controller/static/js/types.ts— type definitionsserver/src/wled_controller/templates/modals/— update CSS and value source modalsserver/src/wled_controller/static/locales/en.jsonserver/src/wled_controller/static/locales/ru.jsonserver/src/wled_controller/static/locales/zh.json
Acceptance Criteria
- "game_event" appears in both source type selectors with appropriate icon
- Selecting it shows game integration picker and relevant config fields
- CSS editor shows event mapping override UI
- Value source editor shows normalization and smoothing controls
- All i18n keys present
Notes
- Depends on Phase 4 (CSS source type exists) and Phase 5 (value source type exists)
- Reuse game-integration.ts helpers for adapter/event metadata fetching
Review Checklist
- All tasks completed
- Code follows frontend conventions
- TypeScript compiles without errors
- Bundle builds successfully
Handoff to Next Phase
All 7 tasks implemented. Key implementation details:
Files modified:
icons.ts— addedgame_eventto both_colorStripTypeIconsand_valueSourceTypeIconsmaps (gamepad2 icon)types.ts— addedgame_eventtoCSSSourceTypeandValueSourceTypeunions, addedGameEventValueSourceinterface, added game event fields toColorStripSourceinterface, also fixed pre-existingsystem_metricsmissing fromValueSourceTypecolor-strips.ts— addedgame_eventtoCSS_TYPE_KEYS,CSS_SECTION_MAP,CSS_TYPE_SETUP, and_typeHandlers; added helper functions for game integration EntitySelect dropdown, idle color BindableColorWidget, inline event mapping editor (add/remove/preset), and game mapping collection for savevalue-sources.ts— addedgame_eventtoVS_FLOAT_TYPE_KEYS; added section toggle inonValueSourceTypeChange; added loading/save logic for game event fields; added EntitySelect for game integration picker with filtered continuous event type dropdowncss-editor.html— addedcss-editor-game-event-sectionwith game integration select, idle color container, mapping preset select, inline mapping editor, and add mapping buttonvalue-source-editor.html— addedvalue-source-game-event-sectionwith game integration select, event type select (continuous events), min/max game value inputs, smoothing/default/timeout slidersapp.ts— imported and wiredaddCSSGameMapping,removeCSSGameMapping,onCSSGameMappingPresetChangeto windowglobal.d.ts— added window type declarations for the 3 new exported functionsen.json,ru.json,zh.json— added ~28 i18n keys each for CSS and value source game_event labels, hints, and errors
UI behavior:
- CSS editor: selecting "Game Event" type shows a game integration EntitySelect, BindableColor idle color picker, and an inline event mapping editor with preset loading (FPS Combat / MOBA Health), add/remove mapping rows (event type, effect type, color, duration, intensity, priority)
- Value source editor: selecting "Game Event" type shows a game integration EntitySelect, event type dropdown (filtered to continuous events from the adapter's supported_events), min/max game value number inputs, smoothing slider, default value slider, timeout slider
Conventions followed: No emoji (SVG icons only), EntitySelect for game integration picker, BindableColorWidget for idle color, fetchWithAuth, cache.invalidate() + reload pattern, all strings via t() with i18n keys in 3 locales, dirty check via snapshotValues(), widget cleanup in onForceClose().