diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go index ab9ef65e..bfbae393 100644 --- a/packages/tui/internal/components/chat/messages.go +++ b/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, diff --git a/packages/tui/internal/components/commands/commands.go b/packages/tui/internal/components/commands/commands.go index 68f6503e..dbd00149 100644 --- a/packages/tui/internal/components/commands/commands.go +++ b/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() diff --git a/packages/tui/internal/components/dialog/help.go b/packages/tui/internal/components/dialog/help.go index 78cbd704..4107384f 100644 --- a/packages/tui/internal/components/dialog/help.go +++ b/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()) diff --git a/packages/tui/internal/layout/flex.go b/packages/tui/internal/layout/flex.go index f164a03d..c7d9ee1b 100644 --- a/packages/tui/internal/layout/flex.go +++ b/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 diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go index 67538e80..4fb3e90d 100644 --- a/packages/tui/internal/tui/tui.go +++ b/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) {