diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index a6e1a4cf..0f275deb 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -243,6 +243,8 @@
Use Theirs (checkout --theirs)
Use Mine (checkout --ours)
File History
+ CONTENT
+ CHANGE
FILTER
Git-Flow
Development Branch:
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 94c92d53..16f0df3d 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -246,6 +246,8 @@
使用 THEIRS (checkout --theirs)
使用 MINE (checkout --ours)
文件历史
+ 文件内容
+ 文件变更
过滤
GIT工作流
开发分支 :
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index 8e35c100..193c25c4 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -246,6 +246,8 @@
使用 THEIRS (checkout --theirs)
使用 MINE (checkout --ours)
檔案歷史
+ 檔案内容
+ 檔案更改
過濾
GIT工作流
開發分支 :
diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs
index e1284b2f..68c5a7a1 100644
--- a/src/ViewModels/FileHistories.cs
+++ b/src/ViewModels/FileHistories.cs
@@ -1,11 +1,22 @@
using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
using System.Threading.Tasks;
+
+using Avalonia.Media.Imaging;
using Avalonia.Threading;
+
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
- public class FileHistories : ObservableObject
+ public class FileHistoriesRevisionFile(string path, object content)
+ {
+ public string Path { get; set; } = path;
+ public object Content { get; set; } = content;
+ }
+
+ public partial class FileHistories : ObservableObject
{
public bool IsLoading
{
@@ -25,38 +36,30 @@ namespace SourceGit.ViewModels
set
{
if (SetProperty(ref _selectedCommit, value))
- {
- if (value == null)
- {
- DiffContext = null;
- DetailContext.Commit = null;
- }
- else
- {
- DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(value, _file), _diffContext);
- DetailContext.Commit = value;
- }
- }
+ RefreshViewContent();
}
}
- public DiffContext DiffContext
+ public int ViewMode
{
- get => _diffContext;
- set => SetProperty(ref _diffContext, value);
+ get => _viewMode;
+ set
+ {
+ if (SetProperty(ref _viewMode, value))
+ RefreshViewContent();
+ }
}
- public CommitDetail DetailContext
+ public object ViewContent
{
- get => _detailContext;
- set => SetProperty(ref _detailContext, value);
+ get => _viewContent;
+ private set => SetProperty(ref _viewContent, value);
}
public FileHistories(Repository repo, string file)
{
_repo = repo;
_file = file;
- _detailContext = new CommitDetail(repo);
Task.Run(() =>
{
@@ -71,12 +74,122 @@ namespace SourceGit.ViewModels
});
}
+ public void NavigateToCommit(Models.Commit commit)
+ {
+ _repo.NavigateToCommit(commit.SHA);
+ }
+
+ private void RefreshViewContent()
+ {
+ if (_selectedCommit == null)
+ {
+ ViewContent = null;
+ return;
+ }
+
+ if (_viewMode == 0)
+ SetViewContentAsRevisionFile();
+ else
+ SetViewContentAsDiff();
+ }
+
+ private void SetViewContentAsRevisionFile()
+ {
+ var objs = new Commands.QueryRevisionObjects(_repo.FullPath, _selectedCommit.SHA, _file).Result();
+ if (objs.Count == 0)
+ {
+ ViewContent = new FileHistoriesRevisionFile(_file, null);
+ return;
+ }
+
+ var obj = objs[0];
+ switch (obj.Type)
+ {
+ case Models.ObjectType.Blob:
+ Task.Run(() =>
+ {
+ var isBinary = new Commands.IsBinary(_repo.FullPath, _selectedCommit.SHA, _file).Result();
+ if (isBinary)
+ {
+ var ext = Path.GetExtension(_file);
+ if (IMG_EXTS.Contains(ext))
+ {
+ var stream = Commands.QueryFileContent.Run(_repo.FullPath, _selectedCommit.SHA, _file);
+ var bitmap = stream.Length > 0 ? new Bitmap(stream) : null;
+ var image = new Models.RevisionImageFile() { Image = bitmap };
+ Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, image));
+ }
+ else
+ {
+ var size = new Commands.QueryFileSize(_repo.FullPath, _file, _selectedCommit.SHA).Result();
+ var binaryFile = new Models.RevisionBinaryFile() { Size = size };
+ Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, binaryFile));
+ }
+
+ return;
+ }
+
+ var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _selectedCommit.SHA, _file);
+ var content = new StreamReader(contentStream).ReadToEnd();
+ var matchLFS = REG_LFS_FORMAT().Match(content);
+ if (matchLFS.Success)
+ {
+ var lfs = new Models.RevisionLFSObject() { Object = new Models.LFSObject() };
+ lfs.Object.Oid = matchLFS.Groups[1].Value;
+ lfs.Object.Size = long.Parse(matchLFS.Groups[2].Value);
+ Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, lfs));
+ }
+ else
+ {
+ var txt = new Models.RevisionTextFile() { FileName = obj.Path, Content = content };
+ Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, txt));
+ }
+ });
+ break;
+ case Models.ObjectType.Commit:
+ Task.Run(() =>
+ {
+ var submoduleRoot = Path.Combine(_repo.FullPath, _file);
+ var commit = new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).Result();
+ if (commit != null)
+ {
+ var message = new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result();
+ var module = new Models.RevisionSubmodule() { Commit = commit, FullMessage = message };
+ Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
+ }
+ else
+ {
+ var module = new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = obj.SHA }, FullMessage = "" };
+ Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
+ }
+ });
+ break;
+ default:
+ ViewContent = new FileHistoriesRevisionFile(_file, null);
+ break;
+ }
+ }
+
+ private void SetViewContentAsDiff()
+ {
+ var option = new Models.DiffOption(_selectedCommit, _file);
+ ViewContent = new DiffContext(_repo.FullPath, option, _viewContent as DiffContext);
+ }
+
+ [GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
+ private static partial Regex REG_LFS_FORMAT();
+
+ private static readonly HashSet IMG_EXTS = new HashSet()
+ {
+ ".ico", ".bmp", ".jpg", ".png", ".jpeg"
+ };
+
private readonly Repository _repo = null;
private readonly string _file = null;
private bool _isLoading = true;
private List _commits = null;
private Models.Commit _selectedCommit = null;
- private DiffContext _diffContext = null;
- private CommitDetail _detailContext = null;
+ private int _viewMode = 0;
+ private object _viewContent = null;
}
}
diff --git a/src/Views/FileHistories.axaml b/src/Views/FileHistories.axaml
index 79e716c4..6c26fbd3 100644
--- a/src/Views/FileHistories.axaml
+++ b/src/Views/FileHistories.axaml
@@ -22,7 +22,7 @@
-
-
+
@@ -104,40 +111,106 @@
HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsLoading}"/>
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Views/FileHistories.axaml.cs b/src/Views/FileHistories.axaml.cs
index fc525f14..dad2baa9 100644
--- a/src/Views/FileHistories.axaml.cs
+++ b/src/Views/FileHistories.axaml.cs
@@ -27,5 +27,16 @@ namespace SourceGit.Views
e.Handled = true;
}
+
+ private void OnPressCommitSHA(object sender, PointerPressedEventArgs e)
+ {
+ if (sender is TextBlock { DataContext: Models.Commit commit } &&
+ DataContext is ViewModels.FileHistories vm)
+ {
+ vm.NavigateToCommit(commit);
+ }
+
+ e.Handled = true;
+ }
}
}
diff --git a/src/Views/RevisionFileContentViewer.axaml b/src/Views/RevisionFileContentViewer.axaml
new file mode 100644
index 00000000..eef7605c
--- /dev/null
+++ b/src/Views/RevisionFileContentViewer.axaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Views/RevisionFileContentViewer.axaml.cs b/src/Views/RevisionFileContentViewer.axaml.cs
new file mode 100644
index 00000000..bca6a082
--- /dev/null
+++ b/src/Views/RevisionFileContentViewer.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia.Controls;
+
+namespace SourceGit.Views
+{
+ public partial class RevisionFileContentViewer : UserControl
+ {
+ public RevisionFileContentViewer()
+ {
+ InitializeComponent();
+ }
+ }
+}
+
diff --git a/src/Views/RevisionFiles.axaml b/src/Views/RevisionFiles.axaml
index bbdd5841..0165ccab 100644
--- a/src/Views/RevisionFiles.axaml
+++ b/src/Views/RevisionFiles.axaml
@@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
@@ -28,56 +27,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+