tui: add a "scroll bar" and error view
This commit is contained in:
parent
8697284064
commit
3892e68251
@ -29,6 +29,9 @@ const (
|
||||
)
|
||||
|
||||
type model struct {
|
||||
width int
|
||||
height int
|
||||
|
||||
ctx *lmcli.Context
|
||||
convShortname string
|
||||
|
||||
@ -135,9 +138,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
}
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
m.height = msg.Height
|
||||
m.content.Width = msg.Width
|
||||
m.content.Height = msg.Height - m.input.Height() - lipgloss.Height(m.footerView()) - lipgloss.Height(m.headerView())
|
||||
m.input.SetWidth(msg.Width - 1)
|
||||
m.content.Height = msg.Height - m.getFixedComponentHeight()
|
||||
m.input.SetWidth(msg.Width-1)
|
||||
m.updateContent()
|
||||
case msgConversationLoaded:
|
||||
m.conversation = (*models.Conversation)(msg)
|
||||
@ -202,6 +207,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
cmds = append(cmds, wrapError(err))
|
||||
}
|
||||
}
|
||||
case msgError:
|
||||
m.err = error(msg)
|
||||
}
|
||||
|
||||
if len(cmds) > 0 {
|
||||
@ -229,15 +236,45 @@ func (m model) View() string {
|
||||
// without this, the below view functions may do weird things
|
||||
return ""
|
||||
}
|
||||
|
||||
m.content.Height = m.height - m.getFixedComponentHeight()
|
||||
|
||||
sections := make([]string, 0, 6)
|
||||
error := m.errorView()
|
||||
scrollbar := m.scrollbarView()
|
||||
sections = append(sections, m.headerView())
|
||||
if scrollbar != "" {
|
||||
sections = append(sections, scrollbar)
|
||||
}
|
||||
sections = append(sections, m.contentView())
|
||||
if error != "" {
|
||||
sections = append(sections, error)
|
||||
}
|
||||
sections = append(sections, m.inputView())
|
||||
sections = append(sections, m.footerView())
|
||||
|
||||
return lipgloss.JoinVertical(
|
||||
lipgloss.Left,
|
||||
m.headerView(),
|
||||
m.contentView(),
|
||||
m.inputView(),
|
||||
m.footerView(),
|
||||
sections...,
|
||||
)
|
||||
}
|
||||
|
||||
func (m *model) getFixedComponentHeight() int {
|
||||
h := 0
|
||||
h += m.input.Height()
|
||||
h += lipgloss.Height(m.headerView())
|
||||
h += lipgloss.Height(m.footerView())
|
||||
scrollbar := m.scrollbarView()
|
||||
if scrollbar != "" {
|
||||
h += lipgloss.Height(scrollbar)
|
||||
}
|
||||
errorView := m.errorView()
|
||||
if errorView != "" {
|
||||
h += lipgloss.Height(errorView)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func (m *model) headerView() string {
|
||||
titleStyle := lipgloss.NewStyle().
|
||||
PaddingLeft(1).
|
||||
@ -258,6 +295,32 @@ func (m *model) contentView() string {
|
||||
return m.content.View()
|
||||
}
|
||||
|
||||
func (m *model) errorView() string {
|
||||
if m.err == nil {
|
||||
return ""
|
||||
}
|
||||
return lipgloss.NewStyle().
|
||||
Bold(true).
|
||||
Foreground(lipgloss.Color("1")).
|
||||
Width(m.content.Width).
|
||||
AlignHorizontal(lipgloss.Center).
|
||||
Render(fmt.Sprintf("%s", m.err))
|
||||
}
|
||||
|
||||
func (m *model) scrollbarView() string {
|
||||
if m.content.AtTop() {
|
||||
return ""
|
||||
}
|
||||
|
||||
count := int(m.content.ScrollPercent() * float64(m.content.Width-2))
|
||||
fill := strings.Repeat("-", count)
|
||||
return lipgloss.NewStyle().
|
||||
PaddingLeft(1).
|
||||
PaddingRight(1).
|
||||
Width(m.content.Width).
|
||||
Render(fill)
|
||||
}
|
||||
|
||||
func (m *model) inputView() string {
|
||||
return m.input.View()
|
||||
}
|
||||
@ -284,8 +347,8 @@ func (m *model) footerView() string {
|
||||
left := strings.Join(leftSegments, segmentSeparator)
|
||||
right := strings.Join(rightSegments, segmentSeparator)
|
||||
|
||||
totalWidth := lipgloss.Width(left + right)
|
||||
remaining := m.content.Width - totalWidth
|
||||
totalWidth := lipgloss.Width(left) + lipgloss.Width(right)
|
||||
remaining := m.width - totalWidth
|
||||
|
||||
var padding string
|
||||
if remaining > 0 {
|
||||
@ -295,7 +358,7 @@ func (m *model) footerView() string {
|
||||
footer := left + padding + right
|
||||
if remaining < 0 {
|
||||
ellipses := "... "
|
||||
footer = footer[:m.content.Width-len(ellipses)] + ellipses
|
||||
footer = footer[:m.width-len(ellipses)] + ellipses
|
||||
}
|
||||
return footerStyle.Render(footer)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user