From 58ce969fcb49c2adf4c30585b6569b658d3c9bb2 Mon Sep 17 00:00:00 2001 From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com> Date: Thu, 11 Jun 2026 15:53:56 -0700 Subject: [PATCH] fix(mobile): preserve repeated iOS terminal hyphens (#5222) Co-authored-by: Orca --- mobile/app.json | 2 +- mobile/app/h/[hostId]/session/[worktreeId].tsx | 5 ++++- .../terminal-text-input-normalization.test.ts | 6 ++++++ .../terminal/terminal-text-input-normalization.ts | 15 +++++++++++++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/mobile/app.json b/mobile/app.json index b6c8cf3a850..4f034020c41 100644 --- a/mobile/app.json +++ b/mobile/app.json @@ -16,7 +16,7 @@ "ios": { "supportsTablet": true, "bundleIdentifier": "com.stably.orca.mobile", - "buildNumber": "1", + "buildNumber": "2", "infoPlist": { "NSLocalNetworkUsageDescription": "Orca connects to the desktop app on your local network.", "NSMicrophoneUsageDescription": "Allow Orca to record voice dictation and transcribe it on your paired desktop.", diff --git a/mobile/app/h/[hostId]/session/[worktreeId].tsx b/mobile/app/h/[hostId]/session/[worktreeId].tsx index a1671496c72..9046fcbf0c3 100644 --- a/mobile/app/h/[hostId]/session/[worktreeId].tsx +++ b/mobile/app/h/[hostId]/session/[worktreeId].tsx @@ -4296,13 +4296,16 @@ export default function SessionScreen() { setInput(normalizeTerminalTextInput(text))} + onChangeText={(text) => + setInput((previousText) => normalizeTerminalTextInput(text, previousText)) + } placeholder="Type a command…" placeholderTextColor={colors.textMuted} autoCapitalize="none" autoCorrect={false} spellCheck={false} smartInsertDelete={false} + keyboardType={Platform.OS === 'ios' ? 'ascii-capable' : 'visible-password'} returnKeyType="send" editable={canSend} onSubmitEditing={() => void handleSend()} diff --git a/mobile/src/terminal/terminal-text-input-normalization.test.ts b/mobile/src/terminal/terminal-text-input-normalization.test.ts index c5213013e31..29e15ea321b 100644 --- a/mobile/src/terminal/terminal-text-input-normalization.test.ts +++ b/mobile/src/terminal/terminal-text-input-normalization.test.ts @@ -11,4 +11,10 @@ describe('normalizeTerminalTextInput', () => { it('keeps ASCII hyphens unchanged', () => { expect(normalizeTerminalTextInput('git checkout -- file')).toBe('git checkout -- file') }) + + it('preserves longer trailing hyphen runs when iOS re-collapses the controlled value', () => { + expect(normalizeTerminalTextInput('—', '--')).toBe('---') + expect(normalizeTerminalTextInput('—', '---')).toBe('----') + expect(normalizeTerminalTextInput('git checkout —', 'git checkout --')).toBe('git checkout ---') + }) }) diff --git a/mobile/src/terminal/terminal-text-input-normalization.ts b/mobile/src/terminal/terminal-text-input-normalization.ts index d669187139b..70500421b3b 100644 --- a/mobile/src/terminal/terminal-text-input-normalization.ts +++ b/mobile/src/terminal/terminal-text-input-normalization.ts @@ -1,7 +1,18 @@ // Why: iOS smart punctuation can rewrite two ASCII hyphens into a single // Unicode dash before React Native delivers terminal text input. const IOS_SMART_DASH_REPLACEMENT_PATTERN = /[\u2013\u2014]/g +const IOS_SMART_DASH_REPLACEMENT_TEST = /[\u2013\u2014]/ -export function normalizeTerminalTextInput(text: string): string { - return text.replace(IOS_SMART_DASH_REPLACEMENT_PATTERN, '--') +export function normalizeTerminalTextInput(text: string, previousText = ''): string { + const normalizedText = text.replace(IOS_SMART_DASH_REPLACEMENT_PATTERN, '--') + const previousTrailingHyphens = /-+$/.exec(previousText)?.[0] ?? '' + const previousPrefix = previousText.slice(0, previousText.length - previousTrailingHyphens.length) + const collapsedPreviousHyphenRun = + previousTrailingHyphens.length >= 2 && + IOS_SMART_DASH_REPLACEMENT_TEST.test(text) && + (text === `${previousPrefix}\u2013` || text === `${previousPrefix}\u2014`) + if (collapsedPreviousHyphenRun) { + return `${previousText}-` + } + return normalizedText }