mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-23 21:24:59 +00:00
refactor: use TreeDataGrid instead of TreeView/DataGrid to improve performance (#148)
This commit is contained in:
parent
3160f1d142
commit
b192a1c423
24 changed files with 1333 additions and 1330 deletions
|
@ -4,6 +4,8 @@ using System.IO;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Models.TreeDataGrid;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
|
@ -48,48 +50,17 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _visibleChanges, value);
|
||||
}
|
||||
|
||||
public List<FileTreeNode> ChangeTree
|
||||
public List<Models.Change> SelectedChanges
|
||||
{
|
||||
get => _changeTree;
|
||||
set => SetProperty(ref _changeTree, value);
|
||||
}
|
||||
|
||||
public Models.Change SelectedChange
|
||||
{
|
||||
get => _selectedChange;
|
||||
get => _selectedChanges;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedChange, value))
|
||||
if (SetProperty(ref _selectedChanges, value))
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
SelectedChangeNode = null;
|
||||
if (value == null || value.Count != 1)
|
||||
DiffContext = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedChangeNode = FileTreeNode.SelectByPath(_changeTree, value.Path);
|
||||
DiffContext = new DiffContext(_repo, new Models.DiffOption(_commit, value), _diffContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FileTreeNode SelectedChangeNode
|
||||
{
|
||||
get => _selectedChangeNode;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedChangeNode, value))
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
SelectedChange = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedChange = value.Backend as Models.Change;
|
||||
}
|
||||
DiffContext = new DiffContext(_repo, new Models.DiffOption(_commit, value[0]), _diffContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,26 +77,10 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public List<FileTreeNode> RevisionFilesTree
|
||||
public HierarchicalTreeDataGridSource<FileTreeNode> RevisionFiles
|
||||
{
|
||||
get => _revisionFilesTree;
|
||||
set => SetProperty(ref _revisionFilesTree, value);
|
||||
}
|
||||
|
||||
public FileTreeNode SelectedRevisionFileNode
|
||||
{
|
||||
get => _selectedRevisionFileNode;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedRevisionFileNode, value) && value != null && !value.IsFolder)
|
||||
{
|
||||
RefreshViewRevisionFile(value.Backend as Models.Object);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewRevisionFileContent = null;
|
||||
}
|
||||
}
|
||||
get => _revisionFiles;
|
||||
private set => SetProperty(ref _revisionFiles, value);
|
||||
}
|
||||
|
||||
public string SearchFileFilter
|
||||
|
@ -159,17 +114,14 @@ namespace SourceGit.ViewModels
|
|||
_changes.Clear();
|
||||
if (_visibleChanges != null)
|
||||
_visibleChanges.Clear();
|
||||
if (_changeTree != null)
|
||||
_changeTree.Clear();
|
||||
_selectedChange = null;
|
||||
_selectedChangeNode = null;
|
||||
if (_selectedChanges != null)
|
||||
_selectedChanges.Clear();
|
||||
_searchChangeFilter = null;
|
||||
_diffContext = null;
|
||||
if (_revisionFilesBackup != null)
|
||||
_revisionFilesBackup.Clear();
|
||||
if (_revisionFiles != null)
|
||||
_revisionFiles.Clear();
|
||||
if (_revisionFilesTree != null)
|
||||
_revisionFilesTree.Clear();
|
||||
_selectedRevisionFileNode = null;
|
||||
_revisionFiles.Dispose();
|
||||
_searchFileFilter = null;
|
||||
_viewRevisionFileContent = null;
|
||||
_cancelToken = null;
|
||||
|
@ -346,9 +298,14 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
_changes = null;
|
||||
VisibleChanges = null;
|
||||
SelectedChange = null;
|
||||
RevisionFilesTree = null;
|
||||
SelectedRevisionFileNode = null;
|
||||
SelectedChanges = null;
|
||||
|
||||
if (_revisionFiles != null)
|
||||
{
|
||||
_revisionFiles.Dispose();
|
||||
_revisionFiles = null;
|
||||
}
|
||||
|
||||
if (_commit == null)
|
||||
return;
|
||||
if (_cancelToken != null)
|
||||
|
@ -379,40 +336,34 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
var tree = FileTreeNode.Build(visible);
|
||||
var tree = FileTreeNode.Build(visible, true);
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
Changes = changes;
|
||||
VisibleChanges = visible;
|
||||
ChangeTree = tree;
|
||||
});
|
||||
});
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var files = cmdRevisionFiles.Result();
|
||||
_revisionFilesBackup = cmdRevisionFiles.Result();
|
||||
if (cmdRevisionFiles.Cancel.Requested)
|
||||
return;
|
||||
|
||||
var visible = files;
|
||||
if (!string.IsNullOrWhiteSpace(_searchFileFilter))
|
||||
var visible = _revisionFilesBackup;
|
||||
var isSearching = !string.IsNullOrWhiteSpace(_searchFileFilter);
|
||||
if (isSearching)
|
||||
{
|
||||
visible = new List<Models.Object>();
|
||||
foreach (var f in files)
|
||||
foreach (var f in _revisionFilesBackup)
|
||||
{
|
||||
if (f.Path.Contains(_searchFileFilter, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
visible.Add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var tree = FileTreeNode.Build(visible);
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
_revisionFiles = files;
|
||||
RevisionFilesTree = tree;
|
||||
});
|
||||
var tree = FileTreeNode.Build(visible, isSearching || visible.Count <= 100);
|
||||
Dispatcher.UIThread.Invoke(() => BuildRevisionFilesSource(tree));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -431,15 +382,11 @@ namespace SourceGit.ViewModels
|
|||
foreach (var c in _changes)
|
||||
{
|
||||
if (c.Path.Contains(_searchChangeFilter, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
visible.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
VisibleChanges = visible;
|
||||
}
|
||||
|
||||
ChangeTree = FileTreeNode.Build(_visibleChanges);
|
||||
}
|
||||
|
||||
private void RefreshVisibleFiles()
|
||||
|
@ -447,24 +394,29 @@ namespace SourceGit.ViewModels
|
|||
if (_revisionFiles == null)
|
||||
return;
|
||||
|
||||
var visible = _revisionFiles;
|
||||
if (!string.IsNullOrWhiteSpace(_searchFileFilter))
|
||||
var visible = _revisionFilesBackup;
|
||||
var isSearching = !string.IsNullOrWhiteSpace(_searchFileFilter);
|
||||
if (isSearching)
|
||||
{
|
||||
visible = new List<Models.Object>();
|
||||
foreach (var f in _revisionFiles)
|
||||
foreach (var f in _revisionFilesBackup)
|
||||
{
|
||||
if (f.Path.Contains(_searchFileFilter, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
visible.Add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RevisionFilesTree = FileTreeNode.Build(visible);
|
||||
BuildRevisionFilesSource(FileTreeNode.Build(visible, isSearching || visible.Count < 100));
|
||||
}
|
||||
|
||||
private void RefreshViewRevisionFile(Models.Object file)
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
ViewRevisionFileContent = null;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (file.Type)
|
||||
{
|
||||
case Models.ObjectType.Blob:
|
||||
|
@ -541,6 +493,35 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
private void BuildRevisionFilesSource(List<FileTreeNode> tree)
|
||||
{
|
||||
var source = new HierarchicalTreeDataGridSource<FileTreeNode>(tree)
|
||||
{
|
||||
Columns =
|
||||
{
|
||||
new HierarchicalExpanderColumn<FileTreeNode>(
|
||||
new TemplateColumn<FileTreeNode>("Icon", "FileTreeNodeExpanderTemplate", null, GridLength.Auto),
|
||||
x => x.Children,
|
||||
x => x.Children.Count > 0,
|
||||
x => x.IsExpanded),
|
||||
new TextColumn<FileTreeNode, string>(
|
||||
null,
|
||||
x => string.Empty,
|
||||
GridLength.Star)
|
||||
}
|
||||
};
|
||||
|
||||
source.Selection = new Models.TreeDataGridSelectionModel<FileTreeNode>(source, x => x.Children);
|
||||
source.RowSelection.SingleSelect = true;
|
||||
source.RowSelection.SelectionChanged += (s, _) =>
|
||||
{
|
||||
if (s is Models.TreeDataGridSelectionModel<FileTreeNode> selection)
|
||||
RefreshViewRevisionFile(selection.SelectedItem?.Backend as Models.Object);
|
||||
};
|
||||
|
||||
RevisionFiles = source;
|
||||
}
|
||||
|
||||
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
|
||||
{
|
||||
".ico", ".bmp", ".jpg", ".png", ".jpeg"
|
||||
|
@ -551,14 +532,11 @@ namespace SourceGit.ViewModels
|
|||
private Models.Commit _commit = null;
|
||||
private List<Models.Change> _changes = null;
|
||||
private List<Models.Change> _visibleChanges = null;
|
||||
private List<FileTreeNode> _changeTree = null;
|
||||
private Models.Change _selectedChange = null;
|
||||
private FileTreeNode _selectedChangeNode = null;
|
||||
private List<Models.Change> _selectedChanges = null;
|
||||
private string _searchChangeFilter = string.Empty;
|
||||
private DiffContext _diffContext = null;
|
||||
private List<Models.Object> _revisionFiles = null;
|
||||
private List<FileTreeNode> _revisionFilesTree = null;
|
||||
private FileTreeNode _selectedRevisionFileNode = null;
|
||||
private List<Models.Object> _revisionFilesBackup = null;
|
||||
private HierarchicalTreeDataGridSource<FileTreeNode> _revisionFiles = null;
|
||||
private string _searchFileFilter = string.Empty;
|
||||
private object _viewRevisionFileContent = null;
|
||||
private Commands.Command.CancelToken _cancelToken = null;
|
||||
|
|
|
@ -85,6 +85,11 @@ namespace SourceGit.ViewModels
|
|||
_content = previous._content;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
|
||||
_title = _option.Path;
|
||||
else
|
||||
_title = $"{_option.OrgPath} → {_option.Path}";
|
||||
|
||||
LoadDiffContent();
|
||||
}
|
||||
|
||||
|
@ -175,11 +180,6 @@ namespace SourceGit.ViewModels
|
|||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
|
||||
Title = _option.Path;
|
||||
else
|
||||
Title = $"{_option.OrgPath} → {_option.Path}";
|
||||
|
||||
FileModeChange = latest.FileModeChange;
|
||||
Content = rs;
|
||||
IsTextDiff = latest.TextDiff != null;
|
||||
|
|
|
@ -18,11 +18,10 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _isExpanded, value);
|
||||
}
|
||||
|
||||
public static List<FileTreeNode> Build(List<Models.Change> changes)
|
||||
public static List<FileTreeNode> Build(List<Models.Change> changes, bool expanded)
|
||||
{
|
||||
var nodes = new List<FileTreeNode>();
|
||||
var folders = new Dictionary<string, FileTreeNode>();
|
||||
var expanded = changes.Count <= 50;
|
||||
|
||||
foreach (var c in changes)
|
||||
{
|
||||
|
@ -94,11 +93,10 @@ namespace SourceGit.ViewModels
|
|||
return nodes;
|
||||
}
|
||||
|
||||
public static List<FileTreeNode> Build(List<Models.Object> files)
|
||||
public static List<FileTreeNode> Build(List<Models.Object> files, bool expanded)
|
||||
{
|
||||
var nodes = new List<FileTreeNode>();
|
||||
var folders = new Dictionary<string, FileTreeNode>();
|
||||
var expanded = files.Count <= 50;
|
||||
|
||||
foreach (var f in files)
|
||||
{
|
||||
|
|
|
@ -35,48 +35,17 @@ namespace SourceGit.ViewModels
|
|||
private set => SetProperty(ref _visibleChanges, value);
|
||||
}
|
||||
|
||||
public List<FileTreeNode> ChangeTree
|
||||
public List<Models.Change> SelectedChanges
|
||||
{
|
||||
get => _changeTree;
|
||||
private set => SetProperty(ref _changeTree, value);
|
||||
}
|
||||
|
||||
public Models.Change SelectedChange
|
||||
{
|
||||
get => _selectedChange;
|
||||
get => _selectedChanges;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedChange, value))
|
||||
if (SetProperty(ref _selectedChanges, value))
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
SelectedNode = null;
|
||||
if (value != null && value.Count == 1)
|
||||
DiffContext = new DiffContext(_repo, new Models.DiffOption(StartPoint.SHA, _endPoint, value[0]), _diffContext);
|
||||
else
|
||||
DiffContext = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedNode = FileTreeNode.SelectByPath(_changeTree, value.Path);
|
||||
DiffContext = new DiffContext(_repo, new Models.DiffOption(StartPoint.SHA, _endPoint, value), _diffContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FileTreeNode SelectedNode
|
||||
{
|
||||
get => _selectedNode;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedNode, value))
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
SelectedChange = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedChange = value.Backend as Models.Change;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,17 +95,14 @@ namespace SourceGit.ViewModels
|
|||
foreach (var c in _changes)
|
||||
{
|
||||
if (c.Path.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
visible.Add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var tree = FileTreeNode.Build(visible);
|
||||
var tree = FileTreeNode.Build(visible, true);
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
VisibleChanges = visible;
|
||||
ChangeTree = tree;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -148,10 +114,8 @@ namespace SourceGit.ViewModels
|
|||
_changes.Clear();
|
||||
if (_visibleChanges != null)
|
||||
_visibleChanges.Clear();
|
||||
if (_changeTree != null)
|
||||
_changeTree.Clear();
|
||||
_selectedChange = null;
|
||||
_selectedNode = null;
|
||||
if (_selectedChanges != null)
|
||||
_selectedChanges.Clear();
|
||||
_searchFilter = null;
|
||||
_diffContext = null;
|
||||
}
|
||||
|
@ -168,8 +132,12 @@ namespace SourceGit.ViewModels
|
|||
SearchFilter = string.Empty;
|
||||
}
|
||||
|
||||
public ContextMenu CreateChangeContextMenu(Models.Change change)
|
||||
public ContextMenu CreateChangeContextMenu()
|
||||
{
|
||||
if (_selectedChanges == null || _selectedChanges.Count != 1)
|
||||
return null;
|
||||
|
||||
var change = _selectedChanges[0];
|
||||
var menu = new ContextMenu();
|
||||
|
||||
var diffWithMerger = new MenuItem();
|
||||
|
@ -237,24 +205,18 @@ namespace SourceGit.ViewModels
|
|||
foreach (var c in _changes)
|
||||
{
|
||||
if (c.Path.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
visible.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
VisibleChanges = visible;
|
||||
}
|
||||
|
||||
ChangeTree = FileTreeNode.Build(_visibleChanges);
|
||||
}
|
||||
|
||||
private string _repo = string.Empty;
|
||||
private string _endPoint = string.Empty;
|
||||
private List<Models.Change> _changes = null;
|
||||
private List<Models.Change> _visibleChanges = null;
|
||||
private List<FileTreeNode> _changeTree = null;
|
||||
private Models.Change _selectedChange = null;
|
||||
private FileTreeNode _selectedNode = null;
|
||||
private List<Models.Change> _selectedChanges = null;
|
||||
private string _searchFilter = string.Empty;
|
||||
private DiffContext _diffContext = null;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,23 @@ namespace SourceGit.ViewModels
|
|||
public bool UseAmend
|
||||
{
|
||||
get => _useAmend;
|
||||
set => SetProperty(ref _useAmend, value);
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _useAmend, value) && value)
|
||||
{
|
||||
var commits = new Commands.QueryCommits(_repo.FullPath, "-n 1", false).Result();
|
||||
if (commits.Count == 0)
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "No commits to amend!!!");
|
||||
_useAmend = false;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
CommitMessage = commits[0].FullMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Models.Change> Unstaged
|
||||
|
@ -73,103 +89,58 @@ namespace SourceGit.ViewModels
|
|||
private set => SetProperty(ref _staged, value);
|
||||
}
|
||||
|
||||
public int Count
|
||||
public List<Models.Change> SelectedUnstaged
|
||||
{
|
||||
get => _count;
|
||||
}
|
||||
|
||||
public Models.Change SelectedUnstagedChange
|
||||
{
|
||||
get => _selectedUnstagedChange;
|
||||
get => _selectedUnstaged;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedUnstagedChange, value) && value != null)
|
||||
if (SetProperty(ref _selectedUnstaged, value))
|
||||
{
|
||||
SelectedStagedChange = null;
|
||||
SelectedStagedTreeNode = null;
|
||||
SetDetail(value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Models.Change SelectedStagedChange
|
||||
{
|
||||
get => _selectedStagedChange;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedStagedChange, value) && value != null)
|
||||
{
|
||||
SelectedUnstagedChange = null;
|
||||
SelectedUnstagedTreeNode = null;
|
||||
SetDetail(value, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<FileTreeNode> UnstagedTree
|
||||
{
|
||||
get => _unstagedTree;
|
||||
private set => SetProperty(ref _unstagedTree, value);
|
||||
}
|
||||
|
||||
public List<FileTreeNode> StagedTree
|
||||
{
|
||||
get => _stagedTree;
|
||||
private set => SetProperty(ref _stagedTree, value);
|
||||
}
|
||||
|
||||
public FileTreeNode SelectedUnstagedTreeNode
|
||||
{
|
||||
get => _selectedUnstagedTreeNode;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedUnstagedTreeNode, value))
|
||||
{
|
||||
if (value == null)
|
||||
if (value == null || value.Count == 0)
|
||||
{
|
||||
SelectedUnstagedChange = null;
|
||||
if (_selectedStaged == null || _selectedStaged.Count == 0)
|
||||
SetDetail(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedUnstagedChange = value.Backend as Models.Change;
|
||||
SelectedStagedTreeNode = null;
|
||||
SelectedStagedChange = null;
|
||||
SelectedStaged = null;
|
||||
|
||||
if (value.IsFolder)
|
||||
{
|
||||
SetDetail(null, true);
|
||||
}
|
||||
if (value.Count == 1)
|
||||
SetDetail(value[0]);
|
||||
else
|
||||
SetDetail(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FileTreeNode SelectedStagedTreeNode
|
||||
public List<Models.Change> SelectedStaged
|
||||
{
|
||||
get => _selectedStagedTreeNode;
|
||||
get => _selectedStaged;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedStagedTreeNode, value))
|
||||
if (SetProperty(ref _selectedStaged, value))
|
||||
{
|
||||
if (value == null)
|
||||
if (value == null || value.Count == 0)
|
||||
{
|
||||
SelectedStagedChange = null;
|
||||
if (_selectedUnstaged == null || _selectedUnstaged.Count == 0)
|
||||
SetDetail(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedStagedChange = value.Backend as Models.Change;
|
||||
SelectedUnstagedTreeNode = null;
|
||||
SelectedUnstagedChange = null;
|
||||
SelectedUnstaged = null;
|
||||
|
||||
if (value.IsFolder)
|
||||
{
|
||||
SetDetail(null, false);
|
||||
}
|
||||
if (value.Count == 1)
|
||||
SetDetail(value[0]);
|
||||
else
|
||||
SetDetail(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => _count;
|
||||
|
||||
public object DetailContext
|
||||
{
|
||||
get => _detailContext;
|
||||
|
@ -194,14 +165,10 @@ namespace SourceGit.ViewModels
|
|||
_unstaged.Clear();
|
||||
if (_staged != null)
|
||||
_staged.Clear();
|
||||
if (_unstagedTree != null)
|
||||
_unstagedTree.Clear();
|
||||
if (_stagedTree != null)
|
||||
_stagedTree.Clear();
|
||||
_selectedUnstagedChange = null;
|
||||
_selectedStagedChange = null;
|
||||
_selectedUnstagedTreeNode = null;
|
||||
_selectedStagedTreeNode = null;
|
||||
if (_selectedUnstaged != null)
|
||||
_selectedUnstaged.Clear();
|
||||
if (_selectedStaged != null)
|
||||
_selectedStaged.Clear();
|
||||
_detailContext = null;
|
||||
_commitMessage = string.Empty;
|
||||
}
|
||||
|
@ -210,20 +177,22 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
var unstaged = new List<Models.Change>();
|
||||
var staged = new List<Models.Change>();
|
||||
var selectedUnstaged = new List<Models.Change>();
|
||||
var selectedStaged = new List<Models.Change>();
|
||||
|
||||
var viewFile = string.Empty;
|
||||
var lastSelectedIsUnstaged = false;
|
||||
if (_selectedUnstagedChange != null)
|
||||
var lastSelectedUnstaged = new HashSet<string>();
|
||||
var lastSelectedStaged = new HashSet<string>();
|
||||
if (_selectedUnstaged != null)
|
||||
{
|
||||
viewFile = _selectedUnstagedChange.Path;
|
||||
lastSelectedIsUnstaged = true;
|
||||
foreach (var c in _selectedUnstaged)
|
||||
lastSelectedUnstaged.Add(c.Path);
|
||||
}
|
||||
else if (_selectedStagedChange != null)
|
||||
else if (_selectedStaged != null)
|
||||
{
|
||||
viewFile = _selectedStagedChange.Path;
|
||||
foreach (var c in _selectedStaged)
|
||||
lastSelectedStaged.Add(c.Path);
|
||||
}
|
||||
|
||||
var viewChange = null as Models.Change;
|
||||
var hasConflict = false;
|
||||
foreach (var c in changes)
|
||||
{
|
||||
|
@ -233,65 +202,43 @@ namespace SourceGit.ViewModels
|
|||
|| c.Index == Models.ChangeState.Renamed)
|
||||
{
|
||||
staged.Add(c);
|
||||
if (!lastSelectedIsUnstaged && c.Path == viewFile)
|
||||
{
|
||||
viewChange = c;
|
||||
}
|
||||
|
||||
if (lastSelectedStaged.Contains(c.Path))
|
||||
selectedStaged.Add(c);
|
||||
}
|
||||
|
||||
if (c.WorkTree != Models.ChangeState.None)
|
||||
{
|
||||
unstaged.Add(c);
|
||||
hasConflict |= c.IsConflit;
|
||||
if (lastSelectedIsUnstaged && c.Path == viewFile)
|
||||
{
|
||||
viewChange = c;
|
||||
}
|
||||
|
||||
if (lastSelectedUnstaged.Contains(c.Path))
|
||||
selectedUnstaged.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
_count = changes.Count;
|
||||
|
||||
var unstagedTree = FileTreeNode.Build(unstaged);
|
||||
var stagedTree = FileTreeNode.Build(staged);
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
_isLoadingData = true;
|
||||
Unstaged = unstaged;
|
||||
Staged = staged;
|
||||
UnstagedTree = unstagedTree;
|
||||
StagedTree = stagedTree;
|
||||
_isLoadingData = false;
|
||||
|
||||
// Restore last selection states.
|
||||
if (viewChange != null)
|
||||
{
|
||||
var scrollOffset = Vector.Zero;
|
||||
if (_detailContext is DiffContext old)
|
||||
scrollOffset = old.SyncScrollOffset;
|
||||
var scrollOffset = Vector.Zero;
|
||||
if (_detailContext is DiffContext old)
|
||||
scrollOffset = old.SyncScrollOffset;
|
||||
|
||||
if (lastSelectedIsUnstaged)
|
||||
{
|
||||
SelectedUnstagedChange = viewChange;
|
||||
SelectedUnstagedTreeNode = FileTreeNode.SelectByPath(_unstagedTree, viewFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedStagedChange = viewChange;
|
||||
SelectedStagedTreeNode = FileTreeNode.SelectByPath(_stagedTree, viewFile);
|
||||
}
|
||||
|
||||
if (_detailContext is DiffContext cur)
|
||||
cur.SyncScrollOffset = scrollOffset;
|
||||
}
|
||||
if (selectedUnstaged.Count > 0)
|
||||
SelectedUnstaged = selectedUnstaged;
|
||||
else if (selectedStaged.Count > 0)
|
||||
SelectedStaged = selectedStaged;
|
||||
else
|
||||
{
|
||||
SelectedUnstagedChange = null;
|
||||
SelectedUnstagedTreeNode = null;
|
||||
SelectedStagedChange = null;
|
||||
SelectedStagedTreeNode = null;
|
||||
SetDetail(null, false);
|
||||
}
|
||||
SetDetail(null);
|
||||
|
||||
if (_detailContext is DiffContext cur)
|
||||
cur.SyncScrollOffset = scrollOffset;
|
||||
|
||||
// Try to load merge message from MERGE_MSG
|
||||
if (string.IsNullOrEmpty(_commitMessage))
|
||||
|
@ -305,30 +252,24 @@ namespace SourceGit.ViewModels
|
|||
return hasConflict;
|
||||
}
|
||||
|
||||
public void SetDetail(Models.Change change, bool isUnstaged)
|
||||
public void OpenAssumeUnchanged()
|
||||
{
|
||||
if (_isLoadingData)
|
||||
return;
|
||||
var dialog = new Views.AssumeUnchangedManager()
|
||||
{
|
||||
DataContext = new AssumeUnchangedManager(_repo.FullPath)
|
||||
};
|
||||
|
||||
if (change == null)
|
||||
{
|
||||
DetailContext = null;
|
||||
}
|
||||
else if (change.IsConflit && isUnstaged)
|
||||
{
|
||||
DetailContext = new ConflictContext(_repo.FullPath, change);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_detailContext is DiffContext previous)
|
||||
{
|
||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), previous);
|
||||
}
|
||||
else
|
||||
{
|
||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged));
|
||||
}
|
||||
}
|
||||
dialog.ShowDialog(App.GetTopLevel() as Window);
|
||||
}
|
||||
|
||||
public void StageSelected()
|
||||
{
|
||||
StageChanges(_selectedUnstaged);
|
||||
}
|
||||
|
||||
public void StageAll()
|
||||
{
|
||||
StageChanges(_unstaged);
|
||||
}
|
||||
|
||||
public async void StageChanges(List<Models.Change> changes)
|
||||
|
@ -336,7 +277,7 @@ namespace SourceGit.ViewModels
|
|||
if (_unstaged.Count == 0 || changes.Count == 0)
|
||||
return;
|
||||
|
||||
SetDetail(null, true);
|
||||
SetDetail(null);
|
||||
IsStaging = true;
|
||||
_repo.SetWatcherEnabled(false);
|
||||
if (changes.Count == _unstaged.Count)
|
||||
|
@ -357,12 +298,22 @@ namespace SourceGit.ViewModels
|
|||
IsStaging = false;
|
||||
}
|
||||
|
||||
public void UnstageSelected()
|
||||
{
|
||||
UnstageChanges(_selectedStaged);
|
||||
}
|
||||
|
||||
public void UnstageAll()
|
||||
{
|
||||
UnstageChanges(_staged);
|
||||
}
|
||||
|
||||
public async void UnstageChanges(List<Models.Change> changes)
|
||||
{
|
||||
if (_staged.Count == 0 || changes.Count == 0)
|
||||
return;
|
||||
|
||||
SetDetail(null, false);
|
||||
SetDetail(null);
|
||||
IsUnstaging = true;
|
||||
_repo.SetWatcherEnabled(false);
|
||||
if (changes.Count == _staged.Count)
|
||||
|
@ -412,113 +363,25 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public async void UseTheirs(List<Models.Change> changes)
|
||||
public void Commit()
|
||||
{
|
||||
var files = new List<string>();
|
||||
foreach (var change in changes)
|
||||
{
|
||||
if (change.IsConflit)
|
||||
files.Add(change.Path);
|
||||
}
|
||||
|
||||
_repo.SetWatcherEnabled(false);
|
||||
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseTheirs(files));
|
||||
if (succ)
|
||||
{
|
||||
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
|
||||
}
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
DoCommit(false);
|
||||
}
|
||||
|
||||
public async void UseMine(List<Models.Change> changes)
|
||||
public void CommitWithPush()
|
||||
{
|
||||
var files = new List<string>();
|
||||
foreach (var change in changes)
|
||||
{
|
||||
if (change.IsConflit)
|
||||
files.Add(change.Path);
|
||||
}
|
||||
|
||||
_repo.SetWatcherEnabled(false);
|
||||
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseMine(files));
|
||||
if (succ)
|
||||
{
|
||||
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
|
||||
}
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
DoCommit(true);
|
||||
}
|
||||
|
||||
public async void UseExternalMergeTool(Models.Change change)
|
||||
public ContextMenu CreateContextMenuForUnstagedChanges()
|
||||
{
|
||||
var type = Preference.Instance.ExternalMergeToolType;
|
||||
var exec = Preference.Instance.ExternalMergeToolPath;
|
||||
|
||||
var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type);
|
||||
if (tool == null)
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Invalid merge tool in preference setting!");
|
||||
return;
|
||||
}
|
||||
|
||||
var args = tool.Type != 0 ? tool.Cmd : Preference.Instance.ExternalMergeToolCmd;
|
||||
|
||||
_repo.SetWatcherEnabled(false);
|
||||
await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, exec, args, change.Path));
|
||||
_repo.SetWatcherEnabled(true);
|
||||
}
|
||||
|
||||
public async void DoCommit(bool autoPush)
|
||||
{
|
||||
if (!PopupHost.CanCreatePopup())
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Repository has unfinished job! Please wait!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_staged.Count == 0)
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "No files added to commit!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_commitMessage))
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Commit without message is NOT allowed!");
|
||||
return;
|
||||
}
|
||||
|
||||
PushCommitMessage();
|
||||
|
||||
SetDetail(null, false);
|
||||
IsCommitting = true;
|
||||
_repo.SetWatcherEnabled(false);
|
||||
var succ = await Task.Run(() => new Commands.Commit(_repo.FullPath, _commitMessage, _useAmend).Exec());
|
||||
if (succ)
|
||||
{
|
||||
CommitMessage = string.Empty;
|
||||
UseAmend = false;
|
||||
|
||||
if (autoPush)
|
||||
{
|
||||
PopupHost.ShowAndStartPopup(new Push(_repo, null));
|
||||
}
|
||||
}
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
IsCommitting = false;
|
||||
}
|
||||
|
||||
public ContextMenu CreateContextMenuForUnstagedChanges(List<Models.Change> changes)
|
||||
{
|
||||
if (changes.Count == 0)
|
||||
if (_selectedUnstaged.Count == 0)
|
||||
return null;
|
||||
|
||||
var menu = new ContextMenu();
|
||||
if (changes.Count == 1)
|
||||
if (_selectedUnstaged.Count == 1)
|
||||
{
|
||||
var change = changes[0];
|
||||
var change = _selectedUnstaged[0];
|
||||
var path = Path.GetFullPath(Path.Combine(_repo.FullPath, change.Path));
|
||||
|
||||
var explore = new MenuItem();
|
||||
|
@ -551,7 +414,7 @@ namespace SourceGit.ViewModels
|
|||
useTheirs.Header = App.Text("FileCM.UseTheirs");
|
||||
useTheirs.Click += (_, e) =>
|
||||
{
|
||||
UseTheirs(changes);
|
||||
UseTheirs(_selectedUnstaged);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -560,7 +423,7 @@ namespace SourceGit.ViewModels
|
|||
useMine.Header = App.Text("FileCM.UseMine");
|
||||
useMine.Click += (_, e) =>
|
||||
{
|
||||
UseMine(changes);
|
||||
UseMine(_selectedUnstaged);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -585,7 +448,7 @@ namespace SourceGit.ViewModels
|
|||
stage.Icon = App.CreateMenuIcon("Icons.File.Add");
|
||||
stage.Click += (_, e) =>
|
||||
{
|
||||
StageChanges(changes);
|
||||
StageChanges(_selectedUnstaged);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -594,7 +457,7 @@ namespace SourceGit.ViewModels
|
|||
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
||||
discard.Click += (_, e) =>
|
||||
{
|
||||
Discard(changes, true);
|
||||
Discard(_selectedUnstaged, true);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -605,7 +468,7 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
if (PopupHost.CanCreatePopup())
|
||||
{
|
||||
PopupHost.ShowPopup(new StashChanges(_repo, changes, false));
|
||||
PopupHost.ShowPopup(new StashChanges(_repo, _selectedUnstaged, false));
|
||||
}
|
||||
e.Handled = true;
|
||||
};
|
||||
|
@ -627,7 +490,7 @@ namespace SourceGit.ViewModels
|
|||
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
|
||||
if (storageFile != null)
|
||||
{
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, changes, true, storageFile.Path.LocalPath));
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedUnstaged, true, storageFile.Path.LocalPath));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
|
||||
}
|
||||
|
@ -679,7 +542,7 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
var hasConflicts = false;
|
||||
var hasNoneConflicts = false;
|
||||
foreach (var change in changes)
|
||||
foreach (var change in _selectedUnstaged)
|
||||
{
|
||||
if (change.IsConflit)
|
||||
{
|
||||
|
@ -704,7 +567,7 @@ namespace SourceGit.ViewModels
|
|||
useTheirs.Header = App.Text("FileCM.UseTheirs");
|
||||
useTheirs.Click += (_, e) =>
|
||||
{
|
||||
UseTheirs(changes);
|
||||
UseTheirs(_selectedUnstaged);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -713,7 +576,7 @@ namespace SourceGit.ViewModels
|
|||
useMine.Header = App.Text("FileCM.UseMine");
|
||||
useMine.Click += (_, e) =>
|
||||
{
|
||||
UseMine(changes);
|
||||
UseMine(_selectedUnstaged);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -723,31 +586,31 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
|
||||
var stage = new MenuItem();
|
||||
stage.Header = App.Text("FileCM.StageMulti", changes.Count);
|
||||
stage.Header = App.Text("FileCM.StageMulti", _selectedUnstaged.Count);
|
||||
stage.Icon = App.CreateMenuIcon("Icons.File.Add");
|
||||
stage.Click += (_, e) =>
|
||||
{
|
||||
StageChanges(changes);
|
||||
StageChanges(_selectedUnstaged);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
var discard = new MenuItem();
|
||||
discard.Header = App.Text("FileCM.DiscardMulti", changes.Count);
|
||||
discard.Header = App.Text("FileCM.DiscardMulti", _selectedUnstaged.Count);
|
||||
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
||||
discard.Click += (_, e) =>
|
||||
{
|
||||
Discard(changes, true);
|
||||
Discard(_selectedUnstaged, true);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
var stash = new MenuItem();
|
||||
stash.Header = App.Text("FileCM.StashMulti", changes.Count);
|
||||
stash.Header = App.Text("FileCM.StashMulti", _selectedUnstaged.Count);
|
||||
stash.Icon = App.CreateMenuIcon("Icons.Stashes");
|
||||
stash.Click += (_, e) =>
|
||||
{
|
||||
if (PopupHost.CanCreatePopup())
|
||||
{
|
||||
PopupHost.ShowPopup(new StashChanges(_repo, changes, false));
|
||||
PopupHost.ShowPopup(new StashChanges(_repo, _selectedUnstaged, false));
|
||||
}
|
||||
e.Handled = true;
|
||||
};
|
||||
|
@ -769,7 +632,7 @@ namespace SourceGit.ViewModels
|
|||
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
|
||||
if (storageFile != null)
|
||||
{
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, changes, true, storageFile.Path.LocalPath));
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedUnstaged, true, storageFile.Path.LocalPath));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
|
||||
}
|
||||
|
@ -786,15 +649,15 @@ namespace SourceGit.ViewModels
|
|||
return menu;
|
||||
}
|
||||
|
||||
public ContextMenu CreateContextMenuForStagedChanges(List<Models.Change> changes)
|
||||
public ContextMenu CreateContextMenuForStagedChanges()
|
||||
{
|
||||
if (changes.Count == 0)
|
||||
if (_selectedStaged.Count == 0)
|
||||
return null;
|
||||
|
||||
var menu = new ContextMenu();
|
||||
if (changes.Count == 1)
|
||||
if (_selectedStaged.Count == 1)
|
||||
{
|
||||
var change = changes[0];
|
||||
var change = _selectedStaged[0];
|
||||
var path = Path.GetFullPath(Path.Combine(_repo.FullPath, change.Path));
|
||||
|
||||
var explore = new MenuItem();
|
||||
|
@ -822,7 +685,7 @@ namespace SourceGit.ViewModels
|
|||
unstage.Icon = App.CreateMenuIcon("Icons.File.Remove");
|
||||
unstage.Click += (o, e) =>
|
||||
{
|
||||
UnstageChanges(changes);
|
||||
UnstageChanges(_selectedStaged);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -831,7 +694,7 @@ namespace SourceGit.ViewModels
|
|||
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
||||
discard.Click += (_, e) =>
|
||||
{
|
||||
Discard(changes, false);
|
||||
Discard(_selectedStaged, false);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -842,7 +705,7 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
if (PopupHost.CanCreatePopup())
|
||||
{
|
||||
PopupHost.ShowPopup(new StashChanges(_repo, changes, false));
|
||||
PopupHost.ShowPopup(new StashChanges(_repo, _selectedStaged, false));
|
||||
}
|
||||
e.Handled = true;
|
||||
};
|
||||
|
@ -864,7 +727,7 @@ namespace SourceGit.ViewModels
|
|||
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
|
||||
if (storageFile != null)
|
||||
{
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, changes, false, storageFile.Path.LocalPath));
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedStaged, false, storageFile.Path.LocalPath));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
|
||||
}
|
||||
|
@ -894,31 +757,31 @@ namespace SourceGit.ViewModels
|
|||
else
|
||||
{
|
||||
var unstage = new MenuItem();
|
||||
unstage.Header = App.Text("FileCM.UnstageMulti", changes.Count);
|
||||
unstage.Header = App.Text("FileCM.UnstageMulti", _selectedStaged.Count);
|
||||
unstage.Icon = App.CreateMenuIcon("Icons.File.Remove");
|
||||
unstage.Click += (o, e) =>
|
||||
{
|
||||
UnstageChanges(changes);
|
||||
UnstageChanges(_selectedStaged);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
var discard = new MenuItem();
|
||||
discard.Header = App.Text("FileCM.DiscardMulti", changes.Count);
|
||||
discard.Header = App.Text("FileCM.DiscardMulti", _selectedStaged.Count);
|
||||
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
||||
discard.Click += (_, e) =>
|
||||
{
|
||||
Discard(changes, false);
|
||||
Discard(_selectedStaged, false);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
var stash = new MenuItem();
|
||||
stash.Header = App.Text("FileCM.StashMulti", changes.Count);
|
||||
stash.Header = App.Text("FileCM.StashMulti", _selectedStaged.Count);
|
||||
stash.Icon = App.CreateMenuIcon("Icons.Stashes");
|
||||
stash.Click += (_, e) =>
|
||||
{
|
||||
if (PopupHost.CanCreatePopup())
|
||||
{
|
||||
PopupHost.ShowPopup(new StashChanges(_repo, changes, false));
|
||||
PopupHost.ShowPopup(new StashChanges(_repo, _selectedStaged, false));
|
||||
}
|
||||
e.Handled = true;
|
||||
};
|
||||
|
@ -940,7 +803,7 @@ namespace SourceGit.ViewModels
|
|||
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
|
||||
if (storageFile != null)
|
||||
{
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, changes, false, storageFile.Path.LocalPath));
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedStaged, false, storageFile.Path.LocalPath));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
|
||||
}
|
||||
|
@ -993,6 +856,139 @@ namespace SourceGit.ViewModels
|
|||
return menu;
|
||||
}
|
||||
|
||||
private void SetDetail(Models.Change change)
|
||||
{
|
||||
if (_isLoadingData)
|
||||
return;
|
||||
|
||||
var isUnstaged = _selectedUnstaged != null && _selectedUnstaged.Count > 0;
|
||||
if (change == null)
|
||||
{
|
||||
DetailContext = null;
|
||||
}
|
||||
else if (change.IsConflit && isUnstaged)
|
||||
{
|
||||
DetailContext = new ConflictContext(_repo.FullPath, change);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_detailContext is DiffContext previous)
|
||||
{
|
||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), previous);
|
||||
}
|
||||
else
|
||||
{
|
||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void UseTheirs(List<Models.Change> changes)
|
||||
{
|
||||
var files = new List<string>();
|
||||
foreach (var change in changes)
|
||||
{
|
||||
if (change.IsConflit)
|
||||
files.Add(change.Path);
|
||||
}
|
||||
|
||||
_repo.SetWatcherEnabled(false);
|
||||
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseTheirs(files));
|
||||
if (succ)
|
||||
{
|
||||
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
|
||||
}
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
}
|
||||
|
||||
private async void UseMine(List<Models.Change> changes)
|
||||
{
|
||||
var files = new List<string>();
|
||||
foreach (var change in changes)
|
||||
{
|
||||
if (change.IsConflit)
|
||||
files.Add(change.Path);
|
||||
}
|
||||
|
||||
_repo.SetWatcherEnabled(false);
|
||||
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseMine(files));
|
||||
if (succ)
|
||||
{
|
||||
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
|
||||
}
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
}
|
||||
|
||||
private async void UseExternalMergeTool(Models.Change change)
|
||||
{
|
||||
var type = Preference.Instance.ExternalMergeToolType;
|
||||
var exec = Preference.Instance.ExternalMergeToolPath;
|
||||
|
||||
var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type);
|
||||
if (tool == null)
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Invalid merge tool in preference setting!");
|
||||
return;
|
||||
}
|
||||
|
||||
var args = tool.Type != 0 ? tool.Cmd : Preference.Instance.ExternalMergeToolCmd;
|
||||
|
||||
_repo.SetWatcherEnabled(false);
|
||||
await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, exec, args, change.Path));
|
||||
_repo.SetWatcherEnabled(true);
|
||||
}
|
||||
|
||||
private void DoCommit(bool autoPush)
|
||||
{
|
||||
if (!PopupHost.CanCreatePopup())
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Repository has unfinished job! Please wait!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_staged.Count == 0)
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "No files added to commit!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_commitMessage))
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Commit without message is NOT allowed!");
|
||||
return;
|
||||
}
|
||||
|
||||
PushCommitMessage();
|
||||
|
||||
SetDetail(null);
|
||||
IsCommitting = true;
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var succ = new Commands.Commit(_repo.FullPath, _commitMessage, _useAmend).Exec();
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (succ)
|
||||
{
|
||||
CommitMessage = string.Empty;
|
||||
UseAmend = false;
|
||||
|
||||
if (autoPush)
|
||||
{
|
||||
PopupHost.ShowAndStartPopup(new Push(_repo, null));
|
||||
}
|
||||
}
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
|
||||
IsCommitting = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void PushCommitMessage()
|
||||
{
|
||||
var existIdx = _repo.CommitMessages.IndexOf(CommitMessage);
|
||||
|
@ -1022,13 +1018,9 @@ namespace SourceGit.ViewModels
|
|||
private bool _useAmend = false;
|
||||
private List<Models.Change> _unstaged = null;
|
||||
private List<Models.Change> _staged = null;
|
||||
private Models.Change _selectedUnstagedChange = null;
|
||||
private Models.Change _selectedStagedChange = null;
|
||||
private List<Models.Change> _selectedUnstaged = null;
|
||||
private List<Models.Change> _selectedStaged = null;
|
||||
private int _count = 0;
|
||||
private List<FileTreeNode> _unstagedTree = null;
|
||||
private List<FileTreeNode> _stagedTree = null;
|
||||
private FileTreeNode _selectedUnstagedTreeNode = null;
|
||||
private FileTreeNode _selectedStagedTreeNode = null;
|
||||
private object _detailContext = null;
|
||||
private string _commitMessage = string.Empty;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue