feat(settings): add auto-organize exclusions

This commit is contained in:
pixelpaws
2025-11-20 16:08:32 +08:00
parent 5093c30c06
commit 07721af87c
21 changed files with 339 additions and 18 deletions

View File

@@ -1252,15 +1252,24 @@ export class BaseModelApiClient {
// Start the auto-organize operation
const endpoint = this.apiConfig.endpoints.autoOrganize;
const requestOptions = {
method: filePaths ? 'POST' : 'GET',
headers: filePaths ? { 'Content-Type': 'application/json' } : {}
};
const exclusionPatterns = (state.global.settings.auto_organize_exclusions || [])
.filter(pattern => typeof pattern === 'string' && pattern.trim())
.map(pattern => pattern.trim());
const requestBody = {};
if (filePaths) {
requestOptions.body = JSON.stringify({ file_paths: filePaths });
requestBody.file_paths = filePaths;
}
if (exclusionPatterns.length > 0) {
requestBody.exclusion_patterns = exclusionPatterns;
}
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody),
};
const response = await fetch(endpoint, requestOptions);
if (!response.ok) {

View File

@@ -131,11 +131,36 @@ export class SettingsManager {
}
merged.priority_tags = normalizedPriority;
merged.auto_organize_exclusions = this.normalizePatternList(
backendSettings?.auto_organize_exclusions ?? defaults.auto_organize_exclusions
);
Object.keys(merged).forEach(key => this.backendSettingKeys.add(key));
return merged;
}
normalizePatternList(value) {
if (Array.isArray(value)) {
const sanitized = value
.map(item => typeof item === 'string' ? item.trim() : '')
.filter(Boolean);
return [...new Set(sanitized)];
}
if (typeof value === 'string') {
const sanitized = value
.replace(/\n/g, ',')
.replace(/;/g, ',')
.split(',')
.map(part => part.trim())
.filter(Boolean);
return [...new Set(sanitized)];
}
return [];
}
registerStartupMessages(messages = []) {
if (!Array.isArray(messages) || messages.length === 0) {
return;
@@ -376,6 +401,16 @@ export class SettingsManager {
usePortableCheckbox.checked = !!state.global.settings.use_portable_settings;
}
const autoOrganizeExclusionsInput = document.getElementById('autoOrganizeExclusions');
if (autoOrganizeExclusionsInput) {
const patterns = this.normalizePatternList(state.global.settings.auto_organize_exclusions);
autoOrganizeExclusionsInput.value = patterns.join(', ');
}
const autoOrganizeExclusionsError = document.getElementById('autoOrganizeExclusionsError');
if (autoOrganizeExclusionsError) {
autoOrganizeExclusionsError.textContent = '';
}
// Set video autoplay on hover setting
const autoplayOnHoverCheckbox = document.getElementById('autoplayOnHover');
if (autoplayOnHoverCheckbox) {
@@ -1592,11 +1627,63 @@ export class SettingsManager {
}
}
}
async saveAutoOrganizeExclusions() {
const input = document.getElementById('autoOrganizeExclusions');
const errorElement = document.getElementById('autoOrganizeExclusionsError');
if (!input) return;
const normalized = this.normalizePatternList(input.value);
if (input.value.trim() && normalized.length === 0) {
if (errorElement) {
errorElement.textContent = translate(
'settings.autoOrganizeExclusions.validation.noPatterns',
{},
'Enter at least one pattern separated by commas or semicolons.'
);
}
return;
}
const current = this.normalizePatternList(state.global.settings.auto_organize_exclusions);
if (normalized.join('|') === current.join('|')) {
if (errorElement) {
errorElement.textContent = '';
}
return;
}
try {
if (errorElement) {
errorElement.textContent = '';
}
await this.saveSetting('auto_organize_exclusions', normalized);
input.value = normalized.join(', ');
showToast(
'toast.settings.settingsUpdated',
{ setting: translate('settings.autoOrganizeExclusions.label') },
'success'
);
} catch (error) {
console.error('Failed to save auto-organize exclusions:', error);
if (errorElement) {
errorElement.textContent = translate(
'settings.autoOrganizeExclusions.validation.saveFailed',
{ message: error.message },
`Unable to save exclusions: ${error.message}`
);
}
showToast('toast.settings.settingSaveFailed', { message: error.message }, 'error');
}
}
async saveInputSetting(elementId, settingKey) {
const element = document.getElementById(elementId);
if (!element) return;
const value = element.value.trim(); // Trim whitespace
try {

View File

@@ -34,6 +34,7 @@ const DEFAULT_SETTINGS_BASE = Object.freeze({
compact_mode: false,
priority_tags: { ...DEFAULT_PRIORITY_TAG_CONFIG },
update_flag_strategy: 'same_base',
auto_organize_exclusions: [],
});
export function createDefaultSettings() {