diff --git a/app/Tabs/Sessions/Navigation/TabBar.tsx b/app/Tabs/Sessions/Navigation/TabBar.tsx index db7c00c..be30ba5 100644 --- a/app/Tabs/Sessions/Navigation/TabBar.tsx +++ b/app/Tabs/Sessions/Navigation/TabBar.tsx @@ -31,6 +31,7 @@ export default function TabBar({ sessions, activeSessionId, onTabPress, onTabClo > { + const activeRef = activeSessionId ? terminalRefs.current[activeSessionId] : null; + if (activeRef && activeRef.current) { + setTimeout(() => { + activeRef.current?.fit(); + }, 0); + } + }, [keyboardHeight, activeSessionId]); + + // Ensure keyboard shows immediately when entering sessions and fit terminal + useFocusEffect( + React.useCallback(() => { + if (sessions.length > 0) { + setTimeout(() => { + hiddenInputRef.current?.focus(); + const activeRef = activeSessionId ? terminalRefs.current[activeSessionId] : null; + activeRef?.current?.fit(); + }, 0); + } + }, [sessions.length, activeSessionId]) + ); + const handleTabPress = (sessionId: string) => { setActiveSession(sessionId); }; @@ -135,31 +158,24 @@ export default function Sessions() { )} - { - // Prevent keyboard dismissal by maintaining focus - hiddenInputRef.current?.focus(); + 0 ? keyboardHeight : 0, + left: 0, + right: 0, + height: 60, + zIndex: 1000, // Ensure tab bar is above everything }} > - 0 ? keyboardHeight : 0, - left: 0, - right: 0, - height: 60, - zIndex: 1000, // Ensure tab bar is above everything - }} - > - - - + + {/* Hidden TextInput to maintain keyboard focus - positioned to not interfere with tab bar */} {sessions.length > 0 && ( diff --git a/app/Tabs/Sessions/Terminal.tsx b/app/Tabs/Sessions/Terminal.tsx index a3241bc..c549f82 100644 --- a/app/Tabs/Sessions/Terminal.tsx +++ b/app/Tabs/Sessions/Terminal.tsx @@ -26,6 +26,7 @@ interface TerminalProps { export type TerminalHandle = { sendInput: (data: string) => void; + fit: () => void; }; export const Terminal = forwardRef(({ @@ -442,6 +443,16 @@ export const Terminal = forwardRef(({ })); } } + + // Expose a fit method for React Native to call when layout changes (e.g., keyboard height) + window.nativeFit = function() { + try { + fitAddon.fit(); + if (ws && ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'resize', data: { cols: terminal.cols, rows: terminal.rows } })); + } + } catch (e) {} + } // Listen for resize events window.addEventListener('resize', handleResize); @@ -538,6 +549,11 @@ export const Terminal = forwardRef(({ const escaped = JSON.stringify(data); webViewRef.current?.injectJavaScript(`window.nativeInput(${escaped}); true;`); } catch (e) {} + }, + fit: () => { + try { + webViewRef.current?.injectJavaScript(`window.nativeFit && window.nativeFit(); true;`); + } catch (e) {} } }), []);