Skip to content

Commit a37c6b2

Browse files
authored
In Local Changes, added filter-box in Staged area, to match Unstaged area (#1153)
Also added minimal handling (RaiseException) if trying to commit with active filter (might commit more changes than visible, so disallow). Minor unification in unstageChanges() to make it more similar to StageChanges().
1 parent ac7b025 commit a37c6b2

File tree

2 files changed

+92
-17
lines changed

2 files changed

+92
-17
lines changed

Diff for: src/ViewModels/WorkingCopy.cs

+56-14
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,28 @@ public string UnstagedFilter
109109
if (_isLoadingData)
110110
return;
111111

112-
VisibleUnstaged = GetVisibleUnstagedChanges(_unstaged);
112+
VisibleUnstaged = GetVisibleChanges(_unstaged, _unstagedFilter);
113113
SelectedUnstaged = [];
114114
}
115115
}
116116
}
117117

118+
public string StagedFilter
119+
{
120+
get => _stagedFilter;
121+
set
122+
{
123+
if (SetProperty(ref _stagedFilter, value))
124+
{
125+
if (_isLoadingData)
126+
return;
127+
128+
VisibleStaged = GetVisibleChanges(_staged, _stagedFilter);
129+
SelectedStaged = [];
130+
}
131+
}
132+
}
133+
118134
public List<Models.Change> Unstaged
119135
{
120136
get => _unstaged;
@@ -133,6 +149,12 @@ public List<Models.Change> Staged
133149
private set => SetProperty(ref _staged, value);
134150
}
135151

152+
public List<Models.Change> VisibleStaged
153+
{
154+
get => _visibleStaged;
155+
private set => SetProperty(ref _visibleStaged, value);
156+
}
157+
136158
public List<Models.Change> SelectedUnstaged
137159
{
138160
get => _selectedUnstaged;
@@ -216,6 +238,9 @@ public void Cleanup()
216238
_visibleUnstaged.Clear();
217239
OnPropertyChanged(nameof(VisibleUnstaged));
218240

241+
_visibleStaged.Clear();
242+
OnPropertyChanged(nameof(VisibleStaged));
243+
219244
_unstaged.Clear();
220245
OnPropertyChanged(nameof(Unstaged));
221246

@@ -269,7 +294,7 @@ public void SetData(List<Models.Change> changes)
269294
}
270295
}
271296

272-
var visibleUnstaged = GetVisibleUnstagedChanges(unstaged);
297+
var visibleUnstaged = GetVisibleChanges(unstaged, _unstagedFilter);
273298
var selectedUnstaged = new List<Models.Change>();
274299
foreach (var c in visibleUnstaged)
275300
{
@@ -278,8 +303,10 @@ public void SetData(List<Models.Change> changes)
278303
}
279304

280305
var staged = GetStagedChanges();
306+
307+
var visibleStaged = GetVisibleChanges(staged, _stagedFilter);
281308
var selectedStaged = new List<Models.Change>();
282-
foreach (var c in staged)
309+
foreach (var c in visibleStaged)
283310
{
284311
if (lastSelectedStaged.Contains(c.Path))
285312
selectedStaged.Add(c);
@@ -290,6 +317,7 @@ public void SetData(List<Models.Change> changes)
290317
_isLoadingData = true;
291318
HasUnsolvedConflicts = hasConflict;
292319
VisibleUnstaged = visibleUnstaged;
320+
VisibleStaged = visibleStaged;
293321
Unstaged = unstaged;
294322
Staged = staged;
295323
SelectedUnstaged = selectedUnstaged;
@@ -337,7 +365,7 @@ public void UnstageSelected(Models.Change next)
337365

338366
public void UnstageAll()
339367
{
340-
UnstageChanges(_staged, null);
368+
UnstageChanges(_visibleStaged, null);
341369
}
342370

343371
public void Discard(List<Models.Change> changes)
@@ -350,6 +378,11 @@ public void ClearUnstagedFilter()
350378
{
351379
UnstagedFilter = string.Empty;
352380
}
381+
382+
public void ClearStagedFilter()
383+
{
384+
StagedFilter = string.Empty;
385+
}
353386

354387
public async void UseTheirs(List<Models.Change> changes)
355388
{
@@ -1472,16 +1505,16 @@ public ContextMenu CreateContextForOpenAI()
14721505
return menu;
14731506
}
14741507

1475-
private List<Models.Change> GetVisibleUnstagedChanges(List<Models.Change> unstaged)
1508+
private List<Models.Change> GetVisibleChanges(List<Models.Change> changes, string filter)
14761509
{
1477-
if (string.IsNullOrEmpty(_unstagedFilter))
1478-
return unstaged;
1510+
if (string.IsNullOrEmpty(filter))
1511+
return changes;
14791512

14801513
var visible = new List<Models.Change>();
14811514

1482-
foreach (var c in unstaged)
1515+
foreach (var c in changes)
14831516
{
1484-
if (c.Path.Contains(_unstagedFilter, StringComparison.OrdinalIgnoreCase))
1517+
if (c.Path.Contains(filter, StringComparison.OrdinalIgnoreCase))
14851518
visible.Add(c);
14861519
}
14871520

@@ -1599,7 +1632,8 @@ private async void StageChanges(List<Models.Change> changes, Models.Change next)
15991632

16001633
private async void UnstageChanges(List<Models.Change> changes, Models.Change next)
16011634
{
1602-
if (changes.Count == 0)
1635+
var count = changes.Count;
1636+
if (count == 0)
16031637
return;
16041638

16051639
// Use `_selectedStaged` instead of `SelectedStaged` to avoid UI refresh.
@@ -1611,16 +1645,15 @@ private async void UnstageChanges(List<Models.Change> changes, Models.Change nex
16111645
{
16121646
await Task.Run(() => new Commands.UnstageChangesForAmend(_repo.FullPath, changes).Exec());
16131647
}
1614-
else if (changes.Count == _staged.Count)
1648+
else if (count == _staged.Count)
16151649
{
16161650
await Task.Run(() => new Commands.Reset(_repo.FullPath).Exec());
16171651
}
16181652
else
16191653
{
1620-
for (int i = 0; i < changes.Count; i += 10)
1654+
for (int i = 0; i < count; i += 10)
16211655
{
1622-
var count = Math.Min(10, changes.Count - i);
1623-
var step = changes.GetRange(i, count);
1656+
var step = changes.GetRange(i, Math.Min(10, count - i));
16241657
await Task.Run(() => new Commands.Reset(_repo.FullPath, step).Exec());
16251658
}
16261659
}
@@ -1650,6 +1683,13 @@ private void DoCommit(bool autoStage, bool autoPush, bool allowEmpty)
16501683
return;
16511684
}
16521685

1686+
if (!string.IsNullOrEmpty(_stagedFilter))
1687+
{
1688+
// FIXME - make this a proper warning message-box "Staged-area filter will not be applied to commit. Continue?" Yes/No
1689+
App.RaiseException(_repo.FullPath, "Committing with staged-area filter applied is NOT allowed!");
1690+
return;
1691+
}
1692+
16531693
if (string.IsNullOrWhiteSpace(_commitMessage))
16541694
{
16551695
App.RaiseException(_repo.FullPath, "Commit without message is NOT allowed!");
@@ -1729,11 +1769,13 @@ private bool IsChanged(List<Models.Change> old, List<Models.Change> cur)
17291769
private List<Models.Change> _unstaged = [];
17301770
private List<Models.Change> _visibleUnstaged = [];
17311771
private List<Models.Change> _staged = [];
1772+
private List<Models.Change> _visibleStaged = [];
17321773
private List<Models.Change> _selectedUnstaged = [];
17331774
private List<Models.Change> _selectedStaged = [];
17341775
private int _count = 0;
17351776
private object _detailContext = null;
17361777
private string _unstagedFilter = string.Empty;
1778+
private string _stagedFilter = string.Empty;
17371779
private string _commitMessage = string.Empty;
17381780

17391781
private bool _hasUnsolvedConflicts = false;

Diff for: src/Views/WorkingCopy.axaml

+36-3
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@
129129
Background="{DynamicResource Brush.Border0}"/>
130130

131131
<!-- Staged -->
132-
<Grid Grid.Row="2" RowDefinitions="28,*">
132+
<Grid Grid.Row="2" RowDefinitions="28,36,*">
133133
<!-- Staged Toolbar -->
134134
<Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
135135
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto">
@@ -156,14 +156,47 @@
156156
</Grid>
157157
</Border>
158158

159+
<!-- Staged Filter -->
160+
<Border Grid.Row="1" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
161+
<TextBox Height="24"
162+
Margin="4,0"
163+
BorderThickness="1"
164+
CornerRadius="12"
165+
Text="{Binding StagedFilter, Mode=TwoWay}"
166+
BorderBrush="{DynamicResource Brush.Border2}"
167+
VerticalContentAlignment="Center">
168+
<TextBox.InnerLeftContent>
169+
<Path Width="14" Height="14"
170+
Margin="6,0,0,0"
171+
Fill="{DynamicResource Brush.FG2}"
172+
Data="{StaticResource Icons.Search}"/>
173+
</TextBox.InnerLeftContent>
174+
175+
<TextBox.InnerRightContent>
176+
<Button Classes="icon_button"
177+
Width="16"
178+
Margin="0,0,6,0"
179+
Command="{Binding ClearStagedFilter}"
180+
IsVisible="{Binding StagedFilter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
181+
HorizontalAlignment="Right">
182+
<Path Width="14" Height="14"
183+
Margin="0,1,0,0"
184+
Fill="{DynamicResource Brush.FG1}"
185+
Data="{StaticResource Icons.Clear}"/>
186+
</Button>
187+
</TextBox.InnerRightContent>
188+
</TextBox>
189+
</Border>
190+
159191
<!-- Staged Changes -->
160-
<v:ChangeCollectionView Grid.Row="1"
192+
<v:ChangeCollectionView Grid.Row="2"
161193
x:Name="StagedChangesView"
162194
Focusable="True"
195+
IsUnstagedChange="False"
163196
SelectionMode="Multiple"
164197
Background="{DynamicResource Brush.Contents}"
165198
ViewMode="{Binding Source={x:Static vm:Preferences.Instance}, Path=StagedChangeViewMode}"
166-
Changes="{Binding Staged}"
199+
Changes="{Binding VisibleStaged}"
167200
SelectedChanges="{Binding SelectedStaged, Mode=TwoWay}"
168201
ContextRequested="OnStagedContextRequested"
169202
ChangeDoubleTapped="OnStagedChangeDoubleTapped"

0 commit comments

Comments
 (0)