fix: restore special keys bar on mobile terminal
- Add SpecialKeysStrip and SpecialKeysPanel to mobile terminal page - Store sendData and focusInput refs via onTerminalReady callback - Pass activeModifier/onModifierChange to TerminalComponent on mobile - Add virtual keyboard padding to prevent keyboard from covering terminal - Special keys bar sits at bottom of viewport, panel opens as overlay
This commit is contained in:
@@ -6,10 +6,14 @@ import {
|
||||
type TerminalSessionInfo,
|
||||
} from "../components/terminal-session-tabs";
|
||||
import { Icon } from "../components/icon";
|
||||
import { SpecialKeysStrip } from "../components/special-keys-strip";
|
||||
import { SpecialKeysPanel } from "../components/special-keys-panel";
|
||||
import { useMobileViewport } from "../hooks/use-mobile-viewport";
|
||||
import { useAutoHide } from "../hooks/use-auto-hide";
|
||||
import { useVirtualKeyboard } from "../hooks/use-virtual-keyboard";
|
||||
import { useTerminalSessions } from "../hooks/use-terminal-sessions";
|
||||
import type { TerminalSession } from "../api/terminal";
|
||||
import type { ModifierKey } from "../hooks/use-special-keys";
|
||||
|
||||
const SESSIONS_TO_INFO = (sessions: TerminalSession[]): TerminalSessionInfo[] =>
|
||||
sessions.map((s) => ({
|
||||
@@ -40,7 +44,12 @@ export const TerminalPage: React.FC = () => {
|
||||
Record<string, TerminalStatus>
|
||||
>({});
|
||||
const changeFontSizeRef = useRef<((delta: number) => void) | null>(null);
|
||||
const sendDataRef = useRef<((data: string) => void) | null>(null);
|
||||
const focusInputRef = useRef<(() => void) | null>(null);
|
||||
const [showResetConfirm, setShowResetConfirm] = useState(false);
|
||||
const [showSpecialKeysPanel, setShowSpecialKeysPanel] = useState(false);
|
||||
const [activeModifier, setActiveModifier] = useState<ModifierKey | null>(null);
|
||||
const { isOpen: isKeyboardOpen, height: keyboardHeight } = useVirtualKeyboard();
|
||||
|
||||
const {
|
||||
sessions,
|
||||
@@ -206,15 +215,17 @@ export const TerminalPage: React.FC = () => {
|
||||
|
||||
const handleTerminalReady = useCallback(
|
||||
(
|
||||
_sendData: (data: string) => void,
|
||||
sendData: (data: string) => void,
|
||||
status: TerminalStatus,
|
||||
_focusInput: () => void,
|
||||
focusInput: () => void,
|
||||
changeFontSize: (delta: number) => void,
|
||||
) => {
|
||||
setTerminalStatuses((prev) => ({
|
||||
...prev,
|
||||
[activeSessionId ?? "default"]: status,
|
||||
}));
|
||||
sendDataRef.current = sendData;
|
||||
focusInputRef.current = focusInput;
|
||||
changeFontSizeRef.current = changeFontSize;
|
||||
},
|
||||
[activeSessionId],
|
||||
@@ -224,6 +235,10 @@ export const TerminalPage: React.FC = () => {
|
||||
changeFontSizeRef.current?.(delta);
|
||||
}, []);
|
||||
|
||||
const handleSendKey = useCallback((data: string) => {
|
||||
sendDataRef.current?.(data);
|
||||
}, []);
|
||||
|
||||
const handleReset = useCallback(() => {
|
||||
if (activeSessionId && terminalRefs.current[activeSessionId]) {
|
||||
terminalRefs.current[activeSessionId].current?.reset();
|
||||
@@ -318,6 +333,7 @@ export const TerminalPage: React.FC = () => {
|
||||
{/* Terminal content — always fills full viewport */}
|
||||
<div
|
||||
className="terminal-page-content mobile-full"
|
||||
style={{ paddingBottom: isKeyboardOpen ? keyboardHeight : 0 }}
|
||||
onClick={() => headerAutoHide.toggle()}
|
||||
>
|
||||
{error && <div className="terminal-error-banner">{error}</div>}
|
||||
@@ -332,6 +348,8 @@ export const TerminalPage: React.FC = () => {
|
||||
onClose={() => handleClose(session.id)}
|
||||
isMobile={true}
|
||||
showControls={false}
|
||||
activeModifier={activeModifier}
|
||||
onModifierChange={setActiveModifier}
|
||||
onTerminalReady={handleTerminalReady}
|
||||
/>
|
||||
</div>
|
||||
@@ -342,6 +360,24 @@ export const TerminalPage: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<SpecialKeysStrip
|
||||
onSend={handleSendKey}
|
||||
isVisible={!showSpecialKeysPanel}
|
||||
onMoreClick={() => setShowSpecialKeysPanel(true)}
|
||||
onKeepFocus={() => focusInputRef.current?.()}
|
||||
activeModifier={activeModifier}
|
||||
onModifierChange={setActiveModifier}
|
||||
/>
|
||||
|
||||
<SpecialKeysPanel
|
||||
onSend={handleSendKey}
|
||||
isOpen={showSpecialKeysPanel}
|
||||
onClose={() => setShowSpecialKeysPanel(false)}
|
||||
onKeepFocus={() => focusInputRef.current?.()}
|
||||
activeModifier={activeModifier}
|
||||
onModifierChange={setActiveModifier}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user