adamdottv 7 месяцев назад
Родитель
Сommit
5a107b275c

+ 3 - 85
packages/tui/internal/components/chat/messages.go

@@ -10,7 +10,6 @@ import (
 	"github.com/charmbracelet/lipgloss/v2"
 	"github.com/sst/opencode-sdk-go"
 	"github.com/sst/opencode/internal/app"
-	"github.com/sst/opencode/internal/components/commands"
 	"github.com/sst/opencode/internal/components/dialog"
 	"github.com/sst/opencode/internal/layout"
 	"github.com/sst/opencode/internal/styles"
@@ -39,7 +38,6 @@ type messagesComponent struct {
 	viewport        viewport.Model
 	spinner         spinner.Model
 	attachments     viewport.Model
-	commands        commands.CommandsComponent
 	cache           *MessageCache
 	rendering       bool
 	showToolDetails bool
@@ -49,7 +47,7 @@ type renderFinishedMsg struct{}
 type ToggleToolDetailsMsg struct{}
 
 func (m *messagesComponent) Init() tea.Cmd {
-	return tea.Batch(m.viewport.Init(), m.spinner.Tick, m.commands.Init())
+	return tea.Batch(m.viewport.Init(), m.spinner.Tick)
 }
 
 func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
@@ -100,10 +98,6 @@ func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	m.spinner = spinner
 	cmds = append(cmds, cmd)
 
-	updated, cmd := m.commands.Update(msg)
-	m.commands = updated.(commands.CommandsComponent)
-	cmds = append(cmds, cmd)
-
 	return m, tea.Batch(cmds...)
 }
 
@@ -271,8 +265,8 @@ func (m *messagesComponent) renderView() {
 		))
 	}
 
-	m.viewport.SetHeight(m.height - lipgloss.Height(m.header()))
-	m.viewport.SetContent("\n" + strings.Join(centered, "\n") + "\n")
+	m.viewport.SetHeight(m.height - lipgloss.Height(m.header()) + 1)
+	m.viewport.SetContent("\n" + strings.Join(centered, "\n"))
 }
 
 func (m *messagesComponent) header() string {
@@ -309,9 +303,6 @@ func (m *messagesComponent) header() string {
 }
 
 func (m *messagesComponent) View() string {
-	if len(m.app.Messages) == 0 {
-		return m.home()
-	}
 	t := theme.CurrentTheme()
 	if m.rendering {
 		return lipgloss.Place(
@@ -334,70 +325,6 @@ func (m *messagesComponent) View() string {
 		Render(header + "\n" + m.viewport.View())
 }
 
-func (m *messagesComponent) home() string {
-	t := theme.CurrentTheme()
-	baseStyle := styles.NewStyle().Background(t.Background())
-	base := baseStyle.Render
-	muted := styles.NewStyle().Foreground(t.TextMuted()).Background(t.Background()).Render
-
-	open := `
-█▀▀█ █▀▀█ █▀▀ █▀▀▄ 
-█░░█ █░░█ █▀▀ █░░█ 
-▀▀▀▀ █▀▀▀ ▀▀▀ ▀  ▀ `
-	code := `
-█▀▀ █▀▀█ █▀▀▄ █▀▀
-█░░ █░░█ █░░█ █▀▀
-▀▀▀ ▀▀▀▀ ▀▀▀  ▀▀▀`
-
-	logo := lipgloss.JoinHorizontal(
-		lipgloss.Top,
-		muted(open),
-		base(code),
-	)
-	// cwd := app.Info.Path.Cwd
-	// config := app.Info.Path.Config
-
-	versionStyle := styles.NewStyle().
-		Foreground(t.TextMuted()).
-		Background(t.Background()).
-		Width(lipgloss.Width(logo)).
-		Align(lipgloss.Right)
-	version := versionStyle.Render(m.app.Version)
-
-	logoAndVersion := strings.Join([]string{logo, version}, "\n")
-	logoAndVersion = lipgloss.PlaceHorizontal(
-		m.width,
-		lipgloss.Center,
-		logoAndVersion,
-		styles.WhitespaceStyle(t.Background()),
-	)
-	m.commands.SetBackgroundColor(t.Background())
-	commands := lipgloss.PlaceHorizontal(
-		m.width,
-		lipgloss.Center,
-		m.commands.View(),
-		styles.WhitespaceStyle(t.Background()),
-	)
-
-	lines := []string{}
-	lines = append(lines, logoAndVersion)
-	lines = append(lines, "")
-	lines = append(lines, "")
-	// lines = append(lines, base("cwd ")+muted(cwd))
-	// lines = append(lines, base("config ")+muted(config))
-	// lines = append(lines, "")
-	lines = append(lines, commands)
-
-	return lipgloss.Place(
-		m.width,
-		m.height,
-		lipgloss.Center,
-		lipgloss.Center,
-		baseStyle.Render(strings.Join(lines, "\n")),
-		styles.WhitespaceStyle(t.Background()),
-	)
-}
-
 func (m *messagesComponent) SetSize(width, height int) tea.Cmd {
 	if m.width == width && m.height == height {
 		return nil
@@ -412,7 +339,6 @@ func (m *messagesComponent) SetSize(width, height int) tea.Cmd {
 	m.viewport.SetHeight(height - lipgloss.Height(m.header()))
 	m.attachments.SetWidth(width + 40)
 	m.attachments.SetHeight(3)
-	m.commands.SetSize(width, height)
 	m.renderView()
 	return nil
 }
@@ -476,19 +402,11 @@ func NewMessagesComponent(app *app.App) MessagesComponent {
 	attachments := viewport.New()
 	vp.KeyMap = viewport.KeyMap{}
 
-	t := theme.CurrentTheme()
-	commandsView := commands.New(
-		app,
-		commands.WithBackground(t.Background()),
-		commands.WithLimit(6),
-	)
-
 	return &messagesComponent{
 		app:             app,
 		viewport:        vp,
 		spinner:         s,
 		attachments:     attachments,
-		commands:        commandsView,
 		showToolDetails: true,
 		cache:           NewMessageCache(),
 		tail:            true,

+ 0 - 14
packages/tui/internal/components/commands/commands.go

@@ -14,7 +14,6 @@ import (
 )
 
 type CommandsComponent interface {
-	tea.Model
 	tea.ViewModel
 	SetSize(width, height int) tea.Cmd
 	SetBackgroundColor(color compat.AdaptiveColor)
@@ -43,19 +42,6 @@ func (c *commandsComponent) SetBackgroundColor(color compat.AdaptiveColor) {
 	c.background = &color
 }
 
-func (c *commandsComponent) Init() tea.Cmd {
-	return nil
-}
-
-func (c *commandsComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
-	switch msg := msg.(type) {
-	case tea.WindowSizeMsg:
-		c.width = msg.Width
-		c.height = msg.Height
-	}
-	return c, nil
-}
-
 func (c *commandsComponent) View() string {
 	t := theme.CurrentTheme()
 

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

@@ -20,10 +20,7 @@ type helpDialog struct {
 }
 
 func (h *helpDialog) Init() tea.Cmd {
-	return tea.Batch(
-		h.commandsComponent.Init(),
-		h.viewport.Init(),
-	)
+	return h.viewport.Init()
 }
 
 func (h *helpDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
@@ -38,10 +35,6 @@ func (h *helpDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		h.commandsComponent.SetSize(msg.Width-4, msg.Height-6)
 	}
 
-	// Update commands component first to get the latest content
-	_, cmdCmd := h.commandsComponent.Update(msg)
-	cmds = append(cmds, cmdCmd)
-
 	// Update viewport content
 	h.viewport.SetContent(h.commandsComponent.View())
 

+ 2 - 8
packages/tui/internal/layout/flex.go

@@ -73,10 +73,7 @@ func Render(opts FlexOptions, items ...FlexItem) string {
 	}
 
 	// Calculate available space for grow items
-	availableSpace := mainAxisSize - totalFixedSize
-	if availableSpace < 0 {
-		availableSpace = 0
-	}
+	availableSpace := max(mainAxisSize-totalFixedSize, 0)
 
 	// Calculate size for each grow item
 	growItemSize := 0
@@ -164,10 +161,7 @@ func Render(opts FlexOptions, items ...FlexItem) string {
 	}
 
 	// Apply justification
-	remainingSpace := mainAxisSize - totalActualSize
-	if remainingSpace < 0 {
-		remainingSpace = 0
-	}
+	remainingSpace := max(mainAxisSize-totalActualSize, 0)
 
 	// Calculate spacing based on justification
 	var spaceBefore, spaceBetween, spaceAfter int

+ 86 - 23
packages/tui/internal/tui/tui.go

@@ -17,6 +17,7 @@ import (
 	"github.com/sst/opencode/internal/commands"
 	"github.com/sst/opencode/internal/completions"
 	"github.com/sst/opencode/internal/components/chat"
+	cmdcomp "github.com/sst/opencode/internal/components/commands"
 	"github.com/sst/opencode/internal/components/dialog"
 	"github.com/sst/opencode/internal/components/modal"
 	"github.com/sst/opencode/internal/components/status"
@@ -425,13 +426,13 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 }
 
 func (a appModel) View() string {
-	messagesView := a.messages.View()
 	editorView := a.editor.View()
-
-	editorHeight := lipgloss.Height(editorView)
-	if editorHeight < 5 {
-		editorHeight = 5
+	lines := a.editor.Lines()
+	messagesView := a.messages.View()
+	if a.app.Session.ID == "" {
+		messagesView = a.home()
 	}
+	editorHeight := max(lines, 5)
 
 	t := theme.CurrentTheme()
 	centeredEditorView := lipgloss.PlaceHorizontal(
@@ -445,7 +446,7 @@ func (a appModel) View() string {
 		layout.FlexOptions{
 			Direction: layout.Column,
 			Width:     a.width,
-			Height:    a.height - 1, // Leave room for status bar
+			Height:    a.height,
 		},
 		layout.FlexItem{
 			View: messagesView,
@@ -453,15 +454,18 @@ func (a appModel) View() string {
 		},
 		layout.FlexItem{
 			View:      centeredEditorView,
-			FixedSize: editorHeight,
+			FixedSize: 5,
 		},
+		// layout.FlexItem{
+		// 	View:      a.status.View(),
+		// 	FixedSize: 1,
+		// },
 	)
 
-	if a.editor.Lines() > 1 {
+	if lines > 1 {
 		editorWidth := min(a.width, 80)
 		editorX := (a.width - editorWidth) / 2
-		editorY := a.height - editorHeight - 1 // Position from bottom, accounting for status bar
-
+		editorY := a.height - editorHeight
 		mainLayout = layout.PlaceOverlay(
 			editorX,
 			editorY,
@@ -476,7 +480,7 @@ func (a appModel) View() string {
 		a.completions.SetWidth(editorWidth)
 		overlay := a.completions.View()
 		overlayHeight := lipgloss.Height(overlay)
-		editorY := a.height - editorHeight - 1
+		editorY := a.height - editorHeight + 1
 
 		mainLayout = layout.PlaceOverlay(
 			editorX,
@@ -486,23 +490,82 @@ func (a appModel) View() string {
 		)
 	}
 
-	components := []string{
-		mainLayout,
-		a.status.View(),
-	}
-	appView := strings.Join(components, "\n")
-
 	if a.modal != nil {
-		appView = a.modal.Render(appView)
+		mainLayout = a.modal.Render(mainLayout)
 	}
-
-	appView = a.toastManager.RenderOverlay(appView)
-
+	mainLayout = a.toastManager.RenderOverlay(mainLayout)
 	if theme.CurrentThemeUsesAnsiColors() {
-		appView = util.ConvertRGBToAnsi16Colors(appView)
+		mainLayout = util.ConvertRGBToAnsi16Colors(mainLayout)
 	}
+	return mainLayout + "\n" + a.status.View()
+}
 
-	return appView
+func (a appModel) home() string {
+	t := theme.CurrentTheme()
+	baseStyle := styles.NewStyle().Background(t.Background())
+	base := baseStyle.Render
+	muted := styles.NewStyle().Foreground(t.TextMuted()).Background(t.Background()).Render
+
+	open := `
+█▀▀█ █▀▀█ █▀▀ █▀▀▄ 
+█░░█ █░░█ █▀▀ █░░█ 
+▀▀▀▀ █▀▀▀ ▀▀▀ ▀  ▀ `
+	code := `
+█▀▀ █▀▀█ █▀▀▄ █▀▀
+█░░ █░░█ █░░█ █▀▀
+▀▀▀ ▀▀▀▀ ▀▀▀  ▀▀▀`
+
+	logo := lipgloss.JoinHorizontal(
+		lipgloss.Top,
+		muted(open),
+		base(code),
+	)
+	// cwd := app.Info.Path.Cwd
+	// config := app.Info.Path.Config
+
+	versionStyle := styles.NewStyle().
+		Foreground(t.TextMuted()).
+		Background(t.Background()).
+		Width(lipgloss.Width(logo)).
+		Align(lipgloss.Right)
+	version := versionStyle.Render(a.app.Version)
+
+	logoAndVersion := strings.Join([]string{logo, version}, "\n")
+	logoAndVersion = lipgloss.PlaceHorizontal(
+		a.width,
+		lipgloss.Center,
+		logoAndVersion,
+		styles.WhitespaceStyle(t.Background()),
+	)
+	commandsView := cmdcomp.New(
+		a.app,
+		cmdcomp.WithBackground(t.Background()),
+		cmdcomp.WithLimit(6),
+	)
+	cmds := lipgloss.PlaceHorizontal(
+		a.width,
+		lipgloss.Center,
+		commandsView.View(),
+		styles.WhitespaceStyle(t.Background()),
+	)
+
+	lines := []string{}
+	lines = append(lines, logoAndVersion)
+	lines = append(lines, "")
+	lines = append(lines, "")
+	// lines = append(lines, base("cwd ")+muted(cwd))
+	// lines = append(lines, base("config ")+muted(config))
+	// lines = append(lines, "")
+	lines = append(lines, cmds)
+
+	return lipgloss.Place(
+		a.width,
+		a.height-5,
+		lipgloss.Center,
+		lipgloss.Center,
+		baseStyle.Render(strings.Join(lines, "\n")),
+		styles.WhitespaceStyle(t.Background()),
+	)
 }
 
 func (a appModel) executeCommand(command commands.Command) (tea.Model, tea.Cmd) {