Files
ComfyUI_frontend/src/stores/commandStore.ts
Johnpaul Chiwetelu 84379d9522 Feature/expanded minimap (#4902)
* [feat] Add formatKeySequence function to format keybindings for commands

* [feat] Add lock and unlock canvas commands with keybindings and update localization

* feat: Implement canvas scale synchronization and zoom level adjustment

* feat: Enhance GraphCanvasMenu with zoom controls and improved button functionality

* feat: Refactor MiniMap component layout and remove unused bottomPanelStore

* feat: Update zoom control shortcuts to use formatted key sequences

* feat: Add tests for ZoomControlsModal and enhance GraphCanvasMenu tests

* Update locales [skip ci]

* Fix browser tests

* ui: align minimap properly

* Update locales [skip ci]

* feat: focus zoom input when zoom modal loads

* style: improve styling of zoom controls and add focus effect

* fix styling and tests

* styling: add divider to graph canvas menu

* styling: position minimap properly

* styling: add close button for minimap

* styling: add horizontal divider to minimap

* styling: update minimap toggle button text and remove old styles

* Update locales [skip ci]

* Update locales [skip ci]

* feat: disable canvas menu in viewport settings after zoom adjustments

* Update test expectations [skip ci]

* fix: update canvas read-only property access to use state object

* Update locales [skip ci]

* fix: adjust button group and minimap positioning

* feat: enhance zoom controls and adjust minimap positioning per PR comments

* feat: implement zoom controls composable

* feat: add timeout delays for headless tests

* fix: update zoom input validation range in applyZoom function

* [refactor] Update positioning and styles for GraphCanvasMenu, MiniMap, and ZoomControlsModal components

* [refactor] Adjust z-index and positioning for GraphCanvasMenu, MiniMap, and ZoomControlsModal components

* [style] Adjust margin for minimap button styles in GraphCanvasMenu component

* [refactor] minimap should show on focus mode

* [refactor] Update LiteGraphCanvasSplitterOverlay to conditionally render side and bottom panels based on focus mode

* [style] Adjust right positioning for MiniMap and ZoomControlsModal components

* [style] Adjust right positioning for MiniMap and ZoomControlsModal components

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2025-08-21 11:16:29 -07:00

141 lines
4.0 KiB
TypeScript

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { useErrorHandling } from '@/composables/useErrorHandling'
import type { ComfyExtension } from '@/types/comfy'
import { type KeybindingImpl, useKeybindingStore } from './keybindingStore'
export interface ComfyCommand {
id: string
function: () => void | Promise<void>
label?: string | (() => string)
icon?: string | (() => string)
tooltip?: string | (() => string)
menubarLabel?: string | (() => string) // Menubar item label, if different from command label
versionAdded?: string
confirmation?: string // If non-nullish, this command will prompt for confirmation
source?: string
active?: () => boolean // Getter to check if the command is active/toggled on
category?: 'essentials' | 'view-controls' // For shortcuts panel organization
}
export class ComfyCommandImpl implements ComfyCommand {
id: string
function: () => void | Promise<void>
_label?: string | (() => string)
_icon?: string | (() => string)
_tooltip?: string | (() => string)
_menubarLabel?: string | (() => string)
versionAdded?: string
confirmation?: string
source?: string
active?: () => boolean
category?: 'essentials' | 'view-controls'
constructor(command: ComfyCommand) {
this.id = command.id
this.function = command.function
this._label = command.label
this._icon = command.icon
this._tooltip = command.tooltip
this._menubarLabel = command.menubarLabel ?? command.label
this.versionAdded = command.versionAdded
this.confirmation = command.confirmation
this.source = command.source
this.active = command.active
this.category = command.category
}
get label() {
return typeof this._label === 'function' ? this._label() : this._label
}
get icon() {
return typeof this._icon === 'function' ? this._icon() : this._icon
}
get tooltip() {
return typeof this._tooltip === 'function' ? this._tooltip() : this._tooltip
}
get menubarLabel() {
return typeof this._menubarLabel === 'function'
? this._menubarLabel()
: this._menubarLabel
}
get keybinding(): KeybindingImpl | null {
return useKeybindingStore().getKeybindingByCommandId(this.id)
}
}
export const useCommandStore = defineStore('command', () => {
const commandsById = ref<Record<string, ComfyCommandImpl>>({})
const commands = computed(() => Object.values(commandsById.value))
const registerCommand = (command: ComfyCommand) => {
if (commandsById.value[command.id]) {
console.warn(`Command ${command.id} already registered`)
}
commandsById.value[command.id] = new ComfyCommandImpl(command)
}
const registerCommands = (commands: ComfyCommand[]) => {
for (const command of commands) {
registerCommand(command)
}
}
const getCommand = (command: string) => {
return commandsById.value[command]
}
const { wrapWithErrorHandlingAsync } = useErrorHandling()
const execute = async (
commandId: string,
errorHandler?: (error: any) => void
) => {
const command = getCommand(commandId)
if (command) {
await wrapWithErrorHandlingAsync(command.function, errorHandler)()
} else {
throw new Error(`Command ${commandId} not found`)
}
}
const isRegistered = (command: string) => {
return !!commandsById.value[command]
}
const loadExtensionCommands = (extension: ComfyExtension) => {
if (extension.commands) {
for (const command of extension.commands) {
registerCommand({
...command,
source: extension.name
})
}
}
}
const formatKeySequence = (command: ComfyCommandImpl): string => {
const sequences = command.keybinding?.combo.getKeySequences() || []
return sequences
.map((seq) => seq.replace(/Control/g, 'Ctrl').replace(/Shift/g, 'Shift'))
.join(' + ')
}
return {
commands,
execute,
getCommand,
registerCommand,
registerCommands,
isRegistered,
loadExtensionCommands,
formatKeySequence
}
})