From: Lonny Wong Date: Thu, 27 Apr 2023 03:57:09 +0000 (+0800) Subject: improve support for trzsz (#1084) X-Git-Url: http://git.prime8.dev/?a=commitdiff_plain;h=8c6c6ee885d7ea94c0886fc860a3a64e2cb43118;p=ttyd.git improve support for trzsz (#1084) * trzsz support drag and drop to upload * optimize trzsz upload speed * trzsz support windows * trzsz support transfer directories in browser --- diff --git a/html/package.json b/html/package.json index 29f4cf9..ca2e33a 100644 --- a/html/package.json +++ b/html/package.json @@ -51,7 +51,7 @@ "decko": "^1.2.0", "file-saver": "^2.0.5", "preact": "^10.11.2", - "trzsz": "^0.4.3", + "trzsz": "^1.1.0", "whatwg-fetch": "^3.6.2", "xterm": "^5.1.0", "xterm-addon-canvas": "^0.3.0", diff --git a/html/src/components/app.tsx b/html/src/components/app.tsx index 71a2d89..1ad5fd3 100644 --- a/html/src/components/app.tsx +++ b/html/src/components/app.tsx @@ -15,6 +15,7 @@ const clientOptions = { enableZmodem: false, enableTrzsz: false, enableSixel: false, + isWindows: false, } as ClientOptions; const termOptions = { fontSize: 13, diff --git a/html/src/components/terminal/xterm/addons/zmodem.ts b/html/src/components/terminal/xterm/addons/zmodem.ts index 3d38c5c..8571f68 100644 --- a/html/src/components/terminal/xterm/addons/zmodem.ts +++ b/html/src/components/terminal/xterm/addons/zmodem.ts @@ -7,6 +7,7 @@ import { TrzszFilter } from 'trzsz'; export interface ZmodeOptions { zmodem: boolean; trzsz: boolean; + windows: boolean; onSend: () => void; sender: (data: string | Uint8Array) => void; writer: (data: string | Uint8Array) => void; @@ -54,6 +55,11 @@ export class ZmodemAddon implements ITerminalAddon { this.terminal.focus(); } + private addDisposableListener(target: EventTarget, type: string, listener: EventListener) { + target.addEventListener(type, listener); + this.disposables.push({ dispose: () => target.removeEventListener(type, listener) }); + } + @bind private trzszInit() { const { terminal } = this; @@ -68,6 +74,16 @@ export class ZmodemAddon implements ITerminalAddon { }, sendToServer: data => sender(data), terminalColumns: terminal.cols, + isWindowsShell: this.options.windows, + }); + const element = terminal.element as EventTarget; + this.addDisposableListener(element, 'dragover', event => event.preventDefault()); + this.addDisposableListener(element, 'drop', event => { + event.preventDefault(); + this.trzszFilter + .uploadFiles((event as DragEvent).dataTransfer?.items as DataTransferItemList) + .then(() => console.log('[ttyd] upload success')) + .catch(err => console.log('[ttyd] upload failed: ' + err)); }); this.disposables.push(terminal.onResize(size => this.trzszFilter.setTerminalColumns(size.cols))); } diff --git a/html/src/components/terminal/xterm/index.ts b/html/src/components/terminal/xterm/index.ts index ac49b9f..8736ef8 100644 --- a/html/src/components/terminal/xterm/index.ts +++ b/html/src/components/terminal/xterm/index.ts @@ -44,6 +44,7 @@ export interface ClientOptions { enableTrzsz: boolean; enableSixel: boolean; titleFixed?: string; + isWindows: boolean; } export interface FlowControl { @@ -218,7 +219,10 @@ export class Xterm { if (socket?.readyState !== WebSocket.OPEN) return; if (typeof data === 'string') { - socket.send(textEncoder.encode(Command.INPUT + data)); + const payload = new Uint8Array(data.length * 3 + 1); + payload[0] = Command.INPUT.charCodeAt(0); + const stats = textEncoder.encodeInto(data, payload.subarray(1)); + socket.send(payload.subarray(0, (stats.written as number) + 1)); } else { const payload = new Uint8Array(data.length + 1); payload[0] = Command.INPUT.charCodeAt(0); @@ -320,6 +324,7 @@ export class Xterm { this.zmodemAddon = new ZmodemAddon({ zmodem: prefs.enableZmodem, trzsz: prefs.enableTrzsz, + windows: prefs.isWindows, onSend: this.sendCb, sender: this.sendData, writer: this.writeData, @@ -370,6 +375,9 @@ export class Xterm { this.titleFixed = value; document.title = value; break; + case 'isWindows': + if (value) console.log('[ttyd] is windows'); + break; default: console.log(`[ttyd] option: ${key}=${JSON.stringify(value)}`); if (terminal.options[key] instanceof Object) { diff --git a/html/yarn.lock b/html/yarn.lock index 6b69dd9..b94e479 100644 --- a/html/yarn.lock +++ b/html/yarn.lock @@ -9232,13 +9232,13 @@ __metadata: languageName: node linkType: hard -"trzsz@npm:^0.4.3": - version: 0.4.3 - resolution: "trzsz@npm:0.4.3" +"trzsz@npm:^1.1.0": + version: 1.1.0 + resolution: "trzsz@npm:1.1.0" bin: trz: bin/trz.js tsz: bin/tsz.js - checksum: b7c768b40eac4a0a3ea866bc79c1912191feb4315de5c752720cce4f712b18ea0ced8b16ac19ef873db915b462ac9a3c00e975d8a0d6d6e28fe850f38e40ca11 + checksum: 9d01e42984299b8fe79adcd67a227e86bed4953a70b0b02bf777e0e99389adc57d2a1b495964dbec365c84a9bd781f81d6d974ac2e1df3c208ffbe9757ace1a3 languageName: node linkType: hard @@ -9307,7 +9307,7 @@ __metadata: style-loader: ^3.3.1 terser-webpack-plugin: ^5.3.6 through2: ^4.0.2 - trzsz: ^0.4.3 + trzsz: ^1.1.0 ts-loader: ^9.4.1 typescript: ^4.8.4 util: ^0.12.5 @@ -9413,11 +9413,11 @@ __metadata: "typescript@patch:typescript@^4.8.4#~builtin": version: 4.8.4 - resolution: "typescript@patch:typescript@npm%3A4.8.4#~builtin::version=4.8.4&hash=0102e9" + resolution: "typescript@patch:typescript@npm%3A4.8.4#~builtin::version=4.8.4&hash=1a91c8" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 301459fc3eb3b1a38fe91bf96d98eb55da88a9cb17b4ef80b4d105d620f4d547ba776cc27b44cc2ef58b66eda23fe0a74142feb5e79a6fb99f54fc018a696afa + checksum: c981e82b77a5acdcc4e69af9c56cdecf5b934a87a08e7b52120596701e389a878b8e3f860e73ffb287bf649cc47a8c741262ce058148f71de4cdd88bb9c75153 languageName: node linkType: hard diff --git a/src/server.c b/src/server.c index 1556d71..cc398bc 100644 --- a/src/server.c +++ b/src/server.c @@ -334,6 +334,10 @@ int main(int argc, char **argv) { struct json_object *client_prefs = json_object_new_object(); +#ifdef _WIN32 + json_object_object_add(client_prefs, "isWindows", json_object_new_boolean(true)); +#endif + // parse command line options int c; while ((c = getopt_long(start, argv, opt_string, options, NULL)) != -1) {