Skip to content

Commit 414d629

Browse files
feat: add new tab functionality with keyboard shortcuts in QueryWorkspace and ActiveConnectionLayout
1 parent afea07c commit 414d629

File tree

2 files changed

+75
-24
lines changed

2 files changed

+75
-24
lines changed

src/renderer/components/ActiveConnectionLayout/ActiveConnectionLayout.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Button } from '../ui'
44
import { DatabaseExplorer } from '../DatabaseExplorer/DatabaseExplorer'
55
import { QueryWorkspace } from '../QueryWorkspace/QueryWorkspace'
66
import { ThemeSwitcher } from '../ThemeSwitcher'
7-
import { useState, useEffect } from 'react'
7+
import { useState, useEffect, useRef } from 'react'
88
import './ActiveConnectionLayout.css'
99

1010
interface ActiveConnectionLayoutProps {
@@ -19,6 +19,7 @@ export function ActiveConnectionLayout({
1919
onDisconnect
2020
}: ActiveConnectionLayoutProps) {
2121
const [isReadOnly, setIsReadOnly] = useState(false)
22+
const newTabHandlerRef = useRef<(() => void) | null>(null)
2223

2324
useEffect(() => {
2425
const checkReadOnly = async () => {
@@ -32,6 +33,23 @@ export function ActiveConnectionLayout({
3233
checkReadOnly()
3334
}, [connectionId])
3435

36+
// Global keyboard shortcut for Cmd+T / Ctrl+T
37+
useEffect(() => {
38+
const handleKeyDown = (event: KeyboardEvent) => {
39+
if ((event.metaKey || event.ctrlKey) && event.key === 't') {
40+
event.preventDefault()
41+
if (newTabHandlerRef.current) {
42+
newTabHandlerRef.current()
43+
}
44+
}
45+
}
46+
47+
document.addEventListener('keydown', handleKeyDown)
48+
return () => {
49+
document.removeEventListener('keydown', handleKeyDown)
50+
}
51+
}, [])
52+
3553
const handleOpenTableTab = (database: string, tableName: string) => {
3654
if (window.openTableTab) {
3755
window.openTableTab(database, tableName)
@@ -76,8 +94,10 @@ export function ActiveConnectionLayout({
7694
<Panel defaultSize={80} className="workspace-panel">
7795
<QueryWorkspace
7896
connectionId={connectionId}
79-
connectionName={connectionName}
8097
onOpenTableTab={handleOpenTableTab}
98+
onRegisterNewTabHandler={(handler) => {
99+
newTabHandlerRef.current = handler
100+
}}
81101
/>
82102
</Panel>
83103
</PanelGroup>

src/renderer/components/QueryWorkspace/QueryWorkspace.tsx

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@ const DEFAULT_LIMIT = 100
2424
interface QueryWorkspaceProps {
2525
connectionId: string
2626
onOpenTableTab?: (database: string, tableName: string) => void
27+
onRegisterNewTabHandler?: (handler: () => void) => void
2728
}
2829

29-
export function QueryWorkspace({ connectionId, onOpenTableTab }: QueryWorkspaceProps) {
30+
export function QueryWorkspace({
31+
connectionId,
32+
onOpenTableTab,
33+
onRegisterNewTabHandler
34+
}: QueryWorkspaceProps) {
3035
const [tabs, setTabs] = useState<Tab[]>([
3136
{
3237
id: '1',
@@ -43,33 +48,13 @@ export function QueryWorkspace({ connectionId, onOpenTableTab }: QueryWorkspaceP
4348
const [showAIPanel, setShowAIPanel] = useState(false)
4449
const editorRef = useRef<any>(null)
4550
const executeQueryRef = useRef<() => void>(() => {})
51+
const newTabRef = useRef<() => void>()
4652
const [showLimitWarning, setShowLimitWarning] = useState(false)
4753
const [queryLimitOverride, setQueryLimitOverride] = useState(false)
4854

4955
const activeTab = tabs.find((tab) => tab.id === activeTabId)
5056
const activeResult = activeTab ? results[activeTab.id] : null
5157

52-
const handleEditorDidMount = useCallback((editor: any, monaco: Monaco) => {
53-
editorRef.current = editor
54-
55-
// Add keyboard shortcuts
56-
editor.addAction({
57-
id: 'execute-query',
58-
label: 'Execute Query',
59-
keybindings: [
60-
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter,
61-
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyE
62-
],
63-
contextMenuGroupId: 'navigation',
64-
contextMenuOrder: 1.5,
65-
run: () => {
66-
if (executeQueryRef.current) {
67-
executeQueryRef.current()
68-
}
69-
}
70-
})
71-
}, [])
72-
7358
// Tab management functions
7459
const handleNewTab = useCallback(() => {
7560
const newTab: QueryTab = {
@@ -144,6 +129,52 @@ export function QueryWorkspace({ connectionId, onOpenTableTab }: QueryWorkspaceP
144129
}
145130
}, [openTableTab, onOpenTableTab])
146131

132+
const handleEditorDidMount = useCallback((editor: any, monaco: Monaco) => {
133+
editorRef.current = editor
134+
135+
// Add keyboard shortcuts
136+
editor.addAction({
137+
id: 'execute-query',
138+
label: 'Execute Query',
139+
keybindings: [
140+
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter,
141+
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyE
142+
],
143+
contextMenuGroupId: 'navigation',
144+
contextMenuOrder: 1.5,
145+
run: () => {
146+
if (executeQueryRef.current) {
147+
executeQueryRef.current()
148+
}
149+
}
150+
})
151+
152+
editor.addAction({
153+
id: 'new-query-tab',
154+
label: 'New Query Tab',
155+
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyN],
156+
contextMenuGroupId: 'navigation',
157+
contextMenuOrder: 1.6,
158+
run: () => {
159+
if (newTabRef.current) {
160+
newTabRef.current()
161+
}
162+
}
163+
})
164+
}, [])
165+
166+
// Update the ref whenever handleNewTab changes
167+
useEffect(() => {
168+
newTabRef.current = handleNewTab
169+
}, [handleNewTab])
170+
171+
// Register the new tab handler with parent component
172+
useEffect(() => {
173+
if (onRegisterNewTabHandler) {
174+
onRegisterNewTabHandler(handleNewTab)
175+
}
176+
}, [handleNewTab, onRegisterNewTabHandler])
177+
147178
const executeQuery = useCallback(
148179
async (queryToExecute: string, forceUnlimited = false) => {
149180
if (!activeTab || activeTab.type !== 'query') return

0 commit comments

Comments
 (0)