Forms: review r3 fix

This commit is contained in:
ZacharyZhang-NY committed 2026-10-05 13:15:30 -04:00
1 parent 634c5ec7fd
commit 49b3b7840a
3 files changed
+82 -7

No files matched your search

+20 -7
View File
@@ -172,14 +172,27 @@ func InputGroup(c *ui.Context, value *string, opts InputGroupOptions) InputGroup
return parts
}
// inputGroupEditor builds the input; a disabled one edits a copy, so queued input cannot reach value.
// inputGroupLock remembers locks so an unlocked input starts afresh.
type inputGroupLock struct {
locked bool
gen int
}
// inputGroupEditor builds the input, or plain selectable text while locked, so no edit command runs.
func inputGroupEditor(c *ui.Context, box *ui.Element, value *string, locked bool) *ui.Element {
if !locked {
return ui.TextInputBase(c, value)
lk := ui.Local(box, "lock", func() inputGroupLock { return inputGroupLock{} })
if lk.locked && !locked {
// A new identity drops the edits queued in the old editor while locked.
lk.gen++
}
shown := ui.Local(box, "locked", func() string { return *value })
*shown = *value
in := ui.TextInputBase(c, shown)
*shown = *value
lk.locked = locked
var in *ui.Element
ui.Row(c).Key(lk.gen).FillWidth().MinWidth(0).Children(func() {
if locked {
in = ui.Text(c, *value).SingleLine().Selectable()
} else {
in = ui.TextInputBase(c, value)
}
})
return in
}
+30
View File
@@ -141,3 +141,33 @@ func TestInputGroupHitAreasCompact(t *testing.T) {
t.Fatalf("button %v", r)
}
}
// Cut and paste after disabling a field with a selection change neither value nor clipboard.
func TestInputGroupDisabledEditCommands(t *testing.T) {
value, disabled, changes := "secret", false, 0
tt := ui.NewTester(func(c *ui.Context) {
Use(c, Settings{})
if InputGroup(c, &value, InputGroupOptions{Label: "Code", Disabled: disabled}).Changed() {
changes++
}
}, 400, 100)
_ = tt.Click("Code")
tt.Key(ui.Cmd, ui.KeyA)
tt.SetClipboard("clip")
disabled = true
tt.Frame()
tt.Key(ui.Cmd, ui.KeyX)
tt.Command("cut")
tt.Command("paste")
tt.Command("undo")
tt.Frame()
if value != "secret" || tt.Clipboard() != "clip" || changes != 0 {
t.Fatalf("value %q clipboard %q changes %d", value, tt.Clipboard(), changes)
}
disabled = false
tt.Frame()
tt.Frame()
if value != "secret" || tt.Clipboard() != "clip" || changes != 0 {
t.Fatalf("after enabling: value %q clipboard %q", value, tt.Clipboard())
}
}
+32
View File
@@ -144,3 +144,35 @@ func TestTagsInputDisabledAfterFocus(t *testing.T) {
t.Fatalf("tags %q changes %d", tags, n)
}
}
// Cut and paste after disabling with a selected draft change neither draft nor clipboard.
func TestTagsInputDisabledEditCommands(t *testing.T) {
tags, n, seen := []string{}, 0, ""
opts := TagsInputOptions{Label: "Tags", Validate: func(s string) string { seen = s; return "" }}
tt := ui.NewTester(func(c *ui.Context) {
Use(c, Settings{})
if TagsInput(c, &tags, opts).Changed() {
n++
}
}, 520, 200)
_ = tt.Click("Tags")
tt.Type("ivy")
tt.Key(ui.Cmd, ui.KeyA)
tt.SetClipboard("clip")
opts.Disabled = true
tt.Frame()
tt.Key(ui.Cmd, ui.KeyX)
tt.Command("cut")
tt.Command("paste")
tt.Frame()
if tt.Clipboard() != "clip" || n != 0 {
t.Fatalf("clipboard %q changes %d", tt.Clipboard(), n)
}
opts.Disabled = false
tt.Frame()
_ = tt.Click("Tags")
tt.Key(0, ui.KeyEnter)
if seen != "ivy" || tt.Clipboard() != "clip" || len(tags) != 1 {
t.Fatalf("draft %q clipboard %q tags %q", seen, tt.Clipboard(), tags)
}
}