feat(sync): support lstat v1

This commit is contained in:
Simon Chan 2020-09-19 05:31:22 +08:00
parent 00485d8760
commit 09ff9dc966
22 changed files with 648 additions and 400 deletions

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
node_modules
lib
node_modules
*.log
tsconfig.tsbuildinfo

View file

@ -15,6 +15,7 @@
"reimplement",
"sendrecv",
"streamsaver",
"struct",
"tcpip",
"uifabric",
"webadb",

View file

@ -136,7 +136,8 @@ export default class AdbWebBackend implements AdbBackend {
await this._device.clearHalt('in', this._inEndpointNumber);
}
return result.data!.buffer;
const { buffer } = result.data!;
return buffer;
} catch (e) {
if (e instanceof Error && e.name === 'NotFoundError') {
this.onDisconnectedEvent.fire();

View file

@ -8,9 +8,6 @@
"DOM"
]
},
"include": [
"src"
],
"references": [
{
"path": "../adb/tsconfig.json"

View file

@ -185,8 +185,6 @@ Supported on devices with `ls_v2` feature.
#### STAT
*(Not Implemented)*
Request server to return the information of a file.
If path is a symbolic link, the returned information is about the link itself.

View file

@ -1,8 +1,7 @@
import { AutoDisposable } from '@yume-chan/event';
import { AdbBackend } from './backend';
import { AdbBufferedStream } from './buffered-stream';
import { AdbStream } from './stream';
import { AutoResetEvent } from './utils';
import { AutoResetEvent, Struct, StructInitType, StructReader } from './utils';
export enum AdbSyncRequestId {
List = 'LIST',
@ -15,74 +14,26 @@ export enum AdbSyncRequestId {
export enum AdbSyncResponseId {
Entry = 'DENT',
Stat = 'STAT',
Done = 'DONE',
Data = 'DATA',
Ok = 'OKAY',
}
export abstract class AdbSyncRequestBase<T extends AdbSyncRequestId = AdbSyncRequestId> {
public readonly id: T;
public constructor(id: T) {
this.id = id;
}
public abstract toBuffer(backend: AdbBackend): ArrayBuffer;
Fail = 'FAIL',
}
export type AdbSyncNumberRequestId =
AdbSyncRequestId.Done;
export class AdbSyncNumberRequest extends AdbSyncRequestBase<AdbSyncNumberRequestId> {
public readonly value: number;
public constructor(id: AdbSyncNumberRequestId, value: number) {
super(id);
this.value = value;
}
public toBuffer(backend: AdbBackend): ArrayBuffer {
const array = new Uint8Array(8);
const idBuffer = backend.encodeUtf8(this.id);
array.set(new Uint8Array(idBuffer));
const view = new DataView(array.buffer);
view.setUint32(4, this.value, true);
return array.buffer;
}
}
export type AdbSyncStringRequestId =
AdbSyncRequestId.List |
AdbSyncRequestId.Send |
AdbSyncRequestId.Stat |
AdbSyncRequestId.Receive;
export class AdbSyncStringRequest extends AdbSyncRequestBase<AdbSyncStringRequestId> {
public value: string;
public constructor(id: AdbSyncStringRequestId, value: string) {
super(id);
this.value = value;
}
public toBuffer(backend: AdbBackend) {
const valueBuffer = backend.encodeUtf8(this.value);
const array = new Uint8Array(8 + valueBuffer.byteLength);
const idBuffer = backend.encodeUtf8(this.id);
array.set(new Uint8Array(idBuffer));
const view = new DataView(array.buffer);
view.setUint32(4, valueBuffer.byteLength, true);
array.set(new Uint8Array(valueBuffer), 8);
return array.buffer;
}
}
const AdbSyncStringRequest =
new Struct(true)
.fixedLengthString('id', 4, undefined as any as AdbSyncStringRequestId)
.lengthPrefixedString('value', 'int32');
// https://github.com/python/cpython/blob/4e581d64b8aff3e2eda99b12f080c877bb78dfca/Lib/stat.py#L36
export enum LinuxFileType {
@ -91,16 +42,51 @@ export enum LinuxFileType {
Link = 0o12,
}
const AdbSyncStatResponseStruct =
new Struct(true)
.int32('mode')
.int32('size')
.int32('lastModifiedTime')
export class AdbSyncStatResponse {
public static readonly size = AdbSyncStatResponseStruct.size;
public static async parse(reader: StructReader): Promise<AdbSyncStatResponse> {
const struct = await AdbSyncStatResponseStruct.parse(reader);
if (struct.mode === 0 && struct.size === 0 && struct.lastModifiedTime === 0) {
throw new Error('lstat failed');
}
return new AdbSyncStatResponse(struct.mode, struct.size, struct.lastModifiedTime);
}
public readonly id = AdbSyncResponseId.Stat;
public readonly type: LinuxFileType;
public readonly mode: number;
public readonly size: number;
public readonly lastModifiedTime: number;
public constructor(mode: number, size: number, lastModifiedTime: number) {
this.type = mode >> 12 as LinuxFileType;
this.mode = mode & 0b00001111_11111111;
this.size = size;
this.lastModifiedTime = lastModifiedTime;
}
}
const AdbSyncEntryResponseStruct =
AdbSyncStatResponseStruct
.lengthPrefixedString('name', 'int32');
export class AdbSyncEntryResponse {
public static async parse(stream: AdbBufferedStream): Promise<AdbSyncEntryResponse> {
const buffer = await stream.read(16);
const view = new DataView(buffer);
const mode = view.getUint32(0, true);
const size = view.getUint32(4, true);
const lastModifiedTime = view.getUint32(8, true);
const nameLength = view.getUint32(12, true);
const name = stream.backend.decodeUtf8(await stream.read(nameLength));
return new AdbSyncEntryResponse(mode, size, lastModifiedTime, name);
public static readonly size = AdbSyncEntryResponseStruct.size;
public static async parse(reader: StructReader): Promise<AdbSyncEntryResponse> {
const struct = await AdbSyncEntryResponseStruct.parse(reader);
return new AdbSyncEntryResponse(struct.mode, struct.size, struct.lastModifiedTime, struct.name);
}
public readonly id = AdbSyncResponseId.Entry;
@ -111,8 +97,6 @@ export class AdbSyncEntryResponse {
public readonly size: number;
public readonly logicalSize: number;
public readonly lastModifiedTime: number;
public readonly name: string;
@ -121,46 +105,57 @@ export class AdbSyncEntryResponse {
this.type = mode >> 12 as LinuxFileType;
this.mode = mode & 0b00001111_11111111;
this.size = size;
this.logicalSize = this.type === LinuxFileType.File ? this.size : 0;
this.lastModifiedTime = lastModifiedTime;
this.name = name;
}
}
export class AdbSyncDataResponse {
public static async parse(stream: AdbBufferedStream): Promise<AdbSyncDataResponse> {
const buffer = await stream.read(4);
const view = new DataView(buffer);
const length = view.getUint32(0, true);
const data = await stream.read(length);
return new AdbSyncDataResponse(data);
}
public readonly id = AdbSyncResponseId.Data;
public readonly data: ArrayBuffer;
public constructor(data: ArrayBuffer) {
this.data = data;
}
}
const AdbSyncDataResponse =
new Struct(true)
.lengthPrefixedBuffer('data', 'int32')
.extra({ id: AdbSyncResponseId.Data } as const);
export class AdbSyncDoneResponse {
public static readonly instance = new AdbSyncDoneResponse();
public readonly id = AdbSyncResponseId.Done;
}
async function parseResponse(stream: AdbBufferedStream) {
const AdbSyncFailResponseStruct =
new Struct(true)
.lengthPrefixedString('message', 'int32');
class AdbSyncFailResponse {
public static async parse(reader: StructReader): Promise<never> {
const struct = await AdbSyncFailResponseStruct.parse(reader);
throw new Error(struct.message);
}
}
async function parseResponse(stream: AdbBufferedStream, size: number) {
// DONE responses' size are always same as the request's normal response.
// For example DONE responses for LIST requests are 16 bytes (same as DENT responses),
// but DONE responses for STAT requests are 12 bytes (same as STAT responses)
// So we need to know responses' size in advance.
const id = stream.backend.decodeUtf8(await stream.read(4)) as AdbSyncResponseId;
const structReader = {
read: stream.read.bind(stream),
decodeUtf8: stream.backend.decodeUtf8.bind(stream.backend),
};
switch (id) {
case AdbSyncResponseId.Entry:
return AdbSyncEntryResponse.parse(stream);
return AdbSyncEntryResponse.parse(structReader);
case AdbSyncResponseId.Stat:
return AdbSyncStatResponse.parse(structReader);
case AdbSyncResponseId.Data:
return AdbSyncDataResponse.parse(stream);
return AdbSyncDataResponse.parse(structReader);
case AdbSyncResponseId.Done:
await stream.read(4);
return new AdbSyncDoneResponse();
await stream.read(size);
return AdbSyncDoneResponse.instance;
case AdbSyncResponseId.Fail:
return AdbSyncFailResponse.parse(structReader);
default:
throw new Error('');
throw new Error('Unexpected response id');
}
}
@ -175,14 +170,29 @@ export class AdbSync extends AutoDisposable {
this.stream = new AdbBufferedStream(stream);
}
public async lstat(path: string) {
await this.sendLock.wait();
try {
await this.write(AdbSyncStringRequest, { id: AdbSyncRequestId.Stat, value: path });
const response = await parseResponse(this.stream, AdbSyncStatResponse.size);
if (response.id !== AdbSyncResponseId.Stat) {
throw new Error('Unexpected response id');
}
return response;
} finally {
this.sendLock.notify();
}
}
public async *iterate(path: string) {
await this.sendLock.wait();
try {
await this.write(new AdbSyncStringRequest(AdbSyncRequestId.List, path));
await this.write(AdbSyncStringRequest, { id: AdbSyncRequestId.List, value: path });
while (true) {
const response = await parseResponse(this.stream);
const response = await parseResponse(this.stream, AdbSyncEntryResponse.size);
switch (response.id) {
case AdbSyncResponseId.Entry:
yield response;
@ -210,9 +220,9 @@ export class AdbSync extends AutoDisposable {
await this.sendLock.wait();
try {
await this.write(new AdbSyncStringRequest(AdbSyncRequestId.Receive, path));
await this.write(AdbSyncStringRequest, { id: AdbSyncRequestId.Receive, value: path });
while (true) {
const response = await parseResponse(this.stream);
const response = await parseResponse(this.stream, AdbSyncDataResponse.size);
switch (response.id) {
case AdbSyncResponseId.Data:
yield response.data;
@ -233,7 +243,7 @@ export class AdbSync extends AutoDisposable {
this.stream.close();
}
private write(request: AdbSyncRequestBase) {
return this.stream.write(request.toBuffer(this.stream.backend));
private write<T extends Struct<unknown, unknown>>(type: T, value: StructInitType<T>) {
return this.stream.write(type.toBuffer(value, this.stream.backend));
}
}

View file

@ -1,3 +1,5 @@
export * from './auto-reset-event';
export * from './base64';
export * from './event-iterator';
export * from './struct';
export { default as Struct } from './struct';

View file

@ -0,0 +1,259 @@
const enum StructFieldType {
Int32,
FixedLengthString,
LengthPrefixedBuffer,
}
interface StructFieldBase {
type: StructFieldType;
name: PropertyKey;
}
interface StructInt32Field extends StructFieldBase {
type: StructFieldType.Int32;
signed: boolean;
}
interface StructFixedLengthStringField extends StructFieldBase {
type: StructFieldType.FixedLengthString;
length: number;
}
interface StructLengthPrefixedBufferField extends StructFieldBase {
type: StructFieldType.LengthPrefixedBuffer;
lengthType: 'int32';
subType: 'buffer' | 'string';
}
type StructField =
StructInt32Field |
StructFixedLengthStringField |
StructLengthPrefixedBufferField;
export interface StructReader {
decodeUtf8(buffer: ArrayBuffer): string;
read(length: number): Promise<ArrayBuffer>;
}
export interface StructWriter {
encodeUtf8(input: string): ArrayBuffer;
}
type KeyOfType<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T];
export type StructValueType<T extends Struct<unknown, unknown>> =
T extends { parse(reader: StructReader): Promise<infer R> } ? R : never;
export type StructInitType<T extends Struct<unknown, unknown>> =
T extends { create(value: infer R): any } ? R : never;
export default class Struct<T, TInit> {
private littleEndian: boolean;
private _size = 0;
public get size() { return this._size; }
private fields: StructField[] = [];
private _extra?: any;
public constructor(littleEndian = false) {
this.littleEndian = littleEndian;
}
private clone(): Struct<any, any> {
const result = new Struct<any, any>(this.littleEndian);
result.fields = this.fields.slice();
result._size = this._size;
result._extra = this._extra;
return result;
}
public int32<K extends PropertyKey>(name: K): Struct<
T & { [KK in K]: number },
T & { [KK in K]: number }
> {
const result = this.clone();
result.fields.push({ type: StructFieldType.Int32, name, signed: true });
result._size += 4;
return result;
}
public uint32<K extends PropertyKey>(name: K): Struct<
T & { [KK in K]: number },
T & { [KK in K]: number }
> {
const result = this.clone();
result.fields.push({ type: StructFieldType.Int32, name, signed: false });
result._size += 4;
return result;
}
public fixedLengthString<K extends PropertyKey, U = string>(
name: K,
length: number,
_type?: U
): Struct<
T & { [KK in K]: U },
T & { [KK in K]: U }
> {
const result = this.clone();
result.fields.push({ type: StructFieldType.FixedLengthString, name, length });
result._size += 4;
return result;
}
public lengthPrefixedBuffer<K extends PropertyKey>(
name: K,
lengthType: 'int32',
): Struct<
T & { [KK in K]: ArrayBuffer },
T & { [KK in K]: ArrayBuffer }
> {
const result = this.clone();
result.fields.push({
type: StructFieldType.LengthPrefixedBuffer,
name,
lengthType,
subType: 'buffer'
});
result._size += 4;
return result;
}
public lengthPrefixedString<K extends PropertyKey, U = string>(
name: K,
lengthType: 'int32',
_type?: U
): Struct<
T & { [KK in K]: U },
T & { [KK in K]: U }
> {
const result = this.clone();
result.fields.push({
type: StructFieldType.LengthPrefixedBuffer,
name,
lengthType,
subType: 'string',
});
result._size += 4;
return result;
}
public extra<U extends object>(value: U): Struct<T & U, T> {
const result = this.clone();
result._extra = { ...result._extra, value };
return result;
}
public create(value: TInit): T {
return { ...value, ...this._extra } as any;
}
public async parse(reader: StructReader): Promise<T> {
const result: any = {};
let buffer: ArrayBuffer;
let view: DataView;
let length: number;
for (const field of this.fields) {
switch (field.type) {
case StructFieldType.Int32:
buffer = await reader.read(4);
view = new DataView(buffer);
if (field.signed) {
result[field.name] = view.getInt32(0, this.littleEndian);
} else {
result[field.name] = view.getUint32(0, this.littleEndian);
}
break;
case StructFieldType.FixedLengthString:
buffer = await reader.read(field.length);
result[field.name] = reader.decodeUtf8(buffer);
break;
case StructFieldType.LengthPrefixedBuffer:
switch (field.lengthType) {
case 'int32':
buffer = await reader.read(4);
view = new DataView(buffer);
length = view.getUint32(0, this.littleEndian);
break;
default:
throw new Error();
}
buffer = await reader.read(length);
switch (field.subType) {
case 'buffer':
result[field.name] = buffer;
break;
case 'string':
result[field.name] = reader.decodeUtf8(buffer);
break;
}
break;
}
}
return { ...result, ...this._extra };
}
public toBuffer(init: TInit, writer: StructWriter): ArrayBuffer {
const value = this.create(init) as any;
let size = this._size;
for (const field of this.fields) {
switch (field.type) {
case StructFieldType.FixedLengthString:
value[field.name] = writer.encodeUtf8(value[field.name]).slice(0, field.length);
break;
case StructFieldType.LengthPrefixedBuffer:
switch (field.subType) {
case 'string':
const buffer = writer.encodeUtf8(value[field.name]);
value[field.name] = buffer;
break;
}
size += value[field.name].byteLength;
break;
}
}
const result = new Uint8Array(size);
const view = new DataView(result.buffer);
let offset = 0;
let buffer: ArrayBuffer;
let length: number;
for (const field of this.fields) {
switch (field.type) {
case StructFieldType.Int32:
if (field.signed) {
view.setInt32(offset, value[field.name], this.littleEndian);
} else {
view.setUint32(offset, value[field.name], this.littleEndian);
}
offset += 4;
break;
case StructFieldType.LengthPrefixedBuffer:
buffer = value[field.name];
length = buffer.byteLength;
view.setUint32(offset, length, this.littleEndian);
offset += 4;
result.set(new Uint8Array(buffer), offset);
offset += buffer.byteLength;
break;
case StructFieldType.FixedLengthString:
buffer = value[field.name];
result.set(new Uint8Array(buffer), offset);
offset += buffer.byteLength;
break;
}
}
return result;
}
}

View file

@ -4,9 +4,6 @@
"outDir": "lib", // /* Redirect output structure to the directory. */
"rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
},
"include": [
"src"
],
"references": [
{
"path": "../event/tsconfig.json"

View file

@ -2,22 +2,16 @@
## Start
In `demo` folder:
```sh
npm start
```
Or in root folder:
From root folder:
```sh
npm run start:demo
```
## Watch changes in `webadb`
From another shell, run in root folder:
From this folder:
```sh
npm run build:watch
npm start
```
Then navigate to `http://localhost:9000`.

View file

@ -13,18 +13,27 @@
}
},
"@fluentui/date-time-utilities": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.8.0.tgz",
"integrity": "sha512-qzlTp3t+PghebJsLK9JwZr91qBRZ/fOml8TQCIjdtsEn4mH6/ciCwir7Fj8iOEkwwTC0iKsEr1jfsITtJKWSmA==",
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.8.1.tgz",
"integrity": "sha512-2FsR7scZ6yS9h7MEUAunpLLYpHp4z7+DVgGlIBlNeL7YD5Vl0msj4pn7zRd1pcGfvoQfkWz3+ju3rBBl4LV4wQ==",
"requires": {
"@uifabric/set-version": "^7.0.22",
"@uifabric/set-version": "^7.0.23",
"tslib": "^1.10.0"
}
},
"@fluentui/dom-utilities": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@fluentui/dom-utilities/-/dom-utilities-1.1.1.tgz",
"integrity": "sha512-w40gi8fzCpwa7U8cONiuu8rszPStkVOL/weDf5pCbYEb1gdaV7MDPSNkgM6IV0Kz+k017noDgK9Fv4ru1Dwz1g==",
"requires": {
"@uifabric/set-version": "^7.0.23",
"tslib": "^1.10.0"
}
},
"@fluentui/keyboard-key": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.2.11.tgz",
"integrity": "sha512-4iG5vNlRD3PrLaMfDTimHNOP1x6V3Dad0fXOwtvBBMsfdySPE9zlY+G+0aqCFcgjymOriFOk0ANZVBpK7XrnTg==",
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.2.12.tgz",
"integrity": "sha512-t3yIbbPKJubb22vQ/FIWwS9vFAzaPYzFxKWPHVWLtxs/P+5yL+LD3B16DRtYreWAdl9CZvEbos58ChLZ0KHwSQ==",
"requires": {
"tslib": "^1.10.0"
}
@ -40,53 +49,53 @@
}
},
"@fluentui/react-focus": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-7.16.0.tgz",
"integrity": "sha512-TwB4Av7ID70ejisDIGkCZGKOxlquSazr6W+9Jv1JQAvsBLuj5XOspFJH4/Igjniw1LeO9QmAvFZeh/XRShiObw==",
"version": "7.16.5",
"resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-7.16.5.tgz",
"integrity": "sha512-FlRqYSzkptXuKvsIiI9m1tf7g5pRcbu9S9rK6c8pHax/kDRsBuDRW2OajxjVYR36B6IyAgYjylWdk6zBJI5oSQ==",
"requires": {
"@fluentui/keyboard-key": "^0.2.11",
"@uifabric/merge-styles": "^7.18.0",
"@uifabric/set-version": "^7.0.22",
"@uifabric/styling": "^7.16.0",
"@uifabric/utilities": "^7.31.0",
"@fluentui/keyboard-key": "^0.2.12",
"@uifabric/merge-styles": "^7.19.1",
"@uifabric/set-version": "^7.0.23",
"@uifabric/styling": "^7.16.5",
"@uifabric/utilities": "^7.32.2",
"tslib": "^1.10.0"
}
},
"@fluentui/react-icons": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-0.3.0.tgz",
"integrity": "sha512-QDrIhLUpkxM5q5bFE4pkweJJsfaNswdfDoc+X6cmr22Dii+anDFTpOcePEJiTtILxdlEmH0968OcZ4BGZF/joQ==",
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-0.3.4.tgz",
"integrity": "sha512-/6xyGL7EQVCn9TP1eV+VjKS0HuC7WGZHs0t604E40LEE1HCIbXx7Jm1KDlMqP36n1W8XVDgyEZlffTmEOVGRkg==",
"requires": {
"@microsoft/load-themed-styles": "^1.10.26",
"@uifabric/set-version": "^7.0.22",
"@uifabric/utilities": "^7.31.0",
"@uifabric/set-version": "^7.0.23",
"@uifabric/utilities": "^7.32.2",
"tslib": "^1.10.0"
}
},
"@fluentui/react-window-provider": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-0.3.0.tgz",
"integrity": "sha512-zHeH1PAmoFB3OkgU8f51E3oGHrL/CjuvdPBlb1SGpByUGNihAgH/CwvJohV9z0yPDkq+chfNUmxWA/oDVpbh6Q==",
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-0.3.3.tgz",
"integrity": "sha512-MVPf2hqOQ17LAZsuvGcr3oOHksAskUm+fCYdXFhbVoAgsCDVTIuH6i8XgHFd6YjBtzjZmI4+k/3NTQfDqBX8EQ==",
"requires": {
"@uifabric/set-version": "^7.0.22",
"@uifabric/set-version": "^7.0.23",
"tslib": "^1.10.0"
}
},
"@fluentui/theme": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-0.2.0.tgz",
"integrity": "sha512-L5OwqymTdxTVwBa3ifkQLF1A3YU6WMkMTk6PFIMfOonjt8LJ3yMMqZgz+KQR3sF/tzgy4wzW4oBmrxtTfJS2EQ==",
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-0.3.2.tgz",
"integrity": "sha512-Yt4VK2NKTc+Sao0+ZguXiQ0ZpN74h+7c+7YAyxaao2R/nwSHSnmH42VVlzBN+aL5kYDrbQ4P9Z8zPIwKEZ1u3A==",
"requires": {
"@uifabric/merge-styles": "^7.18.0",
"@uifabric/set-version": "^7.0.22",
"@uifabric/utilities": "^7.31.0",
"@uifabric/merge-styles": "^7.19.1",
"@uifabric/set-version": "^7.0.23",
"@uifabric/utilities": "^7.32.2",
"tslib": "^1.10.0"
}
},
"@microsoft/load-themed-styles": {
"version": "1.10.86",
"resolved": "https://registry.npmjs.org/@microsoft/load-themed-styles/-/load-themed-styles-1.10.86.tgz",
"integrity": "sha512-4C6EelO32Li6qVGO+Bna3glNSyT9iDcatYinvFyGLoCboGyMBdBVgyJC2uyF+31n3++Q7Htt6CAZmdd8JxKjjQ=="
"version": "1.10.93",
"resolved": "https://registry.npmjs.org/@microsoft/load-themed-styles/-/load-themed-styles-1.10.93.tgz",
"integrity": "sha512-iziiQyDJmyP8QE33hYjuVsj18RvtzRMdON1QLDkJSrs9xisXWgEjK8U12UsEkBYpYXzxPxqq5+X+fK8Vs6g8vQ=="
},
"@nodelib/fs.scandir": {
"version": "2.1.3",
@ -140,9 +149,9 @@
}
},
"@types/history": {
"version": "4.7.7",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.7.tgz",
"integrity": "sha512-2xtoL22/3Mv6a70i4+4RB7VgbDDORoWwjcqeNysojZA0R7NK17RbY5Gof/2QiFfJgX+KkWghbwJ+d/2SB8Ndzg==",
"version": "4.7.8",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz",
"integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==",
"dev": true
},
"@types/html-minifier-terser": {
@ -164,9 +173,9 @@
"dev": true
},
"@types/node": {
"version": "14.6.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.4.tgz",
"integrity": "sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==",
"version": "14.11.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.1.tgz",
"integrity": "sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw==",
"dev": true
},
"@types/prop-types": {
@ -280,33 +289,33 @@
}
},
"@uifabric/foundation": {
"version": "7.9.0",
"resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.9.0.tgz",
"integrity": "sha512-4gdPwx0HV59aWvPKIw6yIje60CYwJZmTJsdLRXqh8Np1tWp2EsbA8U/IHQL1V91rEN0DlQhASqCDFhfQoD1jUw==",
"version": "7.9.5",
"resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.9.5.tgz",
"integrity": "sha512-r4KjYJAjSRgBGqeJXGKogYgzJS55/zcxmU3Gsps0BCMP8SCn55KZ31KiMYmjxoNnJAlGnhIq+h5zUEVRhpHN/Q==",
"requires": {
"@uifabric/merge-styles": "^7.18.0",
"@uifabric/set-version": "^7.0.22",
"@uifabric/styling": "^7.16.0",
"@uifabric/utilities": "^7.31.0",
"@uifabric/merge-styles": "^7.19.1",
"@uifabric/set-version": "^7.0.23",
"@uifabric/styling": "^7.16.5",
"@uifabric/utilities": "^7.32.2",
"tslib": "^1.10.0"
}
},
"@uifabric/icons": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.5.0.tgz",
"integrity": "sha512-RINA9VkajlCnlwEBbqiwLBaaGn38Bf9UvjOuwrrja4B9lclLeQzZuGrG/kp7CnDtIO+LC19OYl/7E3jW7yIihA==",
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.5.5.tgz",
"integrity": "sha512-lErlirRm3D4Lv63oxa/JFx+JUyHRX/pqNoolLQKlPKqNauHFcrcEEDRuZdtfSOJtF/1a09ZvIyirij3XwZjNBw==",
"requires": {
"@uifabric/set-version": "^7.0.22",
"@uifabric/styling": "^7.16.0",
"@uifabric/set-version": "^7.0.23",
"@uifabric/styling": "^7.16.5",
"tslib": "^1.10.0"
}
},
"@uifabric/merge-styles": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz",
"integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==",
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.19.1.tgz",
"integrity": "sha512-yqUwmk62Kgu216QNPE9vOfS3h0kiSbTvoqM5QcZi+IzpqsBOlzZx3A9Er9UiDaqHRd5lsYF5pO/jeUULmBWF/A==",
"requires": {
"@uifabric/set-version": "^7.0.22",
"@uifabric/set-version": "^7.0.23",
"tslib": "^1.10.0"
}
},
@ -322,33 +331,34 @@
}
},
"@uifabric/set-version": {
"version": "7.0.22",
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
"version": "7.0.23",
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.23.tgz",
"integrity": "sha512-9E+YKtnH2kyMKnK9XZZsqyM8OCxEJIIfxtaThTlQpYOzrWAGJxQADFbZ7+Usi0U2xHnWNPFROjq+B9ocEzhqMA==",
"requires": {
"tslib": "^1.10.0"
}
},
"@uifabric/styling": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.16.0.tgz",
"integrity": "sha512-yO404ws8Wl4fjBwG4T58TFJjeU/K+SpWJ4w+WeNMDlJcYe4zXaWn2lbOJtKtQiMl324RAEjFSOuNkXzPb0uOGQ==",
"version": "7.16.5",
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.16.5.tgz",
"integrity": "sha512-mJcPam0ivtGfC8NEUQgpJFs8uG4ZRY1ml1RY9rOY6py5pTEno15xaq11yfRxv3ACxkuK9D9qZM23x0q8sWsCdg==",
"requires": {
"@fluentui/theme": "^0.2.0",
"@fluentui/theme": "^0.3.2",
"@microsoft/load-themed-styles": "^1.10.26",
"@uifabric/merge-styles": "^7.18.0",
"@uifabric/set-version": "^7.0.22",
"@uifabric/utilities": "^7.31.0",
"@uifabric/merge-styles": "^7.19.1",
"@uifabric/set-version": "^7.0.23",
"@uifabric/utilities": "^7.32.2",
"tslib": "^1.10.0"
}
},
"@uifabric/utilities": {
"version": "7.31.0",
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz",
"integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==",
"version": "7.32.2",
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.32.2.tgz",
"integrity": "sha512-x47zJIjezkfed17EfNRTr9wP6hHR+i0pBbr3eQYetpcVsAXcbZsd+D6divwy+kQOsdLQ8TozWqoVk3ySe6RfSw==",
"requires": {
"@uifabric/merge-styles": "^7.18.0",
"@uifabric/set-version": "^7.0.22",
"@fluentui/dom-utilities": "^1.1.1",
"@uifabric/merge-styles": "^7.19.1",
"@uifabric/set-version": "^7.0.23",
"prop-types": "^15.7.2",
"tslib": "^1.10.0"
}
@ -541,9 +551,9 @@
"dev": true
},
"abab": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz",
"integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==",
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
"integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==",
"dev": true
},
"accepts": {
@ -579,9 +589,9 @@
}
},
"ajv": {
"version": "6.12.4",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
"integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
"version": "6.12.5",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
"integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@ -1951,9 +1961,9 @@
},
"dependencies": {
"domelementtype": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
"integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz",
"integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==",
"dev": true
}
}
@ -3668,9 +3678,9 @@
"dev": true
},
"is-callable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
"integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz",
"integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==",
"dev": true
},
"is-data-descriptor": {
@ -3745,6 +3755,12 @@
"is-extglob": "^2.1.1"
}
},
"is-negative-zero": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
"integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=",
"dev": true
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@ -4279,12 +4295,6 @@
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"dev": true
},
"moment": {
"version": "2.28.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.28.0.tgz",
"integrity": "sha512-Z5KOjYmnHyd/ukynmFd/WwyXHd7L4J9vTI/nn5Ap9AVUgaAE15VvQ9MOGmJJygEUklupqIrFnor/tjTwRU+tQw==",
"dev": true
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -4380,9 +4390,9 @@
}
},
"node-forge": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
"integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==",
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
"dev": true
},
"node-libs-browser": {
@ -4566,15 +4576,37 @@
}
},
"object.assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz",
"integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==",
"dev": true,
"requires": {
"define-properties": "^1.1.2",
"define-properties": "^1.1.3",
"es-abstract": "^1.18.0-next.0",
"has-symbols": "^1.0.1",
"object-keys": "^1.1.1"
},
"dependencies": {
"es-abstract": {
"version": "1.18.0-next.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz",
"integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==",
"dev": true,
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has-symbols": "^1.0.0",
"object-keys": "^1.0.11"
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.0",
"is-negative-zero": "^2.0.0",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.0",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
}
},
"object.getownpropertydescriptors": {
@ -4603,34 +4635,34 @@
"dev": true
},
"office-ui-fabric-react": {
"version": "7.137.1",
"resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.137.1.tgz",
"integrity": "sha512-6m1M9m5psaJqhWwroVp1L0G8q66scLMsQRi+gQ/fY3f75ipGSABGeQ86d4P0ilKaYcLVYIzosocPIZKLbBVpnQ==",
"version": "7.138.0",
"resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.138.0.tgz",
"integrity": "sha512-HW4ugd+x7Jg96yBWxmUNMfkTS0U8RMwf5mGsHBAvW9s5l1ektjTjKnb5beHxNrddXKqcjz9ZThdTk/Gxds0jig==",
"requires": {
"@fluentui/date-time-utilities": "^7.8.0",
"@fluentui/react-focus": "^7.16.0",
"@fluentui/react-icons": "^0.3.0",
"@fluentui/react-window-provider": "^0.3.0",
"@fluentui/date-time-utilities": "^7.8.1",
"@fluentui/react-focus": "^7.16.5",
"@fluentui/react-icons": "^0.3.4",
"@fluentui/react-window-provider": "^0.3.3",
"@microsoft/load-themed-styles": "^1.10.26",
"@uifabric/foundation": "^7.9.0",
"@uifabric/icons": "^7.5.0",
"@uifabric/merge-styles": "^7.18.0",
"@uifabric/react-hooks": "^7.13.0",
"@uifabric/set-version": "^7.0.22",
"@uifabric/styling": "^7.16.0",
"@uifabric/utilities": "^7.31.0",
"@uifabric/foundation": "^7.9.5",
"@uifabric/icons": "^7.5.5",
"@uifabric/merge-styles": "^7.19.1",
"@uifabric/react-hooks": "^7.13.4",
"@uifabric/set-version": "^7.0.23",
"@uifabric/styling": "^7.16.5",
"@uifabric/utilities": "^7.32.2",
"prop-types": "^15.7.2",
"tslib": "^1.10.0"
},
"dependencies": {
"@uifabric/react-hooks": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.13.0.tgz",
"integrity": "sha512-A7K0YFHHr10hB/txsqpPX6PhNhHEv8U7JpY3O81oqlZwSsHroJklQdd897JkAYJUUR+gWe2kQyXkkcaMDdqXjg==",
"version": "7.13.4",
"resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.13.4.tgz",
"integrity": "sha512-hyL3eQqbS7DrZCpkF1QDrC0TX+dV+yZZr5UgT3wAZMtzEMBFVgaiPHdv0zHgUbiQv5ktbQoY7yQp7clfVN65DA==",
"requires": {
"@fluentui/react-window-provider": "^0.3.0",
"@uifabric/set-version": "^7.0.22",
"@uifabric/utilities": "^7.31.0",
"@fluentui/react-window-provider": "^0.3.3",
"@uifabric/set-version": "^7.0.23",
"@uifabric/utilities": "^7.32.2",
"tslib": "^1.10.0"
}
}
@ -4995,9 +5027,9 @@
"dev": true
},
"postcss": {
"version": "7.0.32",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz",
"integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==",
"version": "7.0.34",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz",
"integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
@ -5573,12 +5605,12 @@
"dev": true
},
"selfsigned": {
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
"integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
"version": "1.10.8",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz",
"integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==",
"dev": true,
"requires": {
"node-forge": "0.9.0"
"node-forge": "^0.10.0"
}
},
"semver": {
@ -7996,58 +8028,6 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"write-file-atomic": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
"integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.11",
"imurmurhash": "^0.1.4",
"signal-exit": "^3.0.2"
}
},
"write-file-webpack-plugin": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/write-file-webpack-plugin/-/write-file-webpack-plugin-4.5.1.tgz",
"integrity": "sha512-AZ7qJUvhTCBiOtG21aFJUcNuLVo2FFM6JMGKvaUGAH+QDqQAp2iG0nq3GcuXmJOFQR2JjpjhyYkyPrbFKhdjNQ==",
"dev": true,
"requires": {
"chalk": "^2.4.0",
"debug": "^3.1.0",
"filesize": "^3.6.1",
"lodash": "^4.17.13",
"mkdirp": "^0.5.1",
"moment": "^2.22.1",
"write-file-atomic": "^2.3.0"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",

View file

@ -11,7 +11,7 @@
"url": "git+https://github.com/yume-chan/ya-webadb.git"
},
"scripts": {
"start": "webpack-dev-server",
"start": "webpack-dev-server --info-verbosity verbose",
"build": "webpack --mode production",
"build:dev": "webpack"
},
@ -33,8 +33,7 @@
"webpack": "4.44.1",
"webpack-bundle-analyzer": "3.9.0",
"webpack-cli": "3.3.12",
"webpack-dev-server": "3.11.0",
"write-file-webpack-plugin": "4.5.1"
"webpack-dev-server": "3.11.0"
},
"dependencies": {
"@fluentui/react": "7.137.1",

View file

@ -138,13 +138,15 @@ export default withDisplayName('FileManager', ({
setLoading(true);
const sync = await device.sync();
let items: ListItem[] = [];
const items: ListItem[] = [];
const linkItems: AdbSyncEntryResponse[] = [];
const intervalId = setInterval(() => {
setItems(items.slice());
}, 1000);
try {
let lastBreak = Date.now();
for await (const entry of sync.iterate(currentPath)) {
if (currentPath !== currentPathRef.current) {
break;
@ -154,7 +156,11 @@ export default withDisplayName('FileManager', ({
continue;
}
if (entry.type === LinuxFileType.Link) {
linkItems.push(entry);
} else {
items.push(toListItem(entry));
}
const now = Date.now();
if (now - lastBreak > 16) {
@ -163,6 +169,24 @@ export default withDisplayName('FileManager', ({
}
}
for (const entry of linkItems) {
try {
const followLinkPath = path.resolve(currentPath, entry.name) + '/';
console.log(followLinkPath);
await sync.lstat(followLinkPath);
items.push(toListItem(entry));
console.log(entry);
} catch (e) {
console.log(e);
items.push(toListItem(new AdbSyncEntryResponse(
(LinuxFileType.File << 12) | entry.mode,
0,
entry.lastModifiedTime,
entry.name
)));
}
}
setItems(items);
listRef.current?.scrollToIndex(0);
} finally {
@ -258,7 +282,7 @@ export default withDisplayName('FileManager', ({
minWidth: 0,
onRender(item: AdbSyncEntryResponse) {
if (item.type === LinuxFileType.File) {
return formatSize(item.logicalSize);
return formatSize(item.size);
}
return '';
}
@ -345,7 +369,7 @@ export default withDisplayName('FileManager', ({
let contextMenuItems: IContextualMenuItem[] = [];
if (selectedItems.length === 0 &&
if (selectedItems.length === 1 &&
selectedItems[0].type === LinuxFileType.File) {
contextMenuItems.push({
key: 'download',
@ -361,6 +385,8 @@ export default withDisplayName('FileManager', ({
size: selectedItems[0].size,
});
await readableStream.pipeTo(writeableStream);
} catch (e) {
showErrorDialog(e.message);
} finally {
sync.dispose();
}

View file

@ -1,17 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "lib", // /* Redirect output structure to the directory. */
"rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"lib": [
"ESNext",
"DOM"
],
"jsx": "react" // /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"jsx": "react", // /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
},
"include": [
"src"
],
"references": [
{
"path": "../adb-backend-web/tsconfig.json"

View file

@ -6,7 +6,6 @@ const html_webpack_plugin_1 = tslib_1.__importDefault(require("html-webpack-plug
const mini_css_extract_plugin_1 = tslib_1.__importDefault(require("mini-css-extract-plugin"));
const path_1 = tslib_1.__importDefault(require("path"));
const webpack_bundle_analyzer_1 = require("webpack-bundle-analyzer");
const write_file_webpack_plugin_1 = tslib_1.__importDefault(require("write-file-webpack-plugin"));
const context = path_1.default.resolve(process.cwd());
const plugins = [
new clean_webpack_plugin_1.CleanWebpackPlugin(),
@ -27,7 +26,6 @@ const plugins = [
template: 'www/index.html',
scriptLoading: 'defer',
}),
new write_file_webpack_plugin_1.default(),
];
if (process.env.ANALYZE) {
plugins.push(new webpack_bundle_analyzer_1.BundleAnalyzerPlugin());
@ -69,7 +67,12 @@ const config = (env, argv) => ({
},
devServer: {
contentBase: path_1.default.resolve(context, 'lib'),
port: 9000
port: 9000,
watchOptions: {
ignored: [
/.(js|d.ts|map|tsbuildinfo|css|html)/
]
}
},
});
module.exports = config;

View file

@ -2,9 +2,6 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "lib", // /* Redirect output structure to the directory. */
"rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
},
"include": [
"src"
]
"rootDir": "./src" // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
}
}

View file

@ -161,9 +161,9 @@
"dev": true
},
"@types/qs": {
"version": "6.9.4",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz",
"integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==",
"version": "6.9.5",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
"integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==",
"dev": true
},
"@types/range-parser": {
@ -264,15 +264,6 @@
}
}
},
"@types/write-file-webpack-plugin": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/@types/write-file-webpack-plugin/-/write-file-webpack-plugin-4.5.0.tgz",
"integrity": "sha512-uTUXNNhuE+mJ0BjQD3W9bIOYnmAsLumgLy6ktSHVsFwvr4g+g/KhxSSLf31/KlsSVKovfaLVaUw49ZR0SPVlXw==",
"dev": true,
"requires": {
"@types/webpack": "*"
}
},
"array-union": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",

View file

@ -24,7 +24,6 @@
"@types/webpack": "4.41.22",
"@types/webpack-bundle-analyzer": "3.8.0",
"@types/webpack-dev-server": "3.11.0",
"@types/write-file-webpack-plugin": "4.5.0",
"clean-webpack-plugin": "3.0.0",
"typescript": "4.0.2"
}

View file

@ -3,9 +3,8 @@ import CopyPlugin from 'copy-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import path from 'path';
import type webpack from 'webpack';
import webpack from 'webpack';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import WriteFileWebpackPlugin from 'write-file-webpack-plugin';
const context = path.resolve(process.cwd());
@ -28,7 +27,6 @@ const plugins: webpack.Plugin[] = [
template: 'www/index.html',
scriptLoading: 'defer',
}),
new WriteFileWebpackPlugin(),
];
if (process.env.ANALYZE) {
@ -75,7 +73,7 @@ const config: webpack.ConfigurationFactory = (
},
devServer: {
contentBase: path.resolve(context, 'lib'),
port: 9000
port: 9000,
},
});

View file

@ -11,7 +11,7 @@
"outDir": "../demo", // /* Redirect output structure to the directory. */
"rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"composite": false, // /* Enable project compilation */
"tsBuildInfoFile": "./tsconfig.tsbuildinfo", ///* Specify file to store incremental compilation information */
"tsBuildInfoFile": "./tsconfig.tsbuildinfo", /* Specify file to store incremental compilation information */
},
"include": [
"src"

View file

@ -14,14 +14,14 @@
"declarationMap": true, // /* Generates a sourcemap for each corresponding '.d.ts' file. */
"sourceMap": true, // /* Generates corresponding '.map' file. */
// "outFile": "lib/index.js", // /* Concatenate and emit output to single file. */
"outDir": "lib", // /* Redirect output structure to the directory. */
"rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "outDir": "lib", /* Redirect output structure to the directory. */
// "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"composite": true, // /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
"importHelpers": true, // /* Import emit helpers from 'tslib'. */
"downlevelIteration": true, // /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "downlevelIteration": true, // /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, // /* Enable all strict type-checking options. */