mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 01:57:57 +00:00
* [comment audit] Align legacy failure-read counts with cached display * [comment audit] Condense shared provider lifecycle and browser recovery comments [skip ci] * [comment audit] Condense shared generation, path and preview comments [skip ci] * [comment audit] Condense host, file and Git contract rationale [skip ci] * [comment audit] Tighten Git lifecycle and provider contract comments [skip ci] * [comment audit] Clarify shared host authority and launch isolation [skip ci] * [comment audit] simplify local access mobile and native chat contracts [skip ci] * [comment audit] simplify native chat presentation and state contracts [skip ci] * [comment audit] simplify native runtime and provider contracts [skip ci] * [comment audit] simplify migration and orchestration contracts [skip ci] * [comment audit] simplify plugin trust and process capture rationale [skip ci] * [comment audit] simplify terminal delivery and remote compatibility rationale [skip ci] * [comment audit] clarify remote recovery and launch wire rationale [skip ci] * [comment audit] shorten shared RPC compatibility and runtime evidence comments [skip ci] * [comment audit] simplify secure storage shell startup and sidebar rationale [skip ci] * [comment audit] clarify sidebar, skill and SSH invariants [skip ci] * [comment audit] condense structured chat delivery and timing rationale [skip ci] * [comment audit] condense terminal replay and telemetry invariants [skip ci] * [comment audit] clarify launch permission and terminal delivery rationale [skip ci] * [comment audit] clarify workspace ownership and layout contracts [skip ci] * [comment audit] wait for fitted and painted SSH terminal links * [comment audit] clarify layout persistence and session ownership [skip ci] * [comment audit] clarify host routing and workspace lifecycle contracts [skip ci] * [comment audit] clarify startup persistence and app lifetime comments [skip ci] * [comment audit] clarify recovery and activity boundaries [skip ci] * [comment audit] condense activity and artifact invariants [skip ci] * [comment audit] condense automation authority contracts [skip ci] * [comment audit] simplify automation scheduling and history contracts [skip ci] * [comment audit] clarify browser chrome and annotation lifecycles [skip ci] * [comment audit] clarify browser routing and retained guest ownership [skip ci] * [comment audit] clarify browser recovery and document ownership comments [skip ci] * [comment audit] restore hosted runners required by native IME fixtures * [comment audit] shorten preview, palette and dashboard invariants [skip ci] * [comment audit] clarify terminal preview, dashboard and retention comments [skip ci] * [comment audit] clarify diff-note recovery and editor lifecycle comments [skip ci] * [comment audit] shorten rich-text and combined-diff ownership comments [skip ci] * [comment audit] shorten autosave, draft recovery and model ownership comments [skip ci] * [comment audit] shorten save-queue, notebook and Markdown constraints [skip ci] * [comment audit] shorten Monaco, PDF and rich Markdown safeguards [skip ci] * [comment audit] clarify rich Markdown source and selection safeguards [skip ci] * [comment audit] clarify editor loading and emulator stream lifetimes [skip ci] * [comment audit] trim emulator and feature tour narration [skip ci] * [comment audit] clarify floating workspace and GitHub cache ownership [skip ci] * [comment audit] trim provider controls and Linear filter explanations [skip ci] * [comment audit] clarify pairing and chat resume lifetimes [skip ci] * [comment audit] clarify chat delivery and transcript lifetimes [skip ci] * [comment audit] clarify session options and host-owned status [skip ci] * [comment audit] clarify draft durability and live-status precedence [skip ci] * [comment audit] Trim chat send and model ownership explanations [skip ci] * [comment audit] Shorten transcript ownership and send recovery comments [skip ci] * [comment audit] Simplify native chat composer and transcript hook comments [skip ci] * [comment audit] Shorten native chat scroll and structured session explanations [skip ci] * [comment audit] Trim workspace picker and onboarding commentary [skip ci] * [comment audit] Simplify pet rendering, review cache and quick open comments [skip ci] * [comment audit] Trim sidebar and session history explanations [skip ci] * [comment audit] Condense session resume and review checks comments [skip ci] * [comment audit] Shorten checks state and file explorer refresh comments [skip ci] * [comment audit] Trim plugin bridge and source-control action rationale [skip ci] * [comment audit] Trim source-control listing and review rationale [skip ci] * [comment audit] Shorten sidebar lifecycle and explorer safeguards [skip ci] * [comment audit] Condense Settings account and appearance rationale [skip ci] * [comment audit] Trim pairing and repository Settings explanations [skip ci] * [comment audit] Condense Settings search SSH and terminal safeguards [skip ci] * [comment audit] Shorten Settings voice and provider ownership comments [skip ci] * [comment audit] Condense Settings draft persistence and host-state rationale [skip ci] * [comment audit] Trim Settings hooks and sidebar setup rationale [skip ci] * [comment audit] Condense sidebar deletion and board-filter safeguards [skip ci] * [comment audit] Condense worktree cards, host ownership and Markdown contracts [skip ci] * [comment audit] Condense sidebar drag, folder and filtering contracts [skip ci] * [comment audit] Condense sidebar parity, sleep and host ownership contracts [skip ci] * [comment audit] Prune focus-read baseline after comment cleanup * [comment audit] Clarify sidebar visibility, board drops and agent evidence [skip ci] * [comment audit] Tighten sidebar listing, drag and reveal contracts [skip ci] * [comment audit] Clarify viewport geometry and skill update safeguards [skip ci] * [comment audit] Tighten skill inventory, usage and host status comments [skip ci] * [comment audit] Clarify usage ownership and resource kill safeguards [skip ci] * [comment audit] Tighten tab selection, rename and search contracts [skip ci] * [comment audit] Tighten tab-strip geometry and drag ownership comments [skip ci] * [comment audit] Tighten Tasks recovery, pagination and mutation comments [skip ci] * [comment audit] Tighten provider loading and terminal recovery comments [skip ci] * [comment audit] Tighten completion, cadence and PTY ownership comments [skip ci] * [comment audit] Clarify terminal restore and parked-pane boundaries [skip ci] * [comment audit] Tighten PTY startup and replay explanations [skip ci] * [comment audit] Clarify PTY identity and delivery ownership [skip ci] * [comment audit] Shorten remote reconnect and input replay rationale [skip ci] * [comment audit] Condense terminal parking clipboard and file link comments [skip ci] * [comment audit] Clarify IME ownership and trim trace history [skip ci] * [comment audit] Shorten pane recovery and parked watcher explanations [skip ci] * [comment audit] Condense snapshot replay and visibility recovery rationale [skip ci] * [comment audit] Shorten terminal parking and keyboard ownership rationale [skip ci] * [comment audit] Trim renderer lifecycle and menu rationale [skip ci] * [comment audit] Condense workspace cleanup ownership and settlement notes [skip ci] * [comment audit] Clarify renderer hook evidence and source ownership [skip ci] * [comment audit] Tighten IPC ownership and reconnect explanations [skip ci] * [comment audit] Trim renderer focus, paste and attention comments [skip ci] * [comment audit] Shorten scroll, locale and agent lifecycle comments [skip ci] * [comment audit] Trim agent launch, resume and ownership commentary [skip ci] * [comment audit] Shorten account, browser and editor comments [skip ci] * [comment audit] Clarify host-mirror waits, previews and input ownership [skip ci] * [comment audit] Condense launch recovery and editor tokenization comments [skip ci] * [comment audit] Condense workspace selection and terminal pane rationale [skip ci] * [comment audit] Condense terminal fitting and rendering recovery comments [skip ci] * [comment audit] Condense terminal input and host routing explanations [skip ci] * [comment audit] Condense ownership and sleeping-session recovery rationale [skip ci] * [comment audit] Condense structured launch and terminal link explanations [skip ci] * [comment audit] Condense terminal ownership and workspace file routing rationale [skip ci] * [comment audit] Condense session persistence and workspace activation rationale [skip ci] * [comment audit] Condense workspace routing and browser ownership rationale [skip ci] * [comment audit] Condense mirror recovery and layout authority rationale [skip ci] * [comment audit] Condense runtime transport and file safety rationale [skip ci] * [comment audit] Condense runtime graph and structured session rationale [skip ci] * [comment audit] Condense browser creation and remote tab recovery rationale [skip ci] * [comment audit] Condense snapshot authority and publisher recovery rationale [skip ci] * [comment audit] Condense frame, startup and provider cache rationale [skip ci] * [comment audit] Condense host twin and agent lifecycle rationale [skip ci] * [comment audit] Condense browser authority and editor cleanup rationale [skip ci] * [comment audit] Condense editor buffer identity and review cache rationale [skip ci] * [comment audit] Condense provider lifetime and repository ownership rationale [skip ci] * [comment audit] Condense reconnect, hydration and terminal retirement rationale [skip ci] * [comment audit] Condense recovery, reconciliation and persistence rationale [skip ci] * [comment audit] Condense cleanup ownership and listing admission rationale [skip ci] * [comment audit] Condense teardown ordering and terminal ownership rationale [skip ci] * [comment audit] Condense recovery ledger and web host-boundary rationale [skip ci] * [comment audit] Condense web reconnect and credential lifecycle rationale [skip ci] * [comment audit] Condense cloud rollout and assignment safety rationale [skip ci] * [comment audit] Condense relay session and database recovery rationale [skip ci] * [comment audit] Condense relay placement and protocol compatibility rationale [skip ci] * [comment audit] Condense build and packaging constraints [skip ci] * [comment audit] Condense CI gates and validation isolation rationale [skip ci] * [comment audit] Condense catalog identity and browser validation rationale [skip ci] * [comment audit] Condense mobile browser and frame-budget rationale [skip ci] * [comment audit] Shorten mobile route and browser test explanations [skip ci] * [comment audit] Condense editor and session seam test rationale [skip ci] * [comment audit] Trim session and terminal closure history [skip ci] * [comment audit] Shorten terminal browser and census explanations [skip ci] * [comment audit] Preserve root-only E2E diagnostic baseline * [comment audit] Condense mobile seam and HTML preview test rationale [skip ci] * [comment audit] Condense preview instrumentation and render harness rationale [skip ci] * [comment audit] Condense bundle contracts and native-build constraints [skip ci] * [comment audit] Shorten native packaging and CI routing rationale [skip ci] * [comment audit] Condense release tooling and benchmark constraints [skip ci] * [comment audit] Condense packaging and platform gate rationale [skip ci] * [comment audit] Shorten mobile route and history rationale [skip ci] * [comment audit] Condense mobile browser and component rationale [skip ci] * [comment audit] Shorten drawer and workspace-form rationale [skip ci] * [comment audit] Trim mobile review and editor-document explanations [skip ci] * [comment audit] Condense editor lifecycle and Markdown explanations [skip ci] * [comment audit] Trim mobile file, diagnostics and dictation commentary [skip ci] * [comment audit] Simplify mobile host-list and workspace-view explanations [skip ci] * [comment audit] Clarify mobile shell lifetime and bridge delivery constraints [skip ci] * [comment audit] Condense bridge stream, native request and audio rationale [skip ci] * [comment audit] Reduce bridge schema and page-client commentary [skip ci] * [comment audit] Tighten mobile page bridge contracts [skip ci] * [comment audit] Clarify mobile cache and session constraints [skip ci] * [comment audit] Condense mobile route and lifecycle rationale [skip ci] * [comment audit] Tighten mobile shell hook timing rationale [skip ci] * [comment audit] Clarify route handoff and notification compatibility [skip ci] * [comment audit] Clarify push registration and dictation cleanup constraints [skip ci] * [comment audit] Condense keyboard geometry and native media ownership rationale [skip ci] * [comment audit] Tighten mobile chat scroll and composer concurrency rationale [skip ci] * [comment audit] Condense mobile reply compatibility and upload ownership rationale [skip ci] * [comment audit] Condense optimistic echo and scroll ownership rationale [skip ci] * [comment audit] Tighten stream replay and queued session ownership rationale [skip ci] * [comment audit] Condense mobile composer and reply-schema constraints [skip ci] * [comment audit] Clarify mobile transcript recovery and session ownership [skip ci] * [comment audit] Clarify mobile queue and source-control compatibility [skip ci] * [comment audit] Condense storage and task launch constraints [skip ci] * [comment audit] Clarify task schemas and terminal document ownership [skip ci] * [comment audit] Tighten terminal input and viewport rationale [skip ci] * [comment audit] Shorten terminal and RPC recorder contracts [skip ci] * [comment audit] Condense recorder engine and connection contracts [skip ci] * [comment audit] Shorten host credential and relay recovery comments [skip ci] * [comment audit] Tighten pairing recovery and bundle transport rationale [skip ci] * [comment audit] Clarify RPC delivery and workspace catalog boundaries [skip ci] * [comment audit] Condense catalog and relay entry contracts [skip ci] * [comment audit] Shorten shutdown and SSH relay delivery contracts [skip ci] * [comment audit] Condense WSL relay and E2E regression rationale [skip ci] * [comment audit] Shorten cross-version harness and renderer fixture explanations [skip ci] * [comment audit] Condense paired-host and E2E lifecycle rationale [skip ci] * [comment audit] Shorten layout oracle and regression explanations [skip ci] * [comment audit] Condense paired recovery and ownership regression contracts [skip ci] * [comment audit] Shorten restart, sidebar and SSH lifecycle contracts [skip ci] * [comment audit] Condense terminal rendering and IME regression rationale [skip ci] * [comment audit] Shorten terminal recovery and benchmark contracts [skip ci] * [comment audit] Condense tooling and Windows lifecycle proof rationale [skip ci] * [comment audit] Condense workflow routing and release rationale [skip ci] * [comment audit] Condense mobile security and installer contracts [skip ci] * [comment audit] Shorten native rationale and stylesheet workarounds [skip ci] * [comment audit] Shorten Windows visibility probe rationale [skip ci] * [comment audit] Condense embedded release and signing rationale [skip ci] * [comment audit] Retain current main test behavior in final reconciliation [skip ci] * [comment audit] Complete final comment review across current source inventory * [comment audit] Handle consolidated audit reports before final CI * [comment audit] Preserve credential storage census detail [skip ci] * [comment audit] Scale broad changed E2E selections with verified timing shards * [comment audit] Align E2E assertions with browser close and settled session metadata * [comment audit] Match existing E2Es to current resource and windowing contracts * [comment audit] Observe the shared server outage notice in reconnect coverage * [comment audit] Make existing renderer probes measure settled tab and PTY work * [comment audit] Align palette E2E selector with task search * [comment audit] Refresh remaining palette search selectors * [comment audit] Keep selector correction within selected audit specs * [comment audit] Await emoji fixture settings inside renderer evaluation * [comment audit] Cancel fixture fit retries between terminal tests --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
381 lines
14 KiB
TypeScript
381 lines
14 KiB
TypeScript
import { View, Text, ScrollView, TextInput, Pressable } from 'react-native'
|
|
import { hostOs } from '../platform/host-os'
|
|
import {
|
|
ArrowUp,
|
|
ChevronDown,
|
|
ChevronsRight,
|
|
Keyboard as KeyboardIcon,
|
|
Monitor,
|
|
Plus,
|
|
Smartphone
|
|
} from 'lucide-react-native'
|
|
import { triggerMediumImpact } from '../platform/haptics'
|
|
import { createTerminalLiveAccessoryInput } from '../terminal/terminal-live-accessory-input'
|
|
import {
|
|
getTerminalCommandKeyboardType,
|
|
getTerminalLiveInputKeyboardType
|
|
} from '../terminal/terminal-keyboard-type'
|
|
import { MobileTerminalLiveInputStatus } from './MobileTerminalLiveInputStatus'
|
|
import { MobileTerminalInputActions } from './MobileTerminalInputActions'
|
|
import { keepHeldPressThroughLongPress } from './held-press-long-press'
|
|
import { isTerminalPhoneDisplayMode } from './mobile-session-route-helpers'
|
|
import { colors } from '../theme/mobile-theme'
|
|
import { styles } from './mobile-session-styles'
|
|
import { useKeyboardPersistingTaps } from '../platform/keyboard-persisting-taps'
|
|
import type { MobileSessionController } from './use-mobile-session-controller'
|
|
|
|
export function MobileSessionCommandDock({ controller }: { controller: MobileSessionController }) {
|
|
const {
|
|
insets,
|
|
bufferedTerminalDraftState,
|
|
autocompleteEnabled,
|
|
liveInputCapture,
|
|
activeHandle,
|
|
customKeys,
|
|
setShowCustomKeyModal,
|
|
setDeleteKeyTarget,
|
|
visibleBuiltInAccessoryKeys,
|
|
terminalModes,
|
|
canPaste,
|
|
dictationMode,
|
|
dictationEnabled,
|
|
bindCommandField,
|
|
handleLiveInputChange,
|
|
handleLiveInputKeyPress,
|
|
bindLiveInputField,
|
|
submitLiveInput,
|
|
canSend,
|
|
canCompose,
|
|
liveInputEnabled,
|
|
focusLiveInput,
|
|
showNativeChat,
|
|
dictation,
|
|
cancelDictation,
|
|
handleDictationToggle,
|
|
handleDictationPressIn,
|
|
handleDictationPressOut,
|
|
toggleDisplayMode,
|
|
handleSend,
|
|
handleAccessoryKey,
|
|
dismissSoftwareKeyboard,
|
|
toggleLiveInput,
|
|
stopAccessoryRepeat,
|
|
startAccessoryRepeat,
|
|
handlePaste,
|
|
isAttaching,
|
|
attachImage,
|
|
activeMarkdownTab,
|
|
activeFileTab,
|
|
activeBrowserTab,
|
|
keyboardLift
|
|
} = controller
|
|
const accessoryBarKeepsKeyboard = useKeyboardPersistingTaps('always')
|
|
return (
|
|
!activeMarkdownTab &&
|
|
!activeFileTab &&
|
|
!activeBrowserTab &&
|
|
!showNativeChat && (
|
|
<View
|
|
style={[
|
|
styles.commandDock,
|
|
{ paddingBottom: insets.bottom, transform: [{ translateY: -keyboardLift }] }
|
|
]}
|
|
>
|
|
{}
|
|
<View ref={accessoryBarKeepsKeyboard} style={styles.accessoryBar}>
|
|
{/* Why: fixed keyboard escape hatch; outside ScrollView + shortcut path so it can't scroll away or be hidden (#5106). */}
|
|
{keyboardLift > 0 && (
|
|
<Pressable
|
|
style={({ pressed }) => [
|
|
styles.keyboardDismissKey,
|
|
pressed && styles.accessoryKeyPressed
|
|
]}
|
|
onPress={dismissSoftwareKeyboard}
|
|
hitSlop={8}
|
|
accessibilityRole="button"
|
|
accessibilityLabel="Dismiss keyboard"
|
|
accessibilityHint="Hides the software keyboard and keeps the current terminal session open."
|
|
>
|
|
<View style={styles.keyboardDismissGlyph}>
|
|
<KeyboardIcon size={15} color={colors.textSecondary} strokeWidth={2} />
|
|
<ChevronDown
|
|
size={10}
|
|
color={colors.textSecondary}
|
|
strokeWidth={2.5}
|
|
style={styles.keyboardDismissChevron}
|
|
/>
|
|
</View>
|
|
</Pressable>
|
|
)}
|
|
{/* Why: default tap handling makes the first accessory-key tap dismiss the keyboard and get swallowed (#5106). */}
|
|
<ScrollView
|
|
style={styles.accessoryScroll}
|
|
horizontal
|
|
showsHorizontalScrollIndicator={false}
|
|
contentContainerStyle={styles.accessoryContent}
|
|
keyboardShouldPersistTaps="always"
|
|
>
|
|
<Pressable
|
|
style={({ pressed }) => [
|
|
styles.accessoryKey,
|
|
pressed && styles.accessoryKeyPressed,
|
|
!canSend && styles.accessoryKeyDisabled
|
|
]}
|
|
disabled={!canSend}
|
|
onPress={() => {
|
|
if (activeHandle) {
|
|
void toggleDisplayMode(activeHandle)
|
|
}
|
|
}}
|
|
accessibilityLabel={
|
|
isTerminalPhoneDisplayMode(activeHandle, terminalModes)
|
|
? 'Switch to desktop mode'
|
|
: 'Switch to phone mode'
|
|
}
|
|
>
|
|
{isTerminalPhoneDisplayMode(activeHandle, terminalModes) ? (
|
|
<Monitor size={14} color={canSend ? colors.textSecondary : colors.textMuted} />
|
|
) : (
|
|
<Smartphone size={14} color={canSend ? colors.textSecondary : colors.textMuted} />
|
|
)}
|
|
</Pressable>
|
|
<Pressable
|
|
style={({ pressed }) => [
|
|
styles.accessoryKey,
|
|
liveInputEnabled && styles.accessoryKeyActive,
|
|
pressed && styles.accessoryKeyPressed,
|
|
!canCompose && styles.accessoryKeyDisabled
|
|
]}
|
|
// Why: offline, live mode is dead but the buffered box still composes — keep the escape hatch tappable (#6713).
|
|
disabled={!canCompose}
|
|
onPress={toggleLiveInput}
|
|
accessibilityLabel={
|
|
liveInputEnabled
|
|
? 'Switch to buffered command input'
|
|
: 'Switch to live terminal input'
|
|
}
|
|
>
|
|
<ChevronsRight
|
|
size={14}
|
|
color={
|
|
liveInputEnabled
|
|
? colors.bgBase
|
|
: canCompose
|
|
? colors.textSecondary
|
|
: colors.textMuted
|
|
}
|
|
/>
|
|
</Pressable>
|
|
{canPaste && (
|
|
<Pressable
|
|
style={({ pressed }) => [
|
|
styles.accessoryKey,
|
|
pressed && styles.accessoryKeyPressed,
|
|
!canSend && styles.accessoryKeyDisabled
|
|
]}
|
|
disabled={!canSend}
|
|
onPress={() => void handlePaste()}
|
|
accessibilityLabel="Paste from clipboard"
|
|
>
|
|
<Text
|
|
style={[styles.accessoryKeyText, !canSend && styles.accessoryKeyTextDisabled]}
|
|
>
|
|
Paste
|
|
</Text>
|
|
</Pressable>
|
|
)}
|
|
{visibleBuiltInAccessoryKeys.map((key) => (
|
|
<Pressable
|
|
key={key.id}
|
|
style={({ pressed }) => [
|
|
styles.accessoryKey,
|
|
pressed && styles.accessoryKeyPressed,
|
|
!canSend && styles.accessoryKeyDisabled
|
|
]}
|
|
disabled={!canSend}
|
|
onPressIn={() => {
|
|
if (!key.repeatable) {
|
|
return
|
|
}
|
|
const input = createTerminalLiveAccessoryInput(key)
|
|
void handleAccessoryKey(input)
|
|
startAccessoryRepeat(input)
|
|
}}
|
|
onPressOut={() => {
|
|
if (key.repeatable) {
|
|
stopAccessoryRepeat()
|
|
}
|
|
}}
|
|
onPress={() => {
|
|
if (key.repeatable) {
|
|
return
|
|
}
|
|
void handleAccessoryKey(createTerminalLiveAccessoryInput(key))
|
|
}}
|
|
onLongPress={key.repeatable ? keepHeldPressThroughLongPress : undefined}
|
|
accessibilityLabel={key.accessibilityLabel ?? `Send ${key.label}`}
|
|
>
|
|
<Text
|
|
style={[styles.accessoryKeyText, !canSend && styles.accessoryKeyTextDisabled]}
|
|
>
|
|
{key.label}
|
|
</Text>
|
|
</Pressable>
|
|
))}
|
|
{customKeys.map((key) => (
|
|
<Pressable
|
|
key={key.id}
|
|
style={({ pressed }) => [
|
|
styles.accessoryKey,
|
|
styles.customAccessoryKey,
|
|
pressed && styles.accessoryKeyPressed,
|
|
!canSend && styles.accessoryKeyDisabled
|
|
]}
|
|
disabled={!canSend}
|
|
onPress={() => void handleAccessoryKey({ bytes: key.bytes })}
|
|
onLongPress={() => {
|
|
triggerMediumImpact()
|
|
setDeleteKeyTarget(key)
|
|
}}
|
|
delayLongPress={400}
|
|
accessibilityLabel={`Send ${key.label}`}
|
|
>
|
|
<Text
|
|
style={[styles.accessoryKeyText, !canSend && styles.accessoryKeyTextDisabled]}
|
|
>
|
|
{key.label}
|
|
</Text>
|
|
</Pressable>
|
|
))}
|
|
<Pressable
|
|
style={({ pressed }) => [styles.accessoryKey, pressed && styles.accessoryKeyPressed]}
|
|
onPress={() => setShowCustomKeyModal(true)}
|
|
accessibilityLabel="Add custom shortcut"
|
|
>
|
|
<Plus size={14} color={colors.textSecondary} strokeWidth={2.2} />
|
|
</Pressable>
|
|
</ScrollView>
|
|
</View>
|
|
|
|
{}
|
|
{liveInputEnabled ? (
|
|
<View style={[styles.inputBar, styles.liveInputBar]}>
|
|
<Pressable
|
|
style={({ pressed }) => [
|
|
styles.liveInputFocusTarget,
|
|
pressed && styles.liveInputFocusTargetPressed,
|
|
!canSend && styles.liveInputFocusTargetDisabled
|
|
]}
|
|
disabled={!canSend}
|
|
onPress={focusLiveInput}
|
|
accessibilityRole="button"
|
|
accessibilityLabel="Show keyboard for live terminal input"
|
|
accessibilityHint="Typed text is sent directly to the active terminal"
|
|
>
|
|
<KeyboardIcon size={16} color={colors.textSecondary} strokeWidth={2} />
|
|
<MobileTerminalLiveInputStatus
|
|
dictation={dictation}
|
|
isAttaching={isAttaching}
|
|
liveInputText={liveInputCapture}
|
|
/>
|
|
</Pressable>
|
|
<MobileTerminalInputActions
|
|
canSend={canSend}
|
|
isAttaching={isAttaching}
|
|
dictation={dictation}
|
|
dictationMode={dictationMode}
|
|
dictationEnabled={dictationEnabled}
|
|
buttonStyle={styles.dictationButton}
|
|
activeButtonStyle={styles.dictationButtonActive}
|
|
disabledButtonStyle={styles.sendButtonDisabled}
|
|
onAttachImage={() => void attachImage('library')}
|
|
onAttachFile={() => void attachImage('files')}
|
|
onDictationToggle={handleDictationToggle}
|
|
onDictationPressIn={handleDictationPressIn}
|
|
onDictationPressOut={handleDictationPressOut}
|
|
onDictationCancel={cancelDictation}
|
|
/>
|
|
<TextInput
|
|
ref={bindLiveInputField}
|
|
style={styles.liveInputCapture}
|
|
value={liveInputCapture}
|
|
onChange={handleLiveInputChange}
|
|
onKeyPress={handleLiveInputKeyPress}
|
|
onSubmitEditing={submitLiveInput}
|
|
placeholder=""
|
|
showSoftInputOnFocus
|
|
autoCapitalize="none"
|
|
autoCorrect={false}
|
|
spellCheck={false}
|
|
smartInsertDelete={false}
|
|
// Why: iOS textContentType overrides autoComplete and can narrow the keyboard; keep IME switching available.
|
|
autoComplete="off"
|
|
keyboardType={getTerminalLiveInputKeyboardType(hostOs())}
|
|
returnKeyType="default"
|
|
blurOnSubmit={false}
|
|
editable={canSend}
|
|
importantForAutofill="no"
|
|
/>
|
|
</View>
|
|
) : (
|
|
<View style={styles.inputBar}>
|
|
<TextInput
|
|
ref={bindCommandField}
|
|
// Why: Android caches IME inputType at mount, so toggling autocomplete must remount there; iOS updates in place.
|
|
key={
|
|
hostOs() === 'android'
|
|
? autocompleteEnabled
|
|
? 'cmd-input-ac-on'
|
|
: 'cmd-input-ac-off'
|
|
: 'cmd-input'
|
|
}
|
|
style={styles.textInput}
|
|
value={bufferedTerminalDraftState.input}
|
|
// Why: iOS kills active dictation/IME if JS writes a value differing from native text; store raw, normalize at send.
|
|
onChangeText={bufferedTerminalDraftState.setInput}
|
|
placeholder="Type a command…"
|
|
placeholderTextColor={colors.textMuted}
|
|
autoCapitalize="none"
|
|
autoCorrect={autocompleteEnabled}
|
|
spellCheck={autocompleteEnabled}
|
|
smartInsertDelete={false}
|
|
// Why: not autofill content, but keyboard must stay default so non-Latin IMEs remain selectable.
|
|
autoComplete="off"
|
|
keyboardType={getTerminalCommandKeyboardType(hostOs(), autocompleteEnabled)}
|
|
returnKeyType="send"
|
|
blurOnSubmit={false}
|
|
// Why: composing is local — an outage must not lock the field or discard typed text (#6713).
|
|
editable={canCompose}
|
|
onSubmitEditing={() => void handleSend()}
|
|
/>
|
|
<MobileTerminalInputActions
|
|
canSend={canSend}
|
|
isAttaching={isAttaching}
|
|
dictation={dictation}
|
|
dictationMode={dictationMode}
|
|
dictationEnabled={dictationEnabled}
|
|
buttonStyle={styles.dictationButton}
|
|
activeButtonStyle={styles.dictationButtonActive}
|
|
disabledButtonStyle={styles.sendButtonDisabled}
|
|
onAttachImage={() => void attachImage('library')}
|
|
onAttachFile={() => void attachImage('files')}
|
|
onDictationToggle={handleDictationToggle}
|
|
onDictationPressIn={handleDictationPressIn}
|
|
onDictationPressOut={handleDictationPressOut}
|
|
onDictationCancel={cancelDictation}
|
|
/>
|
|
<Pressable
|
|
style={[styles.sendButton, !canSend && styles.sendButtonDisabled]}
|
|
disabled={!canSend}
|
|
onPress={() => void handleSend()}
|
|
accessibilityLabel="Send command"
|
|
>
|
|
<ArrowUp size={18} color={colors.textSecondary} strokeWidth={2.5} />
|
|
</Pressable>
|
|
</View>
|
|
)}
|
|
</View>
|
|
)
|
|
)
|
|
}
|