mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-31 16:21:50 +03:00
fix(tui): suppress terminal scrollbar glyphs
This commit is contained in:
@@ -20,6 +20,18 @@ const options: AppOptions = {
|
|||||||
theme: "auto",
|
theme: "auto",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface HiddenScrollBar {
|
||||||
|
visible: boolean
|
||||||
|
slider: { visible: boolean }
|
||||||
|
startArrow: { visible: boolean }
|
||||||
|
endArrow: { visible: boolean }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HiddenScrollBox {
|
||||||
|
verticalScrollBar: HiddenScrollBar
|
||||||
|
horizontalScrollBar: HiddenScrollBar
|
||||||
|
}
|
||||||
|
|
||||||
function occurrences(frame: string, value: string): number {
|
function occurrences(frame: string, value: string): number {
|
||||||
return frame.split(value).length - 1
|
return frame.split(value).length - 1
|
||||||
}
|
}
|
||||||
@@ -718,6 +730,8 @@ describe("NanobotTui layout", () => {
|
|||||||
shell: { backgroundColor: { intent: string } }
|
shell: { backgroundColor: { intent: string } }
|
||||||
composerFrame: { backgroundColor: { intent: string } }
|
composerFrame: { backgroundColor: { intent: string } }
|
||||||
composer: { backgroundColor: { intent: string } }
|
composer: { backgroundColor: { intent: string } }
|
||||||
|
transcript: { root: HiddenScrollBox }
|
||||||
|
diffViewer: { scroll: HiddenScrollBox }
|
||||||
}
|
}
|
||||||
const lines = setup.captureSpans().lines
|
const lines = setup.captureSpans().lines
|
||||||
const spans = lines.flatMap((line) => line.spans)
|
const spans = lines.flatMap((line) => line.spans)
|
||||||
@@ -730,6 +744,14 @@ describe("NanobotTui layout", () => {
|
|||||||
expect(internals.composer.backgroundColor.intent).toBe("default")
|
expect(internals.composer.backgroundColor.intent).toBe("default")
|
||||||
expect(spans.length).toBeGreaterThan(0)
|
expect(spans.length).toBeGreaterThan(0)
|
||||||
expect(brandedRows).toHaveLength(0)
|
expect(brandedRows).toHaveLength(0)
|
||||||
|
for (const scrollBox of [internals.transcript.root, internals.diffViewer.scroll]) {
|
||||||
|
for (const bar of [scrollBox.verticalScrollBar, scrollBox.horizontalScrollBar]) {
|
||||||
|
expect(bar.visible).toBeFalse()
|
||||||
|
expect(bar.slider.visible).toBeFalse()
|
||||||
|
expect(bar.startArrow.visible).toBeFalse()
|
||||||
|
expect(bar.endArrow.visible).toBeFalse()
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
test("rethemes the complete retained interface when the terminal appearance changes", async () => {
|
test("rethemes the complete retained interface when the terminal appearance changes", async () => {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
} from "@opentui/core"
|
} from "@opentui/core"
|
||||||
|
|
||||||
import type { FileEditEvent, HistoryMessage } from "./protocol"
|
import type { FileEditEvent, HistoryMessage } from "./protocol"
|
||||||
|
import { hideScrollbars } from "./scrollbox"
|
||||||
|
|
||||||
export interface DiffViewerTheme {
|
export interface DiffViewerTheme {
|
||||||
text: string
|
text: string
|
||||||
@@ -152,9 +153,10 @@ export class DiffViewer {
|
|||||||
paddingTop: 1,
|
paddingTop: 1,
|
||||||
paddingBottom: 1,
|
paddingBottom: 1,
|
||||||
},
|
},
|
||||||
verticalScrollbarOptions: { visible: true },
|
verticalScrollbarOptions: { visible: false },
|
||||||
horizontalScrollbarOptions: { visible: false },
|
horizontalScrollbarOptions: { visible: false },
|
||||||
})
|
})
|
||||||
|
hideScrollbars(this.scroll)
|
||||||
this.footer = new TextRenderable(renderer, {
|
this.footer = new TextRenderable(renderer, {
|
||||||
id: "nanobot-tui-diff-footer",
|
id: "nanobot-tui-diff-footer",
|
||||||
content: "←/→ file · pgup/pgdn scroll · esc close",
|
content: "←/→ file · pgup/pgdn scroll · esc close",
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import type { ScrollBoxRenderable } from "@opentui/core"
|
||||||
|
|
||||||
|
/** Keep scrolling functional without drawing terminal-dependent block glyphs. */
|
||||||
|
export function hideScrollbars(scrollBox: ScrollBoxRenderable): void {
|
||||||
|
for (const bar of [scrollBox.verticalScrollBar, scrollBox.horizontalScrollBar]) {
|
||||||
|
// ScrollBar can make itself visible again when content starts overflowing.
|
||||||
|
// Hiding its children as well keeps embedded terminals deterministic.
|
||||||
|
bar.visible = false
|
||||||
|
bar.showArrows = false
|
||||||
|
bar.slider.visible = false
|
||||||
|
bar.startArrow.visible = false
|
||||||
|
bar.endArrow.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
} from "@opentui/core"
|
} from "@opentui/core"
|
||||||
|
|
||||||
import type { FileEditEvent, HistoryMessage, ToolProgressEvent } from "./protocol"
|
import type { FileEditEvent, HistoryMessage, ToolProgressEvent } from "./protocol"
|
||||||
|
import { hideScrollbars } from "./scrollbox"
|
||||||
|
|
||||||
export interface TranscriptTheme {
|
export interface TranscriptTheme {
|
||||||
text: string
|
text: string
|
||||||
@@ -88,8 +89,7 @@ export class Transcript {
|
|||||||
horizontalScrollbarOptions: { visible: false },
|
horizontalScrollbarOptions: { visible: false },
|
||||||
onMouseScroll: () => this.scheduleNavigationUpdate(),
|
onMouseScroll: () => this.scheduleNavigationUpdate(),
|
||||||
})
|
})
|
||||||
this.root.verticalScrollBar.visible = false
|
hideScrollbars(this.root)
|
||||||
this.root.horizontalScrollBar.visible = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setTheme(theme: TranscriptTheme): void {
|
setTheme(theme: TranscriptTheme): void {
|
||||||
@@ -151,7 +151,7 @@ export class Transcript {
|
|||||||
this.wrote = false
|
this.wrote = false
|
||||||
this.nextId = 0
|
this.nextId = 0
|
||||||
this.navigation = { awayFromBottom: false, unseenOutput: false }
|
this.navigation = { awayFromBottom: false, unseenOutput: false }
|
||||||
this.root.verticalScrollBar.visible = false
|
hideScrollbars(this.root)
|
||||||
this.header(header)
|
this.header(header)
|
||||||
this.emitNavigation()
|
this.emitNavigation()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user