feat(demo): add UI for manually adding websocket backends

This commit is contained in:
Simon Chan 2021-12-12 22:53:18 +08:00
parent 3492e3bf71
commit 2e38ec5ce3
27 changed files with 1360 additions and 761 deletions

View file

@ -0,0 +1,111 @@
import { AdbBackend } from '@yume-chan/adb';
import { EventEmitter } from '@yume-chan/event';
const Utf8Encoder = new TextEncoder();
const Utf8Decoder = new TextDecoder();
declare global {
interface TCPSocket {
close(): Promise<void>;
readonly remoteAddress: string;
readonly remotePort: number;
readonly readable: ReadableStream;
readonly writable: WritableStream;
}
interface SocketOptions {
localAddress?: string | undefined;
localPort?: number | undefined;
remoteAddress: string;
remotePort: number;
sendBufferSize?: number;
receiveBufferSize?: number;
keepAlive?: number;
noDelay?: boolean;
}
interface Navigator {
openTCPSocket(options?: SocketOptions): Promise<TCPSocket>;
}
}
export function encodeUtf8(input: string): ArrayBuffer {
return Utf8Encoder.encode(input).buffer;
}
export function decodeUtf8(buffer: ArrayBuffer): string {
return Utf8Decoder.decode(buffer);
}
export default class AdbDirectSocketsBackend implements AdbBackend {
public static isSupported(): boolean {
return typeof window !== 'undefined' && !!window.navigator?.openTCPSocket;
}
public readonly serial: string;
public readonly address: string;
public readonly port: number;
public name: string | undefined;
private socket: TCPSocket | undefined;
private reader: ReadableStreamDefaultReader<ArrayBuffer> | undefined;
private writer: WritableStreamDefaultWriter<ArrayBuffer> | undefined;
private _connected = false;
public get connected() { return this._connected; }
private readonly disconnectEvent = new EventEmitter<void>();
public readonly onDisconnected = this.disconnectEvent.event;
public constructor(address: string, port: number = 5555, name?: string) {
this.address = address;
this.port = port;
this.serial = `${address}:${port}`;
this.name = name;
}
public async connect() {
const socket = await navigator.openTCPSocket({
remoteAddress: this.address,
remotePort: this.port,
noDelay: true,
});
this.socket = socket;
this.reader = this.socket.readable.getReader();
this.writer = this.socket.writable.getWriter();
this._connected = true;
}
public encodeUtf8(input: string): ArrayBuffer {
return encodeUtf8(input);
}
public decodeUtf8(buffer: ArrayBuffer): string {
return decodeUtf8(buffer);
}
public write(buffer: ArrayBuffer): Promise<void> {
return this.writer!.write(buffer);
}
public async read(length: number): Promise<ArrayBuffer> {
const result = await this.reader!.read();
if (result.value) {
return result.value;
}
throw new Error('Stream ended');
}
public dispose(): void | Promise<void> {
this.socket?.close();
}
}