Loading apps/demo/components/terminal.tsx +1 −7 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ export class AdbTerminal extends AutoDisposable { this._socketAbortController = new AbortController(); // pty mode only has one stream value.stdout.pipeTo(new WritableStream<Uint8Array>({ write: (chunk) => { this.terminal.write(chunk); Loading @@ -43,13 +44,6 @@ export class AdbTerminal extends AutoDisposable { }), { signal: this._socketAbortController.signal, }); value.stderr.pipeTo(new WritableStream<Uint8Array>({ write: (chunk) => { this.terminal.write(chunk); }, }), { signal: this._socketAbortController.signal, }); const _writer = value.stdin.getWriter(); this.addDisposable(this.terminal.onData(data => { Loading apps/demo/next.config.js +1 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ const withMDX = require('@next/mdx')({ module.exports = withMDX({ basePath: process.env.BASE_PATH || '', pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'], reactStrictMode: true, reactStrictMode: false, productionBrowserSourceMaps: true, experimental: { // Workaround https://github.com/vercel/next.js/issues/33914 Loading apps/demo/pages/_app.tsx +5 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,11 @@ const ROUTES = [ icon: Icons.Power, name: 'Power Menu', }, { url: '/bug-report', icon: Icons.Bug, name: 'Bug Report', }, ]; function NavLink({ link, defaultRender: DefaultRender, ...props }: IComponentAsProps<INavButtonProps>) { Loading apps/demo/pages/bug-report.tsx 0 → 100644 +149 −0 Original line number Diff line number Diff line // cspell: ignore bugreport // cspell: ignore bugreportz import { MessageBar, MessageBarType, PrimaryButton, Stack, StackItem } from "@fluentui/react"; import { BugReport, BugReportZ, BugReportZVersion } from "@yume-chan/android-bin"; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { observer } from "mobx-react-lite"; import { NextPage } from "next"; import Head from "next/head"; import { globalState } from "../state"; import { RouteStackProps, saveFile } from "../utils"; class BugReportState { bugReport: BugReport | undefined = undefined; bugReportZ: BugReportZ | undefined = undefined; bugReportZVersion: BugReportZVersion | undefined = undefined; bugReportZInProgress = false; bugReportZProgress: string | undefined = undefined; bugReportZTotalSize: string | undefined = undefined; constructor() { makeAutoObservable(this, { bugReportZVersion: observable.deep, generateBugReport: action.bound, generateBugReportZStream: action.bound, generateBugReportZ: action.bound, }); autorun(() => { if (globalState.device) { runInAction(() => { this.bugReport = new BugReport(globalState.device!); this.bugReportZ = new BugReportZ(globalState.device!); this.bugReportZ.version().then(action(version => { this.bugReportZVersion = version; })); }); } else { runInAction(() => { this.bugReport = undefined; this.bugReportZ = undefined; this.bugReportZVersion = undefined; }); } }); } async generateBugReport() { await this.bugReport!.generate() .pipeTo(saveFile('bugreport.txt')); } async generateBugReportZStream() { await this.bugReportZ!.stream() .pipeTo(saveFile('bugreport.zip')); } async generateBugReportZ() { runInAction(() => { this.bugReportZInProgress = true; }); const filename = await this.bugReportZ!.generate( this.bugReportZVersion!.supportProgress ? action((progress, total) => { this.bugReportZProgress = progress; this.bugReportZTotalSize = total; }) : undefined ); const sync = await globalState.device!.sync(); await sync.read(filename) .pipeTo(saveFile('bugreport.zip')); sync.dispose(); runInAction(() => { this.bugReportZInProgress = false; this.bugReportZProgress = undefined; this.bugReportZTotalSize = undefined; }); } } const state = new BugReportState(); const BugReportPage: NextPage = () => { return ( <Stack {...RouteStackProps}> <Head> <title>BugReport - WebADB</title> </Head> <MessageBar messageBarType={MessageBarType.info}>This is the `bugreport`/`bugreportz` tool in Android</MessageBar> <StackItem> <PrimaryButton disabled={!state.bugReport} text="Generate BugReport" onClick={state.generateBugReport} /> </StackItem> <StackItem> <PrimaryButton disabled={!state.bugReportZVersion?.supportStream} text="Generate Zipped BugReport (Streaming)" onClick={state.generateBugReportZStream} /> </StackItem> <StackItem> <Stack horizontal verticalAlign="center" tokens={{ childrenGap: 8 }}> <StackItem> <PrimaryButton disabled={!state.bugReportZVersion || state.bugReportZInProgress} text="Generate Zipped BugReport" onClick={state.generateBugReportZ} /> </StackItem> {state.bugReportZInProgress && ( <StackItem> {state.bugReportZTotalSize ? ( <span> Progress: {state.bugReportZProgress} / {state.bugReportZTotalSize} </span> ) : ( <span> Generating... Please wait {!state.bugReportZVersion!.supportProgress && ' (this device does not support progress)'} </span> )} </StackItem> )} </Stack> </StackItem> </Stack> ); }; export default observer(BugReportPage); apps/demo/pages/file-manager.tsx +4 −19 Original line number Diff line number Diff line Loading @@ -2,30 +2,20 @@ import { Breadcrumb, concatStyleSets, ContextualMenu, ContextualMenuItem, Detail import { FileIconType, getFileTypeIconProps, initializeFileTypeIcons } from "@fluentui/react-file-type-icons"; import { useConst } from '@fluentui/react-hooks'; import { getIcon } from '@fluentui/style-utilities'; import { AdbSyncEntryResponse, ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, LinuxFileType, ReadableStream, WritableStream } from '@yume-chan/adb'; import { AdbSyncEntryResponse, ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, LinuxFileType, ReadableStream } from '@yume-chan/adb'; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { observer } from "mobx-react-lite"; import { NextPage } from "next"; import getConfig from "next/config"; import Head from "next/head"; import Router, { useRouter } from "next/router"; import path from 'path'; import { useCallback, useEffect, useState } from 'react'; import { CommandBar, NoSsr } from '../components'; import { globalState } from '../state'; import { asyncEffect, formatSize, formatSpeed, Icons, pickFile, ProgressStream, RouteStackProps } from '../utils'; import { asyncEffect, formatSize, formatSpeed, Icons, pickFile, ProgressStream, RouteStackProps, saveFile } from '../utils'; initializeFileTypeIcons(); let StreamSaver: typeof import('streamsaver'); if (typeof window !== 'undefined') { const { publicRuntimeConfig } = getConfig(); // Can't use `import` here because ESM is read-only (can't set `mitm` field) // Add `await` here because top-level await is on, so every import can be a `Promise` StreamSaver = await require('streamsaver'); StreamSaver.mitm = publicRuntimeConfig.basePath + '/StreamSaver/mitm.html'; } interface ListItem extends AdbSyncEntryResponse { key: string; } Loading Loading @@ -148,13 +138,8 @@ class FileManagerState { try { const item = this.selectedItems[0]; const itemPath = path.resolve(this.path, item.name); const readable = sync.read(itemPath); const writeable: WritableStream<Uint8Array> = StreamSaver!.createWriteStream( item.name, { size: item.size } ) as any; await readable.pipeTo(writeable); await sync.read(itemPath) .pipeTo(saveFile(item.name, item.size)); } catch (e) { globalState.showErrorDialog(e instanceof Error ? e.message : `${e}`); } finally { Loading Loading
apps/demo/components/terminal.tsx +1 −7 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ export class AdbTerminal extends AutoDisposable { this._socketAbortController = new AbortController(); // pty mode only has one stream value.stdout.pipeTo(new WritableStream<Uint8Array>({ write: (chunk) => { this.terminal.write(chunk); Loading @@ -43,13 +44,6 @@ export class AdbTerminal extends AutoDisposable { }), { signal: this._socketAbortController.signal, }); value.stderr.pipeTo(new WritableStream<Uint8Array>({ write: (chunk) => { this.terminal.write(chunk); }, }), { signal: this._socketAbortController.signal, }); const _writer = value.stdin.getWriter(); this.addDisposable(this.terminal.onData(data => { Loading
apps/demo/next.config.js +1 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ const withMDX = require('@next/mdx')({ module.exports = withMDX({ basePath: process.env.BASE_PATH || '', pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'], reactStrictMode: true, reactStrictMode: false, productionBrowserSourceMaps: true, experimental: { // Workaround https://github.com/vercel/next.js/issues/33914 Loading
apps/demo/pages/_app.tsx +5 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,11 @@ const ROUTES = [ icon: Icons.Power, name: 'Power Menu', }, { url: '/bug-report', icon: Icons.Bug, name: 'Bug Report', }, ]; function NavLink({ link, defaultRender: DefaultRender, ...props }: IComponentAsProps<INavButtonProps>) { Loading
apps/demo/pages/bug-report.tsx 0 → 100644 +149 −0 Original line number Diff line number Diff line // cspell: ignore bugreport // cspell: ignore bugreportz import { MessageBar, MessageBarType, PrimaryButton, Stack, StackItem } from "@fluentui/react"; import { BugReport, BugReportZ, BugReportZVersion } from "@yume-chan/android-bin"; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { observer } from "mobx-react-lite"; import { NextPage } from "next"; import Head from "next/head"; import { globalState } from "../state"; import { RouteStackProps, saveFile } from "../utils"; class BugReportState { bugReport: BugReport | undefined = undefined; bugReportZ: BugReportZ | undefined = undefined; bugReportZVersion: BugReportZVersion | undefined = undefined; bugReportZInProgress = false; bugReportZProgress: string | undefined = undefined; bugReportZTotalSize: string | undefined = undefined; constructor() { makeAutoObservable(this, { bugReportZVersion: observable.deep, generateBugReport: action.bound, generateBugReportZStream: action.bound, generateBugReportZ: action.bound, }); autorun(() => { if (globalState.device) { runInAction(() => { this.bugReport = new BugReport(globalState.device!); this.bugReportZ = new BugReportZ(globalState.device!); this.bugReportZ.version().then(action(version => { this.bugReportZVersion = version; })); }); } else { runInAction(() => { this.bugReport = undefined; this.bugReportZ = undefined; this.bugReportZVersion = undefined; }); } }); } async generateBugReport() { await this.bugReport!.generate() .pipeTo(saveFile('bugreport.txt')); } async generateBugReportZStream() { await this.bugReportZ!.stream() .pipeTo(saveFile('bugreport.zip')); } async generateBugReportZ() { runInAction(() => { this.bugReportZInProgress = true; }); const filename = await this.bugReportZ!.generate( this.bugReportZVersion!.supportProgress ? action((progress, total) => { this.bugReportZProgress = progress; this.bugReportZTotalSize = total; }) : undefined ); const sync = await globalState.device!.sync(); await sync.read(filename) .pipeTo(saveFile('bugreport.zip')); sync.dispose(); runInAction(() => { this.bugReportZInProgress = false; this.bugReportZProgress = undefined; this.bugReportZTotalSize = undefined; }); } } const state = new BugReportState(); const BugReportPage: NextPage = () => { return ( <Stack {...RouteStackProps}> <Head> <title>BugReport - WebADB</title> </Head> <MessageBar messageBarType={MessageBarType.info}>This is the `bugreport`/`bugreportz` tool in Android</MessageBar> <StackItem> <PrimaryButton disabled={!state.bugReport} text="Generate BugReport" onClick={state.generateBugReport} /> </StackItem> <StackItem> <PrimaryButton disabled={!state.bugReportZVersion?.supportStream} text="Generate Zipped BugReport (Streaming)" onClick={state.generateBugReportZStream} /> </StackItem> <StackItem> <Stack horizontal verticalAlign="center" tokens={{ childrenGap: 8 }}> <StackItem> <PrimaryButton disabled={!state.bugReportZVersion || state.bugReportZInProgress} text="Generate Zipped BugReport" onClick={state.generateBugReportZ} /> </StackItem> {state.bugReportZInProgress && ( <StackItem> {state.bugReportZTotalSize ? ( <span> Progress: {state.bugReportZProgress} / {state.bugReportZTotalSize} </span> ) : ( <span> Generating... Please wait {!state.bugReportZVersion!.supportProgress && ' (this device does not support progress)'} </span> )} </StackItem> )} </Stack> </StackItem> </Stack> ); }; export default observer(BugReportPage);
apps/demo/pages/file-manager.tsx +4 −19 Original line number Diff line number Diff line Loading @@ -2,30 +2,20 @@ import { Breadcrumb, concatStyleSets, ContextualMenu, ContextualMenuItem, Detail import { FileIconType, getFileTypeIconProps, initializeFileTypeIcons } from "@fluentui/react-file-type-icons"; import { useConst } from '@fluentui/react-hooks'; import { getIcon } from '@fluentui/style-utilities'; import { AdbSyncEntryResponse, ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, LinuxFileType, ReadableStream, WritableStream } from '@yume-chan/adb'; import { AdbSyncEntryResponse, ADB_SYNC_MAX_PACKET_SIZE, ChunkStream, LinuxFileType, ReadableStream } from '@yume-chan/adb'; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { observer } from "mobx-react-lite"; import { NextPage } from "next"; import getConfig from "next/config"; import Head from "next/head"; import Router, { useRouter } from "next/router"; import path from 'path'; import { useCallback, useEffect, useState } from 'react'; import { CommandBar, NoSsr } from '../components'; import { globalState } from '../state'; import { asyncEffect, formatSize, formatSpeed, Icons, pickFile, ProgressStream, RouteStackProps } from '../utils'; import { asyncEffect, formatSize, formatSpeed, Icons, pickFile, ProgressStream, RouteStackProps, saveFile } from '../utils'; initializeFileTypeIcons(); let StreamSaver: typeof import('streamsaver'); if (typeof window !== 'undefined') { const { publicRuntimeConfig } = getConfig(); // Can't use `import` here because ESM is read-only (can't set `mitm` field) // Add `await` here because top-level await is on, so every import can be a `Promise` StreamSaver = await require('streamsaver'); StreamSaver.mitm = publicRuntimeConfig.basePath + '/StreamSaver/mitm.html'; } interface ListItem extends AdbSyncEntryResponse { key: string; } Loading Loading @@ -148,13 +138,8 @@ class FileManagerState { try { const item = this.selectedItems[0]; const itemPath = path.resolve(this.path, item.name); const readable = sync.read(itemPath); const writeable: WritableStream<Uint8Array> = StreamSaver!.createWriteStream( item.name, { size: item.size } ) as any; await readable.pipeTo(writeable); await sync.read(itemPath) .pipeTo(saveFile(item.name, item.size)); } catch (e) { globalState.showErrorDialog(e instanceof Error ? e.message : `${e}`); } finally { Loading