refactor: save history filters into $GIT_DIR/sourcegit.filters to support different filters between worktrees (#1893)

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2025-11-04 20:54:49 +08:00
parent 36aeb3f932
commit 95ddedd7b6
12 changed files with 341 additions and 309 deletions

View File

@@ -60,6 +60,7 @@ namespace SourceGit
]
)]
[JsonSerializable(typeof(Models.ExternalToolPaths))]
[JsonSerializable(typeof(Models.HistoryFilterCollection))]
[JsonSerializable(typeof(Models.InteractiveRebaseJobCollection))]
[JsonSerializable(typeof(Models.JetBrainsState))]
[JsonSerializable(typeof(Models.ThemeOverrides))]

View File

@@ -1,60 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.Models
{
public enum FilterType
{
LocalBranch = 0,
LocalBranchFolder,
RemoteBranch,
RemoteBranchFolder,
Tag,
}
public enum FilterMode
{
None = 0,
Included,
Excluded,
}
public class Filter : ObservableObject
{
public string Pattern
{
get => _pattern;
set => SetProperty(ref _pattern, value);
}
public FilterType Type
{
get;
set;
} = FilterType.LocalBranch;
public FilterMode Mode
{
get => _mode;
set => SetProperty(ref _mode, value);
}
public bool IsBranch
{
get => Type != FilterType.Tag;
}
public Filter()
{
}
public Filter(string pattern, FilterType type, FilterMode mode)
{
_pattern = pattern;
_mode = mode;
Type = type;
}
private string _pattern = string.Empty;
private FilterMode _mode = FilterMode.None;
}
}

View File

@@ -0,0 +1,246 @@
using System;
using System.Collections.Generic;
using System.Text;
using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.Models
{
public enum FilterType
{
LocalBranch = 0,
LocalBranchFolder,
RemoteBranch,
RemoteBranchFolder,
Tag,
}
public enum FilterMode
{
None = 0,
Included,
Excluded,
}
public class HistoryFilter : ObservableObject
{
public string Pattern
{
get => _pattern;
set => SetProperty(ref _pattern, value);
}
public FilterType Type
{
get;
set;
} = FilterType.LocalBranch;
public FilterMode Mode
{
get => _mode;
set => SetProperty(ref _mode, value);
}
public bool IsBranch
{
get => Type != FilterType.Tag;
}
public HistoryFilter()
{
}
public HistoryFilter(string pattern, FilterType type, FilterMode mode)
{
_pattern = pattern;
_mode = mode;
Type = type;
}
private string _pattern = string.Empty;
private FilterMode _mode = FilterMode.None;
}
public class HistoryFilterCollection
{
public AvaloniaList<HistoryFilter> Filters
{
get;
set;
} = [];
public FilterMode Mode => Filters.Count > 0 ? Filters[0].Mode : FilterMode.None;
public Dictionary<string, FilterMode> ToMap()
{
var map = new Dictionary<string, FilterMode>();
foreach (var filter in Filters)
map.Add(filter.Pattern, filter.Mode);
return map;
}
public bool Update(string pattern, FilterType type, FilterMode mode)
{
// Clear all filters when there's a filter that has different mode.
if (mode != FilterMode.None)
{
var clear = false;
foreach (var filter in Filters)
{
if (filter.Mode != mode)
{
clear = true;
break;
}
}
if (clear)
{
Filters.Clear();
Filters.Add(new HistoryFilter(pattern, type, mode));
return true;
}
}
else
{
for (int i = 0; i < Filters.Count; i++)
{
var filter = Filters[i];
if (filter.Type == type && filter.Pattern.Equals(pattern, StringComparison.Ordinal))
{
Filters.RemoveAt(i);
return true;
}
}
return false;
}
foreach (var filter in Filters)
{
if (filter.Type != type)
continue;
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
return false;
}
Filters.Add(new HistoryFilter(pattern, type, mode));
return true;
}
public FilterMode GetFilterMode(string pattern)
{
foreach (var filter in Filters)
{
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
return filter.Mode;
}
return FilterMode.None;
}
public void RemoveBranchFiltersByPrefix(string pattern)
{
var dirty = new List<HistoryFilter>();
var prefix = $"{pattern}/";
foreach (var filter in Filters)
{
if (filter.Type != FilterType.Tag)
continue;
if (filter.Pattern.StartsWith(prefix, StringComparison.Ordinal))
dirty.Add(filter);
}
foreach (var filter in dirty)
Filters.Remove(filter);
}
public string Build()
{
var includedRefs = new List<string>();
var excludedBranches = new List<string>();
var excludedRemotes = new List<string>();
var excludedTags = new List<string>();
foreach (var filter in Filters)
{
if (filter.Type == FilterType.LocalBranch)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add(filter.Pattern);
else if (filter.Mode == FilterMode.Excluded)
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
}
else if (filter.Type == FilterType.LocalBranchFolder)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add($"--branches={filter.Pattern.AsSpan(11)}/*");
else if (filter.Mode == FilterMode.Excluded)
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
}
else if (filter.Type == FilterType.RemoteBranch)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add(filter.Pattern);
else if (filter.Mode == FilterMode.Excluded)
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
}
else if (filter.Type == FilterType.RemoteBranchFolder)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add($"--remotes={filter.Pattern.AsSpan(13)}/*");
else if (filter.Mode == FilterMode.Excluded)
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
}
else if (filter.Type == FilterType.Tag)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add($"refs/tags/{filter.Pattern}");
else if (filter.Mode == FilterMode.Excluded)
excludedTags.Add($"--exclude=\"{filter.Pattern}\" --decorate-refs-exclude=\"refs/tags/{filter.Pattern}\"");
}
}
var builder = new StringBuilder();
if (includedRefs.Count > 0)
{
foreach (var r in includedRefs)
{
builder.Append(r);
builder.Append(' ');
}
}
else if (excludedBranches.Count + excludedRemotes.Count + excludedTags.Count > 0)
{
foreach (var b in excludedBranches)
{
builder.Append(b);
builder.Append(' ');
}
builder.Append("--exclude=HEAD --branches ");
foreach (var r in excludedRemotes)
{
builder.Append(r);
builder.Append(' ');
}
builder.Append("--exclude=origin/HEAD --remotes ");
foreach (var t in excludedTags)
{
builder.Append(t);
builder.Append(' ');
}
builder.Append("--tags ");
}
return builder.ToString();
}
}
}

View File

@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Avalonia.Collections;
namespace SourceGit.Models
@@ -116,12 +113,6 @@ namespace SourceGit.Models
set;
} = true;
public AvaloniaList<Filter> HistoriesFilters
{
get;
set;
} = [];
public AvaloniaList<CommitTemplate> CommitTemplates
{
get;
@@ -242,166 +233,6 @@ namespace SourceGit.Models
set;
} = string.Empty;
public Dictionary<string, FilterMode> CollectHistoriesFilters()
{
var map = new Dictionary<string, FilterMode>();
foreach (var filter in HistoriesFilters)
map.Add(filter.Pattern, filter.Mode);
return map;
}
public bool UpdateHistoriesFilter(string pattern, FilterType type, FilterMode mode)
{
// Clear all filters when there's a filter that has different mode.
if (mode != FilterMode.None)
{
var clear = false;
foreach (var filter in HistoriesFilters)
{
if (filter.Mode != mode)
{
clear = true;
break;
}
}
if (clear)
{
HistoriesFilters.Clear();
HistoriesFilters.Add(new Filter(pattern, type, mode));
return true;
}
}
else
{
for (int i = 0; i < HistoriesFilters.Count; i++)
{
var filter = HistoriesFilters[i];
if (filter.Type == type && filter.Pattern.Equals(pattern, StringComparison.Ordinal))
{
HistoriesFilters.RemoveAt(i);
return true;
}
}
return false;
}
foreach (var filter in HistoriesFilters)
{
if (filter.Type != type)
continue;
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
return false;
}
HistoriesFilters.Add(new Filter(pattern, type, mode));
return true;
}
public void RemoveChildrenBranchFilters(string pattern)
{
var dirty = new List<Filter>();
var prefix = $"{pattern}/";
foreach (var filter in HistoriesFilters)
{
if (filter.Type == FilterType.Tag)
continue;
if (filter.Pattern.StartsWith(prefix, StringComparison.Ordinal))
dirty.Add(filter);
}
foreach (var filter in dirty)
HistoriesFilters.Remove(filter);
}
public string BuildHistoriesFilter()
{
var includedRefs = new List<string>();
var excludedBranches = new List<string>();
var excludedRemotes = new List<string>();
var excludedTags = new List<string>();
foreach (var filter in HistoriesFilters)
{
if (filter.Type == FilterType.LocalBranch)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add(filter.Pattern);
else if (filter.Mode == FilterMode.Excluded)
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
}
else if (filter.Type == FilterType.LocalBranchFolder)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add($"--branches={filter.Pattern.AsSpan(11)}/*");
else if (filter.Mode == FilterMode.Excluded)
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
}
else if (filter.Type == FilterType.RemoteBranch)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add(filter.Pattern);
else if (filter.Mode == FilterMode.Excluded)
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
}
else if (filter.Type == FilterType.RemoteBranchFolder)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add($"--remotes={filter.Pattern.AsSpan(13)}/*");
else if (filter.Mode == FilterMode.Excluded)
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
}
else if (filter.Type == FilterType.Tag)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add($"refs/tags/{filter.Pattern}");
else if (filter.Mode == FilterMode.Excluded)
excludedTags.Add($"--exclude=\"{filter.Pattern}\" --decorate-refs-exclude=\"refs/tags/{filter.Pattern}\"");
}
}
var builder = new StringBuilder();
if (includedRefs.Count > 0)
{
foreach (var r in includedRefs)
{
builder.Append(r);
builder.Append(' ');
}
}
else if (excludedBranches.Count + excludedRemotes.Count + excludedTags.Count > 0)
{
foreach (var b in excludedBranches)
{
builder.Append(b);
builder.Append(' ');
}
builder.Append("--exclude=HEAD --branches ");
foreach (var r in excludedRemotes)
{
builder.Append(r);
builder.Append(' ');
}
builder.Append("--exclude=origin/HEAD --remotes ");
foreach (var t in excludedTags)
{
builder.Append(t);
builder.Append(' ');
}
builder.Append("--tags ");
}
return builder.ToString();
}
public void PushCommitMessage(string message)
{
message = message.Trim().ReplaceLineEndings("\n");

View File

@@ -98,7 +98,7 @@ namespace SourceGit.ViewModels
log.Complete();
var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch);
if (b != null && _repo.HistoriesFilterMode == Models.FilterMode.Included)
if (b != null && _repo.HistoryFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(b, Models.FilterMode.Included, false, false);
_repo.MarkBranchesDirtyManually();

View File

@@ -102,7 +102,7 @@ namespace SourceGit.ViewModels
log.Complete();
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
if (_repo.HistoryFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, false, false);
_repo.MarkBranchesDirtyManually();

View File

@@ -216,7 +216,7 @@ namespace SourceGit.ViewModels
if (folderEndIdx > 10)
_repo.Settings.ExpandedBranchNodesInSideBar.Add(fake.FullName.Substring(0, folderEndIdx));
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
if (_repo.HistoryFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(fake, Models.FilterMode.Included, false, false);
}

View File

@@ -1,5 +1,4 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
@@ -23,20 +22,9 @@ namespace SourceGit.ViewModels
_target = target;
if (_target is Models.Branch b)
_mode = GetFilterMode(b.FullName);
_mode = _repo.HistoryFilterCollection.GetFilterMode(b.FullName);
else if (_target is Models.Tag t)
_mode = GetFilterMode(t.Name);
}
private Models.FilterMode GetFilterMode(string pattern)
{
foreach (var filter in _repo.Settings.HistoriesFilters)
{
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
return filter.Mode;
}
return Models.FilterMode.None;
_mode = _repo.HistoryFilterCollection.GetFilterMode(t.Name);
}
private void SetFilterMode(Models.FilterMode mode)

View File

@@ -61,7 +61,7 @@ namespace SourceGit.ViewModels
if (succ)
{
foreach (var filter in _repo.Settings.HistoriesFilters)
foreach (var filter in _repo.HistoryFilterCollection.Filters)
{
if (filter.Type == Models.FilterType.LocalBranch &&
filter.Pattern.Equals(oldName, StringComparison.Ordinal))

View File

@@ -41,10 +41,15 @@ namespace SourceGit.ViewModels
set;
} = new();
public Models.FilterMode HistoriesFilterMode
public Models.HistoryFilterCollection HistoryFilterCollection
{
get => _historiesFilterMode;
private set => SetProperty(ref _historiesFilterMode, value);
get => _historyFilterCollection;
}
public Models.FilterMode HistoryFilterMode
{
get => _historyFilterMode;
private set => SetProperty(ref _historyFilterMode, value);
}
public bool HasAllowedSignersFile
@@ -526,6 +531,24 @@ namespace SourceGit.ViewModels
_settings = new Models.RepositorySettings();
}
var historyFilterFile = Path.Combine(GitDir, "sourcegit.filters");
if (File.Exists(historyFilterFile))
{
try
{
using var stream = File.OpenRead(historyFilterFile);
_historyFilterCollection = JsonSerializer.Deserialize(stream, JsonCodeGen.Default.HistoryFilterCollection);
}
catch
{
_historyFilterCollection = new Models.HistoryFilterCollection();
}
}
else
{
_historyFilterCollection = new Models.HistoryFilterCollection();
}
try
{
_watcher = new Models.Watcher(this, FullPath, _gitCommonDir);
@@ -535,11 +558,7 @@ namespace SourceGit.ViewModels
App.RaiseException(string.Empty, $"Failed to start watcher for repository: '{FullPath}'. You may need to press 'F5' to refresh repository manually!\n\nReason: {ex.Message}");
}
if (_settings.HistoriesFilters.Count > 0)
_historiesFilterMode = _settings.HistoriesFilters[0].Mode;
else
_historiesFilterMode = Models.FilterMode.None;
_historyFilterMode = _historyFilterCollection.Mode;
_histories = new Histories(this);
_workingCopy = new WorkingCopy(this) { CommitMessage = _settings.LastCommitMessage };
_stashesPage = new StashesPage(this);
@@ -583,6 +602,16 @@ namespace SourceGit.ViewModels
}
}
try
{
using var stream = File.Create(Path.Combine(GitDir, "sourcegit.filters"));
JsonSerializer.Serialize(stream, _historyFilterCollection, JsonCodeGen.Default.HistoryFilterCollection);
}
catch
{
// Ignore
}
if (_cancellationRefreshBranches is { IsCancellationRequested: false })
_cancellationRefreshBranches.Cancel();
if (_cancellationRefreshTags is { IsCancellationRequested: false })
@@ -598,7 +627,7 @@ namespace SourceGit.ViewModels
_autoFetchTimer = null;
_settings = null;
_historiesFilterMode = Models.FilterMode.None;
_historyFilterMode = Models.FilterMode.None;
_watcher?.Dispose();
_histories.Dispose();
@@ -1014,10 +1043,10 @@ namespace SourceGit.ViewModels
return (_histories?.DetailContext as CommitDetail)?.Commit;
}
public void ClearHistoriesFilter()
public void ClearHistoryFilters()
{
_settings.HistoriesFilters.Clear();
HistoriesFilterMode = Models.FilterMode.None;
_historyFilterCollection.Filters.Clear();
HistoryFilterMode = Models.FilterMode.None;
ResetBranchTreeFilterMode(LocalBranchTrees);
ResetBranchTreeFilterMode(RemoteBranchTrees);
@@ -1025,12 +1054,12 @@ namespace SourceGit.ViewModels
RefreshCommits();
}
public void RemoveHistoriesFilter(Models.Filter filter)
public void RemoveHistoryFilter(Models.HistoryFilter filter)
{
if (_settings.HistoriesFilters.Remove(filter))
if (_historyFilterCollection.Filters.Remove(filter))
{
HistoriesFilterMode = _settings.HistoriesFilters.Count > 0 ? _settings.HistoriesFilters[0].Mode : Models.FilterMode.None;
RefreshHistoriesFilters(true);
HistoryFilterMode = _historyFilterCollection.Mode;
RefreshHistoryFilters(true);
}
}
@@ -1052,9 +1081,9 @@ namespace SourceGit.ViewModels
public void SetTagFilterMode(Models.Tag tag, Models.FilterMode mode)
{
var changed = _settings.UpdateHistoriesFilter(tag.Name, Models.FilterType.Tag, mode);
var changed = _historyFilterCollection.Update(tag.Name, Models.FilterType.Tag, mode);
if (changed)
RefreshHistoriesFilters(true);
RefreshHistoryFilters(true);
}
public void SetBranchFilterMode(Models.Branch branch, Models.FilterMode mode, bool clearExists, bool refresh)
@@ -1071,28 +1100,28 @@ namespace SourceGit.ViewModels
if (clearExists)
{
_settings.HistoriesFilters.Clear();
HistoriesFilterMode = Models.FilterMode.None;
_historyFilterCollection.Filters.Clear();
HistoryFilterMode = Models.FilterMode.None;
}
if (node.Backend is Models.Branch branch)
{
var type = isLocal ? Models.FilterType.LocalBranch : Models.FilterType.RemoteBranch;
var changed = _settings.UpdateHistoriesFilter(node.Path, type, mode);
var changed = _historyFilterCollection.Update(node.Path, type, mode);
if (!changed)
return;
if (isLocal && !string.IsNullOrEmpty(branch.Upstream) && !branch.IsUpstreamGone)
_settings.UpdateHistoriesFilter(branch.Upstream, Models.FilterType.RemoteBranch, mode);
_historyFilterCollection.Update(branch.Upstream, Models.FilterType.RemoteBranch, mode);
}
else
{
var type = isLocal ? Models.FilterType.LocalBranchFolder : Models.FilterType.RemoteBranchFolder;
var changed = _settings.UpdateHistoriesFilter(node.Path, type, mode);
var changed = _historyFilterCollection.Update(node.Path, type, mode);
if (!changed)
return;
_settings.RemoveChildrenBranchFilters(node.Path);
_historyFilterCollection.RemoveBranchFiltersByPrefix(node.Path);
}
var parentType = isLocal ? Models.FilterType.LocalBranchFolder : Models.FilterType.RemoteBranchFolder;
@@ -1108,11 +1137,11 @@ namespace SourceGit.ViewModels
if (parent == null)
break;
_settings.UpdateHistoriesFilter(parent.Path, parentType, Models.FilterMode.None);
_historyFilterCollection.Update(parent.Path, parentType, Models.FilterMode.None);
cur = parent;
} while (true);
RefreshHistoriesFilters(refresh);
RefreshHistoryFilters(refresh);
}
public async Task StashAllAsync(bool autoStart)
@@ -1304,7 +1333,7 @@ namespace SourceGit.ViewModels
if (_settings.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.SimplifyByDecoration))
builder.Append("--simplify-by-decoration ");
var filters = _settings.BuildHistoriesFilter();
var filters = _historyFilterCollection.Build();
if (string.IsNullOrEmpty(filters))
builder.Append("--branches --remotes --tags HEAD");
else
@@ -1770,9 +1799,9 @@ namespace SourceGit.ViewModels
builder.Run(visibles, remotes, true);
}
var historiesFilters = _settings.CollectHistoriesFilters();
UpdateBranchTreeFilterMode(builder.Locals, historiesFilters);
UpdateBranchTreeFilterMode(builder.Remotes, historiesFilters);
var filterMap = _historyFilterCollection.ToMap();
UpdateBranchTreeFilterMode(builder.Locals, filterMap);
UpdateBranchTreeFilterMode(builder.Remotes, filterMap);
return builder;
}
@@ -1802,21 +1831,21 @@ namespace SourceGit.ViewModels
}
}
var historiesFilters = _settings.CollectHistoriesFilters();
UpdateTagFilterMode(historiesFilters);
var filterMap = _historyFilterCollection.ToMap();
UpdateTagFilterMode(filterMap);
if (Preferences.Instance.ShowTagsAsTree)
{
var tree = TagCollectionAsTree.Build(visible, _visibleTags as TagCollectionAsTree);
foreach (var node in tree.Tree)
node.UpdateFilterMode(historiesFilters);
node.UpdateFilterMode(filterMap);
return tree;
}
else
{
var list = new TagCollectionAsList(visible);
foreach (var item in list.TagItems)
item.FilterMode = historiesFilters.GetValueOrDefault(item.Tag.Name, Models.FilterMode.None);
item.FilterMode = filterMap.GetValueOrDefault(item.Tag.Name, Models.FilterMode.None);
return list;
}
}
@@ -1843,45 +1872,41 @@ namespace SourceGit.ViewModels
return new SubmoduleCollectionAsList() { Submodules = visible };
}
private void RefreshHistoriesFilters(bool refresh)
private void RefreshHistoryFilters(bool refresh)
{
if (_settings.HistoriesFilters.Count > 0)
HistoriesFilterMode = _settings.HistoriesFilters[0].Mode;
else
HistoriesFilterMode = Models.FilterMode.None;
HistoryFilterMode = _historyFilterCollection.Mode;
if (!refresh)
return;
var filters = _settings.CollectHistoriesFilters();
UpdateBranchTreeFilterMode(LocalBranchTrees, filters);
UpdateBranchTreeFilterMode(RemoteBranchTrees, filters);
UpdateTagFilterMode(filters);
var map = _historyFilterCollection.ToMap();
UpdateBranchTreeFilterMode(LocalBranchTrees, map);
UpdateBranchTreeFilterMode(RemoteBranchTrees, map);
UpdateTagFilterMode(map);
RefreshCommits();
}
private void UpdateBranchTreeFilterMode(List<BranchTreeNode> nodes, Dictionary<string, Models.FilterMode> filters)
private void UpdateBranchTreeFilterMode(List<BranchTreeNode> nodes, Dictionary<string, Models.FilterMode> map)
{
foreach (var node in nodes)
{
node.FilterMode = filters.GetValueOrDefault(node.Path, Models.FilterMode.None);
node.FilterMode = map.GetValueOrDefault(node.Path, Models.FilterMode.None);
if (!node.IsBranch)
UpdateBranchTreeFilterMode(node.Children, filters);
UpdateBranchTreeFilterMode(node.Children, map);
}
}
private void UpdateTagFilterMode(Dictionary<string, Models.FilterMode> filters)
private void UpdateTagFilterMode(Dictionary<string, Models.FilterMode> map)
{
if (VisibleTags is TagCollectionAsTree tree)
{
foreach (var node in tree.Tree)
node.UpdateFilterMode(filters);
node.UpdateFilterMode(map);
}
else if (VisibleTags is TagCollectionAsList list)
{
foreach (var item in list.TagItems)
item.FilterMode = filters.GetValueOrDefault(item.Tag.Name, Models.FilterMode.None);
item.FilterMode = map.GetValueOrDefault(item.Tag.Name, Models.FilterMode.None);
}
}
@@ -2040,7 +2065,8 @@ namespace SourceGit.ViewModels
private readonly bool _isWorktree = false;
private readonly string _gitCommonDir = null;
private Models.RepositorySettings _settings = null;
private Models.FilterMode _historiesFilterMode = Models.FilterMode.None;
private Models.HistoryFilterCollection _historyFilterCollection = null;
private Models.FilterMode _historyFilterMode = Models.FilterMode.None;
private bool _hasAllowedSignersFile = false;
private Models.Watcher _watcher = null;

View File

@@ -785,7 +785,7 @@
<Border.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="SelectedViewIndex" Converter="{x:Static c:IntConverters.IsZero}"/>
<Binding Path="Settings.HistoriesFilters.Count" Converter="{x:Static c:IntConverters.IsGreaterThanZero}"/>
<Binding Path="HistoryFilterCollection.Filters.Count" Converter="{x:Static c:IntConverters.IsGreaterThanZero}"/>
</MultiBinding>
</Border.IsVisible>
@@ -795,15 +795,15 @@
Width="12" Height="12"
Data="{StaticResource Icons.Filter}"
Fill="{DynamicResource Brush.FG2}"
IsVisible="{Binding HistoriesFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Included}}"/>
IsVisible="{Binding HistoryFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Included}}"/>
<Path Grid.Column="0"
Margin="8,0,0,0"
Width="12" Height="12"
Data="{StaticResource Icons.EyeClose}"
Fill="{DynamicResource Brush.FG2}"
IsVisible="{Binding HistoriesFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Excluded}}"/>
IsVisible="{Binding HistoryFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Excluded}}"/>
<ItemsControl Grid.Column="1" Margin="8,4" ItemsSource="{Binding Settings.HistoriesFilters}">
<ItemsControl Grid.Column="1" Margin="8,4" ItemsSource="{Binding HistoryFilterCollection.Filters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" ItemHeight="22"/>
@@ -811,7 +811,7 @@
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="m:Filter">
<DataTemplate DataType="m:HistoryFilter">
<Border Height="20"
Margin="0,0,6,0"
CornerRadius="12"
@@ -823,7 +823,7 @@
<Path Width="10" Height="10" Data="{StaticResource Icons.Tag}" IsVisible="{Binding !IsBranch}"/>
<TextBlock Text="{Binding Pattern, Converter={x:Static c:StringConverters.TrimRefsPrefix}}" Margin="4,0,8,0"/>
<Button Classes="icon_button" VerticalAlignment="Center" Margin="0" Padding="0" Click="OnRemoveSelectedHistoriesFilter">
<Button Classes="icon_button" VerticalAlignment="Center" Margin="0" Padding="0" Click="OnRemoveSelectedHistoryFilter">
<Path Width="8" Height="8" Data="{StaticResource Icons.Close}"/>
</Button>
</StackPanel>
@@ -832,7 +832,7 @@
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Grid.Column="2" Classes="icon_button" Command="{Binding ClearHistoriesFilter}" ToolTip.Tip="{DynamicResource Text.Repository.ClearAllCommitsFilter}">
<Button Grid.Column="2" Classes="icon_button" Command="{Binding ClearHistoryFilters}" ToolTip.Tip="{DynamicResource Text.Repository.ClearAllCommitsFilter}">
<Path Width="14" Height="14" Margin="16,0,8,0" Data="{StaticResource Icons.RemoveAll}"/>
</Button>
</Grid>

View File

@@ -586,10 +586,10 @@ namespace SourceGit.Views
e.Handled = true;
}
private void OnRemoveSelectedHistoriesFilter(object sender, RoutedEventArgs e)
private void OnRemoveSelectedHistoryFilter(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter })
repo.RemoveHistoriesFilter(filter);
if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.HistoryFilter filter })
repo.RemoveHistoryFilter(filter);
e.Handled = true;
}