mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-24 05:35:00 +00:00
code_review: PR #1153
- use a single filter for both unstage and staged files - show confirm dialog if staged files are displayed partially Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
parent
a37c6b29ec
commit
fa02c65da5
9 changed files with 103 additions and 143 deletions
|
@ -719,6 +719,7 @@
|
|||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">Trigger click event</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitToEdit" xml:space="preserve">Commit (Edit)</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Stage all changes and commit</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithFilter">You have staged {0} file(s) but only {1} file(s) displayed ({2} files are filtered out). Do you want to continue?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithoutFiles" xml:space="preserve">Empty commit detected! Do you want to continue (--allow-empty)?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLICTS DETECTED</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">FILE CONFLICTS ARE RESOLVED</x:String>
|
||||
|
|
|
@ -723,6 +723,7 @@
|
|||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">触发点击事件</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitToEdit" xml:space="preserve">提交(修改原始提交)</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">自动暂存所有变更并提交</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithFilter">当前有 {0} 个文件在暂存区中,但仅显示了 {1} 个文件({2} 个文件被过滤掉了),是否继续提交?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithoutFiles" xml:space="preserve">提交未包含变更文件!是否继续(--allow-empty)?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">检测到冲突</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">文件冲突已解决</x:String>
|
||||
|
|
|
@ -722,6 +722,7 @@
|
|||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">觸發點擊事件</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitToEdit" xml:space="preserve">提交 (修改原始提交)</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">自動暫存全部變更並提交</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithFilter">您已暫存 {0} 檔案,但只顯示 {1} 檔案 ({2} 檔案被篩選器隱藏)。您要繼續嗎?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithoutFiles" xml:space="preserve">未包含任何檔案變更! 您是否仍要提交 (--allow-empty)?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">檢測到衝突</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">檔案衝突已解決</x:String>
|
||||
|
|
26
src/ViewModels/ConfirmCommit.cs
Normal file
26
src/ViewModels/ConfirmCommit.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class ConfirmCommit
|
||||
{
|
||||
public string Message
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public ConfirmCommit(string message, Action onSure)
|
||||
{
|
||||
Message = message;
|
||||
_onSure = onSure;
|
||||
}
|
||||
|
||||
public void Continue()
|
||||
{
|
||||
_onSure?.Invoke();
|
||||
}
|
||||
|
||||
private Action _onSure;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class ConfirmCommitWithoutFiles
|
||||
{
|
||||
public ConfirmCommitWithoutFiles(WorkingCopy wc, bool autoPush)
|
||||
{
|
||||
_wc = wc;
|
||||
_autoPush = autoPush;
|
||||
}
|
||||
|
||||
public void Continue()
|
||||
{
|
||||
_wc.CommitWithoutFiles(_autoPush);
|
||||
}
|
||||
|
||||
private readonly WorkingCopy _wc;
|
||||
private bool _autoPush;
|
||||
}
|
||||
}
|
|
@ -99,38 +99,23 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public string UnstagedFilter
|
||||
public string Filter
|
||||
{
|
||||
get => _unstagedFilter;
|
||||
get => _filter;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _unstagedFilter, value))
|
||||
if (SetProperty(ref _filter, value))
|
||||
{
|
||||
if (_isLoadingData)
|
||||
return;
|
||||
|
||||
VisibleUnstaged = GetVisibleChanges(_unstaged, _unstagedFilter);
|
||||
VisibleUnstaged = GetVisibleChanges(_unstaged);
|
||||
VisibleStaged = GetVisibleChanges(_staged);
|
||||
SelectedUnstaged = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string StagedFilter
|
||||
{
|
||||
get => _stagedFilter;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _stagedFilter, value))
|
||||
{
|
||||
if (_isLoadingData)
|
||||
return;
|
||||
|
||||
VisibleStaged = GetVisibleChanges(_staged, _stagedFilter);
|
||||
SelectedStaged = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Models.Change> Unstaged
|
||||
{
|
||||
get => _unstaged;
|
||||
|
@ -294,7 +279,7 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
var visibleUnstaged = GetVisibleChanges(unstaged, _unstagedFilter);
|
||||
var visibleUnstaged = GetVisibleChanges(unstaged);
|
||||
var selectedUnstaged = new List<Models.Change>();
|
||||
foreach (var c in visibleUnstaged)
|
||||
{
|
||||
|
@ -304,7 +289,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
var staged = GetStagedChanges();
|
||||
|
||||
var visibleStaged = GetVisibleChanges(staged, _stagedFilter);
|
||||
var visibleStaged = GetVisibleChanges(staged);
|
||||
var selectedStaged = new List<Models.Change>();
|
||||
foreach (var c in visibleStaged)
|
||||
{
|
||||
|
@ -374,14 +359,9 @@ namespace SourceGit.ViewModels
|
|||
_repo.ShowPopup(new Discard(_repo, changes));
|
||||
}
|
||||
|
||||
public void ClearUnstagedFilter()
|
||||
public void ClearFilter()
|
||||
{
|
||||
UnstagedFilter = string.Empty;
|
||||
}
|
||||
|
||||
public void ClearStagedFilter()
|
||||
{
|
||||
StagedFilter = string.Empty;
|
||||
Filter = string.Empty;
|
||||
}
|
||||
|
||||
public async void UseTheirs(List<Models.Change> changes)
|
||||
|
@ -571,11 +551,6 @@ namespace SourceGit.ViewModels
|
|||
DoCommit(false, true, false);
|
||||
}
|
||||
|
||||
public void CommitWithoutFiles(bool autoPush)
|
||||
{
|
||||
DoCommit(false, autoPush, true);
|
||||
}
|
||||
|
||||
public ContextMenu CreateContextMenuForUnstagedChanges()
|
||||
{
|
||||
if (_selectedUnstaged == null || _selectedUnstaged.Count == 0)
|
||||
|
@ -1505,16 +1480,16 @@ namespace SourceGit.ViewModels
|
|||
return menu;
|
||||
}
|
||||
|
||||
private List<Models.Change> GetVisibleChanges(List<Models.Change> changes, string filter)
|
||||
private List<Models.Change> GetVisibleChanges(List<Models.Change> changes)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filter))
|
||||
if (string.IsNullOrEmpty(_filter))
|
||||
return changes;
|
||||
|
||||
var visible = new List<Models.Change>();
|
||||
|
||||
foreach (var c in changes)
|
||||
{
|
||||
if (c.Path.Contains(filter, StringComparison.OrdinalIgnoreCase))
|
||||
if (c.Path.Contains(_filter, StringComparison.OrdinalIgnoreCase))
|
||||
visible.Add(c);
|
||||
}
|
||||
|
||||
|
@ -1675,7 +1650,7 @@ namespace SourceGit.ViewModels
|
|||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext);
|
||||
}
|
||||
|
||||
private void DoCommit(bool autoStage, bool autoPush, bool allowEmpty)
|
||||
private void DoCommit(bool autoStage, bool autoPush, bool allowEmpty = false, bool confirmWithFilter = false)
|
||||
{
|
||||
if (!_repo.CanCreatePopup())
|
||||
{
|
||||
|
@ -1683,10 +1658,17 @@ namespace SourceGit.ViewModels
|
|||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_stagedFilter))
|
||||
if (!string.IsNullOrEmpty(_filter) && _staged.Count > _visibleStaged.Count && !confirmWithFilter)
|
||||
{
|
||||
// FIXME - make this a proper warning message-box "Staged-area filter will not be applied to commit. Continue?" Yes/No
|
||||
App.RaiseException(_repo.FullPath, "Committing with staged-area filter applied is NOT allowed!");
|
||||
var confirmMessage = App.Text("WorkingCopy.ConfirmCommitWithFilter", _staged.Count, _visibleStaged.Count, _staged.Count - _visibleStaged.Count);
|
||||
App.OpenDialog(new Views.ConfirmCommit()
|
||||
{
|
||||
DataContext = new ConfirmCommit(confirmMessage, () =>
|
||||
{
|
||||
DoCommit(autoStage, autoPush, allowEmpty, true);
|
||||
})
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1700,9 +1682,13 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
if ((autoStage && _count == 0) || (!autoStage && _staged.Count == 0))
|
||||
{
|
||||
App.OpenDialog(new Views.ConfirmCommitWithoutFiles()
|
||||
var confirmMessage = App.Text("WorkingCopy.ConfirmCommitWithoutFiles");
|
||||
App.OpenDialog(new Views.ConfirmCommit()
|
||||
{
|
||||
DataContext = new ConfirmCommitWithoutFiles(this, autoPush)
|
||||
DataContext = new ConfirmCommit(confirmMessage, () =>
|
||||
{
|
||||
DoCommit(autoStage, autoPush, true, confirmWithFilter);
|
||||
})
|
||||
});
|
||||
|
||||
return;
|
||||
|
@ -1774,8 +1760,7 @@ namespace SourceGit.ViewModels
|
|||
private List<Models.Change> _selectedStaged = [];
|
||||
private int _count = 0;
|
||||
private object _detailContext = null;
|
||||
private string _unstagedFilter = string.Empty;
|
||||
private string _stagedFilter = string.Empty;
|
||||
private string _filter = string.Empty;
|
||||
private string _commitMessage = string.Empty;
|
||||
|
||||
private bool _hasUnsolvedConflicts = false;
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.ConfirmCommitWithoutFiles"
|
||||
x:DataType="vm:ConfirmCommitWithoutFiles"
|
||||
x:Class="SourceGit.Views.ConfirmCommit"
|
||||
x:DataType="vm:ConfirmCommit"
|
||||
x:Name="ThisControl"
|
||||
Icon="/App.ico"
|
||||
Title="{DynamicResource Text.Warn}"
|
||||
|
@ -38,7 +38,7 @@
|
|||
|
||||
<!-- Body -->
|
||||
<Border Grid.Row="1" Margin="16">
|
||||
<TextBlock Text="{DynamicResource Text.WorkingCopy.ConfirmCommitWithoutFiles}"/>
|
||||
<TextBlock Text="{Binding Message}" MaxWidth="400" TextWrapping="Wrap"/>
|
||||
</Border>
|
||||
|
||||
<!-- Buttons -->
|
|
@ -2,20 +2,16 @@ using Avalonia.Interactivity;
|
|||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class ConfirmCommitWithoutFiles : ChromelessWindow
|
||||
public partial class ConfirmCommit : ChromelessWindow
|
||||
{
|
||||
public ConfirmCommitWithoutFiles()
|
||||
public ConfirmCommit()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Sure(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
if (DataContext is ViewModels.ConfirmCommitWithoutFiles vm)
|
||||
{
|
||||
vm.Continue();
|
||||
}
|
||||
|
||||
(DataContext as ViewModels.ConfirmCommit)?.Continue();
|
||||
Close();
|
||||
}
|
||||
|
|
@ -19,13 +19,46 @@
|
|||
<!-- Left -->
|
||||
<Grid Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="36"/>
|
||||
<RowDefinition Height="*" MinHeight="100"/>
|
||||
<RowDefinition Height="1"/>
|
||||
<RowDefinition Height="*" MinHeight="100"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Search Filter -->
|
||||
<Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
|
||||
<TextBox Height="24"
|
||||
Margin="4,0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="12"
|
||||
Text="{Binding Filter, Mode=TwoWay}"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
VerticalContentAlignment="Center">
|
||||
<TextBox.InnerLeftContent>
|
||||
<Path Width="14" Height="14"
|
||||
Margin="6,0,0,0"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
Data="{StaticResource Icons.Search}"/>
|
||||
</TextBox.InnerLeftContent>
|
||||
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button"
|
||||
Width="16"
|
||||
Margin="0,0,6,0"
|
||||
Command="{Binding ClearFilter}"
|
||||
IsVisible="{Binding Filter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||
HorizontalAlignment="Right">
|
||||
<Path Width="14" Height="14"
|
||||
Margin="0,1,0,0"
|
||||
Fill="{DynamicResource Brush.FG1}"
|
||||
Data="{StaticResource Icons.Clear}"/>
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
</Border>
|
||||
|
||||
<!-- Unstaged -->
|
||||
<Grid Grid.Row="0" RowDefinitions="28,36,*">
|
||||
<Grid Grid.Row="1" RowDefinitions="28,*">
|
||||
<!-- Unstaged Toolbar -->
|
||||
<Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
|
||||
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto,Auto,Auto">
|
||||
|
@ -75,40 +108,8 @@
|
|||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Unstaged Filter -->
|
||||
<Border Grid.Row="1" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
|
||||
<TextBox Height="24"
|
||||
Margin="4,0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="12"
|
||||
Text="{Binding UnstagedFilter, Mode=TwoWay}"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
VerticalContentAlignment="Center">
|
||||
<TextBox.InnerLeftContent>
|
||||
<Path Width="14" Height="14"
|
||||
Margin="6,0,0,0"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
Data="{StaticResource Icons.Search}"/>
|
||||
</TextBox.InnerLeftContent>
|
||||
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button"
|
||||
Width="16"
|
||||
Margin="0,0,6,0"
|
||||
Command="{Binding ClearUnstagedFilter}"
|
||||
IsVisible="{Binding UnstagedFilter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||
HorizontalAlignment="Right">
|
||||
<Path Width="14" Height="14"
|
||||
Margin="0,1,0,0"
|
||||
Fill="{DynamicResource Brush.FG1}"
|
||||
Data="{StaticResource Icons.Clear}"/>
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
</Border>
|
||||
|
||||
<!-- Unstaged Changes -->
|
||||
<v:ChangeCollectionView Grid.Row="2"
|
||||
<v:ChangeCollectionView Grid.Row="1"
|
||||
x:Name="UnstagedChangesView"
|
||||
Focusable="True"
|
||||
IsUnstagedChange="True"
|
||||
|
@ -123,13 +124,13 @@
|
|||
</Grid>
|
||||
|
||||
<!-- Splitter -->
|
||||
<GridSplitter Grid.Row="1"
|
||||
<GridSplitter Grid.Row="2"
|
||||
MinHeight="1"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Background="{DynamicResource Brush.Border0}"/>
|
||||
|
||||
<!-- Staged -->
|
||||
<Grid Grid.Row="2" RowDefinitions="28,36,*">
|
||||
<Grid Grid.Row="3" RowDefinitions="28,*">
|
||||
<!-- Staged Toolbar -->
|
||||
<Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
|
||||
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto">
|
||||
|
@ -155,41 +156,9 @@
|
|||
ViewMode="{Binding Source={x:Static vm:Preferences.Instance}, Path=StagedChangeViewMode, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Staged Filter -->
|
||||
<Border Grid.Row="1" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
|
||||
<TextBox Height="24"
|
||||
Margin="4,0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="12"
|
||||
Text="{Binding StagedFilter, Mode=TwoWay}"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
VerticalContentAlignment="Center">
|
||||
<TextBox.InnerLeftContent>
|
||||
<Path Width="14" Height="14"
|
||||
Margin="6,0,0,0"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
Data="{StaticResource Icons.Search}"/>
|
||||
</TextBox.InnerLeftContent>
|
||||
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button"
|
||||
Width="16"
|
||||
Margin="0,0,6,0"
|
||||
Command="{Binding ClearStagedFilter}"
|
||||
IsVisible="{Binding StagedFilter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||
HorizontalAlignment="Right">
|
||||
<Path Width="14" Height="14"
|
||||
Margin="0,1,0,0"
|
||||
Fill="{DynamicResource Brush.FG1}"
|
||||
Data="{StaticResource Icons.Clear}"/>
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
</Border>
|
||||
|
||||
<!-- Staged Changes -->
|
||||
<v:ChangeCollectionView Grid.Row="2"
|
||||
<v:ChangeCollectionView Grid.Row="1"
|
||||
x:Name="StagedChangesView"
|
||||
Focusable="True"
|
||||
IsUnstagedChange="False"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue