diff --git a/src/stores/settingStore.ts b/src/stores/settingStore.ts index 1247e6919..600014881 100644 --- a/src/stores/settingStore.ts +++ b/src/stores/settingStore.ts @@ -7,6 +7,7 @@ import { api } from '@/scripts/api' import { app } from '@/scripts/app' import type { SettingParams } from '@/types/settingTypes' import type { TreeNode } from '@/types/treeExplorerTypes' +import { compareVersions } from '@/utils/formatUtil' export const getSettingInfo = (setting: SettingParams) => { const parts = setting.category || setting.id.split('.') @@ -83,11 +84,56 @@ export const useSettingStore = defineStore('setting', () => { */ function getDefaultValue(key: K): Settings[K] { const param = settingsById.value[key] + + const versionedDefault = getVersionedDefaultValue(key, param) + + if (versionedDefault) { + return versionedDefault + } + return typeof param?.defaultValue === 'function' ? param.defaultValue() : param?.defaultValue } + function getVersionedDefaultValue( + key: K, + param: SettingParams + ): Settings[K] | null { + // get default versioned value, skipping if the key is 'Comfy.InstalledVersion' to prevent infinite loop + if (param?.defaultsByInstallVersion && key !== 'Comfy.InstalledVersion') { + const installedVersion = get('Comfy.InstalledVersion') + + if (installedVersion) { + const sortedVersions = Object.keys(param.defaultsByInstallVersion).sort( + (a, b) => compareVersions(a, b) + ) + + for (const version of sortedVersions.reverse()) { + // Ensure the version is in a valid format before comparing + if (!isValidVersionFormat(version)) { + continue + } + + if (compareVersions(installedVersion, version) >= 0) { + const versionedDefault = param.defaultsByInstallVersion[version] + return typeof versionedDefault === 'function' + ? versionedDefault() + : versionedDefault + } + } + } + } + + return null + } + + function isValidVersionFormat( + version: string + ): version is `${number}.${number}.${number}` { + return /^\d+\.\d+\.\d+$/.test(version) + } + /** * Register a setting. * @param setting - The setting to register. diff --git a/src/types/settingTypes.ts b/src/types/settingTypes.ts index 4518c30ec..8c2497e56 100644 --- a/src/types/settingTypes.ts +++ b/src/types/settingTypes.ts @@ -35,6 +35,10 @@ export interface Setting { export interface SettingParams extends FormItem { id: keyof Settings defaultValue: any | (() => any) + defaultsByInstallVersion?: Record< + `${number}.${number}.${number}`, + any | (() => any) + > onChange?: (newValue: any, oldValue?: any) => void // By default category is id.split('.'). However, changing id to assign // new category has poor backward compatibility. Use this field to overwrite diff --git a/tests-ui/tests/store/settingStore.test.ts b/tests-ui/tests/store/settingStore.test.ts index a217cfeb6..9192e67c8 100644 --- a/tests-ui/tests/store/settingStore.test.ts +++ b/tests-ui/tests/store/settingStore.test.ts @@ -109,6 +109,241 @@ describe('useSettingStore', () => { }) }) + describe('getDefaultValue', () => { + beforeEach(() => { + // Set up installed version for most tests + store.settingValues['Comfy.InstalledVersion'] = '1.30.0' + }) + + it('should return regular default value when no defaultsByInstallVersion', () => { + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default' + } + store.addSetting(setting) + + const result = store.getDefaultValue('test.setting') + expect(result).toBe('regular-default') + }) + + it('should return versioned default when user version matches', () => { + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.21.3': 'version-1.21.3-default', + '1.40.3': 'version-1.40.3-default' + } + } + store.addSetting(setting) + + const result = store.getDefaultValue('test.setting') + // installedVersion is 1.30.0, so should get 1.21.3 default + expect(result).toBe('version-1.21.3-default') + }) + + it('should return latest versioned default when user version is higher', () => { + store.settingValues['Comfy.InstalledVersion'] = '1.50.0' + + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.21.3': 'version-1.21.3-default', + '1.40.3': 'version-1.40.3-default' + } + } + store.addSetting(setting) + + const result = store.getDefaultValue('test.setting') + // installedVersion is 1.50.0, so should get 1.40.3 default + expect(result).toBe('version-1.40.3-default') + }) + + it('should return regular default when user version is lower than all versioned defaults', () => { + store.settingValues['Comfy.InstalledVersion'] = '1.10.0' + + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.21.3': 'version-1.21.3-default', + '1.40.3': 'version-1.40.3-default' + } + } + store.addSetting(setting) + + const result = store.getDefaultValue('test.setting') + // installedVersion is 1.10.0, lower than all versioned defaults + expect(result).toBe('regular-default') + }) + + it('should return regular default when no installed version (existing users)', () => { + // Clear installed version to simulate existing user + delete store.settingValues['Comfy.InstalledVersion'] + + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.21.3': 'version-1.21.3-default', + '1.40.3': 'version-1.40.3-default' + } + } + store.addSetting(setting) + + const result = store.getDefaultValue('test.setting') + // No installed version, should use backward compatibility + expect(result).toBe('regular-default') + }) + + it('should handle function-based versioned defaults', () => { + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.21.3': () => 'dynamic-version-1.21.3-default', + '1.40.3': () => 'dynamic-version-1.40.3-default' + } + } + store.addSetting(setting) + + const result = store.getDefaultValue('test.setting') + // installedVersion is 1.30.0, so should get 1.21.3 default (executed) + expect(result).toBe('dynamic-version-1.21.3-default') + }) + + it('should handle function-based regular defaults with versioned defaults', () => { + store.settingValues['Comfy.InstalledVersion'] = '1.10.0' + + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: () => 'dynamic-regular-default', + defaultsByInstallVersion: { + '1.21.3': 'version-1.21.3-default', + '1.40.3': 'version-1.40.3-default' + } + } + store.addSetting(setting) + + const result = store.getDefaultValue('test.setting') + // installedVersion is 1.10.0, should fallback to function-based regular default + expect(result).toBe('dynamic-regular-default') + }) + + it('should handle complex version comparison correctly', () => { + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.21.3': 'version-1.21.3-default', + '1.21.10': 'version-1.21.10-default', + '1.40.3': 'version-1.40.3-default' + } + } + store.addSetting(setting) + + // Test with 1.21.5 - should get 1.21.3 default + store.settingValues['Comfy.InstalledVersion'] = '1.21.5' + expect(store.getDefaultValue('test.setting')).toBe( + 'version-1.21.3-default' + ) + + // Test with 1.21.15 - should get 1.21.10 default + store.settingValues['Comfy.InstalledVersion'] = '1.21.15' + expect(store.getDefaultValue('test.setting')).toBe( + 'version-1.21.10-default' + ) + + // Test with 1.21.3 exactly - should get 1.21.3 default + store.settingValues['Comfy.InstalledVersion'] = '1.21.3' + expect(store.getDefaultValue('test.setting')).toBe( + 'version-1.21.3-default' + ) + }) + + it('should work with get() method using versioned defaults', () => { + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.21.3': 'version-1.21.3-default', + '1.40.3': 'version-1.40.3-default' + } + } + store.addSetting(setting) + + // get() should use getDefaultValue internally + const result = store.get('test.setting') + expect(result).toBe('version-1.21.3-default') + }) + + it('should handle mixed function and static versioned defaults', () => { + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.21.3': () => 'dynamic-1.21.3-default', + '1.40.3': 'static-1.40.3-default' + } + } + store.addSetting(setting) + + // Test with 1.30.0 - should get dynamic 1.21.3 default + store.settingValues['Comfy.InstalledVersion'] = '1.30.0' + expect(store.getDefaultValue('test.setting')).toBe( + 'dynamic-1.21.3-default' + ) + + // Test with 1.50.0 - should get static 1.40.3 default + store.settingValues['Comfy.InstalledVersion'] = '1.50.0' + expect(store.getDefaultValue('test.setting')).toBe( + 'static-1.40.3-default' + ) + }) + + it('should handle version sorting correctly', () => { + const setting: SettingParams = { + id: 'test.setting', + name: 'Test Setting', + type: 'text', + defaultValue: 'regular-default', + defaultsByInstallVersion: { + '1.40.3': 'version-1.40.3-default', + '1.21.3': 'version-1.21.3-default', // Unsorted order + '1.35.0': 'version-1.35.0-default' + } + } + store.addSetting(setting) + + // Test with 1.37.0 - should get 1.35.0 default (highest version <= 1.37.0) + store.settingValues['Comfy.InstalledVersion'] = '1.37.0' + expect(store.getDefaultValue('test.setting')).toBe( + 'version-1.35.0-default' + ) + }) + }) + describe('get and set', () => { it('should get default value when setting not exists', () => { const setting: SettingParams = {