mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-09-01 16:51:53 +03:00
fix(tui): preserve input typed after submit
This commit is contained in:
@@ -253,6 +253,23 @@ describe("NanobotTui layout", () => {
|
|||||||
expect(sent).toEqual(["你好"])
|
expect(sent).toEqual(["你好"])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("keeps input typed immediately after Enter in the next draft", async () => {
|
||||||
|
const sent: string[] = []
|
||||||
|
setup = await createRenderer({ width: 72, height: 20, screenMode: "alternate-screen" })
|
||||||
|
const app = mount(setup, sent)
|
||||||
|
app.accept({ event: "attached", chat_id: "chat" })
|
||||||
|
await Bun.sleep(1)
|
||||||
|
const composer = (app as unknown as { composer: TextareaRenderable }).composer
|
||||||
|
|
||||||
|
composer.setText("first")
|
||||||
|
setup.mockInput.pressEnter()
|
||||||
|
for (const key of "next") setup.mockInput.pressKey(key)
|
||||||
|
await waitUntil(() => sent.length > 0)
|
||||||
|
|
||||||
|
expect(sent).toEqual(["first"])
|
||||||
|
expect(composer.plainText).toBe("next")
|
||||||
|
})
|
||||||
|
|
||||||
test("inserts newlines with Shift+Enter and the universal Ctrl+J fallback", async () => {
|
test("inserts newlines with Shift+Enter and the universal Ctrl+J fallback", async () => {
|
||||||
const sent: string[] = []
|
const sent: string[] = []
|
||||||
setup = await createRenderer({
|
setup = await createRenderer({
|
||||||
|
|||||||
+22
-7
@@ -733,7 +733,10 @@ export class NanobotTui {
|
|||||||
// IMEs may commit their final composed glyph after Enter. Matching the
|
// IMEs may commit their final composed glyph after Enter. Matching the
|
||||||
// OpenCode/OpenTUI integration, defer twice before reading plainText.
|
// OpenCode/OpenTUI integration, defer twice before reading plainText.
|
||||||
onSubmit: () => this.deferSubmit(),
|
onSubmit: () => this.deferSubmit(),
|
||||||
onPaste: (event) => this.handlePaste(event),
|
onPaste: (event) => {
|
||||||
|
this.flushSubmit()
|
||||||
|
if (!this.composer.isDestroyed) this.handlePaste(event)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
this.status = new TextRenderable(renderer, {
|
this.status = new TextRenderable(renderer, {
|
||||||
id: "nanobot-tui-status",
|
id: "nanobot-tui-status",
|
||||||
@@ -855,12 +858,15 @@ export class NanobotTui {
|
|||||||
if (this.submitPending) return
|
if (this.submitPending) return
|
||||||
this.submitPending = true
|
this.submitPending = true
|
||||||
const generation = ++this.submitGeneration
|
const generation = ++this.submitGeneration
|
||||||
setTimeout(() => setTimeout(() => {
|
setTimeout(() => setTimeout(() => this.flushSubmit(generation), 0), 0)
|
||||||
if (generation !== this.submitGeneration) return
|
}
|
||||||
this.submitPending = false
|
|
||||||
if (this.composer.isDestroyed) return
|
private flushSubmit(generation = this.submitGeneration): void {
|
||||||
this.submit()
|
if (!this.submitPending || generation !== this.submitGeneration) return
|
||||||
}, 0), 0)
|
this.submitPending = false
|
||||||
|
this.submitGeneration += 1
|
||||||
|
if (this.composer.isDestroyed) return
|
||||||
|
this.submit()
|
||||||
}
|
}
|
||||||
|
|
||||||
private submit(): void {
|
private submit(): void {
|
||||||
@@ -1575,6 +1581,15 @@ export class NanobotTui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleKey = (key: KeyEvent): void => {
|
private handleKey = (key: KeyEvent): void => {
|
||||||
|
// The app receives keypresses before the focused Textarea. Seal the pending
|
||||||
|
// submission first so this key is inserted into the next draft.
|
||||||
|
if (this.submitPending) {
|
||||||
|
this.flushSubmit()
|
||||||
|
if (this.quitting || this.composer.isDestroyed) {
|
||||||
|
key.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.diffViewer.visible) {
|
if (this.diffViewer.visible) {
|
||||||
if (key.ctrl && key.name === "c") {
|
if (key.ctrl && key.name === "c") {
|
||||||
const selected = this.renderer.getSelection()?.getSelectedText()
|
const selected = this.renderer.getSelection()?.getSelectedText()
|
||||||
|
|||||||
Reference in New Issue
Block a user