summaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorStefan Haller <stefan@haller-berlin.de>2024-06-22 18:00:31 +0200
committerStefan Haller <stefan@haller-berlin.de>2024-06-23 13:10:48 +0200
commita67eda39a56440f54be7fbb43974fa7a966bce53 (patch)
treeb1b7d0c488a7502fd4874a5a3dd9de92c6a26a4b /pkg
parent8e1464f720d839b6e2c493b8fead0e4d39bbaaa7 (diff)
Rerender fewer views when their width changes
In d5b4f7bb3e and 58a83b0862 we introduced a combined mechanism for rerendering views when either their width changes (needed for the branches view which truncates long branch names), or the screen mode (needed for those views that display more information in half or full screen mode, e.g. the commits view). This was a bad idea, because it unnecessarily rerenders too many views when just their width changes, which causes a noticable lag. This is a problem, for example, when selecting a file in the files panel that has only unstaged changes, and then going to one that has both staged and unstaged changes; this splits the main view, causing the side panels to become a bit narrower, and rerendering all those views took almost 500ms on my machine. Another similar example is entering or leaving staging mode. Fix this by being more specific about which views need rerendering under what conditions; this improves the time it takes to rerender in the above scenarios from 450-500s down to about 20ms. This reintroduces the code that was removed in 58a83b0862, but in a slightly different way.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/gui/context/base_context.go6
-rw-r--r--pkg/gui/context/branches_context.go2
-rw-r--r--pkg/gui/context/local_commits_context.go2
-rw-r--r--pkg/gui/context/reflog_commits_context.go2
-rw-r--r--pkg/gui/context/sub_commits_context.go2
-rw-r--r--pkg/gui/controllers/screen_mode_actions.go27
-rw-r--r--pkg/gui/layout.go2
-rw-r--r--pkg/gui/types/context.go16
8 files changed, 48 insertions, 11 deletions
diff --git a/pkg/gui/context/base_context.go b/pkg/gui/context/base_context.go
index dfcced021..ca04a2fa9 100644
--- a/pkg/gui/context/base_context.go
+++ b/pkg/gui/context/base_context.go
@@ -23,7 +23,7 @@ type BaseContext struct {
focusable bool
transient bool
hasControlledBounds bool
- needsRerenderOnWidthChange bool
+ needsRerenderOnWidthChange types.NeedsRerenderOnWidthChangeLevel
needsRerenderOnHeightChange bool
highlightOnFocus bool
@@ -46,7 +46,7 @@ type NewBaseContextOpts struct {
Transient bool
HasUncontrolledBounds bool // negating for the sake of making false the default
HighlightOnFocus bool
- NeedsRerenderOnWidthChange bool
+ NeedsRerenderOnWidthChange types.NeedsRerenderOnWidthChangeLevel
NeedsRerenderOnHeightChange bool
OnGetOptionsMap func() map[string]string
@@ -201,7 +201,7 @@ func (self *BaseContext) HasControlledBounds() bool {
return self.hasControlledBounds
}
-func (self *BaseContext) NeedsRerenderOnWidthChange() bool {
+func (self *BaseContext) NeedsRerenderOnWidthChange() types.NeedsRerenderOnWidthChangeLevel {
return self.needsRerenderOnWidthChange
}
diff --git a/pkg/gui/context/branches_context.go b/pkg/gui/context/branches_context.go
index d2647ef84..d289f2729 100644
--- a/pkg/gui/context/branches_context.go
+++ b/pkg/gui/context/branches_context.go
@@ -46,7 +46,7 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
Key: LOCAL_BRANCHES_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
- NeedsRerenderOnWidthChange: true,
+ NeedsRerenderOnWidthChange: types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES,
})),
ListRenderer: ListRenderer{
list: viewModel,
diff --git a/pkg/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go
index ab42cfb70..fcb9b00ca 100644
--- a/pkg/gui/context/local_commits_context.go
+++ b/pkg/gui/context/local_commits_context.go
@@ -77,7 +77,7 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
Key: LOCAL_COMMITS_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
- NeedsRerenderOnWidthChange: true,
+ NeedsRerenderOnWidthChange: types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES,
NeedsRerenderOnHeightChange: true,
})),
ListRenderer: ListRenderer{
diff --git a/pkg/gui/context/reflog_commits_context.go b/pkg/gui/context/reflog_commits_context.go
index 57ca7c4dc..cec54988d 100644
--- a/pkg/gui/context/reflog_commits_context.go
+++ b/pkg/gui/context/reflog_commits_context.go
@@ -48,7 +48,7 @@ func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
Key: REFLOG_COMMITS_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
- NeedsRerenderOnWidthChange: true,
+ NeedsRerenderOnWidthChange: types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES,
})),
ListRenderer: ListRenderer{
list: viewModel,
diff --git a/pkg/gui/context/sub_commits_context.go b/pkg/gui/context/sub_commits_context.go
index ab0d2784a..ddbb380c5 100644
--- a/pkg/gui/context/sub_commits_context.go
+++ b/pkg/gui/context/sub_commits_context.go
@@ -121,7 +121,7 @@ func NewSubCommitsContext(
Kind: types.SIDE_CONTEXT,
Focusable: true,
Transient: true,
- NeedsRerenderOnWidthChange: true,
+ NeedsRerenderOnWidthChange: types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES,
NeedsRerenderOnHeightChange: true,
})),
ListRenderer: ListRenderer{
diff --git a/pkg/gui/controllers/screen_mode_actions.go b/pkg/gui/controllers/screen_mode_actions.go
index 1db27f2e2..2d0026793 100644
--- a/pkg/gui/controllers/screen_mode_actions.go
+++ b/pkg/gui/controllers/screen_mode_actions.go
@@ -1,6 +1,7 @@
package controllers
import (
+ "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
@@ -16,7 +17,7 @@ func (self *ScreenModeActions) Next() error {
),
)
- return nil
+ return self.rerenderViewsWithScreenModeDependentContent()
}
func (self *ScreenModeActions) Prev() error {
@@ -27,9 +28,33 @@ func (self *ScreenModeActions) Prev() error {
),
)
+ return self.rerenderViewsWithScreenModeDependentContent()
+}
+
+// these views need to be re-rendered when the screen mode changes. The commits view,
+// for example, will show authorship information in half and full screen mode.
+func (self *ScreenModeActions) rerenderViewsWithScreenModeDependentContent() error {
+ for _, context := range self.c.Context().AllList() {
+ if context.NeedsRerenderOnWidthChange() == types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES {
+ if err := self.rerenderView(context.GetView()); err != nil {
+ return err
+ }
+ }
+ }
+
return nil
}
+func (self *ScreenModeActions) rerenderView(view *gocui.View) error {
+ context, ok := self.c.Helpers().View.ContextForView(view.Name())
+ if !ok {
+ self.c.Log.Errorf("no context found for view %s", view.Name())
+ return nil
+ }
+
+ return context.HandleRender()
+}
+
func nextIntInCycle(sl []types.WindowMaximisation, current types.WindowMaximisation) types.WindowMaximisation {
for i, val := range sl {
if val == current {
diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go
index 4e2b49477..2123731e4 100644
--- a/pkg/gui/layout.go
+++ b/pkg/gui/layout.go
@@ -73,7 +73,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
}
mustRerender := false
- if context.NeedsRerenderOnWidthChange() {
+ if context.NeedsRerenderOnWidthChange() == types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES {
// view.Width() returns the width -1 for some reason
oldWidth := view.Width() + 1
newWidth := dimensionsObj.X1 - dimensionsObj.X0 + 2*frameOffset
diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go
index 003035fc2..70458c16f 100644
--- a/pkg/gui/types/context.go
+++ b/pkg/gui/types/context.go
@@ -39,6 +39,18 @@ type ParentContexter interface {
GetParentContext() (Context, bool)
}
+type NeedsRerenderOnWidthChangeLevel int
+
+const (
+ // view doesn't render differently when its width changes
+ NEEDS_RERENDER_ON_WIDTH_CHANGE_NONE NeedsRerenderOnWidthChangeLevel = iota
+ // view renders differently when its width changes. An example is a view
+ // that truncates long lines to the view width, e.g. the branches view
+ NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES
+ // view renders differently only when the screen mode changes
+ NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_SCREEN_MODE_CHANGES
+)
+
type IBaseContext interface {
HasKeybindings
ParentContexter
@@ -60,8 +72,8 @@ type IBaseContext interface {
// determined independently.
HasControlledBounds() bool
- // true if the view needs to be rerendered when its width changes
- NeedsRerenderOnWidthChange() bool
+ // to what extent the view needs to be rerendered when its width changes
+ NeedsRerenderOnWidthChange() NeedsRerenderOnWidthChangeLevel
// true if the view needs to be rerendered when its height changes
NeedsRerenderOnHeightChange() bool