Skip to content

Commit d4723ee

Browse files
committed
feature: supports show commit histories under selected folder (#1470)
Signed-off-by: leo <[email protected]>
1 parent f62eb88 commit d4723ee

12 files changed

+516
-83
lines changed

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@
303303
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Increase Number of Visible Lines</x:String>
304304
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECT FILE TO VIEW CHANGES</x:String>
305305
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">Open in Merge Tool</x:String>
306+
<x:String x:Key="Text.DirHistories" xml:space="preserve">Dir Histories</x:String>
306307
<x:String x:Key="Text.Discard" xml:space="preserve">Discard Changes</x:String>
307308
<x:String x:Key="Text.Discard.All" xml:space="preserve">All local changes in working copy.</x:String>
308309
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Changes:</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@
307307
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可见的行数</x:String>
308308
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">请选择需要对比的文件</x:String>
309309
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">使用外部比对工具查看</x:String>
310+
<x:String x:Key="Text.DirHistories" xml:space="preserve">目录内容变更历史</x:String>
310311
<x:String x:Key="Text.Discard" xml:space="preserve">放弃更改确认</x:String>
311312
<x:String x:Key="Text.Discard.All" xml:space="preserve">所有本地址未提交的修改。</x:String>
312313
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">变更 :</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@
307307
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可見的行數</x:String>
308308
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">請選擇需要對比的檔案</x:String>
309309
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">使用外部比對工具檢視</x:String>
310+
<x:String x:Key="Text.DirHistories" xml:space="preserve">目錄内容變更歷史</x:String>
310311
<x:String x:Key="Text.Discard" xml:space="preserve">捨棄變更</x:String>
311312
<x:String x:Key="Text.Discard.All" xml:space="preserve">所有本機未提交的變更。</x:String>
312313
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">變更:</x:String>

src/ViewModels/CommitDetail.cs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,85 @@ public Task OpenRevisionFileWithDefaultEditor(string file)
296296
});
297297
}
298298

299+
public ContextMenu CreateChangeContextMenuByFolder(ChangeTreeNode node, List<Models.Change> changes)
300+
{
301+
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, node.FullPath);
302+
var explore = new MenuItem();
303+
explore.Header = App.Text("RevealFile");
304+
explore.Icon = App.CreateMenuIcon("Icons.Explore");
305+
explore.IsEnabled = Directory.Exists(fullPath);
306+
explore.Click += (_, ev) =>
307+
{
308+
Native.OS.OpenInFileManager(fullPath, true);
309+
ev.Handled = true;
310+
};
311+
312+
var history = new MenuItem();
313+
history.Header = App.Text("DirHistories");
314+
history.Icon = App.CreateMenuIcon("Icons.Histories");
315+
history.Click += (_, ev) =>
316+
{
317+
App.ShowWindow(new DirHistories(_repo, node.FullPath, _commit.SHA), false);
318+
ev.Handled = true;
319+
};
320+
321+
var patch = new MenuItem();
322+
patch.Header = App.Text("FileCM.SaveAsPatch");
323+
patch.Icon = App.CreateMenuIcon("Icons.Diff");
324+
patch.Click += async (_, e) =>
325+
{
326+
var storageProvider = App.GetStorageProvider();
327+
if (storageProvider == null)
328+
return;
329+
330+
var options = new FilePickerSaveOptions();
331+
options.Title = App.Text("FileCM.SaveAsPatch");
332+
options.DefaultExtension = ".patch";
333+
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
334+
335+
var baseRevision = _commit.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : _commit.Parents[0];
336+
var storageFile = await storageProvider.SaveFilePickerAsync(options);
337+
if (storageFile != null)
338+
{
339+
var saveTo = storageFile.Path.LocalPath;
340+
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessRevisionCompareChanges(_repo.FullPath, changes, baseRevision, _commit.SHA, saveTo));
341+
if (succ)
342+
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
343+
}
344+
345+
e.Handled = true;
346+
};
347+
348+
var copyPath = new MenuItem();
349+
copyPath.Header = App.Text("CopyPath");
350+
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
351+
copyPath.Click += (_, ev) =>
352+
{
353+
App.CopyText(node.FullPath);
354+
ev.Handled = true;
355+
};
356+
357+
var copyFullPath = new MenuItem();
358+
copyFullPath.Header = App.Text("CopyFullPath");
359+
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
360+
copyFullPath.Click += (_, e) =>
361+
{
362+
App.CopyText(fullPath);
363+
e.Handled = true;
364+
};
365+
366+
var menu = new ContextMenu();
367+
menu.Items.Add(explore);
368+
menu.Items.Add(new MenuItem { Header = "-" });
369+
menu.Items.Add(history);
370+
menu.Items.Add(patch);
371+
menu.Items.Add(new MenuItem { Header = "-" });
372+
menu.Items.Add(copyPath);
373+
menu.Items.Add(copyFullPath);
374+
375+
return menu;
376+
}
377+
299378
public ContextMenu CreateChangeContextMenu(Models.Change change)
300379
{
301380
var diffWithMerger = new MenuItem();
@@ -428,8 +507,61 @@ public ContextMenu CreateChangeContextMenu(Models.Change change)
428507
return menu;
429508
}
430509

510+
public ContextMenu CreateRevisionFileContextMenuByFolder(string path)
511+
{
512+
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, path);
513+
var explore = new MenuItem();
514+
explore.Header = App.Text("RevealFile");
515+
explore.Icon = App.CreateMenuIcon("Icons.Explore");
516+
explore.IsEnabled = Directory.Exists(fullPath);
517+
explore.Click += (_, ev) =>
518+
{
519+
Native.OS.OpenInFileManager(fullPath, true);
520+
ev.Handled = true;
521+
};
522+
523+
var history = new MenuItem();
524+
history.Header = App.Text("DirHistories");
525+
history.Icon = App.CreateMenuIcon("Icons.Histories");
526+
history.Click += (_, ev) =>
527+
{
528+
App.ShowWindow(new DirHistories(_repo, path, _commit.SHA), false);
529+
ev.Handled = true;
530+
};
531+
532+
var copyPath = new MenuItem();
533+
copyPath.Header = App.Text("CopyPath");
534+
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
535+
copyPath.Click += (_, ev) =>
536+
{
537+
App.CopyText(path);
538+
ev.Handled = true;
539+
};
540+
541+
var copyFullPath = new MenuItem();
542+
copyFullPath.Header = App.Text("CopyFullPath");
543+
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
544+
copyFullPath.Click += (_, e) =>
545+
{
546+
App.CopyText(fullPath);
547+
e.Handled = true;
548+
};
549+
550+
var menu = new ContextMenu();
551+
menu.Items.Add(explore);
552+
menu.Items.Add(new MenuItem() { Header = "-" });
553+
menu.Items.Add(history);
554+
menu.Items.Add(new MenuItem() { Header = "-" });
555+
menu.Items.Add(copyPath);
556+
menu.Items.Add(copyFullPath);
557+
return menu;
558+
}
559+
431560
public ContextMenu CreateRevisionFileContextMenu(Models.Object file)
432561
{
562+
if (file.Type == Models.ObjectType.Tree)
563+
return CreateRevisionFileContextMenuByFolder(file.Path);
564+
433565
var menu = new ContextMenu();
434566
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file.Path);
435567
var explore = new MenuItem();

src/ViewModels/DirHistories.cs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Avalonia.Threading;
4+
using CommunityToolkit.Mvvm.ComponentModel;
5+
6+
namespace SourceGit.ViewModels
7+
{
8+
public class DirHistories : ObservableObject
9+
{
10+
public string Title
11+
{
12+
get;
13+
}
14+
15+
public bool IsLoading
16+
{
17+
get => _isLoading;
18+
private set => SetProperty(ref _isLoading, value);
19+
}
20+
21+
public List<Models.Commit> Commits
22+
{
23+
get => _commits;
24+
private set => SetProperty(ref _commits, value);
25+
}
26+
27+
public Models.Commit SelectedCommit
28+
{
29+
get => _selectedCommit;
30+
set
31+
{
32+
if (SetProperty(ref _selectedCommit, value))
33+
Detail.Commit = value;
34+
}
35+
}
36+
37+
public CommitDetail Detail
38+
{
39+
get => _detail;
40+
private set => SetProperty(ref _detail, value);
41+
}
42+
43+
public DirHistories(Repository repo, string dir, string revision = null)
44+
{
45+
if (!string.IsNullOrEmpty(revision))
46+
Title = $"{dir} @ {revision}";
47+
else
48+
Title = dir;
49+
50+
_repo = repo;
51+
_detail = new CommitDetail(repo);
52+
53+
Task.Run(() =>
54+
{
55+
var commits = new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {revision??string.Empty} -- \"{dir}\"", false).Result();
56+
Dispatcher.UIThread.Invoke(() =>
57+
{
58+
Commits = commits;
59+
IsLoading = false;
60+
61+
if (commits.Count > 0)
62+
SelectedCommit = commits[0];
63+
});
64+
});
65+
}
66+
67+
public void NavigateToCommit(Models.Commit commit)
68+
{
69+
_repo.NavigateToCommit(commit.SHA);
70+
}
71+
72+
public string GetCommitFullMessage(Models.Commit commit)
73+
{
74+
var sha = commit.SHA;
75+
if (_cachedCommitFullMessage.TryGetValue(sha, out var msg))
76+
return msg;
77+
78+
msg = new Commands.QueryCommitFullMessage(_repo.FullPath, sha).Result();
79+
_cachedCommitFullMessage[sha] = msg;
80+
return msg;
81+
}
82+
83+
private Repository _repo = null;
84+
private bool _isLoading = true;
85+
private List<Models.Commit> _commits = [];
86+
private Models.Commit _selectedCommit = null;
87+
private CommitDetail _detail = null;
88+
private Dictionary<string, string> _cachedCommitFullMessage = new();
89+
}
90+
}

src/ViewModels/FileHistories.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@ private void RefreshViewContent()
238238

239239
public class FileHistories : ObservableObject
240240
{
241+
public string Title
242+
{
243+
get;
244+
}
245+
241246
public bool IsLoading
242247
{
243248
get => _isLoading;
@@ -264,6 +269,11 @@ public object ViewContent
264269

265270
public FileHistories(Repository repo, string file, string commit = null)
266271
{
272+
if (!string.IsNullOrEmpty(commit))
273+
Title = $"{file} @ {commit}";
274+
else
275+
Title = file;
276+
267277
_repo = repo;
268278

269279
Task.Run(() =>

0 commit comments

Comments
 (0)