enhance: performance of filtering branch

This commit is contained in:
leo 2024-05-14 18:50:36 +08:00
parent ae63aa334a
commit c48d69362e
2 changed files with 37 additions and 33 deletions

View file

@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Avalonia.Collections; using Avalonia.Collections;
namespace SourceGit.ViewModels namespace SourceGit.ViewModels
@ -58,6 +58,8 @@ namespace SourceGit.ViewModels
public void Run(List<Models.Branch> branches, List<Models.Remote> remotes, bool bForceExpanded) public void Run(List<Models.Branch> branches, List<Models.Remote> remotes, bool bForceExpanded)
{ {
var folders = new Dictionary<string, BranchTreeNode>();
foreach (var remote in remotes) foreach (var remote in remotes)
{ {
var path = $"remote/{remote.Name}"; var path = $"remote/{remote.Name}";
@ -69,7 +71,7 @@ namespace SourceGit.ViewModels
IsExpanded = bForceExpanded || _expanded.Contains(path), IsExpanded = bForceExpanded || _expanded.Contains(path),
}; };
_maps.Add(path, node); folders.Add(path, node);
_remotes.Add(node); _remotes.Add(node);
} }
@ -78,16 +80,17 @@ namespace SourceGit.ViewModels
var isFiltered = _filters.Contains(branch.FullName); var isFiltered = _filters.Contains(branch.FullName);
if (branch.IsLocal) if (branch.IsLocal)
{ {
MakeBranchNode(branch, _locals, "local", isFiltered, bForceExpanded); MakeBranchNode(branch, _locals, folders, "local", isFiltered, bForceExpanded);
} }
else else
{ {
var remote = _remotes.Find(x => x.Name == branch.Remote); var remote = _remotes.Find(x => x.Name == branch.Remote);
if (remote != null) if (remote != null)
MakeBranchNode(branch, remote.Children, $"remote/{remote.Name}", isFiltered, bForceExpanded); MakeBranchNode(branch, remote.Children, folders, $"remote/{remote.Name}", isFiltered, bForceExpanded);
} }
} }
folders.Clear();
SortNodes(_locals); SortNodes(_locals);
SortNodes(_remotes); SortNodes(_remotes);
} }
@ -113,67 +116,69 @@ namespace SourceGit.ViewModels
} }
} }
private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, string prefix, bool isFiltered, bool bForceExpanded) private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool isFiltered, bool bForceExpanded)
{ {
var subs = branch.Name.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); var sepIdx = branch.Name.IndexOf('/', StringComparison.Ordinal);
if (sepIdx == -1)
if (subs.Length == 1)
{ {
var node = new BranchTreeNode() roots.Add(new BranchTreeNode()
{ {
Name = subs[0], Name = branch.Name,
Type = BranchTreeNodeType.Branch, Type = BranchTreeNodeType.Branch,
Backend = branch, Backend = branch,
IsExpanded = false, IsExpanded = false,
IsFiltered = isFiltered, IsFiltered = isFiltered,
}; });
roots.Add(node);
return; return;
} }
BranchTreeNode lastFolder = null; var lastFolder = null as BranchTreeNode;
var path = prefix; var start = 0;
for (var i = 0; i < subs.Length - 1; i++)
while (sepIdx != -1)
{ {
path = string.Concat(path, "/", subs[i]); var folder = string.Concat(prefix, "/", branch.Name.Substring(0, sepIdx));
if (_maps.TryGetValue(path, out var value)) var name = branch.Name.Substring(start, sepIdx - start);
if (folders.TryGetValue(folder, out var val))
{ {
lastFolder = value; lastFolder = val;
} }
else if (lastFolder == null) else if (lastFolder == null)
{ {
lastFolder = new BranchTreeNode() lastFolder = new BranchTreeNode()
{ {
Name = subs[i], Name = name,
Type = BranchTreeNodeType.Folder, Type = BranchTreeNodeType.Folder,
IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(path), IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder),
}; };
roots.Add(lastFolder); roots.Add(lastFolder);
_maps.Add(path, lastFolder); folders.Add(folder, lastFolder);
} }
else else
{ {
var folder = new BranchTreeNode() var cur = new BranchTreeNode()
{ {
Name = subs[i], Name = name,
Type = BranchTreeNodeType.Folder, Type = BranchTreeNodeType.Folder,
IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(path), IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder),
}; };
_maps.Add(path, folder); lastFolder.Children.Add(cur);
lastFolder.Children.Add(folder); folders.Add(folder, cur);
lastFolder = folder; lastFolder = cur;
} }
start = sepIdx + 1;
sepIdx = branch.Name.IndexOf('/', start);
} }
var last = new BranchTreeNode() lastFolder.Children.Add(new BranchTreeNode()
{ {
Name = subs[subs.Length - 1], Name = Path.GetFileName(branch.Name),
Type = BranchTreeNodeType.Branch, Type = BranchTreeNodeType.Branch,
Backend = branch, Backend = branch,
IsExpanded = false, IsExpanded = false,
IsFiltered = isFiltered, IsFiltered = isFiltered,
}; });
lastFolder.Children.Add(last);
} }
private void SortNodes(List<BranchTreeNode> nodes) private void SortNodes(List<BranchTreeNode> nodes)
@ -198,7 +203,6 @@ namespace SourceGit.ViewModels
private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>(); private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>();
private readonly HashSet<string> _expanded = new HashSet<string>(); private readonly HashSet<string> _expanded = new HashSet<string>();
private readonly List<string> _filters = new List<string>(); private readonly List<string> _filters = new List<string>();
private readonly Dictionary<string, BranchTreeNode> _maps = new Dictionary<string, BranchTreeNode>();
} }
} }
} }

View file

@ -1389,7 +1389,7 @@ namespace SourceGit.ViewModels
visibles.Add(b); visibles.Add(b);
} }
builder.Run(visibles, remotes, true); builder.Run(visibles, remotes, visibles.Count <= 20);
} }
return builder; return builder;