From 1bd8a937bafedd87f84fb7d1d344be7a172696c2 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sun, 12 Jul 2026 14:49:15 +0530 Subject: [PATCH 1/6] chore: update the xtermjs to v6 - updated the themes with new fields - added option to turn off the xtermjs scrollabr - fixed touch related stuff introduced in new version --- bun.lock | 35 ++-- package-lock.json | 104 +++++------ package.json | 16 +- src/components/terminal/terminal.js | 27 +++ src/components/terminal/terminalDefaults.js | 1 + src/components/terminal/terminalManager.js | 11 +- .../terminal/terminalThemeManager.js | 171 ++++++++++++++++-- .../terminal/terminalTouchScrolling.js | 44 +++-- .../terminal/terminalTouchSelection.js | 18 +- src/settings/terminalSettings.js | 18 +- 10 files changed, 304 insertions(+), 141 deletions(-) diff --git a/bun.lock b/bun.lock index e8e62adcd..9a60acd1c 100644 --- a/bun.lock +++ b/bun.lock @@ -43,14 +43,14 @@ "@lezer/highlight": "^1.2.3", "@lezer/lr": "^1.4.7", "@ungap/custom-elements": "^1.3.0", - "@xterm/addon-attach": "^0.11.0", - "@xterm/addon-fit": "^0.10.0", - "@xterm/addon-image": "^0.8.0", - "@xterm/addon-search": "^0.15.0", - "@xterm/addon-unicode11": "^0.8.0", - "@xterm/addon-web-links": "^0.11.0", - "@xterm/addon-webgl": "^0.18.0", - "@xterm/xterm": "^5.5.0", + "@xterm/addon-attach": "^0.12.0", + "@xterm/addon-fit": "^0.11.0", + "@xterm/addon-image": "^0.9.0", + "@xterm/addon-search": "^0.16.0", + "@xterm/addon-unicode11": "^0.9.0", + "@xterm/addon-web-links": "^0.12.0", + "@xterm/addon-webgl": "^0.19.0", + "@xterm/xterm": "^6.0.0", "acorn": "^8.16.0", "autosize": "^6.0.1", "codemirror": "^6.0.2", @@ -110,6 +110,7 @@ "cordova-plugin-advanced-http": "file:src/plugins/cordova-plugin-advanced-http", "cordova-plugin-browser": "file:src/plugins/browser", "cordova-plugin-buildinfo": "file:src/plugins/cordova-plugin-buildinfo", + "cordova-plugin-crashhandler": "file:src/plugins/cordova-plugin-crashhandler", "cordova-plugin-device": "^2.1.0", "cordova-plugin-file": "^8.1.3", "cordova-plugin-ftp": "file:src/plugins/ftp", @@ -757,21 +758,21 @@ "@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], - "@xterm/addon-attach": ["@xterm/addon-attach@0.11.0", "", { "peerDependencies": { "@xterm/xterm": "^5.0.0" } }, "sha512-JboCN0QAY6ZLY/SSB/Zl2cQ5zW1Eh4X3fH7BnuR1NB7xGRhzbqU2Npmpiw/3zFlxDaU88vtKzok44JKi2L2V2Q=="], + "@xterm/addon-attach": ["@xterm/addon-attach@0.12.0", "", {}, "sha512-1lxvXM4JYSm60lbFmE8WMOy2oF2ip3Ye8jWorSAmwy7x8FiC53netEJ5RguL8+FSRj79MUQsNCb2hprY2QA2ig=="], - "@xterm/addon-fit": ["@xterm/addon-fit@0.10.0", "", { "peerDependencies": { "@xterm/xterm": "^5.0.0" } }, "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ=="], + "@xterm/addon-fit": ["@xterm/addon-fit@0.11.0", "", {}, "sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g=="], - "@xterm/addon-image": ["@xterm/addon-image@0.8.0", "", { "peerDependencies": { "@xterm/xterm": "^5.2.0" } }, "sha512-b/dqpFn3jUad2pUP5UpF4scPIh0WdxRQL/1qyiahGfUI85XZTCXo0py9G6AcOR2QYUw8eJ8EowGspT7BQcgw6A=="], + "@xterm/addon-image": ["@xterm/addon-image@0.9.0", "", {}, "sha512-oYWA8/QAr5/Emwl1xL7WCoOqeG3IZfpzEz/OVq1j4Oi9934TQmHiyubClikRf0D/jL3JNiNuz/Lsqx0kXQ02BA=="], - "@xterm/addon-search": ["@xterm/addon-search@0.15.0", "", { "peerDependencies": { "@xterm/xterm": "^5.0.0" } }, "sha512-ZBZKLQ+EuKE83CqCmSSz5y1tx+aNOCUaA7dm6emgOX+8J9H1FWXZyrKfzjwzV+V14TV3xToz1goIeRhXBS5qjg=="], + "@xterm/addon-search": ["@xterm/addon-search@0.16.0", "", {}, "sha512-9OeuBFu0/uZJPu+9AHKY6g/w0Czyb/Ut0A5t79I4ULoU4IfU5BEpPFVGQxP4zTTMdfZEYkVIRYbHBX1xWwjeSA=="], - "@xterm/addon-unicode11": ["@xterm/addon-unicode11@0.8.0", "", { "peerDependencies": { "@xterm/xterm": "^5.0.0" } }, "sha512-LxinXu8SC4OmVa6FhgwsVCBZbr8WoSGzBl2+vqe8WcQ6hb1r6Gj9P99qTNdPiFPh4Ceiu2pC8xukZ6+2nnh49Q=="], + "@xterm/addon-unicode11": ["@xterm/addon-unicode11@0.9.0", "", {}, "sha512-FxDnYcyuXhNl+XSqGZL/t0U9eiNb/q3EWT5rYkQT/zuig8Gz/VagnQANKHdDWFM2lTMk9ly0EFQxxxtZUoRetw=="], - "@xterm/addon-web-links": ["@xterm/addon-web-links@0.11.0", "", { "peerDependencies": { "@xterm/xterm": "^5.0.0" } }, "sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q=="], + "@xterm/addon-web-links": ["@xterm/addon-web-links@0.12.0", "", {}, "sha512-4Smom3RPyVp7ZMYOYDoC/9eGJJJqYhnPLGGqJ6wOBfB8VxPViJNSKdgRYb8NpaM6YSelEKbA2SStD7lGyqaobw=="], - "@xterm/addon-webgl": ["@xterm/addon-webgl@0.18.0", "", { "peerDependencies": { "@xterm/xterm": "^5.0.0" } }, "sha512-xCnfMBTI+/HKPdRnSOHaJDRqEpq2Ugy8LEj9GiY4J3zJObo3joylIFaMvzBwbYRg8zLtkO0KQaStCeSfoaI2/w=="], + "@xterm/addon-webgl": ["@xterm/addon-webgl@0.19.0", "", {}, "sha512-b3fMOsyLVuCeNJWxolACEUED0vm7qC0cy4wRvf3oURSzDTYVQiGPhTnhWZwIHdvC48Y+oLhvYXnY4XDXPoJo6A=="], - "@xterm/xterm": ["@xterm/xterm@5.5.0", "", {}, "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A=="], + "@xterm/xterm": ["@xterm/xterm@6.0.0", "", {}, "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg=="], "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="], @@ -1025,6 +1026,8 @@ "cordova-plugin-buildinfo": ["cordova-plugin-buildinfo@file:src/plugins/cordova-plugin-buildinfo", { "devDependencies": { "jshint": "^2.6.0" } }], + "cordova-plugin-crashhandler": ["cordova-plugin-crashhandler@file:src/plugins/cordova-plugin-crashhandler", {}], + "cordova-plugin-device": ["cordova-plugin-device@2.1.0", "", {}, "sha512-FU0Lw1jZpuKOgG4v80LrfMAOIMCGfAVPumn7AwaX9S1iU/X3OPZUyoKUgP09q4bxL35IeNPkqNWVKYduAXZ1sg=="], "cordova-plugin-file": ["cordova-plugin-file@8.1.3", "", {}, "sha512-KlnP3CapNIsKncoWV5lYcIFYDPl0aZ1J3AH3QESlQX1Cb6Ct0p6GrAUvINyrFsjPbWHj8i0b6la6udVsghbATg=="], diff --git a/package-lock.json b/package-lock.json index 3a84e30e9..50540a937 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,14 +47,14 @@ "@lezer/highlight": "^1.2.3", "@lezer/lr": "^1.4.7", "@ungap/custom-elements": "^1.3.0", - "@xterm/addon-attach": "^0.11.0", - "@xterm/addon-fit": "^0.10.0", - "@xterm/addon-image": "^0.8.0", - "@xterm/addon-search": "^0.15.0", - "@xterm/addon-unicode11": "^0.8.0", - "@xterm/addon-web-links": "^0.11.0", - "@xterm/addon-webgl": "^0.18.0", - "@xterm/xterm": "^5.5.0", + "@xterm/addon-attach": "^0.12.0", + "@xterm/addon-fit": "^0.11.0", + "@xterm/addon-image": "^0.9.0", + "@xterm/addon-search": "^0.16.0", + "@xterm/addon-unicode11": "^0.9.0", + "@xterm/addon-web-links": "^0.12.0", + "@xterm/addon-webgl": "^0.19.0", + "@xterm/xterm": "^6.0.0", "acorn": "^8.16.0", "autosize": "^6.0.1", "codemirror": "^6.0.2", @@ -6043,73 +6043,55 @@ } }, "node_modules/@xterm/addon-attach": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-attach/-/addon-attach-0.11.0.tgz", - "integrity": "sha512-JboCN0QAY6ZLY/SSB/Zl2cQ5zW1Eh4X3fH7BnuR1NB7xGRhzbqU2Npmpiw/3zFlxDaU88vtKzok44JKi2L2V2Q==", - "license": "MIT", - "peerDependencies": { - "@xterm/xterm": "^5.0.0" - } + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-attach/-/addon-attach-0.12.0.tgz", + "integrity": "sha512-1lxvXM4JYSm60lbFmE8WMOy2oF2ip3Ye8jWorSAmwy7x8FiC53netEJ5RguL8+FSRj79MUQsNCb2hprY2QA2ig==", + "license": "MIT" }, "node_modules/@xterm/addon-fit": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz", - "integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==", - "license": "MIT", - "peerDependencies": { - "@xterm/xterm": "^5.0.0" - } + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.11.0.tgz", + "integrity": "sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==", + "license": "MIT" }, "node_modules/@xterm/addon-image": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-image/-/addon-image-0.8.0.tgz", - "integrity": "sha512-b/dqpFn3jUad2pUP5UpF4scPIh0WdxRQL/1qyiahGfUI85XZTCXo0py9G6AcOR2QYUw8eJ8EowGspT7BQcgw6A==", - "license": "MIT", - "peerDependencies": { - "@xterm/xterm": "^5.2.0" - } + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-image/-/addon-image-0.9.0.tgz", + "integrity": "sha512-oYWA8/QAr5/Emwl1xL7WCoOqeG3IZfpzEz/OVq1j4Oi9934TQmHiyubClikRf0D/jL3JNiNuz/Lsqx0kXQ02BA==", + "license": "MIT" }, "node_modules/@xterm/addon-search": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.15.0.tgz", - "integrity": "sha512-ZBZKLQ+EuKE83CqCmSSz5y1tx+aNOCUaA7dm6emgOX+8J9H1FWXZyrKfzjwzV+V14TV3xToz1goIeRhXBS5qjg==", - "license": "MIT", - "peerDependencies": { - "@xterm/xterm": "^5.0.0" - } + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.16.0.tgz", + "integrity": "sha512-9OeuBFu0/uZJPu+9AHKY6g/w0Czyb/Ut0A5t79I4ULoU4IfU5BEpPFVGQxP4zTTMdfZEYkVIRYbHBX1xWwjeSA==", + "license": "MIT" }, "node_modules/@xterm/addon-unicode11": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.8.0.tgz", - "integrity": "sha512-LxinXu8SC4OmVa6FhgwsVCBZbr8WoSGzBl2+vqe8WcQ6hb1r6Gj9P99qTNdPiFPh4Ceiu2pC8xukZ6+2nnh49Q==", - "license": "MIT", - "peerDependencies": { - "@xterm/xterm": "^5.0.0" - } + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.9.0.tgz", + "integrity": "sha512-FxDnYcyuXhNl+XSqGZL/t0U9eiNb/q3EWT5rYkQT/zuig8Gz/VagnQANKHdDWFM2lTMk9ly0EFQxxxtZUoRetw==", + "license": "MIT" }, "node_modules/@xterm/addon-web-links": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.11.0.tgz", - "integrity": "sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q==", - "license": "MIT", - "peerDependencies": { - "@xterm/xterm": "^5.0.0" - } + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.12.0.tgz", + "integrity": "sha512-4Smom3RPyVp7ZMYOYDoC/9eGJJJqYhnPLGGqJ6wOBfB8VxPViJNSKdgRYb8NpaM6YSelEKbA2SStD7lGyqaobw==", + "license": "MIT" }, "node_modules/@xterm/addon-webgl": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.18.0.tgz", - "integrity": "sha512-xCnfMBTI+/HKPdRnSOHaJDRqEpq2Ugy8LEj9GiY4J3zJObo3joylIFaMvzBwbYRg8zLtkO0KQaStCeSfoaI2/w==", - "license": "MIT", - "peerDependencies": { - "@xterm/xterm": "^5.0.0" - } + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.19.0.tgz", + "integrity": "sha512-b3fMOsyLVuCeNJWxolACEUED0vm7qC0cy4wRvf3oURSzDTYVQiGPhTnhWZwIHdvC48Y+oLhvYXnY4XDXPoJo6A==", + "license": "MIT" }, "node_modules/@xterm/xterm": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz", - "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==", - "license": "MIT" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-6.0.0.tgz", + "integrity": "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg==", + "license": "MIT", + "workspaces": [ + "addons/*" + ] }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", diff --git a/package.json b/package.json index c2a0cd908..39fc2f685 100644 --- a/package.json +++ b/package.json @@ -152,14 +152,14 @@ "@lezer/highlight": "^1.2.3", "@lezer/lr": "^1.4.7", "@ungap/custom-elements": "^1.3.0", - "@xterm/addon-attach": "^0.11.0", - "@xterm/addon-fit": "^0.10.0", - "@xterm/addon-image": "^0.8.0", - "@xterm/addon-search": "^0.15.0", - "@xterm/addon-unicode11": "^0.8.0", - "@xterm/addon-web-links": "^0.11.0", - "@xterm/addon-webgl": "^0.18.0", - "@xterm/xterm": "^5.5.0", + "@xterm/addon-attach": "^0.12.0", + "@xterm/addon-fit": "^0.11.0", + "@xterm/addon-image": "^0.9.0", + "@xterm/addon-search": "^0.16.0", + "@xterm/addon-unicode11": "^0.9.0", + "@xterm/addon-web-links": "^0.12.0", + "@xterm/addon-webgl": "^0.19.0", + "@xterm/xterm": "^6.0.0", "acorn": "^8.16.0", "autosize": "^6.0.1", "codemirror": "^6.0.2", diff --git a/src/components/terminal/terminal.js b/src/components/terminal/terminal.js index 36907a66f..a1ab88f9c 100644 --- a/src/components/terminal/terminal.js +++ b/src/components/terminal/terminal.js @@ -557,6 +557,10 @@ export default class TerminalComponent { try { // Open first to ensure a stable renderer is attached this.terminal.open(container); + this.updateBackgroundColor(); + this.updateScrollbarVisibility( + getTerminalSettings().showScrollbar !== false, + ); // Renderer selection: 'canvas' (default core), 'webgl', or 'auto' if ( @@ -983,6 +987,29 @@ export default class TerminalComponent { } this.options.theme = { ...this.options.theme, ...theme }; this.terminal.options.theme = this.options.theme; + this.updateBackgroundColor(); + } + + /** Keep xterm's viewport chrome aligned with the active theme. */ + updateBackgroundColor() { + const background = this.terminal?.options.theme?.background; + if (!background) return; + + if (this.container) this.container.style.background = background; + if (this.terminal?.element) { + this.terminal.element.style.backgroundColor = background; + } + } + + /** + * Toggle xterm.js 6's custom scrollbar without disabling scroll APIs. + * @param {boolean} visible Whether the scrollbar should be shown + */ + updateScrollbarVisibility(visible) { + this.terminal?.element?.classList.toggle( + "terminal-scrollbar-hidden", + visible === false, + ); } /** diff --git a/src/components/terminal/terminalDefaults.js b/src/components/terminal/terminalDefaults.js index 2a631cad1..c3e3d9be7 100644 --- a/src/components/terminal/terminalDefaults.js +++ b/src/components/terminal/terminalDefaults.js @@ -8,6 +8,7 @@ export const DEFAULT_TERMINAL_SETTINGS = { cursorStyle: "block", cursorInactiveStyle: "outline", scrollback: 1000, + showScrollbar: true, theme: "dark", tabStopWidth: 4, convertEol: true, diff --git a/src/components/terminal/terminalManager.js b/src/components/terminal/terminalManager.js index fb8e1ba8f..01923d6e0 100644 --- a/src/components/terminal/terminalManager.js +++ b/src/components/terminal/terminalManager.js @@ -1005,9 +1005,18 @@ class TerminalManager { touch-action: none; } - .terminal-content .xterm-viewport { + .terminal-content .xterm-viewport, + .terminal-content .xterm-scrollable-element { + background-color: transparent !important; overscroll-behavior: none; } + + .terminal-content + .terminal-scrollbar-hidden + .xterm-scrollable-element + > .scrollbar.vertical { + display: none !important; + } `; } diff --git a/src/components/terminal/terminalThemeManager.js b/src/components/terminal/terminalThemeManager.js index 0654600c1..c186a4a67 100644 --- a/src/components/terminal/terminalThemeManager.js +++ b/src/components/terminal/terminalThemeManager.js @@ -11,7 +11,13 @@ class TerminalThemeManager { foreground: "#f5f5f5", cursor: "#4285f4", cursorAccent: "#23272a", - selection: "#ffffff40", + selectionBackground: "#ffffff40", + selectionForeground: "#f5f5f5", + selectionInactiveBackground: "#ffffff40", + scrollbarSliderBackground: "#f5f5f533", + scrollbarSliderHoverBackground: "#f5f5f566", + scrollbarSliderActiveBackground: "#f5f5f580", + overviewRulerBorder: "#2d3134", black: "#181b1e", red: "#f07178", green: "#c3e88d", @@ -34,7 +40,13 @@ class TerminalThemeManager { foreground: "#0f1729", cursor: "#3b82f6", cursorAccent: "#ffffff", - selection: "#e2e8f0", + selectionBackground: "#cbd5e1", + selectionForeground: "#0f1729", + selectionInactiveBackground: "#cbd5e1", + scrollbarSliderBackground: "#0f172933", + scrollbarSliderHoverBackground: "#0f172966", + scrollbarSliderActiveBackground: "#0f172980", + overviewRulerBorder: "#475569", black: "#1e293b", red: "#dc2626", green: "#16a34a", @@ -57,7 +69,13 @@ class TerminalThemeManager { foreground: "#839496", cursor: "#839496", cursorAccent: "#002b36", - selection: "#073642", + selectionBackground: "#073642", + selectionForeground: "#839496", + selectionInactiveBackground: "#073642", + scrollbarSliderBackground: "#83949633", + scrollbarSliderHoverBackground: "#83949666", + scrollbarSliderActiveBackground: "#83949680", + overviewRulerBorder: "#002b36", black: "#073642", red: "#dc322f", green: "#859900", @@ -80,7 +98,13 @@ class TerminalThemeManager { foreground: "#657b83", cursor: "#657b83", cursorAccent: "#fdf6e3", - selection: "#eee8d5", + selectionBackground: "#d6cda9", + selectionForeground: "#657b83", + selectionInactiveBackground: "#d6cda9", + scrollbarSliderBackground: "#657b8333", + scrollbarSliderHoverBackground: "#657b8366", + scrollbarSliderActiveBackground: "#657b8380", + overviewRulerBorder: "#002b36", black: "#073642", red: "#dc322f", green: "#859900", @@ -103,7 +127,13 @@ class TerminalThemeManager { foreground: "#f8f8f2", cursor: "#f8f8f0", cursorAccent: "#272822", - selection: "#49483e", + selectionBackground: "#49483e", + selectionForeground: "#f8f8f2", + selectionInactiveBackground: "#49483e", + scrollbarSliderBackground: "#f8f8f233", + scrollbarSliderHoverBackground: "#f8f8f266", + scrollbarSliderActiveBackground: "#f8f8f280", + overviewRulerBorder: "#75715e", black: "#272822", red: "#f92672", green: "#a6e22e", @@ -126,7 +156,13 @@ class TerminalThemeManager { foreground: "#f8f8f2", cursor: "#f8f8f0", cursorAccent: "#282a36", - selection: "#44475a", + selectionBackground: "#44475a", + selectionForeground: "#f8f8f2", + selectionInactiveBackground: "#44475a", + scrollbarSliderBackground: "#f8f8f233", + scrollbarSliderHoverBackground: "#f8f8f266", + scrollbarSliderActiveBackground: "#f8f8f280", + overviewRulerBorder: "#4d4d4d", black: "#000000", red: "#ff5555", green: "#50fa7b", @@ -149,7 +185,13 @@ class TerminalThemeManager { foreground: "#d8dee9", cursor: "#d8dee9", cursorAccent: "#2e3440", - selection: "#434c5e", + selectionBackground: "#434c5e", + selectionForeground: "#d8dee9", + selectionInactiveBackground: "#434c5e", + scrollbarSliderBackground: "#d8dee933", + scrollbarSliderHoverBackground: "#d8dee966", + scrollbarSliderActiveBackground: "#d8dee980", + overviewRulerBorder: "#4c566a", black: "#3b4252", red: "#bf616a", green: "#a3be8c", @@ -172,7 +214,13 @@ class TerminalThemeManager { foreground: "#ebdbb2", cursor: "#ebdbb2", cursorAccent: "#282828", - selection: "#665c54", + selectionBackground: "#665c54", + selectionForeground: "#ebdbb2", + selectionInactiveBackground: "#665c54", + scrollbarSliderBackground: "#ebdbb233", + scrollbarSliderHoverBackground: "#ebdbb266", + scrollbarSliderActiveBackground: "#ebdbb280", + overviewRulerBorder: "#928374", black: "#282828", red: "#cc241d", green: "#98971a", @@ -195,7 +243,13 @@ class TerminalThemeManager { foreground: "#abb2bf", cursor: "#528bff", cursorAccent: "#21252b", - selection: "#3e4451", + selectionBackground: "#3e4451", + selectionForeground: "#abb2bf", + selectionInactiveBackground: "#3e4451", + scrollbarSliderBackground: "#abb2bf33", + scrollbarSliderHoverBackground: "#abb2bf66", + scrollbarSliderActiveBackground: "#abb2bf80", + overviewRulerBorder: "#5c6370", black: "#21252b", red: "#e86671", green: "#98c379", @@ -218,7 +272,13 @@ class TerminalThemeManager { foreground: "#eeffff", cursor: "#ffcc00", cursorAccent: "#263238", - selection: "#37474f", + selectionBackground: "#37474f", + selectionForeground: "#eeffff", + selectionInactiveBackground: "#37474f", + scrollbarSliderBackground: "#eeffff33", + scrollbarSliderHoverBackground: "#eeffff66", + scrollbarSliderActiveBackground: "#eeffff80", + overviewRulerBorder: "#546e7a", black: "#263238", red: "#f07178", green: "#c3e88d", @@ -241,7 +301,13 @@ class TerminalThemeManager { foreground: "#c0caf5", cursor: "#c0caf5", cursorAccent: "#1a1b26", - selection: "#33467c", + selectionBackground: "#33467c", + selectionForeground: "#c0caf5", + selectionInactiveBackground: "#33467c", + scrollbarSliderBackground: "#c0caf533", + scrollbarSliderHoverBackground: "#c0caf566", + scrollbarSliderActiveBackground: "#c0caf580", + overviewRulerBorder: "#414868", black: "#15161e", red: "#f7768e", green: "#9ece6a", @@ -264,7 +330,13 @@ class TerminalThemeManager { foreground: "#cdd6f4", cursor: "#f5e0dc", cursorAccent: "#1e1e2e", - selection: "#585b70", + selectionBackground: "#585b70", + selectionForeground: "#cdd6f4", + selectionInactiveBackground: "#585b70", + scrollbarSliderBackground: "#cdd6f433", + scrollbarSliderHoverBackground: "#cdd6f466", + scrollbarSliderActiveBackground: "#cdd6f480", + overviewRulerBorder: "#585b70", black: "#45475a", red: "#f38ba8", green: "#a6e3a1", @@ -287,7 +359,13 @@ class TerminalThemeManager { foreground: "#f92aad", cursor: "#f4f99d", cursorAccent: "#241b2f", - selection: "#495495", + selectionBackground: "#495495", + selectionForeground: "#f92aad", + selectionInactiveBackground: "#495495", + scrollbarSliderBackground: "#f92aad33", + scrollbarSliderHoverBackground: "#f92aad66", + scrollbarSliderActiveBackground: "#f92aad80", + overviewRulerBorder: "#495495", black: "#241b2f", red: "#ff8b94", green: "#a8e6cf", @@ -310,7 +388,13 @@ class TerminalThemeManager { foreground: "#0abdc6", cursor: "#ea00d9", cursorAccent: "#000b1e", - selection: "#711c91", + selectionBackground: "#711c91", + selectionForeground: "#0abdc6", + selectionInactiveBackground: "#711c91", + scrollbarSliderBackground: "#0abdc633", + scrollbarSliderHoverBackground: "#0abdc666", + scrollbarSliderActiveBackground: "#0abdc680", + overviewRulerBorder: "#133e7c", black: "#000b1e", red: "#ff0040", green: "#00ff41", @@ -333,7 +417,13 @@ class TerminalThemeManager { foreground: "#d4ddd4", cursor: "#87ceeb", cursorAccent: "#1b2b1b", - selection: "#3a4f3a", + selectionBackground: "#3a4f3a", + selectionForeground: "#d4ddd4", + selectionInactiveBackground: "#3a4f3a", + scrollbarSliderBackground: "#d4ddd433", + scrollbarSliderHoverBackground: "#d4ddd466", + scrollbarSliderActiveBackground: "#d4ddd480", + overviewRulerBorder: "#5f6f5f", black: "#1b2b1b", red: "#d75f5f", green: "#87af87", @@ -356,7 +446,13 @@ class TerminalThemeManager { foreground: "#ffd5a5", cursor: "#ff8c42", cursorAccent: "#3c1f1f", - selection: "#8b4513", + selectionBackground: "#8b4513", + selectionForeground: "#ffd5a5", + selectionInactiveBackground: "#8b4513", + scrollbarSliderBackground: "#ffd5a533", + scrollbarSliderHoverBackground: "#ffd5a566", + scrollbarSliderActiveBackground: "#ffd5a580", + overviewRulerBorder: "#8b4513", black: "#3c1f1f", red: "#ff6b6b", green: "#ffa500", @@ -379,7 +475,13 @@ class TerminalThemeManager { foreground: "#e6e1cf", cursor: "#f29718", cursorAccent: "#0f1419", - selection: "#253340", + selectionBackground: "#253340", + selectionForeground: "#e6e1cf", + selectionInactiveBackground: "#253340", + scrollbarSliderBackground: "#e6e1cf33", + scrollbarSliderHoverBackground: "#e6e1cf66", + scrollbarSliderActiveBackground: "#e6e1cf80", + overviewRulerBorder: "#4d5566", black: "#0f1419", red: "#ff3333", green: "#b8cc52", @@ -402,7 +504,13 @@ class TerminalThemeManager { foreground: "#111827", cursor: "#6366f1", cursorAccent: "#ffffff", - selection: "#e0e7ff", + selectionBackground: "#c7d2fe", + selectionForeground: "#111827", + selectionInactiveBackground: "#c7d2fe", + scrollbarSliderBackground: "#11182733", + scrollbarSliderHoverBackground: "#11182766", + scrollbarSliderActiveBackground: "#11182780", + overviewRulerBorder: "#4b5563", black: "#374151", red: "#dc2626", green: "#16a34a", @@ -425,7 +533,13 @@ class TerminalThemeManager { foreground: "#e5e7eb", cursor: "#6366f1", cursorAccent: "#181820", - selection: "#374151", + selectionBackground: "#374151", + selectionForeground: "#e5e7eb", + selectionInactiveBackground: "#374151", + scrollbarSliderBackground: "#e5e7eb33", + scrollbarSliderHoverBackground: "#e5e7eb66", + scrollbarSliderActiveBackground: "#e5e7eb80", + overviewRulerBorder: "#1f1f2a", black: "#0f0f14", red: "#f87171", green: "#4ade80", @@ -448,6 +562,23 @@ class TerminalThemeManager { this.pluginThemes = new Map(); } + /** + * Normalize the renamed selection field in legacy plugin themes. + * @param {object} theme - Theme object + * @returns {object} Normalized theme object + */ + normalizeTheme(theme) { + const normalized = { ...theme }; + + // Keep third-party themes written for older xterm.js versions working. + if (!normalized.selectionBackground && normalized.selection) { + normalized.selectionBackground = normalized.selection; + } + delete normalized.selection; + + return normalized; + } + /** * Get a theme by name * @param {string} themeName - Theme name @@ -508,7 +639,7 @@ class TerminalThemeManager { // Store theme with plugin metadata this.pluginThemes.set(name, { - ...theme, + ...this.normalizeTheme(theme), _pluginId: pluginId, _isPlugin: true, }); diff --git a/src/components/terminal/terminalTouchScrolling.js b/src/components/terminal/terminalTouchScrolling.js index c82e40126..beab16530 100644 --- a/src/components/terminal/terminalTouchScrolling.js +++ b/src/components/terminal/terminalTouchScrolling.js @@ -2,9 +2,9 @@ * Terminal Touch Scrolling with Momentum Physics * Provides smooth, consistent touch scrolling with inertia across all Android WebView versions. * - * Listens on terminal.element (same as TerminalTouchSelection) because xterm's canvas - * layers overlay the .xterm-viewport and intercept touch events. Scrolls by directly - * manipulating viewport.scrollTop — xterm.js syncs from the native scroll event. + * Listens on terminal.element (same as TerminalTouchSelection) because renderer + * layers intercept touch events. Pixel movement is converted to terminal rows and + * sent through xterm's public scroll API so it works with the v6 custom scrollbar. */ export default class TerminalTouchScrolling { @@ -24,6 +24,7 @@ export default class TerminalTouchScrolling { this.velocitySamples = []; this.velocity = 0; + this.scrollRemainder = 0; this.maxVelocity = 35; this.friction = 0.95; this.minVelocity = 0.1; @@ -48,9 +49,25 @@ export default class TerminalTouchScrolling { this.attachListeners(); } - getViewport() { - if (!this.element) return null; - return this.element.querySelector(".xterm-viewport"); + getCellHeight() { + const screen = this.element?.querySelector(".xterm-screen"); + const screenHeight = screen?.getBoundingClientRect().height || 0; + return screenHeight > 0 && this.terminal.rows > 0 + ? screenHeight / this.terminal.rows + : this.terminal.options.fontSize * + (this.terminal.options.lineHeight || 1); + } + + scrollByPixels(deltaY) { + const cellHeight = this.getCellHeight(); + if (!Number.isFinite(cellHeight) || cellHeight <= 0) return; + + this.scrollRemainder += deltaY; + const lines = Math.trunc(this.scrollRemainder / cellHeight); + if (lines === 0) return; + + this.terminal.scrollLines(lines); + this.scrollRemainder -= lines * cellHeight; } attachListeners() { @@ -79,9 +96,9 @@ export default class TerminalTouchScrolling { isSelectionActive() { if (!this.touchSelection) return false; return ( - this.touchSelection.isSelecting || this.touchSelection.isHandleDragging || - this.touchSelection.isPinching + this.touchSelection.isPinching || + this.touchSelection.isSelectionTouchActive ); } @@ -99,6 +116,7 @@ export default class TerminalTouchScrolling { this.didScroll = false; this.velocity = 0; this.velocitySamples = []; + this.scrollRemainder = 0; } onTouchMove(event) { @@ -130,10 +148,7 @@ export default class TerminalTouchScrolling { event.preventDefault(); this.didScroll = true; - const viewport = this.getViewport(); - if (viewport) { - viewport.scrollTop += deltaY; - } + this.scrollByPixels(deltaY); } this.lastTouchY = touch.clientY; @@ -184,10 +199,7 @@ export default class TerminalTouchScrolling { return; } - const viewport = this.getViewport(); - if (viewport) { - viewport.scrollTop += this.velocity; - } + this.scrollByPixels(this.velocity); this.velocity *= this.friction; this.animationId = requestAnimationFrame(animate); diff --git a/src/components/terminal/terminalTouchSelection.js b/src/components/terminal/terminalTouchSelection.js index dff0e2b48..8908b1a92 100644 --- a/src/components/terminal/terminalTouchSelection.js +++ b/src/components/terminal/terminalTouchSelection.js @@ -190,7 +190,7 @@ export default class TerminalTouchSelection { this.protectionTimeout = null; // Scroll tracking - this.scrollElement = null; + this.terminalScrollDisposable = null; this.isTerminalScrolling = false; this.scrollEndTimeout = null; this.scrollEndDelay = 100; @@ -335,13 +335,8 @@ export default class TerminalTouchSelection { // Terminal scroll listener this.boundHandlers.terminalScroll = this.onTerminalScroll.bind(this); - this.scrollElement = - this.terminal.element.querySelector(".xterm-viewport") || - this.terminal.element; - this.scrollElement.addEventListener( - "scroll", + this.terminalScrollDisposable = this.terminal.onScroll( this.boundHandlers.terminalScroll, - { passive: true }, ); // Terminal resize listener (for keyboard events) @@ -1545,13 +1540,8 @@ export default class TerminalTouchSelection { this.boundHandlers.handleTouchEnd, ); - if (this.scrollElement) { - this.scrollElement.removeEventListener( - "scroll", - this.boundHandlers.terminalScroll, - ); - this.scrollElement = null; - } + this.terminalScrollDisposable?.dispose(); + this.terminalScrollDisposable = null; window.removeEventListener( "orientationchange", this.boundHandlers.orientationChange, diff --git a/src/settings/terminalSettings.js b/src/settings/terminalSettings.js index bd52bd913..a7cfa75fa 100644 --- a/src/settings/terminalSettings.js +++ b/src/settings/terminalSettings.js @@ -113,6 +113,15 @@ export default function terminalSettings() { info: strings["info-fontLigatures"], category: categories.display, }, + { + key: "showScrollbar", + text: strings["terminal:show scrollbar"] || "Show Scrollbar", + checkbox: terminalValues.showScrollbar !== false, + info: + strings["info-terminal-show-scrollbar"] || + "Show the xterm scrollbar beside the terminal.", + category: categories.display, + }, { key: "cursorStyle", text: strings["terminal:cursor style"], @@ -438,6 +447,9 @@ export async function updateActiveTerminals(key, value) { case "scrollback": tab.terminalComponent.terminal.options.scrollback = value; break; + case "showScrollbar": + tab.terminalComponent.updateScrollbarVisibility(value); + break; case "tabStopWidth": tab.terminalComponent.terminal.options.tabStopWidth = value; break; @@ -450,11 +462,7 @@ export async function updateActiveTerminals(key, value) { case "theme": tab.terminalComponent.terminal.options.theme = TerminalThemeManager.getTheme(value); - // Update container background to match new theme - if (tab.terminalComponent.container) { - tab.terminalComponent.container.style.background = - tab.terminalComponent.terminal.options.theme.background; - } + tab.terminalComponent.updateBackgroundColor(); break; case "imageSupport": tab.terminalComponent.updateImageSupport(value); From d021a4a05768bc24298a299cc1604af26fd307cb Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:13:14 +0530 Subject: [PATCH 2/6] fix: scroll, selection --- src/components/terminal/terminal.js | 26 ++++- .../terminal/terminalTouchScrolling.js | 66 +++++++---- .../terminal/terminalTouchSelection.js | 103 ++++++++++++------ 3 files changed, 139 insertions(+), 56 deletions(-) diff --git a/src/components/terminal/terminal.js b/src/components/terminal/terminal.js index a1ab88f9c..70808ec2e 100644 --- a/src/components/terminal/terminal.js +++ b/src/components/terminal/terminal.js @@ -73,6 +73,7 @@ export default class TerminalComponent { this.parsedAppKeybindings = []; this.parsedAppKeybindingsVersion = -1; this.boundNativeSelectionMenuHandler = null; + this.visibleScrollbarWidth = undefined; this.init(); } @@ -1006,10 +1007,33 @@ export default class TerminalComponent { * @param {boolean} visible Whether the scrollbar should be shown */ updateScrollbarVisibility(visible) { - this.terminal?.element?.classList.toggle( + if (!this.terminal) return; + + const overviewRuler = { ...this.terminal.options.overviewRuler }; + if (visible === false) { + if ( + !this.terminal.element?.classList.contains("terminal-scrollbar-hidden") + ) { + this.visibleScrollbarWidth = overviewRuler.width; + } + // xterm 6 and FitAddon fall back to 14px when width is zero. A tiny, + // truthy width removes the gutter while CSS hides the remaining fraction. + overviewRuler.width = 0.001; + } else if (this.visibleScrollbarWidth === undefined) { + delete overviewRuler.width; + } else { + overviewRuler.width = this.visibleScrollbarWidth; + } + this.terminal.options.overviewRuler = overviewRuler; + this.terminal.element?.classList.toggle( "terminal-scrollbar-hidden", visible === false, ); + + requestAnimationFrame(() => { + if (!this.terminal) return; + this.fitAddon?.fit(); + }); } /** diff --git a/src/components/terminal/terminalTouchScrolling.js b/src/components/terminal/terminalTouchScrolling.js index beab16530..4626ac7a1 100644 --- a/src/components/terminal/terminalTouchScrolling.js +++ b/src/components/terminal/terminalTouchScrolling.js @@ -17,18 +17,19 @@ export default class TerminalTouchScrolling { this.element = null; this.touchStartY = 0; + this.lastTouchX = 0; this.lastTouchY = 0; this.lastTouchTime = 0; this.isTouching = false; this.didScroll = false; + this.totalMovement = 0; this.velocitySamples = []; this.velocity = 0; this.scrollRemainder = 0; - this.maxVelocity = 35; - this.friction = 0.95; - this.minVelocity = 0.1; - this.velocityThreshold = 1; + this.friction = 0.92; + this.minVelocity = 0.5; + this.scrollConfirmPixels = 6; this.animationId = null; this.boundHandlers = {}; @@ -58,7 +59,23 @@ export default class TerminalTouchScrolling { (this.terminal.options.lineHeight || 1); } - scrollByPixels(deltaY) { + scrollByPixels(deltaY, clientX = this.lastTouchX, clientY = this.lastTouchY) { + if (this.terminal.buffer.active.type === "alternate") { + const target = + this.element?.querySelector(".xterm-screen") || this.element; + target?.dispatchEvent( + new WheelEvent("wheel", { + bubbles: true, + cancelable: true, + clientX, + clientY, + deltaY, + deltaMode: WheelEvent.DOM_DELTA_PIXEL, + }), + ); + return; + } + const cellHeight = this.getCellHeight(); if (!Number.isFinite(cellHeight) || cellHeight <= 0) return; @@ -76,7 +93,7 @@ export default class TerminalTouchScrolling { this.boundHandlers.touchStart = this.onTouchStart.bind(this); this.boundHandlers.touchMove = this.onTouchMove.bind(this); this.boundHandlers.touchEnd = this.onTouchEnd.bind(this); - this.boundHandlers.touchCancel = this.onTouchEnd.bind(this); + this.boundHandlers.touchCancel = this.onTouchCancel.bind(this); this.element.addEventListener("touchstart", this.boundHandlers.touchStart, { passive: false, @@ -110,10 +127,12 @@ export default class TerminalTouchScrolling { const touch = event.touches[0]; this.touchStartY = touch.clientY; + this.lastTouchX = touch.clientX; this.lastTouchY = touch.clientY; this.lastTouchTime = performance.now(); this.isTouching = true; this.didScroll = false; + this.totalMovement = 0; this.velocity = 0; this.velocitySamples = []; this.scrollRemainder = 0; @@ -135,22 +154,25 @@ export default class TerminalTouchScrolling { const touch = event.touches[0]; const deltaY = this.lastTouchY - touch.clientY; const deltaTime = performance.now() - this.lastTouchTime; + this.totalMovement += Math.abs(deltaY); if (deltaTime > 0) { const instantVelocity = (deltaY / deltaTime) * 16.67; this.velocitySamples.push(instantVelocity); - if (this.velocitySamples.length > 6) { + if (this.velocitySamples.length > 5) { this.velocitySamples.shift(); } } if (Math.abs(deltaY) > 0.5) { - event.preventDefault(); - this.didScroll = true; - - this.scrollByPixels(deltaY); + this.scrollByPixels(deltaY, touch.clientX, touch.clientY); + if (this.totalMovement > this.scrollConfirmPixels) { + event.preventDefault(); + this.didScroll = true; + } } + this.lastTouchX = touch.clientX; this.lastTouchY = touch.clientY; this.lastTouchTime = performance.now(); } @@ -171,22 +193,26 @@ export default class TerminalTouchScrolling { if (this.velocitySamples.length > 0) { this.velocity = - this.velocitySamples.reduce((a, b) => a + b, 0) / - this.velocitySamples.length; - - this.velocity = Math.max( - -this.maxVelocity, - Math.min(this.maxVelocity, this.velocity), - ); + (this.velocitySamples.reduce((a, b) => a + b, 0) / + this.velocitySamples.length) * + 1.1; } - if (Math.abs(this.velocity) > this.velocityThreshold) { + if (Math.abs(this.velocity) >= this.minVelocity) { this.startMomentum(); } this.velocitySamples = []; } + onTouchCancel() { + this.isTouching = false; + this.didScroll = false; + this.velocitySamples = []; + this.scrollRemainder = 0; + this.stopMomentum(); + } + startMomentum() { const animate = () => { if (this.isTouching) { @@ -199,8 +225,8 @@ export default class TerminalTouchScrolling { return; } - this.scrollByPixels(this.velocity); this.velocity *= this.friction; + this.scrollByPixels(this.velocity); this.animationId = requestAnimationFrame(animate); }; diff --git a/src/components/terminal/terminalTouchSelection.js b/src/components/terminal/terminalTouchSelection.js index 8908b1a92..8a95642f9 100644 --- a/src/components/terminal/terminalTouchSelection.js +++ b/src/components/terminal/terminalTouchSelection.js @@ -194,6 +194,8 @@ export default class TerminalTouchSelection { this.isTerminalScrolling = false; this.scrollEndTimeout = null; this.scrollEndDelay = 100; + this.selectionRenderFrame = null; + this.selectionResizeTimeout = null; this.init(); } @@ -466,6 +468,13 @@ export default class TerminalTouchSelection { return; } + // A long press can otherwise produce a compatibility mouse/click event + // after touchend. xterm 6 handles that event as a new selection gesture, + // which clears the range created by startSelection. + if (this.isSelecting && event.cancelable) { + event.preventDefault(); + } + if (this.tapHoldTimeout) { clearTimeout(this.tapHoldTimeout); this.tapHoldTimeout = null; @@ -687,42 +696,42 @@ export default class TerminalTouchSelection { } } - onTerminalResize(size) { - // Handle terminal resize (keyboard open/close on Android) - setTimeout(() => { + onTerminalResize() { + // xterm 6 clears its selection on vertical resize. Debounce the keyboard's + // intermediate sizes, then restore our range using absolute buffer rows. + if (this.selectionResizeTimeout) { + clearTimeout(this.selectionResizeTimeout); + } + this.selectionResizeTimeout = setTimeout(() => { + this.selectionResizeTimeout = null; this.updateCellDimensions(); - if (this.isSelecting) { - // Don't clear selection if it's protected (during keyboard events) - if (this.selectionProtected) { - // Just update handle positions during protected period - this.updateHandlePositions(); - return; - } + if (!this.isSelecting) return; - // Only clear selection if it becomes invalid due to actual content resize - // Don't clear selection for keyboard-related resizes - if ( - this.selectionStart && - this.selectionEnd && - (this.selectionStart.row >= size.rows || - this.selectionEnd.row >= size.rows) - ) { - this.clearSelection(); - } else if (this.isSelecting) { - // Maintain selection and update handle positions - this.updateHandlePositions(); - // Temporarily hide context menu during resize but keep selection - if (this.contextMenu && this.contextMenu.style.display === "flex") { - this.hideContextMenu(true); - } - // Re-show context menu after resize if selection is still active - setTimeout(() => { - if (this.isSelecting && this.options.showContextMenu) { - this.showContextMenu(); - } - }, 100); - } + const start = this.selectionStart; + const end = this.selectionEnd; + const buffer = this.terminal.buffer.active; + if ( + !start || + !end || + start.row < 0 || + end.row < 0 || + start.row >= buffer.length || + end.row >= buffer.length || + !buffer.getLine(start.row) || + !buffer.getLine(end.row) + ) { + // Invalid buffer coordinates must also remove our overlay handles, + // even while the selection is protected from keyboard side effects. + this.forceClearSelection(); + return; } + + const lastColumn = Math.max(0, this.terminal.cols - 1); + start.col = Math.min(start.col, lastColumn); + end.col = Math.min(end.col, lastColumn); + + this.hideContextMenu(true); + this.finalizeSelection(); }, 50); } @@ -847,9 +856,25 @@ export default class TerminalTouchSelection { } finalizeSelection() { - if (this.options.showContextMenu && this.currentSelection) { - this.showContextMenu(); + if (!this.isSelecting) return; + + this.updateSelection(); + this.currentSelection = this.terminal.getSelection(); + + if (this.selectionRenderFrame) { + cancelAnimationFrame(this.selectionRenderFrame); } + this.selectionRenderFrame = requestAnimationFrame(() => { + this.selectionRenderFrame = null; + if (!this.isSelecting || !this.terminal) return; + + // Reapply after any compatibility mouse events dispatched by WebView. + this.updateSelection(); + this.currentSelection = this.terminal.getSelection(); + if (this.options.showContextMenu && this.currentSelection) { + this.showContextMenu(); + } + }); } showHandles() { @@ -1255,6 +1280,14 @@ export default class TerminalTouchSelection { clearTimeout(this.scrollEndTimeout); this.scrollEndTimeout = null; } + if (this.selectionRenderFrame) { + cancelAnimationFrame(this.selectionRenderFrame); + this.selectionRenderFrame = null; + } + if (this.selectionResizeTimeout) { + clearTimeout(this.selectionResizeTimeout); + this.selectionResizeTimeout = null; + } // Clear protection timeout if (this.protectionTimeout) { From 9ea0b386af27b905a0af11c90db49312f19dd80f Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:15:47 +0530 Subject: [PATCH 3/6] translation --- src/lang/ar-ye.json | 4 +- src/lang/be-by.json | 4 +- src/lang/bn-bd.json | 4 +- src/lang/cs-cz.json | 4 +- src/lang/de-de.json | 4 +- src/lang/en-us.json | 2 + src/lang/es-sv.json | 4 +- src/lang/fr-fr.json | 4 +- src/lang/he-il.json | 4 +- src/lang/hi-in.json | 4 +- src/lang/hu-hu.json | 4 +- src/lang/id-id.json | 4 +- src/lang/index.d.ts | 1664 +++++++++++++++++++------------------- src/lang/ir-fa.json | 4 +- src/lang/it-it.json | 4 +- src/lang/ja-jp.json | 4 +- src/lang/ko-kr.json | 4 +- src/lang/ml-in.json | 4 +- src/lang/mm-unicode.json | 4 +- src/lang/mm-zawgyi.json | 4 +- src/lang/pl-pl.json | 4 +- src/lang/pt-br.json | 4 +- src/lang/pu-in.json | 4 +- src/lang/ru-ru.json | 4 +- src/lang/tl-ph.json | 4 +- src/lang/tr-tr.json | 4 +- src/lang/uk-ua.json | 4 +- src/lang/uz-uz.json | 4 +- src/lang/vi-vn.json | 4 +- src/lang/zh-cn.json | 4 +- src/lang/zh-hant.json | 4 +- src/lang/zh-tw.json | 4 +- 32 files changed, 925 insertions(+), 861 deletions(-) diff --git a/src/lang/ar-ye.json b/src/lang/ar-ye.json index 9bb8087f5..4a1c09c7c 100644 --- a/src/lang/ar-ye.json +++ b/src/lang/ar-ye.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/be-by.json b/src/lang/be-by.json index 8e29ec3ac..5d9250879 100644 --- a/src/lang/be-by.json +++ b/src/lang/be-by.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/bn-bd.json b/src/lang/bn-bd.json index a0dd03034..d2b354ad3 100644 --- a/src/lang/bn-bd.json +++ b/src/lang/bn-bd.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/cs-cz.json b/src/lang/cs-cz.json index f39ce119f..79492bb4e 100644 --- a/src/lang/cs-cz.json +++ b/src/lang/cs-cz.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/de-de.json b/src/lang/de-de.json index be2694449..bd63f3bf0 100644 --- a/src/lang/de-de.json +++ b/src/lang/de-de.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/en-us.json b/src/lang/en-us.json index bf10fc762..acd7938cd 100644 --- a/src/lang/en-us.json +++ b/src/lang/en-us.json @@ -333,6 +333,7 @@ "info-fontWeight": "The font weight used to render non-bold text.", "info-cursorBlink": "Whether the cursor blinks.", "info-scrollback": "The amount of scrollback in the terminal. Scrollback is the amount of rows that are retained when lines are scrolled beyond the initial viewport.", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", "info-tabStopWidth": "The size of tab stops in the terminal.", "info-letterSpacing": "The spacing in whole pixels between characters.", "info-imageSupport": "Whether images are supported in the terminal.", @@ -457,6 +458,7 @@ "letter spacing": "Letter Spacing", "terminal:tab stop width": "Tab Stop Width", "terminal:scrollback": "Scrollback Lines", + "terminal:show scrollbar": "Show Scrollbar", "terminal:cursor blink": "Cursor Blink", "terminal:font weight": "Font Weight", "terminal:cursor inactive style": "Cursor Inactive Style", diff --git a/src/lang/es-sv.json b/src/lang/es-sv.json index b543e0eb7..34f2a3a43 100644 --- a/src/lang/es-sv.json +++ b/src/lang/es-sv.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/fr-fr.json b/src/lang/fr-fr.json index 9b4f5b35e..e1320be03 100644 --- a/src/lang/fr-fr.json +++ b/src/lang/fr-fr.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/he-il.json b/src/lang/he-il.json index 0042ec220..9ccb79ea8 100644 --- a/src/lang/he-il.json +++ b/src/lang/he-il.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/hi-in.json b/src/lang/hi-in.json index bd1374930..b73bbdb60 100644 --- a/src/lang/hi-in.json +++ b/src/lang/hi-in.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/hu-hu.json b/src/lang/hu-hu.json index 538928575..51dae4650 100644 --- a/src/lang/hu-hu.json +++ b/src/lang/hu-hu.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/id-id.json b/src/lang/id-id.json index 933308f8c..a2c66dce5 100644 --- a/src/lang/id-id.json +++ b/src/lang/id-id.json @@ -829,5 +829,7 @@ "diff sec": "{sec}d lalu", "command": "Perintah", "managed": "Dikelola", - "acode service": "Layanan Acode" + "acode service": "Layanan Acode", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/index.d.ts b/src/lang/index.d.ts index a53973c3b..447cc8052 100644 --- a/src/lang/index.d.ts +++ b/src/lang/index.d.ts @@ -2,837 +2,839 @@ // Do not edit manually declare type LangStrings = { - lang: string; - about: string; - "active files": string; - alert: string; - "app theme": string; - autocorrect: string; - autosave: string; - cancel: string; - "change language": string; - "choose color": string; - clear: string; - "close app": string; - "commit message": string; - console: string; - "conflict error": string; - copy: string; - "create folder error": string; - cut: string; - delete: string; - dependencies: string; - delay: string; - "editor settings": string; - "editor theme": string; - "enter file name": string; - "enter folder name": string; - "empty folder message": string; - "enter line number": string; - error: string; - failed: string; - "file already exists": string; - "file already exists force": string; - "file already exists force named": string; - "file changed": string; - "file deleted": string; - "file is not supported": string; - "file not supported": string; - "file too large": string; - "file renamed": string; - "file saved": string; - "folder added": string; - "folder already added": string; - "font size": string; - goto: string; - "icons definition": string; - info: string; - "invalid value": string; - "language changed": string; - linting: string; - logout: string; - loading: string; - "my profile": string; - "new file": string; - "new folder": string; - no: string; - "no editor message": string; - "not set": string; - "unsaved files close app": string; - notice: string; - "open file": string; - "open files and folders": string; - "open folder": string; - "open recent": string; - ok: string; - overwrite: string; - paste: string; - "preview mode": string; - "read only file": string; - reload: string; - rename: string; - "new name": string; - "enter new name": string; - "code actions": string; - replace: string; - required: string; - "run your web app": string; - save: string; - saving: string; - "save as": string; - "save file to run": string; - search: string; - "see logs and errors": string; - "select folder": string; - settings: string; - "settings saved": string; - "show line numbers": string; - "show hidden files": string; - "show share button": string; - "show spaces": string; - "soft tab": string; - "sort by name": string; - success: string; - "tab size": string; - "text wrap": string; - theme: string; - "title-listfiles": string; - "ui zoom": string; - "unable to delete file": string; - "unable to open file": string; - "unable to open folder": string; - "unable to save file": string; - "unable to rename": string; - "unsaved file": string; - warning: string; - "use emmet": string; - "use quick tools": string; - yes: string; - encoding: string; - "syntax highlighting": string; - "read only": string; - "select all": string; - "select branch": string; - "create new branch": string; - "use branch": string; - "new branch": string; - branch: string; - "key bindings": string; - edit: string; - reset: string; - color: string; - "select word": string; - "quick tools": string; - select: string; - "editor font": string; - "new project": string; - format: string; - "project name": string; - "unsupported device": string; - "vibrate on tap": string; - "copy command is not supported by ftp.": string; - "support title": string; - fullscreen: string; - animation: string; - backup: string; - restore: string; - "backup successful": string; - "invalid backup file": string; - "add path": string; - "live autocompletion": string; - "local word completion": string; - "language package completion": string; - "recommend extensions": string; - "auto close tags": string; - "auto rename tags": string; - "file properties": string; - path: string; - type: string; - "word count": string; - "line count": string; - "last modified": string; - size: string; - share: string; - "show print margin": string; - login: string; - "scrollbar size": string; - "scrollbar height": string; - "cursor controller size": string; - full: string; - "scroll past end": string; - "settings-info-scroll-past-end": string; - none: string; - small: string; - large: string; - "confirm on exit": string; - "show console": string; - image: string; - "insert file": string; - "insert color": string; - "powersave mode warning": string; - exit: string; - custom: string; - "reset warning": string; - "theme type": string; - light: string; - dark: string; - "file browser": string; - "operation not permitted": string; - "no such file or directory": string; - "input/output error": string; - "permission denied": string; - "bad address": string; - "file exists": string; - "not a directory": string; - "is a directory": string; - "invalid argument": string; - "too many open files in system": string; - "too many open files": string; - "text file busy": string; - "no space left on device": string; - "read-only file system": string; - "file name too long": string; - "too many users": string; - "connection timed out": string; - "connection refused": string; - "owner died": string; - "an error occurred": string; - "add ftp": string; - "add sftp": string; - "save file": string; - "save file as": string; - files: string; - help: string; - "file has been deleted": string; - "feature not available": string; - "feature available in paid version": string; - "deleted file": string; - "line height": string; - "preview info": string; - "manage all files": string; - "close file": string; - "reset connections": string; - "check file changes": string; - "open in browser": string; - "desktop mode": string; - "toggle console": string; - "new line mode": string; - "add a storage": string; - "rate acode": string; - support: string; - "downloading file": string; - "downloading...": string; - "folder name": string; - "keyboard mode": string; - normal: string; - "app settings": string; - "disable in-app-browser caching": string; - "copied to clipboard": string; - "clipboard not available": string; - "remember opened files": string; - "remember opened folders": string; - "no suggestions": string; - "no suggestions aggressive": string; - install: string; - installing: string; - plugins: string; - "recently used": string; - update: string; - uninstall: string; - "download acode pro": string; - "loading plugins": string; - faqs: string; - feedback: string; - header: string; - sidebar: string; - inapp: string; - browser: string; - "diagonal scrolling": string; - "reverse scrolling": string; - formatter: string; - "format on save": string; - "remove ads": string; - fast: string; - slow: string; - "scroll settings": string; - "scroll speed": string; - "loading...": string; - "no plugins found": string; - name: string; - username: string; - optional: string; - hostname: string; - password: string; - "security type": string; - "connection mode": string; - port: string; - "key file": string; - "select key file": string; - passphrase: string; - "connecting...": string; - "type filename": string; - "unable to load files": string; - "preview port": string; - "find file": string; - system: string; - "please select a formatter": string; - "case sensitive": string; - "regular expression": string; - "whole word": string; - "edit with": string; - "open with": string; - "no app found to handle this file": string; - "restore default settings": string; - "server port": string; - "preview settings": string; - "preview settings note": string; - "backup/restore note": string; - host: string; - "retry ftp/sftp when fail": string; - more: string; - "thank you :)": string; - "purchase pending": string; - cancelled: string; - local: string; - remote: string; - "show console toggler": string; - "binary file": string; - "relative line numbers": string; - "elastic tabstops": string; - "line based rtl switching": string; - "hard wrap": string; - spellcheck: string; - "wrap method": string; - "use textarea for ime": string; - "invalid plugin": string; - "type command": string; - plugin: string; - "quicktools trigger mode": string; - "print margin": string; - "touch move threshold": string; - "info-retryremotefsafterfail": string; - "info-fullscreen": string; - "info-checkfiles": string; - "info-console": string; - "info-keyboardmode": string; - "info-rememberfiles": string; - "info-rememberfolders": string; - "info-floatingbutton": string; - "info-openfilelistpos": string; - "info-touchmovethreshold": string; - "info-scroll-settings": string; - "info-animation": string; - "info-quicktoolstriggermode": string; - "info-checkForAppUpdates": string; - "info-quickTools": string; - "info-showHiddenFiles": string; - "info-listFiles": string; - "info-all_file_access": string; - "info-fontSize": string; - "info-fontFamily": string; - "info-theme": string; - "info-cursorStyle": string; - "info-cursorInactiveStyle": string; - "info-fontWeight": string; - "info-cursorBlink": string; - "info-scrollback": string; - "info-tabStopWidth": string; - "info-letterSpacing": string; - "info-imageSupport": string; - "info-fontLigatures": string; - "info-confirmTabClose": string; - "info-backup": string; - "info-restore": string; - "info-uninstall": string; - owned: string; - api_error: string; - installed: string; - all: string; - medium: string; - refund: string; - "product not available": string; - "no-product-info": string; - close: string; - explore: string; - "key bindings updated": string; - "search in files": string; - "exclude files": string; - "include files": string; - "search result": string; - "invalid regex": string; - bottom: string; - "save all": string; - "close all": string; - "unsaved files warning": string; - "save all warning": string; - "save all changes warning": string; - "close all warning": string; - refresh: string; - "shortcut buttons": string; - "no result": string; - "searching...": string; - "quicktools:ctrl-key": string; - "quicktools:tab-key": string; - "quicktools:shift-key": string; - "quicktools:undo": string; - "quicktools:redo": string; - "quicktools:search": string; - "quicktools:save": string; - "quicktools:esc-key": string; - "quicktools:curlybracket": string; - "quicktools:squarebracket": string; - "quicktools:parentheses": string; - "quicktools:anglebracket": string; - "quicktools:left-arrow-key": string; - "quicktools:right-arrow-key": string; - "quicktools:up-arrow-key": string; - "quicktools:down-arrow-key": string; - "quicktools:moveline-up": string; - "quicktools:moveline-down": string; - "quicktools:copyline-up": string; - "quicktools:copyline-down": string; - "quicktools:semicolon": string; - "quicktools:quotation": string; - "quicktools:and": string; - "quicktools:bar": string; - "quicktools:equal": string; - "quicktools:slash": string; - "quicktools:exclamation": string; - "quicktools:alt-key": string; - "quicktools:meta-key": string; - "quicktools:search-prev": string; - "quicktools:search-next": string; - "quicktools:search-settings": string; - "quicktools:search-replace": string; - "quicktools:search-replace-all": string; - "info-quicktoolssettings": string; - "info-excludefolders": string; - "missed files": string; - remove: string; - "quicktools:command-palette": string; - "default file encoding": string; - "remove entry": string; - "delete entry": string; - "change encoding": string; - "reopen file": string; - "plugin min version": string; - "color preview": string; - confirm: string; - problems: string; - "show side buttons": string; - bug_report: string; - "verified publisher": string; - most_downloaded: string; - newly_added: string; - top_rated: string; - "rename not supported": string; - compress: string; - "copy uri": string; - "copying items": string; - "cannot paste folder into itself": string; - "folder already exists": string; - "delete entries": string; - "deleting items": string; - "import project zip": string; - changelog: string; - notifications: string; - no_unread_notifications: string; - should_use_current_file_for_preview: string; - "fade fold widgets": string; - "quicktools:home-key": string; - "quicktools:end-key": string; - "quicktools:pageup-key": string; - "quicktools:pagedown-key": string; - "quicktools:delete-key": string; - "quicktools:tilde": string; - "quicktools:backtick": string; - "quicktools:hash": string; - "quicktools:dollar": string; - "quicktools:modulo": string; - "quicktools:caret": string; - plugin_enabled: string; - plugin_disabled: string; - enable_plugin: string; - disable_plugin: string; - open_source: string; - "terminal settings": string; - "font ligatures": string; - "letter spacing": string; - "terminal:tab stop width": string; - "terminal:scrollback": string; - "terminal:cursor blink": string; - "terminal:font weight": string; - "terminal:cursor inactive style": string; - "terminal:cursor style": string; - "terminal:font family": string; - "terminal:convert eol": string; - "terminal:confirm tab close": string; - "terminal:image support": string; - terminal: string; - "running processes": string; - "terminal not installed prompt": string; - "terminal first launch prompt": string; - "don't ask again": string; - allFileAccess: string; - fonts: string; - sponsor: string; - downloads: string; - reviews: string; - overview: string; - contributors: string; - "quicktools:hyphen": string; - "check for app updates": string; - "prompt update check consent message": string; - keywords: string; - author: string; - "filtered by": string; - "clean install state": string; - "backup created": string; - "restore completed": string; - "restore will include": string; - "restore warning": string; - "reload to apply": string; - "reload app": string; - "preparing backup": string; - "collecting settings": string; - "collecting key bindings": string; - "collecting plugins": string; - "creating backup": string; - "validating backup": string; - "restoring key bindings": string; - "restoring plugins": string; - "restoring settings": string; - "legacy backup warning": string; - "checksum mismatch": string; - "plugin not found": string; - "paid plugin skipped": string; - "source not found": string; - restored: string; - skipped: string; - "backup not valid object": string; - "backup no data": string; - "backup legacy warning": string; - "backup missing metadata": string; - "backup checksum mismatch": string; - "backup checksum verify failed": string; - "backup invalid settings": string; - "backup invalid keybindings": string; - "backup invalid plugins": string; - "issues found": string; - "error details": string; - "active tools": string; - recent: string; - "command palette": string; - "change theme": string; - documentation: string; - "open in terminal": string; - "developer mode": string; - "info-developermode": string; - "developer mode enabled": string; - "developer mode disabled": string; - "copy relative path": string; - "available tools": string; - "shortcut request sent": string; - "add to home screen": string; - "pin shortcuts not supported": string; - "save file before home shortcut": string; - terminal_required_message_for_lsp: string; - "shift click selection": string; - "earn ad-free time": string; - "indent guides": string; - "language servers": string; - "lint gutter": string; - "rainbow brackets": string; - "lsp-add-custom-server": string; - "lsp-binary-args": string; - "lsp-binary-command": string; - "lsp-binary-path-optional": string; - "lsp-check-command-optional": string; - "lsp-checking-installation-status": string; - "lsp-configured": string; - "lsp-custom-server-added": string; - "lsp-default": string; - "lsp-details-line": string; - "lsp-edit-initialization-options": string; - "lsp-empty": string; - "lsp-enabled": string; - "lsp-error-add-server-failed": string; - "lsp-error-args-must-be-array": string; - "lsp-error-binary-command-required": string; - "lsp-error-language-id-required": string; - "lsp-error-package-required": string; - "lsp-error-server-id-required": string; - "lsp-feature-completion": string; - "lsp-feature-completion-info": string; - "lsp-feature-diagnostics": string; - "lsp-feature-diagnostics-info": string; - "lsp-feature-formatting": string; - "lsp-feature-formatting-info": string; - "lsp-feature-hover": string; - "lsp-feature-hover-info": string; - "lsp-feature-inlay-hints": string; - "lsp-feature-inlay-hints-info": string; - "lsp-feature-signature": string; - "lsp-feature-signature-info": string; - "lsp-feature-state-toast": string; - "lsp-initialization-options": string; - "lsp-initialization-options-json": string; - "lsp-initialization-options-updated": string; - "lsp-install-command": string; - "lsp-install-command-unavailable": string; - "lsp-install-info-check-failed": string; - "lsp-install-info-missing": string; - "lsp-install-info-ready": string; - "lsp-install-info-unknown": string; - "lsp-install-info-version-available": string; - "lsp-install-notification": string; - "lsp-install-method-apk": string; - "lsp-install-method-cargo": string; - "lsp-install-method-manual": string; - "lsp-install-method-npm": string; - "lsp-install-method-pip": string; - "lsp-install-method-shell": string; - "lsp-install-method-title": string; - "lsp-install-repair": string; - "lsp-installation-status": string; - "lsp-installed": string; - "lsp-invalid-timeout": string; - "lsp-language-ids": string; - "lsp-packages-prompt": string; - "lsp-remove-custom-server": string; - "lsp-remove-custom-server-confirm": string; - "lsp-remove-installed-files": string; - "lsp-custom-server-removed": string; - "lsp-server-disabled-toast": string; - "lsp-server-enabled-toast": string; - "lsp-server-id": string; - "lsp-server-label": string; - "lsp-server-not-found": string; - "lsp-server-uninstalled": string; - "lsp-startup-timeout": string; - "lsp-startup-timeout-ms": string; - "lsp-startup-timeout-set": string; - "lsp-state-disabled": string; - "lsp-state-enabled": string; - "lsp-status": string; - "lsp-status-check-failed": string; - "lsp-status-installed": string; - "lsp-status-installed-version": string; - "lsp-status-line": string; - "lsp-status-not-installed": string; - "lsp-status-unknown": string; - "lsp-timeout-ms": string; - "lsp-transport-method-stdio": string; - "lsp-transport-method-websocket": string; - "lsp-uninstall-command-unavailable": string; - "lsp-uninstall-notification": string; - "lsp-uninstall-server": string; - "lsp-update-command-optional": string; - "lsp-update-command-unavailable": string; - "lsp-update-server": string; - "lsp-version-line": string; - "lsp-websocket-url": string; - "lsp-websocket-server-managed-externally": string; - "lsp-error-websocket-url-invalid": string; - "lsp-error-websocket-url-required": string; - "lsp-view-initialization-options": string; - "settings-category-about-acode": string; - "settings-category-discover-apps": string; - "settings-category-advanced": string; - "settings-category-assistance": string; - "settings-category-core": string; - "settings-category-cursor": string; - "settings-category-cursor-selection": string; - "settings-category-custom-servers": string; - "settings-category-customization-tools": string; - "settings-category-display": string; - "settings-category-editing": string; - "settings-category-features": string; - "settings-category-files-sessions": string; - "settings-category-fonts": string; - "settings-category-general": string; - "settings-category-guides-indicators": string; - "settings-category-installation": string; - "settings-category-interface": string; - "settings-category-maintenance": string; - "settings-category-permissions": string; - "settings-category-preview": string; - "settings-category-scrolling": string; - "settings-category-server": string; - "settings-category-servers": string; - "settings-category-session": string; - "settings-category-support-acode": string; - "settings-category-text-layout": string; - "settings-info-app-animation": string; - "settings-info-app-check-files": string; - "settings-info-app-clean-install-state": string; - "settings-info-app-confirm-on-exit": string; - "settings-info-app-console": string; - "settings-info-app-default-file-encoding": string; - "settings-info-app-exclude-folders": string; - "settings-info-app-floating-button": string; - "settings-info-app-font-manager": string; - "settings-info-app-fullscreen": string; - "settings-info-app-keybindings": string; - "settings-info-app-keyboard-mode": string; - "settings-info-app-language": string; - "settings-info-app-open-file-list-position": string; - "settings-info-app-quick-tools-settings": string; - "settings-info-app-quick-tools-trigger-mode": string; - "settings-info-app-remember-files": string; - "settings-info-app-remember-folders": string; - "settings-info-app-retry-remote-fs": string; - "settings-info-app-side-buttons": string; - "settings-info-app-sponsor-sidebar": string; - "settings-info-app-touch-move-threshold": string; - "settings-info-app-ui-zoom": string; - "settings-info-app-vibrate-on-tap": string; - "settings-info-editor-autosave": string; - "settings-info-editor-color-preview": string; - "settings-info-editor-fade-fold-widgets": string; - "settings-info-editor-font-family": string; - "settings-info-editor-font-size": string; - "settings-info-editor-format-on-save": string; - "settings-info-editor-hard-wrap": string; - "settings-info-editor-indent-guides": string; - "settings-info-editor-line-height": string; - "settings-info-editor-line-numbers": string; - "settings-info-editor-lint-gutter": string; - "settings-info-editor-live-autocomplete": string; - "settings-info-editor-local-word-completion": string; - "settings-info-editor-language-completion": string; - "settings-info-editor-recommend-extensions": string; - "extension recommendation title": string; - "extension recommendation message": string; - "extension request title": string; - "extension request message": string; - "search plugins": string; - "request plugin": string; - "settings-info-editor-auto-close-tags": string; - "settings-info-editor-auto-rename-tags": string; - "settings-info-editor-rainbow-brackets": string; - "settings-info-editor-relative-line-numbers": string; - "settings-info-editor-rtl-text": string; - "settings-info-editor-scroll-settings": string; - "settings-info-editor-shift-click-selection": string; - "settings-info-editor-show-share-button": string; - "settings-info-editor-show-spaces": string; - "settings-info-editor-soft-tab": string; - "settings-info-editor-tab-size": string; - "settings-info-editor-teardrop-size": string; - "settings-info-editor-text-wrap": string; - "settings-info-lsp-add-custom-server": string; - "settings-info-lsp-allow-non-terminal-workspace": string; - "settings-info-lsp-edit-init-options": string; - "settings-info-lsp-install-server": string; - "settings-info-lsp-remove-custom-server": string; - "settings-info-lsp-server-enabled": string; - "settings-info-lsp-startup-timeout": string; - "settings-info-lsp-uninstall-server": string; - "settings-info-lsp-update-server": string; - "settings-info-lsp-view-init-options": string; - "settings-info-main-ad-rewards": string; - "settings-info-main-app-settings": string; - "settings-info-main-backup-restore": string; - "settings-info-main-changelog": string; - "settings-info-main-edit-settings": string; - "settings-info-main-editor-settings": string; - "settings-info-main-formatter": string; - "settings-info-main-lsp-settings": string; - "settings-info-main-plugins": string; - "settings-info-main-preview-settings": string; - "settings-info-main-rateapp": string; - "settings-info-main-remove-ads": string; - "settings-info-main-reset": string; - "settings-info-main-sponsors": string; - "settings-info-main-terminal-settings": string; - "settings-info-main-theme": string; - "settings-info-preview-disable-cache": string; - "settings-info-preview-host": string; - "settings-info-preview-mode": string; - "settings-info-preview-preview-port": string; - "settings-info-preview-server-port": string; - "settings-info-preview-show-console-toggler": string; - "settings-info-preview-use-current-file": string; - "settings-info-terminal-convert-eol": string; - "settings-note-formatter-settings": string; - "settings-note-lsp-settings": string; - "lsp-allow-non-terminal-workspace": string; - "search result label singular": string; - "search result label plural": string; - "pin tab": string; - "unpin tab": string; - "pinned tab": string; - "unpin tab before closing": string; - "app font": string; - "settings-info-app-font-family": string; - "unsaved selected tabs warning": string; - "save selected tabs": string; - "close selected tabs": string; - "save selected tabs warning": string; - "close selected tabs warning": string; - "close tabs to right": string; - "close tabs to left": string; - "close other tabs": string; - "plugin-not-supported": string; - "plugin-not-supported-info": string; - "login-to-view": string; - "iap-plugin-purchase-warning": string; - "iap-pro-purchase-warning": string; - "confirm-login": string; - "terminal:failsafe": string; - "terminal:failsafe-info": string; - compact: string; - off: string; - "quick tools height": string; - "quick tools toggler": string; - "terminal:block": string; - "terminal:underline": string; - "terminal:bar": string; - "terminal:inactive block": string; - "terminal:inactive underline": string; - "terminal:inactive bar": string; - "terminal:inactive none": string; - "terminal:normal": string; - "terminal:bold": string; - "quicktools-trigger:click": string; - "quicktools-trigger:touch": string; - "settings-info-terminal-uninstall": string; - "terminal:inactive outline": string; - "restored successfully": string; - "uninstalled successfully": string; - "enter plugin source": string; - "enter keywords": string; - "enter author name": string; - "update available": string; - "update available info": string; - "plugin updates": string; - "plugin updates singular": string; - "plugin updates plural": string; - "just now": string; - "day singular": string; - "hour singular": string; - "min singular": string; - "day plural": string; - "hour plural": string; - "min plural": string; - "settings-category-builtin-servers": string; - "settings-category-plugin-servers": string; - "active processes": string; - "total memory": string; - uptime: string; - note: string; - "acode main process": string; - "ppid parent": string; - unknown: string; - "just started": string; - "diff days": string; - "diff hr": string; - "diff min": string; - "diff sec": string; - command: string; - managed: string; - "acode service": string; + "lang": string; + "about": string; + "active files": string; + "alert": string; + "app theme": string; + "autocorrect": string; + "autosave": string; + "cancel": string; + "change language": string; + "choose color": string; + "clear": string; + "close app": string; + "commit message": string; + "console": string; + "conflict error": string; + "copy": string; + "create folder error": string; + "cut": string; + "delete": string; + "dependencies": string; + "delay": string; + "editor settings": string; + "editor theme": string; + "enter file name": string; + "enter folder name": string; + "empty folder message": string; + "enter line number": string; + "error": string; + "failed": string; + "file already exists": string; + "file already exists force": string; + "file already exists force named": string; + "file changed": string; + "file deleted": string; + "file is not supported": string; + "file not supported": string; + "file too large": string; + "file renamed": string; + "file saved": string; + "folder added": string; + "folder already added": string; + "font size": string; + "goto": string; + "icons definition": string; + "info": string; + "invalid value": string; + "language changed": string; + "linting": string; + "logout": string; + "loading": string; + "my profile": string; + "new file": string; + "new folder": string; + "no": string; + "no editor message": string; + "not set": string; + "unsaved files close app": string; + "notice": string; + "open file": string; + "open files and folders": string; + "open folder": string; + "open recent": string; + "ok": string; + "overwrite": string; + "paste": string; + "preview mode": string; + "read only file": string; + "reload": string; + "rename": string; + "new name": string; + "enter new name": string; + "code actions": string; + "replace": string; + "required": string; + "run your web app": string; + "save": string; + "saving": string; + "save as": string; + "save file to run": string; + "search": string; + "see logs and errors": string; + "select folder": string; + "settings": string; + "settings saved": string; + "show line numbers": string; + "show hidden files": string; + "show share button": string; + "show spaces": string; + "soft tab": string; + "sort by name": string; + "success": string; + "tab size": string; + "text wrap": string; + "theme": string; + "title-listfiles": string; + "ui zoom": string; + "unable to delete file": string; + "unable to open file": string; + "unable to open folder": string; + "unable to save file": string; + "unable to rename": string; + "unsaved file": string; + "warning": string; + "use emmet": string; + "use quick tools": string; + "yes": string; + "encoding": string; + "syntax highlighting": string; + "read only": string; + "select all": string; + "select branch": string; + "create new branch": string; + "use branch": string; + "new branch": string; + "branch": string; + "key bindings": string; + "edit": string; + "reset": string; + "color": string; + "select word": string; + "quick tools": string; + "select": string; + "editor font": string; + "new project": string; + "format": string; + "project name": string; + "unsupported device": string; + "vibrate on tap": string; + "copy command is not supported by ftp.": string; + "support title": string; + "fullscreen": string; + "animation": string; + "backup": string; + "restore": string; + "backup successful": string; + "invalid backup file": string; + "add path": string; + "live autocompletion": string; + "local word completion": string; + "language package completion": string; + "recommend extensions": string; + "auto close tags": string; + "auto rename tags": string; + "file properties": string; + "path": string; + "type": string; + "word count": string; + "line count": string; + "last modified": string; + "size": string; + "share": string; + "show print margin": string; + "login": string; + "scrollbar size": string; + "scrollbar height": string; + "cursor controller size": string; + "full": string; + "scroll past end": string; + "settings-info-scroll-past-end": string; + "none": string; + "small": string; + "large": string; + "confirm on exit": string; + "show console": string; + "image": string; + "insert file": string; + "insert color": string; + "powersave mode warning": string; + "exit": string; + "custom": string; + "reset warning": string; + "theme type": string; + "light": string; + "dark": string; + "file browser": string; + "operation not permitted": string; + "no such file or directory": string; + "input/output error": string; + "permission denied": string; + "bad address": string; + "file exists": string; + "not a directory": string; + "is a directory": string; + "invalid argument": string; + "too many open files in system": string; + "too many open files": string; + "text file busy": string; + "no space left on device": string; + "read-only file system": string; + "file name too long": string; + "too many users": string; + "connection timed out": string; + "connection refused": string; + "owner died": string; + "an error occurred": string; + "add ftp": string; + "add sftp": string; + "save file": string; + "save file as": string; + "files": string; + "help": string; + "file has been deleted": string; + "feature not available": string; + "feature available in paid version": string; + "deleted file": string; + "line height": string; + "preview info": string; + "manage all files": string; + "close file": string; + "reset connections": string; + "check file changes": string; + "open in browser": string; + "desktop mode": string; + "toggle console": string; + "new line mode": string; + "add a storage": string; + "rate acode": string; + "support": string; + "downloading file": string; + "downloading...": string; + "folder name": string; + "keyboard mode": string; + "normal": string; + "app settings": string; + "disable in-app-browser caching": string; + "copied to clipboard": string; + "clipboard not available": string; + "remember opened files": string; + "remember opened folders": string; + "no suggestions": string; + "no suggestions aggressive": string; + "install": string; + "installing": string; + "plugins": string; + "recently used": string; + "update": string; + "uninstall": string; + "download acode pro": string; + "loading plugins": string; + "faqs": string; + "feedback": string; + "header": string; + "sidebar": string; + "inapp": string; + "browser": string; + "diagonal scrolling": string; + "reverse scrolling": string; + "formatter": string; + "format on save": string; + "remove ads": string; + "fast": string; + "slow": string; + "scroll settings": string; + "scroll speed": string; + "loading...": string; + "no plugins found": string; + "name": string; + "username": string; + "optional": string; + "hostname": string; + "password": string; + "security type": string; + "connection mode": string; + "port": string; + "key file": string; + "select key file": string; + "passphrase": string; + "connecting...": string; + "type filename": string; + "unable to load files": string; + "preview port": string; + "find file": string; + "system": string; + "please select a formatter": string; + "case sensitive": string; + "regular expression": string; + "whole word": string; + "edit with": string; + "open with": string; + "no app found to handle this file": string; + "restore default settings": string; + "server port": string; + "preview settings": string; + "preview settings note": string; + "backup/restore note": string; + "host": string; + "retry ftp/sftp when fail": string; + "more": string; + "thank you :)": string; + "purchase pending": string; + "cancelled": string; + "local": string; + "remote": string; + "show console toggler": string; + "binary file": string; + "relative line numbers": string; + "elastic tabstops": string; + "line based rtl switching": string; + "hard wrap": string; + "spellcheck": string; + "wrap method": string; + "use textarea for ime": string; + "invalid plugin": string; + "type command": string; + "plugin": string; + "quicktools trigger mode": string; + "print margin": string; + "touch move threshold": string; + "info-retryremotefsafterfail": string; + "info-fullscreen": string; + "info-checkfiles": string; + "info-console": string; + "info-keyboardmode": string; + "info-rememberfiles": string; + "info-rememberfolders": string; + "info-floatingbutton": string; + "info-openfilelistpos": string; + "info-touchmovethreshold": string; + "info-scroll-settings": string; + "info-animation": string; + "info-quicktoolstriggermode": string; + "info-checkForAppUpdates": string; + "info-quickTools": string; + "info-showHiddenFiles": string; + "info-listFiles": string; + "info-all_file_access": string; + "info-fontSize": string; + "info-fontFamily": string; + "info-theme": string; + "info-cursorStyle": string; + "info-cursorInactiveStyle": string; + "info-fontWeight": string; + "info-cursorBlink": string; + "info-scrollback": string; + "info-terminal-show-scrollbar": string; + "info-tabStopWidth": string; + "info-letterSpacing": string; + "info-imageSupport": string; + "info-fontLigatures": string; + "info-confirmTabClose": string; + "info-backup": string; + "info-restore": string; + "info-uninstall": string; + "owned": string; + "api_error": string; + "installed": string; + "all": string; + "medium": string; + "refund": string; + "product not available": string; + "no-product-info": string; + "close": string; + "explore": string; + "key bindings updated": string; + "search in files": string; + "exclude files": string; + "include files": string; + "search result": string; + "invalid regex": string; + "bottom": string; + "save all": string; + "close all": string; + "unsaved files warning": string; + "save all warning": string; + "save all changes warning": string; + "close all warning": string; + "refresh": string; + "shortcut buttons": string; + "no result": string; + "searching...": string; + "quicktools:ctrl-key": string; + "quicktools:tab-key": string; + "quicktools:shift-key": string; + "quicktools:undo": string; + "quicktools:redo": string; + "quicktools:search": string; + "quicktools:save": string; + "quicktools:esc-key": string; + "quicktools:curlybracket": string; + "quicktools:squarebracket": string; + "quicktools:parentheses": string; + "quicktools:anglebracket": string; + "quicktools:left-arrow-key": string; + "quicktools:right-arrow-key": string; + "quicktools:up-arrow-key": string; + "quicktools:down-arrow-key": string; + "quicktools:moveline-up": string; + "quicktools:moveline-down": string; + "quicktools:copyline-up": string; + "quicktools:copyline-down": string; + "quicktools:semicolon": string; + "quicktools:quotation": string; + "quicktools:and": string; + "quicktools:bar": string; + "quicktools:equal": string; + "quicktools:slash": string; + "quicktools:exclamation": string; + "quicktools:alt-key": string; + "quicktools:meta-key": string; + "quicktools:search-prev": string; + "quicktools:search-next": string; + "quicktools:search-settings": string; + "quicktools:search-replace": string; + "quicktools:search-replace-all": string; + "info-quicktoolssettings": string; + "info-excludefolders": string; + "missed files": string; + "remove": string; + "quicktools:command-palette": string; + "default file encoding": string; + "remove entry": string; + "delete entry": string; + "change encoding": string; + "reopen file": string; + "plugin min version": string; + "color preview": string; + "confirm": string; + "problems": string; + "show side buttons": string; + "bug_report": string; + "verified publisher": string; + "most_downloaded": string; + "newly_added": string; + "top_rated": string; + "rename not supported": string; + "compress": string; + "copy uri": string; + "copying items": string; + "cannot paste folder into itself": string; + "folder already exists": string; + "delete entries": string; + "deleting items": string; + "import project zip": string; + "changelog": string; + "notifications": string; + "no_unread_notifications": string; + "should_use_current_file_for_preview": string; + "fade fold widgets": string; + "quicktools:home-key": string; + "quicktools:end-key": string; + "quicktools:pageup-key": string; + "quicktools:pagedown-key": string; + "quicktools:delete-key": string; + "quicktools:tilde": string; + "quicktools:backtick": string; + "quicktools:hash": string; + "quicktools:dollar": string; + "quicktools:modulo": string; + "quicktools:caret": string; + "plugin_enabled": string; + "plugin_disabled": string; + "enable_plugin": string; + "disable_plugin": string; + "open_source": string; + "terminal settings": string; + "font ligatures": string; + "letter spacing": string; + "terminal:tab stop width": string; + "terminal:scrollback": string; + "terminal:show scrollbar": string; + "terminal:cursor blink": string; + "terminal:font weight": string; + "terminal:cursor inactive style": string; + "terminal:cursor style": string; + "terminal:font family": string; + "terminal:convert eol": string; + "terminal:confirm tab close": string; + "terminal:image support": string; + "terminal": string; + "running processes": string; + "terminal not installed prompt": string; + "terminal first launch prompt": string; + "don't ask again": string; + "allFileAccess": string; + "fonts": string; + "sponsor": string; + "downloads": string; + "reviews": string; + "overview": string; + "contributors": string; + "quicktools:hyphen": string; + "check for app updates": string; + "prompt update check consent message": string; + "keywords": string; + "author": string; + "filtered by": string; + "clean install state": string; + "backup created": string; + "restore completed": string; + "restore will include": string; + "restore warning": string; + "reload to apply": string; + "reload app": string; + "preparing backup": string; + "collecting settings": string; + "collecting key bindings": string; + "collecting plugins": string; + "creating backup": string; + "validating backup": string; + "restoring key bindings": string; + "restoring plugins": string; + "restoring settings": string; + "legacy backup warning": string; + "checksum mismatch": string; + "plugin not found": string; + "paid plugin skipped": string; + "source not found": string; + "restored": string; + "skipped": string; + "backup not valid object": string; + "backup no data": string; + "backup legacy warning": string; + "backup missing metadata": string; + "backup checksum mismatch": string; + "backup checksum verify failed": string; + "backup invalid settings": string; + "backup invalid keybindings": string; + "backup invalid plugins": string; + "issues found": string; + "error details": string; + "active tools": string; + "recent": string; + "command palette": string; + "change theme": string; + "documentation": string; + "open in terminal": string; + "developer mode": string; + "info-developermode": string; + "developer mode enabled": string; + "developer mode disabled": string; + "copy relative path": string; + "available tools": string; + "shortcut request sent": string; + "add to home screen": string; + "pin shortcuts not supported": string; + "save file before home shortcut": string; + "terminal_required_message_for_lsp": string; + "shift click selection": string; + "earn ad-free time": string; + "indent guides": string; + "language servers": string; + "lint gutter": string; + "rainbow brackets": string; + "lsp-add-custom-server": string; + "lsp-binary-args": string; + "lsp-binary-command": string; + "lsp-binary-path-optional": string; + "lsp-check-command-optional": string; + "lsp-checking-installation-status": string; + "lsp-configured": string; + "lsp-custom-server-added": string; + "lsp-default": string; + "lsp-details-line": string; + "lsp-edit-initialization-options": string; + "lsp-empty": string; + "lsp-enabled": string; + "lsp-error-add-server-failed": string; + "lsp-error-args-must-be-array": string; + "lsp-error-binary-command-required": string; + "lsp-error-language-id-required": string; + "lsp-error-package-required": string; + "lsp-error-server-id-required": string; + "lsp-feature-completion": string; + "lsp-feature-completion-info": string; + "lsp-feature-diagnostics": string; + "lsp-feature-diagnostics-info": string; + "lsp-feature-formatting": string; + "lsp-feature-formatting-info": string; + "lsp-feature-hover": string; + "lsp-feature-hover-info": string; + "lsp-feature-inlay-hints": string; + "lsp-feature-inlay-hints-info": string; + "lsp-feature-signature": string; + "lsp-feature-signature-info": string; + "lsp-feature-state-toast": string; + "lsp-initialization-options": string; + "lsp-initialization-options-json": string; + "lsp-initialization-options-updated": string; + "lsp-install-command": string; + "lsp-install-command-unavailable": string; + "lsp-install-info-check-failed": string; + "lsp-install-info-missing": string; + "lsp-install-info-ready": string; + "lsp-install-info-unknown": string; + "lsp-install-info-version-available": string; + "lsp-install-notification": string; + "lsp-install-method-apk": string; + "lsp-install-method-cargo": string; + "lsp-install-method-manual": string; + "lsp-install-method-npm": string; + "lsp-install-method-pip": string; + "lsp-install-method-shell": string; + "lsp-install-method-title": string; + "lsp-install-repair": string; + "lsp-installation-status": string; + "lsp-installed": string; + "lsp-invalid-timeout": string; + "lsp-language-ids": string; + "lsp-packages-prompt": string; + "lsp-remove-custom-server": string; + "lsp-remove-custom-server-confirm": string; + "lsp-remove-installed-files": string; + "lsp-custom-server-removed": string; + "lsp-server-disabled-toast": string; + "lsp-server-enabled-toast": string; + "lsp-server-id": string; + "lsp-server-label": string; + "lsp-server-not-found": string; + "lsp-server-uninstalled": string; + "lsp-startup-timeout": string; + "lsp-startup-timeout-ms": string; + "lsp-startup-timeout-set": string; + "lsp-state-disabled": string; + "lsp-state-enabled": string; + "lsp-status": string; + "lsp-status-check-failed": string; + "lsp-status-installed": string; + "lsp-status-installed-version": string; + "lsp-status-line": string; + "lsp-status-not-installed": string; + "lsp-status-unknown": string; + "lsp-timeout-ms": string; + "lsp-transport-method-stdio": string; + "lsp-transport-method-websocket": string; + "lsp-uninstall-command-unavailable": string; + "lsp-uninstall-notification": string; + "lsp-uninstall-server": string; + "lsp-update-command-optional": string; + "lsp-update-command-unavailable": string; + "lsp-update-server": string; + "lsp-version-line": string; + "lsp-websocket-url": string; + "lsp-websocket-server-managed-externally": string; + "lsp-error-websocket-url-invalid": string; + "lsp-error-websocket-url-required": string; + "lsp-view-initialization-options": string; + "settings-category-about-acode": string; + "settings-category-discover-apps": string; + "settings-category-advanced": string; + "settings-category-assistance": string; + "settings-category-core": string; + "settings-category-cursor": string; + "settings-category-cursor-selection": string; + "settings-category-custom-servers": string; + "settings-category-customization-tools": string; + "settings-category-display": string; + "settings-category-editing": string; + "settings-category-features": string; + "settings-category-files-sessions": string; + "settings-category-fonts": string; + "settings-category-general": string; + "settings-category-guides-indicators": string; + "settings-category-installation": string; + "settings-category-interface": string; + "settings-category-maintenance": string; + "settings-category-permissions": string; + "settings-category-preview": string; + "settings-category-scrolling": string; + "settings-category-server": string; + "settings-category-servers": string; + "settings-category-session": string; + "settings-category-support-acode": string; + "settings-category-text-layout": string; + "settings-info-app-animation": string; + "settings-info-app-check-files": string; + "settings-info-app-clean-install-state": string; + "settings-info-app-confirm-on-exit": string; + "settings-info-app-console": string; + "settings-info-app-default-file-encoding": string; + "settings-info-app-exclude-folders": string; + "settings-info-app-floating-button": string; + "settings-info-app-font-manager": string; + "settings-info-app-fullscreen": string; + "settings-info-app-keybindings": string; + "settings-info-app-keyboard-mode": string; + "settings-info-app-language": string; + "settings-info-app-open-file-list-position": string; + "settings-info-app-quick-tools-settings": string; + "settings-info-app-quick-tools-trigger-mode": string; + "settings-info-app-remember-files": string; + "settings-info-app-remember-folders": string; + "settings-info-app-retry-remote-fs": string; + "settings-info-app-side-buttons": string; + "settings-info-app-sponsor-sidebar": string; + "settings-info-app-touch-move-threshold": string; + "settings-info-app-ui-zoom": string; + "settings-info-app-vibrate-on-tap": string; + "settings-info-editor-autosave": string; + "settings-info-editor-color-preview": string; + "settings-info-editor-fade-fold-widgets": string; + "settings-info-editor-font-family": string; + "settings-info-editor-font-size": string; + "settings-info-editor-format-on-save": string; + "settings-info-editor-hard-wrap": string; + "settings-info-editor-indent-guides": string; + "settings-info-editor-line-height": string; + "settings-info-editor-line-numbers": string; + "settings-info-editor-lint-gutter": string; + "settings-info-editor-live-autocomplete": string; + "settings-info-editor-local-word-completion": string; + "settings-info-editor-language-completion": string; + "settings-info-editor-recommend-extensions": string; + "extension recommendation title": string; + "extension recommendation message": string; + "extension request title": string; + "extension request message": string; + "search plugins": string; + "request plugin": string; + "settings-info-editor-auto-close-tags": string; + "settings-info-editor-auto-rename-tags": string; + "settings-info-editor-rainbow-brackets": string; + "settings-info-editor-relative-line-numbers": string; + "settings-info-editor-rtl-text": string; + "settings-info-editor-scroll-settings": string; + "settings-info-editor-shift-click-selection": string; + "settings-info-editor-show-share-button": string; + "settings-info-editor-show-spaces": string; + "settings-info-editor-soft-tab": string; + "settings-info-editor-tab-size": string; + "settings-info-editor-teardrop-size": string; + "settings-info-editor-text-wrap": string; + "settings-info-lsp-add-custom-server": string; + "settings-info-lsp-allow-non-terminal-workspace": string; + "settings-info-lsp-edit-init-options": string; + "settings-info-lsp-install-server": string; + "settings-info-lsp-remove-custom-server": string; + "settings-info-lsp-server-enabled": string; + "settings-info-lsp-startup-timeout": string; + "settings-info-lsp-uninstall-server": string; + "settings-info-lsp-update-server": string; + "settings-info-lsp-view-init-options": string; + "settings-info-main-ad-rewards": string; + "settings-info-main-app-settings": string; + "settings-info-main-backup-restore": string; + "settings-info-main-changelog": string; + "settings-info-main-edit-settings": string; + "settings-info-main-editor-settings": string; + "settings-info-main-formatter": string; + "settings-info-main-lsp-settings": string; + "settings-info-main-plugins": string; + "settings-info-main-preview-settings": string; + "settings-info-main-rateapp": string; + "settings-info-main-remove-ads": string; + "settings-info-main-reset": string; + "settings-info-main-sponsors": string; + "settings-info-main-terminal-settings": string; + "settings-info-main-theme": string; + "settings-info-preview-disable-cache": string; + "settings-info-preview-host": string; + "settings-info-preview-mode": string; + "settings-info-preview-preview-port": string; + "settings-info-preview-server-port": string; + "settings-info-preview-show-console-toggler": string; + "settings-info-preview-use-current-file": string; + "settings-info-terminal-convert-eol": string; + "settings-note-formatter-settings": string; + "settings-note-lsp-settings": string; + "lsp-allow-non-terminal-workspace": string; + "search result label singular": string; + "search result label plural": string; + "pin tab": string; + "unpin tab": string; + "pinned tab": string; + "unpin tab before closing": string; + "app font": string; + "settings-info-app-font-family": string; + "unsaved selected tabs warning": string; + "save selected tabs": string; + "close selected tabs": string; + "save selected tabs warning": string; + "close selected tabs warning": string; + "close tabs to right": string; + "close tabs to left": string; + "close other tabs": string; + "plugin-not-supported": string; + "plugin-not-supported-info": string; + "login-to-view": string; + "iap-plugin-purchase-warning": string; + "iap-pro-purchase-warning": string; + "confirm-login": string; + "terminal:failsafe": string; + "terminal:failsafe-info": string; + "compact": string; + "off": string; + "quick tools height": string; + "quick tools toggler": string; + "terminal:block": string; + "terminal:underline": string; + "terminal:bar": string; + "terminal:inactive block": string; + "terminal:inactive underline": string; + "terminal:inactive bar": string; + "terminal:inactive none": string; + "terminal:normal": string; + "terminal:bold": string; + "quicktools-trigger:click": string; + "quicktools-trigger:touch": string; + "settings-info-terminal-uninstall": string; + "terminal:inactive outline": string; + "restored successfully": string; + "uninstalled successfully": string; + "enter plugin source": string; + "enter keywords": string; + "enter author name": string; + "update available": string; + "update available info": string; + "plugin updates": string; + "plugin updates singular": string; + "plugin updates plural": string; + "just now": string; + "day singular": string; + "hour singular": string; + "min singular": string; + "day plural": string; + "hour plural": string; + "min plural": string; + "settings-category-builtin-servers": string; + "settings-category-plugin-servers": string; + "active processes": string; + "total memory": string; + "uptime": string; + "note": string; + "acode main process": string; + "ppid parent": string; + "unknown": string; + "just started": string; + "diff days": string; + "diff hr": string; + "diff min": string; + "diff sec": string; + "command": string; + "managed": string; + "acode service": string; }; declare var strings: LangStrings; diff --git a/src/lang/ir-fa.json b/src/lang/ir-fa.json index 84b8f04d7..8c2ac9da5 100644 --- a/src/lang/ir-fa.json +++ b/src/lang/ir-fa.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/it-it.json b/src/lang/it-it.json index bef19fda7..e33878927 100644 --- a/src/lang/it-it.json +++ b/src/lang/it-it.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/ja-jp.json b/src/lang/ja-jp.json index 3bdcbf836..c1d28ba35 100644 --- a/src/lang/ja-jp.json +++ b/src/lang/ja-jp.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/ko-kr.json b/src/lang/ko-kr.json index a93da9398..42963a18f 100644 --- a/src/lang/ko-kr.json +++ b/src/lang/ko-kr.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/ml-in.json b/src/lang/ml-in.json index 6951c93b3..ee8052f1a 100644 --- a/src/lang/ml-in.json +++ b/src/lang/ml-in.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/mm-unicode.json b/src/lang/mm-unicode.json index e0f0f67b6..e74101b9f 100644 --- a/src/lang/mm-unicode.json +++ b/src/lang/mm-unicode.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/mm-zawgyi.json b/src/lang/mm-zawgyi.json index c9fe4e2d8..772654689 100644 --- a/src/lang/mm-zawgyi.json +++ b/src/lang/mm-zawgyi.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/pl-pl.json b/src/lang/pl-pl.json index ace3330fe..76f7e05b3 100644 --- a/src/lang/pl-pl.json +++ b/src/lang/pl-pl.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/pt-br.json b/src/lang/pt-br.json index da328a107..facba76b0 100644 --- a/src/lang/pt-br.json +++ b/src/lang/pt-br.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/pu-in.json b/src/lang/pu-in.json index a51da85db..2daa7dee9 100644 --- a/src/lang/pu-in.json +++ b/src/lang/pu-in.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/ru-ru.json b/src/lang/ru-ru.json index 2d823fcfe..8e101865d 100644 --- a/src/lang/ru-ru.json +++ b/src/lang/ru-ru.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/tl-ph.json b/src/lang/tl-ph.json index 01799a698..ddf0162be 100644 --- a/src/lang/tl-ph.json +++ b/src/lang/tl-ph.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/tr-tr.json b/src/lang/tr-tr.json index f88b34c48..6154499ba 100644 --- a/src/lang/tr-tr.json +++ b/src/lang/tr-tr.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/uk-ua.json b/src/lang/uk-ua.json index 2e4ae9354..080ea08dd 100644 --- a/src/lang/uk-ua.json +++ b/src/lang/uk-ua.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/uz-uz.json b/src/lang/uz-uz.json index 0d0ed9b76..15dc46c84 100644 --- a/src/lang/uz-uz.json +++ b/src/lang/uz-uz.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/vi-vn.json b/src/lang/vi-vn.json index 5b8c745c2..14e338c47 100644 --- a/src/lang/vi-vn.json +++ b/src/lang/vi-vn.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/zh-cn.json b/src/lang/zh-cn.json index 1ac42123c..a517f4eca 100644 --- a/src/lang/zh-cn.json +++ b/src/lang/zh-cn.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/zh-hant.json b/src/lang/zh-hant.json index 3accd75e3..68e3cb1ba 100644 --- a/src/lang/zh-hant.json +++ b/src/lang/zh-hant.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } diff --git a/src/lang/zh-tw.json b/src/lang/zh-tw.json index 1700c507c..d42f8b752 100644 --- a/src/lang/zh-tw.json +++ b/src/lang/zh-tw.json @@ -829,5 +829,7 @@ "diff sec": "{sec}s ago", "command": "Command", "managed": "Managed", - "acode service": "Acode Service" + "acode service": "Acode Service", + "info-terminal-show-scrollbar": "Show the xterm scrollbar beside the terminal.", + "terminal:show scrollbar": "Show Scrollbar" } From bd157bf87dc3382be8fb0168805ca8e860ce841b Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:27:50 +0530 Subject: [PATCH 4/6] fix --- src/components/terminal/terminal.js | 36 ++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/terminal/terminal.js b/src/components/terminal/terminal.js index 70808ec2e..76c09a882 100644 --- a/src/components/terminal/terminal.js +++ b/src/components/terminal/terminal.js @@ -74,6 +74,7 @@ export default class TerminalComponent { this.parsedAppKeybindingsVersion = -1; this.boundNativeSelectionMenuHandler = null; this.visibleScrollbarWidth = undefined; + this.lastRequestedServerSize = null; this.init(); } @@ -809,7 +810,7 @@ export default class TerminalComponent { // Focus terminal and ensure it's ready this.terminal.focus(); - this.fit(); + void this.fitAndResizeTerminal(true); if (!settled) { settled = true; @@ -872,6 +873,9 @@ export default class TerminalComponent { */ async resizeTerminal(cols, rows) { if (!this.pid || !this.serverMode) return; + const resizeKey = `${cols}x${rows}`; + if (this.lastRequestedServerSize === resizeKey) return; + this.lastRequestedServerSize = resizeKey; try { await new Promise((resolve, reject) => { @@ -887,6 +891,9 @@ export default class TerminalComponent { ); }); } catch (error) { + if (this.lastRequestedServerSize === resizeKey) { + this.lastRequestedServerSize = null; + } console.error("Failed to resize terminal:", error); } } @@ -900,6 +907,27 @@ export default class TerminalComponent { } } + /** + * Fit the client and immediately synchronize dimensions to the PTY. + * @param {boolean} forceServerSync Sync even when fitting kept the same size + */ + async fitAndResizeTerminal(forceServerSync = false) { + if (!this.terminal || !this.fitAddon) return; + + const previousCols = this.terminal.cols; + const previousRows = this.terminal.rows; + this.fit(); + + if ( + this.serverMode && + (forceServerSync || + this.terminal.cols !== previousCols || + this.terminal.rows !== previousRows) + ) { + await this.resizeTerminal(this.terminal.cols, this.terminal.rows); + } + } + /** * Write data to terminal * @param {string} data - Data to write @@ -1009,7 +1037,9 @@ export default class TerminalComponent { updateScrollbarVisibility(visible) { if (!this.terminal) return; - const overviewRuler = { ...this.terminal.options.overviewRuler }; + const overviewRuler = { + ...(this.terminal.options.overviewRuler ?? {}), + }; if (visible === false) { if ( !this.terminal.element?.classList.contains("terminal-scrollbar-hidden") @@ -1032,7 +1062,7 @@ export default class TerminalComponent { requestAnimationFrame(() => { if (!this.terminal) return; - this.fitAddon?.fit(); + void this.fitAndResizeTerminal(); }); } From eea6a3f5cf894edb04477579778edc34ee98c31f Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:34:19 +0530 Subject: [PATCH 5/6] fix: selection flicker when window resize --- src/components/terminal/terminal.js | 11 ++++-- .../terminal/terminalTouchSelection.js | 34 ++++++++++++++++--- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/components/terminal/terminal.js b/src/components/terminal/terminal.js index 76c09a882..8f1647e0e 100644 --- a/src/components/terminal/terminal.js +++ b/src/components/terminal/terminal.js @@ -870,11 +870,12 @@ export default class TerminalComponent { * Resize terminal * @param {number} cols - Number of columns * @param {number} rows - Number of rows + * @param {boolean} force - Send even if these dimensions were requested before */ - async resizeTerminal(cols, rows) { + async resizeTerminal(cols, rows, force = false) { if (!this.pid || !this.serverMode) return; const resizeKey = `${cols}x${rows}`; - if (this.lastRequestedServerSize === resizeKey) return; + if (!force && this.lastRequestedServerSize === resizeKey) return; this.lastRequestedServerSize = resizeKey; try { @@ -924,7 +925,11 @@ export default class TerminalComponent { this.terminal.cols !== previousCols || this.terminal.rows !== previousRows) ) { - await this.resizeTerminal(this.terminal.cols, this.terminal.rows); + await this.resizeTerminal( + this.terminal.cols, + this.terminal.rows, + forceServerSync, + ); } } diff --git a/src/components/terminal/terminalTouchSelection.js b/src/components/terminal/terminalTouchSelection.js index 8a95642f9..54d642cef 100644 --- a/src/components/terminal/terminalTouchSelection.js +++ b/src/components/terminal/terminalTouchSelection.js @@ -196,6 +196,8 @@ export default class TerminalTouchSelection { this.scrollEndDelay = 100; this.selectionRenderFrame = null; this.selectionResizeTimeout = null; + this.orientationResizeTimeout = null; + this.resizeSettleDelay = 150; this.init(); } @@ -661,13 +663,23 @@ export default class TerminalTouchSelection { } onOrientationChange() { - // Update cell dimensions and handle positions after orientation change - setTimeout(() => { + // Keyboard animation emits a burst of window resize events. Only update + // handles after the geometry settles, and never resurrect handles while + // xterm's selection is temporarily cleared by its resize operation. + if (this.orientationResizeTimeout) { + clearTimeout(this.orientationResizeTimeout); + } + this.orientationResizeTimeout = setTimeout(() => { + this.orientationResizeTimeout = null; this.updateCellDimensions(); - if (this.isSelecting) { + if ( + this.isSelecting && + !this.selectionResizeTimeout && + this.terminal.hasSelection() + ) { this.updateHandlePositions(); } - }, 100); + }, this.resizeSettleDelay); } onTerminalScroll() { @@ -699,6 +711,14 @@ export default class TerminalTouchSelection { onTerminalResize() { // xterm 6 clears its selection on vertical resize. Debounce the keyboard's // intermediate sizes, then restore our range using absolute buffer rows. + if (this.isSelecting) { + this.hideHandles(); + this.hideContextMenu(true); + if (this.selectionRenderFrame) { + cancelAnimationFrame(this.selectionRenderFrame); + this.selectionRenderFrame = null; + } + } if (this.selectionResizeTimeout) { clearTimeout(this.selectionResizeTimeout); } @@ -732,7 +752,7 @@ export default class TerminalTouchSelection { this.hideContextMenu(true); this.finalizeSelection(); - }, 50); + }, this.resizeSettleDelay); } startSelection(touch) { @@ -1288,6 +1308,10 @@ export default class TerminalTouchSelection { clearTimeout(this.selectionResizeTimeout); this.selectionResizeTimeout = null; } + if (this.orientationResizeTimeout) { + clearTimeout(this.orientationResizeTimeout); + this.orientationResizeTimeout = null; + } // Clear protection timeout if (this.protectionTimeout) { From 6b177e20f40985c24960be4cc6b5918c1d9db747 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:44:44 +0530 Subject: [PATCH 6/6] fix(terminal): wait for AXS server readiness before creating session --- src/components/terminal/terminal.js | 62 ++++++++++++++++++++-------- src/plugins/terminal/www/Terminal.js | 15 ++++--- 2 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/components/terminal/terminal.js b/src/components/terminal/terminal.js index 8f1647e0e..82100572f 100644 --- a/src/components/terminal/terminal.js +++ b/src/components/terminal/terminal.js @@ -16,7 +16,6 @@ import { getResolvedKeyBindings, getResolvedKeyBindingsVersion, } from "cm/commandRegistry"; -import toast from "components/toast"; import confirm from "dialogs/confirm"; import fonts from "lib/fonts"; import appSettings from "lib/settings"; @@ -704,25 +703,12 @@ export default class TerminalComponent { console.error, terminalValues.failsafeMode, ); - - // Check if AXS started with interval polling - const maxRetries = 10; - let retries = 0; - while (retries < maxRetries) { - await new Promise((resolve) => setTimeout(resolve, 1000)); - if (await Terminal.isAxsRunning()) { - break; - } - retries++; - } - - // If AXS still not running after retries, throw error - if (!(await Terminal.isAxsRunning())) { - toast("Failed to start AXS server after multiple attempts"); - //throw new Error("Failed to start AXS server after multiple attempts"); - } } + // A live AXS process does not guarantee that its HTTP listener is ready. + // This is especially noticeable during a cold app start. + await this.waitForServerReady(); + const requestBody = { cols: this.terminal.cols, rows: this.terminal.rows, @@ -754,6 +740,46 @@ export default class TerminalComponent { } } + /** + * Wait until the AXS HTTP server is accepting requests. + * @param {number} maxAttempts - Maximum number of readiness checks + * @param {number} retryDelay - Delay between checks in milliseconds + */ + async waitForServerReady(maxAttempts = 20, retryDelay = 500) { + const statusUrl = `http://127.0.0.1:${this.options.port}/status`; + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + try { + const response = await new Promise((resolve, reject) => { + cordova.plugin.http.sendRequest( + statusUrl, + { method: "GET", responseType: "text" }, + resolve, + reject, + ); + }); + + if ( + response.status >= 200 && + response.status < 300 && + response.data?.trim() === "OK" + ) { + return; + } + } catch { + // Connection failures are expected while AXS is binding its port. + } + + if (attempt < maxAttempts - 1) { + await new Promise((resolve) => setTimeout(resolve, retryDelay)); + } + } + + throw new Error( + `AXS terminal server did not become ready on port ${this.options.port}`, + ); + } + /** * Connect to terminal session via WebSocket * @param {string} pid - Terminal PID diff --git a/src/plugins/terminal/www/Terminal.js b/src/plugins/terminal/www/Terminal.js index ea4431b9a..e6332b32f 100644 --- a/src/plugins/terminal/www/Terminal.js +++ b/src/plugins/terminal/www/Terminal.js @@ -68,12 +68,17 @@ const Terminal = { }); }); } else { - Executor.start("sh", (type, data) => { - //console[type === "stderr" ? "error" : "log"](`[AXS] ${data}`); - logger(`${type} ${data}`); - }).then(async (uuid) => { + try { + const uuid = await Executor.start("sh", (type, data) => { + //console[type === "stderr" ? "error" : "log"](`[AXS] ${data}`); + logger(`${type} ${data}`); + }); await Executor.write(uuid, `source ${filesDir}/init-sandbox.sh ${installing ? "--installing" : ""} ${failsafeArg}; exit`); - }); + } catch (error) { + const message = `Failed to start AXS: ${formatError(error)}`; + err_logger(message); + throw new Error(message); + } } },