Skip to content

Commit

Permalink
refactor(scrcpy): rewrite option classes to improve tree-shaking
Browse files Browse the repository at this point in the history
  • Loading branch information
yume-chan committed Nov 27, 2024
1 parent 9247200 commit cc5d529
Show file tree
Hide file tree
Showing 63 changed files with 599 additions and 329 deletions.
2 changes: 2 additions & 0 deletions libraries/adb-scrcpy/src/options/1_16.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export class AdbScrcpyOptions1_16 extends AdbScrcpyOptions<
const client = await AdbScrcpyClient.start(adb, path, version, options);

const encoders: ScrcpyEncoder[] = [];

// `client.stdout` is supplied by user and may not support async iteration
await client.stdout.pipeTo(
new WritableStream({
write: (line) => {
Expand Down
8 changes: 3 additions & 5 deletions libraries/adb/src/commands/subprocess/protocols/none.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { MaybeConsumable, WritableStream } from "@yume-chan/stream-extra";
import { ReadableStream } from "@yume-chan/stream-extra";

import type { Adb, AdbSocket } from "../../../adb.js";
import { unreachable } from "../../../utils/index.js";

import type { AdbSubprocessProtocol } from "./types.js";

Expand Down Expand Up @@ -64,10 +63,9 @@ export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
this.#socket = socket;

this.#stderr = new ReadableStream({
start: (controller) => {
this.#socket.closed
.then(() => controller.close())
.catch(unreachable);
start: async (controller) => {
await this.#socket.closed;
controller.close();
},
});
this.#exit = socket.closed.then(() => 0);
Expand Down
30 changes: 16 additions & 14 deletions libraries/adb/src/commands/sync/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,25 @@ export interface AdbSyncEntry extends AdbSyncStat {
name: string;
}

export const AdbSyncEntryResponse = struct(
/* #__PURE__ */ (() => ({
...AdbSyncLstatResponse.fields,
name: string(u32),
}))(),
{ littleEndian: true, extra: AdbSyncLstatResponse.extra },
);
export const AdbSyncEntryResponse = /* #__PURE__ */ (() =>
struct(
{
...AdbSyncLstatResponse.fields,
name: string(u32),
},
{ littleEndian: true, extra: AdbSyncLstatResponse.extra },
))();

export type AdbSyncEntryResponse = StructValue<typeof AdbSyncEntryResponse>;

export const AdbSyncEntry2Response = struct(
/* #__PURE__ */ (() => ({
...AdbSyncStatResponse.fields,
name: string(u32),
}))(),
{ littleEndian: true, extra: AdbSyncStatResponse.extra },
);
export const AdbSyncEntry2Response = /* #__PURE__ */ (() =>
struct(
{
...AdbSyncStatResponse.fields,
name: string(u32),
},
{ littleEndian: true, extra: AdbSyncStatResponse.extra },
))();

export type AdbSyncEntry2Response = StructValue<typeof AdbSyncEntry2Response>;

Expand Down
12 changes: 7 additions & 5 deletions libraries/adb/src/daemon/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ export interface AdbCredentialStore {
iterateKeys(): AdbKeyIterable;
}

export enum AdbAuthType {
Token = 1,
Signature = 2,
PublicKey = 3,
}
export const AdbAuthType = {
Token: 1,
Signature: 2,
PublicKey: 3,
} as const;

export type AdbAuthType = (typeof AdbAuthType)[keyof typeof AdbAuthType];

export interface AdbAuthenticator {
/**
Expand Down
43 changes: 22 additions & 21 deletions libraries/adb/src/daemon/transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,28 @@ import { AdbCommand, calculateChecksum } from "./packet.js";
export const ADB_DAEMON_VERSION_OMIT_CHECKSUM = 0x01000001;
// https://android.googlesource.com/platform/packages/modules/adb/+/79010dc6d5ca7490c493df800d4421730f5466ca/transport.cpp#1252
// There are some other feature constants, but some of them are only used by ADB server, not devices (daemons).
export const ADB_DAEMON_DEFAULT_FEATURES = [
AdbFeature.ShellV2,
AdbFeature.Cmd,
AdbFeature.StatV2,
AdbFeature.ListV2,
AdbFeature.FixedPushMkdir,
"apex",
AdbFeature.Abb,
// only tells the client the symlink timestamp issue in `adb push --sync` has been fixed.
// No special handling required.
"fixed_push_symlink_timestamp",
AdbFeature.AbbExec,
"remount_shell",
"track_app",
AdbFeature.SendReceiveV2,
"sendrecv_v2_brotli",
"sendrecv_v2_lz4",
"sendrecv_v2_zstd",
"sendrecv_v2_dry_run_send",
AdbFeature.DelayedAck,
] as AdbFeature[];
export const ADB_DAEMON_DEFAULT_FEATURES = /* #__PURE__ */ (() =>
[
AdbFeature.ShellV2,
AdbFeature.Cmd,
AdbFeature.StatV2,
AdbFeature.ListV2,
AdbFeature.FixedPushMkdir,
"apex",
AdbFeature.Abb,
// only tells the client the symlink timestamp issue in `adb push --sync` has been fixed.
// No special handling required.
"fixed_push_symlink_timestamp",
AdbFeature.AbbExec,
"remount_shell",
"track_app",
AdbFeature.SendReceiveV2,
"sendrecv_v2_brotli",
"sendrecv_v2_lz4",
"sendrecv_v2_zstd",
"sendrecv_v2_dry_run_send",
AdbFeature.DelayedAck,
] as AdbFeature[])();
export const ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE = 32 * 1024 * 1024;

export type AdbDaemonConnection = ReadableWritablePair<
Expand Down
56 changes: 26 additions & 30 deletions libraries/android-bin/src/bug-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,37 +211,33 @@ export class BugReport extends AdbCommandBase {
let filename: string | undefined;
let error: string | undefined;

await process.stdout
for await (const line of process.stdout
.pipeThrough(new TextDecoderStream())
.pipeThrough(new SplitStringStream("\n"))
.pipeTo(
new WritableStream<string>({
write(line) {
// `BEGIN:` and `PROGRESS:` only appear when `-p` is specified.
let match = line.match(BugReport.PROGRESS_REGEX);
if (match) {
options?.onProgress?.(match[1]!, match[2]!);
}

match = line.match(BugReport.BEGIN_REGEX);
if (match) {
filename = match[1]!;
}

match = line.match(BugReport.OK_REGEX);
if (match) {
filename = match[1];
}

match = line.match(BugReport.FAIL_REGEX);
if (match) {
// Don't report error now
// We want to gather all output.
error = match[1];
}
},
}),
);
// Each chunk should contain one or several full lines
.pipeThrough(new SplitStringStream("\n"))) {
// `BEGIN:` and `PROGRESS:` only appear when `-p` is specified.
let match = line.match(BugReport.PROGRESS_REGEX);
if (match) {
options?.onProgress?.(match[1]!, match[2]!);
}

match = line.match(BugReport.BEGIN_REGEX);
if (match) {
filename = match[1]!;
}

match = line.match(BugReport.OK_REGEX);
if (match) {
filename = match[1];
}

match = line.match(BugReport.FAIL_REGEX);
if (match) {
// Don't report error now
// We want to gather all output.
error = match[1];
}
}

if (error) {
throw new Error(error);
Expand Down
88 changes: 41 additions & 47 deletions libraries/android-bin/src/logcat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
SplitStringStream,
TextDecoderStream,
WrapReadableStream,
WritableStream,
} from "@yume-chan/stream-extra";
import type { AsyncExactReadable, StructValue } from "@yume-chan/struct";
import { decodeUtf8, struct, u16, u32 } from "@yume-chan/struct";
Expand Down Expand Up @@ -437,53 +436,48 @@ export class Logcat extends AdbCommandBase {
]);

const result: LogSize[] = [];
await stdout
for await (const line of stdout
.pipeThrough(new TextDecoderStream())
.pipeThrough(new SplitStringStream("\n"))
.pipeTo(
new WritableStream({
write(chunk) {
let match = chunk.match(Logcat.LOG_SIZE_REGEX_11);
if (match) {
result.push({
id: Logcat.logNameToId(match[1]!),
size: Logcat.parseSize(
Number.parseInt(match[2]!, 10),
match[3]!,
),
readable: Logcat.parseSize(
Number.parseInt(match[6]!, 10),
match[7]!,
),
consumed: Logcat.parseSize(
Number.parseInt(match[4]!, 10),
match[5]!,
),
maxEntrySize: parseInt(match[8]!, 10),
maxPayloadSize: parseInt(match[9]!, 10),
});
return;
}

match = chunk.match(Logcat.LOG_SIZE_REGEX_10);
if (match) {
result.push({
id: Logcat.logNameToId(match[1]!),
size: Logcat.parseSize(
Number.parseInt(match[2]!, 10),
match[3]!,
),
consumed: Logcat.parseSize(
Number.parseInt(match[4]!, 10),
match[5]!,
),
maxEntrySize: parseInt(match[6]!, 10),
maxPayloadSize: parseInt(match[7]!, 10),
});
}
},
}),
);
.pipeThrough(new SplitStringStream("\n"))) {
let match = line.match(Logcat.LOG_SIZE_REGEX_11);
if (match) {
result.push({
id: Logcat.logNameToId(match[1]!),
size: Logcat.parseSize(
Number.parseInt(match[2]!, 10),
match[3]!,
),
readable: Logcat.parseSize(
Number.parseInt(match[6]!, 10),
match[7]!,
),
consumed: Logcat.parseSize(
Number.parseInt(match[4]!, 10),
match[5]!,
),
maxEntrySize: parseInt(match[8]!, 10),
maxPayloadSize: parseInt(match[9]!, 10),
});
break;
}

match = line.match(Logcat.LOG_SIZE_REGEX_10);
if (match) {
result.push({
id: Logcat.logNameToId(match[1]!),
size: Logcat.parseSize(
Number.parseInt(match[2]!, 10),
match[3]!,
),
consumed: Logcat.parseSize(
Number.parseInt(match[4]!, 10),
match[5]!,
),
maxEntrySize: parseInt(match[6]!, 10),
maxPayloadSize: parseInt(match[7]!, 10),
});
}
}

return result;
}
Expand Down
1 change: 0 additions & 1 deletion libraries/scrcpy/side-effect-test/src/index.js

This file was deleted.

6 changes: 5 additions & 1 deletion libraries/scrcpy/src/1_15/impl/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const VideoOrientation = {
Landscape: 1,
PortraitFlipped: 2,
LandscapeFlipped: 3,
};
} as const;

export type VideoOrientation =
(typeof VideoOrientation)[keyof typeof VideoOrientation];
Expand Down Expand Up @@ -85,6 +85,10 @@ export class CodecOptions implements ScrcpyOptionValue {
}
}

export namespace CodecOptions {
export type Init = CodecOptionsInit;
}

export interface Init {
logLevel?: LogLevel;

Expand Down
20 changes: 8 additions & 12 deletions libraries/scrcpy/src/1_15/impl/inject-touch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,7 @@ import { bipedal, struct, u16, u32, u64, u8 } from "@yume-chan/struct";

import type { AndroidMotionEventAction } from "../../android/index.js";
import type { ScrcpyInjectTouchControlMessage } from "../../latest.js";

export function clamp(value: number, min: number, max: number): number {
if (value < min) {
return min;
}

if (value > max) {
return max;
}

return value;
}
import { clamp } from "../../utils/index.js";

export const UnsignedFloat: Field<number, never, never> = {
size: 2,
Expand All @@ -33,6 +22,13 @@ export const UnsignedFloat: Field<number, never, never> = {
}),
};

export const PointerId = {
Mouse: -1n,
Finger: -2n,
VirtualMouse: -3n,
VirtualFinger: -4n,
} as const;

export const InjectTouchControlMessage = struct(
{
type: u8,
Expand Down
3 changes: 2 additions & 1 deletion libraries/scrcpy/src/1_18/impl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export {
} from "./back-or-screen-on.js";
export { ControlMessageTypes } from "./control-message-types.js";
export { Defaults } from "./defaults.js";
export type { Init } from "./init.js";
export { VideoOrientation } from "./init.js";
export type { Init, LogLevel } from "./init.js";
export { EncoderRegex } from "./parse-encoder.js";
export { SerializeOrder } from "./serialize-order.js";
2 changes: 1 addition & 1 deletion libraries/scrcpy/src/1_18/impl/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const VideoOrientation = {
Landscape: 1,
PortraitFlipped: 2,
LandscapeFlipped: 3,
};
} as const;

export type VideoOrientation =
(typeof VideoOrientation)[keyof typeof VideoOrientation];
Expand Down
Loading

0 comments on commit cc5d529

Please sign in to comment.