diff --git a/internal/ui/chat/assistant.go b/internal/ui/chat/assistant.go index 66fe97e1bc5a7d6242200835a72136c098935ab1..331167bdc13d90233f881343ce607c07e0ef700c 100644 --- a/internal/ui/chat/assistant.go +++ b/internal/ui/chat/assistant.go @@ -230,3 +230,22 @@ func (a *AssistantMessageItem) SetMessage(message *message.Message) tea.Cmd { } return nil } + +// ToggleExpanded toggles the expanded state of the thinking box. +func (a *AssistantMessageItem) ToggleExpanded() { + a.thinkingExpanded = !a.thinkingExpanded + a.clearCache() +} + +// HandleMouseClick implements MouseClickable. +func (a *AssistantMessageItem) HandleMouseClick(btn ansi.MouseButton, x, y int) bool { + if btn != ansi.MouseLeft { + return false + } + // check if the click is within the thinking box + if a.thinkingBoxHeight > 0 && y < a.thinkingBoxHeight { + a.ToggleExpanded() + return true + } + return false +} diff --git a/internal/ui/chat/messages.go b/internal/ui/chat/messages.go index 3e12efefa4db1c9d78cbfe5a44374f4a918290f4..fe1e0c8f891c14f90c7e58cf8a99deb16d165765 100644 --- a/internal/ui/chat/messages.go +++ b/internal/ui/chat/messages.go @@ -26,11 +26,17 @@ type Identifiable interface { ID() string } +// Animatable is an interface for items that support animation. type Animatable interface { StartAnimation() tea.Cmd Animate(msg anim.StepMsg) tea.Cmd } +// Expandable is an interface for items that can be expanded or collapsed. +type Expandable interface { + ToggleExpanded() +} + // MessageItem represents a [message.Message] item that can be displayed in the // UI and be part of a [list.List] identifiable by a unique ID. type MessageItem interface { diff --git a/internal/ui/model/chat.go b/internal/ui/model/chat.go index 685d541da9f7bf5240a6bc9302098a1ed79153bb..2844cb81619e99956ba5895686d82e65eef92ce7 100644 --- a/internal/ui/model/chat.go +++ b/internal/ui/model/chat.go @@ -250,6 +250,13 @@ func (m *Chat) GetMessageItem(id string) chat.MessageItem { return item } +// ToggleExpandedSelectedItem expands the selected message item if it is expandable. +func (m *Chat) ToggleExpandedSelectedItem() { + if expandable, ok := m.list.SelectedItem().(chat.Expandable); ok { + expandable.ToggleExpanded() + } +} + // HandleMouseDown handles mouse down events for the chat component. func (m *Chat) HandleMouseDown(x, y int) bool { if m.list.Len() == 0 { diff --git a/internal/ui/model/keys.go b/internal/ui/model/keys.go index d421c00ca032a97b424fafe6442a243fc98080b1..f2f3fc9106c92effe38b48dd6f664cb8617f9443 100644 --- a/internal/ui/model/keys.go +++ b/internal/ui/model/keys.go @@ -37,6 +37,7 @@ type KeyMap struct { End key.Binding Copy key.Binding ClearHighlight key.Binding + Expand key.Binding } Initialize struct { @@ -205,7 +206,10 @@ func DefaultKeyMap() KeyMap { key.WithKeys("esc", "alt+esc"), key.WithHelp("esc", "clear selection"), ) - + km.Chat.Expand = key.NewBinding( + key.WithKeys("space"), + key.WithHelp("space", "expand/collapse"), + ) km.Initialize.Yes = key.NewBinding( key.WithKeys("y", "Y"), key.WithHelp("y", "yes"), diff --git a/internal/ui/model/ui.go b/internal/ui/model/ui.go index 967452e3e81aa7c92c75b02c184dd6f53aaa164a..57a7113ae5b432436f23ec79e0d6d5cacdbb94f0 100644 --- a/internal/ui/model/ui.go +++ b/internal/ui/model/ui.go @@ -577,6 +577,8 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd { m.focus = uiFocusEditor cmds = append(cmds, m.textarea.Focus()) m.chat.Blur() + case key.Matches(msg, m.keyMap.Chat.Expand): + m.chat.ToggleExpandedSelectedItem() case key.Matches(msg, m.keyMap.Chat.Up): if cmd := m.chat.ScrollBy(-1); cmd != nil { cmds = append(cmds, cmd)