1
0
Эх сурвалжийг харах

fix(tui): preserve burst form input

Kit Langton 2 өдөр өмнө
parent
commit
eb45ada74e

+ 6 - 3
packages/tui/src/mini/footer.form.tsx

@@ -71,6 +71,7 @@ export function RunFormBody(props: {
     return typeof value === "string" ? value : undefined
   })
   let area: TextareaRenderable | undefined
+  let editingReady = false
 
   createEffect(() => {
     setState((previous) => formSync(previous, props.request))
@@ -93,6 +94,7 @@ export function RunFormBody(props: {
       if (!area || area.isDestroyed || !state().editing) return
       area.focus()
       area.cursorOffset = area.plainText.length
+      editingReady = true
     })
   })
 
@@ -209,7 +211,6 @@ export function RunFormBody(props: {
       return
     }
     if (unsupported()) return
-    if (state().editing) return
     const character =
       !event.ctrl &&
       !event.meta &&
@@ -219,12 +220,14 @@ export function RunFormBody(props: {
       /^[^\p{C}\p{Zl}\p{Zp}]$/u.test(event.sequence)
         ? event.sequence
         : undefined
-    if (custom() && state().selected === rows().length && character) {
-      const next = formPick(state(), props.request)
+    if (custom() && state().selected === rows().length && character && !editingReady) {
+      const next = state().editing ? state() : formPick(state(), props.request)
+      if (!state().editing) editingReady = false
       setState(formSetDraft(next, current(), formInput(next, current()) + character))
       event.preventDefault()
       return
     }
+    if (state().editing) return
     if (
       event.name === "tab" ||
       event.name === "left" ||

+ 8 - 2
packages/tui/src/routes/session/form.tsx

@@ -67,6 +67,7 @@ export function FormPrompt(props: { form: FormWithLocation }) {
   })
 
   let textarea: TextareaRenderable | undefined
+  let editingReady = false
   let review: ScrollBoxRenderable | undefined
 
   const message = createMemo(() => {
@@ -178,13 +179,16 @@ export function FormPrompt(props: { form: FormWithLocation }) {
   onCleanup(
     keymap.intercept("key", ({ event, consume }) => {
       if (keymap.mode.current() !== FORM_MODE) return
-      if (store.editing || textual() || !other()) return
+      if (textual() || !other() || (store.editing && editingReady)) return
       if (event.ctrl || event.meta || event.option || event.super || event.hyper) return
       if (!/^[^\p{C}\p{Zl}\p{Zp}]$/u.test(event.sequence)) return
       const current = answerField()
       if (!current) return
       setStore("custom", { ...store.custom, [current.key]: input() + event.sequence })
-      setStore("editing", true)
+      if (!store.editing) {
+        editingReady = false
+        setStore("editing", true)
+      }
       consume()
     }),
   )
@@ -884,8 +888,10 @@ export function FormPrompt(props: { form: FormWithLocation }) {
                             textarea = val
                             val.traits = { status: "ANSWER" }
                             queueMicrotask(() => {
+                              val.setText(input())
                               val.focus()
                               val.gotoLineEnd()
+                              editingReady = true
                             })
                           }}
                           initialValue={input()}

+ 3 - 3
packages/tui/test/cli/tui/form.test.tsx

@@ -148,9 +148,9 @@ test("typing starts a highlighted custom answer without losing the first charact
     expect(prompt.app.renderer.currentFocusedEditor).toBeNull()
 
     prompt.app.mockInput.pressKey("j")
-    prompt.app.mockInput.pressKey("1")
-    await prompt.app.waitFor(() => prompt.app.renderer.currentFocusedEditor?.plainText === "1")
-    expect(prompt.app.renderer.currentFocusedEditor?.plainText).toBe("1")
+    await prompt.app.mockInput.typeText("123")
+    await prompt.app.waitFor(() => prompt.app.renderer.currentFocusedEditor?.plainText === "123")
+    expect(prompt.app.renderer.currentFocusedEditor?.plainText).toBe("123")
   } finally {
     prompt.app.renderer.destroy()
   }

+ 3 - 3
packages/tui/test/mini/footer.view.test.tsx

@@ -300,9 +300,9 @@ test("direct footer typing starts a highlighted custom answer without losing the
     expect(app.renderer.currentFocusedEditor).toBeNull()
 
     app.mockInput.pressKey("j")
-    app.mockInput.pressKey("h")
-    await app.waitFor(() => app.renderer.currentFocusedEditor?.plainText === "h")
-    expect(app.renderer.currentFocusedEditor?.plainText).toBe("h")
+    await app.mockInput.typeText("hello")
+    await app.waitFor(() => app.renderer.currentFocusedEditor?.plainText === "hello")
+    expect(app.renderer.currentFocusedEditor?.plainText).toBe("hello")
   } finally {
     app.cleanup()
   }