diff --git a/src/connect.ts b/src/connect.ts index cf73010..b30595e 100644 --- a/src/connect.ts +++ b/src/connect.ts @@ -21,7 +21,7 @@ export const connect = async (button: InstallButton) => { } try { - await port.open({ baudRate: 115200 }); + await port.open({ baudRate: 115200, bufferSize: 8192 }); } catch (err: any) { alert(err.message); return; diff --git a/src/install-dialog.ts b/src/install-dialog.ts index 1c22529..95bb9e4 100644 --- a/src/install-dialog.ts +++ b/src/install-dialog.ts @@ -923,13 +923,13 @@ export class EwtInstallDialog extends LitElement { if (state.state === FlashStateType.FINISHED) { sleep(100) // Flashing closes the port - .then(() => this.port.open({ baudRate: 115200 })) + .then(() => this.port.open({ baudRate: 115200, bufferSize: 8192 })) .then(() => this._initialize(true)) .then(() => this.requestUpdate()); } else if (state.state === FlashStateType.ERROR) { sleep(100) // Flashing closes the port - .then(() => this.port.open({ baudRate: 115200 })); + .then(() => this.port.open({ baudRate: 115200, bufferSize: 8192 })); } }, this.port, diff --git a/src/util/console-color.ts b/src/util/console-color.ts index b6e1934..af20534 100644 --- a/src/util/console-color.ts +++ b/src/util/console-color.ts @@ -6,6 +6,7 @@ interface ConsoleState { foregroundColor: string | null; backgroundColor: string | null; carriageReturn: boolean; + lines: string[]; secret: boolean; } @@ -18,6 +19,7 @@ export class ColoredConsole { foregroundColor: null, backgroundColor: null, carriageReturn: false, + lines: [], secret: false, }; @@ -27,26 +29,13 @@ export class ColoredConsole { return this.targetElement.innerText; } - addLine(line: string) { + processLine(line: string): Element { // @ts-expect-error const re = /(?:\033|\\033)(?:\[(.*?)[@-~]|\].*?(?:\007|\033\\))/g; let i = 0; - if (this.state.carriageReturn) { - if (line !== "\n") { - // don't remove if \r\n - this.targetElement.removeChild(this.targetElement.lastChild!); - } - this.state.carriageReturn = false; - } - - if (line.includes("\r")) { - this.state.carriageReturn = true; - } - const lineSpan = document.createElement("span"); lineSpan.classList.add("line"); - this.targetElement.appendChild(lineSpan); const addSpan = (content: string) => { if (content === "") return; @@ -179,17 +168,52 @@ export class ColoredConsole { } } } + addSpan(line.substring(i)); + return lineSpan; + } + + processLines() { const atBottom = this.targetElement.scrollTop > this.targetElement.scrollHeight - this.targetElement.offsetHeight - 50; + const prevCarriageReturn = this.state.carriageReturn; + const fragment = document.createDocumentFragment(); - addSpan(line.substring(i)); + if (this.state.lines.length == 0) { + return; + } + + for (const line of this.state.lines) { + if (this.state.carriageReturn && line !== "\n") { + if (fragment.childElementCount) { + fragment.removeChild(fragment.lastChild!); + } + } + fragment.appendChild(this.processLine(line)); + this.state.carriageReturn = line.includes("\r"); + } + + if (prevCarriageReturn && this.state.lines[0] !== "\n") { + this.targetElement.replaceChild(fragment, this.targetElement.lastChild!); + } else { + this.targetElement.appendChild(fragment); + } + + this.state.lines = []; // Keep scroll at bottom if (atBottom) { this.targetElement.scrollTop = this.targetElement.scrollHeight; } } + + addLine(line: string) { + // Processing of lines is deferred for performance reasons + if (this.state.lines.length == 0) { + setTimeout(() => this.processLines(), 0); + } + this.state.lines.push(line); + } } export const coloredConsoleStyles = ` diff --git a/src/util/line-break-transformer.ts b/src/util/line-break-transformer.ts index 353d83d..10619ed 100644 --- a/src/util/line-break-transformer.ts +++ b/src/util/line-break-transformer.ts @@ -8,7 +8,7 @@ export class LineBreakTransformer implements Transformer { // Append new chunks to existing chunks. this.chunks += chunk; // For each line breaks in chunks, send the parsed lines out. - const lines = this.chunks.split("\r\n"); + const lines = this.chunks.split(/\r?\n/); this.chunks = lines.pop()!; lines.forEach((line) => controller.enqueue(line + "\r\n")); }