tui: dynamic input textarea height and styling updates
Maintain a height of 4 up to half of the main content area Add rounded border
This commit is contained in:
parent
5af857edae
commit
0b991800d6
@ -126,9 +126,7 @@ var (
|
|||||||
PaddingLeft(1).
|
PaddingLeft(1).
|
||||||
PaddingRight(1).
|
PaddingRight(1).
|
||||||
Background(lipgloss.Color("0"))
|
Background(lipgloss.Color("0"))
|
||||||
footerStyle = lipgloss.NewStyle().
|
footerStyle = lipgloss.NewStyle()
|
||||||
BorderTop(true).
|
|
||||||
BorderStyle(lipgloss.NormalBorder())
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m model) Init() tea.Cmd {
|
func (m model) Init() tea.Cmd {
|
||||||
@ -206,7 +204,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.width = msg.Width
|
m.width = msg.Width
|
||||||
m.height = msg.Height
|
m.height = msg.Height
|
||||||
m.content.Width = msg.Width
|
m.content.Width = msg.Width
|
||||||
m.input.SetWidth(msg.Width)
|
m.input.SetWidth(msg.Width-m.input.FocusedStyle.Base.GetHorizontalBorderSize())
|
||||||
m.rebuildMessageCache()
|
m.rebuildMessageCache()
|
||||||
m.updateContent()
|
m.updateContent()
|
||||||
case msgConversationLoaded:
|
case msgConversationLoaded:
|
||||||
@ -295,6 +293,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
cmds = append(cmds, cmd)
|
cmds = append(cmds, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
prevInputLineCnt := m.input.LineCount()
|
||||||
inputCaptured := false
|
inputCaptured := false
|
||||||
m.input, cmd = m.input.Update(msg)
|
m.input, cmd = m.input.Update(msg)
|
||||||
if cmd != nil {
|
if cmd != nil {
|
||||||
@ -313,12 +313,42 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.cache.header = m.headerView()
|
m.cache.header = m.headerView()
|
||||||
m.cache.footer = m.footerView()
|
m.cache.footer = m.footerView()
|
||||||
m.cache.error = m.errorView()
|
m.cache.error = m.errorView()
|
||||||
|
|
||||||
|
fixedHeight := height(m.cache.header) + height(m.cache.error) + height(m.cache.footer)
|
||||||
|
|
||||||
|
// calculate clamped input height to accomodate input text
|
||||||
|
newHeight := max(4, min((m.height-fixedHeight-1)/2, m.input.LineCount()))
|
||||||
|
m.input.SetHeight(newHeight)
|
||||||
m.cache.input = m.inputView()
|
m.cache.input = m.inputView()
|
||||||
fixedHeight := height(m.cache.header) + height(m.cache.error) + height(m.cache.input) + height(m.cache.footer)
|
|
||||||
m.content.Height = m.height - fixedHeight
|
m.content.Height = m.height - height(m.cache.input) - fixedHeight
|
||||||
m.cache.content = m.contentView()
|
m.cache.content = m.contentView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is a pretty nasty hack to ensure the input area viewport doesn't
|
||||||
|
// scroll below its content, which can happen when the input viewport
|
||||||
|
// height has grown, or previously entered lines have been deleted
|
||||||
|
if prevInputLineCnt != m.input.LineCount() {
|
||||||
|
// dist is the distance we'd need to scroll up from the current cursor
|
||||||
|
// position to position the last input line at the bottom of the
|
||||||
|
// viewport. if negative, we're already scrolled above the bottom
|
||||||
|
dist := m.input.Line() - (m.input.LineCount() - m.input.Height())
|
||||||
|
if dist > 0 {
|
||||||
|
for i := 0; i < dist; i++ {
|
||||||
|
// move cursor up until content reaches the bottom of the viewport
|
||||||
|
m.input.CursorUp()
|
||||||
|
}
|
||||||
|
m.input, cmd = m.input.Update(nil)
|
||||||
|
cmds = append(cmds, cmd)
|
||||||
|
for i := 0; i < dist; i++ {
|
||||||
|
// move cursor back down to its previous position
|
||||||
|
m.input.CursorDown()
|
||||||
|
}
|
||||||
|
m.input, cmd = m.input.Update(nil)
|
||||||
|
cmds = append(cmds, cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return m, tea.Batch(cmds...)
|
return m, tea.Batch(cmds...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,16 +498,13 @@ func initialModel(ctx *lmcli.Context, convShortname string) model {
|
|||||||
m.input.Placeholder = "Enter a message"
|
m.input.Placeholder = "Enter a message"
|
||||||
|
|
||||||
m.input.ShowLineNumbers = false
|
m.input.ShowLineNumbers = false
|
||||||
m.input.SetHeight(4)
|
|
||||||
m.input.Focus()
|
m.input.Focus()
|
||||||
m.input.FocusedStyle.CursorLine = lipgloss.NewStyle()
|
m.input.FocusedStyle.CursorLine = lipgloss.NewStyle()
|
||||||
m.input.FocusedStyle.Base = lipgloss.NewStyle().
|
m.input.FocusedStyle.Base = lipgloss.NewStyle().
|
||||||
BorderTop(true).
|
Border(lipgloss.RoundedBorder(), true, true, true, false)
|
||||||
BorderStyle(lipgloss.NormalBorder())
|
|
||||||
m.input.BlurredStyle.Base = lipgloss.NewStyle().
|
m.input.BlurredStyle.Base = lipgloss.NewStyle().
|
||||||
Faint(true).
|
Faint(true).
|
||||||
BorderTop(true).
|
Border(lipgloss.RoundedBorder(), true, true, true, false)
|
||||||
BorderStyle(lipgloss.NormalBorder())
|
|
||||||
|
|
||||||
m.spinner = spinner.New(spinner.WithSpinner(
|
m.spinner = spinner.New(spinner.WithSpinner(
|
||||||
spinner.Spinner{
|
spinner.Spinner{
|
||||||
|
Loading…
Reference in New Issue
Block a user