Merge remote-tracking branch 'origin/main' into onboarding

Kujtim Hoxha created

Change summary

internal/tui/components/chat/editor/editor.go |  9 ++++++++-
internal/tui/components/chat/editor/keys.go   | 16 ++++++++++++++++
internal/tui/page/chat/chat.go                |  4 ++++
internal/tui/tui.go                           |  9 ++++++++-
4 files changed, 36 insertions(+), 2 deletions(-)

Detailed changes

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

@@ -157,6 +157,9 @@ 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.KeyboardEnhancementsMsg:
+		m.keyMap.keyboard = msg
+		return m, nil
 	case filepicker.FilePickedMsg:
 		if len(m.attachments) >= maxAttachments {
 			return m, util.ReportError(fmt.Errorf("cannot add more than %d images", maxAttachments))
@@ -252,7 +255,11 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			m.deleteMode = false
 			return m, nil
 		}
-		// Hanlde Enter key
+		if key.Matches(msg, m.keyMap.Newline) {
+			m.textarea.InsertRune('\n')
+			return m, nil
+		}
+		// Handle Enter key
 		if m.textarea.Focused() && key.Matches(msg, m.keyMap.SendMessage) {
 			value := m.textarea.Value()
 			if len(value) > 0 && value[len(value)-1] == '\\' {

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

@@ -2,12 +2,16 @@ package editor
 
 import (
 	"github.com/charmbracelet/bubbles/v2/key"
+	tea "github.com/charmbracelet/bubbletea/v2"
 )
 
 type EditorKeyMap struct {
 	AddFile     key.Binding
 	SendMessage key.Binding
 	OpenEditor  key.Binding
+	Newline     key.Binding
+
+	keyboard tea.KeyboardEnhancementsMsg
 }
 
 func DefaultEditorKeyMap() EditorKeyMap {
@@ -24,15 +28,27 @@ func DefaultEditorKeyMap() EditorKeyMap {
 			key.WithKeys("ctrl+e"),
 			key.WithHelp("ctrl+e", "open editor"),
 		),
+		Newline: key.NewBinding(
+			key.WithKeys("shift+enter", "ctrl+j"),
+			// "ctrl+j" is a common keybinding for newline in many editors. If
+			// the terminal supports "shift+enter", we substitute the help text
+			// to reflect that.
+			key.WithHelp("ctrl+j", "newline"),
+		),
 	}
 }
 
 // KeyBindings implements layout.KeyMapProvider
 func (k EditorKeyMap) KeyBindings() []key.Binding {
+	newline := k.Newline
+	if k.keyboard.SupportsKeyDisambiguation() {
+		newline.SetHelp("shift+enter", newline.Help().Desc)
+	}
 	return []key.Binding{
 		k.AddFile,
 		k.SendMessage,
 		k.OpenEditor,
+		newline,
 	}
 }
 

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

@@ -152,6 +152,10 @@ func (p *chatPage) Init() tea.Cmd {
 func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	var cmds []tea.Cmd
 	switch msg := msg.(type) {
+	case tea.KeyboardEnhancementsMsg:
+		m, cmd := p.editor.Update(msg)
+		p.editor = m.(editor.Editor)
+		return p, cmd
 	case tea.WindowSizeMsg:
 		return p, p.SetSize(msg.Width, msg.Height)
 	case CancelTimerExpiredMsg:

internal/tui/tui.go 🔗

@@ -99,7 +99,14 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 
 	switch msg := msg.(type) {
 	case tea.KeyboardEnhancementsMsg:
-		return a, nil
+		for id, page := range a.pages {
+			m, pageCmd := page.Update(msg)
+			a.pages[id] = m.(util.Model)
+			if pageCmd != nil {
+				cmds = append(cmds, pageCmd)
+			}
+		}
+		return a, tea.Batch(cmds...)
 	case tea.WindowSizeMsg:
 		return a, a.handleWindowResize(msg.Width, msg.Height)