From ac51f6a2f6a9033888bd1142cffbf784e3743ed4 Mon Sep 17 00:00:00 2001 From: Will Miao Date: Sat, 13 Jun 2026 09:43:49 +0800 Subject: [PATCH] feat(settings): add adjustable card overlay blur setting (#973) --- locales/de.json | 4 +- locales/en.json | 4 +- locales/es.json | 4 +- locales/fr.json | 4 +- locales/he.json | 4 +- locales/ja.json | 4 +- locales/ko.json | 4 +- locales/ru.json | 4 +- locales/zh-CN.json | 4 +- locales/zh-TW.json | 4 +- static/css/components/card.css | 4 +- .../css/components/modal/settings-modal.css | 61 +++++++++++++++++++ static/js/managers/SettingsManager.js | 36 +++++++++++ static/js/state/index.js | 1 + .../components/modals/settings_modal.html | 18 ++++++ 15 files changed, 148 insertions(+), 12 deletions(-) diff --git a/locales/de.json b/locales/de.json index 71192ce0..c1131fd0 100644 --- a/locales/de.json +++ b/locales/de.json @@ -448,7 +448,9 @@ "modelName": "Modellname", "fileName": "Dateiname" }, - "modelNameDisplayHelp": "Wählen Sie aus, was in der Fußzeile der Modellkarte angezeigt werden soll" + "modelNameDisplayHelp": "Wählen Sie aus, was in der Fußzeile der Modellkarte angezeigt werden soll", + "cardBlurAmount": "Karten-Overlay-Unschärfe", + "cardBlurAmountHelp": "Passen Sie die Unschärfeintensität der Kopf- und Fußzeilen-Overlays auf Modell- und Rezeptkarten an (0 = keine Unschärfe, 20 = maximale Unschärfe)." }, "folderSettings": { "activeLibrary": "Aktive Bibliothek", diff --git a/locales/en.json b/locales/en.json index e563bb75..99e0e2d8 100644 --- a/locales/en.json +++ b/locales/en.json @@ -448,7 +448,9 @@ "modelName": "Model Name", "fileName": "File Name" }, - "modelNameDisplayHelp": "Choose what to display in the model card footer" + "modelNameDisplayHelp": "Choose what to display in the model card footer", + "cardBlurAmount": "Card Overlay Blur", + "cardBlurAmountHelp": "Adjust the blur intensity of the header and footer overlays on model and recipe cards (0 = no blur, 20 = maximum blur)." }, "folderSettings": { "activeLibrary": "Active Library", diff --git a/locales/es.json b/locales/es.json index ed36d0e5..014ea17d 100644 --- a/locales/es.json +++ b/locales/es.json @@ -448,7 +448,9 @@ "modelName": "Nombre del modelo", "fileName": "Nombre del archivo" }, - "modelNameDisplayHelp": "Elige qué mostrar en el pie de la tarjeta del modelo" + "modelNameDisplayHelp": "Elige qué mostrar en el pie de la tarjeta del modelo", + "cardBlurAmount": "Desenfoque de superposición de tarjetas", + "cardBlurAmountHelp": "Ajuste la intensidad de desenfoque de las superposiciones del encabezado y pie de página en las tarjetas de modelos y recetas (0 = sin desenfoque, 20 = desenfoque máximo)." }, "folderSettings": { "activeLibrary": "Biblioteca activa", diff --git a/locales/fr.json b/locales/fr.json index 847f4ddb..cca906fb 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -448,7 +448,9 @@ "modelName": "Nom du modèle", "fileName": "Nom du fichier" }, - "modelNameDisplayHelp": "Choisissez ce qui doit être affiché dans le pied de page de la carte du modèle" + "modelNameDisplayHelp": "Choisissez ce qui doit être affiché dans le pied de page de la carte du modèle", + "cardBlurAmount": "Flou de superposition des cartes", + "cardBlurAmountHelp": "Ajustez l'intensité du flou des superpositions d'en-tête et de pied de page sur les cartes de modèles et de recettes (0 = aucun flou, 20 = flou maximal)." }, "folderSettings": { "activeLibrary": "Bibliothèque active", diff --git a/locales/he.json b/locales/he.json index 38369163..2e80873b 100644 --- a/locales/he.json +++ b/locales/he.json @@ -448,7 +448,9 @@ "modelName": "שם מודל", "fileName": "שם קובץ" }, - "modelNameDisplayHelp": "בחר מה להציג בכותרת התחתונה של כרטיס המודל" + "modelNameDisplayHelp": "בחר מה להציג בכותרת התחתונה של כרטיס המודל", + "cardBlurAmount": "עוצמת טשטוש שכבת-על בכרטיס", + "cardBlurAmountHelp": "כוונן את עוצמת הטשטוש של שכבת-העל בכותרת ובכותרות תחתונה בכרטיסי מודל ומתכונים (0 = ללא טשטוש, 20 = טשטוש מקסימלי)." }, "folderSettings": { "activeLibrary": "ספרייה פעילה", diff --git a/locales/ja.json b/locales/ja.json index 7ac682e1..87231cf4 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -448,7 +448,9 @@ "modelName": "モデル名", "fileName": "ファイル名" }, - "modelNameDisplayHelp": "モデルカードのフッターに表示する内容を選択" + "modelNameDisplayHelp": "モデルカードのフッターに表示する内容を選択", + "cardBlurAmount": "カードオーバーレイのぼかし", + "cardBlurAmountHelp": "モデルカードとレシピカードのヘッダー・フッターオーバーレイのぼかし強度を調整します(0 = ぼかしなし、20 = 最大ぼかし)。" }, "folderSettings": { "activeLibrary": "アクティブライブラリ", diff --git a/locales/ko.json b/locales/ko.json index b1c8baee..d8cf62df 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -448,7 +448,9 @@ "modelName": "모델명", "fileName": "파일명" }, - "modelNameDisplayHelp": "모델 카드 하단에 표시할 내용을 선택하세요" + "modelNameDisplayHelp": "모델 카드 하단에 표시할 내용을 선택하세요", + "cardBlurAmount": "카드 오버레이 흐림 강도", + "cardBlurAmountHelp": "모델 및 레시피 카드의 헤더와 푸터 오버레이 흐림 강도를 조정합니다 (0 = 흐림 없음, 20 = 최대 흐림)." }, "folderSettings": { "activeLibrary": "활성 라이브러리", diff --git a/locales/ru.json b/locales/ru.json index 31040b00..f732048c 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -448,7 +448,9 @@ "modelName": "Название модели", "fileName": "Имя файла" }, - "modelNameDisplayHelp": "Выберите, что отображать в нижней части карточки модели" + "modelNameDisplayHelp": "Выберите, что отображать в нижней части карточки модели", + "cardBlurAmount": "Размытие наложения карточек", + "cardBlurAmountHelp": "Настройте интенсивность размытия наложений верхнего и нижнего колонтитулов на карточках моделей и рецептов (0 = без размытия, 20 = максимальное размытие)." }, "folderSettings": { "activeLibrary": "Активная библиотека", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index f87d4c92..40d54e95 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -448,7 +448,9 @@ "modelName": "模型名称", "fileName": "文件名" }, - "modelNameDisplayHelp": "选择在模型卡片底部显示的内容" + "modelNameDisplayHelp": "选择在模型卡片底部显示的内容", + "cardBlurAmount": "卡片叠加模糊强度", + "cardBlurAmountHelp": "调整模型和配方卡片上页眉和页脚叠加层的模糊强度(0 = 无模糊,20 = 最大模糊)。" }, "folderSettings": { "activeLibrary": "活动库", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index ba596dd8..fcbe22b8 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -448,7 +448,9 @@ "modelName": "模型名稱", "fileName": "檔案名稱" }, - "modelNameDisplayHelp": "選擇在模型卡片底部顯示的內容" + "modelNameDisplayHelp": "選擇在模型卡片底部顯示的內容", + "cardBlurAmount": "卡片疊加模糊強度", + "cardBlurAmountHelp": "調整模型和配方卡片上頁首和頁尾疊加層的模糊強度(0 = 無模糊,20 = 最大模糊)。" }, "folderSettings": { "activeLibrary": "使用中的資料庫", diff --git a/static/css/components/card.css b/static/css/components/card.css index 1cd7a1f9..71bf2bb5 100644 --- a/static/css/components/card.css +++ b/static/css/components/card.css @@ -278,7 +278,7 @@ left: 0; right: 0; background: linear-gradient(transparent 15%, oklch(0% 0 0 / 0.75)); - backdrop-filter: blur(8px); + backdrop-filter: blur(var(--card-blur-amount, 8px)); color: white; padding: var(--space-1); display: flex; @@ -294,7 +294,7 @@ left: 0; right: 0; background: linear-gradient(oklch(0% 0 0 / 0.75), transparent 85%); - backdrop-filter: blur(8px); + backdrop-filter: blur(var(--card-blur-amount, 8px)); color: white; padding: var(--space-1); display: flex; diff --git a/static/css/components/modal/settings-modal.css b/static/css/components/modal/settings-modal.css index 9002a704..41a390dc 100644 --- a/static/css/components/modal/settings-modal.css +++ b/static/css/components/modal/settings-modal.css @@ -813,6 +813,67 @@ outline: none; } +/* Range Slider Control */ +.range-control { + width: 100%; + display: flex; + align-items: center; + gap: 10px; + justify-content: flex-end; +} + +.range-control input[type="range"] { + width: 120px; + height: 4px; + -webkit-appearance: none; + appearance: none; + background: var(--border-color); + border-radius: 2px; + outline: none; + cursor: pointer; + flex-shrink: 0; +} + +.range-control input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 16px; + height: 16px; + border-radius: 50%; + background: var(--lora-accent); + cursor: pointer; + border: 2px solid var(--lora-surface); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + transition: transform 0.15s ease; +} + +.range-control input[type="range"]::-webkit-slider-thumb:hover { + transform: scale(1.15); +} + +.range-control input[type="range"]::-moz-range-thumb { + width: 16px; + height: 16px; + border-radius: 50%; + background: var(--lora-accent); + cursor: pointer; + border: 2px solid var(--lora-surface); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); +} + +.range-control .range-value { + min-width: 36px; + text-align: center; + font-size: 0.9em; + font-weight: 600; + color: var(--text-color); + font-variant-numeric: tabular-nums; +} + +[data-theme="dark"] .range-control input[type="range"] { + background: rgba(255, 255, 255, 0.15); +} + /* Toggle Switch */ .toggle-switch { position: relative; diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 5fbc00fc..adcaf7f2 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -804,6 +804,16 @@ export class SettingsManager { ); } + // Set card blur amount slider + const cardBlurAmountInput = document.getElementById('cardBlurAmount'); + if (cardBlurAmountInput) { + cardBlurAmountInput.value = state.global.settings.card_blur_amount ?? 8; + } + const cardBlurAmountValue = document.getElementById('cardBlurAmountValue'); + if (cardBlurAmountValue) { + cardBlurAmountValue.textContent = `${state.global.settings.card_blur_amount ?? 8}px`; + } + const usePortableCheckbox = document.getElementById('usePortableSettings'); if (usePortableCheckbox) { usePortableCheckbox.checked = !!state.global.settings.use_portable_settings; @@ -2051,6 +2061,28 @@ export class SettingsManager { } } + async saveRangeSetting(elementId, displayId, settingKey) { + const element = document.getElementById(elementId); + if (!element) return; + + const value = parseInt(element.value, 10); + + try { + await this.saveSetting(settingKey, value); + this.applyFrontendSettings(); + + // Update the displayed value next to the slider + const displayEl = document.getElementById(displayId); + if (displayEl) { + displayEl.textContent = `${value}px`; + } + + showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success'); + } catch (error) { + showToast('toast.settings.settingSaveFailed', { message: error.message }, 'error'); + } + } + updateExampleImagesOpenSettingsVisibility() { const openMode = state.global.settings.example_images_open_mode || 'system'; const localRootSetting = document.getElementById('exampleImagesLocalRootSetting'); @@ -2887,6 +2919,10 @@ export class SettingsManager { } applyFrontendSettings() { + // Apply card blur amount to CSS custom property + const cardBlurAmount = state.global.settings.card_blur_amount ?? 8; + document.documentElement.style.setProperty('--card-blur-amount', `${cardBlurAmount}px`); + // Apply autoplay setting to existing videos in card previews const autoplayOnHover = state.global.settings.autoplay_on_hover; document.querySelectorAll('.card-preview video').forEach(video => { diff --git a/static/js/state/index.js b/static/js/state/index.js index c44b8f80..26bd0bc9 100644 --- a/static/js/state/index.js +++ b/static/js/state/index.js @@ -32,6 +32,7 @@ const DEFAULT_SETTINGS_BASE = Object.freeze({ auto_download_example_images: false, blur_mature_content: true, mature_blur_level: 'R', + card_blur_amount: 8, autoplay_on_hover: false, display_density: 'default', card_info_display: 'always', diff --git a/templates/components/modals/settings_modal.html b/templates/components/modals/settings_modal.html index 1dd221de..f51c9903 100644 --- a/templates/components/modals/settings_modal.html +++ b/templates/components/modals/settings_modal.html @@ -448,6 +448,7 @@ + @@ -556,6 +557,23 @@ +
+
+
+ +
+
+ + 8px +
+
+
+