refactor: deduplicate preset logic per review feedback

- Reuse serializeKeybindingImpl via KeybindingImpl wrapper instead of
  reimplementing serialization for raw bindings
- Extract switchToDefaultPreset() to replace 3 duplicated reset patterns
- Extract promptAndSaveNewPreset() shared between presetService and
  KeybindingPanel
This commit is contained in:
Johnpaul
2026-03-11 19:21:02 +01:00
parent 52a56b3a88
commit 70f61e3379
3 changed files with 47 additions and 76 deletions

View File

@@ -178,7 +178,6 @@ import { useKeybindingStore } from '@/platform/keybindings/keybindingStore'
import { useKeybindingPresetService } from '@/platform/keybindings/presetService'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useCommandStore } from '@/stores/commandStore'
import { useDialogService } from '@/services/dialogService'
import { normalizeI18nKey } from '@/utils/formatUtil'
import KeybindingPresetToolbar from './keybinding/KeybindingPresetToolbar.vue'
@@ -193,7 +192,6 @@ const keybindingService = useKeybindingService()
const presetService = useKeybindingPresetService()
const settingStore = useSettingStore()
const commandStore = useCommandStore()
const dialogService = useDialogService()
const { t } = useI18n()
const presetNames = ref<string[]>([])
@@ -211,11 +209,7 @@ async function initPresets() {
keybindingStore.savedPresetData = preset
keybindingStore.currentPresetName = currentName
} else {
keybindingStore.resetAllKeybindings()
keybindingStore.currentPresetName = 'default'
keybindingStore.savedPresetData = null
await keybindingService.persistUserKeybindings()
await settingStore.set('Comfy.Keybinding.CurrentPreset', 'default')
await presetService.switchToDefaultPreset()
}
}
}
@@ -224,25 +218,7 @@ onMounted(() => initPresets())
// "..." menu entries (teleported to header)
async function saveAsNewPreset() {
const name = await dialogService.prompt({
title: t('g.keybindingPresets.saveAsNewPreset'),
message: t('g.keybindingPresets.presetNamePrompt'),
defaultValue: ''
})
if (!name) return
const trimmedName = name.trim()
if (!trimmedName) return
if (presetNames.value.includes(trimmedName)) {
const overwrite = await dialogService.confirm({
title: t('g.keybindingPresets.overwritePresetTitle'),
message: t('g.keybindingPresets.overwritePresetMessage', {
name: trimmedName
}),
type: 'overwrite'
})
if (!overwrite) return
}
await presetService.savePreset(trimmedName)
await presetService.promptAndSaveNewPreset()
refreshPresetList()
}

View File

@@ -4,7 +4,7 @@ import type { Ref } from 'vue'
import { computed, ref } from 'vue'
import type { KeyComboImpl } from './keyCombo'
import type { KeybindingImpl } from './keybinding'
import { KeybindingImpl } from './keybinding'
import type { KeybindingPreset } from './types'
export const useKeybindingStore = defineStore('keybinding', () => {
@@ -25,28 +25,18 @@ export const useKeybindingStore = defineStore('keybinding', () => {
if (!savedPresetData.value) return false
const serializeKeybindingImpl = (b: KeybindingImpl) =>
const serialize = (b: KeybindingImpl) =>
`${b.commandId}:${b.combo.serialize()}:${b.targetElementId ?? ''}`
const serializeRawBinding = (b: {
commandId: string
combo: { key: string; ctrl?: boolean; alt?: boolean; shift?: boolean }
targetElementId?: string
}) =>
`${b.commandId}:${b.combo.key.toUpperCase()}:${b.combo.ctrl ?? false}:${b.combo.alt ?? false}:${b.combo.shift ?? false}:${b.targetElementId ?? ''}`
const currentNew = newBindings.map(serializeKeybindingImpl).sort().join('|')
const currentNew = newBindings.map(serialize).sort().join('|')
const savedNew = savedPresetData.value.newBindings
.map(serializeRawBinding)
.map((b) => serialize(new KeybindingImpl(b)))
.sort()
.join('|')
const currentUnset = unsetBindings
.map(serializeKeybindingImpl)
.sort()
.join('|')
const currentUnset = unsetBindings.map(serialize).sort().join('|')
const savedUnset = savedPresetData.value.unsetBindings
.map(serializeRawBinding)
.map((b) => serialize(new KeybindingImpl(b)))
.sort()
.join('|')

View File

@@ -59,6 +59,14 @@ export function useKeybindingPresetService() {
const toast = useToastStore()
const { wrapWithErrorHandlingAsync } = useErrorHandling()
async function switchToDefaultPreset({ resetBindings = true } = {}) {
if (resetBindings) keybindingStore.resetAllKeybindings()
keybindingStore.currentPresetName = 'default'
keybindingStore.savedPresetData = null
await keybindingService.persistUserKeybindings()
await settingStore.set('Comfy.Keybinding.CurrentPreset', 'default')
}
const DELETE_DIALOG_KEY = 'delete-keybinding-preset'
const UNSAVED_DIALOG_KEY = 'unsaved-keybinding-changes'
@@ -165,11 +173,7 @@ export function useKeybindingPresetService() {
}
if (keybindingStore.currentPresetName === name) {
keybindingStore.resetAllKeybindings()
keybindingStore.currentPresetName = 'default'
keybindingStore.savedPresetData = null
await keybindingService.persistUserKeybindings()
await settingStore.set('Comfy.Keybinding.CurrentPreset', 'default')
await switchToDefaultPreset()
}
toast.add({
@@ -210,16 +214,37 @@ export function useKeybindingPresetService() {
}
const preset = result.data
applyPreset(preset)
keybindingStore.currentPresetName = 'default'
keybindingStore.savedPresetData = null
await keybindingService.persistUserKeybindings()
await settingStore.set('Comfy.Keybinding.CurrentPreset', 'default')
await switchToDefaultPreset({ resetBindings: false })
toast.add({
severity: 'success',
summary: t('g.keybindingPresets.presetImported')
})
}
async function promptAndSaveNewPreset(): Promise<boolean> {
const name = await dialogService.prompt({
title: t('g.keybindingPresets.saveAsNewPreset'),
message: t('g.keybindingPresets.presetNamePrompt'),
defaultValue: ''
})
if (!name) return false
const trimmedName = name.trim()
if (!trimmedName) return false
const existingPresets = await listPresets()
if (existingPresets.includes(trimmedName)) {
const overwrite = await dialogService.confirm({
title: t('g.keybindingPresets.overwritePresetTitle'),
message: t('g.keybindingPresets.overwritePresetMessage', {
name: trimmedName
}),
type: 'overwrite'
})
if (!overwrite) return false
}
await savePreset(trimmedName)
return true
}
async function switchPreset(targetName: string) {
if (keybindingStore.isCurrentPresetModified) {
const displayName =
@@ -233,36 +258,14 @@ export function useKeybindingPresetService() {
if (keybindingStore.currentPresetName !== 'default') {
await savePreset(keybindingStore.currentPresetName)
} else {
const name = await dialogService.prompt({
title: t('g.keybindingPresets.saveAsNewPreset'),
message: t('g.keybindingPresets.presetNamePrompt'),
defaultValue: ''
})
if (!name) return
const trimmedName = name.trim()
if (!trimmedName) return
const existingPresets = await listPresets()
if (existingPresets.includes(trimmedName)) {
const overwrite = await dialogService.confirm({
title: t('g.keybindingPresets.overwritePresetTitle'),
message: t('g.keybindingPresets.overwritePresetMessage', {
name: trimmedName
}),
type: 'overwrite'
})
if (!overwrite) return
}
await savePreset(trimmedName)
const saved = await promptAndSaveNewPreset()
if (!saved) return
}
}
}
if (targetName === 'default') {
keybindingStore.resetAllKeybindings()
keybindingStore.currentPresetName = 'default'
keybindingStore.savedPresetData = null
await keybindingService.persistUserKeybindings()
await settingStore.set('Comfy.Keybinding.CurrentPreset', 'default')
await switchToDefaultPreset()
return
}
@@ -280,6 +283,8 @@ export function useKeybindingPresetService() {
exportPreset,
importPreset: wrapWithErrorHandlingAsync(importPreset),
switchPreset: wrapWithErrorHandlingAsync(switchPreset),
switchToDefaultPreset: wrapWithErrorHandlingAsync(switchToDefaultPreset),
promptAndSaveNewPreset: wrapWithErrorHandlingAsync(promptAndSaveNewPreset),
applyPreset
}
}