Add visual IconSelect grid for filter type picker in PP template editor

Replace plain filter type dropdown with icon grid showing each filter
with its icon and description. Selecting a filter immediately adds it
to the template (no separate "+" click needed).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 00:45:43 +03:00
parent a728c75113
commit be91e74c6e
5 changed files with 76 additions and 1 deletions

View File

@@ -50,6 +50,7 @@ import {
import { wrapCard } from '../core/card-colors.js';
import { IconSelect } from '../core/icon-select.js';
import { EntitySelect } from '../core/entity-palette.js';
import * as P from '../core/icon-paths.js';
// ── Card section instances ──
const csRawStreams = new CardSection('raw-streams', { titleKey: 'streams.section.streams', gridClass: 'templates-grid', addCardOnclick: "showAddStreamModal('raw')", keyAttr: 'data-stream-id' });
@@ -2005,12 +2006,49 @@ function _getFilterName(filterId) {
return translated;
}
let _filterIconSelect = null;
const _FILTER_ICONS = {
brightness: P.sunDim,
saturation: P.palette,
gamma: P.sun,
downscaler: P.monitor,
pixelate: P.layoutDashboard,
auto_crop: P.target,
flip: P.rotateCw,
color_correction: P.palette,
filter_template: P.fileText,
frame_interpolation: P.fastForward,
noise_gate: P.volume2,
palette_quantization: P.sparkles,
};
function _populateFilterSelect() {
const select = document.getElementById('pp-add-filter-select');
select.innerHTML = `<option value="">${t('filters.select_type')}</option>`;
const items = [
{ value: '', icon: `<svg class="icon" viewBox="0 0 24 24">${P.wrench}</svg>`, label: t('filters.select_type') },
];
for (const f of _availableFilters) {
const name = _getFilterName(f.filter_id);
select.innerHTML += `<option value="${f.filter_id}">${name}</option>`;
const pathData = _FILTER_ICONS[f.filter_id] || P.wrench;
items.push({
value: f.filter_id,
icon: `<svg class="icon" viewBox="0 0 24 24">${pathData}</svg>`,
label: name,
desc: t(`filters.${f.filter_id}.desc`),
});
}
if (_filterIconSelect) {
_filterIconSelect.updateItems(items);
} else if (items.length > 0) {
_filterIconSelect = new IconSelect({
target: select,
items,
columns: 2,
onChange: () => addFilterFromSelect(),
});
}
}
@@ -2285,6 +2323,7 @@ export function addFilterFromSelect() {
_modalFilters.push({ filter_id: filterId, options, _expanded: true });
select.value = '';
if (_filterIconSelect) _filterIconSelect.setValue('');
renderModalFilterList();
_autoGeneratePPTemplateName();
}

View File

@@ -382,17 +382,29 @@
"filters.drag_to_reorder": "Drag to reorder",
"filters.empty": "No filters added. Use the selector below to add filters.",
"filters.brightness": "Brightness",
"filters.brightness.desc": "Adjust overall image brightness",
"filters.saturation": "Saturation",
"filters.saturation.desc": "Boost or reduce color intensity",
"filters.gamma": "Gamma",
"filters.gamma.desc": "Non-linear brightness curve correction",
"filters.downscaler": "Downscaler",
"filters.downscaler.desc": "Reduce resolution for faster processing",
"filters.pixelate": "Pixelate",
"filters.pixelate.desc": "Mosaic-style block averaging",
"filters.auto_crop": "Auto Crop",
"filters.auto_crop.desc": "Remove black bars from letterboxed content",
"filters.flip": "Flip",
"filters.flip.desc": "Mirror image horizontally or vertically",
"filters.color_correction": "Color Correction",
"filters.color_correction.desc": "White balance and color temperature",
"filters.filter_template": "Filter Template",
"filters.filter_template.desc": "Embed another processing template",
"filters.frame_interpolation": "Frame Interpolation",
"filters.frame_interpolation.desc": "Blend between frames for smoother output",
"filters.noise_gate": "Noise Gate",
"filters.noise_gate.desc": "Suppress small color changes below threshold",
"filters.palette_quantization": "Palette Quantization",
"filters.palette_quantization.desc": "Reduce colors to a limited palette",
"postprocessing.description_label": "Description (optional):",
"postprocessing.description_placeholder": "Describe this template...",
"postprocessing.created": "Template created successfully",

View File

@@ -382,17 +382,29 @@
"filters.drag_to_reorder": "Перетащите для изменения порядка",
"filters.empty": "Фильтры не добавлены. Используйте селектор ниже для добавления.",
"filters.brightness": "Яркость",
"filters.brightness.desc": "Регулировка общей яркости изображения",
"filters.saturation": "Насыщенность",
"filters.saturation.desc": "Усиление или снижение интенсивности цвета",
"filters.gamma": "Гамма",
"filters.gamma.desc": "Нелинейная коррекция кривой яркости",
"filters.downscaler": "Уменьшение",
"filters.downscaler.desc": "Снижение разрешения для быстрой обработки",
"filters.pixelate": "Пикселизация",
"filters.pixelate.desc": "Мозаичное усреднение блоков",
"filters.auto_crop": "Авто Обрезка",
"filters.auto_crop.desc": "Удаление чёрных полос из леттербокса",
"filters.flip": "Отражение",
"filters.flip.desc": "Зеркальное отражение по горизонтали или вертикали",
"filters.color_correction": "Цветокоррекция",
"filters.color_correction.desc": "Баланс белого и цветовая температура",
"filters.filter_template": "Шаблон фильтров",
"filters.filter_template.desc": "Встроить другой шаблон обработки",
"filters.frame_interpolation": "Интерполяция кадров",
"filters.frame_interpolation.desc": "Сглаживание между кадрами",
"filters.noise_gate": "Шумоподавление",
"filters.noise_gate.desc": "Подавление малых изменений цвета ниже порога",
"filters.palette_quantization": "Квантизация палитры",
"filters.palette_quantization.desc": "Сокращение цветов до ограниченной палитры",
"postprocessing.description_label": "Описание (необязательно):",
"postprocessing.description_placeholder": "Опишите этот шаблон...",
"postprocessing.created": "Шаблон успешно создан",

View File

@@ -382,17 +382,29 @@
"filters.drag_to_reorder": "拖动以重新排序",
"filters.empty": "尚未添加滤镜。使用下方选择器添加滤镜。",
"filters.brightness": "亮度",
"filters.brightness.desc": "调整整体图像亮度",
"filters.saturation": "饱和度",
"filters.saturation.desc": "增强或降低色彩强度",
"filters.gamma": "伽马",
"filters.gamma.desc": "非线性亮度曲线校正",
"filters.downscaler": "缩小",
"filters.downscaler.desc": "降低分辨率以加快处理",
"filters.pixelate": "像素化",
"filters.pixelate.desc": "马赛克式块平均",
"filters.auto_crop": "自动裁剪",
"filters.auto_crop.desc": "移除信箱式内容的黑边",
"filters.flip": "翻转",
"filters.flip.desc": "水平或垂直镜像翻转",
"filters.color_correction": "色彩校正",
"filters.color_correction.desc": "白平衡和色温调整",
"filters.filter_template": "滤镜模板",
"filters.filter_template.desc": "嵌入另一个处理模板",
"filters.frame_interpolation": "帧插值",
"filters.frame_interpolation.desc": "帧间混合以获得更平滑的输出",
"filters.noise_gate": "噪声门",
"filters.noise_gate.desc": "抑制低于阈值的细微色彩变化",
"filters.palette_quantization": "调色板量化",
"filters.palette_quantization.desc": "将颜色减少到有限调色板",
"postprocessing.description_label": "描述(可选):",
"postprocessing.description_placeholder": "描述此模板...",
"postprocessing.created": "模板创建成功",

View File

@@ -7,7 +7,7 @@
* - Navigation: network-first with offline fallback
*/
const CACHE_NAME = 'ledgrab-v19';
const CACHE_NAME = 'ledgrab-v20';
// Only pre-cache static assets (no auth required).
// Do NOT pre-cache '/' — it requires API key auth and would cache an error page.