Skip to content

Commit

Permalink
Fix bug where performance rendering could render one line too many
Browse files Browse the repository at this point in the history
  • Loading branch information
meowgorithm committed Sep 17, 2021
1 parent 8c03905 commit 0ac5ecd
Showing 1 changed file with 20 additions and 16 deletions.
36 changes: 20 additions & 16 deletions viewport/viewport.go
Expand Up @@ -21,7 +21,7 @@ type Model struct {
YOffset int

// YPosition is the position of the viewport in relation to the terminal
// window. It's used in high performance rendering.
// window. It's used in high performance rendering only.
YPosition int

// HighPerformanceRendering bypasses the normal Bubble Tea renderer to
Expand Down Expand Up @@ -69,15 +69,16 @@ func (m Model) ScrollPercent() float64 {
// SetContent set the pager's text content. For high performance rendering the
// Sync command should also be called.
func (m *Model) SetContent(s string) {
s = strings.Replace(s, "\r\n", "\n", -1) // normalize line endings
s = strings.ReplaceAll(s, "\r\n", "\n") // normalize line endings
m.lines = strings.Split(s, "\n")

if m.YOffset > len(m.lines)-1 {
m.GotoBottom()
}
}

// Return the lines that should currently be visible in the viewport.
// visibleLines returns the lines that should currently be visible in the
// viewport.
func (m Model) visibleLines() (lines []string) {
if len(m.lines) > 0 {
top := max(0, m.YOffset)
Expand All @@ -87,6 +88,16 @@ func (m Model) visibleLines() (lines []string) {
return lines
}

// scrollArea returns the scrollable boundaries for high performance rendering.
func (m Model) scrollArea() (top, bottom int) {
top = max(0, m.YPosition)
bottom = max(top, top+m.Height)
if top > 0 && bottom > top {
bottom--
}
return top, bottom
}

// SetYOffset sets the Y offset.
func (m *Model) SetYOffset(n int) {
m.YOffset = clamp(n, 0, len(m.lines)-m.Height)
Expand Down Expand Up @@ -186,17 +197,8 @@ func Sync(m Model) tea.Cmd {
if len(m.lines) == 0 {
return nil
}

// TODO: we should probably use m.visibleLines() rather than these two
// expressions.
top := max(m.YOffset, 0)
bottom := clamp(m.YOffset+m.Height, 0, len(m.lines)-1)

return tea.SyncScrollArea(
m.lines[top:bottom],
m.YPosition,
m.YPosition+m.Height,
)
top, bottom := m.scrollArea()
return tea.SyncScrollArea(m.visibleLines(), top, bottom)
}

// ViewDown is a high performance command that moves the viewport up by a given
Expand All @@ -210,7 +212,8 @@ func ViewDown(m Model, lines []string) tea.Cmd {
if len(lines) == 0 {
return nil
}
return tea.ScrollDown(lines, m.YPosition, m.YPosition+m.Height)
top, bottom := m.scrollArea()
return tea.ScrollDown(lines, top, bottom)
}

// ViewUp is a high performance command the moves the viewport down by a given
Expand All @@ -220,7 +223,8 @@ func ViewUp(m Model, lines []string) tea.Cmd {
if len(lines) == 0 {
return nil
}
return tea.ScrollUp(lines, m.YPosition, m.YPosition+m.Height)
top, bottom := m.scrollArea()
return tea.ScrollUp(lines, top, bottom)
}

// UPDATE
Expand Down

0 comments on commit 0ac5ecd

Please sign in to comment.