mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-25 05:04:19 +01:00
html: add option to toggle trzsz
This commit is contained in:
@@ -42,6 +42,7 @@ export interface ClientOptions {
|
||||
disableLeaveAlert: boolean;
|
||||
disableResizeOverlay: boolean;
|
||||
enableZmodem: boolean;
|
||||
enableTrzsz: boolean;
|
||||
enableSixel: boolean;
|
||||
titleFixed: string;
|
||||
}
|
||||
@@ -65,6 +66,7 @@ interface Props {
|
||||
|
||||
interface State {
|
||||
zmodem: boolean;
|
||||
trzsz: boolean;
|
||||
}
|
||||
|
||||
export class Xterm extends Component<Props, State> {
|
||||
@@ -119,10 +121,18 @@ export class Xterm extends Component<Props, State> {
|
||||
window.removeEventListener('beforeunload', this.onWindowUnload);
|
||||
}
|
||||
|
||||
render({ id }: Props, { zmodem }: State) {
|
||||
render({ id }: Props, { zmodem, trzsz }: State) {
|
||||
return (
|
||||
<div id={id} ref={c => (this.container = c)}>
|
||||
{zmodem && <ZmodemAddon callback={this.zmodemCb} sender={this.sendData} writer={this.writeData} />}
|
||||
{(zmodem || trzsz) && (
|
||||
<ZmodemAddon
|
||||
zmodem={zmodem}
|
||||
trzsz={trzsz}
|
||||
callback={this.zmodemCb}
|
||||
sender={this.sendData}
|
||||
writer={this.writeData}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -353,6 +363,12 @@ export class Xterm extends Component<Props, State> {
|
||||
console.log(`[ttyd] Zmodem enabled`);
|
||||
}
|
||||
break;
|
||||
case 'enableTrzsz':
|
||||
if (value) {
|
||||
this.setState({ trzsz: true });
|
||||
console.log(`[ttyd] trzsz enabled`);
|
||||
}
|
||||
break;
|
||||
case 'enableSixel':
|
||||
if (value) {
|
||||
const imageWorkerUrl = window.URL.createObjectURL(
|
||||
@@ -400,6 +416,7 @@ export class Xterm extends Component<Props, State> {
|
||||
if (this.opened) {
|
||||
terminal.reset();
|
||||
terminal.resize(dims.cols, dims.rows);
|
||||
terminal.options.disableStdin = false;
|
||||
overlayAddon.showOverlay('Reconnected', 300);
|
||||
} else {
|
||||
this.opened = true;
|
||||
@@ -416,6 +433,7 @@ export class Xterm extends Component<Props, State> {
|
||||
|
||||
const { refreshToken, connect, doReconnect, overlayAddon } = this;
|
||||
overlayAddon.showOverlay('Connection Closed', null);
|
||||
this.setState({ zmodem: false, trzsz: false });
|
||||
|
||||
// 1000: CLOSE_NORMAL
|
||||
if (event.code !== 1000 && doReconnect) {
|
||||
|
||||
@@ -8,6 +8,8 @@ import { TrzszFilter } from 'trzsz';
|
||||
import { Modal } from '../modal';
|
||||
|
||||
interface Props {
|
||||
zmodem: boolean;
|
||||
trzsz: boolean;
|
||||
callback: (addon: ZmodemAddon) => void;
|
||||
sender: (data: string | Uint8Array) => void;
|
||||
writer: (data: string | Uint8Array) => void;
|
||||
@@ -19,9 +21,10 @@ interface State {
|
||||
|
||||
export class ZmodemAddon extends Component<Props, State> implements ITerminalAddon {
|
||||
private terminal: Terminal | undefined;
|
||||
private keyDispose: IDisposable | undefined;
|
||||
private disposables: IDisposable[] = [];
|
||||
private sentry: Zmodem.Sentry;
|
||||
private session: Zmodem.Session;
|
||||
private denier: () => void;
|
||||
private trzszFilter: TrzszFilter;
|
||||
|
||||
constructor(props: Props) {
|
||||
@@ -43,100 +46,91 @@ export class ZmodemAddon extends Component<Props, State> implements ITerminalAdd
|
||||
this.props.callback(this);
|
||||
}
|
||||
|
||||
activate(terminal: Terminal): void {
|
||||
this.terminal = terminal;
|
||||
this.zmodemInit();
|
||||
this.trzszInit();
|
||||
componentWillUnmount() {
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
dispose(): void {}
|
||||
activate(terminal: Terminal) {
|
||||
this.terminal = terminal;
|
||||
if (this.props.zmodem) this.zmodemInit();
|
||||
if (this.props.trzsz) this.trzszInit();
|
||||
}
|
||||
|
||||
dispose() {
|
||||
for (const d of this.disposables) {
|
||||
d.dispose();
|
||||
}
|
||||
this.disposables.length = 0;
|
||||
}
|
||||
|
||||
consume(data: ArrayBuffer) {
|
||||
try {
|
||||
this.trzszFilter.processServerOutput(data);
|
||||
if (this.props.trzsz) {
|
||||
this.trzszFilter.processServerOutput(data);
|
||||
} else {
|
||||
this.sentry.consume(data);
|
||||
}
|
||||
} catch (e) {
|
||||
this.handleError(e, 'consume');
|
||||
}
|
||||
}
|
||||
|
||||
@bind
|
||||
private handleError(e: Error, reason: string) {
|
||||
console.error(`[ttyd] zmodem ${reason}: `, e);
|
||||
this.zmodemReset();
|
||||
}
|
||||
|
||||
@bind
|
||||
private trzszInit() {
|
||||
this.trzszFilter = new TrzszFilter({
|
||||
writeToTerminal: data => this.trzszWrite(data),
|
||||
sendToServer: data => this.trzszSend(data),
|
||||
terminalColumns: this.terminal.cols,
|
||||
});
|
||||
this.terminal.onResize(size => this.trzszFilter.setTerminalColumns(size.cols));
|
||||
}
|
||||
|
||||
@bind
|
||||
private trzszWrite(data: string | ArrayBuffer | Uint8Array | Blob) {
|
||||
if (this.trzszFilter.isTransferringFiles()) {
|
||||
this.props.writer(data as string);
|
||||
} else {
|
||||
this.sentry.consume(data as ArrayBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@bind
|
||||
private trzszSend(data: string | Uint8Array) {
|
||||
this.props.sender(data);
|
||||
}
|
||||
|
||||
@bind
|
||||
private zmodemInit() {
|
||||
this.session = null;
|
||||
this.sentry = new Zmodem.Sentry({
|
||||
to_terminal: octets => this.zmodemWrite(octets),
|
||||
sender: octets => this.zmodemSend(octets),
|
||||
on_retract: () => this.zmodemReset(),
|
||||
on_detect: detection => this.zmodemDetect(detection),
|
||||
});
|
||||
}
|
||||
|
||||
@bind
|
||||
private zmodemReset() {
|
||||
private reset() {
|
||||
this.terminal.options.disableStdin = false;
|
||||
|
||||
if (this.keyDispose) {
|
||||
this.keyDispose.dispose();
|
||||
this.keyDispose = null;
|
||||
}
|
||||
this.zmodemInit();
|
||||
|
||||
this.terminal.focus();
|
||||
}
|
||||
|
||||
@bind
|
||||
private zmodemWrite(data: ArrayBuffer): void {
|
||||
this.props.writer(new Uint8Array(data));
|
||||
private handleError(e: Error, reason: string) {
|
||||
console.error(`[ttyd] zmodem ${reason}: `, e);
|
||||
this.reset();
|
||||
}
|
||||
|
||||
@bind
|
||||
private zmodemSend(data: ArrayLike<number>): void {
|
||||
this.props.sender(new Uint8Array(data));
|
||||
private trzszInit() {
|
||||
const { writer, sender, zmodem } = this.props;
|
||||
const { terminal } = this;
|
||||
this.trzszFilter = new TrzszFilter({
|
||||
writeToTerminal: data => {
|
||||
if (!this.trzszFilter.isTransferringFiles() && zmodem) {
|
||||
this.sentry.consume(data);
|
||||
} else {
|
||||
writer(typeof data === 'string' ? data : new Uint8Array(data as ArrayBuffer));
|
||||
}
|
||||
},
|
||||
sendToServer: data => sender(data),
|
||||
terminalColumns: terminal.cols,
|
||||
});
|
||||
this.disposables.push(terminal.onResize(size => this.trzszFilter.setTerminalColumns(size.cols)));
|
||||
}
|
||||
|
||||
@bind
|
||||
private zmodemInit() {
|
||||
const { writer, sender } = this.props;
|
||||
const { terminal, reset, zmodemDetect } = this;
|
||||
this.session = null;
|
||||
this.sentry = new Zmodem.Sentry({
|
||||
to_terminal: octets => writer(new Uint8Array(octets)),
|
||||
sender: octets => sender(new Uint8Array(octets)),
|
||||
on_retract: () => reset(),
|
||||
on_detect: detection => zmodemDetect(detection),
|
||||
});
|
||||
this.disposables.push(terminal.onKey(e => {
|
||||
const event = e.domEvent;
|
||||
if (event.ctrlKey && event.key === 'c') {
|
||||
if (this.denier) this.denier();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@bind
|
||||
private zmodemDetect(detection: Zmodem.Detection): void {
|
||||
const { terminal, receiveFile, zmodemReset } = this;
|
||||
const { terminal, receiveFile, reset } = this;
|
||||
terminal.options.disableStdin = true;
|
||||
|
||||
this.keyDispose = terminal.onKey(e => {
|
||||
const event = e.domEvent;
|
||||
if (event.ctrlKey && event.key === 'c') {
|
||||
detection.deny();
|
||||
}
|
||||
});
|
||||
|
||||
this.denier = () => detection.deny();
|
||||
this.session = detection.confirm();
|
||||
this.session.on('session_end', zmodemReset);
|
||||
this.session.on('session_end', () => reset());
|
||||
|
||||
if (this.session.type === 'send') {
|
||||
this.setState({ modal: true });
|
||||
|
||||
6102
src/html.h
generated
6102
src/html.h
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user