;
-}) {
- const [command, setCommand] = useState('');
-
- async function handleExecute() {
- if (!command.trim()) return;
- await props.executeCommand(command);
- setCommand('');
- }
-
- return (
-
-
-
-
- Execute
-
-
-
- );
-}
diff --git a/packages/react-native-xtermjs-webview-internal/index.html b/packages/react-native-xtermjs-webview-internal/index.html
index a7be769..6f1ec3b 100644
--- a/packages/react-native-xtermjs-webview-internal/index.html
+++ b/packages/react-native-xtermjs-webview-internal/index.html
@@ -1,9 +1,9 @@
-
+
-
+
{
window.ReactNativeWebView?.postMessage?.(arg);
};
setTimeout(() => {
- postMessage('DEBUG: set timeout');
-}, 1000);
+ postMessage('initialized');
+}, 10);
+
+terminal.onData((data) => {
+ const base64Data = Base64.encode(data);
+ postMessage(base64Data);
+});
function terminalWriteBase64(base64Data: string) {
try {
- postMessage(`DEBUG: terminalWriteBase64 ${base64Data}`);
- const data = new Uint8Array(Buffer.from(base64Data, 'base64'));
- postMessage(`DEBUG: terminalWriteBase64 decoded ${decoder.decode(data)}`);
-
+ const data = Base64.toUint8Array(base64Data);
terminal.write(data);
} catch (e) {
postMessage(`DEBUG: terminalWriteBase64 error ${e}`);
diff --git a/packages/react-native-xtermjs-webview-internal/src/vite-env.d.ts b/packages/react-native-xtermjs-webview-internal/src/vite-env.d.ts
index 4e37827..065b340 100644
--- a/packages/react-native-xtermjs-webview-internal/src/vite-env.d.ts
+++ b/packages/react-native-xtermjs-webview-internal/src/vite-env.d.ts
@@ -2,6 +2,7 @@
interface Window {
terminal?: Terminal;
+ fitAddon?: FitAddon;
terminalWriteBase64?: (data: string) => void;
ReactNativeWebView?: {
postMessage?: (data: string) => void;
diff --git a/packages/react-native-xtermjs-webview/src/index.tsx b/packages/react-native-xtermjs-webview/src/index.tsx
index f2e9153..da9cd66 100644
--- a/packages/react-native-xtermjs-webview/src/index.tsx
+++ b/packages/react-native-xtermjs-webview/src/index.tsx
@@ -8,13 +8,19 @@ type StrictOmit = Omit;
export type XtermWebViewHandle = {
write: (data: Uint8Array) => void;
};
-const decoder = new TextDecoder('utf-8');
export function XtermJsWebView({
ref,
+ onMessage,
...props
-}: StrictOmit, 'source' | 'originWhitelist'> & {
+}: StrictOmit<
+ ComponentProps,
+ 'source' | 'originWhitelist' | 'onMessage'
+> & {
ref: React.RefObject;
+ onMessage?: (
+ data: { type: 'data'; data: Uint8Array } | { type: 'initialized' },
+ ) => void;
}) {
const webViewRef = useRef(null);
@@ -22,17 +28,8 @@ export function XtermJsWebView({
return {
write: (data) => {
const base64Data = Base64.fromUint8Array(data);
- console.log('writing rn side', {
- base64Data,
- dataLength: data.length,
- });
-
- console.log(
- 'try to decode',
- decoder.decode(Base64.toUint8Array(base64Data)),
- );
webViewRef.current?.injectJavaScript(`
- window?.terminalWriteBase64('${base64Data}');
+ window?.terminalWriteBase64?.('${base64Data}');
`);
},
};
@@ -43,6 +40,15 @@ export function XtermJsWebView({
ref={webViewRef}
originWhitelist={['*']}
source={{ html: htmlString }}
+ onMessage={(event) => {
+ const message = event.nativeEvent.data;
+ if (message === 'initialized') {
+ onMessage?.({ type: 'initialized' });
+ return;
+ }
+ const data = Base64.toUint8Array(message);
+ onMessage?.({ type: 'data', data });
+ }}
{...props}
/>
);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index fa308fa..641b396 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -130,6 +130,9 @@ importers:
expo-system-ui:
specifier: ~6.0.7
version: 6.0.7(expo@54.0.8)(react-native-web@0.21.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.3)(@react-native-community/cli@20.0.2(typescript@5.9.2))(@types/react@19.1.12)(react@19.1.0))
+ p-queue:
+ specifier: ^8.1.1
+ version: 8.1.1
react:
specifier: 19.1.0
version: 19.1.0
@@ -385,9 +388,15 @@ importers:
packages/react-native-xtermjs-webview-internal:
dependencies:
+ '@xterm/addon-fit':
+ specifier: ^0.10.0
+ version: 0.10.0(@xterm/xterm@5.5.0)
'@xterm/xterm':
specifier: ^5.5.0
version: 5.5.0
+ js-base64:
+ specifier: ^3.7.8
+ version: 3.7.8
react:
specifier: 19.1.0
version: 19.1.0
@@ -3512,6 +3521,11 @@ packages:
resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==}
engines: {node: '>=10.0.0'}
+ '@xterm/addon-fit@0.10.0':
+ resolution: {integrity: sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==}
+ peerDependencies:
+ '@xterm/xterm': ^5.0.0
+
'@xterm/xterm@5.5.0':
resolution: {integrity: sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==}
@@ -13028,6 +13042,10 @@ snapshots:
'@xmldom/xmldom@0.8.11': {}
+ '@xterm/addon-fit@0.10.0(@xterm/xterm@5.5.0)':
+ dependencies:
+ '@xterm/xterm': 5.5.0
+
'@xterm/xterm@5.5.0': {}
abbrev@3.0.1: {}