mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-06-22 10:55:00 +00:00
Merge branch 'sourcegit-scm:develop' into develop
This commit is contained in:
commit
26e6231acf
24 changed files with 300 additions and 64 deletions
|
@ -47,7 +47,7 @@
|
|||
|
||||
## Translation Status
|
||||
|
||||
[](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md)
|
||||
[](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md)
|
||||
|
||||
> [!NOTE]
|
||||
> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md)
|
||||
|
@ -132,7 +132,7 @@ For **Linux** users:
|
|||
|
||||
## OpenAI
|
||||
|
||||
This software supports using OpenAI or other AI service that has an OpenAI comaptible HTTP API to generate commit message. You need configurate the service in `Preference` window.
|
||||
This software supports using OpenAI or other AI service that has an OpenAI compatible HTTP API to generate commit message. You need configurate the service in `Preference` window.
|
||||
|
||||
For `OpenAI`:
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
### de_DE.axaml: 99.60%
|
||||
### de_DE.axaml: 99.21%
|
||||
|
||||
|
||||
<details>
|
||||
|
@ -6,40 +6,26 @@
|
|||
|
||||
- Text.BranchUpstreamInvalid
|
||||
- Text.Configure.CustomAction.WaitForExit
|
||||
- Text.Diff.First
|
||||
- Text.Diff.Last
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.StashCM.SaveAsPatch
|
||||
|
||||
</details>
|
||||
|
||||
### es_ES.axaml: 97.35%
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Missing Keys</summary>
|
||||
|
||||
- Text.AIAssistant.Regen
|
||||
- Text.AIAssistant.Use
|
||||
- Text.ApplyStash
|
||||
- Text.ApplyStash.DropAfterApply
|
||||
- Text.ApplyStash.RestoreIndex
|
||||
- Text.ApplyStash.Stash
|
||||
- Text.BranchCM.CustomAction
|
||||
- Text.BranchUpstreamInvalid
|
||||
- Text.Clone.RecurseSubmodules
|
||||
- Text.Configure.CustomAction.Scope.Branch
|
||||
- Text.Configure.CustomAction.WaitForExit
|
||||
- Text.CreateBranch.Name.WarnSpace
|
||||
- Text.DeleteRepositoryNode.Path
|
||||
- Text.DeleteRepositoryNode.TipForGroup
|
||||
- Text.DeleteRepositoryNode.TipForRepository
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.Repository.Notifications.Clear
|
||||
- Text.Stash.AutoRestore
|
||||
- Text.Stash.AutoRestore.Tip
|
||||
- Text.WorkingCopy.SignOff
|
||||
|
||||
</details>
|
||||
|
||||
### fr_FR.axaml: 92.18%
|
||||
### es_ES.axaml: 99.60%
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Missing Keys</summary>
|
||||
|
||||
- Text.Diff.First
|
||||
- Text.Diff.Last
|
||||
- Text.StashCM.SaveAsPatch
|
||||
|
||||
</details>
|
||||
|
||||
### fr_FR.axaml: 91.81%
|
||||
|
||||
|
||||
<details>
|
||||
|
@ -60,6 +46,8 @@
|
|||
- Text.DeleteRepositoryNode.Path
|
||||
- Text.DeleteRepositoryNode.TipForGroup
|
||||
- Text.DeleteRepositoryNode.TipForRepository
|
||||
- Text.Diff.First
|
||||
- Text.Diff.Last
|
||||
- Text.InProgress.CherryPick.Head
|
||||
- Text.InProgress.Merge.Operating
|
||||
- Text.InProgress.Rebase.StoppedAt
|
||||
|
@ -102,12 +90,13 @@
|
|||
- Text.SHALinkCM.NavigateTo
|
||||
- Text.Stash.AutoRestore
|
||||
- Text.Stash.AutoRestore.Tip
|
||||
- Text.StashCM.SaveAsPatch
|
||||
- Text.WorkingCopy.CommitToEdit
|
||||
- Text.WorkingCopy.SignOff
|
||||
|
||||
</details>
|
||||
|
||||
### it_IT.axaml: 97.61%
|
||||
### it_IT.axaml: 97.23%
|
||||
|
||||
|
||||
<details>
|
||||
|
@ -127,14 +116,17 @@
|
|||
- Text.DeleteRepositoryNode.Path
|
||||
- Text.DeleteRepositoryNode.TipForGroup
|
||||
- Text.DeleteRepositoryNode.TipForRepository
|
||||
- Text.Diff.First
|
||||
- Text.Diff.Last
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.Repository.Notifications.Clear
|
||||
- Text.Stash.AutoRestore
|
||||
- Text.Stash.AutoRestore.Tip
|
||||
- Text.StashCM.SaveAsPatch
|
||||
|
||||
</details>
|
||||
|
||||
### pt_BR.axaml: 91.91%
|
||||
### pt_BR.axaml: 91.55%
|
||||
|
||||
|
||||
<details>
|
||||
|
@ -162,6 +154,8 @@
|
|||
- Text.DeleteRepositoryNode.Path
|
||||
- Text.DeleteRepositoryNode.TipForGroup
|
||||
- Text.DeleteRepositoryNode.TipForRepository
|
||||
- Text.Diff.First
|
||||
- Text.Diff.Last
|
||||
- Text.Diff.UseBlockNavigation
|
||||
- Text.Fetch.Force
|
||||
- Text.FileCM.ResolveUsing
|
||||
|
@ -199,12 +193,13 @@
|
|||
- Text.SHALinkCM.NavigateTo
|
||||
- Text.Stash.AutoRestore
|
||||
- Text.Stash.AutoRestore.Tip
|
||||
- Text.StashCM.SaveAsPatch
|
||||
- Text.WorkingCopy.CommitToEdit
|
||||
- Text.WorkingCopy.SignOff
|
||||
|
||||
</details>
|
||||
|
||||
### ru_RU.axaml: 99.47%
|
||||
### ru_RU.axaml: 99.08%
|
||||
|
||||
|
||||
<details>
|
||||
|
@ -213,7 +208,10 @@
|
|||
- Text.BranchCM.CustomAction
|
||||
- Text.BranchUpstreamInvalid
|
||||
- Text.Configure.CustomAction.Scope.Branch
|
||||
- Text.Diff.First
|
||||
- Text.Diff.Last
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.StashCM.SaveAsPatch
|
||||
|
||||
</details>
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2025.05
|
||||
2025.06
|
|
@ -37,6 +37,19 @@ namespace SourceGit.Commands
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool ProcessStashChanges(string repo, List<Models.DiffOption> opts, string saveTo)
|
||||
{
|
||||
using (var sw = File.Create(saveTo))
|
||||
{
|
||||
foreach (var opt in opts)
|
||||
{
|
||||
if (!ProcessSingleChange(repo, opt, sw))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool ProcessSingleChange(string repo, Models.DiffOption opt, FileStream writer)
|
||||
{
|
||||
var starter = new ProcessStartInfo();
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace SourceGit.Models
|
|||
{
|
||||
if (startIdx > 0)
|
||||
OnReceive(buffer.Substring(0, startIdx));
|
||||
|
||||
|
||||
var endIdx = buffer.IndexOf(">", startIdx + 1, StringComparison.Ordinal);
|
||||
if (endIdx <= startIdx)
|
||||
{
|
||||
|
|
|
@ -65,13 +65,16 @@ namespace SourceGit.Native
|
|||
{
|
||||
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
var cwd = string.IsNullOrEmpty(workdir) ? home : workdir;
|
||||
var terminal = OS.ShellOrTerminal;
|
||||
|
||||
var startInfo = new ProcessStartInfo();
|
||||
startInfo.WorkingDirectory = cwd;
|
||||
startInfo.FileName = OS.ShellOrTerminal;
|
||||
startInfo.FileName = terminal;
|
||||
|
||||
if (OS.ShellOrTerminal.EndsWith("wezterm", StringComparison.OrdinalIgnoreCase))
|
||||
if (terminal.EndsWith("wezterm", StringComparison.OrdinalIgnoreCase))
|
||||
startInfo.Arguments = $"start --cwd \"{cwd}\"";
|
||||
else if (terminal.EndsWith("ptyxis", StringComparison.OrdinalIgnoreCase))
|
||||
startInfo.Arguments = $"--working-directory=\"{cwd}\"";
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<StreamGeometry x:Key="Icons.Binary">M71 1024V0h661L953 219V1024H71zm808-731-220-219H145V951h735V293zM439 512h-220V219h220V512zm-74-219H292v146h74v-146zm0 512h74v73h-220v-73H292v-146H218V585h147v219zm294-366h74V512H512v-73h74v-146H512V219h147v219zm74 439H512V585h220v293zm-74-219h-74v146h74v-146z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Blame">M128 256h192a64 64 0 110 128H128a64 64 0 110-128zm576 192h192a64 64 0 010 128h-192a64 64 0 010-128zm-576 192h192a64 64 0 010 128H128a64 64 0 010-128zm576 0h192a64 64 0 010 128h-192a64 64 0 010-128zm0-384h192a64 64 0 010 128h-192a64 64 0 010-128zM128 448h192a64 64 0 110 128H128a64 64 0 110-128zm384-320a64 64 0 0164 64v640a64 64 0 01-128 0V192a64 64 0 0164-64z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Bookmark">M832 64H192c-18 0-32 14-32 32v832c0 18 14 32 32 32h640c18 0 32-14 32-32V96c0-18-14-32-32-32zM736 596 624 502 506 596V131h230v318z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Bottom">M509 546 780 275 871 366 509 728 147 366 238 275zM509 728h-362v128h724v-128z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Branch">M757 226a143 143 0 00-55 276 96 96 0 01-88 59h-191a187 187 0 00-96 27V312a143 143 0 10-96 0v399a143 143 0 10103 2 96 96 0 0188-59h191a191 191 0 00187-151 143 143 0 00-43-279zM280 130a48 48 0 110 96 48 48 0 010-96zm0 764a48 48 0 110-96 48 48 0 010 96zM757 417a48 48 0 110-96 48 48 0 010 96z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Branch.Add">M896 128h-64V64c0-35-29-64-64-64s-64 29-64 64v64h-64c-35 0-64 29-64 64s29 64 64 64h64v64c0 35 29 64 64 64s64-29 64-64V256h64c35 0 64-29 64-64s-29-64-64-64zm-204 307C673 481 628 512 576 512H448c-47 0-90 13-128 35V372C394 346 448 275 448 192c0-106-86-192-192-192S64 86 64 192c0 83 54 154 128 180v280c-74 26-128 97-128 180c0 106 86 192 192 192s192-86 192-192c0-67-34-125-84-159c22-20 52-33 84-33h128c122 0 223-85 249-199c-19 4-37 7-57 7c-26 0-51-5-76-13zM256 128c35 0 64 29 64 64s-29 64-64 64s-64-29-64-64s29-64 64-64zm0 768c-35 0-64-29-64-64s29-64 64-64s64 29 64 64s-29 64-64 64z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Check">M512 597m-1 0a1 1 0 103 0a1 1 0 10-3 0ZM810 393 732 315 448 600 293 444 214 522l156 156 78 78 362-362z</StreamGeometry>
|
||||
|
@ -119,6 +120,7 @@
|
|||
<StreamGeometry x:Key="Icons.Tags">M996 452 572 28A96 96 0 00504 0H96C43 0 0 43 0 96v408a96 96 0 0028 68l424 424c37 37 98 37 136 0l408-408c37-37 37-98 0-136zM224 320c-53 0-96-43-96-96s43-96 96-96 96 43 96 96-43 96-96 96zm1028 268L844 996c-37 37-98 37-136 0l-1-1L1055 647c34-34 53-79 53-127s-19-93-53-127L663 0h97a96 96 0 0168 28l424 424c37 37 37 98 0 136z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Target">M765 118 629 239l-16 137-186 160 54 59 183-168 144 4 136-129 47-43-175-12L827 67zM489 404c-66 0-124 55-124 125s54 121 124 121c66 0 120-55 120-121H489l23-121c-8-4-16-4-23-4zM695 525c0 114-93 207-206 207s-206-94-206-207 93-207 206-207c16 0 27 0 43 4l43-207c-27-4-54-8-85-8-229 0-416 188-416 419s187 419 416 419c225 0 408-180 416-403v-12l-210-4z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Terminal">M144 112h736c18 0 32 14 32 32v736c0 18-14 32-32 32H144c-18 0-32-14-32-32V144c0-18 14-32 32-32zm112 211v72a9 9 0 003 7L386 509 259 615a9 9 0 00-3 7v72a9 9 0 0015 7L493 516a9 9 0 000-14l-222-186a9 9 0 00-15 7zM522 624a10 10 0 00-10 10v60a10 10 0 0010 10h237a10 10 0 0010-10v-60a10 10 0 00-10-10H522z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Top">M170 831 513 489 855 831 960 726 512 278 64 726 170 831zM512 278h448v-128h-896v128h448z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Track">M897 673v13c0 51-42 93-93 93h-10c-1 0-2 0-2 0H220c-23 0-42 19-42 42v13c0 23 19 42 42 42h552c14 0 26 12 26 26 0 14-12 26-26 26H220c-51 0-93-42-93-93v-13c0-51 42-93 93-93h20c1-0 2-0 2-0h562c23 0 42-19 42-42v-13c0-11-5-22-13-29-8-7-17-11-28-10H660c-14 0-26-12-26-26 0-14 12-26 26-26h144c24-1 47 7 65 24 18 17 29 42 29 67zM479 98c-112 0-203 91-203 203 0 44 14 85 38 118l132 208c15 24 50 24 66 0l133-209c23-33 37-73 37-117 0-112-91-203-203-203zm0 327c-68 0-122-55-122-122s55-122 122-122 122 55 122 122-55 122-122 122z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Tree">M912 800a48 48 0 1 1 0 96h-416a48 48 0 1 1 0-96h416z m-704-704A112 112 0 0 1 256 309.184V480h80a48 48 0 0 1 0 96H256v224h81.664a48 48 0 1 1 0 96H256a96 96 0 0 1-96-96V309.248A112 112 0 0 1 208 96z m704 384a48 48 0 1 1 0 96h-416a48 48 0 0 1 0-96h416z m0-320a48 48 0 1 1 0 96h-416a48 48 0 0 1 0-96h416z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.TriangleLeft">M30 0 30 30 0 15z</StreamGeometry>
|
||||
|
|
|
@ -250,7 +250,9 @@
|
|||
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">OLD</x:String>
|
||||
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">Copy</x:String>
|
||||
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">File Mode Changed</x:String>
|
||||
<x:String x:Key="Text.Diff.First" xml:space="preserve">First Difference</x:String>
|
||||
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">Ignore Whitespace Change</x:String>
|
||||
<x:String x:Key="Text.Diff.Last" xml:space="preserve">Last Difference</x:String>
|
||||
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS OBJECT CHANGE</x:String>
|
||||
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Next Difference</x:String>
|
||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">NO CHANGES OR ONLY EOL CHANGES</x:String>
|
||||
|
@ -667,6 +669,7 @@
|
|||
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Apply</x:String>
|
||||
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Drop</x:String>
|
||||
<x:String x:Key="Text.StashCM.Pop" xml:space="preserve">Pop</x:String>
|
||||
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Save as Patch...</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Drop Stash</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Drop:</x:String>
|
||||
<x:String x:Key="Text.Stashes" xml:space="preserve">STASHES</x:String>
|
||||
|
|
|
@ -253,7 +253,9 @@
|
|||
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">原始大小</x:String>
|
||||
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">复制</x:String>
|
||||
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">文件权限已变化</x:String>
|
||||
<x:String x:Key="Text.Diff.First" xml:space="preserve">首个差异</x:String>
|
||||
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">忽略空白符号变化</x:String>
|
||||
<x:String x:Key="Text.Diff.Last" xml:space="preserve">最后一个差异</x:String>
|
||||
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS对象变更</x:String>
|
||||
<x:String x:Key="Text.Diff.Next" xml:space="preserve">下一个差异</x:String>
|
||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">没有变更或仅有换行符差异</x:String>
|
||||
|
@ -671,6 +673,7 @@
|
|||
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">应用(apply)</x:String>
|
||||
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">删除(drop)</x:String>
|
||||
<x:String x:Key="Text.StashCM.Pop" xml:space="preserve">应用并删除(pop)</x:String>
|
||||
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">另存为补丁...</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">丢弃贮藏确认</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">丢弃贮藏 :</x:String>
|
||||
<x:String x:Key="Text.Stashes" xml:space="preserve">贮藏列表</x:String>
|
||||
|
|
|
@ -253,7 +253,9 @@
|
|||
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">原始大小</x:String>
|
||||
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">複製</x:String>
|
||||
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">檔案權限已變更</x:String>
|
||||
<x:String x:Key="Text.Diff.First" xml:space="preserve">第一個差異</x:String>
|
||||
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">忽略空白符號變化</x:String>
|
||||
<x:String x:Key="Text.Diff.Last" xml:space="preserve">最後一個差異</x:String>
|
||||
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS 物件變更</x:String>
|
||||
<x:String x:Key="Text.Diff.Next" xml:space="preserve">下一個差異</x:String>
|
||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">沒有變更或僅有換行字元差異</x:String>
|
||||
|
@ -670,6 +672,7 @@
|
|||
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">套用 (apply)</x:String>
|
||||
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">刪除 (drop)</x:String>
|
||||
<x:String x:Key="Text.StashCM.Pop" xml:space="preserve">套用並刪除 (pop)</x:String>
|
||||
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">另存為修補檔 (patch)...</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">捨棄擱置變更確認</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">捨棄擱置變更:</x:String>
|
||||
<x:String x:Key="Text.Stashes" xml:space="preserve">擱置變更</x:String>
|
||||
|
|
|
@ -101,12 +101,12 @@ namespace SourceGit.ViewModels
|
|||
return (_current >= 0 && _current < Blocks.Count) ? Blocks[_current] : null;
|
||||
}
|
||||
|
||||
public Block GotoNext()
|
||||
public Block GotoFirst()
|
||||
{
|
||||
if (Blocks.Count == 0)
|
||||
return null;
|
||||
|
||||
Current = (_current + 1) % Blocks.Count;
|
||||
Current = 0;
|
||||
return Blocks[_current];
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,29 @@ namespace SourceGit.ViewModels
|
|||
if (Blocks.Count == 0)
|
||||
return null;
|
||||
|
||||
Current = _current == -1 ? Blocks.Count - 1 : (_current - 1 + Blocks.Count) % Blocks.Count;
|
||||
if (_current == -1)
|
||||
Current = 0;
|
||||
else if (_current > 0)
|
||||
Current = _current - 1;
|
||||
return Blocks[_current];
|
||||
}
|
||||
|
||||
public Block GotoNext()
|
||||
{
|
||||
if (Blocks.Count == 0)
|
||||
return null;
|
||||
|
||||
if (_current < Blocks.Count - 1)
|
||||
Current = _current + 1;
|
||||
return Blocks[_current];
|
||||
}
|
||||
|
||||
public Block GotoLast()
|
||||
{
|
||||
if (Blocks.Count == 0)
|
||||
return null;
|
||||
|
||||
Current = Blocks.Count - 1;
|
||||
return Blocks[_current];
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,15 @@ namespace SourceGit.ViewModels
|
|||
|
||||
public int ActivePageIndex
|
||||
{
|
||||
get => _activePageIndex;
|
||||
set => SetProperty(ref _activePageIndex, value);
|
||||
get => _repo.CommitDetailActivePageIndex;
|
||||
set
|
||||
{
|
||||
if (_repo.CommitDetailActivePageIndex != value)
|
||||
{
|
||||
_repo.CommitDetailActivePageIndex = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Models.Commit Commit
|
||||
|
@ -617,11 +624,7 @@ namespace SourceGit.ViewModels
|
|||
_changes = null;
|
||||
_revisionFiles.Clear();
|
||||
|
||||
FullMessage = string.Empty;
|
||||
SignInfo = null;
|
||||
Changes = [];
|
||||
VisibleChanges = null;
|
||||
SelectedChanges = null;
|
||||
ViewRevisionFileContent = null;
|
||||
Children.Clear();
|
||||
RevisionFileSearchFilter = string.Empty;
|
||||
|
@ -821,7 +824,6 @@ namespace SourceGit.ViewModels
|
|||
};
|
||||
|
||||
private Repository _repo = null;
|
||||
private int _activePageIndex = 0;
|
||||
private Models.Commit _commit = null;
|
||||
private string _fullMessage = string.Empty;
|
||||
private Models.CommitSignInfo _signInfo = null;
|
||||
|
|
|
@ -453,6 +453,12 @@ namespace SourceGit.ViewModels
|
|||
private set => SetProperty(ref _isAutoFetching, value);
|
||||
}
|
||||
|
||||
public int CommitDetailActivePageIndex
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = 0;
|
||||
|
||||
public Repository(bool isBare, string path, string gitDir)
|
||||
{
|
||||
IsBare = isBare;
|
||||
|
@ -657,6 +663,12 @@ namespace SourceGit.ViewModels
|
|||
return;
|
||||
}
|
||||
|
||||
if (_currentBranch == null)
|
||||
{
|
||||
App.RaiseException(_fullpath, "Can NOT found current branch!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
var pull = new Pull(this, null);
|
||||
if (autoStart && pull.SelectedBranch != null)
|
||||
ShowAndStartPopup(pull);
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.IO;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
@ -88,7 +89,7 @@ namespace SourceGit.ViewModels
|
|||
private set
|
||||
{
|
||||
if (SetProperty(ref _changes, value))
|
||||
SelectedChange = null;
|
||||
SelectedChange = value is { Count: >0 } ? value[0] : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,9 +158,45 @@ namespace SourceGit.ViewModels
|
|||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var patch = new MenuItem();
|
||||
patch.Header = App.Text("StashCM.SaveAsPatch");
|
||||
patch.Icon = App.CreateMenuIcon("Icons.Diff");
|
||||
patch.Click += async (_, e) =>
|
||||
{
|
||||
var storageProvider = App.GetStorageProvider();
|
||||
if (storageProvider == null)
|
||||
return;
|
||||
|
||||
var options = new FilePickerSaveOptions();
|
||||
options.Title = App.Text("StashCM.SaveAsPatch");
|
||||
options.DefaultExtension = ".patch";
|
||||
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
|
||||
|
||||
var storageFile = await storageProvider.SaveFilePickerAsync(options);
|
||||
if (storageFile != null)
|
||||
{
|
||||
var opts = new List<Models.DiffOption>();
|
||||
foreach (var c in _changes)
|
||||
{
|
||||
if (_untrackedChanges.Contains(c.Path))
|
||||
opts.Add(new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], c));
|
||||
else
|
||||
opts.Add(new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, c));
|
||||
}
|
||||
|
||||
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessStashChanges(_repo.FullPath, opts, storageFile.Path.LocalPath));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
var menu = new ContextMenu();
|
||||
menu.Items.Add(apply);
|
||||
menu.Items.Add(drop);
|
||||
menu.Items.Add(new MenuItem { Header = "-" });
|
||||
menu.Items.Add(patch);
|
||||
return menu;
|
||||
}
|
||||
|
||||
|
|
|
@ -1466,7 +1466,7 @@ namespace SourceGit.ViewModels
|
|||
return unstaged;
|
||||
|
||||
var visible = new List<Models.Change>();
|
||||
|
||||
|
||||
foreach (var c in unstaged)
|
||||
{
|
||||
if (c.Path.Contains(_unstagedFilter, StringComparison.OrdinalIgnoreCase))
|
||||
|
|
|
@ -134,6 +134,7 @@
|
|||
<v:ChangeCollectionView ViewMode="{Binding Source={x:Static vm:Preferences.Instance}, Path=CommitChangeViewMode}"
|
||||
Changes="{Binding VisibleChanges}"
|
||||
SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}"
|
||||
AutoSelectFirstChange="True"
|
||||
ContextRequested="OnChangeContextRequested"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
|
|
@ -85,6 +85,15 @@ namespace SourceGit.Views
|
|||
set => SetValue(ChangesProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> AutoSelectFirstChangeProperty =
|
||||
AvaloniaProperty.Register<ChangeCollectionView, bool>(nameof(AutoSelectFirstChange), false);
|
||||
|
||||
public bool AutoSelectFirstChange
|
||||
{
|
||||
get => GetValue(AutoSelectFirstChangeProperty);
|
||||
set => SetValue(AutoSelectFirstChangeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<List<Models.Change>> SelectedChangesProperty =
|
||||
AvaloniaProperty.Register<ChangeCollectionView, List<Models.Change>>(nameof(SelectedChanges));
|
||||
|
||||
|
@ -205,9 +214,9 @@ namespace SourceGit.Views
|
|||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == ViewModeProperty)
|
||||
UpdateDataSource(false);
|
||||
else if (change.Property == ChangesProperty)
|
||||
UpdateDataSource(true);
|
||||
else if (change.Property == ChangesProperty)
|
||||
UpdateDataSource(false);
|
||||
else if (change.Property == SelectedChangesProperty)
|
||||
UpdateSelection();
|
||||
}
|
||||
|
@ -292,9 +301,9 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
private void UpdateDataSource(bool disableEvents)
|
||||
private void UpdateDataSource(bool onlyViewModeChange)
|
||||
{
|
||||
_disableSelectionChangingEvent = disableEvents;
|
||||
_disableSelectionChangingEvent = !onlyViewModeChange;
|
||||
|
||||
var changes = Changes;
|
||||
if (changes == null || changes.Count == 0)
|
||||
|
@ -324,7 +333,19 @@ namespace SourceGit.Views
|
|||
MakeTreeRows(rows, tree.Tree);
|
||||
tree.Rows.AddRange(rows);
|
||||
|
||||
if (selected.Count > 0)
|
||||
if (!onlyViewModeChange && AutoSelectFirstChange)
|
||||
{
|
||||
foreach (var row in tree.Rows)
|
||||
{
|
||||
if (row.Change != null)
|
||||
{
|
||||
tree.SelectedRows.Add(row);
|
||||
SetCurrentValue(SelectedChangesProperty, [row.Change]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (selected.Count > 0)
|
||||
{
|
||||
var sets = new HashSet<Models.Change>();
|
||||
foreach (var c in selected)
|
||||
|
@ -346,16 +367,34 @@ namespace SourceGit.Views
|
|||
{
|
||||
var grid = new ViewModels.ChangeCollectionAsGrid();
|
||||
grid.Changes.AddRange(changes);
|
||||
if (selected.Count > 0)
|
||||
|
||||
if (!onlyViewModeChange && AutoSelectFirstChange)
|
||||
{
|
||||
grid.SelectedChanges.Add(changes[0]);
|
||||
SetCurrentValue(SelectedChangesProperty, [changes[0]]);
|
||||
}
|
||||
else if (selected.Count > 0)
|
||||
{
|
||||
grid.SelectedChanges.AddRange(selected);
|
||||
}
|
||||
|
||||
Content = grid;
|
||||
}
|
||||
else
|
||||
{
|
||||
var list = new ViewModels.ChangeCollectionAsList();
|
||||
list.Changes.AddRange(changes);
|
||||
if (selected.Count > 0)
|
||||
|
||||
if (!onlyViewModeChange && AutoSelectFirstChange)
|
||||
{
|
||||
list.SelectedChanges.Add(changes[0]);
|
||||
SetCurrentValue(SelectedChangesProperty, [changes[0]]);
|
||||
}
|
||||
else if (selected.Count > 0)
|
||||
{
|
||||
list.SelectedChanges.AddRange(selected);
|
||||
}
|
||||
|
||||
Content = list;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
ViewMode="{Binding Source={x:Static vm:Preferences.Instance}, Path=CommitChangeViewMode}"
|
||||
Changes="{Binding VisibleChanges}"
|
||||
SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}"
|
||||
AutoSelectFirstChange="True"
|
||||
ContextRequested="OnChangeContextRequested"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
|
|
@ -34,6 +34,19 @@
|
|||
|
||||
<!-- Toolbar Buttons -->
|
||||
<StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
Click="OnGotoFirstChange"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.First}">
|
||||
<Button.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="IsTextDiff"/>
|
||||
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseBlockNavigationInDiffView" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</Button.IsVisible>
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Top}"/>
|
||||
</Button>
|
||||
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
Click="OnGotoPrevChange"
|
||||
|
@ -61,6 +74,19 @@
|
|||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
|
||||
</Button>
|
||||
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
Click="OnGotoLastChange"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.Last}">
|
||||
<Button.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="IsTextDiff"/>
|
||||
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseBlockNavigationInDiffView" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</Button.IsVisible>
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Bottom}"/>
|
||||
</Button>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="28"
|
||||
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=TwoWay}"
|
||||
|
|
|
@ -11,6 +11,13 @@ namespace SourceGit.Views
|
|||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnGotoFirstChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
var textDiff = this.FindDescendantOfType<TextDiffView>();
|
||||
textDiff?.GotoFirstChange();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnGotoPrevChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
var textDiff = this.FindDescendantOfType<TextDiffView>();
|
||||
|
@ -24,5 +31,12 @@ namespace SourceGit.Views
|
|||
textDiff?.GotoNextChange();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnGotoLastChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
var textDiff = this.FindDescendantOfType<TextDiffView>();
|
||||
textDiff?.GotoLastChange();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
|
||||
public static readonly RoutedEvent<LauncherTabSelectedEventArgs> PageSelectedEvent =
|
||||
RoutedEvent.Register<ChangeCollectionView, LauncherTabSelectedEventArgs>(nameof(PageSelected), RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
|
||||
RoutedEvent.Register<LauncherTabsSelector, LauncherTabSelectedEventArgs>(nameof(PageSelected), RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
|
||||
|
||||
public event EventHandler<LauncherTabSelectedEventArgs> PageSelected
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ namespace SourceGit.Views
|
|||
|
||||
private void OnPageSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is ListBox { SelectedItem : ViewModels.LauncherPage page })
|
||||
if (sender is ListBox { SelectedItem: ViewModels.LauncherPage page })
|
||||
{
|
||||
_isProcessingSelection = true;
|
||||
RaiseEvent(new LauncherTabSelectedEventArgs(page));
|
||||
|
@ -88,7 +88,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
if (_isProcessingSelection)
|
||||
return;
|
||||
|
||||
|
||||
VisiblePages.Clear();
|
||||
|
||||
if (Pages == null)
|
||||
|
|
|
@ -522,7 +522,7 @@ namespace SourceGit.Views
|
|||
|
||||
private void OnRemoveSelectedHistoriesFilter(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter})
|
||||
if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter })
|
||||
repo.RemoveHistoriesFilter(filter);
|
||||
|
||||
e.Handled = true;
|
||||
|
|
|
@ -99,6 +99,7 @@
|
|||
<v:ChangeCollectionView ViewMode="{Binding Source={x:Static vm:Preferences.Instance}, Path=CommitChangeViewMode}"
|
||||
Changes="{Binding VisibleChanges}"
|
||||
SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}"
|
||||
AutoSelectFirstChange="True"
|
||||
ContextRequested="OnChangeContextRequested"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
|
|
@ -543,6 +543,21 @@ namespace SourceGit.Views
|
|||
{
|
||||
}
|
||||
|
||||
public void GotoFirstChange()
|
||||
{
|
||||
var blockNavigation = BlockNavigation;
|
||||
if (blockNavigation != null)
|
||||
{
|
||||
var prev = blockNavigation.GotoFirst();
|
||||
if (prev != null)
|
||||
{
|
||||
TextArea.Caret.Line = prev.Start;
|
||||
ScrollToLine(prev.Start);
|
||||
}
|
||||
}
|
||||
// NOTE: Not implemented (button hidden) for non-block navigation.
|
||||
}
|
||||
|
||||
public void GotoPrevChange()
|
||||
{
|
||||
var blockNavigation = BlockNavigation;
|
||||
|
@ -641,6 +656,21 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
public void GotoLastChange()
|
||||
{
|
||||
var blockNavigation = BlockNavigation;
|
||||
if (blockNavigation != null)
|
||||
{
|
||||
var next = blockNavigation.GotoLast();
|
||||
if (next != null)
|
||||
{
|
||||
TextArea.Caret.Line = next.Start;
|
||||
ScrollToLine(next.Start);
|
||||
}
|
||||
}
|
||||
// NOTE: Not implemented (button hidden) for non-block navigation.
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
|
@ -976,7 +1006,7 @@ namespace SourceGit.Views
|
|||
|
||||
if (startPosition.Location > endPosition.Location)
|
||||
(startPosition, endPosition) = (endPosition, startPosition);
|
||||
|
||||
|
||||
var startIdx = Math.Min(startPosition.Line - 1, lines.Count - 1);
|
||||
var endIdx = Math.Min(endPosition.Line - 1, lines.Count - 1);
|
||||
|
||||
|
@ -1682,6 +1712,19 @@ namespace SourceGit.Views
|
|||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void GotoFirstChange()
|
||||
{
|
||||
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||
if (presenter == null)
|
||||
return;
|
||||
|
||||
presenter.GotoFirstChange();
|
||||
if (presenter is SingleSideTextDiffPresenter singleSide)
|
||||
singleSide.ForceSyncScrollOffset();
|
||||
|
||||
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
|
||||
}
|
||||
|
||||
public void GotoPrevChange()
|
||||
{
|
||||
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||
|
@ -1708,6 +1751,19 @@ namespace SourceGit.Views
|
|||
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
|
||||
}
|
||||
|
||||
public void GotoLastChange()
|
||||
{
|
||||
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||
if (presenter == null)
|
||||
return;
|
||||
|
||||
presenter.GotoLastChange();
|
||||
if (presenter is SingleSideTextDiffPresenter singleSide)
|
||||
singleSide.ForceSyncScrollOffset();
|
||||
|
||||
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue