feat: handle binding for history scroll init on first interaction

tauraamui created

Change summary

internal/tui/components/chat/editor/editor.go  | 12 ++++++++----
internal/tui/components/chat/editor/history.go |  8 +++++++-
internal/tui/components/chat/editor/keys.go    |  5 +++++
internal/tui/page/chat/chat.go                 |  6 ++++++
4 files changed, 26 insertions(+), 5 deletions(-)

Detailed changes

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

@@ -188,6 +188,9 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 	var cmds []tea.Cmd
 	switch msg := msg.(type) {
 	case LoadHistoryMsg:
+		if m.inHistoryMode() {
+			return m, nil
+		}
 		msgs, err := m.getUserMessagesAsText()
 		if err != nil {
 			// TODO(tauraamui): handle error for loading history better in the UI later
@@ -198,6 +201,7 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 	case CloseHistoryMsg:
 		m.history = nil
 		m.textarea.SetValue("closed history") // for easier temporary visual debugging
+		return m, nil
 	case tea.WindowSizeMsg:
 		return m, m.repositionCompletions
 	case filepicker.FilePickedMsg:
@@ -312,7 +316,7 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 			return m, nil
 		}
 		if key.Matches(msg, DeleteKeyMaps.Escape) && m.inHistoryMode() {
-			return m, util.CmdHandler(CloseHistoryMsg{})
+			cmds = append(cmds, util.CmdHandler(CloseHistoryMsg{}))
 		}
 		rune := msg.Code
 		if m.deleteMode && unicode.IsDigit(rune) {
@@ -333,7 +337,7 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 			}
 			return m, m.openEditor(m.textarea.Value())
 		}
-		if key.Matches(msg, DeleteKeyMaps.Escape) {
+		if key.Matches(msg, DeleteKeyMaps.Escape) && m.deleteMode {
 			m.deleteMode = false
 			return m, nil
 		}
@@ -354,9 +358,9 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 		}
 		// history
 		if m.textarea.Focused() && key.Matches(msg, m.keyMap.Previous) || key.Matches(msg, m.keyMap.Next) {
-			// m.textarea.SetValue(m.stepOverHistory(m.getUserMessagesAsText, m.getDirectionFromKey(msg)))
-			if m.history == nil {
+			if !m.inHistoryMode() {
 				cmds = append(cmds, util.CmdHandler(LoadHistoryMsg{}))
+				break
 			}
 		}
 	}

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

@@ -7,8 +7,14 @@ type historyState struct {
 }
 
 type History interface {
+	ScrollUp()
+	ScrollDown()
 }
 
 func InitialiseHistory(messages []string) History {
-	return historyState{}
+	return &historyState{}
 }
+
+func (h *historyState) ScrollUp() {}
+
+func (h *historyState) ScrollDown() {}

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

@@ -11,6 +11,7 @@ type EditorKeyMap struct {
 	Newline     key.Binding
 	Next        key.Binding
 	Previous    key.Binding
+	Escape      key.Binding
 }
 
 func DefaultEditorKeyMap() EditorKeyMap {
@@ -42,6 +43,10 @@ func DefaultEditorKeyMap() EditorKeyMap {
 			key.WithKeys("shift+up"),
 			key.WithHelp("shift+↑", "up"),
 		),
+		Escape: key.NewBinding(
+			key.WithKeys("esc", "alt+esc"),
+			key.WithHelp("esc", "cancel history mode"),
+		),
 	}
 }
 

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

@@ -365,6 +365,12 @@ func (p *chatPage) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 			p.editor = u.(editor.Editor)
 			cmds = append(cmds, cmd)
 		}
+	case editor.CloseHistoryMsg:
+		if p.focusedPane == PanelTypeEditor {
+			u, cmd := p.editor.Update(msg)
+			p.editor = u.(editor.Editor)
+			cmds = append(cmds, cmd)
+		}
 	case tea.KeyPressMsg:
 		switch {
 		case key.Matches(msg, p.keyMap.NewSession):