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

View file

@ -1,5 +1,6 @@
import { IComponentAsProps, IconButton, INavButtonProps, mergeStyles, mergeStyleSets, Nav, Stack, StackItem } from "@fluentui/react";
import type { AppProps } from 'next/app';
import Head from "next/head";
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { useCallback, useEffect, useState } from "react";
@ -103,6 +104,10 @@ function App({ Component, pageProps }: AppProps) {
return (
<ErrorDialogProvider>
<Head>
<link rel="manifest" href="/manifest.json" />
</Head>
<Stack verticalFill>
<Stack className={classNames['title-container']} horizontal verticalAlign="center">
<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 { FileIconType } 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 { FileIconType, getFileTypeIconProps } from "@fluentui/react-file-type-icons";
import { useConst } from '@fluentui/react-hooks';
import { AdbSyncEntryResponse, ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, InspectStream, LinuxFileType, ReadableStream, WritableStream } from '@yume-chan/adb';
import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx";
@ -16,6 +14,8 @@ import { CommandBar, NoSsr } from '../components';
import { globalState } from '../state';
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,
* the progress value won't be 100% accurate. But it's usually good enough.
@ -259,16 +259,16 @@ class FileManagerState {
switch (item.type) {
case LinuxFileType.Link:
iconName = getFileTypeIconNameFromExtensionOrType(undefined, FileIconType.linkedFolder);
({ iconName } = getFileTypeIconProps({ type: FileIconType.linkedFolder }));
break;
case LinuxFileType.Directory:
iconName = getFileTypeIconNameFromExtensionOrType(undefined, FileIconType.folder);
({ iconName } = getFileTypeIconProps({ type: FileIconType.folder }));
break;
case LinuxFileType.File:
iconName = getFileTypeIconNameFromExtensionOrType(path.extname(item.name!), undefined);
({ iconName } = getFileTypeIconProps({ extension: path.extname(item.name!) }));
break;
default:
iconName = getFileTypeIconNameFromExtensionOrType('txt', undefined);
({ iconName } = getFileTypeIconProps({ extension: 'txt' }));
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 {
interface TCPSocket {
@ -50,10 +50,29 @@ export default class AdbDirectSocketsBackend implements AdbBackend {
}
public async connect() {
return await navigator.openTCPSocket({
const { readable, writable } = await navigator.openTCPSocket({
remoteAddress: this.host,
remotePort: this.port,
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> {
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>{
@ -249,11 +249,11 @@ export class WrapWritableStream<T, W extends WritableStream<T>, S> extends Writa
},
abort: async (reason) => {
await this.writer.abort(reason);
wrapper.close(this.state);
wrapper.close?.(this.state);
},
close: async () => {
await this.writer.close();
await wrapper.close(this.state);
await wrapper.close?.(this.state);
},
});
}