Add 6 new device providers, IconSelect grids, and UI fixes

New device providers: ESP-NOW, Philips Hue, USB HID, SPI Direct,
Razer Chroma SDK, and SteelSeries GameSense — each with client,
provider, full backend registration, schemas, routes, and frontend
support including discovery, form fields, and i18n.

Add IconSelect grids for SPI LED chipset selector and GameSense
peripheral type selector with new Lucide icons (cpu, keyboard,
mouse, headphones).

Replace emoji graph overlay buttons (eye, bell) with proper SVG
path icons for consistent cross-platform rendering.

Fix connection overlay causing horizontal scroll by adding
overflow: hidden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-14 20:32:28 +03:00
parent 51ec0970c3
commit 272cb69247
28 changed files with 2752 additions and 10 deletions

View File

@@ -34,6 +34,12 @@
<option value="ws">WebSocket</option>
<option value="openrgb">OpenRGB</option>
<option value="dmx">DMX</option>
<option value="espnow">ESP-NOW</option>
<option value="hue">Philips Hue</option>
<option value="usbhid">USB HID</option>
<option value="spi">SPI Direct</option>
<option value="chroma">Razer Chroma</option>
<option value="gamesense">SteelSeries</option>
<option value="mock">Mock</option>
</select>
</div>
@@ -154,6 +160,102 @@
<small class="input-hint" style="display:none" data-i18n="device.dmx_start_channel.hint">First DMX channel within the universe (1-512)</small>
<input type="number" id="device-dmx-start-channel" min="1" max="512" value="1">
</div>
<!-- ESP-NOW fields -->
<div class="form-group" id="device-espnow-peer-mac-group" style="display: none;">
<div class="label-row">
<label for="device-espnow-peer-mac" data-i18n="device.espnow.peer_mac">Peer MAC:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.espnow.peer_mac.hint">MAC address of the remote ESP32 receiver (e.g. AA:BB:CC:DD:EE:FF)</small>
<input type="text" id="device-espnow-peer-mac" placeholder="AA:BB:CC:DD:EE:FF" pattern="^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$">
</div>
<div class="form-group" id="device-espnow-channel-group" style="display: none;">
<div class="label-row">
<label for="device-espnow-channel" data-i18n="device.espnow.channel">WiFi Channel:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.espnow.channel.hint">WiFi channel (1-14). Must match the receiver's channel.</small>
<input type="number" id="device-espnow-channel" min="1" max="14" value="1">
</div>
<!-- Philips Hue fields -->
<div class="form-group" id="device-hue-username-group" style="display: none;">
<div class="label-row">
<label for="device-hue-username" data-i18n="device.hue.username">Bridge Username:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.hue.username.hint">Hue bridge application key from pairing</small>
<input type="text" id="device-hue-username" placeholder="Hue application key">
</div>
<div class="form-group" id="device-hue-client-key-group" style="display: none;">
<div class="label-row">
<label for="device-hue-client-key" data-i18n="device.hue.client_key">Client Key:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.hue.client_key.hint">Entertainment API client key (hex string from pairing)</small>
<input type="text" id="device-hue-client-key" placeholder="Hex client key">
</div>
<div class="form-group" id="device-hue-group-id-group" style="display: none;">
<div class="label-row">
<label for="device-hue-group-id" data-i18n="device.hue.group_id">Entertainment Group:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.hue.group_id.hint">Entertainment configuration ID from your Hue bridge</small>
<input type="text" id="device-hue-group-id" placeholder="Entertainment group ID">
</div>
<!-- SPI Direct fields -->
<div class="form-group" id="device-spi-speed-group" style="display: none;">
<div class="label-row">
<label for="device-spi-speed" data-i18n="device.spi.speed">SPI Speed (Hz):</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.spi.speed.hint">SPI clock speed. 800000 Hz for WS2812, 2400000 Hz for APA102.</small>
<input type="number" id="device-spi-speed" min="100000" max="4000000" value="800000">
</div>
<div class="form-group" id="device-spi-led-type-group" style="display: none;">
<div class="label-row">
<label for="device-spi-led-type" data-i18n="device.spi.led_type">LED Chipset:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.spi.led_type.hint">Type of addressable LED strip connected to the GPIO/SPI pin</small>
<select id="device-spi-led-type">
<option value="WS2812B">WS2812B</option>
<option value="WS2812">WS2812</option>
<option value="WS2811">WS2811</option>
<option value="SK6812">SK6812 (RGB)</option>
<option value="SK6812_RGBW">SK6812 (RGBW)</option>
</select>
</div>
<!-- Razer Chroma fields -->
<div class="form-group" id="device-chroma-device-type-group" style="display: none;">
<div class="label-row">
<label for="device-chroma-device-type" data-i18n="device.chroma.device_type">Peripheral Type:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.chroma.device_type.hint">Which Razer peripheral to control</small>
<select id="device-chroma-device-type">
<option value="chromalink">ChromaLink (5 zones)</option>
<option value="keyboard">Keyboard (132 keys)</option>
<option value="mouse">Mouse (30 LEDs)</option>
<option value="mousepad">Mousepad (15 LEDs)</option>
<option value="headset">Headset (5 zones)</option>
<option value="keypad">Keypad (20 keys)</option>
</select>
</div>
<!-- SteelSeries GameSense fields -->
<div class="form-group" id="device-gamesense-device-type-group" style="display: none;">
<div class="label-row">
<label for="device-gamesense-device-type" data-i18n="device.gamesense.device_type">Peripheral Type:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="device.gamesense.device_type.hint">Which SteelSeries peripheral to control</small>
<select id="device-gamesense-device-type">
<option value="keyboard">Keyboard</option>
<option value="mouse">Mouse</option>
<option value="headset">Headset</option>
<option value="mousepad">Mousepad</option>
<option value="indicator">Indicator</option>
</select>
</div>
<div id="add-device-error" class="error-message" style="display: none;"></div>
</form>
</div>