refactor(settings): restructure settings modal with subsection headers

- Replace duplicate section headers with meaningful subsection titles
- Group settings under logical subsections using existing i18n keys
- Add new translation key 'settings.sections.apiConfiguration'
- Update CSS for subsection styling with proper visual hierarchy
- Improve UX by making settings organization clearer

Subsections now use familiar titles from existing translations:
- API Configuration, Storage Location, Language (General)
- Content Filtering, Video Settings, Layout Settings (Interface)
- Folder Settings, Download Path Templates, Priority Tags,
  Update Flags, Example Images (Download)
- Auto-organize Exclusions, Metadata Refresh Skip Paths (Organization)
- Metadata Archive, Misc (System)
- Proxy Settings (Network)
This commit is contained in:
Will Miao
2026-02-24 14:33:09 +08:00
parent 8d7e861458
commit de53ab9304
12 changed files with 742 additions and 632 deletions

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "Einstellungspfad: {{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "Inhaltsfilterung",
"videoSettings": "Video-Einstellungen",
"layoutSettings": "Layout-Einstellungen",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "Settings path: {{path}}"
},
"sections": {
"apiConfiguration": "API Configuration",
"contentFiltering": "Content Filtering",
"videoSettings": "Video Settings",
"layoutSettings": "Layout Settings",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "Ruta de configuración: {{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "Filtrado de contenido",
"videoSettings": "Configuración de video",
"layoutSettings": "Configuración de diseño",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "Chemin des paramètres: {{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "Filtrage du contenu",
"videoSettings": "Paramètres vidéo",
"layoutSettings": "Paramètres d'affichage",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "נתיב ההגדרות: {{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "סינון תוכן",
"videoSettings": "הגדרות וידאו",
"layoutSettings": "הגדרות פריסה",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "設定パス: {{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "コンテンツフィルタリング",
"videoSettings": "動画設定",
"layoutSettings": "レイアウト設定",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "설정 경로: {{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "콘텐츠 필터링",
"videoSettings": "비디오 설정",
"layoutSettings": "레이아웃 설정",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "Путь настроек: {{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "Фильтрация контента",
"videoSettings": "Настройки видео",
"layoutSettings": "Настройки макета",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "设置路径:{{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "内容过滤",
"videoSettings": "视频设置",
"layoutSettings": "布局设置",

View File

@@ -255,6 +255,7 @@
"clipboardFallback": "設定路徑:{{path}}"
},
"sections": {
"apiConfiguration": "[TODO: Translate] API Configuration",
"contentFiltering": "內容過濾",
"videoSettings": "影片設定",
"layoutSettings": "版面設定",

View File

@@ -573,20 +573,34 @@
}
}
/* Remove old section header - replaced by subsection headers */
.settings-section-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 0 var(--space-2) 0;
margin-bottom: var(--space-3);
border-bottom: 2px solid var(--lora-accent);
display: none;
}
.settings-section-header h3 {
font-size: 20px;
/* Subsection styling */
.settings-subsection {
margin-bottom: var(--space-4);
}
.settings-subsection:last-child {
margin-bottom: 0;
}
.settings-subsection-header {
display: flex;
align-items: center;
padding: var(--space-2) 0;
margin-bottom: var(--space-2);
border-bottom: 1px solid var(--lora-border);
}
.settings-subsection-header h4 {
font-size: 16px;
font-weight: 600;
margin: 0;
color: var(--text-color);
opacity: 0.9;
}
/* Remove toggle button styles */
@@ -598,10 +612,14 @@
display: flex;
flex-direction: column; /* Changed to column for help text placement */
margin-bottom: var(--space-3); /* Increased to provide more spacing between items */
padding: var(--space-1);
padding: var(--space-2);
border-radius: var(--border-radius-xs);
}
.setting-item:last-child {
margin-bottom: 0;
}
.setting-item:hover {
background: rgba(0, 0, 0, 0.02);
}
@@ -610,6 +628,32 @@
background: rgba(255, 255, 255, 0.05);
}
/* Subsection styling */
.settings-subsection {
margin-bottom: var(--space-5);
}
.settings-subsection:last-child {
margin-bottom: 0;
}
.settings-subsection-header {
display: flex;
align-items: center;
padding: var(--space-2) var(--space-2) var(--space-2) 0;
margin-bottom: var(--space-2);
border-bottom: 1px solid var(--lora-border);
}
.settings-subsection-header h4 {
font-size: 15px;
font-weight: 600;
margin: 0;
color: var(--text-color);
opacity: 0.85;
letter-spacing: 0.3px;
}
/* Control row with label and input together */
.setting-row {
display: flex;

View File

@@ -49,11 +49,11 @@
<!-- Section 1: General -->
<div id="section-general" class="settings-section active" data-section="general">
<div class="settings-section-header">
<h3>{{ t('settings.nav.general') }}</h3>
<!-- API Configuration -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.apiConfiguration') }}</h4>
</div>
<!-- API Key -->
<div class="setting-item api-key-item">
<div class="setting-row">
<div class="setting-info">
@@ -77,8 +77,13 @@
{{ t('settings.civitaiApiKeyHelp') }}
</div>
</div>
</div>
<!-- Storage Location -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.storageLocation') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -96,8 +101,13 @@
{{ t('settings.storage.locationHelp') }}
</div>
</div>
</div>
<!-- Language -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('common.language.select') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -123,14 +133,15 @@
</div>
</div>
</div>
</div>
<!-- Section 2: Interface -->
<div id="section-interface" class="settings-section" data-section="interface">
<div class="settings-section-header">
<h3>{{ t('settings.nav.interface') }}</h3>
</div>
<!-- Content Filtering -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.contentFiltering') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -166,8 +177,13 @@
{{ t('settings.contentFiltering.showOnlySfwHelp') }}
</div>
</div>
</div>
<!-- Video Settings -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.videoSettings') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -185,8 +201,13 @@
{{ t('settings.videoSettings.autoplayOnHoverHelp') }}
</div>
</div>
</div>
<!-- Layout Settings -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.layoutSettings') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -280,14 +301,15 @@
</div>
</div>
</div>
</div>
<!-- Section 3: Download -->
<div id="section-download" class="settings-section" data-section="download">
<div class="settings-section-header">
<h3>{{ t('settings.nav.download') }}</h3>
</div>
<!-- Folder Settings -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.folderSettings') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -367,44 +389,13 @@
{{ t('settings.folderSettings.defaultEmbeddingRootHelp') }}
</div>
</div>
<!-- Update Flags -->
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
<label for="updateFlagStrategy">{{ t('settings.updateFlagStrategy.label') }}</label>
</div>
<div class="setting-control select-control">
<select id="updateFlagStrategy" onchange="settingsManager.saveSelectSetting('updateFlagStrategy', 'update_flag_strategy')">
<option value="same_base">{{ t('settings.updateFlagStrategy.options.sameBase') }}</option>
<option value="any">{{ t('settings.updateFlagStrategy.options.any') }}</option>
</select>
</div>
</div>
<div class="input-help">
{{ t('settings.updateFlagStrategy.help') }}
</div>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
<label for="hideEarlyAccessUpdates">{{ t('settings.hideEarlyAccessUpdates.label') }}</label>
<!-- Download Path Templates -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.downloadPathTemplates.title') }}</h4>
</div>
<div class="setting-control">
<label class="toggle-switch">
<input type="checkbox" id="hideEarlyAccessUpdates"
onchange="settingsManager.saveToggleSetting('hideEarlyAccessUpdates', 'hide_early_access_updates')">
<span class="toggle-slider"></span>
</label>
</div>
</div>
<div class="input-help">
{{ t('settings.hideEarlyAccessUpdates.help') }}
</div>
</div>
<!-- Path Templates -->
<div class="setting-item">
<div class="input-help">
{{ t('settings.downloadPathTemplates.help') }}
@@ -517,8 +508,54 @@
</div>
</div>
</div>
</div>
<!-- Update Flags -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.updateFlags') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
<label for="updateFlagStrategy">{{ t('settings.updateFlagStrategy.label') }}</label>
</div>
<div class="setting-control select-control">
<select id="updateFlagStrategy" onchange="settingsManager.saveSelectSetting('updateFlagStrategy', 'update_flag_strategy')">
<option value="same_base">{{ t('settings.updateFlagStrategy.options.sameBase') }}</option>
<option value="any">{{ t('settings.updateFlagStrategy.options.any') }}</option>
</select>
</div>
</div>
<div class="input-help">
{{ t('settings.updateFlagStrategy.help') }}
</div>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
<label for="hideEarlyAccessUpdates">{{ t('settings.hideEarlyAccessUpdates.label') }}</label>
</div>
<div class="setting-control">
<label class="toggle-switch">
<input type="checkbox" id="hideEarlyAccessUpdates"
onchange="settingsManager.saveToggleSetting('hideEarlyAccessUpdates', 'hide_early_access_updates')">
<span class="toggle-slider"></span>
</label>
</div>
</div>
<div class="input-help">
{{ t('settings.hideEarlyAccessUpdates.help') }}
</div>
</div>
</div>
<!-- Example Images -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.exampleImages') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -571,8 +608,13 @@
{{ t('settings.exampleImages.optimizeImagesHelp') }}
</div>
</div>
</div>
<!-- Priority Tags -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.priorityTags.title') }}</h4>
</div>
<div class="setting-item priority-tags-item">
<div class="setting-row">
<div class="setting-info priority-tags-header">
@@ -611,14 +653,15 @@
</div>
</div>
</div>
</div>
<!-- Section 4: Organization -->
<div id="section-organization" class="settings-section" data-section="organization">
<div class="settings-section-header">
<h3>{{ t('settings.nav.organization') }}</h3>
</div>
<!-- Auto-organize Exclusions -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.autoOrganizeExclusions.label') }}</h4>
</div>
<div class="setting-item auto-organize-exclusions-item">
<div class="setting-row">
<div class="setting-info">
@@ -631,8 +674,13 @@
<textarea id="autoOrganizeExclusions" class="priority-tags-input auto-organize-exclusions-input" placeholder="{{ t('settings.autoOrganizeExclusions.placeholder') }}"></textarea>
<div class="settings-input-error-message" id="autoOrganizeExclusionsError"></div>
</div>
</div>
<!-- Metadata Refresh Skip Paths -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.metadataRefreshSkipPaths.label') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -646,14 +694,15 @@
<div class="settings-input-error-message" id="metadataRefreshSkipPathsError"></div>
</div>
</div>
</div>
<!-- Section 5: System -->
<div id="section-system" class="settings-section" data-section="system">
<div class="settings-section-header">
<h3>{{ t('settings.nav.system') }}</h3>
</div>
<!-- Metadata Archive -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.metadataArchive') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -696,8 +745,13 @@
{{ t('settings.metadataArchive.managementHelp') }}
</div>
</div>
</div>
<!-- Misc -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.misc') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -716,14 +770,15 @@
</div>
</div>
</div>
</div>
<!-- Section 6: Network -->
<div id="section-network" class="settings-section" data-section="network">
<div class="settings-section-header">
<h3>{{ t('settings.nav.network') }}</h3>
</div>
<!-- Proxy Settings -->
<div class="settings-subsection">
<div class="settings-subsection-header">
<h4>{{ t('settings.sections.proxySettings') }}</h4>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
@@ -842,6 +897,7 @@
</div>
</div>
</div>
</div>
</div>
</div>