mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-03 01:39:21 +02:00
91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
import { PromiseResolver } from "@yume-chan/async";
|
|
import type { AsyncExactReadable, StructInit } from "@yume-chan/struct";
|
|
import { string, struct, u32, u64, u8 } from "@yume-chan/struct";
|
|
|
|
import type { ScrcpyDeviceMessageParser } from "../../base/index.js";
|
|
import type { ScrcpySetClipboardControlMessage } from "../../latest.js";
|
|
|
|
export const AckClipboardDeviceMessage = struct(
|
|
{ sequence: u64 },
|
|
{ littleEndian: false },
|
|
);
|
|
|
|
export const SetClipboardControlMessage = struct(
|
|
{
|
|
// value of `type` can change between versions
|
|
type: u8,
|
|
sequence: u64,
|
|
paste: u8<boolean>(),
|
|
content: string(u32),
|
|
},
|
|
{ littleEndian: false },
|
|
);
|
|
|
|
export type SetClipboardControlMessage = StructInit<
|
|
typeof SetClipboardControlMessage
|
|
>;
|
|
|
|
export class AckClipboardHandler implements ScrcpyDeviceMessageParser {
|
|
#resolvers = new Map<bigint, PromiseResolver<void>>();
|
|
|
|
#closed = false;
|
|
|
|
readonly id = 1;
|
|
|
|
async parse(_id: number, stream: AsyncExactReadable): Promise<undefined> {
|
|
const message = await AckClipboardDeviceMessage.deserialize(stream);
|
|
const resolver = this.#resolvers.get(message.sequence);
|
|
if (resolver) {
|
|
resolver.resolve();
|
|
this.#resolvers.delete(message.sequence);
|
|
}
|
|
}
|
|
|
|
close(): void {
|
|
for (const resolver of this.#resolvers.values()) {
|
|
resolver.reject();
|
|
}
|
|
this.#resolvers.clear();
|
|
this.#closed = true;
|
|
}
|
|
|
|
error(e?: unknown): void {
|
|
for (const resolver of this.#resolvers.values()) {
|
|
resolver.reject(e);
|
|
}
|
|
this.#resolvers.clear();
|
|
this.#closed = true;
|
|
}
|
|
|
|
serializeSetClipboardControlMessage(
|
|
message: ScrcpySetClipboardControlMessage,
|
|
): Uint8Array | [Uint8Array, Promise<void>] {
|
|
if (message.sequence === 0n) {
|
|
return SetClipboardControlMessage.serialize(message);
|
|
}
|
|
|
|
if (this.#closed) {
|
|
throw new Error();
|
|
}
|
|
|
|
const resolver = new PromiseResolver<void>();
|
|
this.#resolvers.set(message.sequence, resolver);
|
|
return [
|
|
SetClipboardControlMessage.serialize(message),
|
|
resolver.promise,
|
|
];
|
|
}
|
|
}
|
|
|
|
export function serializeSetClipboardControlMessage(
|
|
message: ScrcpySetClipboardControlMessage,
|
|
ackHandler: AckClipboardHandler | undefined,
|
|
): Uint8Array | [Uint8Array, Promise<void>] {
|
|
if (!ackHandler) {
|
|
throw new Error(
|
|
"`serializeSetClipboardControlMessage` requires `control: true` option",
|
|
);
|
|
}
|
|
|
|
return ackHandler.serializeSetClipboardControlMessage(message);
|
|
}
|