-
-
Notifications
You must be signed in to change notification settings - Fork 898
feat(platform): 优化Windows平台路径处理和SSH配置文件支持 #3220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
0574a6a
42ac2f2
a71f4de
b099994
2df61d4
239e177
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,3 +43,4 @@ docsite/ | |
| .superpowers | ||
| docs/superpowers | ||
| .claude | ||
| .idea/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import { describe, expect, it } from "vitest"; | ||
|
|
||
| import { getWheelLineDelta } from "./termutil"; | ||
|
|
||
| describe("getWheelLineDelta", () => { | ||
| it("returns 0 for zero and non-finite deltas", () => { | ||
| expect(getWheelLineDelta(0, 0, 16, 40)).toBe(0); | ||
| expect(getWheelLineDelta(Number.NaN, 0, 16, 40)).toBe(0); | ||
| expect(getWheelLineDelta(Number.POSITIVE_INFINITY, 0, 16, 40)).toBe(0); | ||
| expect(getWheelLineDelta(Number.NEGATIVE_INFINITY, 0, 16, 40)).toBe(0); | ||
| }); | ||
|
|
||
| it("converts pixel deltas using cell height", () => { | ||
| expect(getWheelLineDelta(32, 0, 16, 40)).toBe(2); | ||
| expect(getWheelLineDelta(-24, 0, 12, 40)).toBe(-2); | ||
| }); | ||
|
|
||
| it("keeps line deltas unchanged", () => { | ||
| expect(getWheelLineDelta(3, 1, 16, 40)).toBe(3); | ||
| expect(getWheelLineDelta(-2, 1, 16, 40)).toBe(-2); | ||
| }); | ||
|
|
||
| it("converts page deltas using row count", () => { | ||
| expect(getWheelLineDelta(1, 2, 16, 30)).toBe(30); | ||
| expect(getWheelLineDelta(-1, 2, 16, 18)).toBe(-18); | ||
| }); | ||
|
|
||
| it("falls back to sane defaults for invalid dimensions", () => { | ||
| expect(getWheelLineDelta(16, 0, 0, 0)).toBe(1); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -40,6 +40,7 @@ import { | |||||||||
| bufferLinesToText, | ||||||||||
| createTempFileFromBlob, | ||||||||||
| extractAllClipboardData, | ||||||||||
| getWheelLineDelta, | ||||||||||
| normalizeCursorStyle, | ||||||||||
| quoteForPosixShell, | ||||||||||
| } from "./termutil"; | ||||||||||
|
|
@@ -109,6 +110,7 @@ export class TermWrap { | |||||||||
| // xterm.js paste() method triggers onData event, which can cause duplicate sends | ||||||||||
| lastPasteData: string = ""; | ||||||||||
| lastPasteTime: number = 0; | ||||||||||
| wheelScrollRemainder: number = 0; | ||||||||||
|
|
||||||||||
| // dev only (for debugging) | ||||||||||
| recentWrites: { idx: number; data: string; ts: number }[] = []; | ||||||||||
|
|
@@ -313,6 +315,44 @@ export class TermWrap { | |||||||||
| this.connectElem.removeEventListener("drop", dropHandler); | ||||||||||
| }, | ||||||||||
| }); | ||||||||||
| const wheelHandler = (event: WheelEvent) => { | ||||||||||
| if (event.defaultPrevented || this.terminal.modes.mouseTrackingMode !== "none") { | ||||||||||
| return; | ||||||||||
| } | ||||||||||
| const target = event.target; | ||||||||||
| if (target instanceof Element && target.closest(".xterm-viewport") != null) { | ||||||||||
| return; | ||||||||||
| } | ||||||||||
| // This relies on xterm.js private internals (`_core._renderService`) because | ||||||||||
| // there is no public API for measured cell height yet; fall back to 16px | ||||||||||
| // (a conservative default line height) so wheel deltas still map to lines, | ||||||||||
| // and revisit this when xterm exposes public cell dimensions. | ||||||||||
| const cellHeight = (this.terminal as any)?._core?._renderService?.dimensions?.css?.cell?.height ?? 16; | ||||||||||
| const lineDelta = getWheelLineDelta(event.deltaY, event.deltaMode, cellHeight, this.terminal.rows); | ||||||||||
|
Comment on lines
+326
to
+327
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nullish coalescing doesn't guard against The The pattern in 🛡️ Suggested fix- const cellHeight = (this.terminal as any)?._core?._renderService?.dimensions?.css?.cell?.height ?? 16;
+ const cellHeight = (this.terminal as any)?._core?._renderService?.dimensions?.css?.cell?.height || 16;Alternatively, add an explicit guard: const cellHeight = (this.terminal as any)?._core?._renderService?.dimensions?.css?.cell?.height ?? 16;
+ if (cellHeight === 0) {
+ return;
+ }
const lineDelta = getWheelLineDelta(event.deltaY, event.deltaMode, cellHeight, this.terminal.rows);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
| if (lineDelta === 0) { | ||||||||||
| return; | ||||||||||
| } | ||||||||||
| this.wheelScrollRemainder += lineDelta; | ||||||||||
| const wholeLines = | ||||||||||
| this.wheelScrollRemainder > 0 | ||||||||||
| ? Math.floor(this.wheelScrollRemainder) | ||||||||||
| : Math.ceil(this.wheelScrollRemainder); | ||||||||||
| if (wholeLines === 0) { | ||||||||||
| event.preventDefault(); | ||||||||||
| event.stopPropagation(); | ||||||||||
| return; | ||||||||||
| } | ||||||||||
| this.wheelScrollRemainder -= wholeLines; | ||||||||||
| this.terminal.scrollLines(wholeLines); | ||||||||||
| event.preventDefault(); | ||||||||||
| event.stopPropagation(); | ||||||||||
| }; | ||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||||||
| this.connectElem.addEventListener("wheel", wheelHandler, { passive: false, capture: true }); | ||||||||||
| this.toDispose.push({ | ||||||||||
| dispose: () => { | ||||||||||
| this.connectElem.removeEventListener("wheel", wheelHandler, true); | ||||||||||
| }, | ||||||||||
| }); | ||||||||||
| this.handleResize(); | ||||||||||
| const pasteHandler = this.pasteHandler.bind(this); | ||||||||||
| this.connectElem.addEventListener("paste", pasteHandler, true); | ||||||||||
|
|
||||||||||
Uh oh!
There was an error while loading. Please reload this page.