summaryrefslogtreecommitdiffstats
path: root/pkg/gui/refresh.go
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2022-01-30 13:08:09 +1100
committerJesse Duffield <jessedduffield@gmail.com>2022-03-17 19:13:40 +1100
commit8ea7b7a62e5a09314bbe7a446a45e649d66b524d (patch)
tree4f2e2fe927b5f8380249e51eef30820383d145e2 /pkg/gui/refresh.go
parent09dc160da98a0a4fe976d3d174cc93af57c53892 (diff)
migrate files context to new structure
Diffstat (limited to 'pkg/gui/refresh.go')
-rw-r--r--pkg/gui/refresh.go81
1 files changed, 53 insertions, 28 deletions
diff --git a/pkg/gui/refresh.go b/pkg/gui/refresh.go
index bf22b5ff6..6f8f16fa5 100644
--- a/pkg/gui/refresh.go
+++ b/pkg/gui/refresh.go
@@ -371,7 +371,8 @@ func (gui *Gui) refreshStateFiles() error {
selectedNode := gui.getSelectedFileNode()
- prevNodes := gui.State.FileTreeViewModel.GetAllItems()
+ fileTreeViewModel := state.Contexts.Files.WorkingTreeViewModal
+ prevNodes := fileTreeViewModel.GetAllItems()
prevSelectedLineIdx := gui.State.Panels.Files.SelectedLineIdx
// If git thinks any of our files have inline merge conflicts, but they actually don't,
@@ -383,7 +384,7 @@ func (gui *Gui) refreshStateFiles() error {
// we call git status again.
pathsToStage := []string{}
prevConflictFileCount := 0
- for _, file := range state.FileTreeViewModel.GetAllFiles() {
+ for _, file := range gui.State.Files {
if file.HasMergeConflicts {
prevConflictFileCount++
}
@@ -419,10 +420,10 @@ func (gui *Gui) refreshStateFiles() error {
}
// for when you stage the old file of a rename and the new file is in a collapsed dir
- state.FileTreeViewModel.RWMutex.Lock()
+ fileTreeViewModel.RWMutex.Lock()
for _, file := range files {
if selectedNode != nil && selectedNode.Path != "" && file.PreviousName == selectedNode.Path {
- state.FileTreeViewModel.ExpandToPath(file.Name)
+ fileTreeViewModel.ExpandToPath(file.Name)
}
}
@@ -432,46 +433,70 @@ func (gui *Gui) refreshStateFiles() error {
// extra state here to see if the user's set the filter themselves we can do that, but
// I'd prefer to maintain as little state as possible.
if conflictFileCount > 0 {
- if state.FileTreeViewModel.GetFilter() == filetree.DisplayAll {
- state.FileTreeViewModel.SetFilter(filetree.DisplayConflicted)
+ if fileTreeViewModel.GetFilter() == filetree.DisplayAll {
+ fileTreeViewModel.SetFilter(filetree.DisplayConflicted)
}
- } else if state.FileTreeViewModel.GetFilter() == filetree.DisplayConflicted {
- state.FileTreeViewModel.SetFilter(filetree.DisplayAll)
+ } else if fileTreeViewModel.GetFilter() == filetree.DisplayConflicted {
+ fileTreeViewModel.SetFilter(filetree.DisplayAll)
}
- state.FileTreeViewModel.SetFiles(files)
- state.FileTreeViewModel.RWMutex.Unlock()
+ state.Files = files
+ fileTreeViewModel.SetTree()
+ fileTreeViewModel.RWMutex.Unlock()
if err := gui.fileWatcher.addFilesToFileWatcher(files); err != nil {
return err
}
if selectedNode != nil {
- newIdx := gui.findNewSelectedIdx(prevNodes[prevSelectedLineIdx:], state.FileTreeViewModel.GetAllItems())
+ newIdx := gui.findNewSelectedIdx(prevNodes[prevSelectedLineIdx:], fileTreeViewModel.GetAllItems())
if newIdx != -1 && newIdx != prevSelectedLineIdx {
- newNode := state.FileTreeViewModel.GetItemAtIndex(newIdx)
- // when not in tree mode, we show merge conflict files at the top, so you
- // can work through them one by one without having to sift through a large
- // set of files. If you have just fixed the merge conflicts of a file, we
- // actually don't want to jump to that file's new position, because that
- // file will now be ages away amidst the other files without merge
- // conflicts: the user in this case would rather work on the next file
- // with merge conflicts, which will have moved up to fill the gap left by
- // the last file, meaning the cursor doesn't need to move at all.
- leaveCursor := !state.FileTreeViewModel.InTreeMode() && newNode != nil &&
- selectedNode.File != nil && selectedNode.File.HasMergeConflicts &&
- newNode.File != nil && !newNode.File.HasMergeConflicts
-
- if !leaveCursor {
- state.Panels.Files.SelectedLineIdx = newIdx
- }
+ state.Panels.Files.SelectedLineIdx = newIdx
}
}
- gui.refreshSelectedLine(state.Panels.Files, state.FileTreeViewModel.GetItemsLength())
+ gui.refreshSelectedLine(state.Panels.Files, fileTreeViewModel.GetItemsLength())
return nil
}
+// Let's try to find our file again and move the cursor to that.
+// If we can't find our file, it was probably just removed by the user. In that
+// case, we go looking for where the next file has been moved to. Given that the
+// user could have removed a whole directory, we continue iterating through the old
+// nodes until we find one that exists in the new set of nodes, then move the cursor
+// to that.
+// prevNodes starts from our previously selected node because we don't need to consider anything above that
+func (gui *Gui) findNewSelectedIdx(prevNodes []*filetree.FileNode, currNodes []*filetree.FileNode) int {
+ getPaths := func(node *filetree.FileNode) []string {
+ if node == nil {
+ return nil
+ }
+ if node.File != nil && node.File.IsRename() {
+ return node.File.Names()
+ } else {
+ return []string{node.Path}
+ }
+ }
+
+ for _, prevNode := range prevNodes {
+ selectedPaths := getPaths(prevNode)
+
+ for idx, node := range currNodes {
+ paths := getPaths(node)
+
+ // If you started off with a rename selected, and now it's broken in two, we want you to jump to the new file, not the old file.
+ // This is because the new should be in the same position as the rename was meaning less cursor jumping
+ foundOldFileInRename := prevNode.File != nil && prevNode.File.IsRename() && node.Path == prevNode.File.PreviousName
+ foundNode := utils.StringArraysOverlap(paths, selectedPaths) && !foundOldFileInRename
+ if foundNode {
+ return idx
+ }
+ }
+ }
+
+ return -1
+}
+
// the reflogs panel is the only panel where we cache data, in that we only
// load entries that have been created since we last ran the call. This means
// we need to be more careful with how we use this, and to ensure we're emptying