fix: use DOM event listener with stopPropagation to prevent multiple tab closures

This commit is contained in:
Ethanfly 2025-12-31 15:58:33 +08:00
parent 0bafc358aa
commit 9aaa1eaf07
2 changed files with 20 additions and 15 deletions

View File

@ -84,13 +84,6 @@ function App() {
e.preventDefault(); e.preventDefault();
setShowCommandPalette(true); setShowCommandPalette(true);
} }
// Ctrl+W: 关闭当前标签页
if ((e.ctrlKey || e.metaKey) && e.key === 'w') {
e.preventDefault();
if (activeTabId) {
closeTab(activeTabId);
}
}
// Escape: 关闭弹窗 // Escape: 关闭弹窗
if (e.key === 'Escape') { if (e.key === 'Escape') {
setShowCommandPalette(false); setShowCommandPalette(false);
@ -101,7 +94,7 @@ function App() {
window.addEventListener('keydown', handleKeyDown); window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown);
}, [activeTabId, closeTab]); }, []);
// 连接主机 // 连接主机
const connectHost = useCallback((host) => { const connectHost = useCallback((host) => {

View File

@ -22,6 +22,7 @@ function Terminal({ tabId, hostId, isActive, onConnectionChange, onShowCommandPa
const contextMenuHandlerRef = useRef(null); const contextMenuHandlerRef = useRef(null);
const resizeTimeoutRef = useRef(null); const resizeTimeoutRef = useRef(null);
const webglAddonRef = useRef(null); const webglAddonRef = useRef(null);
const keydownHandlerRef = useRef(null);
const onConnectionChangeRef = useRef(onConnectionChange); const onConnectionChangeRef = useRef(onConnectionChange);
onConnectionChangeRef.current = onConnectionChange; onConnectionChangeRef.current = onConnectionChange;
@ -234,31 +235,36 @@ function Terminal({ tabId, hostId, isActive, onConnectionChange, onShowCommandPa
} }
}); });
// 自定义按键处理 - 拦截 Ctrl+W 和 Ctrl+K仅当前活动标签页响应 // 在容器上添加键盘事件监听器(捕获阶段),确保能拦截并阻止事件冒泡
term.attachCustomKeyEventHandler((e) => { keydownHandlerRef.current = (e) => {
// 只有活动标签页才响应快捷键 // 只有活动标签页才响应快捷键
if (!isActiveRef.current) { if (!isActiveRef.current) {
return true; return;
} }
// Ctrl+W: 关闭当前标签页 // Ctrl+W: 关闭当前标签页
if ((e.ctrlKey || e.metaKey) && e.key === 'w') { if ((e.ctrlKey || e.metaKey) && e.key === 'w') {
e.preventDefault(); e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
if (onCloseTabRef.current) { if (onCloseTabRef.current) {
onCloseTabRef.current(); onCloseTabRef.current();
} }
return false; // 阻止 xterm 处理 return;
} }
// Ctrl+K: 打开命令面板 // Ctrl+K: 打开命令面板
if ((e.ctrlKey || e.metaKey) && e.key === 'k') { if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault(); e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
if (onShowCommandPaletteRef.current) { if (onShowCommandPaletteRef.current) {
onShowCommandPaletteRef.current(); onShowCommandPaletteRef.current();
} }
return false; return;
} }
return true; // 允许 xterm 处理其他按键 };
}); // 使用捕获阶段确保在 xterm 处理之前拦截
container.addEventListener('keydown', keydownHandlerRef.current, true);
// 选中自动复制到剪贴板 // 选中自动复制到剪贴板
term.onSelectionChange(() => { term.onSelectionChange(() => {
@ -344,6 +350,12 @@ function Terminal({ tabId, hostId, isActive, onConnectionChange, onShowCommandPa
contextMenuHandlerRef.current = null; contextMenuHandlerRef.current = null;
} }
// 清理键盘事件监听器
if (keydownHandlerRef.current && terminalRef.current) {
terminalRef.current.removeEventListener('keydown', keydownHandlerRef.current, true);
keydownHandlerRef.current = null;
}
if (cleanupListenersRef.current) { if (cleanupListenersRef.current) {
cleanupListenersRef.current(); cleanupListenersRef.current();
cleanupListenersRef.current = null; cleanupListenersRef.current = null;