adamdottv пре 8 месеци
родитељ
комит
ac777b77cf

+ 1 - 1
packages/tui/internal/components/dialog/help.go

@@ -83,6 +83,6 @@ type HelpDialog interface {
 func NewHelpDialog(commands []commands.Command) HelpDialog {
 	return &helpDialog{
 		commands: commands,
-		modal:    modal.New(),
+		modal:    modal.New(modal.WithTitle("Help")),
 	}
 }

+ 6 - 17
packages/tui/internal/components/dialog/models.go

@@ -180,6 +180,7 @@ func (m *modelDialog) switchProvider(offset int) {
 
 	m.hScrollOffset = newOffset
 	m.provider = m.availableProviders[m.hScrollOffset]
+	m.modal.SetTitle(fmt.Sprintf("Select %s Model", m.provider.Name))
 	m.setupModelsForProvider(m.provider.Id)
 }
 
@@ -189,14 +190,6 @@ func (m *modelDialog) View() string {
 		Background(t.BackgroundElement()).
 		Foreground(t.Text())
 
-	// Capitalize first letter of provider name
-	title := baseStyle.
-		Foreground(t.Primary()).
-		Bold(true).
-		Width(maxDialogWidth).
-		Padding(0, 0, 1).
-		Render(fmt.Sprintf("Select %s Model", m.provider.Name))
-
 	// Render visible models
 	endIdx := min(m.scrollOffset+numVisibleModels, len(m.provider.Models))
 	modelItems := make([]string, 0, endIdx-m.scrollOffset)
@@ -217,8 +210,9 @@ func (m *modelDialog) View() string {
 
 	content := lipgloss.JoinVertical(
 		lipgloss.Left,
-		title,
-		baseStyle.Width(maxDialogWidth).Render(lipgloss.JoinVertical(lipgloss.Left, modelItems...)),
+		baseStyle.
+			Width(maxDialogWidth).
+			Render(lipgloss.JoinVertical(lipgloss.Left, modelItems...)),
 		scrollIndicator,
 	)
 
@@ -238,12 +232,7 @@ func (m *modelDialog) getScrollIndicators(maxWidth int) string {
 	}
 
 	if m.hScrollPossible {
-		if m.hScrollOffset > 0 {
-			indicator = "← " + indicator
-		}
-		if m.hScrollOffset < len(m.availableProviders)-1 {
-			indicator += "→"
-		}
+		indicator = "← " + indicator + "→"
 	}
 
 	if indicator == "" {
@@ -313,6 +302,6 @@ func NewModelDialog(app *app.App) ModelDialog {
 		hScrollOffset:      0,
 		hScrollPossible:    len(availableProviders) > 1,
 		provider:           availableProviders[0],
-		modal:              modal.New(),
+		modal:              modal.New(modal.WithTitle(fmt.Sprintf("Select %s Model", availableProviders[0].Name))),
 	}
 }

+ 10 - 10
packages/tui/internal/components/dialog/session.go

@@ -19,14 +19,12 @@ type SessionDialog interface {
 	layout.Modal
 }
 
-type sessionItem struct {
-	session client.SessionInfo
-}
+type sessionItem client.SessionInfo
 
 func (s sessionItem) Render(selected bool, width int) string {
 	t := theme.CurrentTheme()
 	baseStyle := styles.BaseStyle().
-		Width(width - 2).
+		Width(width - 4).
 		Background(t.BackgroundElement())
 
 	if selected {
@@ -39,7 +37,7 @@ func (s sessionItem) Render(selected bool, width int) string {
 			Foreground(t.Text())
 	}
 
-	return baseStyle.Padding(0, 1).Render(s.session.Title)
+	return baseStyle.Padding(0, 1).Render(s.Title)
 }
 
 type sessionDialog struct {
@@ -60,15 +58,14 @@ func (s *sessionDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		s.width = msg.Width
 		s.height = msg.Height
 		s.list.SetMaxWidth(layout.Current.Container.Width - 12)
-	case tea.KeyMsg:
+	case tea.KeyPressMsg:
 		switch msg.String() {
 		case "enter":
 			if item, idx := s.list.GetSelectedItem(); idx >= 0 {
-				selectedSession := item.session
-				s.selectedSessionID = selectedSession.Id
+				s.selectedSessionID = item.Id
 				return s, tea.Sequence(
 					util.CmdHandler(modal.CloseModalMsg{}),
-					util.CmdHandler(app.SessionSelectedMsg(&selectedSession)),
+					util.CmdHandler(app.SessionSelectedMsg(&item)),
 				)
 			}
 		}
@@ -94,7 +91,10 @@ func NewSessionDialog(app *app.App) SessionDialog {
 
 	var sessionItems []sessionItem
 	for _, sess := range sessions {
-		sessionItems = append(sessionItems, sessionItem{session: sess})
+		if sess.ParentID != nil {
+			continue
+		}
+		sessionItems = append(sessionItems, sessionItem(sess))
 	}
 
 	list := list.NewListComponent(

+ 3 - 2
packages/tui/internal/components/list/list.go

@@ -1,9 +1,10 @@
 package list
 
 import (
+	"strings"
+
 	"github.com/charmbracelet/bubbles/v2/key"
 	tea "github.com/charmbracelet/bubbletea/v2"
-	"github.com/charmbracelet/lipgloss/v2"
 )
 
 type ListItem interface {
@@ -148,7 +149,7 @@ func (c *listComponent[T]) View() string {
 		listItems = append(listItems, title)
 	}
 
-	return lipgloss.JoinVertical(lipgloss.Left, listItems...)
+	return strings.Join(listItems, "\n")
 }
 
 func NewListComponent[T ListItem](items []T, maxVisibleItems int, fallbackMsg string, useAlphaNumericKeys bool) List[T] {

+ 19 - 7
packages/tui/internal/components/modal/modal.go

@@ -1,6 +1,8 @@
 package modal
 
 import (
+	"strings"
+
 	"github.com/charmbracelet/lipgloss/v2"
 	"github.com/sst/opencode/internal/layout"
 	"github.com/sst/opencode/internal/styles"
@@ -66,6 +68,10 @@ func New(opts ...ModalOption) *Modal {
 	return m
 }
 
+func (m *Modal) SetTitle(title string) {
+	m.title = title
+}
+
 // Render renders the modal centered on the screen
 func (m *Modal) Render(contentView string, background string) string {
 	t := theme.CurrentTheme()
@@ -95,15 +101,21 @@ func (m *Modal) Render(contentView string, background string) string {
 		titleStyle := baseStyle.
 			Foreground(t.Primary()).
 			Bold(true).
-			Width(innerWidth).
 			Padding(0, 1)
 
-		titleView := titleStyle.Render(m.title)
-		finalContent = lipgloss.JoinVertical(
-			lipgloss.Left,
-			titleView,
-			contentView,
-		)
+		// titleView := titleStyle.Render(m.title)
+		escStyle := baseStyle.Foreground(t.TextMuted()).Bold(false)
+		escText := escStyle.Render("esc")
+
+		// Calculate position for esc text
+		titleWidth := lipgloss.Width(m.title)
+		escWidth := lipgloss.Width(escText)
+		spacesNeeded := max(0, innerWidth-titleWidth-escWidth-3)
+		spacer := strings.Repeat(" ", spacesNeeded)
+		titleLine := m.title + spacer + escText
+		titleLine = titleStyle.Render(titleLine)
+
+		finalContent = strings.Join([]string{titleLine, contentView}, "\n") + "\n"
 	} else {
 		finalContent = contentView
 	}

+ 5 - 1
packages/tui/internal/tui/tui.go

@@ -204,8 +204,12 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		}
 		a.layout.SetSize(a.width, a.height)
 	case app.SessionSelectedMsg:
+		var err error
 		a.app.Session = msg
-		a.app.Messages, _ = a.app.ListMessages(context.Background(), msg.Id)
+		a.app.Messages, err = a.app.ListMessages(context.Background(), msg.Id)
+		if err != nil {
+			slog.Error("Failed to list messages", "error", err)
+		}
 	case app.ModelSelectedMsg:
 		a.app.Provider = &msg.Provider
 		a.app.Model = &msg.Model