From 56a332f64ae3f5913e3ad8b7c1773ee9af65967a Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 20 Oct 2025 11:56:51 +0800 Subject: [PATCH] feature: supports to goto previous revision (not in undo/redo history, but the file itself) in `Blame` view (#1686) Signed-off-by: leo --- src/Resources/Icons.axaml | 1 + src/Resources/Locales/de_DE.axaml | 2 +- src/Resources/Locales/en_US.axaml | 3 +- src/Resources/Locales/es_ES.axaml | 2 +- src/Resources/Locales/fr_FR.axaml | 2 +- src/Resources/Locales/id_ID.axaml | 2 +- src/Resources/Locales/it_IT.axaml | 2 +- src/Resources/Locales/ja_JP.axaml | 2 +- src/Resources/Locales/pt_BR.axaml | 2 +- src/Resources/Locales/ru_RU.axaml | 2 +- src/Resources/Locales/ta_IN.axaml | 2 +- src/Resources/Locales/uk_UA.axaml | 2 +- src/Resources/Locales/zh_CN.axaml | 3 +- src/Resources/Locales/zh_TW.axaml | 3 +- src/ViewModels/Blame.cs | 57 +++++++++++++++++++------------ src/Views/Blame.axaml | 13 +++++-- 16 files changed, 64 insertions(+), 36 deletions(-) diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index 3103e68f..ea1530a5 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -59,6 +59,7 @@ M884 159l-18-18a43 43 0 00-38-12l-235 43a166 166 0 00-101 60L400 349a128 128 0 00-148 47l-120 171a21 21 0 005 29l17 12a128 128 0 00178-32l27-38 124 124-38 27a128 128 0 00-32 178l12 17a21 21 0 0029 5l171-120a128 128 0 0047-148l117-92A166 166 0 00853 431l43-235a43 43 0 00-12-38zm-177 249a64 64 0 110-90 64 64 0 010 90zm-373 312a21 21 0 010 30l-139 139a21 21 0 01-30 0l-30-30a21 21 0 010-30l139-139a21 21 0 0130 0z M525 0C235 0 0 235 0 525c0 232 150 429 359 498 26 5 36-11 36-25 0-12-1-54-1-97-146 31-176-63-176-63-23-61-58-76-58-76-48-32 3-32 3-32 53 3 81 54 81 54 47 80 123 57 153 43 4-34 18-57 33-70-116-12-239-57-239-259 0-57 21-104 54-141-5-13-23-67 5-139 0 0 44-14 144 54 42-11 87-17 131-17s90 6 131 17C756 203 801 217 801 217c29 72 10 126 5 139 34 37 54 83 54 141 0 202-123 246-240 259 19 17 36 48 36 97 0 70-1 127-1 144 0 14 10 30 36 25 209-70 359-266 359-498C1050 235 814 0 525 0z M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z + M727 641c-78 0-142 55-157 128H256V320h251c16 108 108 192 221 192 124 0 224-100 224-224S851 64 727 64c-113 0-205 84-221 192H96c-18 0-32 14-32 32s14 32 32 32h96v482c0 18 14 32 32 32h347c15 73 79 128 157 128 88 0 160-72 160-160s-72-160-160-160zm0 256c-53 0-96-43-96-96s43-96 96-96 96 43 96 96-43 96-96 96z M30 271l241 0 0-241-241 0 0 241zM392 271l241 0 0-241-241 0 0 241zM753 30l0 241 241 0 0-241-241 0zM30 632l241 0 0-241-241 0 0 241zM392 632l241 0 0-241-241 0 0 241zM753 632l241 0 0-241-241 0 0 241zM30 994l241 0 0-241-241 0 0 241zM392 994l241 0 0-241-241 0 0 241zM753 994l241 0 0-241-241 0 0 241z M566 585l37-146-145 0-37 146 145 0zM1005 297l-32 128q-4 14-18 14l-187 0-37 146 178 0q9 0 14 7 6 8 3 16l-32 128q-3 14-18 14l-187 0-46 187q-4 14-18 14l-128 0q-9 0-15-7-5-7-3-16l45-178-145 0-46 187q-4 14-18 14l-129 0q-9 0-14-7-5-7-3-16l45-178-178 0q-9 0-14-7-5-7-3-16l32-128q4-14 18-14l187 0 37-146-178 0q-9 0-14-7-6-8-3-16l32-128q3-14 18-14l187 0 46-187q4-14 18-14l128 0q9 0 14 7 5 7 3 16l-45 178 145 0 46-187q4-14 18-14l128 0q9 0 14 7 5 7 3 16l-45 178 178 0q9 0 14 7 5 7 3 16z M0 512M1024 512M512 0M512 1024M955 323q0 23-16 39l-414 414-78 78q-16 16-39 16t-39-16l-78-78-207-207q-16-16-16-39t16-39l78-78q16-16 39-16t39 16l168 169 375-375q16-16 39-16t39 16l78 78q16 16 16 39z diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index c770bdcf..0eb6a90f 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -56,7 +56,7 @@ Überspringen Bisecting. Aktuellen Commit als gut oder schlecht markieren und einen anderen auschecken. Blame - BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!! + BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!! Auschecken von ${0}$... Mit ${0}$ vergleichen Mit Worktree vergleichen diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index c0c465ae..1b978bc5 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -52,7 +52,8 @@ Skip Bisecting. Mark current commit as good or bad and checkout another one. Blame - BLAME ON THIS FILE IS NOT SUPPORTED!!! + Blame on Previous Revision + BLAME ON THIS FILE IS NOT SUPPORTED!!! Checkout ${0}$... Compare with ${0}$ Compare with Worktree diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index 76c6748e..16131682 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -56,7 +56,7 @@ Saltar Bisecting. Marcar el commit actual como bueno o malo y revisar otro. Blame - ¡BLAME EN ESTE ARCHIVO NO SOPORTADO! + ¡BLAME EN ESTE ARCHIVO NO SOPORTADO! Checkout ${0}$... Comparar con ${0}$ Comparar con Worktree diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 2052f93a..ceebf736 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -41,7 +41,7 @@ Rafraîchir FICHIER BINAIRE NON SUPPORTÉ !!! Blâme - LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!! + LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!! Récupérer ${0}$... Comparer avec ${0}$ Comparer avec le worktree diff --git a/src/Resources/Locales/id_ID.axaml b/src/Resources/Locales/id_ID.axaml index 19601f7c..1e8a6c69 100644 --- a/src/Resources/Locales/id_ID.axaml +++ b/src/Resources/Locales/id_ID.axaml @@ -55,7 +55,7 @@ Lewati Bisect berjalan. Tandai commit saat ini sebagai baik atau buruk dan checkout yang lain. Blame - BLAME PADA BERKAS INI TIDAK DIDUKUNG!!! + BLAME PADA BERKAS INI TIDAK DIDUKUNG!!! Checkout ${0}$... Bandingkan dengan ${0}$ Bandingkan dengan Worktree diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index f726f598..3ddab9fe 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -55,7 +55,7 @@ Salta Bisecando. Marca il commit corrente come buono o cattivo e fai checkout di un altro. Attribuisci - L'ATTRIBUZIONE SU QUESTO FILE NON È SUPPORTATA!!! + L'ATTRIBUZIONE SU QUESTO FILE NON È SUPPORTATA!!! Checkout ${0}$... Confronta con ${0}$ Confronta con Worktree diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml index 958ceb9f..6d772308 100644 --- a/src/Resources/Locales/ja_JP.axaml +++ b/src/Resources/Locales/ja_JP.axaml @@ -41,7 +41,7 @@ 更新 バイナリファイルはサポートされていません!!! Blame - BLAMEではこのファイルはサポートされていません!!! + BLAMEではこのファイルはサポートされていません!!! ${0}$ をチェックアウトする... ワークツリーと比較 ブランチ名をコピー diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index 24569a93..04ececee 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -35,7 +35,7 @@ Atualizar ARQUIVO BINÁRIO NÃO SUPORTADO!!! Blame - BLAME NESTE ARQUIVO NÃO É SUPORTADO!!! + BLAME NESTE ARQUIVO NÃO É SUPORTADO!!! Checkout ${0}$... Comparar com ${0}$ Comparar com Worktree diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 9d0eb5b1..56db5457 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -56,7 +56,7 @@ Пропустить Раздвоение. Сделать текущую ревизию хорошей или плохой и переключиться на другой. Расследование - РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!! + РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!! Переключиться на ${0}$... Сравнить с ${0}$ Сравнить с рабочим каталогом diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml index e98dfc05..8c102934 100644 --- a/src/Resources/Locales/ta_IN.axaml +++ b/src/Resources/Locales/ta_IN.axaml @@ -41,7 +41,7 @@ புதுப்பி இருமம் கோப்பு ஆதரிக்கப்படவில்லை!!! குற்றச்சாட்டு - இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!! + இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!! ${0}$ சரிபார்... பணிமரத்துடன் ஒப்பிடுக கிளை பெயரை நகலெடு diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml index 6b91933e..7c5814eb 100644 --- a/src/Resources/Locales/uk_UA.axaml +++ b/src/Resources/Locales/uk_UA.axaml @@ -41,7 +41,7 @@ Оновити БІНАРНИЙ ФАЙЛ НЕ ПІДТРИМУЄТЬСЯ!!! Автор рядка - ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!! + ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!! Перейти на ${0}$... Порівняти з ${0}$ Порівняти з робочим деревом diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 94a2d5da..8700104d 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -56,7 +56,8 @@ 无法判定 二分定位进行中。请标记当前的提交是 '正确' 还是 '错误',然后检出另一个提交。 逐行追溯(blame) - 选中文件不支持该操作!!! + 对当前版本的前一版本执行逐行追溯操作 + 选中文件不支持该操作!!! 检出(checkout) ${0}$... 与当前 ${0}$ 比较 与本地工作树比较 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 9aa98f5c..29cd3807 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -56,7 +56,8 @@ 無法確認 二分搜尋進行中。請標記目前的提交為「良好」或「錯誤」,然後簽出另一個提交。 逐行溯源 (blame) - 所選擇的檔案不支援該操作! + 對當前版本的先前版本執行逐行溯源操作。 + 所選擇的檔案不支援該操作! 簽出 (checkout) ${0}$... 與目前 ${0}$ 比較 與本機工作區比較 diff --git a/src/ViewModels/Blame.cs b/src/ViewModels/Blame.cs index e8b01e41..fda29964 100644 --- a/src/ViewModels/Blame.cs +++ b/src/ViewModels/Blame.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text; using System.Threading; using System.Threading.Tasks; using Avalonia.Threading; @@ -20,6 +21,12 @@ namespace SourceGit.ViewModels private set => SetProperty(ref _revision, value); } + public Models.Commit PrevRevision + { + get => _prevRevision; + private set => SetProperty(ref _prevRevision, value); + } + public Models.BlameData Data { get => _data; @@ -51,10 +58,10 @@ namespace SourceGit.ViewModels FilePath = file; Revision = commit; + PrevRevision = null; _repo = repo; _navigationHistory.Add(sha); - _commits.Add(sha, commit); SetBlameData(sha); } @@ -90,6 +97,14 @@ namespace SourceGit.ViewModels NavigateToCommit(_navigationHistory[_navigationActiveIndex], true); } + public void GotoPrevRevision() + { + if (_prevRevision == null) + return; + + NavigateToCommit(_prevRevision.SHA, false); + } + public void NavigateToCommit(string commitSHA, bool isBackOrForward) { if (Revision.SHA.StartsWith(commitSHA, StringComparison.Ordinal)) @@ -130,28 +145,28 @@ namespace SourceGit.ViewModels _cancellationSource = new CancellationTokenSource(); var token = _cancellationSource.Token; - if (_commits.TryGetValue(commitSHA, out var c)) + Task.Run(async () => { - Revision = c; - } - else - { - Task.Run(async () => - { - var result = await new Commands.QuerySingleCommit(_repo, commitSHA) - .GetResultAsync() - .ConfigureAwait(false); + var argsBuilder = new StringBuilder(); + argsBuilder + .Append("--date-order -n 2 ") + .Append(commitSHA ?? string.Empty) + .Append(" -- ") + .Append(FilePath.Quoted()); - Dispatcher.UIThread.Post(() => + var commits = await new Commands.QueryCommits(_repo, argsBuilder.ToString(), false) + .GetResultAsync() + .ConfigureAwait(false); + + Dispatcher.UIThread.Post(() => + { + if (!token.IsCancellationRequested) { - if (!token.IsCancellationRequested) - { - _commits.Add(commitSHA, result); - Revision = result ?? new Models.Commit() { SHA = commitSHA }; - } - }); - }, token); - } + Revision = commits.Count > 0 ? commits[0] : null; + PrevRevision = commits.Count == 2 ? commits[1] : null; + } + }); + }); Task.Run(async () => { @@ -169,11 +184,11 @@ namespace SourceGit.ViewModels private string _repo; private Models.Commit _revision; + private Models.Commit _prevRevision; private CancellationTokenSource _cancellationSource = null; private int _navigationActiveIndex = 0; private List _navigationHistory = []; private Models.BlameData _data = null; - private Dictionary _commits = new(); private Dictionary _commitMessages = new(); } } diff --git a/src/Views/Blame.axaml b/src/Views/Blame.axaml index bd8a2f81..af27d356 100644 --- a/src/Views/Blame.axaml +++ b/src/Views/Blame.axaml @@ -38,7 +38,7 @@ - + @@ -76,6 +76,15 @@ TextTrimming="CharacterEllipsis"/> + + @@ -107,7 +116,7 @@ HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="{Binding IsBinary}"> - +