mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
feat: add metadata refresh skip paths setting, #790
This commit is contained in:
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "Fehler beim Speichern der Ausschlüsse: {message}"
|
"saveFailed": "Fehler beim Speichern der Ausschlüsse: {message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "Metadaten-Aktualisierung: Übersprungene Pfade",
|
||||||
|
"placeholder": "Beispiel: temp, archived/old, test_models",
|
||||||
|
"help": "Modelle in diesen Verzeichnispfaden bei der Massenaktualisierung der Metadaten (\"Alle Metadaten abrufen\") überspringen. Geben Sie durch Kommas getrennte relative Ordnerpfade ein.",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "Geben Sie mindestens einen durch Kommas getrennten Pfad ein.",
|
||||||
|
"saveFailed": "Übersprungene Pfade konnten nicht gespeichert werden: {message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "Anzeige-Dichte",
|
"displayDensity": "Anzeige-Dichte",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "Unable to save exclusions: {message}"
|
"saveFailed": "Unable to save exclusions: {message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "Metadata refresh skip paths",
|
||||||
|
"placeholder": "Example: temp, archived/old, test_models",
|
||||||
|
"help": "Skip models in these directory paths during bulk metadata refresh (\"Fetch All Metadata\"). Enter relative folder paths separated by commas.",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "Enter at least one path separated by commas.",
|
||||||
|
"saveFailed": "Unable to save skip paths: {message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "Display Density",
|
"displayDensity": "Display Density",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "No se pudieron guardar las exclusiones: {message}"
|
"saveFailed": "No se pudieron guardar las exclusiones: {message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "Rutas a omitir en la actualización de metadatos",
|
||||||
|
"placeholder": "Ejemplo: temp, archived/old, test_models",
|
||||||
|
"help": "Omitir modelos en estas rutas de directorio durante la actualización masiva de metadatos (\"Obtener todos los metadatos\"). Ingrese rutas de carpetas relativas separadas por comas.",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "Ingrese al menos una ruta separada por comas.",
|
||||||
|
"saveFailed": "No se pudieron guardar las rutas a omitir: {message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "Densidad de visualización",
|
"displayDensity": "Densidad de visualización",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "Impossible d'enregistrer les exclusions : {message}"
|
"saveFailed": "Impossible d'enregistrer les exclusions : {message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "Chemins à ignorer pour l'actualisation des métadonnées",
|
||||||
|
"placeholder": "Exemple : temp, archived/old, test_models",
|
||||||
|
"help": "Ignorer les modèles dans ces chemins de répertoires lors de l'actualisation groupée des métadonnées (\"Récupérer toutes les métadonnées\"). Entrez des chemins de dossiers relatifs séparés par des virgules.",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "Entrez au moins un chemin séparé par des virgules.",
|
||||||
|
"saveFailed": "Impossible d'enregistrer les chemins à ignorer : {message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "Densité d'affichage",
|
"displayDensity": "Densité d'affichage",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "לא ניתן לשמור את ההוצאות: {message}"
|
"saveFailed": "לא ניתן לשמור את ההוצאות: {message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "נתיבים לדילוג ברענון מטא-נתונים",
|
||||||
|
"placeholder": "דוגמה: temp, archived/old, test_models",
|
||||||
|
"help": "דלג על מודלים בנתיבי תיקיות אלה בעת רענון מטא-נתונים המוני (\"אחזר את כל המטא-נתונים\"). הזן נתיבי תיקיות יחסיים מופרדים בפסיקים.",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "הזן לפחות נתיב אחד מופרד בפסיקים.",
|
||||||
|
"saveFailed": "לא ניתן לשמור נתיבי דילוג: {message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "צפיפות תצוגה",
|
"displayDensity": "צפיפות תצוגה",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "除外設定を保存できませんでした: {message}"
|
"saveFailed": "除外設定を保存できませんでした: {message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "メタデータ更新スキップパス",
|
||||||
|
"placeholder": "例:temp, archived/old, test_models",
|
||||||
|
"help": "一括メタデータ更新(「すべてのメタデータを取得」)時にこれらのディレクトリパス内のモデルをスキップします。カンマ区切りで相対フォルダパスを入力してください。",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "カンマで区切って少なくとも1つのパスを入力してください。",
|
||||||
|
"saveFailed": "スキップパスの保存に失敗しました:{message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "表示密度",
|
"displayDensity": "表示密度",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "제외 항목을 저장할 수 없습니다: {message}"
|
"saveFailed": "제외 항목을 저장할 수 없습니다: {message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "메타데이터 새로고침 건너뛰기 경로",
|
||||||
|
"placeholder": "예: temp, archived/old, test_models",
|
||||||
|
"help": "일괄 메타데이터 새로고침(\"모든 메타데이터 가져오기\") 시 이 디렉터리 경로의 모델을 건너뜁니다. 쉼표로 구분된 상대 폴더 경로를 입력하세요.",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "쉼표로 구분하여 하나 이상의 경로를 입력하세요.",
|
||||||
|
"saveFailed": "건너뛰기 경로를 저장할 수 없습니다: {message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "표시 밀도",
|
"displayDensity": "표시 밀도",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "Не удалось сохранить исключения: {message}"
|
"saveFailed": "Не удалось сохранить исключения: {message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "Пути для пропуска обновления метаданных",
|
||||||
|
"placeholder": "Пример: temp, archived/old, test_models",
|
||||||
|
"help": "Пропускать модели в этих каталогах при массовом обновлении метаданных («Получить все метаданные»). Введите относительные пути папок через запятую.",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "Введите хотя бы один путь, разделённый запятыми.",
|
||||||
|
"saveFailed": "Не удалось сохранить пути для пропуска: {message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "Плотность отображения",
|
"displayDensity": "Плотность отображения",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "无法保存排除项:{message}"
|
"saveFailed": "无法保存排除项:{message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "元数据刷新跳过路径",
|
||||||
|
"placeholder": "示例:temp, archived/old, test_models",
|
||||||
|
"help": "批量刷新元数据(\"获取全部元数据\")时跳过这些目录路径中的模型。输入以逗号分隔的相对文件夹路径。",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "请输入至少一个路径,以逗号分隔。",
|
||||||
|
"saveFailed": "无法保存跳过路径:{message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "显示密度",
|
"displayDensity": "显示密度",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -292,6 +292,15 @@
|
|||||||
"saveFailed": "無法儲存排除項目:{message}"
|
"saveFailed": "無法儲存排除項目:{message}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"metadataRefreshSkipPaths": {
|
||||||
|
"label": "中繼資料重新整理跳過路徑",
|
||||||
|
"placeholder": "範例:temp, archived/old, test_models",
|
||||||
|
"help": "批次重新整理中繼資料(「擷取所有中繼資料」)時跳過這些目錄路徑中的模型。輸入以逗號分隔的相對資料夾路徑。",
|
||||||
|
"validation": {
|
||||||
|
"noPaths": "請輸入至少一個路徑,以逗號分隔。",
|
||||||
|
"saveFailed": "無法儲存跳過路徑:{message}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"layoutSettings": {
|
"layoutSettings": {
|
||||||
"displayDensity": "顯示密度",
|
"displayDensity": "顯示密度",
|
||||||
"displayDensityOptions": {
|
"displayDensityOptions": {
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ DEFAULT_SETTINGS: Dict[str, Any] = {
|
|||||||
"model_card_footer_action": "replace_preview",
|
"model_card_footer_action": "replace_preview",
|
||||||
"update_flag_strategy": "same_base",
|
"update_flag_strategy": "same_base",
|
||||||
"auto_organize_exclusions": [],
|
"auto_organize_exclusions": [],
|
||||||
|
"metadata_refresh_skip_paths": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -261,6 +262,17 @@ class SettingsManager:
|
|||||||
self.settings["auto_organize_exclusions"] = []
|
self.settings["auto_organize_exclusions"] = []
|
||||||
inserted_defaults = True
|
inserted_defaults = True
|
||||||
|
|
||||||
|
if "metadata_refresh_skip_paths" in self.settings:
|
||||||
|
normalized_skip_paths = self.normalize_metadata_refresh_skip_paths(
|
||||||
|
self.settings.get("metadata_refresh_skip_paths")
|
||||||
|
)
|
||||||
|
if normalized_skip_paths != self.settings.get("metadata_refresh_skip_paths"):
|
||||||
|
self.settings["metadata_refresh_skip_paths"] = normalized_skip_paths
|
||||||
|
updated_existing = True
|
||||||
|
else:
|
||||||
|
self.settings["metadata_refresh_skip_paths"] = []
|
||||||
|
inserted_defaults = True
|
||||||
|
|
||||||
for key, value in defaults.items():
|
for key, value in defaults.items():
|
||||||
if key == "priority_tags":
|
if key == "priority_tags":
|
||||||
continue
|
continue
|
||||||
@@ -805,6 +817,7 @@ class SettingsManager:
|
|||||||
defaults['priority_tags'] = DEFAULT_PRIORITY_TAG_CONFIG.copy()
|
defaults['priority_tags'] = DEFAULT_PRIORITY_TAG_CONFIG.copy()
|
||||||
defaults.setdefault('folder_paths', {})
|
defaults.setdefault('folder_paths', {})
|
||||||
defaults['auto_organize_exclusions'] = []
|
defaults['auto_organize_exclusions'] = []
|
||||||
|
defaults['metadata_refresh_skip_paths'] = []
|
||||||
|
|
||||||
library_name = defaults.get("active_library") or "default"
|
library_name = defaults.get("active_library") or "default"
|
||||||
default_library = self._build_library_payload(
|
default_library = self._build_library_payload(
|
||||||
@@ -876,6 +889,44 @@ class SettingsManager:
|
|||||||
self._save_settings()
|
self._save_settings()
|
||||||
return exclusions
|
return exclusions
|
||||||
|
|
||||||
|
def normalize_metadata_refresh_skip_paths(self, value: Any) -> List[str]:
|
||||||
|
if value is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if isinstance(value, str):
|
||||||
|
candidates: Iterable[str] = (
|
||||||
|
value.replace("\n", ",").replace(";", ",").split(",")
|
||||||
|
)
|
||||||
|
elif isinstance(value, Sequence) and not isinstance(value, (bytes, bytearray, str)):
|
||||||
|
candidates = value
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
paths: List[str] = []
|
||||||
|
for raw in candidates:
|
||||||
|
if isinstance(raw, str):
|
||||||
|
token = raw.replace("\\", "/").strip().strip("/")
|
||||||
|
if token:
|
||||||
|
paths.append(token)
|
||||||
|
|
||||||
|
unique_paths: List[str] = []
|
||||||
|
seen = set()
|
||||||
|
for path in paths:
|
||||||
|
if path not in seen:
|
||||||
|
seen.add(path)
|
||||||
|
unique_paths.append(path)
|
||||||
|
|
||||||
|
return unique_paths
|
||||||
|
|
||||||
|
def get_metadata_refresh_skip_paths(self) -> List[str]:
|
||||||
|
skip_paths = self.normalize_metadata_refresh_skip_paths(
|
||||||
|
self.settings.get("metadata_refresh_skip_paths")
|
||||||
|
)
|
||||||
|
if skip_paths != self.settings.get("metadata_refresh_skip_paths"):
|
||||||
|
self.settings["metadata_refresh_skip_paths"] = skip_paths
|
||||||
|
self._save_settings()
|
||||||
|
return skip_paths
|
||||||
|
|
||||||
def get_startup_messages(self) -> List[Dict[str, Any]]:
|
def get_startup_messages(self) -> List[Dict[str, Any]]:
|
||||||
return [message.copy() for message in self._startup_messages]
|
return [message.copy() for message in self._startup_messages]
|
||||||
|
|
||||||
@@ -913,6 +964,8 @@ class SettingsManager:
|
|||||||
"""Set setting value and save"""
|
"""Set setting value and save"""
|
||||||
if key == "auto_organize_exclusions":
|
if key == "auto_organize_exclusions":
|
||||||
value = self.normalize_auto_organize_exclusions(value)
|
value = self.normalize_auto_organize_exclusions(value)
|
||||||
|
elif key == "metadata_refresh_skip_paths":
|
||||||
|
value = self.normalize_metadata_refresh_skip_paths(value)
|
||||||
self.settings[key] = value
|
self.settings[key] = value
|
||||||
portable_switch_pending = False
|
portable_switch_pending = False
|
||||||
if key == "use_portable_settings" and isinstance(value, bool):
|
if key == "use_portable_settings" and isinstance(value, bool):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional, Protocol, Sequence
|
from typing import Any, Dict, List, Optional, Protocol, Sequence
|
||||||
|
|
||||||
from ..metadata_sync_service import MetadataSyncService
|
from ..metadata_sync_service import MetadataSyncService
|
||||||
from ...utils.metadata_manager import MetadataManager
|
from ...utils.metadata_manager import MetadataManager
|
||||||
@@ -43,11 +43,13 @@ class BulkMetadataRefreshUseCase:
|
|||||||
total_models = len(cache.raw_data)
|
total_models = len(cache.raw_data)
|
||||||
|
|
||||||
enable_metadata_archive_db = self._settings.get("enable_metadata_archive_db", False)
|
enable_metadata_archive_db = self._settings.get("enable_metadata_archive_db", False)
|
||||||
|
skip_paths = self._settings.get("metadata_refresh_skip_paths", [])
|
||||||
to_process: Sequence[Dict[str, Any]] = [
|
to_process: Sequence[Dict[str, Any]] = [
|
||||||
model
|
model
|
||||||
for model in cache.raw_data
|
for model in cache.raw_data
|
||||||
if model.get("sha256")
|
if model.get("sha256")
|
||||||
and not model.get("skip_metadata_refresh", False)
|
and not model.get("skip_metadata_refresh", False)
|
||||||
|
and not self._is_in_skip_path(model.get("folder", ""), skip_paths)
|
||||||
and (not model.get("civitai") or not model["civitai"].get("id"))
|
and (not model.get("civitai") or not model["civitai"].get("id"))
|
||||||
and not (
|
and not (
|
||||||
# Skip models confirmed not on CivitAI when no need to retry
|
# Skip models confirmed not on CivitAI when no need to retry
|
||||||
@@ -121,6 +123,21 @@ class BulkMetadataRefreshUseCase:
|
|||||||
|
|
||||||
return {"success": True, "message": message, "processed": processed, "updated": success, "total": total_models}
|
return {"success": True, "message": message, "processed": processed, "updated": success, "total": total_models}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_in_skip_path(folder: str, skip_paths: List[str]) -> bool:
|
||||||
|
if not skip_paths or not folder:
|
||||||
|
return False
|
||||||
|
normalized = folder.replace("\\", "/").strip("/")
|
||||||
|
if not normalized:
|
||||||
|
return False
|
||||||
|
for sp in skip_paths:
|
||||||
|
nsp = sp.replace("\\", "/").strip("/")
|
||||||
|
if not nsp:
|
||||||
|
continue
|
||||||
|
if normalized == nsp or normalized.startswith(nsp + "/"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
async def execute_with_error_handling(
|
async def execute_with_error_handling(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -133,6 +133,10 @@ export class SettingsManager {
|
|||||||
backendSettings?.auto_organize_exclusions ?? defaults.auto_organize_exclusions
|
backendSettings?.auto_organize_exclusions ?? defaults.auto_organize_exclusions
|
||||||
);
|
);
|
||||||
|
|
||||||
|
merged.metadata_refresh_skip_paths = this.normalizePatternList(
|
||||||
|
backendSettings?.metadata_refresh_skip_paths ?? defaults.metadata_refresh_skip_paths
|
||||||
|
);
|
||||||
|
|
||||||
Object.keys(merged).forEach(key => this.backendSettingKeys.add(key));
|
Object.keys(merged).forEach(key => this.backendSettingKeys.add(key));
|
||||||
|
|
||||||
return merged;
|
return merged;
|
||||||
@@ -349,6 +353,16 @@ export class SettingsManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const metadataRefreshSkipPathsInput = document.getElementById('metadataRefreshSkipPaths');
|
||||||
|
if (metadataRefreshSkipPathsInput) {
|
||||||
|
metadataRefreshSkipPathsInput.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key === 'Enter' && !event.shiftKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.saveMetadataRefreshSkipPaths();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.setupPriorityTagInputs();
|
this.setupPriorityTagInputs();
|
||||||
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
@@ -410,6 +424,16 @@ export class SettingsManager {
|
|||||||
autoOrganizeExclusionsError.textContent = '';
|
autoOrganizeExclusionsError.textContent = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const metadataRefreshSkipPathsInput = document.getElementById('metadataRefreshSkipPaths');
|
||||||
|
if (metadataRefreshSkipPathsInput) {
|
||||||
|
const skipPaths = this.normalizePatternList(state.global.settings.metadata_refresh_skip_paths);
|
||||||
|
metadataRefreshSkipPathsInput.value = skipPaths.join(', ');
|
||||||
|
}
|
||||||
|
const metadataRefreshSkipPathsError = document.getElementById('metadataRefreshSkipPathsError');
|
||||||
|
if (metadataRefreshSkipPathsError) {
|
||||||
|
metadataRefreshSkipPathsError.textContent = '';
|
||||||
|
}
|
||||||
|
|
||||||
// Set video autoplay on hover setting
|
// Set video autoplay on hover setting
|
||||||
const autoplayOnHoverCheckbox = document.getElementById('autoplayOnHover');
|
const autoplayOnHoverCheckbox = document.getElementById('autoplayOnHover');
|
||||||
if (autoplayOnHoverCheckbox) {
|
if (autoplayOnHoverCheckbox) {
|
||||||
@@ -1721,6 +1745,58 @@ export class SettingsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async saveMetadataRefreshSkipPaths() {
|
||||||
|
const input = document.getElementById('metadataRefreshSkipPaths');
|
||||||
|
const errorElement = document.getElementById('metadataRefreshSkipPathsError');
|
||||||
|
if (!input) return;
|
||||||
|
|
||||||
|
const normalized = this.normalizePatternList(input.value);
|
||||||
|
|
||||||
|
if (input.value.trim() && normalized.length === 0) {
|
||||||
|
if (errorElement) {
|
||||||
|
errorElement.textContent = translate(
|
||||||
|
'settings.metadataRefreshSkipPaths.validation.noPaths',
|
||||||
|
{},
|
||||||
|
'Enter at least one path separated by commas.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const current = this.normalizePatternList(state.global.settings.metadata_refresh_skip_paths);
|
||||||
|
if (normalized.join('|') === current.join('|')) {
|
||||||
|
if (errorElement) {
|
||||||
|
errorElement.textContent = '';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (errorElement) {
|
||||||
|
errorElement.textContent = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.saveSetting('metadata_refresh_skip_paths', normalized);
|
||||||
|
input.value = normalized.join(', ');
|
||||||
|
|
||||||
|
showToast(
|
||||||
|
'toast.settings.settingsUpdated',
|
||||||
|
{ setting: translate('settings.metadataRefreshSkipPaths.label') },
|
||||||
|
'success'
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save metadata refresh skip paths:', error);
|
||||||
|
if (errorElement) {
|
||||||
|
errorElement.textContent = translate(
|
||||||
|
'settings.metadataRefreshSkipPaths.validation.saveFailed',
|
||||||
|
{ message: error.message },
|
||||||
|
`Unable to save skip paths: ${error.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
showToast('toast.settings.settingSaveFailed', { message: error.message }, 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async saveInputSetting(elementId, settingKey) {
|
async saveInputSetting(elementId, settingKey) {
|
||||||
const element = document.getElementById(elementId);
|
const element = document.getElementById(elementId);
|
||||||
if (!element) return;
|
if (!element) return;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const DEFAULT_SETTINGS_BASE = Object.freeze({
|
|||||||
priority_tags: { ...DEFAULT_PRIORITY_TAG_CONFIG },
|
priority_tags: { ...DEFAULT_PRIORITY_TAG_CONFIG },
|
||||||
update_flag_strategy: 'same_base',
|
update_flag_strategy: 'same_base',
|
||||||
auto_organize_exclusions: [],
|
auto_organize_exclusions: [],
|
||||||
|
metadata_refresh_skip_paths: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
export function createDefaultSettings() {
|
export function createDefaultSettings() {
|
||||||
|
|||||||
@@ -536,6 +536,25 @@
|
|||||||
<div class="settings-input-error-message" id="autoOrganizeExclusionsError"></div>
|
<div class="settings-input-error-message" id="autoOrganizeExclusionsError"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item priority-tags-item auto-organize-exclusions-item">
|
||||||
|
<div class="setting-row priority-tags-header">
|
||||||
|
<div class="setting-info priority-tags-info">
|
||||||
|
<label>{{ t('settings.metadataRefreshSkipPaths.label') }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-help">
|
||||||
|
{{ t('settings.metadataRefreshSkipPaths.help') }}
|
||||||
|
</div>
|
||||||
|
<textarea
|
||||||
|
id="metadataRefreshSkipPaths"
|
||||||
|
class="priority-tags-input auto-organize-exclusions-input"
|
||||||
|
rows="3"
|
||||||
|
placeholder="{{ t('settings.metadataRefreshSkipPaths.placeholder') }}"
|
||||||
|
onblur="settingsManager.saveMetadataRefreshSkipPaths()"
|
||||||
|
></textarea>
|
||||||
|
<div class="settings-input-error-message" id="metadataRefreshSkipPathsError"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Add Example Images Settings Section -->
|
<!-- Add Example Images Settings Section -->
|
||||||
<div class="settings-section">
|
<div class="settings-section">
|
||||||
<h3>{{ t('settings.sections.exampleImages') }}</h3>
|
<h3>{{ t('settings.sections.exampleImages') }}</h3>
|
||||||
|
|||||||
Reference in New Issue
Block a user