Fix mobile terminal tab routing and remount restoration

This commit is contained in:
Mohamed Boudra
2026-02-25 20:05:23 +07:00
parent 91634ca6f2
commit c0420ac1f9
3 changed files with 185 additions and 9 deletions
@@ -57,6 +57,7 @@ export default function TerminalEmulator({
const rootRef = useRef<HTMLDivElement | null>(null);
const hostRef = useRef<HTMLDivElement | null>(null);
const runtimeRef = useRef<TerminalEmulatorRuntime | null>(null);
const appliedInitialOutputRef = useRef<string | null>(null);
useEffect(() => {
const host = hostRef.current;
@@ -86,15 +87,34 @@ export default function TerminalEmulator({
cursorColor,
},
});
appliedInitialOutputRef.current = initialOutputText;
return () => {
runtime.unmount();
if (runtimeRef.current === runtime) {
runtimeRef.current = null;
}
appliedInitialOutputRef.current = null;
};
}, [backgroundColor, cursorColor, foregroundColor, streamKey]);
useEffect(() => {
const runtime = runtimeRef.current;
if (!runtime) {
return;
}
if (appliedInitialOutputRef.current === initialOutputText) {
return;
}
appliedInitialOutputRef.current = initialOutputText;
runtime.clear();
if (initialOutputText.length > 0) {
runtime.write({ text: initialOutputText });
}
}, [initialOutputText]);
useEffect(() => {
runtimeRef.current?.setCallbacks({
callbacks: {
+27 -9
View File
@@ -169,6 +169,24 @@ export function TerminalPane({ serverId, cwd }: TerminalPaneProps) {
const selectedTerminalIdRef = useRef<string | null>(selectedTerminalId);
const pendingTerminalInputRef = useRef<PendingTerminalInput[]>([]);
const updateSelectedTerminalId = useCallback(
(
next:
| string
| null
| ((current: string | null) => string | null)
) => {
const current = selectedTerminalIdRef.current;
const resolved =
typeof next === "function"
? (next as (value: string | null) => string | null)(current)
: next;
selectedTerminalIdRef.current = resolved;
setSelectedTerminalId(resolved);
},
[]
);
useEffect(() => {
selectedTerminalIdRef.current = selectedTerminalId;
}, [selectedTerminalId]);
@@ -377,7 +395,7 @@ export function TerminalPane({ serverId, cwd }: TerminalPaneProps) {
};
});
selectedTerminalByScopeRef.current.set(scopeKey, createdTerminal.id);
setSelectedTerminalId(createdTerminal.id);
updateSelectedTerminalId(createdTerminal.id);
requestTerminalFocus();
}
void queryClient.invalidateQueries({
@@ -401,7 +419,7 @@ export function TerminalPane({ serverId, cwd }: TerminalPaneProps) {
setHoveredTerminalId((current) => (current === terminalId ? null : current));
outputPumpRef.current?.clearTerminal({ terminalId });
if (selectedTerminalIdRef.current === terminalId) {
setSelectedTerminalId((current) =>
updateSelectedTerminalId((current) =>
current === terminalId ? null : current
);
setModifiers({ ...EMPTY_MODIFIERS });
@@ -417,9 +435,9 @@ export function TerminalPane({ serverId, cwd }: TerminalPaneProps) {
});
useEffect(() => {
setSelectedTerminalId(selectedTerminalByScopeRef.current.get(scopeKey) ?? null);
updateSelectedTerminalId(selectedTerminalByScopeRef.current.get(scopeKey) ?? null);
lastReportedSizeRef.current = null;
}, [scopeKey]);
}, [scopeKey, updateSelectedTerminalId]);
useEffect(() => {
if (selectedTerminalId) {
@@ -429,7 +447,7 @@ export function TerminalPane({ serverId, cwd }: TerminalPaneProps) {
useEffect(() => {
if (terminals.length === 0) {
setSelectedTerminalId(null);
updateSelectedTerminalId(null);
return;
}
@@ -442,16 +460,16 @@ export function TerminalPane({ serverId, cwd }: TerminalPaneProps) {
const stored = selectedTerminalByScopeRef.current.get(scopeKey);
if (has(stored)) {
setSelectedTerminalId(stored!);
updateSelectedTerminalId(stored!);
return;
}
const fallback = terminals[0]?.id ?? null;
if (fallback) {
selectedTerminalByScopeRef.current.set(scopeKey, fallback);
setSelectedTerminalId(fallback);
updateSelectedTerminalId(fallback);
}
}, [scopeKey, terminals, selectedTerminalId]);
}, [scopeKey, terminals, selectedTerminalId, updateSelectedTerminalId]);
useEffect(() => {
const terminalIds = terminals.map((terminal) => terminal.id);
@@ -917,7 +935,7 @@ export function TerminalPane({ serverId, cwd }: TerminalPaneProps) {
<Pressable
key={terminal.id}
testID={`terminal-tab-${terminal.id}`}
onPress={() => setSelectedTerminalId(terminal.id)}
onPress={() => updateSelectedTerminalId(terminal.id)}
onHoverIn={() => handleTerminalTabHoverIn(terminal.id)}
onHoverOut={() => handleTerminalTabHoverOut(terminal.id)}
style={({ pressed, hovered }) => [