Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/Converters/FilterModeConverters.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Avalonia.Data.Converters;
using System.Collections.Generic;

using Avalonia.Data.Converters;
using Avalonia.Media;

namespace SourceGit.Converters
Expand All @@ -15,5 +17,23 @@ public static class FilterModeConverters
_ => Brushes.Transparent,
};
});

public static readonly IMultiValueConverter ToBorderBrushWithMatchState =
new FuncMultiValueConverter<object, IBrush>(values =>
{
var list = new List<object>(values);
if (list.Count < 2 || list[0] is not Models.FilterMode mode)
return Brushes.Transparent;

if (list[1] is true)
return Brushes.Gray;

return mode switch
{
Models.FilterMode.Included => Brushes.Green,
Models.FilterMode.Excluded => Brushes.Red,
_ => Brushes.Transparent,
};
});
}
}
12 changes: 11 additions & 1 deletion src/Models/HistoryFilter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.Text.Json.Serialization;

using CommunityToolkit.Mvvm.ComponentModel;

namespace SourceGit.Models
{
Expand Down Expand Up @@ -43,6 +45,13 @@ public bool IsBranch
get => Type != FilterType.Tag;
}

[JsonIgnore]
public bool HasNoMatch
{
get => _hasNoMatch;
set => SetProperty(ref _hasNoMatch, value);
}

public HistoryFilter()
{
}
Expand All @@ -56,5 +65,6 @@ public HistoryFilter(string pattern, FilterType type, FilterMode mode)

private string _pattern = string.Empty;
private FilterMode _mode = FilterMode.None;
private bool _hasNoMatch = false;
}
}
78 changes: 78 additions & 0 deletions src/ViewModels/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,7 @@ public void RefreshBranches()
CurrentBranch = branches.Find(x => x.IsCurrent);
LocalBranchTrees = builder.Locals;
RemoteBranchTrees = builder.Remotes;
UpdateBranchHistoryFilterMatchState();

var localBranchesCount = 0;
foreach (var b in branches)
Expand Down Expand Up @@ -1214,6 +1215,7 @@ public void RefreshTags()

Tags = tags;
VisibleTags = BuildVisibleTags();
UpdateTagHistoryFilterMatchState();
});
}, token);
}
Expand Down Expand Up @@ -1788,6 +1790,10 @@ private void RefreshHistoryFilters(bool refresh)
UpdateBranchTreeFilterMode(LocalBranchTrees, map);
UpdateBranchTreeFilterMode(RemoteBranchTrees, map);
UpdateTagFilterMode(map);

UpdateBranchHistoryFilterMatchState();
UpdateTagHistoryFilterMatchState();

RefreshCommits();
}

Expand Down Expand Up @@ -1816,6 +1822,78 @@ private void UpdateTagFilterMode(Dictionary<string, Models.FilterMode> map)
}
}

private void UpdateBranchHistoryFilterMatchState()
{
var branchPaths = new HashSet<string>(StringComparer.Ordinal);
CollectBranchPaths(LocalBranchTrees, branchPaths);
CollectBranchPaths(RemoteBranchTrees, branchPaths);

foreach (var filter in _uiStates.HistoryFilters)
{
switch (filter.Type)
{
case Models.FilterType.LocalBranch:
case Models.FilterType.RemoteBranch:
filter.HasNoMatch = !branchPaths.Contains(filter.Pattern);
break;
case Models.FilterType.LocalBranchFolder:
case Models.FilterType.RemoteBranchFolder:
var prefix = filter.Pattern + "/";
var hasChild = false;
foreach (var p in branchPaths)
{
if (p.StartsWith(prefix, StringComparison.Ordinal))
{
hasChild = true;
break;
}
}
filter.HasNoMatch = !hasChild;
break;
}
}
}

private void UpdateTagHistoryFilterMatchState()
{
var tagNames = new HashSet<string>(StringComparer.Ordinal);
if (VisibleTags is TagCollectionAsTree tree)
CollectTagNamesRecursive(tree.Tree, tagNames);
else if (VisibleTags is TagCollectionAsList list)
{
foreach (var item in list.TagItems)
tagNames.Add(item.Tag.Name);
}

foreach (var filter in _uiStates.HistoryFilters)
{
if (filter.Type == Models.FilterType.Tag)
filter.HasNoMatch = !tagNames.Contains(filter.Pattern);
}
}

private void CollectBranchPaths(List<BranchTreeNode> nodes, HashSet<string> set)
{
foreach (var node in nodes)
{
if (node.IsBranch)
set.Add(node.Path);
else
CollectBranchPaths(node.Children, set);
}
}

private static void CollectTagNamesRecursive(List<TagTreeNode> nodes, HashSet<string> set)
{
foreach (var node in nodes)
{
if (node.IsFolder)
CollectTagNamesRecursive(node.Children, set);
else
set.Add(node.FullPath);
}
}

private void ResetBranchTreeFilterMode(List<BranchTreeNode> nodes)
{
foreach (var node in nodes)
Expand Down
7 changes: 6 additions & 1 deletion src/Views/Repository.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -952,8 +952,13 @@
Margin="0,0,6,0"
CornerRadius="12"
BorderThickness="1"
BorderBrush="{Binding Mode, Converter={x:Static c:FilterModeConverters.ToBorderBrush}}"
VerticalAlignment="Center">
<Border.BorderBrush>
<MultiBinding Converter="{x:Static c:FilterModeConverters.ToBorderBrushWithMatchState}">
<Binding Path="Mode"/>
<Binding Path="HasNoMatch"/>
</MultiBinding>
</Border.BorderBrush>
<Grid Margin="8,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
Expand Down