`).join('');
@@ -647,8 +648,9 @@ function _loadNotificationState(css) {
document.getElementById('css-editor-notification-duration-val').textContent = dur;
document.getElementById('css-editor-notification-default-color').value = css.default_color || '#ffffff';
document.getElementById('css-editor-notification-filter-mode').value = css.app_filter_mode || 'off';
- document.getElementById('css-editor-notification-filter-list').value = (css.app_filter_list || []).join(', ');
+ document.getElementById('css-editor-notification-filter-list').value = (css.app_filter_list || []).join('\n');
onNotificationFilterModeChange();
+ _attachNotificationProcessPicker();
// App colors dict → list
const ac = css.app_colors || {};
@@ -666,11 +668,18 @@ function _resetNotificationState() {
document.getElementById('css-editor-notification-filter-mode').value = 'off';
document.getElementById('css-editor-notification-filter-list').value = '';
onNotificationFilterModeChange();
+ _attachNotificationProcessPicker();
_notificationAppColors = [];
_notificationAppColorsRenderList();
_showNotificationEndpoint(null);
}
+function _attachNotificationProcessPicker() {
+ const container = document.getElementById('css-editor-notification-filter-picker-container');
+ const textarea = document.getElementById('css-editor-notification-filter-list');
+ if (container && textarea) attachProcessPicker(container, textarea);
+}
+
function _showNotificationEndpoint(cssId) {
const el = document.getElementById('css-editor-notification-endpoint');
if (!el) return;
@@ -811,7 +820,6 @@ export function createColorStripCard(source, pictureSourceMap, audioSourceMap) {
${defColor.toUpperCase()}
${appCount > 0 ? `${ICON_PALETTE} ${appCount} ${t('color_strip.notification.app_count')}` : ''}
- ${source.led_count ? `${ICON_LED} ${source.led_count}` : ''}
`;
} else {
const ps = pictureSourceMap && pictureSourceMap[source.picture_source_id];
@@ -1155,7 +1163,7 @@ export async function saveCSSEditor() {
if (!cssId) payload.source_type = 'api_input';
} else if (sourceType === 'notification') {
const filterList = document.getElementById('css-editor-notification-filter-list').value
- .split(',').map(s => s.trim()).filter(Boolean);
+ .split('\n').map(s => s.trim()).filter(Boolean);
payload = {
name,
notification_effect: document.getElementById('css-editor-notification-effect').value,
@@ -1164,7 +1172,6 @@ export async function saveCSSEditor() {
app_filter_mode: document.getElementById('css-editor-notification-filter-mode').value,
app_filter_list: filterList,
app_colors: _notificationGetAppColorsDict(),
- led_count: parseInt(document.getElementById('css-editor-led-count').value) || 0,
};
if (!cssId) payload.source_type = 'notification';
} else {
diff --git a/server/src/wled_controller/static/locales/en.json b/server/src/wled_controller/static/locales/en.json
index 2b9b670..97e565a 100644
--- a/server/src/wled_controller/static/locales/en.json
+++ b/server/src/wled_controller/static/locales/en.json
@@ -826,8 +826,8 @@
"color_strip.notification.filter_mode.whitelist": "Whitelist",
"color_strip.notification.filter_mode.blacklist": "Blacklist",
"color_strip.notification.filter_list": "App List:",
- "color_strip.notification.filter_list.hint": "Comma-separated app names for the filter.",
- "color_strip.notification.filter_list.placeholder": "Discord, Slack, Telegram",
+ "color_strip.notification.filter_list.hint": "One app name per line. Use Browse to pick from running processes.",
+ "color_strip.notification.filter_list.placeholder": "Discord\nSlack\nTelegram",
"color_strip.notification.app_colors": "App Colors",
"color_strip.notification.app_colors.label": "Color Mappings:",
"color_strip.notification.app_colors.hint": "Per-app color overrides. Each row maps an app name to a specific notification color.",
diff --git a/server/src/wled_controller/static/locales/ru.json b/server/src/wled_controller/static/locales/ru.json
index c3baf94..c0331c2 100644
--- a/server/src/wled_controller/static/locales/ru.json
+++ b/server/src/wled_controller/static/locales/ru.json
@@ -826,8 +826,8 @@
"color_strip.notification.filter_mode.whitelist": "Белый список",
"color_strip.notification.filter_mode.blacklist": "Чёрный список",
"color_strip.notification.filter_list": "Список приложений:",
- "color_strip.notification.filter_list.hint": "Имена приложений через запятую.",
- "color_strip.notification.filter_list.placeholder": "Discord, Slack, Telegram",
+ "color_strip.notification.filter_list.hint": "Одно имя приложения на строку. Используйте «Обзор» для выбора из запущенных процессов.",
+ "color_strip.notification.filter_list.placeholder": "Discord\nSlack\nTelegram",
"color_strip.notification.app_colors": "Цвета приложений",
"color_strip.notification.app_colors.label": "Назначения цветов:",
"color_strip.notification.app_colors.hint": "Индивидуальные цвета для приложений. Каждая строка связывает имя приложения с цветом уведомления.",
diff --git a/server/src/wled_controller/static/locales/zh.json b/server/src/wled_controller/static/locales/zh.json
index 4dc65d8..9930c5e 100644
--- a/server/src/wled_controller/static/locales/zh.json
+++ b/server/src/wled_controller/static/locales/zh.json
@@ -826,8 +826,8 @@
"color_strip.notification.filter_mode.whitelist": "白名单",
"color_strip.notification.filter_mode.blacklist": "黑名单",
"color_strip.notification.filter_list": "应用列表:",
- "color_strip.notification.filter_list.hint": "以逗号分隔的应用名称。",
- "color_strip.notification.filter_list.placeholder": "Discord, Slack, Telegram",
+ "color_strip.notification.filter_list.hint": "每行一个应用名称。使用「浏览」从运行中的进程中选择。",
+ "color_strip.notification.filter_list.placeholder": "Discord\nSlack\nTelegram",
"color_strip.notification.app_colors": "应用颜色",
"color_strip.notification.app_colors.label": "颜色映射:",
"color_strip.notification.app_colors.hint": "每个应用的自定义通知颜色。每行将一个应用名称映射到特定颜色。",
diff --git a/server/src/wled_controller/static/sw.js b/server/src/wled_controller/static/sw.js
index 9f698a5..3b40ea5 100644
--- a/server/src/wled_controller/static/sw.js
+++ b/server/src/wled_controller/static/sw.js
@@ -7,7 +7,7 @@
* - Navigation: network-first with offline fallback
*/
-const CACHE_NAME = 'ledgrab-v12';
+const CACHE_NAME = 'ledgrab-v14';
// Only pre-cache static assets (no auth required).
// Do NOT pre-cache '/' — it requires API key auth and would cache an error page.
diff --git a/server/src/wled_controller/storage/color_strip_source.py b/server/src/wled_controller/storage/color_strip_source.py
index 3b1d94a..cb48901 100644
--- a/server/src/wled_controller/storage/color_strip_source.py
+++ b/server/src/wled_controller/storage/color_strip_source.py
@@ -238,7 +238,6 @@ class ColorStripSource:
app_filter_mode=data.get("app_filter_mode") or "off",
app_filter_list=app_filter_list,
os_listener=bool(data.get("os_listener", False)),
- led_count=data.get("led_count") or 0,
)
# Default: "picture" type
@@ -504,7 +503,6 @@ class NotificationColorStripSource(ColorStripSource):
app_filter_mode: str = "off" # off | whitelist | blacklist
app_filter_list: list = field(default_factory=list) # app names for filter
os_listener: bool = False # whether to listen for OS notifications
- led_count: int = 0 # 0 = use device LED count
def to_dict(self) -> dict:
d = super().to_dict()
@@ -515,5 +513,4 @@ class NotificationColorStripSource(ColorStripSource):
d["app_filter_mode"] = self.app_filter_mode
d["app_filter_list"] = list(self.app_filter_list)
d["os_listener"] = self.os_listener
- d["led_count"] = self.led_count
return d
diff --git a/server/src/wled_controller/storage/color_strip_store.py b/server/src/wled_controller/storage/color_strip_store.py
index 0c1dc53..f641c27 100644
--- a/server/src/wled_controller/storage/color_strip_store.py
+++ b/server/src/wled_controller/storage/color_strip_store.py
@@ -279,7 +279,6 @@ class ColorStripStore:
app_filter_mode=app_filter_mode or "off",
app_filter_list=app_filter_list if isinstance(app_filter_list, list) else [],
os_listener=bool(os_listener) if os_listener is not None else False,
- led_count=led_count,
)
else:
if calibration is None:
@@ -472,8 +471,6 @@ class ColorStripStore:
source.app_filter_list = app_filter_list
if os_listener is not None:
source.os_listener = bool(os_listener)
- if led_count is not None:
- source.led_count = led_count
source.updated_at = datetime.utcnow()
self._save()
diff --git a/server/src/wled_controller/templates/modals/css-editor.html b/server/src/wled_controller/templates/modals/css-editor.html
index ae27f9e..df0a8f4 100644
--- a/server/src/wled_controller/templates/modals/css-editor.html
+++ b/server/src/wled_controller/templates/modals/css-editor.html
@@ -145,7 +145,6 @@
Colors to cycle through smoothly. At least 2 required.
-
@@ -497,8 +496,17 @@
- Comma-separated app names for the filter.
-
+ One app name per line. Use Browse to pick from running processes.
+