Skip to content

Commit e3af401

Browse files
committed
perf: image select and clear
1 parent d81d776 commit e3af401

3 files changed

Lines changed: 56 additions & 9 deletions

File tree

internal/ui/imageinput/imageparse_test.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,3 @@ func TestLoadFile(t *testing.T) {
109109
t.Errorf("mime = %q, want image/png", block.Image.MimeType)
110110
}
111111
}
112-
113-
func TestLoadFile_NotFound(t *testing.T) {
114-
_, err := LoadFile("/nonexistent/path.png")
115-
if err == nil {
116-
t.Fatal("expected error for missing file")
117-
}
118-
}

internal/ui/tui/model.go

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tui
22

33
import (
44
"fmt"
5+
"slices"
56
"strings"
67
"time"
78

@@ -86,6 +87,7 @@ type Model struct {
8687
ShowSummary bool
8788
RunStats runStats
8889
Images []agentcore.ContentBlock // attached images (from Ctrl+V clipboard paste)
90+
ImageCursor int // -1 = not selecting; 0+ = selected image index
8991
Pasting int // number of async image reads in progress (clipboard paste or drag-drop)
9092

9193
Glamour *glamour.TermRenderer
@@ -148,6 +150,7 @@ func New(driver Driver, modelName string, cfg ...Config) Model {
148150
Cwd: c.Cwd,
149151
GitBranch: c.GitBranch,
150152
ShowWelcome: true,
153+
ImageCursor: -1,
151154
config: c,
152155
}
153156
}
@@ -282,9 +285,20 @@ func (m Model) View() string {
282285
if len(m.Images) > 0 {
283286
var tags []string
284287
for i := range m.Images {
285-
tags = append(tags, fmt.Sprintf("[Image #%d]", i+1))
288+
tag := fmt.Sprintf("[Image #%d]", i+1)
289+
if m.ImageCursor == i {
290+
tags = append(tags, ImageSelectedStyle.Render(tag))
291+
} else {
292+
tags = append(tags, CommandStyle.Render(tag))
293+
}
286294
}
287-
parts = append(parts, CommandStyle.Render(strings.Join(tags, " ")))
295+
line := strings.Join(tags, " ")
296+
if m.ImageCursor >= 0 {
297+
line += " " + MutedStyle.Render("Delete to remove · Esc to cancel")
298+
} else {
299+
line += " " + MutedStyle.Render("(↑ to select)")
300+
}
301+
parts = append(parts, line)
288302
}
289303
parts = append(parts, SeparatorStyle.Render(strings.Repeat("─", m.Width)))
290304
parts = append(parts, m.Input.View())
@@ -343,6 +357,35 @@ func (m Model) handleKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
343357
}
344358
}
345359

360+
// Image selection mode: navigate and delete attached images.
361+
if m.ImageCursor >= 0 {
362+
switch msg.String() {
363+
case "left", "h":
364+
if m.ImageCursor > 0 {
365+
m.ImageCursor--
366+
}
367+
return m, nil
368+
case "right", "l":
369+
if m.ImageCursor < len(m.Images)-1 {
370+
m.ImageCursor++
371+
}
372+
return m, nil
373+
case "delete", "backspace":
374+
m.Images = slices.Delete(m.Images, m.ImageCursor, m.ImageCursor+1)
375+
if len(m.Images) == 0 {
376+
m.ImageCursor = -1
377+
} else if m.ImageCursor >= len(m.Images) {
378+
m.ImageCursor = len(m.Images) - 1
379+
}
380+
return m, nil
381+
case "esc", "down":
382+
m.ImageCursor = -1
383+
return m, nil
384+
}
385+
// Other keys (ctrl+c, enter, etc.): exit selection, fall through to normal handling.
386+
m.ImageCursor = -1
387+
}
388+
346389
switch msg.String() {
347390
case "ctrl+c":
348391
if m.QuitPending {
@@ -393,6 +436,7 @@ func (m Model) handleKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
393436
}
394437
images := m.Images
395438
m.Images = nil
439+
m.ImageCursor = -1
396440
m.Input.Reset()
397441
m.Input.SetHeight(1)
398442
m.ShowSummary = false
@@ -422,6 +466,13 @@ func (m Model) handleKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
422466
output += "\n" + ErrorStyle.Render(" error: "+err.Error())
423467
}
424468
return m, tea.Println(output)
469+
470+
case "up":
471+
// Enter image selection when cursor is on the first line of input.
472+
if len(m.Images) > 0 && !m.Running && m.Input.Line() == 0 {
473+
m.ImageCursor = len(m.Images) - 1
474+
return m, nil
475+
}
425476
}
426477

427478
var cmd tea.Cmd

internal/ui/tui/styles.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ var ErrorStyle = lipgloss.NewStyle().
5050
var CommandStyle = lipgloss.NewStyle().
5151
Foreground(ColorCommand)
5252

53+
// Image tag selected (reverse video highlight)
54+
var ImageSelectedStyle = lipgloss.NewStyle().Reverse(true)
55+
5356
// Separator
5457
var SeparatorStyle = lipgloss.NewStyle().
5558
Foreground(ColorSeparator)

0 commit comments

Comments
 (0)