mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-06-17 08:24:59 +00:00
parent
0ea4021a64
commit
ee4d8a6a0e
4 changed files with 182 additions and 130 deletions
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Threading;
|
||||
|
@ -10,10 +11,25 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
public class Blame : ObservableObject
|
||||
{
|
||||
public string Title
|
||||
public string FilePath
|
||||
{
|
||||
get => _title;
|
||||
private set => SetProperty(ref _title, value);
|
||||
get;
|
||||
}
|
||||
|
||||
public Models.Commit Revision
|
||||
{
|
||||
get => _revision;
|
||||
private set => SetProperty(ref _revision, value);
|
||||
}
|
||||
|
||||
public Models.BlameData Data
|
||||
{
|
||||
get => _data;
|
||||
private set
|
||||
{
|
||||
if (SetProperty(ref _data, value))
|
||||
OnPropertyChanged(nameof(IsBinary));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsBinary
|
||||
|
@ -21,92 +37,27 @@ namespace SourceGit.ViewModels
|
|||
get => _data != null && _data.IsBinary;
|
||||
}
|
||||
|
||||
public bool CanMoveBack
|
||||
public bool CanBack
|
||||
{
|
||||
get => _shaHistoryIndex > 0 && _shaHistory.Count > 1;
|
||||
}
|
||||
public bool CanMoveForward
|
||||
{
|
||||
get => _shaHistoryIndex < _shaHistory.Count - 1;
|
||||
get => _navigationActiveIndex > 0;
|
||||
}
|
||||
|
||||
public Models.BlameData Data
|
||||
public bool CanForward
|
||||
{
|
||||
get => _data;
|
||||
private set => SetProperty(ref _data, value);
|
||||
get => _navigationActiveIndex < _navigationHistory.Count - 1;
|
||||
}
|
||||
|
||||
public Blame(string repo, string file, string revision)
|
||||
public Blame(string repo, string file, Models.Commit commit)
|
||||
{
|
||||
var sha = commit.SHA.Substring(0, 10);
|
||||
|
||||
FilePath = file;
|
||||
Revision = commit;
|
||||
|
||||
_repo = repo;
|
||||
_file = file;
|
||||
|
||||
SetBlameData($"{revision.AsSpan(0, 10)}", true);
|
||||
}
|
||||
|
||||
private void SetBlameData(string commitSHA, bool resetHistoryForward)
|
||||
{
|
||||
Title = $"{_file} @ {commitSHA}";
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var result = new Commands.Blame(_repo, _file, commitSHA).Result();
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
Data = result;
|
||||
OnPropertyChanged(nameof(IsBinary));
|
||||
});
|
||||
});
|
||||
|
||||
if (resetHistoryForward)
|
||||
{
|
||||
if (_shaHistoryIndex < _shaHistory.Count - 1)
|
||||
_shaHistory.RemoveRange(_shaHistoryIndex + 1, _shaHistory.Count - _shaHistoryIndex - 1);
|
||||
|
||||
if (_shaHistory.Count == 0 || _shaHistory[_shaHistoryIndex] != commitSHA)
|
||||
{
|
||||
_shaHistory.Add(commitSHA);
|
||||
_shaHistoryIndex = _shaHistory.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(CanMoveBack));
|
||||
OnPropertyChanged(nameof(CanMoveForward));
|
||||
}
|
||||
|
||||
public void Back()
|
||||
{
|
||||
--_shaHistoryIndex;
|
||||
if (_shaHistoryIndex < 0)
|
||||
_shaHistoryIndex = 0;
|
||||
|
||||
NavigateToCommit(_shaHistory[_shaHistoryIndex], false);
|
||||
}
|
||||
|
||||
public void Forward()
|
||||
{
|
||||
++_shaHistoryIndex;
|
||||
if (_shaHistoryIndex >= _shaHistory.Count)
|
||||
_shaHistoryIndex = _shaHistory.Count - 1;
|
||||
|
||||
NavigateToCommit(_shaHistory[_shaHistoryIndex], false);
|
||||
}
|
||||
|
||||
public void NavigateToCommit(string commitSHA, bool resetHistoryForward)
|
||||
{
|
||||
var launcher = App.GetLauncher();
|
||||
if (launcher == null)
|
||||
return;
|
||||
|
||||
foreach (var page in launcher.Pages)
|
||||
{
|
||||
if (page.Data is Repository repo && repo.FullPath.Equals(_repo))
|
||||
{
|
||||
repo.NavigateToCommit(commitSHA);
|
||||
SetBlameData(commitSHA, resetHistoryForward);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_navigationHistory.Add(sha);
|
||||
_commits.Add(sha, commit);
|
||||
SetBlameData(sha);
|
||||
}
|
||||
|
||||
public string GetCommitMessage(string sha)
|
||||
|
@ -119,12 +70,102 @@ namespace SourceGit.ViewModels
|
|||
return msg;
|
||||
}
|
||||
|
||||
public void Back()
|
||||
{
|
||||
if (_navigationActiveIndex <= 0)
|
||||
return;
|
||||
|
||||
_navigationActiveIndex--;
|
||||
OnPropertyChanged(nameof(CanBack));
|
||||
OnPropertyChanged(nameof(CanForward));
|
||||
NavigateToCommit(_navigationHistory[_navigationActiveIndex]);
|
||||
}
|
||||
|
||||
public void Forward()
|
||||
{
|
||||
if (_navigationActiveIndex >= _navigationHistory.Count - 1)
|
||||
return;
|
||||
|
||||
_navigationActiveIndex++;
|
||||
OnPropertyChanged(nameof(CanBack));
|
||||
OnPropertyChanged(nameof(CanForward));
|
||||
NavigateToCommit(_navigationHistory[_navigationActiveIndex]);
|
||||
}
|
||||
|
||||
public void NavigateToCommit(string commitSHA)
|
||||
{
|
||||
if (!_navigationHistory[_navigationActiveIndex].Equals(commitSHA, StringComparison.Ordinal))
|
||||
{
|
||||
_navigationHistory.Add(commitSHA);
|
||||
_navigationActiveIndex = _navigationHistory.Count - 1;
|
||||
OnPropertyChanged(nameof(CanBack));
|
||||
OnPropertyChanged(nameof(CanForward));
|
||||
}
|
||||
|
||||
if (!Revision.SHA.StartsWith(commitSHA, StringComparison.Ordinal))
|
||||
SetBlameData(commitSHA);
|
||||
|
||||
if (App.GetLauncher() is { Pages: { } pages })
|
||||
{
|
||||
foreach (var page in pages)
|
||||
{
|
||||
if (page.Data is Repository repo && repo.FullPath.Equals(_repo))
|
||||
{
|
||||
repo.NavigateToCommit(commitSHA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBlameData(string commitSHA)
|
||||
{
|
||||
if (_cancellationSource is { IsCancellationRequested: false })
|
||||
_cancellationSource.Cancel();
|
||||
|
||||
_cancellationSource = new CancellationTokenSource();
|
||||
var token = _cancellationSource.Token;
|
||||
|
||||
if (_commits.TryGetValue(commitSHA, out var c))
|
||||
{
|
||||
Revision = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
var result = new Commands.QuerySingleCommit(_repo, commitSHA).Result();
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
_commits.Add(commitSHA, result);
|
||||
Revision = result ?? new Models.Commit() { SHA = commitSHA };
|
||||
}
|
||||
});
|
||||
}, token);
|
||||
}
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var result = new Commands.Blame(_repo, FilePath, commitSHA).Result();
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (!token.IsCancellationRequested)
|
||||
Data = result;
|
||||
});
|
||||
}, token);
|
||||
}
|
||||
|
||||
private string _repo;
|
||||
private string _file;
|
||||
private string _title;
|
||||
private int _shaHistoryIndex = 0;
|
||||
private List<string> _shaHistory = [];
|
||||
private Models.Commit _revision;
|
||||
private CancellationTokenSource _cancellationSource = null;
|
||||
private int _navigationActiveIndex = 0;
|
||||
private List<string> _navigationHistory = [];
|
||||
private Models.BlameData _data = null;
|
||||
private Dictionary<string, string> _commitMessages = new Dictionary<string, string>();
|
||||
private Dictionary<string, Models.Commit> _commits = new();
|
||||
private Dictionary<string, string> _commitMessages = new();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,7 +313,7 @@ namespace SourceGit.ViewModels
|
|||
blame.IsEnabled = change.Index != Models.ChangeState.Deleted;
|
||||
blame.Click += (_, ev) =>
|
||||
{
|
||||
App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit.SHA), false);
|
||||
App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit), false);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -481,7 +481,7 @@ namespace SourceGit.ViewModels
|
|||
blame.IsEnabled = file.Type == Models.ObjectType.Blob;
|
||||
blame.Click += (_, ev) =>
|
||||
{
|
||||
App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit.SHA), false);
|
||||
App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit), false);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.Blame"
|
||||
x:DataType="vm:Blame"
|
||||
|
@ -43,22 +44,44 @@
|
|||
|
||||
<!-- File -->
|
||||
<Border Grid.Row="1" Padding="8,0" >
|
||||
<Grid>
|
||||
<TextBlock Text="{Binding Title}" VerticalAlignment="Center"/>
|
||||
<StackPanel HorizontalAlignment="Right" VerticalAlignment="Center" Orientation="Horizontal">
|
||||
<Button Classes="icon_button"
|
||||
IsEnabled="{Binding CanMoveBack}"
|
||||
<Grid ColumnDefinitions="Auto,*,Auto,Auto,400">
|
||||
<Path Grid.Column="0"
|
||||
Width="14" Height="14"
|
||||
Data="{StaticResource Icons.File}"/>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Margin="4,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding FilePath, Mode=OneWay}"/>
|
||||
|
||||
<Button Grid.Column="2"
|
||||
Classes="icon_button"
|
||||
IsEnabled="{Binding CanBack}"
|
||||
Width="28"
|
||||
Click="HistoryBack">
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.TriangleLeft}"/>
|
||||
Command="{Binding Back}">
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.TriangleLeft}"/>
|
||||
</Button>
|
||||
<Button Classes="icon_button"
|
||||
IsEnabled="{Binding CanMoveForward}"
|
||||
|
||||
<Button Grid.Column="3"
|
||||
Classes="icon_button"
|
||||
IsEnabled="{Binding CanForward}"
|
||||
Width="28"
|
||||
Click="HistoryForward">
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.TriangleRight}"/>
|
||||
Command="{Binding Forward}">
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.TriangleRight}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<Border Grid.Column="4" Background="#40000000" CornerRadius="3" Padding="4,0" Margin="0,2">
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Column="0"
|
||||
FontWeight="Bold"
|
||||
Margin="0,0,6,0"
|
||||
Text="{Binding Revision.SHA, Converter={x:Static c:StringConverters.ToShortSHA}, Mode=OneWay}"/>
|
||||
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding Revision.Subject}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
|
|
|
@ -224,9 +224,7 @@ namespace SourceGit.Views
|
|||
if (rect.Contains(pos))
|
||||
{
|
||||
if (DataContext is ViewModels.Blame blame)
|
||||
{
|
||||
blame.NavigateToCommit(info.CommitSHA, true);
|
||||
}
|
||||
blame.NavigateToCommit(info.CommitSHA);
|
||||
|
||||
e.Handled = true;
|
||||
break;
|
||||
|
@ -433,8 +431,6 @@ namespace SourceGit.Views
|
|||
public Blame()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
AddHandler(PointerReleasedEvent, MouseUpHandler, handledEventsToo: true);
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
|
@ -443,30 +439,22 @@ namespace SourceGit.Views
|
|||
GC.Collect();
|
||||
}
|
||||
|
||||
private void HistoryBack(object _, RoutedEventArgs e)
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Blame blame)
|
||||
{
|
||||
blame.Back();
|
||||
}
|
||||
}
|
||||
private void HistoryForward(object _, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Blame blame)
|
||||
{
|
||||
blame.Forward();
|
||||
}
|
||||
}
|
||||
base.OnPointerReleased(e);
|
||||
|
||||
private void MouseUpHandler(object sender, PointerReleasedEventArgs e)
|
||||
if (!e.Handled && DataContext is ViewModels.Blame blame)
|
||||
{
|
||||
if (e.InitialPressMouseButton == MouseButton.XButton1)
|
||||
{
|
||||
HistoryBack(null, null);
|
||||
blame.Back();
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.InitialPressMouseButton == MouseButton.XButton2)
|
||||
{
|
||||
HistoryForward(null, null);
|
||||
blame.Forward();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue