Add notification reactive color strip source with webhook trigger

New source_type "notification" fires one-shot visual effects (flash, pulse, sweep)
triggered via POST webhook. Designed as a composite layer for overlay on persistent
sources. Includes app color mapping, whitelist/blacklist filtering, and auto-sizing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 21:10:32 +03:00
parent 80b48e3618
commit de04872fdc
16 changed files with 932 additions and 6 deletions

View File

@@ -30,6 +30,7 @@
<option value="mapped" data-i18n="color_strip.type.mapped">Mapped</option>
<option value="audio" data-i18n="color_strip.type.audio">Audio Reactive</option>
<option value="api_input" data-i18n="color_strip.type.api_input">API Input</option>
<option value="notification" data-i18n="color_strip.type.notification">Notification</option>
</select>
</div>
@@ -441,6 +442,90 @@
</div>
</div>
<!-- Notification-specific fields -->
<div id="css-editor-notification-section" style="display:none">
<div class="form-group">
<div class="label-row">
<label for="css-editor-notification-effect" data-i18n="color_strip.notification.effect">Effect:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.notification.effect.hint">Visual effect when a notification fires.</small>
<select id="css-editor-notification-effect">
<option value="flash" data-i18n="color_strip.notification.effect.flash">Flash</option>
<option value="pulse" data-i18n="color_strip.notification.effect.pulse">Pulse</option>
<option value="sweep" data-i18n="color_strip.notification.effect.sweep">Sweep</option>
</select>
</div>
<div class="form-group">
<div class="label-row">
<label for="css-editor-notification-duration">
<span data-i18n="color_strip.notification.duration">Duration (ms):</span>
<span id="css-editor-notification-duration-val">1500</span>
</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.notification.duration.hint">How long the notification effect plays, in milliseconds.</small>
<input type="range" id="css-editor-notification-duration" min="100" max="10000" step="100" value="1500"
oninput="document.getElementById('css-editor-notification-duration-val').textContent = this.value">
</div>
<div class="form-group">
<div class="label-row">
<label for="css-editor-notification-default-color" data-i18n="color_strip.notification.default_color">Default Color:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.notification.default_color.hint">Color used when the notification has no app-specific color mapping.</small>
<input type="color" id="css-editor-notification-default-color" value="#ffffff">
</div>
<div class="form-group">
<div class="label-row">
<label for="css-editor-notification-filter-mode" data-i18n="color_strip.notification.filter_mode">App Filter:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.notification.filter_mode.hint">Filter notifications by app name. Off = accept all, Whitelist = only listed apps, Blacklist = all except listed apps.</small>
<select id="css-editor-notification-filter-mode" onchange="onNotificationFilterModeChange()">
<option value="off" data-i18n="color_strip.notification.filter_mode.off">Off</option>
<option value="whitelist" data-i18n="color_strip.notification.filter_mode.whitelist">Whitelist</option>
<option value="blacklist" data-i18n="color_strip.notification.filter_mode.blacklist">Blacklist</option>
</select>
</div>
<div id="css-editor-notification-filter-list-group" class="form-group" style="display:none">
<div class="label-row">
<label data-i18n="color_strip.notification.filter_list">App List:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.notification.filter_list.hint">Comma-separated app names for the filter.</small>
<input type="text" id="css-editor-notification-filter-list" data-i18n-placeholder="color_strip.notification.filter_list.placeholder" placeholder="Discord, Slack, Telegram">
</div>
<details class="form-collapse">
<summary data-i18n="color_strip.notification.app_colors">App Colors</summary>
<div class="form-collapse-body">
<div class="form-group">
<div class="label-row">
<label data-i18n="color_strip.notification.app_colors.label">Color Mappings:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.notification.app_colors.hint">Per-app color overrides. Each row maps an app name to a specific color.</small>
<div id="notification-app-colors-list"></div>
<button type="button" class="btn btn-secondary" onclick="notificationAddAppColor()" data-i18n="color_strip.notification.app_colors.add">+ Add Mapping</button>
</div>
</div>
</details>
<div class="form-group" id="css-editor-notification-endpoint-group">
<div class="label-row">
<label data-i18n="color_strip.notification.endpoint">Webhook Endpoint:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.notification.endpoint.hint">Use this URL to trigger notifications from external systems.</small>
<div id="css-editor-notification-endpoint" class="template-config" style="font-family:monospace; font-size:0.85em; word-break:break-all;"></div>
</div>
</div>
<!-- Shared LED count field -->
<div id="css-editor-led-count-group" class="form-group">
<div class="label-row">