mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-24 10:13:41 -05:00
Don't scroll a view up to fill blank space while its content is loading
The layout scrolls a view up if its origin is past the bottom of its content, to avoid showing blank space (e.g. after a resize). But it measures content height by the lines loaded so far, and command/pty tasks load asynchronously. So when a view is re-rendered while scrolled down, the layout would yank it to the top because only a fraction of the content has been read yet, then leave it there once loading finished. Track whether a command task is actively reading (set synchronously when the task is created, so a layout pass in between sees it; cleared at EOF, but not when stopped, since that means a newer task is taking over) and skip the scroll-up clamp for such views. onEndOfInput already re-clamps once loading completes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
85cff19a2a
commit
fbadbbf99a
@@ -78,6 +78,11 @@ type ViewBufferManager struct {
|
||||
taskKey string
|
||||
onNewKey func()
|
||||
|
||||
// Whether a command task is currently reading content into the view. While
|
||||
// this is true the content is still growing, so callers (e.g. the layout)
|
||||
// must not clamp the view's scroll position to the amount loaded so far.
|
||||
loading atomic.Bool
|
||||
|
||||
// beforeStart is the function that is called before starting a new task
|
||||
beforeStart func()
|
||||
refreshView func()
|
||||
@@ -162,6 +167,21 @@ func (self *ViewBufferManager) ReadLines(totalLines int) {
|
||||
}
|
||||
}
|
||||
|
||||
// IsLoading reports whether a command task is currently reading content into the
|
||||
// view, meaning the content is still growing.
|
||||
func (self *ViewBufferManager) IsLoading() bool {
|
||||
return self.loading.Load()
|
||||
}
|
||||
|
||||
// StartLoading marks the view as loading content. It must be called
|
||||
// synchronously when a command/pty task is started, before the task's goroutine
|
||||
// runs, so that a layout pass happening in between doesn't clamp the scroll
|
||||
// position to the not-yet-loaded content. It is cleared when the task reaches
|
||||
// the end of its input.
|
||||
func (self *ViewBufferManager) StartLoading() {
|
||||
self.loading.Store(true)
|
||||
}
|
||||
|
||||
func (self *ViewBufferManager) ReadToEnd(then func()) {
|
||||
if ch := self.readLines.Load(); ch != nil {
|
||||
readLines := *ch
|
||||
@@ -379,6 +399,11 @@ func (self *ViewBufferManager) NewCmdTask(start func() (Cmd, io.Reader), prefix
|
||||
// whether to scroll) and sets the origin, both of which
|
||||
// are UI-thread-only, so run it there.
|
||||
_ = self.onUIThread(self.onEndOfInput)
|
||||
// The content is fully loaded now, so it's safe again for the
|
||||
// layout to clamp the scroll position to it. We deliberately
|
||||
// don't clear this when stopped (rather than EOF'd), because that
|
||||
// means a newer task is taking over and is still loading.
|
||||
self.loading.Store(false)
|
||||
callThen()
|
||||
// Any read requests that were queued while we were reading are
|
||||
// now trivially satisfied, since we've read everything. Fire
|
||||
|
||||
Reference in New Issue
Block a user