Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
be02e80
[feat] Implement shortcuts management panel with categorized commands
Myestery Aug 1, 2025
dda25af
feat: Add shortcuts tab and categorize commands in command store
Myestery Aug 1, 2025
1968333
feat: Add category to sidebar tab and extend bottom panel interface
Myestery Aug 1, 2025
10300f8
feat: Add shortcuts toggle button to sidebar and re order mindmap
Myestery Aug 1, 2025
b37d8d4
feat: Enhance bottom panel store with multi-panel support and shortcu…
Myestery Aug 1, 2025
e2efdd0
npm run locale
Myestery Aug 1, 2025
96ecb88
Merge branch 'main' into bottom-keybindings
Myestery Aug 1, 2025
06a7e66
cleanup commands and style
Myestery Aug 1, 2025
0f6b4ca
Merge branch 'main' into bottom-keybindings
Myestery Aug 1, 2025
d737a84
Reset src/locales to main branch state
Myestery Aug 2, 2025
197c8dd
[bugfix] Fix pre-commit hook cross-platform compatibility (#4643)
huchenlei Aug 1, 2025
912c64f
Ignore Claude local config (#4649)
benceruleanlu Aug 1, 2025
6cf4d69
[fix] Add type guard for SubgraphDefinition to improve TypeScript inf…
christian-byrne Aug 2, 2025
9c85776
[fix] Fix viewport sync in minimap and subgraphs navigation (#4644)
christian-byrne Aug 2, 2025
84123c5
[feat] Add keyboard shortcuts localization to main.json
Myestery Aug 2, 2025
f26d967
Merge branch 'main' into bottom-keybindings
Myestery Aug 2, 2025
d73d627
unit and browser tests
Myestery Aug 2, 2025
dce73e5
use correct type in EssentialsPanel
Myestery Aug 4, 2025
471ddf4
[refactor] Simplify command subcategory grouping in EssentialsPanel a…
Myestery Aug 4, 2025
34351f5
fix unused css
Myestery Aug 4, 2025
7c5ab4e
feat: add aria-label for keybinding display accessibility
Myestery Aug 4, 2025
732bcc4
fix: use filtered subcategories for rendering shortcuts
Myestery Aug 4, 2025
af90f5d
adjust keyboard shortcuts margins and responsiveness
Myestery Aug 7, 2025
256997e
fix playwright tests
Myestery Aug 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: Enhance bottom panel store with multi-panel support and shortcu…
…ts integration
  • Loading branch information
Myestery committed Aug 1, 2025
commit b37d8d48dc8781b11ab8bdcfe54d15ee7a4463f9
120 changes: 96 additions & 24 deletions src/stores/workspace/bottomPanelStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

import { useShortcutsTab } from '@/composables/bottomPanelTabs/useShortcutsTab'
import {
useCommandTerminalTab,
useLogsTerminalTab
Expand All @@ -10,45 +11,110 @@ import { ComfyExtension } from '@/types/comfy'
import type { BottomPanelExtension } from '@/types/extensionTypes'
import { isElectron } from '@/utils/envUtil'

type PanelType = 'terminal' | 'shortcuts'

interface PanelState {
tabs: BottomPanelExtension[]
activeTabId: string
visible: boolean
}

export const useBottomPanelStore = defineStore('bottomPanel', () => {
const bottomPanelVisible = ref(false)
const toggleBottomPanel = () => {
// If there are no tabs, don't show the bottom panel
if (bottomPanelTabs.value.length === 0) {
return
}
bottomPanelVisible.value = !bottomPanelVisible.value
}
// Multi-panel state
const panels = ref<Record<PanelType, PanelState>>({
terminal: { tabs: [], activeTabId: '', visible: false },
shortcuts: { tabs: [], activeTabId: '', visible: false }
})

const activePanel = ref<PanelType | null>(null)

// Computed properties for active panel
const activePanelState = computed(() =>
activePanel.value ? panels.value[activePanel.value] : null
)

const bottomPanelTabs = ref<BottomPanelExtension[]>([])
const activeBottomPanelTabId = ref<string>('')
const activeBottomPanelTab = computed<BottomPanelExtension | null>(() => {
return (
bottomPanelTabs.value.find(
(tab) => tab.id === activeBottomPanelTabId.value
) ?? null
)
const state = activePanelState.value
if (!state) return null
return state.tabs.find((tab) => tab.id === state.activeTabId) ?? null
})

const bottomPanelVisible = computed({
get: () => !!activePanel.value,
set: (visible: boolean) => {
if (!visible) {
activePanel.value = null
}
}
})
const bottomPanelTabs = computed(() => activePanelState.value?.tabs ?? [])
const activeBottomPanelTabId = computed({
get: () => activePanelState.value?.activeTabId ?? '',
set: (tabId: string) => {
const state = activePanelState.value
if (state) {
state.activeTabId = tabId
}
}
})

const togglePanel = (panelType: PanelType) => {
const panel = panels.value[panelType]
if (panel.tabs.length === 0) return

if (activePanel.value === panelType) {
// Hide current panel
activePanel.value = null
} else {
// Show target panel
activePanel.value = panelType
if (!panel.activeTabId && panel.tabs.length > 0) {
panel.activeTabId = panel.tabs[0].id
}
}
}

const toggleBottomPanel = () => {
// Legacy method - toggles terminal panel
togglePanel('terminal')
}

const setActiveTab = (tabId: string) => {
activeBottomPanelTabId.value = tabId
const state = activePanelState.value
if (state) {
state.activeTabId = tabId
}
}

const toggleBottomPanelTab = (tabId: string) => {
if (activeBottomPanelTabId.value === tabId && bottomPanelVisible.value) {
bottomPanelVisible.value = false
} else {
activeBottomPanelTabId.value = tabId
bottomPanelVisible.value = true
// Find which panel contains this tab
for (const [panelType, panel] of Object.entries(panels.value)) {
const tab = panel.tabs.find((t) => t.id === tabId)
if (tab) {
if (activePanel.value === panelType && panel.activeTabId === tabId) {
activePanel.value = null
} else {
activePanel.value = panelType as PanelType
panel.activeTabId = tabId
}
return
}
}
}
const registerBottomPanelTab = (tab: BottomPanelExtension) => {
bottomPanelTabs.value = [...bottomPanelTabs.value, tab]
if (bottomPanelTabs.value.length === 1) {
activeBottomPanelTabId.value = tab.id
const targetPanel = tab.targetPanel ?? 'terminal'
const panel = panels.value[targetPanel]

panel.tabs = [...panel.tabs, tab]
if (panel.tabs.length === 1) {
panel.activeTabId = tab.id
}

useCommandStore().registerCommand({
id: `Workspace.ToggleBottomPanelTab.${tab.id}`,
icon: 'pi pi-list',
label: `Toggle ${tab.title} Bottom Panel`,
category: 'view-controls' as const,
function: () => toggleBottomPanelTab(tab.id),
source: 'System'
})
Expand All @@ -59,6 +125,7 @@ export const useBottomPanelStore = defineStore('bottomPanel', () => {
if (isElectron()) {
registerBottomPanelTab(useCommandTerminalTab())
}
useShortcutsTab().forEach(registerBottomPanelTab)
}

const registerExtensionBottomPanelTabs = (extension: ComfyExtension) => {
Expand All @@ -68,6 +135,11 @@ export const useBottomPanelStore = defineStore('bottomPanel', () => {
}

return {
// Multi-panel API
panels,
activePanel,
togglePanel,

bottomPanelVisible,
toggleBottomPanel,
bottomPanelTabs,
Expand Down