import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { encodeUtf8, type AdbSubprocessProtocol, type Adb } from '@yume-chan/adb' import { Consumable, WritableStream } from '@yume-chan/stream-extra' import { memo, useCallback, useEffect, useRef, useState } from 'react' import { Terminal } from 'xterm' import { FitAddon } from 'xterm-addon-fit' import 'xterm/css/xterm.css' interface ShellTabProps { adb: Adb | undefined } export const ShellTab: React.FC = memo(({ adb }) => { const [process, setProcess] = useState() const [terminal, setTerminal] = useState() const [reader, setReader] = useState | undefined>() useEffect(() => { if (adb) { console.log('adb is connected') console.log('creating terminal') const terminal: Terminal = new Terminal() terminal.options.cursorBlink = true terminal.options.theme = { background: '#1e1e1e', foreground: '#d4d4d4' } console.log('creating process') const _reader = new WritableStream({ write(chunk) { terminal.write(chunk) } }) adb.subprocess.shell('/data/data/com.termux/files/usr/bin/telnet localhost 45515').then(_process => { _process.stdout.pipeTo(_reader) const writer = _process.stdin.getWriter() terminal.onData(data => { const buffer = encodeUtf8(data) const consumable = new Consumable(buffer) writer.write(consumable) }) setReader(_reader) setProcess(_process) setTerminal(terminal) }) } else { console.log('adb is not connected') if (process) { process?.stdout.cancel() process?.stderr.cancel() process?.stdin.close() process?.kill() } setProcess(undefined) setTerminal(undefined) } }, [adb]) const killProcess = useCallback(() => { console.log('killing shell') console.log(process) if (process && terminal) { terminal.write('exit\n') reader?.close() process.stderr.cancel() process.stdin.close() process.stdout.cancel() process.kill() } }, [process]) return ( Shell Access your device's shell using a terminal emulator
{terminal ? ( ) : (

No Connection ADB

)}
) }) interface ShellTerminalProps { terminal: Terminal } const ShellTerminal: React.FC = ({ terminal }) => { const shellRef = useRef(null) useEffect(() => { console.log(shellRef.current) // check if shellRef is have child remove all if (shellRef.current && shellRef.current.children.length > 0) { for (const child of shellRef.current.children) { shellRef.current.removeChild(child) } } if (terminal && shellRef.current) { const addon = new FitAddon() terminal.loadAddon(addon) terminal.open(shellRef.current) addon.fit() } }, [terminal]) return
}