fix(tui): completions: reposition popup on window resize

Ayman Bagabas created

Change summary

internal/tui/components/chat/editor/editor.go      |  9 +++++++++
internal/tui/components/completions/completions.go | 12 +++++++++---
internal/tui/page/chat/chat.go                     |  4 +++-
internal/tui/tui.go                                |  2 +-
4 files changed, 22 insertions(+), 5 deletions(-)

Detailed changes

internal/tui/components/chat/editor/editor.go 🔗

@@ -161,10 +161,19 @@ func (m *editorCmp) send() tea.Cmd {
 	)
 }
 
+func (m *editorCmp) repositionCompletions() tea.Msg {
+	cur := m.textarea.Cursor()
+	x := cur.X + m.x // adjust for padding
+	y := cur.Y + m.y + 1
+	return completions.RepositionCompletionsMsg{X: x, Y: y}
+}
+
 func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	var cmd tea.Cmd
 	var cmds []tea.Cmd
 	switch msg := msg.(type) {
+	case tea.WindowSizeMsg:
+		return m, m.repositionCompletions
 	case filepicker.FilePickedMsg:
 		if len(m.attachments) >= maxAttachments {
 			return m, util.ReportError(fmt.Errorf("cannot add more than %d images", maxAttachments))

internal/tui/components/completions/completions.go 🔗

@@ -29,6 +29,10 @@ type FilterCompletionsMsg struct {
 	Reopen bool
 }
 
+type RepositionCompletionsMsg struct {
+	X, Y int
+}
+
 type CompletionsClosedMsg struct{}
 
 type CompletionsOpenedMsg struct{}
@@ -52,6 +56,7 @@ type Completions interface {
 
 type completionsCmp struct {
 	wWidth    int // The window width
+	wHeight   int // The window height
 	width     int
 	lastWidth int
 	height    int  // Height of the completions component`
@@ -88,7 +93,7 @@ func New() Completions {
 	)
 	return &completionsCmp{
 		width:  0,
-		height: 0,
+		height: maxCompletionsHeight,
 		list:   l,
 		query:  "",
 		keyMap: completionsKeyMap,
@@ -107,8 +112,7 @@ func (c *completionsCmp) Init() tea.Cmd {
 func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	switch msg := msg.(type) {
 	case tea.WindowSizeMsg:
-		c.wWidth = msg.Width
-		c.height = min(msg.Height-c.y, 15)
+		c.wWidth, c.wHeight = msg.Width, msg.Height
 		return c, nil
 	case tea.KeyPressMsg:
 		switch {
@@ -159,6 +163,8 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		case key.Matches(msg, c.keyMap.Cancel):
 			return c, util.CmdHandler(CloseCompletionsMsg{})
 		}
+	case RepositionCompletionsMsg:
+		c.x, c.y = msg.X, msg.Y
 	case CloseCompletionsMsg:
 		c.open = false
 		return c, util.CmdHandler(CompletionsClosedMsg{})

internal/tui/page/chat/chat.go 🔗

@@ -165,7 +165,9 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		p.keyboardEnhancements = msg
 		return p, nil
 	case tea.WindowSizeMsg:
-		return p, p.SetSize(msg.Width, msg.Height)
+		u, cmd := p.editor.Update(msg)
+		p.editor = u.(editor.Editor)
+		return p, tea.Batch(p.SetSize(msg.Width, msg.Height), cmd)
 	case CancelTimerExpiredMsg:
 		p.isCanceling = false
 		return p, nil

internal/tui/tui.go 🔗

@@ -116,7 +116,7 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		return a, a.handleWindowResize(msg.Width, msg.Height)
 
 	// Completions messages
-	case completions.OpenCompletionsMsg, completions.FilterCompletionsMsg, completions.CloseCompletionsMsg:
+	case completions.OpenCompletionsMsg, completions.FilterCompletionsMsg, completions.CloseCompletionsMsg, completions.RepositionCompletionsMsg:
 		u, completionCmd := a.completions.Update(msg)
 		a.completions = u.(completions.Completions)
 		return a, completionCmd