Private
Public Access
1
0

Clean up tui View handling

This commit is contained in:
2024-05-30 07:04:55 +00:00
parent c1792f27ff
commit ed784bb1cf
4 changed files with 78 additions and 57 deletions

View File

@@ -57,8 +57,7 @@ type (
type Model struct {
shared.State
width int
height int
shared.Sections
// app state
conversation *models.Conversation
@@ -72,10 +71,6 @@ type Model struct {
replyChunkChan chan string
persistence bool // whether we will save new messages in the conversation
tokenCount uint
startTime time.Time
elapsed time.Duration
// ui state
focus focusState
wrap bool // whether message content is wrapped to viewport width
@@ -84,6 +79,10 @@ type Model struct {
messageCache []string // cache of syntax highlighted and wrapped message content
messageOffsets []int
tokenCount uint
startTime time.Time
elapsed time.Duration
// ui elements
content viewport.Model
input textarea.Model
@@ -228,7 +227,7 @@ func (m Model) Init() tea.Cmd {
}
func (m *Model) HandleResize(width, height int) {
m.width, m.height = width, height
m.Width, m.Height = width, height
m.content.Width = width
m.input.SetWidth(width - m.input.FocusedStyle.Base.GetHorizontalFrameSize())
if len(m.messages) > 0 {
@@ -390,21 +389,21 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
}
// update views once window dimensions are known
if m.width > 0 {
m.State.Views.Header = m.headerView()
m.State.Views.Footer = m.footerView()
m.State.Views.Error = tuiutil.ErrorBanner(m.State.Err, m.width)
fixedHeight := tuiutil.Height(m.State.Views.Header) + tuiutil.Height(m.State.Views.Error) + tuiutil.Height(m.State.Views.Footer)
if m.Width > 0 {
m.Header = m.headerView()
m.Footer = m.footerView()
m.Error = tuiutil.ErrorBanner(m.Err, m.Width)
fixedHeight := tuiutil.Height(m.Header) + tuiutil.Height(m.Error) + tuiutil.Height(m.Footer)
// calculate clamped input height to accomodate input text
// minimum 4 lines, maximum half of content area
newHeight := max(4, min((m.height-fixedHeight-1)/2, m.input.LineCount()))
newHeight := max(4, min((m.Height-fixedHeight-1)/2, m.input.LineCount()))
m.input.SetHeight(newHeight)
m.State.Views.Input = m.input.View()
m.Input = m.input.View()
// remaining height towards content
m.content.Height = m.height - fixedHeight - tuiutil.Height(m.State.Views.Input)
m.State.Views.Content = m.content.View()
m.content.Height = m.Height - fixedHeight - tuiutil.Height(m.Input)
m.Content = m.content.View()
}
// this is a pretty nasty hack to ensure the input area viewport doesn't
@@ -630,6 +629,29 @@ func (m *Model) HandleInputKey(msg tea.KeyMsg) (bool, tea.Cmd) {
return false, nil
}
func (m Model) View() string {
if m.Width == 0 {
return ""
}
sections := make([]string, 0, 6)
if m.Header != "" {
sections = append(sections, m.Header)
}
sections = append(sections, m.Content)
if m.Error != "" {
sections = append(sections, m.Error)
}
sections = append(sections, m.Input)
if m.Footer != "" {
sections = append(sections, m.Footer)
}
return lipgloss.JoinVertical(lipgloss.Left, sections...)
}
func (m *Model) renderMessageHeading(i int, message *models.Message) string {
icon := ""
friendly := message.Role.FriendlyRole()
@@ -828,9 +850,9 @@ func (m *Model) headerView() string {
} else {
title = "Untitled"
}
title = tuiutil.TruncateToCellWidth(title, m.width-styles.Header.GetHorizontalPadding(), "...")
title = tuiutil.TruncateToCellWidth(title, m.Width-styles.Header.GetHorizontalPadding(), "...")
header := titleStyle.Render(title)
return styles.Header.Width(m.width).Render(header)
return styles.Header.Width(m.Width).Render(header)
}
func (m *Model) footerView() string {
@@ -868,7 +890,7 @@ func (m *Model) footerView() string {
right := strings.Join(rightSegments, segmentSeparator)
totalWidth := lipgloss.Width(left) + lipgloss.Width(right)
remaining := m.width - totalWidth
remaining := m.Width - totalWidth
var padding string
if remaining > 0 {
@@ -877,9 +899,9 @@ func (m *Model) footerView() string {
footer := left + padding + right
if remaining < 0 {
footer = tuiutil.TruncateToCellWidth(footer, m.width, "...")
footer = tuiutil.TruncateToCellWidth(footer, m.Width, "...")
}
return footerStyle.Width(m.width).Render(footer)
return footerStyle.Width(m.Width).Render(footer)
}
func (m *Model) setMessage(i int, msg models.Message) {