Support filtering files

This commit is contained in:
Jesse Duffield 2023-05-27 19:58:48 +10:00
parent 84870d4503
commit 13326344f0
9 changed files with 72 additions and 19 deletions

View file

@ -23,3 +23,7 @@ func (f *CommitFile) Added() bool {
func (f *CommitFile) Deleted() bool {
return f.ChangeStatus == "D"
}
func (f *CommitFile) GetPath() string {
return f.Name
}

View file

@ -10,6 +10,7 @@ import (
)
type CommitFilesContext struct {
*FilteredList[*models.CommitFile]
*filetree.CommitFileTreeViewModel
*ListContextTrait
*DynamicTitleBuilder
@ -21,8 +22,13 @@ var (
)
func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
viewModel := filetree.NewCommitFileTreeViewModel(
filteredList := NewFilteredList(
func() []*models.CommitFile { return c.Model().CommitFiles },
func(file *models.CommitFile) []string { return []string{file.GetPath()} },
)
viewModel := filetree.NewCommitFileTreeViewModel(
func() []*models.CommitFile { return filteredList.GetFilteredList() },
c.Log,
c.UserConfig.Gui.ShowFileTree,
)
@ -39,6 +45,7 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
}
return &CommitFilesContext{
FilteredList: filteredList,
CommitFileTreeViewModel: viewModel,
DynamicTitleBuilder: NewDynamicTitleBuilder(c.Tr.CommitFilesDynamicTitle),
ListContextTrait: &ListContextTrait{
@ -71,3 +78,17 @@ func (self *CommitFilesContext) GetSelectedItemId() string {
func (self *CommitFilesContext) GetDiffTerminals() []string {
return []string{self.GetRef().RefName()}
}
// used for type switch
func (self *CommitFilesContext) IsFilterableContext() {}
// TODO: see if we can just call SetTree() within HandleRender(). It doesn't seem
// right that we need to imperatively refresh the view model like this
func (self *CommitFilesContext) SetFilter(filter string) {
self.FilteredList.SetFilter(filter)
self.SetTree()
}
func (self *CommitFilesContext) ClearFilter() {
self.SetFilter("")
}

View file

@ -14,6 +14,13 @@ type FilteredList[T any] struct {
filter string
}
func NewFilteredList[T any](getList func() []T, getFilterFields func(T) []string) *FilteredList[T] {
return &FilteredList[T]{
getList: getList,
getFilterFields: getFilterFields,
}
}
func (self *FilteredList[T]) GetFilter() string {
return self.filter
}
@ -28,13 +35,14 @@ func (self *FilteredList[T]) ClearFilter() {
self.SetFilter("")
}
func (self *FilteredList[T]) GetList() []T {
func (self *FilteredList[T]) GetFilteredList() []T {
if self.filteredIndices == nil {
return self.getList()
}
return utils.ValuesAtIndices(self.getList(), self.filteredIndices)
}
// TODO: update to just 'Len'
func (self *FilteredList[T]) UnfilteredLen() int {
return len(self.getList())
}

View file

@ -6,16 +6,13 @@ type FilteredListViewModel[T any] struct {
}
func NewFilteredListViewModel[T any](getList func() []T, getFilterFields func(T) []string) *FilteredListViewModel[T] {
filteredList := &FilteredList[T]{
getList: getList,
getFilterFields: getFilterFields,
}
filteredList := NewFilteredList(getList, getFilterFields)
self := &FilteredListViewModel[T]{
FilteredList: filteredList,
}
listViewModel := NewListViewModel(filteredList.GetList)
listViewModel := NewListViewModel(filteredList.GetFilteredList)
self.ListViewModel = listViewModel

View file

@ -9,20 +9,30 @@ import (
)
type WorkingTreeContext struct {
*FilteredList[*models.File]
*filetree.FileTreeViewModel
*ListContextTrait
}
var _ types.IListContext = (*WorkingTreeContext)(nil)
var (
_ types.IListContext = (*WorkingTreeContext)(nil)
_ types.IFilterableContext = (*WorkingTreeContext)(nil)
)
func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
viewModel := filetree.NewFileTreeViewModel(
filteredList := NewFilteredList(
func() []*models.File { return c.Model().Files },
func(file *models.File) []string { return []string{file.GetPath()} },
)
viewModel := filetree.NewFileTreeViewModel(
func() []*models.File { return filteredList.GetFilteredList() },
c.Log,
c.UserConfig.Gui.ShowFileTree,
)
getDisplayStrings := func(startIdx int, length int) [][]string {
c.Log.Warn("in get display strings")
lines := presentation.RenderFileTree(viewModel, c.Modes().Diffing.Ref, c.Model().Submodules)
return slices.Map(lines, func(line string) []string {
return []string{line}
@ -30,6 +40,7 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
}
return &WorkingTreeContext{
FilteredList: filteredList,
FileTreeViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
@ -54,3 +65,17 @@ func (self *WorkingTreeContext) GetSelectedItemId() string {
return item.ID()
}
// used for type switch
func (self *WorkingTreeContext) IsFilterableContext() {}
// TODO: see if we can just call SetTree() within HandleRender(). It doesn't seem
// right that we need to imperatively refresh the view model like this
func (self *WorkingTreeContext) SetFilter(filter string) {
self.FilteredList.SetFilter(filter)
self.SetTree()
}
func (self *WorkingTreeContext) ClearFilter() {
self.SetFilter("")
}

View file

@ -658,7 +658,7 @@ func (self *FilesController) handleStatusFilterPressed() error {
}
func (self *FilesController) setStatusFiltering(filter filetree.FileTreeDisplayFilter) error {
self.context().FileTreeViewModel.SetFilter(filter)
self.context().FileTreeViewModel.SetStatusFilter(filter)
return self.c.PostRefreshUpdate(self.context())
}

View file

@ -464,10 +464,10 @@ func (self *RefreshHelper) refreshStateFiles() error {
// I'd prefer to maintain as little state as possible.
if conflictFileCount > 0 {
if fileTreeViewModel.GetFilter() == filetree.DisplayAll {
fileTreeViewModel.SetFilter(filetree.DisplayConflicted)
fileTreeViewModel.SetStatusFilter(filetree.DisplayConflicted)
}
} else if fileTreeViewModel.GetFilter() == filetree.DisplayConflicted {
fileTreeViewModel.SetFilter(filetree.DisplayAll)
fileTreeViewModel.SetStatusFilter(filetree.DisplayAll)
}
self.c.Model().Files = files

View file

@ -34,7 +34,7 @@ type IFileTree interface {
ITree[models.File]
FilterFiles(test func(*models.File) bool) []*models.File
SetFilter(filter FileTreeDisplayFilter)
SetStatusFilter(filter FileTreeDisplayFilter)
Get(index int) *FileNode
GetFile(path string) *models.File
GetAllItems() []*FileNode
@ -91,7 +91,7 @@ func (self *FileTree) FilterFiles(test func(*models.File) bool) []*models.File {
return slices.Filter(self.getFiles(), test)
}
func (self *FileTree) SetFilter(filter FileTreeDisplayFilter) {
func (self *FileTree) SetStatusFilter(filter FileTreeDisplayFilter) {
self.filter = filter
self.SetTree()
}
@ -102,7 +102,7 @@ func (self *FileTree) ToggleShowTree() {
}
func (self *FileTree) Get(index int) *FileNode {
// need to traverse the three depth first until we get to the index.
// need to traverse the tree depth first until we get to the index.
return NewFileNode(self.tree.GetNodeAtIndex(index+1, self.collapsedPaths)) // ignoring root
}

View file

@ -26,8 +26,6 @@ type FileTreeViewModel struct {
var _ IFileTreeViewModel = &FileTreeViewModel{}
// how to tackle this? We could just filter down the list of files at a high point and then the rest will take care of itself.
func NewFileTreeViewModel(getFiles func() []*models.File, log *logrus.Entry, showTree bool) *FileTreeViewModel {
fileTree := NewFileTree(getFiles, log, showTree)
listCursor := traits.NewListCursor(fileTree)
@ -128,8 +126,8 @@ func (self *FileTreeViewModel) findNewSelectedIdx(prevNodes []*FileNode, currNod
return -1
}
func (self *FileTreeViewModel) SetFilter(filter FileTreeDisplayFilter) {
self.IFileTree.SetFilter(filter)
func (self *FileTreeViewModel) SetStatusFilter(filter FileTreeDisplayFilter) {
self.IFileTree.SetStatusFilter(filter)
self.IListCursor.SetSelectedLineIdx(0)
}