feature: Allow show uncommitted changes in commits history like TortoiseHG Workspace

This commit is contained in:
Giuseppe Lippolis 2024-07-26 11:28:40 +02:00
parent 3c5a661fa0
commit ba8c6382e7
15 changed files with 166 additions and 65 deletions

View file

@ -35,6 +35,7 @@ namespace SourceGit.Models
public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime; public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime;
public bool IsCurrentHead => Decorators.Find(x => x.Type is DecoratorType.CurrentBranchHead or DecoratorType.CurrentCommitHead) != null; public bool IsCurrentHead => Decorators.Find(x => x.Type is DecoratorType.CurrentBranchHead or DecoratorType.CurrentCommitHead) != null;
public bool IsWorkCopy => string.IsNullOrWhiteSpace(SHA);
public double Opacity => IsMerged ? 1 : OpacityForNotMerged; public double Opacity => IsMerged ? 1 : OpacityForNotMerged;
public FontWeight FontWeight => IsCurrentHead ? FontWeight.Bold : FontWeight.Regular; public FontWeight FontWeight => IsCurrentHead ? FontWeight.Bold : FontWeight.Regular;

View file

@ -101,6 +101,7 @@ namespace SourceGit.Models
{ {
public Point Center; public Point Center;
public int Color; public int Color;
public bool IsWorkCopy;
} }
public List<Path> Paths { get; set; } = new List<Path>(); public List<Path> Paths { get; set; } = new List<Path>();
@ -156,42 +157,45 @@ namespace SourceGit.Models
// Find first curves that links to this commit and marks others that links to this commit ended. // Find first curves that links to this commit and marks others that links to this commit ended.
double offsetX = -HALF_WIDTH; double offsetX = -HALF_WIDTH;
foreach (var l in unsolved) if (!string.IsNullOrEmpty(commit.SHA))
{ {
if (l.Next == commit.SHA) foreach (var l in unsolved)
{ {
if (major == null) if (l.Next == commit.SHA)
{ {
offsetX += UNIT_WIDTH; if (major == null)
major = l;
if (commit.Parents.Count > 0)
{ {
major.Next = commit.Parents[0]; offsetX += UNIT_WIDTH;
if (!mapUnsolved.ContainsKey(major.Next)) major = l;
mapUnsolved.Add(major.Next, major);
if (commit.Parents.Count > 0)
{
major.Next = commit.Parents[0];
if (!mapUnsolved.ContainsKey(major.Next))
mapUnsolved.Add(major.Next, major);
}
else
{
major.Next = "ENDED";
ended.Add(l);
}
major.Add(offsetX, offsetY, HALF_HEIGHT);
} }
else else
{ {
major.Next = "ENDED";
ended.Add(l); ended.Add(l);
} }
major.Add(offsetX, offsetY, HALF_HEIGHT); isMerged = isMerged || l.IsMerged;
} }
else else
{ {
ended.Add(l); if (!mapUnsolved.ContainsKey(l.Next))
mapUnsolved.Add(l.Next, l);
offsetX += UNIT_WIDTH;
l.Add(offsetX, offsetY, HALF_HEIGHT);
} }
isMerged = isMerged || l.IsMerged;
}
else
{
if (!mapUnsolved.ContainsKey(l.Next))
mapUnsolved.Add(l.Next, l);
offsetX += UNIT_WIDTH;
l.Add(offsetX, offsetY, HALF_HEIGHT);
} }
} }
@ -211,11 +215,11 @@ namespace SourceGit.Models
{ {
major.IsMerged = isMerged; major.IsMerged = isMerged;
position = new Point(major.LastX, offsetY); position = new Point(major.LastX, offsetY);
temp.Dots.Add(new Dot() { Center = position, Color = major.Path.Color }); temp.Dots.Add(new Dot() { Center = position, Color = major.Path.Color, IsWorkCopy = commit.IsWorkCopy });
} }
else else
{ {
temp.Dots.Add(new Dot() { Center = position, Color = 0 }); temp.Dots.Add(new Dot() { Center = position, Color = 0, IsWorkCopy = commit.IsWorkCopy });
} }
// Deal with parents // Deal with parents

View file

@ -286,6 +286,7 @@
<x:String x:Key="Text.Histories.Search" xml:space="preserve">SEARCH SHA/SUBJECT/AUTHOR. PRESS ENTER TO SEARCH, ESC TO QUIT</x:String> <x:String x:Key="Text.Histories.Search" xml:space="preserve">SEARCH SHA/SUBJECT/AUTHOR. PRESS ENTER TO SEARCH, ESC TO QUIT</x:String>
<x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">CLEAR</x:String> <x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">CLEAR</x:String>
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">SELECTED {0} COMMITS</x:String> <x:String x:Key="Text.Histories.Selected" xml:space="preserve">SELECTED {0} COMMITS</x:String>
<x:String x:Key="Text.Histories.UncommittedChanges.Subject" xml:space="preserve">★Uncommitted local changes★</x:String>
<x:String x:Key="Text.Hotkeys" xml:space="preserve">Keyboard Shortcuts Reference</x:String> <x:String x:Key="Text.Hotkeys" xml:space="preserve">Keyboard Shortcuts Reference</x:String>
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">GLOBAL</x:String> <x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">GLOBAL</x:String>
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">Cancel current popup</x:String> <x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">Cancel current popup</x:String>
@ -380,6 +381,7 @@
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Default Clone Dir</x:String> <x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Default Clone Dir</x:String>
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">User Email</x:String> <x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">User Email</x:String>
<x:String x:Key="Text.Preference.Git.Email.Placeholder" xml:space="preserve">Global git user email</x:String> <x:String x:Key="Text.Preference.Git.Email.Placeholder" xml:space="preserve">Global git user email</x:String>
<x:String x:Key="Text.Preference.Git.ShowUncommittedChangesInHistory" xml:space="preserve">Show uncommitted changes in history</x:String>
<x:String x:Key="Text.Preference.Git.Path" xml:space="preserve">Install Path</x:String> <x:String x:Key="Text.Preference.Git.Path" xml:space="preserve">Install Path</x:String>
<x:String x:Key="Text.Preference.Git.Shell" xml:space="preserve">Shell</x:String> <x:String x:Key="Text.Preference.Git.Shell" xml:space="preserve">Shell</x:String>
<x:String x:Key="Text.Preference.Git.User" xml:space="preserve">User Name</x:String> <x:String x:Key="Text.Preference.Git.User" xml:space="preserve">User Name</x:String>

View file

@ -289,6 +289,7 @@
<x:String x:Key="Text.Histories.Search" xml:space="preserve">查询提交指纹、信息、作者。回车键开始ESC键取消</x:String> <x:String x:Key="Text.Histories.Search" xml:space="preserve">查询提交指纹、信息、作者。回车键开始ESC键取消</x:String>
<x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">清空</x:String> <x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">清空</x:String>
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">已选中 {0} 项提交</x:String> <x:String x:Key="Text.Histories.Selected" xml:space="preserve">已选中 {0} 项提交</x:String>
<x:String x:Key="Text.Histories.UncommittedChanges.Subject" xml:space="preserve">★未提交的本地更改★</x:String>
<x:String x:Key="Text.Hotkeys" xml:space="preserve">快捷键参考</x:String> <x:String x:Key="Text.Hotkeys" xml:space="preserve">快捷键参考</x:String>
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">全局快捷键</x:String> <x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">全局快捷键</x:String>
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">取消弹出面板</x:String> <x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">取消弹出面板</x:String>
@ -383,6 +384,7 @@
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">默认克隆路径</x:String> <x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">默认克隆路径</x:String>
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">邮箱</x:String> <x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">邮箱</x:String>
<x:String x:Key="Text.Preference.Git.Email.Placeholder" xml:space="preserve">默认GIT用户邮箱</x:String> <x:String x:Key="Text.Preference.Git.Email.Placeholder" xml:space="preserve">默认GIT用户邮箱</x:String>
<x:String x:Key="Text.Preference.Git.ShowUncommittedChangesInHistory" xml:space="preserve">顯示歷史中未提交的更改</x:String>
<x:String x:Key="Text.Preference.Git.Path" xml:space="preserve">安装路径</x:String> <x:String x:Key="Text.Preference.Git.Path" xml:space="preserve">安装路径</x:String>
<x:String x:Key="Text.Preference.Git.Shell" xml:space="preserve">终端Shell</x:String> <x:String x:Key="Text.Preference.Git.Shell" xml:space="preserve">终端Shell</x:String>
<x:String x:Key="Text.Preference.Git.User" xml:space="preserve">用户名</x:String> <x:String x:Key="Text.Preference.Git.User" xml:space="preserve">用户名</x:String>

View file

@ -289,6 +289,7 @@
<x:String x:Key="Text.Histories.Search" xml:space="preserve">查詢提交指紋、資訊、作者。回車鍵開始ESC鍵取消</x:String> <x:String x:Key="Text.Histories.Search" xml:space="preserve">查詢提交指紋、資訊、作者。回車鍵開始ESC鍵取消</x:String>
<x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">清空</x:String> <x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">清空</x:String>
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">已選中 {0} 項提交</x:String> <x:String x:Key="Text.Histories.Selected" xml:space="preserve">已選中 {0} 項提交</x:String>
<x:String x:Key="Text.Histories.UncommittedChanges.Subject" xml:space="preserve">★未提交的本地更改★</x:String>
<x:String x:Key="Text.Hotkeys" xml:space="preserve">快捷鍵參考</x:String> <x:String x:Key="Text.Hotkeys" xml:space="preserve">快捷鍵參考</x:String>
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">全域性快捷鍵</x:String> <x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">全域性快捷鍵</x:String>
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">取消彈出面板</x:String> <x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">取消彈出面板</x:String>
@ -383,6 +384,7 @@
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">預設克隆路徑</x:String> <x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">預設克隆路徑</x:String>
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">郵箱</x:String> <x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">郵箱</x:String>
<x:String x:Key="Text.Preference.Git.Email.Placeholder" xml:space="preserve">預設GIT使用者郵箱</x:String> <x:String x:Key="Text.Preference.Git.Email.Placeholder" xml:space="preserve">預設GIT使用者郵箱</x:String>
<x:String x:Key="Text.Preference.Git.ShowUncommittedChangesInHistory" xml:space="preserve">显示历史记录中未提交的更改</x:String>
<x:String x:Key="Text.Preference.Git.Path" xml:space="preserve">安裝路徑</x:String> <x:String x:Key="Text.Preference.Git.Path" xml:space="preserve">安裝路徑</x:String>
<x:String x:Key="Text.Preference.Git.Shell" xml:space="preserve">終端Shell</x:String> <x:String x:Key="Text.Preference.Git.Shell" xml:space="preserve">終端Shell</x:String>
<x:String x:Key="Text.Preference.Git.User" xml:space="preserve">使用者名稱</x:String> <x:String x:Key="Text.Preference.Git.User" xml:space="preserve">使用者名稱</x:String>

View file

@ -116,7 +116,14 @@ namespace SourceGit.ViewModels
AutoSelectedCommit = commit; AutoSelectedCommit = commit;
NavigationId = _navigationId + 1; NavigationId = _navigationId + 1;
if (_detailContext is CommitDetail detail)
if (commit.IsWorkCopy)
{
var wc = _repo.WorkingCopy ??= new WorkingCopy(_repo);
DetailContext = wc;
wc.RefreshWorkingCopyChangesAsync();
}
else if (_detailContext is CommitDetail detail)
{ {
detail.Commit = commit; detail.Commit = commit;
} }

View file

@ -147,6 +147,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _maxHistoryCommits, value); set => SetProperty(ref _maxHistoryCommits, value);
} }
public bool ShowUncommittedChangesInHistory
{
get => _showUncommittedChangesInHistory;
set => SetProperty(ref _showUncommittedChangesInHistory, value);
}
public int SubjectGuideLength public int SubjectGuideLength
{ {
get => _subjectGuideLength; get => _subjectGuideLength;
@ -515,6 +521,7 @@ namespace SourceGit.ViewModels
private LayoutInfo _layout = new LayoutInfo(); private LayoutInfo _layout = new LayoutInfo();
private int _maxHistoryCommits = 20000; private int _maxHistoryCommits = 20000;
private bool _showUncommittedChangesInHistory = false;
private int _subjectGuideLength = 50; private int _subjectGuideLength = 50;
private bool _restoreTabs = false; private bool _restoreTabs = false;
private bool _useFixedTabWidth = true; private bool _useFixedTabWidth = true;

View file

@ -716,6 +716,7 @@ namespace SourceGit.ViewModels
Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true); Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true);
var limits = $"-{Preference.Instance.MaxHistoryCommits} "; var limits = $"-{Preference.Instance.MaxHistoryCommits} ";
var showUncommitedChangedInHistory = Preference.Instance.ShowUncommittedChangesInHistory;
var validFilters = new List<string>(); var validFilters = new List<string>();
foreach (var filter in _settings.Filters) foreach (var filter in _settings.Filters)
{ {
@ -762,6 +763,36 @@ namespace SourceGit.ViewModels
} }
var commits = new Commands.QueryCommits(_fullpath, limits).Result(); var commits = new Commands.QueryCommits(_fullpath, limits).Result();
if (showUncommitedChangedInHistory)
{
var changes = new Commands.QueryLocalChanges(_fullpath, _includeUntracked).Result();
if(changes.Count > 0)
{
var config = new Commands.Config(_fullpath).ListAll();
var currentUser = new Models.User();
if (config.TryGetValue("user.name", out var name))
currentUser.Name = name;
if (config.TryGetValue("user.email", out var email))
currentUser.Email = email;
var date = (ulong)DateTime.Now.ToUniversalTime().Subtract(DateTime.UnixEpoch).TotalSeconds;
commits.Insert(0,new Models.Commit()
{
Subject = App.Text("Histories.UncommittedChanges.Subject"),
CanPullFromUpstream = false,
Author = currentUser,
Committer = currentUser,
Parents = [currentBranch.Head],
AuthorTime = date,
CommitterTime = date,
Decorators = [
new Models.Decorator()
{
Type = Models.DecoratorType.CurrentBranchHead,
Name = currentBranch.FriendlyName,
}]
});
}
}
var graph = Models.CommitGraph.Parse(commits, canPushCommits, canPullCommits); var graph = Models.CommitGraph.Parse(commits, canPushCommits, canPullCommits);
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
@ -781,41 +812,15 @@ namespace SourceGit.ViewModels
Dispatcher.UIThread.Invoke(() => Submodules = submodules); Dispatcher.UIThread.Invoke(() => Submodules = submodules);
} }
public void RefreshWorkingCopyChanges() public async void RefreshWorkingCopyChanges()
{ {
var changes = new Commands.QueryLocalChanges(_fullpath, _includeUntracked).Result();
if (_workingCopy == null) if (_workingCopy == null)
return; return;
var hasUnsolvedConflict = _workingCopy.SetData(changes); var result = await _workingCopy.RefreshWorkingCopyChangesAsync();
var inProgress = null as InProgressContext;
var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge"); var hasUnsolvedConflict = result.HasUnsolvedConflict;
var rebaseApplyFolder = Path.Combine(_gitDir, "rebase-apply"); var inProgress = result.InProgressContext;
if (File.Exists(Path.Combine(_gitDir, "CHERRY_PICK_HEAD")))
{
inProgress = new CherryPickInProgress(_fullpath);
}
else if (File.Exists(Path.Combine(_gitDir, "REBASE_HEAD")) && Directory.Exists(rebaseMergeFolder))
{
inProgress = new RebaseInProgress(this);
}
else if (File.Exists(Path.Combine(_gitDir, "REVERT_HEAD")))
{
inProgress = new RevertInProgress(_fullpath);
}
else if (File.Exists(Path.Combine(_gitDir, "MERGE_HEAD")))
{
inProgress = new MergeInProgress(_fullpath);
}
else
{
if (Directory.Exists(rebaseMergeFolder))
Directory.Delete(rebaseMergeFolder, true);
if (Directory.Exists(rebaseApplyFolder))
Directory.Delete(rebaseApplyFolder, true);
}
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
@ -1957,6 +1962,12 @@ namespace SourceGit.ViewModels
} }
} }
public WorkingCopy WorkingCopy
{
get => _workingCopy;
set => _workingCopy = value;
}
private string _fullpath = string.Empty; private string _fullpath = string.Empty;
private string _gitDir = string.Empty; private string _gitDir = string.Empty;
private Models.RepositorySettings _settings = null; private Models.RepositorySettings _settings = null;

View file

@ -1280,6 +1280,47 @@ namespace SourceGit.ViewModels
}); });
} }
public async Task<(InProgressContext InProgressContext, bool HasUnsolvedConflict)> RefreshWorkingCopyChangesAsync()
{
return await Task.Factory.StartNew(() =>
{
var gitDir = _repo.GitDir;
var fullpath = _repo.FullPath;
var changes = new Commands.QueryLocalChanges(fullpath, _repo.IncludeUntracked).Result();
var hasUnsolvedConflict = SetData(changes);
var inProgress = null as InProgressContext;
var rebaseMergeFolder = Path.Combine(gitDir, "rebase-merge");
var rebaseApplyFolder = Path.Combine(gitDir, "rebase-apply");
if (File.Exists(Path.Combine(gitDir, "CHERRY_PICK_HEAD")))
{
inProgress = new CherryPickInProgress(fullpath);
}
else if (File.Exists(Path.Combine(gitDir, "REBASE_HEAD")) && Directory.Exists(rebaseMergeFolder))
{
inProgress = new RebaseInProgress(_repo);
}
else if (File.Exists(Path.Combine(gitDir, "REVERT_HEAD")))
{
inProgress = new RevertInProgress(fullpath);
}
else if (File.Exists(Path.Combine(gitDir, "MERGE_HEAD")))
{
inProgress = new MergeInProgress(fullpath);
}
else
{
if (Directory.Exists(rebaseMergeFolder))
Directory.Delete(rebaseMergeFolder, true);
if (Directory.Exists(rebaseApplyFolder))
Directory.Delete(rebaseApplyFolder, true);
}
return (inProgress, hasUnsolvedConflict);
});
}
private Repository _repo = null; private Repository _repo = null;
private bool _isLoadingData = false; private bool _isLoadingData = false;
private bool _isStaging = false; private bool _isStaging = false;

View file

@ -15,6 +15,7 @@ namespace SourceGit.Views
public Geometry Icon { get; set; } = null; public Geometry Icon { get; set; } = null;
public FormattedText Label { get; set; } = null; public FormattedText Label { get; set; } = null;
public bool IsTag { get; set; } = false; public bool IsTag { get; set; } = false;
public bool IsWorkCopy { get; internal set; } = false;
} }
public static readonly StyledProperty<FontFamily> FontFamilyProperty = public static readonly StyledProperty<FontFamily> FontFamilyProperty =
@ -117,6 +118,14 @@ namespace SourceGit.Views
using (context.PushTransform(Matrix.CreateTranslation(x + 4, 4))) using (context.PushTransform(Matrix.CreateTranslation(x + 4, 4)))
context.DrawGeometry(iconFG, null, item.Icon); context.DrawGeometry(iconFG, null, item.Icon);
if (item.IsWorkCopy)
{
var workCopyBorderRect = new RoundedRect(new Rect(x, 0, 16 + item.Label.Width + 8, 16)
, new CornerRadius(2, 0, 0, 2));
var workCopyBorderPen = new Pen(item.IsTag ? tagBG : branchBG, 2, new DashStyle() { Dashes = [1, 1], Offset = 1 });
context.DrawRectangle(null, workCopyBorderPen, workCopyBorderRect);
}
x += item.Label.Width + 16 + 8 + 4; x += item.Label.Width + 16 + 8 + 4;
} }
} }
@ -156,6 +165,7 @@ namespace SourceGit.Views
{ {
Label = label, Label = label,
IsTag = decorator.Type == Models.DecoratorType.Tag, IsTag = decorator.Type == Models.DecoratorType.Tag,
IsWorkCopy = commit.IsWorkCopy,
}; };
var geo = null as StreamGeometry; var geo = null as StreamGeometry;

View file

@ -189,6 +189,11 @@
</ContentControl.Content> </ContentControl.Content>
<ContentControl.DataTemplates> <ContentControl.DataTemplates>
<DataTemplate DataType="vm:WorkingCopy">
<v:WorkingCopy/>
</DataTemplate>
<DataTemplate DataType="vm:CommitDetail"> <DataTemplate DataType="vm:CommitDetail">
<v:CommitDetail/> <v:CommitDetail/>
</DataTemplate> </DataTemplate>

View file

@ -263,8 +263,12 @@ namespace SourceGit.Views
continue; continue;
if (dot.Center.Y > bottom) if (dot.Center.Y > bottom)
break; break;
var pen = Models.CommitGraph.Pens[dot.Color];
context.DrawEllipse(dotFill, Models.CommitGraph.Pens[dot.Color], dot.Center, 3, 3); if (dot.IsWorkCopy)
{
pen = new Pen(pen.Brush, pen.Thickness, s_UncommittedCahngesLineDashStyle);
}
context.DrawEllipse(dotFill, pen, dot.Center, 5, 5);
} }
} }
@ -282,7 +286,6 @@ namespace SourceGit.Views
var geo = new StreamGeometry(); var geo = new StreamGeometry();
var pen = Models.CommitGraph.Pens[line.Color]; var pen = Models.CommitGraph.Pens[line.Color];
using (var ctx = geo.Open()) using (var ctx = geo.Open())
{ {
var started = false; var started = false;
@ -351,10 +354,12 @@ namespace SourceGit.Views
ctx.BeginFigure(link.Start, false); ctx.BeginFigure(link.Start, false);
ctx.QuadraticBezierTo(link.Control, link.End); ctx.QuadraticBezierTo(link.Control, link.End);
} }
var pen = Models.CommitGraph.Pens[link.Color];
context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo); context.DrawGeometry(null, pen, geo);
} }
} }
private readonly static IDashStyle s_UncommittedCahngesLineDashStyle = new DashStyle() { Dashes = [1, 1], Offset = 1 };
} }
public partial class Histories : UserControl public partial class Histories : UserControl
@ -403,7 +408,7 @@ namespace SourceGit.Views
private void OnCommitDataGridContextRequested(object sender, ContextRequestedEventArgs e) private void OnCommitDataGridContextRequested(object sender, ContextRequestedEventArgs e)
{ {
if (DataContext is ViewModels.Histories histories && sender is DataGrid datagrid) if (DataContext is ViewModels.Histories histories && sender is DataGrid datagrid && datagrid.SelectedItem is Models.Commit { IsWorkCopy: false})
{ {
var menu = histories.MakeContextMenu(datagrid); var menu = histories.MakeContextMenu(datagrid);
datagrid.OpenContextMenu(menu); datagrid.OpenContextMenu(menu);

View file

@ -244,7 +244,7 @@
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.Git}"/> <TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.Git}"/>
</TabItem.Header> </TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,Auto,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*"> <Grid Margin="8" RowDefinitions="32,32,Auto,32,32,32,32,32,Auto,32" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.Git.Path}" Text="{DynamicResource Text.Preference.Git.Path}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
@ -395,6 +395,10 @@
Margin="5,0,0,0" Margin="5,0,0,0"
Text="{DynamicResource Text.Preference.Git.AutoFetchIntervalSuffix}" /> Text="{DynamicResource Text.Preference.Git.AutoFetchIntervalSuffix}" />
</Grid> </Grid>
<CheckBox Grid.Row="9" Grid.Column="1"
Content="{DynamicResource Text.Preference.Git.ShowUncommittedChangesInHistory}"
IsChecked="{Binding ShowUncommittedChangesInHistory, Mode=TwoWay}"
/>
</Grid> </Grid>
</TabItem> </TabItem>

View file

@ -87,7 +87,7 @@
</Grid> </Grid>
</ListBoxItem> </ListBoxItem>
<ListBoxItem> <ListBoxItem IsVisible="{Binding Source={x:Static vm:Preference.Instance}, Path=!ShowUncommittedChangesInHistory , Mode=OneWay}">
<Grid Classes="view_mode" ColumnDefinitions="32,*,Auto"> <Grid Classes="view_mode" ColumnDefinitions="32,*,Auto">
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Send}"/> <Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Send}"/>
<TextBlock Grid.Column="1" Classes="primary" Text="{DynamicResource Text.WorkingCopy}"/> <TextBlock Grid.Column="1" Classes="primary" Text="{DynamicResource Text.WorkingCopy}"/>

View file

@ -118,7 +118,7 @@
<!-- Right --> <!-- Right -->
<Grid Grid.Column="2" Margin="0,4,4,4"> <Grid Grid.Column="2" Margin="0,4,4,4">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="400"/> <RowDefinition Height="*"/>
<RowDefinition Height="4"/> <RowDefinition Height="4"/>
<RowDefinition Height="128" MinHeight="100"/> <RowDefinition Height="128" MinHeight="100"/>
<RowDefinition Height="36"/> <RowDefinition Height="36"/>
@ -153,7 +153,7 @@
<TextBlock Margin="0,16,0,8" FontSize="20" FontWeight="Bold" Text="{DynamicResource Text.WorkingCopy.Conflicts.Resolved}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/> <TextBlock Margin="0,16,0,8" FontSize="20" FontWeight="Bold" Text="{DynamicResource Text.WorkingCopy.Conflicts.Resolved}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
<TextBlock Text="{DynamicResource Text.WorkingCopy.CanStageTip}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/> <TextBlock Text="{DynamicResource Text.WorkingCopy.CanStageTip}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
</Border> </Border>
</DataTemplate> </DataTemplate>