fix: make direct sockets backend work again

This commit is contained in:
Simon Chan 2022-03-31 13:11:12 +08:00
parent 4f4096444e
commit 4c4580e2d7
No known key found for this signature in database
GPG key ID: 8F75717685A974FB
7 changed files with 348 additions and 299 deletions

View file

@ -10,11 +10,11 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@fluentui/react": "^8.52.3", "@fluentui/react": "^8.63.0",
"@fluentui/react-file-type-icons": "^8.5.9", "@fluentui/react-file-type-icons": "^8.6.6",
"@fluentui/react-hooks": "^8.3.10", "@fluentui/react-hooks": "^8.5.3",
"@fluentui/react-icons": "^2.0.160-beta.11", "@fluentui/react-icons": "^2.0.164-rc.2",
"@griffel/react": "^1.0.0", "@griffel/react": "^1.0.2",
"@yume-chan/adb": "^0.0.10", "@yume-chan/adb": "^0.0.10",
"@yume-chan/adb-backend-direct-sockets": "^0.0.9", "@yume-chan/adb-backend-direct-sockets": "^0.0.9",
"@yume-chan/adb-backend-webusb": "^0.0.10", "@yume-chan/adb-backend-webusb": "^0.0.10",
@ -25,9 +25,9 @@
"@yume-chan/event": "^0.0.10", "@yume-chan/event": "^0.0.10",
"@yume-chan/scrcpy": "^0.0.10", "@yume-chan/scrcpy": "^0.0.10",
"@yume-chan/struct": "^0.0.10", "@yume-chan/struct": "^0.0.10",
"mobx": "^6.3.13", "mobx": "^6.5.0",
"mobx-react-lite": "^3.3.0", "mobx-react-lite": "^3.3.0",
"next": "12.1.0", "next": "12.1.3",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"streamsaver": "^2.0.5", "streamsaver": "^2.0.5",
@ -41,7 +41,7 @@
"@next/mdx": "^11.1.2", "@next/mdx": "^11.1.2",
"@types/react": "17.0.27", "@types/react": "17.0.27",
"eslint": "8.8.0", "eslint": "8.8.0",
"eslint-config-next": "12.1.0", "eslint-config-next": "12.1.3",
"typescript": "next" "typescript": "next"
} }
} }

View file

@ -1,5 +1,6 @@
import { IComponentAsProps, IconButton, INavButtonProps, mergeStyles, mergeStyleSets, Nav, Stack, StackItem } from "@fluentui/react"; import { IComponentAsProps, IconButton, INavButtonProps, mergeStyles, mergeStyleSets, Nav, Stack, StackItem } from "@fluentui/react";
import type { AppProps } from 'next/app'; import type { AppProps } from 'next/app';
import Head from "next/head";
import Link from 'next/link'; import Link from 'next/link';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
@ -103,6 +104,10 @@ function App({ Component, pageProps }: AppProps) {
return ( return (
<ErrorDialogProvider> <ErrorDialogProvider>
<Head>
<link rel="manifest" href="/manifest.json" />
</Head>
<Stack verticalFill> <Stack verticalFill>
<Stack className={classNames['title-container']} horizontal verticalAlign="center"> <Stack className={classNames['title-container']} horizontal verticalAlign="center">
<IconButton <IconButton

View file

@ -1,7 +1,5 @@
import { Breadcrumb, concatStyleSets, ContextualMenu, ContextualMenuItem, DetailsListLayoutMode, Dialog, DirectionalHint, IBreadcrumbItem, IColumn, Icon, IContextualMenuItem, IDetailsHeaderProps, IRenderFunction, Layer, MarqueeSelection, mergeStyleSets, Overlay, ProgressIndicator, Selection, ShimmeredDetailsList, Stack, StackItem } from '@fluentui/react'; import { Breadcrumb, concatStyleSets, ContextualMenu, ContextualMenuItem, DetailsListLayoutMode, Dialog, DirectionalHint, IBreadcrumbItem, IColumn, Icon, IContextualMenuItem, IDetailsHeaderProps, IRenderFunction, Layer, MarqueeSelection, mergeStyleSets, Overlay, ProgressIndicator, Selection, ShimmeredDetailsList, Stack, StackItem } from '@fluentui/react';
import { FileIconType } from "@fluentui/react-file-type-icons"; import { FileIconType, getFileTypeIconProps } from "@fluentui/react-file-type-icons";
import { getFileTypeIconNameFromExtensionOrType } from '@fluentui/react-file-type-icons/lib-commonjs/getFileTypeIconProps';
import { DEFAULT_BASE_URL as FILE_TYPE_ICONS_BASE_URL } from '@fluentui/react-file-type-icons/lib-commonjs/initializeFileTypeIcons';
import { useConst } from '@fluentui/react-hooks'; import { useConst } from '@fluentui/react-hooks';
import { AdbSyncEntryResponse, ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, InspectStream, LinuxFileType, ReadableStream, WritableStream } from '@yume-chan/adb'; import { AdbSyncEntryResponse, ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, InspectStream, LinuxFileType, ReadableStream, WritableStream } from '@yume-chan/adb';
import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx";
@ -16,6 +14,8 @@ import { CommandBar, NoSsr } from '../components';
import { globalState } from '../state'; import { globalState } from '../state';
import { asyncEffect, formatSize, formatSpeed, Icons, pickFile, RouteStackProps } from '../utils'; import { asyncEffect, formatSize, formatSpeed, Icons, pickFile, RouteStackProps } from '../utils';
const FILE_TYPE_ICONS_BASE_URL = "https://spoppe-b.azureedge.net/files/fabric-cdn-prod_20220309.001/assets/item-types/";
/** /**
* Because of internal buffer of upstream/downstream streams, * Because of internal buffer of upstream/downstream streams,
* the progress value won't be 100% accurate. But it's usually good enough. * the progress value won't be 100% accurate. But it's usually good enough.
@ -259,16 +259,16 @@ class FileManagerState {
switch (item.type) { switch (item.type) {
case LinuxFileType.Link: case LinuxFileType.Link:
iconName = getFileTypeIconNameFromExtensionOrType(undefined, FileIconType.linkedFolder); ({ iconName } = getFileTypeIconProps({ type: FileIconType.linkedFolder }));
break; break;
case LinuxFileType.Directory: case LinuxFileType.Directory:
iconName = getFileTypeIconNameFromExtensionOrType(undefined, FileIconType.folder); ({ iconName } = getFileTypeIconProps({ type: FileIconType.folder }));
break; break;
case LinuxFileType.File: case LinuxFileType.File:
iconName = getFileTypeIconNameFromExtensionOrType(path.extname(item.name!), undefined); ({ iconName } = getFileTypeIconProps({ extension: path.extname(item.name!) }));
break; break;
default: default:
iconName = getFileTypeIconNameFromExtensionOrType('txt', undefined); ({ iconName } = getFileTypeIconProps({ extension: 'txt' }));
break; break;
} }

View file

@ -0,0 +1,19 @@
{
"$schema": "https://json.schemastore.org/web-manifest-combined.json",
"background_color": "#ffffff",
"categories": [
"utilities"
],
"description": "ADB in your browser",
"display": "standalone",
"icons": [
{
"src": "favicon.ico"
}
],
"isolated_storage": true,
"name": "WebADB Demo",
"short_name": "WebADB",
"start_url": "/",
"scope": "/"
}

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
import type { AdbBackend, ReadableStream, WritableStream } from '@yume-chan/adb'; import { AdbBackend, ReadableStream, WrapReadableStream, WrapWritableStream, WritableStream } from '@yume-chan/adb';
declare global { declare global {
interface TCPSocket { interface TCPSocket {
@ -50,10 +50,29 @@ export default class AdbDirectSocketsBackend implements AdbBackend {
} }
public async connect() { public async connect() {
return await navigator.openTCPSocket({ const { readable, writable } = await navigator.openTCPSocket({
remoteAddress: this.host, remoteAddress: this.host,
remotePort: this.port, remotePort: this.port,
noDelay: true, noDelay: true,
}); });
// Native streams can't `pipeTo()` or `pipeThrough()` polyfilled streams, so we need to wrap them
return {
readable: new WrapReadableStream<Uint8Array, ReadableStream<Uint8Array>, void>({
async start() {
return {
readable,
state: undefined,
};
}
}),
writable: new WrapWritableStream({
async start() {
return {
writable,
state: undefined,
};
}
}),
};
} }
} }

View file

@ -224,7 +224,7 @@ export class StructSerializeStream<T extends Struct<any, any, any, any>>
export interface WritableStreamWrapper<T, W extends WritableStream<T>, S> { export interface WritableStreamWrapper<T, W extends WritableStream<T>, S> {
start(): Promise<{ writable: W, state: S; }>; start(): Promise<{ writable: W, state: S; }>;
close(state: S): Promise<void>; close?(state: S): Promise<void>;
} }
export class WrapWritableStream<T, W extends WritableStream<T>, S> extends WritableStream<T>{ export class WrapWritableStream<T, W extends WritableStream<T>, S> extends WritableStream<T>{
@ -249,11 +249,11 @@ export class WrapWritableStream<T, W extends WritableStream<T>, S> extends Writa
}, },
abort: async (reason) => { abort: async (reason) => {
await this.writer.abort(reason); await this.writer.abort(reason);
wrapper.close(this.state); wrapper.close?.(this.state);
}, },
close: async () => { close: async () => {
await this.writer.close(); await this.writer.close();
await wrapper.close(this.state); await wrapper.close?.(this.state);
}, },
}); });
} }