mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 10:08:13 +00:00
Moves ~970 strings in session screens, the terminal, agent chat (including the copy mobile used to render straight from shared English records), the browser pane and the file explorer to the translation API, with all ten translations. - Chat tool-run sentences, task lists, receipts, notices and turn status take translated words; the shared sentence joiner accepts an optional continuation so German nouns and Turkish casing survive mid-sentence (desktop unchanged) - "Used the browser" vs "… 21 times" and resolved PR comment headers use explicit keys instead of plural rules, which would drop the count for Russian 21, 31, … - Action sheet rows carry stable ids instead of being keyed by translated labels - Rename inputs keep the raw title rather than a translated placeholder Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
112 lines
4.0 KiB
TypeScript
112 lines
4.0 KiB
TypeScript
import { useRef, useCallback, useState, forwardRef, useImperativeHandle } from 'react'
|
||
import { Platform, View } from 'react-native'
|
||
import { WebView, type WebViewMessageEvent } from 'react-native-webview'
|
||
import { useMobileTranslation } from '../i18n/use-mobile-translation'
|
||
import type { TerminalWebViewHandle, TerminalWebViewProps } from './terminal-webview-contract'
|
||
import { TerminalWebViewEngineErrorOverlay } from './terminal-webview-engine-error-state'
|
||
import { TERMINAL_WEBVIEW_FRAME_STYLES } from './terminal-webview-frame-styles'
|
||
import { xtermWebViewSource } from './terminal-webview-html'
|
||
import type { TerminalWebViewCommand } from './terminal-webview-messages'
|
||
import { useTerminalWebViewController } from './use-terminal-webview-controller'
|
||
|
||
type Props = TerminalWebViewProps
|
||
|
||
export type { TerminalWebViewHandle } from './terminal-webview-contract'
|
||
|
||
export const TerminalWebView = forwardRef<TerminalWebViewHandle, Props>(
|
||
function TerminalWebView(props, ref) {
|
||
const t = useMobileTranslation()
|
||
const webViewRef = useRef<WebView>(null)
|
||
|
||
const post = useCallback((command: TerminalWebViewCommand & { id: number }) => {
|
||
webViewRef.current?.postMessage(JSON.stringify(command))
|
||
}, [])
|
||
|
||
const {
|
||
clearEngineError,
|
||
engineError,
|
||
handle,
|
||
receive,
|
||
reportNativeEngineError,
|
||
resetReadiness
|
||
} = useTerminalWebViewController(props, {
|
||
post,
|
||
// iOS can preserve the native view while discarding its JS/backing-store state.
|
||
pingsOnForegroundRecovery: () => Platform.OS === 'ios'
|
||
})
|
||
|
||
useImperativeHandle(ref, () => handle, [handle])
|
||
// Seed scale in page source before document startup; Android injected scripts may run too late.
|
||
const [source] = useState(() =>
|
||
xtermWebViewSource({ textScale: props.textScale ?? 1, shown: props.shownAtMount ?? true })
|
||
)
|
||
|
||
const handleMessage = useCallback(
|
||
(event: WebViewMessageEvent) => {
|
||
let msg: Record<string, unknown>
|
||
try {
|
||
msg = JSON.parse(event.nativeEvent.data) as Record<string, unknown>
|
||
} catch {
|
||
return
|
||
}
|
||
receive(msg)
|
||
},
|
||
[receive]
|
||
)
|
||
|
||
const handleReload = useCallback(() => {
|
||
clearEngineError()
|
||
webViewRef.current?.reload()
|
||
}, [clearEngineError])
|
||
|
||
const handleContentProcessDidTerminate = useCallback(() => {
|
||
// Content-process recovery must discard dead-document commands and prove new readiness before replay.
|
||
resetReadiness()
|
||
clearEngineError()
|
||
webViewRef.current?.reload()
|
||
}, [clearEngineError, resetReadiness])
|
||
|
||
return (
|
||
<View style={[TERMINAL_WEBVIEW_FRAME_STYLES.container, props.style]}>
|
||
<WebView
|
||
ref={webViewRef}
|
||
source={source}
|
||
style={TERMINAL_WEBVIEW_FRAME_STYLES.webview}
|
||
originWhitelist={['*']}
|
||
javaScriptEnabled
|
||
scrollEnabled={false}
|
||
// Prevent Android parent gestures from intercepting drags before xterm sees them.
|
||
nestedScrollEnabled
|
||
scalesPageToFit={false}
|
||
// Fix Android textZoom at 100 so OS font scaling cannot exceed xterm’s canvas-measured grid.
|
||
textZoom={100}
|
||
onLoadStart={resetReadiness}
|
||
onMessage={handleMessage}
|
||
onError={(event) =>
|
||
reportNativeEngineError(
|
||
t('terminal.webView.loadFailed', 'Terminal WebView load failed'),
|
||
event
|
||
)
|
||
}
|
||
onHttpError={(event) =>
|
||
reportNativeEngineError(
|
||
t('terminal.webView.httpError', 'Terminal WebView HTTP error'),
|
||
event
|
||
)
|
||
}
|
||
onRenderProcessGone={(event) =>
|
||
reportNativeEngineError(
|
||
t('terminal.webView.renderProcessEnded', 'Terminal WebView render process ended'),
|
||
event
|
||
)
|
||
}
|
||
onContentProcessDidTerminate={handleContentProcessDidTerminate}
|
||
/>
|
||
{engineError ? (
|
||
<TerminalWebViewEngineErrorOverlay message={engineError} onReload={handleReload} />
|
||
) : null}
|
||
</View>
|
||
)
|
||
}
|
||
)
|