feat(app): auto-focus terminal on create/switch, stabilize sidebar ordering for new items

This commit is contained in:
Mohamed Boudra
2026-03-06 23:19:12 +07:00
parent 1985bd6669
commit a99edcc0b2
5 changed files with 332 additions and 7 deletions
@@ -6,6 +6,7 @@ import "@xterm/xterm/css/xterm.css";
import type { ITheme } from "@xterm/xterm";
import type { PendingTerminalModifiers } from "../utils/terminal-keys";
import { TerminalEmulatorRuntime } from "../terminal/runtime/terminal-emulator-runtime";
import { focusWithRetries } from "../utils/web-focus";
import {
summarizeTerminalText,
terminalDebugLog,
@@ -343,7 +344,19 @@ export default function TerminalEmulator({
if (focusRequestToken <= 0) {
return;
}
runtimeRef.current?.focus();
return focusWithRetries({
focus: () => {
runtimeRef.current?.focus();
},
isFocused: () => {
const root = rootRef.current;
if (!root) {
return false;
}
const active = typeof document !== "undefined" ? document.activeElement : null;
return active instanceof HTMLElement && root.contains(active);
},
});
}, [focusRequestToken]);
useEffect(() => {
@@ -214,6 +214,7 @@ export function TerminalPane({
const selectedTerminalIdRef = useRef<string | null>(selectedTerminalId);
const pendingTerminalInputRef = useRef<PendingTerminalInput[]>([]);
const keyboardRefitTimeoutsRef = useRef<Array<ReturnType<typeof setTimeout>>>([]);
const lastAutoFocusKeyRef = useRef<string | null>(null);
const updateSelectedTerminalId = useCallback(
(next: string | null) => {
@@ -279,6 +280,21 @@ export function TerminalPane({
setResizeRequestToken((current) => current + 1);
}, []);
useEffect(() => {
if (isMobile || !isScreenFocused || !selectedTerminalId) {
lastAutoFocusKeyRef.current = null;
return;
}
const nextFocusKey = `${scopeKey}:${selectedTerminalId}`;
if (lastAutoFocusKeyRef.current === nextFocusKey) {
return;
}
lastAutoFocusKeyRef.current = nextFocusKey;
requestTerminalFocus();
}, [isMobile, isScreenFocused, requestTerminalFocus, scopeKey, selectedTerminalId]);
const clearKeyboardRefitTimeouts = useCallback(() => {
if (keyboardRefitTimeoutsRef.current.length === 0) {
return;