mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-22 04:34:59 +00:00
Merge branch 'release/v2025.06'
This commit is contained in:
commit
fb6b57bdf5
36 changed files with 590 additions and 240 deletions
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
## Translation Status
|
## 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]
|
> [!NOTE]
|
||||||
> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md)
|
> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md)
|
||||||
|
@ -132,7 +132,7 @@ For **Linux** users:
|
||||||
|
|
||||||
## OpenAI
|
## 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`:
|
For `OpenAI`:
|
||||||
|
|
||||||
|
|
|
@ -1,44 +1,29 @@
|
||||||
### de_DE.axaml: 99.47%
|
### de_DE.axaml: 99.34%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing Keys</summary>
|
<summary>Missing Keys</summary>
|
||||||
|
|
||||||
- Text.BranchCM.CustomAction
|
- Text.BranchUpstreamInvalid
|
||||||
- Text.Configure.CustomAction.Scope.Branch
|
|
||||||
- Text.Configure.CustomAction.WaitForExit
|
- Text.Configure.CustomAction.WaitForExit
|
||||||
- Text.Repository.Notifications.Clear
|
- Text.Diff.First
|
||||||
|
- Text.Diff.Last
|
||||||
|
- Text.Preferences.AI.Streaming
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### es_ES.axaml: 97.61%
|
### es_ES.axaml: 99.74%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing Keys</summary>
|
<summary>Missing Keys</summary>
|
||||||
|
|
||||||
- Text.AIAssistant.Regen
|
- Text.Diff.First
|
||||||
- Text.AIAssistant.Use
|
- Text.Diff.Last
|
||||||
- Text.ApplyStash
|
|
||||||
- Text.ApplyStash.DropAfterApply
|
</details>
|
||||||
- Text.ApplyStash.RestoreIndex
|
|
||||||
- Text.ApplyStash.Stash
|
### fr_FR.axaml: 91.93%
|
||||||
- Text.BranchCM.CustomAction
|
|
||||||
- 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.Repository.Notifications.Clear
|
|
||||||
- Text.Stash.AutoRestore
|
|
||||||
- Text.Stash.AutoRestore.Tip
|
|
||||||
- Text.WorkingCopy.SignOff
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### fr_FR.axaml: 92.42%
|
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -51,6 +36,7 @@
|
||||||
- Text.ApplyStash.RestoreIndex
|
- Text.ApplyStash.RestoreIndex
|
||||||
- Text.ApplyStash.Stash
|
- Text.ApplyStash.Stash
|
||||||
- Text.BranchCM.CustomAction
|
- Text.BranchCM.CustomAction
|
||||||
|
- Text.BranchUpstreamInvalid
|
||||||
- Text.Clone.RecurseSubmodules
|
- Text.Clone.RecurseSubmodules
|
||||||
- Text.Configure.CustomAction.Scope.Branch
|
- Text.Configure.CustomAction.Scope.Branch
|
||||||
- Text.Configure.CustomAction.WaitForExit
|
- Text.Configure.CustomAction.WaitForExit
|
||||||
|
@ -58,6 +44,8 @@
|
||||||
- Text.DeleteRepositoryNode.Path
|
- Text.DeleteRepositoryNode.Path
|
||||||
- Text.DeleteRepositoryNode.TipForGroup
|
- Text.DeleteRepositoryNode.TipForGroup
|
||||||
- Text.DeleteRepositoryNode.TipForRepository
|
- Text.DeleteRepositoryNode.TipForRepository
|
||||||
|
- Text.Diff.First
|
||||||
|
- Text.Diff.Last
|
||||||
- Text.InProgress.CherryPick.Head
|
- Text.InProgress.CherryPick.Head
|
||||||
- Text.InProgress.Merge.Operating
|
- Text.InProgress.Merge.Operating
|
||||||
- Text.InProgress.Rebase.StoppedAt
|
- Text.InProgress.Rebase.StoppedAt
|
||||||
|
@ -67,6 +55,7 @@
|
||||||
- Text.MergeMultiple.CommitChanges
|
- Text.MergeMultiple.CommitChanges
|
||||||
- Text.MergeMultiple.Strategy
|
- Text.MergeMultiple.Strategy
|
||||||
- Text.MergeMultiple.Targets
|
- Text.MergeMultiple.Targets
|
||||||
|
- Text.Preferences.AI.Streaming
|
||||||
- Text.Preferences.Appearance.FontSize
|
- Text.Preferences.Appearance.FontSize
|
||||||
- Text.Preferences.Appearance.FontSize.Default
|
- Text.Preferences.Appearance.FontSize.Default
|
||||||
- Text.Preferences.Appearance.FontSize.Editor
|
- Text.Preferences.Appearance.FontSize.Editor
|
||||||
|
@ -104,7 +93,7 @@
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### it_IT.axaml: 97.87%
|
### it_IT.axaml: 97.35%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -117,19 +106,23 @@
|
||||||
- Text.ApplyStash.RestoreIndex
|
- Text.ApplyStash.RestoreIndex
|
||||||
- Text.ApplyStash.Stash
|
- Text.ApplyStash.Stash
|
||||||
- Text.BranchCM.CustomAction
|
- Text.BranchCM.CustomAction
|
||||||
|
- Text.BranchUpstreamInvalid
|
||||||
- Text.Clone.RecurseSubmodules
|
- Text.Clone.RecurseSubmodules
|
||||||
- Text.Configure.CustomAction.Scope.Branch
|
- Text.Configure.CustomAction.Scope.Branch
|
||||||
- Text.Configure.CustomAction.WaitForExit
|
- Text.Configure.CustomAction.WaitForExit
|
||||||
- Text.DeleteRepositoryNode.Path
|
- Text.DeleteRepositoryNode.Path
|
||||||
- Text.DeleteRepositoryNode.TipForGroup
|
- Text.DeleteRepositoryNode.TipForGroup
|
||||||
- Text.DeleteRepositoryNode.TipForRepository
|
- Text.DeleteRepositoryNode.TipForRepository
|
||||||
|
- Text.Diff.First
|
||||||
|
- Text.Diff.Last
|
||||||
|
- Text.Preferences.AI.Streaming
|
||||||
- Text.Repository.Notifications.Clear
|
- Text.Repository.Notifications.Clear
|
||||||
- Text.Stash.AutoRestore
|
- Text.Stash.AutoRestore
|
||||||
- Text.Stash.AutoRestore.Tip
|
- Text.Stash.AutoRestore.Tip
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### pt_BR.axaml: 92.15%
|
### pt_BR.axaml: 91.67%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -143,6 +136,7 @@
|
||||||
- Text.ApplyStash.Stash
|
- Text.ApplyStash.Stash
|
||||||
- Text.BranchCM.CustomAction
|
- Text.BranchCM.CustomAction
|
||||||
- Text.BranchCM.MergeMultiBranches
|
- Text.BranchCM.MergeMultiBranches
|
||||||
|
- Text.BranchUpstreamInvalid
|
||||||
- Text.Clone.RecurseSubmodules
|
- Text.Clone.RecurseSubmodules
|
||||||
- Text.CommitCM.Merge
|
- Text.CommitCM.Merge
|
||||||
- Text.CommitCM.MergeMultiple
|
- Text.CommitCM.MergeMultiple
|
||||||
|
@ -156,6 +150,8 @@
|
||||||
- Text.DeleteRepositoryNode.Path
|
- Text.DeleteRepositoryNode.Path
|
||||||
- Text.DeleteRepositoryNode.TipForGroup
|
- Text.DeleteRepositoryNode.TipForGroup
|
||||||
- Text.DeleteRepositoryNode.TipForRepository
|
- Text.DeleteRepositoryNode.TipForRepository
|
||||||
|
- Text.Diff.First
|
||||||
|
- Text.Diff.Last
|
||||||
- Text.Diff.UseBlockNavigation
|
- Text.Diff.UseBlockNavigation
|
||||||
- Text.Fetch.Force
|
- Text.Fetch.Force
|
||||||
- Text.FileCM.ResolveUsing
|
- Text.FileCM.ResolveUsing
|
||||||
|
@ -169,6 +165,7 @@
|
||||||
- Text.MergeMultiple.CommitChanges
|
- Text.MergeMultiple.CommitChanges
|
||||||
- Text.MergeMultiple.Strategy
|
- Text.MergeMultiple.Strategy
|
||||||
- Text.MergeMultiple.Targets
|
- Text.MergeMultiple.Targets
|
||||||
|
- Text.Preferences.AI.Streaming
|
||||||
- Text.Preferences.General.DateFormat
|
- Text.Preferences.General.DateFormat
|
||||||
- Text.Preferences.General.ShowChildren
|
- Text.Preferences.General.ShowChildren
|
||||||
- Text.Preferences.Git.SSLVerify
|
- Text.Preferences.Git.SSLVerify
|
||||||
|
@ -197,14 +194,18 @@
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### ru_RU.axaml: 99.73%
|
### ru_RU.axaml: 99.21%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing Keys</summary>
|
<summary>Missing Keys</summary>
|
||||||
|
|
||||||
- Text.BranchCM.CustomAction
|
- Text.BranchCM.CustomAction
|
||||||
|
- Text.BranchUpstreamInvalid
|
||||||
- Text.Configure.CustomAction.Scope.Branch
|
- Text.Configure.CustomAction.Scope.Branch
|
||||||
|
- Text.Diff.First
|
||||||
|
- Text.Diff.Last
|
||||||
|
- Text.Preferences.AI.Streaming
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2025.05
|
2025.06
|
|
@ -12,7 +12,7 @@ namespace SourceGit.Commands
|
||||||
Args = includeUntracked ? "add ." : "add -u .";
|
Args = includeUntracked ? "add ." : "add -u .";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Add(string repo, List<Models.Change> changes)
|
public Add(string repo, List<string> changes)
|
||||||
{
|
{
|
||||||
WorkingDirectory = repo;
|
WorkingDirectory = repo;
|
||||||
Context = repo;
|
Context = repo;
|
||||||
|
@ -22,7 +22,7 @@ namespace SourceGit.Commands
|
||||||
foreach (var c in changes)
|
foreach (var c in changes)
|
||||||
{
|
{
|
||||||
builder.Append(" \"");
|
builder.Append(" \"");
|
||||||
builder.Append(c.Path);
|
builder.Append(c);
|
||||||
builder.Append("\"");
|
builder.Append("\"");
|
||||||
}
|
}
|
||||||
Args = builder.ToString();
|
Args = builder.ToString();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
@ -36,6 +35,8 @@ namespace SourceGit.Commands
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_onResponse?.Invoke("Waiting for pre-file analyzing to completed...\n\n");
|
||||||
|
|
||||||
var responseBuilder = new StringBuilder();
|
var responseBuilder = new StringBuilder();
|
||||||
var summaryBuilder = new StringBuilder();
|
var summaryBuilder = new StringBuilder();
|
||||||
foreach (var change in _changes)
|
foreach (var change in _changes)
|
||||||
|
@ -49,18 +50,17 @@ namespace SourceGit.Commands
|
||||||
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
|
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
|
||||||
if (rs.IsSuccess)
|
if (rs.IsSuccess)
|
||||||
{
|
{
|
||||||
var hasFirstValidChar = false;
|
|
||||||
var thinkingBuffer = new StringBuilder();
|
|
||||||
_service.Chat(
|
_service.Chat(
|
||||||
_service.AnalyzeDiffPrompt,
|
_service.AnalyzeDiffPrompt,
|
||||||
$"Here is the `git diff` output: {rs.StdOut}",
|
$"Here is the `git diff` output: {rs.StdOut}",
|
||||||
_cancelToken,
|
_cancelToken,
|
||||||
update =>
|
update =>
|
||||||
ProcessChatResponse(update, ref hasFirstValidChar, thinkingBuffer,
|
{
|
||||||
(responseBuilder, text =>
|
responseBuilder.Append(update);
|
||||||
_onResponse?.Invoke(
|
summaryBuilder.Append(update);
|
||||||
$"Waiting for pre-file analyzing to completed...\n\n{text}")),
|
|
||||||
(summaryBuilder, null)));
|
_onResponse?.Invoke($"Waiting for pre-file analyzing to completed...\n\n{responseBuilder}");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
responseBuilder.Append("\n");
|
responseBuilder.Append("\n");
|
||||||
|
@ -74,15 +74,15 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
var responseBody = responseBuilder.ToString();
|
var responseBody = responseBuilder.ToString();
|
||||||
var subjectBuilder = new StringBuilder();
|
var subjectBuilder = new StringBuilder();
|
||||||
var hasSubjectFirstValidChar = false;
|
|
||||||
var subjectThinkingBuffer = new StringBuilder();
|
|
||||||
_service.Chat(
|
_service.Chat(
|
||||||
_service.GenerateSubjectPrompt,
|
_service.GenerateSubjectPrompt,
|
||||||
$"Here are the summaries changes:\n{summaryBuilder}",
|
$"Here are the summaries changes:\n{summaryBuilder}",
|
||||||
_cancelToken,
|
_cancelToken,
|
||||||
update =>
|
update =>
|
||||||
ProcessChatResponse(update, ref hasSubjectFirstValidChar, subjectThinkingBuffer,
|
{
|
||||||
(subjectBuilder, text => _onResponse?.Invoke($"{text}\n\n{responseBody}"))));
|
subjectBuilder.Append(update);
|
||||||
|
_onResponse?.Invoke($"{subjectBuilder}\n\n{responseBody}");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -90,67 +90,10 @@ namespace SourceGit.Commands
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessChatResponse(
|
|
||||||
string update,
|
|
||||||
ref bool hasFirstValidChar,
|
|
||||||
StringBuilder thinkingBuffer,
|
|
||||||
params (StringBuilder builder, Action<string> callback)[] outputs)
|
|
||||||
{
|
|
||||||
if (!hasFirstValidChar)
|
|
||||||
{
|
|
||||||
update = update.TrimStart();
|
|
||||||
if (string.IsNullOrEmpty(update))
|
|
||||||
return;
|
|
||||||
if (update.StartsWith("<", StringComparison.Ordinal))
|
|
||||||
thinkingBuffer.Append(update);
|
|
||||||
hasFirstValidChar = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thinkingBuffer.Length > 0)
|
|
||||||
thinkingBuffer.Append(update);
|
|
||||||
|
|
||||||
if (thinkingBuffer.Length > 15)
|
|
||||||
{
|
|
||||||
var match = REG_COT.Match(thinkingBuffer.ToString());
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
update = REG_COT.Replace(thinkingBuffer.ToString(), "").TrimStart();
|
|
||||||
if (update.Length > 0)
|
|
||||||
{
|
|
||||||
foreach (var output in outputs)
|
|
||||||
output.builder.Append(update);
|
|
||||||
thinkingBuffer.Clear();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
match = REG_THINK_START.Match(thinkingBuffer.ToString());
|
|
||||||
if (!match.Success)
|
|
||||||
{
|
|
||||||
foreach (var output in outputs)
|
|
||||||
output.builder.Append(thinkingBuffer);
|
|
||||||
thinkingBuffer.Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thinkingBuffer.Length == 0)
|
|
||||||
{
|
|
||||||
foreach (var output in outputs)
|
|
||||||
{
|
|
||||||
output.builder.Append(update);
|
|
||||||
output.callback?.Invoke(output.builder.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Models.OpenAIService _service;
|
private Models.OpenAIService _service;
|
||||||
private string _repo;
|
private string _repo;
|
||||||
private List<Models.Change> _changes;
|
private List<Models.Change> _changes;
|
||||||
private CancellationToken _cancelToken;
|
private CancellationToken _cancelToken;
|
||||||
private Action<string> _onResponse;
|
private Action<string> _onResponse;
|
||||||
|
|
||||||
private static readonly Regex REG_COT = new(@"^<(think|thought|thinking|thought_chain)>(.*?)</\1>", RegexOptions.Singleline);
|
|
||||||
private static readonly Regex REG_THINK_START = new(@"^<(think|thought|thinking|thought_chain)>", RegexOptions.Singleline);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,22 @@ namespace SourceGit.Commands
|
||||||
return branches;
|
return branches;
|
||||||
|
|
||||||
var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var remoteBranches = new HashSet<string>();
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
{
|
||||||
var b = ParseLine(line);
|
var b = ParseLine(line);
|
||||||
if (b != null)
|
if (b != null)
|
||||||
|
{
|
||||||
branches.Add(b);
|
branches.Add(b);
|
||||||
|
if (!b.IsLocal)
|
||||||
|
remoteBranches.Add(b.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var b in branches)
|
||||||
|
{
|
||||||
|
if (b.IsLocal && !string.IsNullOrEmpty(b.Upstream))
|
||||||
|
b.IsUpsteamGone = !remoteBranches.Contains(b.Upstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
return branches;
|
return branches;
|
||||||
|
@ -75,6 +86,7 @@ namespace SourceGit.Commands
|
||||||
branch.Head = parts[1];
|
branch.Head = parts[1];
|
||||||
branch.IsCurrent = parts[2] == "*";
|
branch.IsCurrent = parts[2] == "*";
|
||||||
branch.Upstream = parts[3];
|
branch.Upstream = parts[3];
|
||||||
|
branch.IsUpsteamGone = false;
|
||||||
|
|
||||||
if (branch.IsLocal && !string.IsNullOrEmpty(parts[4]) && !parts[4].Equals("=", StringComparison.Ordinal))
|
if (branch.IsLocal && !string.IsNullOrEmpty(parts[4]) && !parts[4].Equals("=", StringComparison.Ordinal))
|
||||||
branch.TrackStatus = new QueryTrackStatus(WorkingDirectory, branch.Name, branch.Upstream).Result();
|
branch.TrackStatus = new QueryTrackStatus(WorkingDirectory, branch.Name, branch.Upstream).Result();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Avalonia.Data.Converters;
|
using Avalonia.Data.Converters;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
namespace SourceGit.Converters
|
namespace SourceGit.Converters
|
||||||
{
|
{
|
||||||
|
@ -6,5 +7,8 @@ namespace SourceGit.Converters
|
||||||
{
|
{
|
||||||
public static readonly FuncValueConverter<bool, double> ToPageTabWidth =
|
public static readonly FuncValueConverter<bool, double> ToPageTabWidth =
|
||||||
new FuncValueConverter<bool, double>(x => x ? 200 : double.NaN);
|
new FuncValueConverter<bool, double>(x => x ? 200 : double.NaN);
|
||||||
|
|
||||||
|
public static readonly FuncValueConverter<bool, FontWeight> IsBoldToFontWeight =
|
||||||
|
new FuncValueConverter<bool, FontWeight>(x => x ? FontWeight.Bold : FontWeight.Normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace SourceGit.Models
|
||||||
public string Upstream { get; set; }
|
public string Upstream { get; set; }
|
||||||
public BranchTrackStatus TrackStatus { get; set; }
|
public BranchTrackStatus TrackStatus { get; set; }
|
||||||
public string Remote { get; set; }
|
public string Remote { get; set; }
|
||||||
|
public bool IsUpsteamGone { get; set; }
|
||||||
|
|
||||||
public string FriendlyName => IsLocal ? Name : $"{Remote}/{Name}";
|
public string FriendlyName => IsLocal ? Name : $"{Remote}/{Name}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ClientModel;
|
using System.ClientModel;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Azure.AI.OpenAI;
|
using Azure.AI.OpenAI;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
@ -8,6 +11,91 @@ using OpenAI.Chat;
|
||||||
|
|
||||||
namespace SourceGit.Models
|
namespace SourceGit.Models
|
||||||
{
|
{
|
||||||
|
public partial class OpenAIResponse
|
||||||
|
{
|
||||||
|
public OpenAIResponse(Action<string> onUpdate)
|
||||||
|
{
|
||||||
|
_onUpdate = onUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Append(string text)
|
||||||
|
{
|
||||||
|
var buffer = text;
|
||||||
|
|
||||||
|
if (_thinkTail.Length > 0)
|
||||||
|
{
|
||||||
|
_thinkTail.Append(buffer);
|
||||||
|
buffer = _thinkTail.ToString();
|
||||||
|
_thinkTail.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = REG_COT().Replace(buffer, "");
|
||||||
|
|
||||||
|
var startIdx = buffer.IndexOf('<', StringComparison.Ordinal);
|
||||||
|
if (startIdx >= 0)
|
||||||
|
{
|
||||||
|
if (startIdx > 0)
|
||||||
|
OnReceive(buffer.Substring(0, startIdx));
|
||||||
|
|
||||||
|
var endIdx = buffer.IndexOf(">", startIdx + 1, StringComparison.Ordinal);
|
||||||
|
if (endIdx <= startIdx)
|
||||||
|
{
|
||||||
|
if (buffer.Length - startIdx <= 15)
|
||||||
|
_thinkTail.Append(buffer.Substring(startIdx));
|
||||||
|
else
|
||||||
|
OnReceive(buffer.Substring(startIdx));
|
||||||
|
}
|
||||||
|
else if (endIdx < startIdx + 15)
|
||||||
|
{
|
||||||
|
var tag = buffer.Substring(startIdx + 1, endIdx - startIdx - 1);
|
||||||
|
if (_thinkTags.Contains(tag))
|
||||||
|
_thinkTail.Append(buffer.Substring(startIdx));
|
||||||
|
else
|
||||||
|
OnReceive(buffer.Substring(startIdx));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnReceive(buffer.Substring(startIdx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnReceive(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void End()
|
||||||
|
{
|
||||||
|
if (_thinkTail.Length > 0)
|
||||||
|
{
|
||||||
|
OnReceive(_thinkTail.ToString());
|
||||||
|
_thinkTail.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnReceive(string text)
|
||||||
|
{
|
||||||
|
if (!_hasTrimmedStart)
|
||||||
|
{
|
||||||
|
text = text.TrimStart();
|
||||||
|
if (string.IsNullOrEmpty(text))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_hasTrimmedStart = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onUpdate.Invoke(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex(@"<(think|thought|thinking|thought_chain)>.*?</\1>", RegexOptions.Singleline)]
|
||||||
|
private static partial Regex REG_COT();
|
||||||
|
|
||||||
|
private Action<string> _onUpdate = null;
|
||||||
|
private StringBuilder _thinkTail = new StringBuilder();
|
||||||
|
private HashSet<string> _thinkTags = ["think", "thought", "thinking", "thought_chain"];
|
||||||
|
private bool _hasTrimmedStart = false;
|
||||||
|
}
|
||||||
|
|
||||||
public class OpenAIService : ObservableObject
|
public class OpenAIService : ObservableObject
|
||||||
{
|
{
|
||||||
public string Name
|
public string Name
|
||||||
|
@ -42,6 +130,12 @@ namespace SourceGit.Models
|
||||||
set => SetProperty(ref _model, value);
|
set => SetProperty(ref _model, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Streaming
|
||||||
|
{
|
||||||
|
get => _streaming;
|
||||||
|
set => SetProperty(ref _streaming, value);
|
||||||
|
}
|
||||||
|
|
||||||
public string AnalyzeDiffPrompt
|
public string AnalyzeDiffPrompt
|
||||||
{
|
{
|
||||||
get => _analyzeDiffPrompt;
|
get => _analyzeDiffPrompt;
|
||||||
|
@ -89,33 +183,48 @@ namespace SourceGit.Models
|
||||||
|
|
||||||
public void Chat(string prompt, string question, CancellationToken cancellation, Action<string> onUpdate)
|
public void Chat(string prompt, string question, CancellationToken cancellation, Action<string> onUpdate)
|
||||||
{
|
{
|
||||||
Uri server = new(Server);
|
var server = new Uri(_server);
|
||||||
ApiKeyCredential key = new(ApiKey);
|
var key = new ApiKeyCredential(_apiKey);
|
||||||
ChatClient client = null;
|
var client = null as ChatClient;
|
||||||
if (Server.Contains("openai.azure.com/", StringComparison.Ordinal))
|
if (_server.Contains("openai.azure.com/", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
var azure = new AzureOpenAIClient(server, key);
|
var azure = new AzureOpenAIClient(server, key);
|
||||||
client = azure.GetChatClient(Model);
|
client = azure.GetChatClient(_model);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var openai = new OpenAIClient(key, new() { Endpoint = server });
|
var openai = new OpenAIClient(key, new() { Endpoint = server });
|
||||||
client = openai.GetChatClient(Model);
|
client = openai.GetChatClient(_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var messages = new List<ChatMessage>();
|
||||||
|
messages.Add(_model.Equals("o1-mini", StringComparison.Ordinal) ? new UserChatMessage(prompt) : new SystemChatMessage(prompt));
|
||||||
|
messages.Add(new UserChatMessage(question));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var updates = client.CompleteChatStreaming([
|
var rsp = new OpenAIResponse(onUpdate);
|
||||||
_model.Equals("o1-mini", StringComparison.Ordinal) ? new UserChatMessage(prompt) : new SystemChatMessage(prompt),
|
|
||||||
new UserChatMessage(question),
|
if (_streaming)
|
||||||
], null, cancellation);
|
{
|
||||||
|
var updates = client.CompleteChatStreaming(messages, null, cancellation);
|
||||||
|
|
||||||
foreach (var update in updates)
|
foreach (var update in updates)
|
||||||
{
|
{
|
||||||
if (update.ContentUpdate.Count > 0)
|
if (update.ContentUpdate.Count > 0)
|
||||||
onUpdate.Invoke(update.ContentUpdate[0].Text);
|
rsp.Append(update.ContentUpdate[0].Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var completion = client.CompleteChat(messages, null, cancellation);
|
||||||
|
|
||||||
|
if (completion.Value.Content.Count > 0)
|
||||||
|
rsp.Append(completion.Value.Content[0].Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp.End();
|
||||||
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
if (!cancellation.IsCancellationRequested)
|
if (!cancellation.IsCancellationRequested)
|
||||||
|
@ -127,6 +236,7 @@ namespace SourceGit.Models
|
||||||
private string _server;
|
private string _server;
|
||||||
private string _apiKey;
|
private string _apiKey;
|
||||||
private string _model;
|
private string _model;
|
||||||
|
private bool _streaming = true;
|
||||||
private string _analyzeDiffPrompt;
|
private string _analyzeDiffPrompt;
|
||||||
private string _generateSubjectPrompt;
|
private string _generateSubjectPrompt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,18 @@ namespace SourceGit.Models
|
||||||
set;
|
set;
|
||||||
} = false;
|
} = false;
|
||||||
|
|
||||||
|
public bool PushToRemoteWhenCreateTag
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
} = true;
|
||||||
|
|
||||||
|
public bool PushToRemoteWhenDeleteTag
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
} = false;
|
||||||
|
|
||||||
public DealWithLocalChanges DealWithLocalChangesOnCreateBranch
|
public DealWithLocalChanges DealWithLocalChangesOnCreateBranch
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
|
|
|
@ -57,6 +57,7 @@ namespace SourceGit.Models
|
||||||
new ShellOrTerminal("mate-terminal", "MATE Terminal", "mate-terminal"),
|
new ShellOrTerminal("mate-terminal", "MATE Terminal", "mate-terminal"),
|
||||||
new ShellOrTerminal("foot", "Foot", "foot"),
|
new ShellOrTerminal("foot", "Foot", "foot"),
|
||||||
new ShellOrTerminal("wezterm", "WezTerm", "wezterm"),
|
new ShellOrTerminal("wezterm", "WezTerm", "wezterm"),
|
||||||
|
new ShellOrTerminal("ptyxis", "Ptyxis", "ptyxis"),
|
||||||
new ShellOrTerminal("custom", "Custom", ""),
|
new ShellOrTerminal("custom", "Custom", ""),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@
|
||||||
<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.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.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.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">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.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>
|
<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>
|
||||||
|
<StreamGeometry x:Key="Icons.CheckCircled">M512 32C246 32 32 250 32 512s218 480 480 480 480-218 480-480S774 32 512 32zm269 381L496 698c-26 26-61 26-83 0L243 528c-26-26-26-61 0-83s61-26 83 0l128 128 240-240c26-26 61-26 83 0 26 19 26 54 3 80z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Changes">M747 467c29 0 56 4 82 12v-363c0-47-38-84-84-84H125c-47 0-84 38-84 84v707c0 47 38 84 84 84h375a287 287 0 01-43-152c0-160 129-289 289-289zm-531-250h438c19 0 34 15 34 34s-15 34-34 34H216c-19 0-34-15-34-34s15-34 34-34zm0 179h263c19 0 34 15 34 34s-15 34-34 34H216c-19 0-34-15-34-34s15-34 34-34zm131 247h-131c-19 0-34-15-34-34s15-34 34-34h131c19 0 34 15 34 34s-15 34-34 34zM747 521c-130 0-236 106-236 236S617 992 747 992s236-106 236-236S877 521 747 521zm11 386v-65h-130c-12 0-22-10-22-22s10-22 22-22h260l-130 108zm108-192H606l130-108v65h130c12 0 22 10 22 22s-10 22-22 22z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Changes">M747 467c29 0 56 4 82 12v-363c0-47-38-84-84-84H125c-47 0-84 38-84 84v707c0 47 38 84 84 84h375a287 287 0 01-43-152c0-160 129-289 289-289zm-531-250h438c19 0 34 15 34 34s-15 34-34 34H216c-19 0-34-15-34-34s15-34 34-34zm0 179h263c19 0 34 15 34 34s-15 34-34 34H216c-19 0-34-15-34-34s15-34 34-34zm131 247h-131c-19 0-34-15-34-34s15-34 34-34h131c19 0 34 15 34 34s-15 34-34 34zM747 521c-130 0-236 106-236 236S617 992 747 992s236-106 236-236S877 521 747 521zm11 386v-65h-130c-12 0-22-10-22-22s10-22 22-22h260l-130 108zm108-192H606l130-108v65h130c12 0 22 10 22 22s-10 22-22 22z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.CherryPick">M529 511c115 0 212 79 239 185h224a62 62 0 017 123l-7 0-224 0a247 247 0 01-479 0H65a62 62 0 01-7-123l7-0h224a247 247 0 01239-185zm0 124a124 124 0 100 247 124 124 0 000-247zm0-618c32 0 58 24 61 55l0 7V206c89 11 165 45 225 103a74 74 0 0122 45l0 9v87a62 62 0 01-123 7l-0-7v-65l-6-4c-43-33-97-51-163-53l-17-0c-74 0-133 18-180 54l-6 4v65a62 62 0 01-55 61l-7 0a62 62 0 01-61-55l-0-7V362c0-20 8-39 23-53 60-58 135-92 224-103V79c0-34 28-62 62-62z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.CherryPick">M529 511c115 0 212 79 239 185h224a62 62 0 017 123l-7 0-224 0a247 247 0 01-479 0H65a62 62 0 01-7-123l7-0h224a247 247 0 01239-185zm0 124a124 124 0 100 247 124 124 0 000-247zm0-618c32 0 58 24 61 55l0 7V206c89 11 165 45 225 103a74 74 0 0122 45l0 9v87a62 62 0 01-123 7l-0-7v-65l-6-4c-43-33-97-51-163-53l-17-0c-74 0-133 18-180 54l-6 4v65a62 62 0 01-55 61l-7 0a62 62 0 01-61-55l-0-7V362c0-20 8-39 23-53 60-58 135-92 224-103V79c0-34 28-62 62-62z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.CircleDown">M512 926c-229 0-414-186-414-414S283 98 512 98s414 186 414 414-186 414-414 414zm0-73c189 0 341-153 341-341S701 171 512 171 171 323 171 512s153 341 341 341zm-6-192L284 439l52-52 171 171 171-171L728 439l-222 222z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.CircleDown">M512 926c-229 0-414-186-414-414S283 98 512 98s414 186 414 414-186 414-414 414zm0-73c189 0 341-153 341-341S701 171 512 171 171 323 171 512s153 341 341 341zm-6-192L284 439l52-52 171 171 171-171L728 439l-222 222z</StreamGeometry>
|
||||||
|
@ -118,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.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.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.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.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.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>
|
<StreamGeometry x:Key="Icons.TriangleLeft">M30 0 30 30 0 15z</StreamGeometry>
|
||||||
|
|
BIN
src/Resources/Images/ShellIcons/ptyxis.png
Normal file
BIN
src/Resources/Images/ShellIcons/ptyxis.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
|
@ -59,6 +59,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Mit HEAD vergleichen</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Mit HEAD vergleichen</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Mit Worktree vergleichen</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Mit Worktree vergleichen</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Branch-Namen kopieren</x:String>
|
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Branch-Namen kopieren</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Benutzerdefinierte Aktion</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Lösche ${0}$...</x:String>
|
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Lösche ${0}$...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Lösche alle ausgewählten {0} Branches</x:String>
|
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Lösche alle ausgewählten {0} Branches</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Alle Änderungen verwerfen</x:String>
|
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Alle Änderungen verwerfen</x:String>
|
||||||
|
@ -159,6 +160,7 @@
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Ausführbare Datei:</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Ausführbare Datei:</x:String>
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Name:</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Name:</x:String>
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Geltungsbereich:</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Geltungsbereich:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Branch" xml:space="preserve">Branch</x:String>
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Adresse</x:String>
|
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Adresse</x:String>
|
||||||
|
@ -586,6 +588,7 @@
|
||||||
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOKALE BRANCHES</x:String>
|
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOKALE BRANCHES</x:String>
|
||||||
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Zum HEAD wechseln</x:String>
|
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Zum HEAD wechseln</x:String>
|
||||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Erstelle Branch</x:String>
|
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Erstelle Branch</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">BENACHRICHTIGUNGEN LÖSCHEN</x:String>
|
||||||
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInHistories" xml:space="preserve">Nur aktuellen Branch im Graphen hervorheben</x:String>
|
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInHistories" xml:space="preserve">Nur aktuellen Branch im Graphen hervorheben</x:String>
|
||||||
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Öffne in {0}</x:String>
|
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Öffne in {0}</x:String>
|
||||||
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Öffne in externen Tools</x:String>
|
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Öffne in externen Tools</x:String>
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename ${0}$...</x:String>
|
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename ${0}$...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Set Tracking Branch...</x:String>
|
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Set Tracking Branch...</x:String>
|
||||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Compare</x:String>
|
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Compare</x:String>
|
||||||
|
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Invalid upstream!</x:String>
|
||||||
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
|
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
|
||||||
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCEL</x:String>
|
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCEL</x:String>
|
||||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Reset to This Revision</x:String>
|
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Reset to This Revision</x:String>
|
||||||
|
@ -249,7 +250,9 @@
|
||||||
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">OLD</x:String>
|
<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.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.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.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.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.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>
|
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">NO CHANGES OR ONLY EOL CHANGES</x:String>
|
||||||
|
@ -459,6 +462,7 @@
|
||||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Model</x:String>
|
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Model</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
|
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
|
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
|
||||||
|
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Enable Streaming</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APPEARANCE</x:String>
|
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APPEARANCE</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Default Font</x:String>
|
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Default Font</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Font Size</x:String>
|
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Font Size</x:String>
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Rama de Seguimiento:</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Rama de Seguimiento:</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Seguimiento de rama remota</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Seguimiento de rama remota</x:String>
|
||||||
<x:String x:Key="Text.AIAssistant" xml:space="preserve">Asistente OpenAI</x:String>
|
<x:String x:Key="Text.AIAssistant" xml:space="preserve">Asistente OpenAI</x:String>
|
||||||
|
<x:String x:Key="Text.AIAssistant.Regen" xml:space="preserve">RE-GENERAR</x:String>
|
||||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usar OpenAI para generar mensaje de commit</x:String>
|
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usar OpenAI para generar mensaje de commit</x:String>
|
||||||
|
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APLICAR CÓMO MENSAJE DE COMMIT</x:String>
|
||||||
<x:String x:Key="Text.Apply" xml:space="preserve">Aplicar Patch</x:String>
|
<x:String x:Key="Text.Apply" xml:space="preserve">Aplicar Patch</x:String>
|
||||||
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Error</x:String>
|
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Error</x:String>
|
||||||
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Genera errores y se niega a aplicar el patch</x:String>
|
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Genera errores y se niega a aplicar el patch</x:String>
|
||||||
|
@ -37,6 +39,10 @@
|
||||||
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Advertencia</x:String>
|
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Advertencia</x:String>
|
||||||
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Genera advertencias para algunos de estos errores, pero aplica</x:String>
|
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Genera advertencias para algunos de estos errores, pero aplica</x:String>
|
||||||
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espacios en Blanco:</x:String>
|
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espacios en Blanco:</x:String>
|
||||||
|
<x:String x:Key="Text.ApplyStash" xml:space="preserve">Aplicar Stash</x:String>
|
||||||
|
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Borrar después de aplicar</x:String>
|
||||||
|
<x:String x:Key="Text.ApplyStash.RestoreIndex" xml:space="preserve">Restaurar los cambios del índice</x:String>
|
||||||
|
<x:String x:Key="Text.ApplyStash.Stash" xml:space="preserve">Stash:</x:String>
|
||||||
<x:String x:Key="Text.Archive" xml:space="preserve">Archivar...</x:String>
|
<x:String x:Key="Text.Archive" xml:space="preserve">Archivar...</x:String>
|
||||||
<x:String x:Key="Text.Archive.File" xml:space="preserve">Guardar Archivo en:</x:String>
|
<x:String x:Key="Text.Archive.File" xml:space="preserve">Guardar Archivo en:</x:String>
|
||||||
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Seleccionar ruta del archivo</x:String>
|
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Seleccionar ruta del archivo</x:String>
|
||||||
|
@ -53,6 +59,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparar con HEAD</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparar con HEAD</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparar con Worktree</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparar con Worktree</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copiar Nombre de Rama</x:String>
|
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copiar Nombre de Rama</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Acción personalizada</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Eliminar ${0}$...</x:String>
|
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Eliminar ${0}$...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Eliminar {0} ramas seleccionadas</x:String>
|
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Eliminar {0} ramas seleccionadas</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Descartar todos los cambios</x:String>
|
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Descartar todos los cambios</x:String>
|
||||||
|
@ -68,6 +75,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Renombrar ${0}$...</x:String>
|
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Renombrar ${0}$...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Establecer Rama de Seguimiento...</x:String>
|
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Establecer Rama de Seguimiento...</x:String>
|
||||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Comparar Ramas</x:String>
|
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Comparar Ramas</x:String>
|
||||||
|
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">¡Upstream inválido!</x:String>
|
||||||
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
|
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
|
||||||
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCELAR</x:String>
|
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCELAR</x:String>
|
||||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Resetear a Esta Revisión</x:String>
|
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Resetear a Esta Revisión</x:String>
|
||||||
|
@ -100,6 +108,7 @@
|
||||||
<x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Nombre Local:</x:String>
|
<x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Nombre Local:</x:String>
|
||||||
<x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Nombre del repositorio. Opcional.</x:String>
|
<x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Nombre del repositorio. Opcional.</x:String>
|
||||||
<x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Carpeta Padre:</x:String>
|
<x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Carpeta Padre:</x:String>
|
||||||
|
<x:String x:Key="Text.Clone.RecurseSubmodules" xml:space="preserve">Inicializar y actualizar submodulos</x:String>
|
||||||
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">URL del Repositorio:</x:String>
|
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">URL del Repositorio:</x:String>
|
||||||
<x:String x:Key="Text.Close" xml:space="preserve">CERRAR</x:String>
|
<x:String x:Key="Text.Close" xml:space="preserve">CERRAR</x:String>
|
||||||
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Editor</x:String>
|
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Editor</x:String>
|
||||||
|
@ -152,8 +161,10 @@
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Archivo Ejecutable:</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Archivo Ejecutable:</x:String>
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Nombre:</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Nombre:</x:String>
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Alcance:</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Alcance:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Branch" xml:space="preserve">Rama</x:String>
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
|
||||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repositorio</x:String>
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repositorio</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.WaitForExit" xml:space="preserve">Esperar la acción de salida</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Dirección de Email</x:String>
|
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Dirección de Email</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Dirección de email</x:String>
|
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Dirección de email</x:String>
|
||||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
||||||
|
@ -202,6 +213,7 @@
|
||||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash & Reaplicar</x:String>
|
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash & Reaplicar</x:String>
|
||||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nombre de la Nueva Rama:</x:String>
|
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nombre de la Nueva Rama:</x:String>
|
||||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Introduzca el nombre de la rama.</x:String>
|
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Introduzca el nombre de la rama.</x:String>
|
||||||
|
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Los espacios serán reemplazados con guiones.</x:String>
|
||||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Crear Rama Local</x:String>
|
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Crear Rama Local</x:String>
|
||||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Crear Etiqueta...</x:String>
|
<x:String x:Key="Text.CreateTag" xml:space="preserve">Crear Etiqueta...</x:String>
|
||||||
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Nueva Etiqueta En:</x:String>
|
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Nueva Etiqueta En:</x:String>
|
||||||
|
@ -225,8 +237,11 @@
|
||||||
<x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">Estás intentando eliminar múltiples ramas a la vez. ¡Asegúrate de revisar antes de tomar acción!</x:String>
|
<x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">Estás intentando eliminar múltiples ramas a la vez. ¡Asegúrate de revisar antes de tomar acción!</x:String>
|
||||||
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">Eliminar Remoto</x:String>
|
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">Eliminar Remoto</x:String>
|
||||||
<x:String x:Key="Text.DeleteRemote.Remote" xml:space="preserve">Remoto:</x:String>
|
<x:String x:Key="Text.DeleteRemote.Remote" xml:space="preserve">Remoto:</x:String>
|
||||||
|
<x:String x:Key="Text.DeleteRepositoryNode.Path" xml:space="preserve">Ruta:</x:String>
|
||||||
<x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">Destino:</x:String>
|
<x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">Destino:</x:String>
|
||||||
|
<x:String x:Key="Text.DeleteRepositoryNode.TipForGroup" xml:space="preserve">Todos los hijos serán removidos de la lista.</x:String>
|
||||||
<x:String x:Key="Text.DeleteRepositoryNode.TitleForGroup" xml:space="preserve">Confirmar Eliminación de Grupo</x:String>
|
<x:String x:Key="Text.DeleteRepositoryNode.TitleForGroup" xml:space="preserve">Confirmar Eliminación de Grupo</x:String>
|
||||||
|
<x:String x:Key="Text.DeleteRepositoryNode.TipForRepository" xml:space="preserve">¡Esto solo lo removera de la lista, no del disco!</x:String>
|
||||||
<x:String x:Key="Text.DeleteRepositoryNode.TitleForRepository" xml:space="preserve">Confirmar Eliminación de Repositorio</x:String>
|
<x:String x:Key="Text.DeleteRepositoryNode.TitleForRepository" xml:space="preserve">Confirmar Eliminación de Repositorio</x:String>
|
||||||
<x:String x:Key="Text.DeleteSubmodule" xml:space="preserve">Eliminar Submódulo</x:String>
|
<x:String x:Key="Text.DeleteSubmodule" xml:space="preserve">Eliminar Submódulo</x:String>
|
||||||
<x:String x:Key="Text.DeleteSubmodule.Path" xml:space="preserve">Ruta del Submódulo:</x:String>
|
<x:String x:Key="Text.DeleteSubmodule.Path" xml:space="preserve">Ruta del Submódulo:</x:String>
|
||||||
|
@ -449,6 +464,7 @@
|
||||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modelo</x:String>
|
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modelo</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nombre</x:String>
|
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nombre</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Servidor</x:String>
|
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Servidor</x:String>
|
||||||
|
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Activar Transmisión</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APARIENCIA</x:String>
|
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APARIENCIA</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Fuente por defecto</x:String>
|
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Fuente por defecto</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Tamaño de fuente</x:String>
|
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Tamaño de fuente</x:String>
|
||||||
|
@ -576,6 +592,7 @@
|
||||||
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">RAMAS LOCALES</x:String>
|
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">RAMAS LOCALES</x:String>
|
||||||
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navegar a HEAD</x:String>
|
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navegar a HEAD</x:String>
|
||||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Crear Rama</x:String>
|
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Crear Rama</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">LIMPIAR NOTIFICACIONES</x:String>
|
||||||
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInHistories" xml:space="preserve">Resaltar solo la rama actual en el gráfico</x:String>
|
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInHistories" xml:space="preserve">Resaltar solo la rama actual en el gráfico</x:String>
|
||||||
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Abrir en {0}</x:String>
|
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Abrir en {0}</x:String>
|
||||||
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Abrir en Herramientas Externas</x:String>
|
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Abrir en Herramientas Externas</x:String>
|
||||||
|
@ -642,6 +659,8 @@
|
||||||
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Ruta de almacenamiento de la clave privada SSH</x:String>
|
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Ruta de almacenamiento de la clave privada SSH</x:String>
|
||||||
<x:String x:Key="Text.Start" xml:space="preserve">INICIAR</x:String>
|
<x:String x:Key="Text.Start" xml:space="preserve">INICIAR</x:String>
|
||||||
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
|
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
|
||||||
|
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Restaurar automáticamente después del stashing</x:String>
|
||||||
|
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">Tus archivos de trabajo permanecen sin cambios, pero se guarda un stash.</x:String>
|
||||||
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Incluir archivos no rastreados</x:String>
|
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Incluir archivos no rastreados</x:String>
|
||||||
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Mantener archivos staged</x:String>
|
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Mantener archivos staged</x:String>
|
||||||
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Mensaje:</x:String>
|
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Mensaje:</x:String>
|
||||||
|
@ -721,6 +740,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUIR ARCHIVOS NO RASTREADOS</x:String>
|
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUIR ARCHIVOS NO RASTREADOS</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">NO HAY MENSAJES DE ENTRADA RECIENTES</x:String>
|
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">NO HAY MENSAJES DE ENTRADA RECIENTES</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">NO HAY PLANTILLAS DE COMMIT</x:String>
|
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">NO HAY PLANTILLAS DE COMMIT</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">Firmar</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">STAGED</x:String>
|
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">STAGED</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Staged.Unstage" xml:space="preserve">UNSTAGE</x:String>
|
<x:String x:Key="Text.WorkingCopy.Staged.Unstage" xml:space="preserve">UNSTAGE</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Staged.UnstageAll" xml:space="preserve">UNSTAGE TODO</x:String>
|
<x:String x:Key="Text.WorkingCopy.Staged.UnstageAll" xml:space="preserve">UNSTAGE TODO</x:String>
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名 ${0}$...</x:String>
|
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名 ${0}$...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支 ...</x:String>
|
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支 ...</x:String>
|
||||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比较</x:String>
|
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比较</x:String>
|
||||||
|
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">跟踪的上游分支不存在或已删除!</x:String>
|
||||||
<x:String x:Key="Text.Bytes" xml:space="preserve">字节</x:String>
|
<x:String x:Key="Text.Bytes" xml:space="preserve">字节</x:String>
|
||||||
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
||||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重置文件到该版本</x:String>
|
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重置文件到该版本</x:String>
|
||||||
|
@ -252,7 +253,9 @@
|
||||||
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">原始大小</x:String>
|
<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.Copy" xml:space="preserve">复制</x:String>
|
||||||
<x:String x:Key="Text.Diff.FileModeChanged" 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.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.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.Next" xml:space="preserve">下一个差异</x:String>
|
||||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">没有变更或仅有换行符差异</x:String>
|
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">没有变更或仅有换行符差异</x:String>
|
||||||
|
@ -462,6 +465,7 @@
|
||||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">模型</x:String>
|
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">模型</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">配置名称</x:String>
|
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">配置名称</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">服务地址</x:String>
|
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">服务地址</x:String>
|
||||||
|
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">启用流式输出</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外观配置</x:String>
|
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外观配置</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">缺省字体</x:String>
|
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">缺省字体</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">字体大小</x:String>
|
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">字体大小</x:String>
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名 ${0}$...</x:String>
|
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名 ${0}$...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支...</x:String>
|
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支...</x:String>
|
||||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比較</x:String>
|
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比較</x:String>
|
||||||
|
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">追蹤上游分支不存在或已刪除!</x:String>
|
||||||
<x:String x:Key="Text.Bytes" xml:space="preserve">位元組</x:String>
|
<x:String x:Key="Text.Bytes" xml:space="preserve">位元組</x:String>
|
||||||
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
||||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重設檔案為此版本</x:String>
|
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重設檔案為此版本</x:String>
|
||||||
|
@ -252,7 +253,9 @@
|
||||||
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">原始大小</x:String>
|
<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.Copy" xml:space="preserve">複製</x:String>
|
||||||
<x:String x:Key="Text.Diff.FileModeChanged" 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.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.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.Next" xml:space="preserve">下一個差異</x:String>
|
||||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">沒有變更或僅有換行字元差異</x:String>
|
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">沒有變更或僅有換行字元差異</x:String>
|
||||||
|
@ -456,12 +459,13 @@
|
||||||
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String>
|
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String>
|
||||||
<x:String x:Key="Text.Preferences" xml:space="preserve">偏好設定</x:String>
|
<x:String x:Key="Text.Preferences" xml:space="preserve">偏好設定</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">伺服器</x:String>
|
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">分析變更差異提示詞</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API 金鑰</x:String>
|
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API 金鑰</x:String>
|
||||||
|
<x:String x:Key="Text.Preferences.AI.GenerateSubjectPrompt" xml:space="preserve">產生提交訊息提示詞</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">模型</x:String>
|
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">模型</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">名稱</x:String>
|
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">名稱</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">分析變更差異提示詞</x:String>
|
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">伺服器</x:String>
|
||||||
<x:String x:Key="Text.Preferences.AI.GenerateSubjectPrompt" xml:space="preserve">產生提交訊息提示詞</x:String>
|
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">啟用串流輸出</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外觀設定</x:String>
|
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外觀設定</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">預設字型</x:String>
|
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">預設字型</x:String>
|
||||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">字型大小</x:String>
|
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">字型大小</x:String>
|
||||||
|
|
|
@ -48,10 +48,10 @@
|
||||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.4" Condition="'$(Configuration)' == 'Debug'" />
|
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.4" Condition="'$(Configuration)' == 'Debug'" />
|
||||||
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.1.0" />
|
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.1.0" />
|
||||||
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" />
|
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" />
|
||||||
<PackageReference Include="Azure.AI.OpenAI" Version="2.2.0-beta.1" />
|
<PackageReference Include="Azure.AI.OpenAI" Version="2.2.0-beta.2" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
|
||||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.1" />
|
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" />
|
||||||
<PackageReference Include="OpenAI" Version="2.2.0-beta.1" />
|
<PackageReference Include="OpenAI" Version="2.2.0-beta.2" />
|
||||||
<PackageReference Include="TextMateSharp" Version="1.0.66" />
|
<PackageReference Include="TextMateSharp" Version="1.0.66" />
|
||||||
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.66" />
|
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.66" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -101,12 +101,12 @@ namespace SourceGit.ViewModels
|
||||||
return (_current >= 0 && _current < Blocks.Count) ? Blocks[_current] : null;
|
return (_current >= 0 && _current < Blocks.Count) ? Blocks[_current] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block GotoNext()
|
public Block GotoFirst()
|
||||||
{
|
{
|
||||||
if (Blocks.Count == 0)
|
if (Blocks.Count == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Current = (_current + 1) % Blocks.Count;
|
Current = 0;
|
||||||
return Blocks[_current];
|
return Blocks[_current];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,29 @@ namespace SourceGit.ViewModels
|
||||||
if (Blocks.Count == 0)
|
if (Blocks.Count == 0)
|
||||||
return null;
|
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];
|
return Blocks[_current];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Media;
|
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
namespace SourceGit.ViewModels
|
namespace SourceGit.ViewModels
|
||||||
|
@ -45,6 +42,11 @@ namespace SourceGit.ViewModels
|
||||||
get => Backend is Models.Branch { IsCurrent: true };
|
get => Backend is Models.Branch { IsCurrent: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ShowUpstreamGoneTip
|
||||||
|
{
|
||||||
|
get => Backend is Models.Branch { IsUpsteamGone: true };
|
||||||
|
}
|
||||||
|
|
||||||
public string Tooltip
|
public string Tooltip
|
||||||
{
|
{
|
||||||
get => Backend is Models.Branch b ? b.FriendlyName : null;
|
get => Backend is Models.Branch b ? b.FriendlyName : null;
|
||||||
|
|
|
@ -39,11 +39,11 @@ namespace SourceGit.ViewModels
|
||||||
set;
|
set;
|
||||||
} = false;
|
} = false;
|
||||||
|
|
||||||
public bool PushToAllRemotes
|
public bool PushToRemotes
|
||||||
{
|
{
|
||||||
get;
|
get => _repo.Settings.PushToRemoteWhenCreateTag;
|
||||||
set;
|
set => _repo.Settings.PushToRemoteWhenCreateTag = value;
|
||||||
} = true;
|
}
|
||||||
|
|
||||||
public CreateTag(Repository repo, Models.Branch branch)
|
public CreateTag(Repository repo, Models.Branch branch)
|
||||||
{
|
{
|
||||||
|
@ -82,6 +82,7 @@ namespace SourceGit.ViewModels
|
||||||
_repo.SetWatcherEnabled(false);
|
_repo.SetWatcherEnabled(false);
|
||||||
ProgressDescription = "Create tag...";
|
ProgressDescription = "Create tag...";
|
||||||
|
|
||||||
|
var remotes = PushToRemotes ? _repo.Remotes : null;
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
bool succ;
|
bool succ;
|
||||||
|
@ -90,9 +91,9 @@ namespace SourceGit.ViewModels
|
||||||
else
|
else
|
||||||
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn);
|
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn);
|
||||||
|
|
||||||
if (succ && PushToAllRemotes)
|
if (succ && remotes != null)
|
||||||
{
|
{
|
||||||
foreach (var remote in _repo.Remotes)
|
foreach (var remote in remotes)
|
||||||
{
|
{
|
||||||
SetProgressDescription($"Pushing tag to remote {remote.Name} ...");
|
SetProgressDescription($"Pushing tag to remote {remote.Name} ...");
|
||||||
new Commands.Push(_repo.FullPath, remote.Name, _tagName, false).Exec();
|
new Commands.Push(_repo.FullPath, remote.Name, _tagName, false).Exec();
|
||||||
|
|
|
@ -10,17 +10,16 @@ namespace SourceGit.ViewModels
|
||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShouldPushToRemote
|
public bool PushToRemotes
|
||||||
{
|
{
|
||||||
get;
|
get => _repo.Settings.PushToRemoteWhenDeleteTag;
|
||||||
set;
|
set => _repo.Settings.PushToRemoteWhenDeleteTag = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteTag(Repository repo, Models.Tag tag)
|
public DeleteTag(Repository repo, Models.Tag tag)
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
Target = tag;
|
Target = tag;
|
||||||
ShouldPushToRemote = true;
|
|
||||||
View = new Views.DeleteTag() { DataContext = this };
|
View = new Views.DeleteTag() { DataContext = this };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +28,9 @@ namespace SourceGit.ViewModels
|
||||||
_repo.SetWatcherEnabled(false);
|
_repo.SetWatcherEnabled(false);
|
||||||
ProgressDescription = $"Deleting tag '{Target.Name}' ...";
|
ProgressDescription = $"Deleting tag '{Target.Name}' ...";
|
||||||
|
|
||||||
|
var remotes = PushToRemotes ? _repo.Remotes : null;
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
var remotes = ShouldPushToRemote ? _repo.Remotes : null;
|
|
||||||
var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, remotes);
|
var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, remotes);
|
||||||
CallUIThread(() =>
|
CallUIThread(() =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,7 +38,24 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
_fetchAllRemotes = preferedRemote == null;
|
_fetchAllRemotes = preferedRemote == null;
|
||||||
SelectedRemote = preferedRemote != null ? preferedRemote : _repo.Remotes[0];
|
|
||||||
|
if (preferedRemote != null)
|
||||||
|
{
|
||||||
|
SelectedRemote = preferedRemote;
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote))
|
||||||
|
{
|
||||||
|
var def = _repo.Remotes.Find(r => r.Name == _repo.Settings.DefaultRemote);
|
||||||
|
if (def != null)
|
||||||
|
SelectedRemote = def;
|
||||||
|
else
|
||||||
|
SelectedRemote = _repo.Remotes[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectedRemote = _repo.Remotes[0];
|
||||||
|
}
|
||||||
|
|
||||||
View = new Views.Fetch() { DataContext = this };
|
View = new Views.Fetch() { DataContext = this };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1161,6 +1161,10 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public void OpenSubmodule(string submodule)
|
public void OpenSubmodule(string submodule)
|
||||||
{
|
{
|
||||||
|
var selfPage = GetOwnerPage();
|
||||||
|
if (selfPage == null)
|
||||||
|
return;
|
||||||
|
|
||||||
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
|
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
|
||||||
var normalizedPath = root.Replace("\\", "/");
|
var normalizedPath = root.Replace("\\", "/");
|
||||||
|
|
||||||
|
@ -1171,12 +1175,12 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
Id = normalizedPath,
|
Id = normalizedPath,
|
||||||
Name = Path.GetFileName(normalizedPath),
|
Name = Path.GetFileName(normalizedPath),
|
||||||
Bookmark = 0,
|
Bookmark = selfPage.Node.Bookmark,
|
||||||
IsRepository = true,
|
IsRepository = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
App.GetLauncer()?.OpenRepositoryInTab(node, null);
|
App.GetLauncer().OpenRepositoryInTab(node, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddWorktree()
|
public void AddWorktree()
|
||||||
|
|
|
@ -60,6 +60,12 @@ namespace SourceGit.ViewModels
|
||||||
set => SetProperty(ref _httpProxy, value);
|
set => SetProperty(ref _httpProxy, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool EnablePruneOnFetch
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public bool EnableAutoFetch
|
public bool EnableAutoFetch
|
||||||
{
|
{
|
||||||
get => _repo.Settings.EnableAutoFetch;
|
get => _repo.Settings.EnableAutoFetch;
|
||||||
|
@ -153,6 +159,8 @@ namespace SourceGit.ViewModels
|
||||||
GPGUserSigningKey = signingKey;
|
GPGUserSigningKey = signingKey;
|
||||||
if (_cached.TryGetValue("http.proxy", out var proxy))
|
if (_cached.TryGetValue("http.proxy", out var proxy))
|
||||||
HttpProxy = proxy;
|
HttpProxy = proxy;
|
||||||
|
if (_cached.TryGetValue("fetch.prune", out var prune))
|
||||||
|
EnablePruneOnFetch = (prune == "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearHttpProxy()
|
public void ClearHttpProxy()
|
||||||
|
@ -286,6 +294,7 @@ namespace SourceGit.ViewModels
|
||||||
SetIfChanged("tag.gpgsign", GPGTagSigningEnabled ? "true" : "false", "false");
|
SetIfChanged("tag.gpgsign", GPGTagSigningEnabled ? "true" : "false", "false");
|
||||||
SetIfChanged("user.signingkey", GPGUserSigningKey, "");
|
SetIfChanged("user.signingkey", GPGUserSigningKey, "");
|
||||||
SetIfChanged("http.proxy", HttpProxy, "");
|
SetIfChanged("http.proxy", HttpProxy, "");
|
||||||
|
SetIfChanged("fetch.prune", EnablePruneOnFetch ? "true" : "false", "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetIfChanged(string key, string value, string defValue)
|
private void SetIfChanged(string key, string value, string defValue)
|
||||||
|
|
|
@ -109,7 +109,7 @@ namespace SourceGit.ViewModels
|
||||||
if (_isLoadingData)
|
if (_isLoadingData)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VisibleUnstaged = GetVisibleUnstagedChanges();
|
VisibleUnstaged = GetVisibleUnstagedChanges(_unstaged);
|
||||||
SelectedUnstaged = [];
|
SelectedUnstaged = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,9 +214,11 @@ namespace SourceGit.ViewModels
|
||||||
OnPropertyChanged(nameof(SelectedStaged));
|
OnPropertyChanged(nameof(SelectedStaged));
|
||||||
|
|
||||||
_visibleUnstaged.Clear();
|
_visibleUnstaged.Clear();
|
||||||
_unstaged.Clear();
|
|
||||||
OnPropertyChanged(nameof(VisibleUnstaged));
|
OnPropertyChanged(nameof(VisibleUnstaged));
|
||||||
|
|
||||||
|
_unstaged.Clear();
|
||||||
|
OnPropertyChanged(nameof(Unstaged));
|
||||||
|
|
||||||
_staged.Clear();
|
_staged.Clear();
|
||||||
OnPropertyChanged(nameof(Staged));
|
OnPropertyChanged(nameof(Staged));
|
||||||
|
|
||||||
|
@ -231,25 +233,10 @@ namespace SourceGit.ViewModels
|
||||||
// Just force refresh selected changes.
|
// Just force refresh selected changes.
|
||||||
Dispatcher.UIThread.Invoke(() =>
|
Dispatcher.UIThread.Invoke(() =>
|
||||||
{
|
{
|
||||||
if (_selectedUnstaged.Count == 1)
|
|
||||||
SetDetail(_selectedUnstaged[0], true);
|
|
||||||
else if (_selectedStaged.Count == 1)
|
|
||||||
SetDetail(_selectedStaged[0], false);
|
|
||||||
else
|
|
||||||
SetDetail(null, false);
|
|
||||||
|
|
||||||
var inProgress = null as InProgressContext;
|
|
||||||
if (File.Exists(Path.Combine(_repo.GitDir, "CHERRY_PICK_HEAD")))
|
|
||||||
inProgress = new CherryPickInProgress(_repo);
|
|
||||||
else if (Directory.Exists(Path.Combine(_repo.GitDir, "rebase-merge")) || Directory.Exists(Path.Combine(_repo.GitDir, "rebase-apply")))
|
|
||||||
inProgress = new RebaseInProgress(_repo);
|
|
||||||
else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD")))
|
|
||||||
inProgress = new RevertInProgress(_repo);
|
|
||||||
else if (File.Exists(Path.Combine(_repo.GitDir, "MERGE_HEAD")))
|
|
||||||
inProgress = new MergeInProgress(_repo);
|
|
||||||
|
|
||||||
HasUnsolvedConflicts = _cached.Find(x => x.IsConflit) != null;
|
HasUnsolvedConflicts = _cached.Find(x => x.IsConflit) != null;
|
||||||
InProgressContext = inProgress;
|
|
||||||
|
UpdateDetail();
|
||||||
|
UpdateInProgressState();
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -282,9 +269,7 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_unstaged = unstaged;
|
var visibleUnstaged = GetVisibleUnstagedChanges(unstaged);
|
||||||
|
|
||||||
var visibleUnstaged = GetVisibleUnstagedChanges();
|
|
||||||
var selectedUnstaged = new List<Models.Change>();
|
var selectedUnstaged = new List<Models.Change>();
|
||||||
foreach (var c in visibleUnstaged)
|
foreach (var c in visibleUnstaged)
|
||||||
{
|
{
|
||||||
|
@ -305,37 +290,14 @@ namespace SourceGit.ViewModels
|
||||||
_isLoadingData = true;
|
_isLoadingData = true;
|
||||||
HasUnsolvedConflicts = hasConflict;
|
HasUnsolvedConflicts = hasConflict;
|
||||||
VisibleUnstaged = visibleUnstaged;
|
VisibleUnstaged = visibleUnstaged;
|
||||||
|
Unstaged = unstaged;
|
||||||
Staged = staged;
|
Staged = staged;
|
||||||
SelectedUnstaged = selectedUnstaged;
|
SelectedUnstaged = selectedUnstaged;
|
||||||
SelectedStaged = selectedStaged;
|
SelectedStaged = selectedStaged;
|
||||||
_isLoadingData = false;
|
_isLoadingData = false;
|
||||||
|
|
||||||
if (selectedUnstaged.Count == 1)
|
UpdateDetail();
|
||||||
SetDetail(selectedUnstaged[0], true);
|
UpdateInProgressState();
|
||||||
else if (selectedStaged.Count == 1)
|
|
||||||
SetDetail(selectedStaged[0], false);
|
|
||||||
else
|
|
||||||
SetDetail(null, false);
|
|
||||||
|
|
||||||
var inProgress = null as InProgressContext;
|
|
||||||
if (File.Exists(Path.Combine(_repo.GitDir, "CHERRY_PICK_HEAD")))
|
|
||||||
inProgress = new CherryPickInProgress(_repo);
|
|
||||||
else if (Directory.Exists(Path.Combine(_repo.GitDir, "rebase-merge")) || Directory.Exists(Path.Combine(_repo.GitDir, "rebase-apply")))
|
|
||||||
inProgress = new RebaseInProgress(_repo);
|
|
||||||
else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD")))
|
|
||||||
inProgress = new RevertInProgress(_repo);
|
|
||||||
else if (File.Exists(Path.Combine(_repo.GitDir, "MERGE_HEAD")))
|
|
||||||
inProgress = new MergeInProgress(_repo);
|
|
||||||
|
|
||||||
InProgressContext = inProgress;
|
|
||||||
|
|
||||||
// Try to load merge message from MERGE_MSG
|
|
||||||
if (string.IsNullOrEmpty(_commitMessage))
|
|
||||||
{
|
|
||||||
var mergeMsgFile = Path.Combine(_repo.GitDir, "MERGE_MSG");
|
|
||||||
if (File.Exists(mergeMsgFile))
|
|
||||||
CommitMessage = File.ReadAllText(mergeMsgFile);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,38 +353,80 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public async void UseTheirs(List<Models.Change> changes)
|
public async void UseTheirs(List<Models.Change> changes)
|
||||||
{
|
{
|
||||||
|
_repo.SetWatcherEnabled(false);
|
||||||
|
|
||||||
var files = new List<string>();
|
var files = new List<string>();
|
||||||
|
var needStage = new List<string>();
|
||||||
|
|
||||||
foreach (var change in changes)
|
foreach (var change in changes)
|
||||||
{
|
{
|
||||||
if (change.IsConflit)
|
if (!change.IsConflit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (change.WorkTree == Models.ChangeState.Deleted)
|
||||||
|
{
|
||||||
|
var fullpath = Path.Combine(_repo.FullPath, change.Path);
|
||||||
|
if (File.Exists(fullpath))
|
||||||
|
File.Delete(fullpath);
|
||||||
|
|
||||||
|
needStage.Add(change.Path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
files.Add(change.Path);
|
files.Add(change.Path);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_repo.SetWatcherEnabled(false);
|
if (files.Count > 0)
|
||||||
|
{
|
||||||
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseTheirs(files));
|
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseTheirs(files));
|
||||||
if (succ)
|
if (succ)
|
||||||
{
|
needStage.AddRange(files);
|
||||||
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needStage.Count > 0)
|
||||||
|
await Task.Run(() => new Commands.Add(_repo.FullPath, needStage).Exec());
|
||||||
|
|
||||||
_repo.MarkWorkingCopyDirtyManually();
|
_repo.MarkWorkingCopyDirtyManually();
|
||||||
_repo.SetWatcherEnabled(true);
|
_repo.SetWatcherEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void UseMine(List<Models.Change> changes)
|
public async void UseMine(List<Models.Change> changes)
|
||||||
{
|
{
|
||||||
|
_repo.SetWatcherEnabled(false);
|
||||||
|
|
||||||
var files = new List<string>();
|
var files = new List<string>();
|
||||||
|
var needStage = new List<string>();
|
||||||
|
|
||||||
foreach (var change in changes)
|
foreach (var change in changes)
|
||||||
{
|
{
|
||||||
if (change.IsConflit)
|
if (!change.IsConflit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (change.Index == Models.ChangeState.Deleted)
|
||||||
|
{
|
||||||
|
var fullpath = Path.Combine(_repo.FullPath, change.Path);
|
||||||
|
if (File.Exists(fullpath))
|
||||||
|
File.Delete(fullpath);
|
||||||
|
|
||||||
|
needStage.Add(change.Path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
files.Add(change.Path);
|
files.Add(change.Path);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_repo.SetWatcherEnabled(false);
|
if (files.Count > 0)
|
||||||
|
{
|
||||||
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseMine(files));
|
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseMine(files));
|
||||||
if (succ)
|
if (succ)
|
||||||
{
|
needStage.AddRange(files);
|
||||||
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needStage.Count > 0)
|
||||||
|
await Task.Run(() => new Commands.Add(_repo.FullPath, needStage).Exec());
|
||||||
|
|
||||||
_repo.MarkWorkingCopyDirtyManually();
|
_repo.MarkWorkingCopyDirtyManually();
|
||||||
_repo.SetWatcherEnabled(true);
|
_repo.SetWatcherEnabled(true);
|
||||||
}
|
}
|
||||||
|
@ -1456,14 +1460,14 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Models.Change> GetVisibleUnstagedChanges()
|
private List<Models.Change> GetVisibleUnstagedChanges(List<Models.Change> unstaged)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_unstagedFilter))
|
if (string.IsNullOrEmpty(_unstagedFilter))
|
||||||
return _unstaged;
|
return unstaged;
|
||||||
|
|
||||||
var visible = new List<Models.Change>();
|
var visible = new List<Models.Change>();
|
||||||
|
|
||||||
foreach (var c in _unstaged)
|
foreach (var c in unstaged)
|
||||||
{
|
{
|
||||||
if (c.Path.Contains(_unstagedFilter, StringComparison.OrdinalIgnoreCase))
|
if (c.Path.Contains(_unstagedFilter, StringComparison.OrdinalIgnoreCase))
|
||||||
visible.Add(c);
|
visible.Add(c);
|
||||||
|
@ -1487,9 +1491,61 @@ namespace SourceGit.ViewModels
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateDetail()
|
||||||
|
{
|
||||||
|
if (_selectedUnstaged.Count == 1)
|
||||||
|
SetDetail(_selectedUnstaged[0], true);
|
||||||
|
else if (_selectedStaged.Count == 1)
|
||||||
|
SetDetail(_selectedStaged[0], false);
|
||||||
|
else
|
||||||
|
SetDetail(null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateInProgressState()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_commitMessage))
|
||||||
|
{
|
||||||
|
var mergeMsgFile = Path.Combine(_repo.GitDir, "MERGE_MSG");
|
||||||
|
if (File.Exists(mergeMsgFile))
|
||||||
|
CommitMessage = File.ReadAllText(mergeMsgFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(Path.Combine(_repo.GitDir, "CHERRY_PICK_HEAD")))
|
||||||
|
{
|
||||||
|
InProgressContext = new CherryPickInProgress(_repo);
|
||||||
|
}
|
||||||
|
else if (Directory.Exists(Path.Combine(_repo.GitDir, "rebase-merge")) || Directory.Exists(Path.Combine(_repo.GitDir, "rebase-apply")))
|
||||||
|
{
|
||||||
|
var rebasing = new RebaseInProgress(_repo);
|
||||||
|
InProgressContext = rebasing;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(_commitMessage))
|
||||||
|
{
|
||||||
|
var rebaseMsgFile = Path.Combine(_repo.GitDir, "rebase-merge", "message");
|
||||||
|
if (File.Exists(rebaseMsgFile))
|
||||||
|
CommitMessage = File.ReadAllText(rebaseMsgFile);
|
||||||
|
else if (rebasing.StoppedAt != null)
|
||||||
|
CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, rebasing.StoppedAt.SHA).Result();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD")))
|
||||||
|
{
|
||||||
|
InProgressContext = new RevertInProgress(_repo);
|
||||||
|
}
|
||||||
|
else if (File.Exists(Path.Combine(_repo.GitDir, "MERGE_HEAD")))
|
||||||
|
{
|
||||||
|
InProgressContext = new MergeInProgress(_repo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InProgressContext = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void StageChanges(List<Models.Change> changes, Models.Change next)
|
private async void StageChanges(List<Models.Change> changes, Models.Change next)
|
||||||
{
|
{
|
||||||
if (changes.Count == 0)
|
var count = changes.Count;
|
||||||
|
if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Use `_selectedUnstaged` instead of `SelectedUnstaged` to avoid UI refresh.
|
// Use `_selectedUnstaged` instead of `SelectedUnstaged` to avoid UI refresh.
|
||||||
|
@ -1497,7 +1553,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
IsStaging = true;
|
IsStaging = true;
|
||||||
_repo.SetWatcherEnabled(false);
|
_repo.SetWatcherEnabled(false);
|
||||||
if (changes.Count == _unstaged.Count)
|
if (count == _unstaged.Count)
|
||||||
{
|
{
|
||||||
await Task.Run(() => new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Exec());
|
await Task.Run(() => new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Exec());
|
||||||
}
|
}
|
||||||
|
@ -1514,10 +1570,13 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < changes.Count; i += 10)
|
var paths = new List<string>();
|
||||||
|
foreach (var c in changes)
|
||||||
|
paths.Add(c.Path);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i += 10)
|
||||||
{
|
{
|
||||||
var count = Math.Min(10, changes.Count - i);
|
var step = paths.GetRange(i, Math.Min(10, count - i));
|
||||||
var step = changes.GetRange(i, count);
|
|
||||||
await Task.Run(() => new Commands.Add(_repo.FullPath, step).Exec());
|
await Task.Run(() => new Commands.Add(_repo.FullPath, step).Exec());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,17 +57,21 @@
|
||||||
IsExpanded="{Binding IsExpanded}"/>
|
IsExpanded="{Binding IsExpanded}"/>
|
||||||
|
|
||||||
<!-- Name -->
|
<!-- Name -->
|
||||||
<Grid Grid.Column="1" ColumnDefinitions="Auto,*">
|
|
||||||
<Border Grid.Column="0" Margin="0,0,4,0" Background="Green" Height="16" CornerRadius="8" VerticalAlignment="Center" IsVisible="{Binding IsCurrent}">
|
|
||||||
<TextBlock Text="HEAD" Classes="primary" Margin="8,0" Foreground="#FFDDDDDD" FontSize="10" VerticalAlignment="Center"/>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<TextBlock Grid.Column="1"
|
<TextBlock Grid.Column="1"
|
||||||
Classes="primary"
|
Classes="primary"
|
||||||
Text="{Binding Name}"
|
Text="{Binding Name}"
|
||||||
|
FontWeight="{Binding IsCurrent, Converter={x:Static c:BoolConverters.IsBoldToFontWeight}}"
|
||||||
TextTrimming="CharacterEllipsis"/>
|
TextTrimming="CharacterEllipsis"/>
|
||||||
</Grid>
|
|
||||||
|
|
||||||
|
<!-- Upstream invalid tip -->
|
||||||
|
<Border Grid.Column="2"
|
||||||
|
Width="12" Height="12"
|
||||||
|
Margin="8,0"
|
||||||
|
Background="Transparent"
|
||||||
|
ToolTip.Tip="{DynamicResource Text.BranchUpstreamInvalid}"
|
||||||
|
IsVisible="{Binding ShowUpstreamGoneTip}">
|
||||||
|
<Path Data="{StaticResource Icons.Error}" Fill="DarkOrange"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
<!-- Tracking status -->
|
<!-- Tracking status -->
|
||||||
<v:BranchTreeNodeTrackStatusPresenter Grid.Column="2"
|
<v:BranchTreeNodeTrackStatusPresenter Grid.Column="2"
|
||||||
|
|
|
@ -52,31 +52,31 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
if (node.Backend is Models.Remote)
|
if (node.Backend is Models.Remote)
|
||||||
{
|
{
|
||||||
CreateContent(new Thickness(0, 0, 0, 0), "Icons.Remote");
|
CreateContent(new Thickness(0, 0, 0, 0), "Icons.Remote", false);
|
||||||
}
|
}
|
||||||
else if (node.Backend is Models.Branch branch)
|
else if (node.Backend is Models.Branch branch)
|
||||||
{
|
{
|
||||||
if (branch.IsCurrent)
|
if (branch.IsCurrent)
|
||||||
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Check");
|
CreateContent(new Thickness(0, 0, 0, 0), "Icons.CheckCircled", true);
|
||||||
else
|
else
|
||||||
CreateContent(new Thickness(2, 0, 0, 0), "Icons.Branch");
|
CreateContent(new Thickness(2, 0, 0, 0), "Icons.Branch", false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (node.IsExpanded)
|
if (node.IsExpanded)
|
||||||
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder.Open");
|
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder.Open", false);
|
||||||
else
|
else
|
||||||
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder");
|
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateContent(Thickness margin, string iconKey)
|
private void CreateContent(Thickness margin, string iconKey, bool highlight)
|
||||||
{
|
{
|
||||||
var geo = this.FindResource(iconKey) as StreamGeometry;
|
var geo = this.FindResource(iconKey) as StreamGeometry;
|
||||||
if (geo == null)
|
if (geo == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Content = new Path()
|
var path = new Path()
|
||||||
{
|
{
|
||||||
Width = 12,
|
Width = 12,
|
||||||
Height = 12,
|
Height = 12,
|
||||||
|
@ -85,6 +85,11 @@ namespace SourceGit.Views
|
||||||
Margin = margin,
|
Margin = margin,
|
||||||
Data = geo,
|
Data = geo,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (highlight)
|
||||||
|
path.Fill = Brushes.Green;
|
||||||
|
|
||||||
|
Content = path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
|
|
||||||
<CheckBox Grid.Row="5" Grid.Column="1"
|
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||||
Content="{DynamicResource Text.CreateTag.PushToAllRemotes}"
|
Content="{DynamicResource Text.CreateTag.PushToAllRemotes}"
|
||||||
IsChecked="{Binding PushToAllRemotes, Mode=TwoWay}"/>
|
IsChecked="{Binding PushToRemotes, Mode=TwoWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
<CheckBox Grid.Row="1" Grid.Column="1"
|
<CheckBox Grid.Row="1" Grid.Column="1"
|
||||||
Content="{DynamicResource Text.DeleteTag.WithRemote}"
|
Content="{DynamicResource Text.DeleteTag.WithRemote}"
|
||||||
IsChecked="{Binding ShouldPushToRemote, Mode=TwoWay}"/>
|
IsChecked="{Binding PushToRemotes, Mode=TwoWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
|
@ -34,6 +34,20 @@
|
||||||
|
|
||||||
<!-- Toolbar Buttons -->
|
<!-- Toolbar Buttons -->
|
||||||
<StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center">
|
<StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center">
|
||||||
|
<Button Classes="icon_button"
|
||||||
|
Width="28"
|
||||||
|
Click="OnGotoFirstChange"
|
||||||
|
IsVisible="{Binding IsTextDiff}"
|
||||||
|
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"
|
<Button Classes="icon_button"
|
||||||
Width="28"
|
Width="28"
|
||||||
Click="OnGotoPrevChange"
|
Click="OnGotoPrevChange"
|
||||||
|
@ -61,6 +75,20 @@
|
||||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
|
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button Classes="icon_button"
|
||||||
|
Width="28"
|
||||||
|
Click="OnGotoLastChange"
|
||||||
|
IsVisible="{Binding IsTextDiff}"
|
||||||
|
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"
|
<ToggleButton Classes="line_path"
|
||||||
Width="28"
|
Width="28"
|
||||||
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=TwoWay}"
|
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=TwoWay}"
|
||||||
|
|
|
@ -11,6 +11,13 @@ namespace SourceGit.Views
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnGotoFirstChange(object _, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var textDiff = this.FindDescendantOfType<TextDiffView>();
|
||||||
|
textDiff?.GotoFirstChange();
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnGotoPrevChange(object _, RoutedEventArgs e)
|
private void OnGotoPrevChange(object _, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var textDiff = this.FindDescendantOfType<TextDiffView>();
|
var textDiff = this.FindDescendantOfType<TextDiffView>();
|
||||||
|
@ -24,5 +31,12 @@ namespace SourceGit.Views
|
||||||
textDiff?.GotoNextChange();
|
textDiff?.GotoNextChange();
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnGotoLastChange(object _, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var textDiff = this.FindDescendantOfType<TextDiffView>();
|
||||||
|
textDiff?.GotoLastChange();
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -616,6 +616,10 @@
|
||||||
Text="{Binding GenerateSubjectPrompt, Mode=TwoWay}"
|
Text="{Binding GenerateSubjectPrompt, Mode=TwoWay}"
|
||||||
AcceptsReturn="true"
|
AcceptsReturn="true"
|
||||||
TextWrapping="Wrap"/>
|
TextWrapping="Wrap"/>
|
||||||
|
|
||||||
|
<CheckBox Margin="0,12,0,0"
|
||||||
|
Content="{DynamicResource Text.Preferences.AI.Streaming}"
|
||||||
|
IsChecked="{Binding Streaming, Mode=TwoWay}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ContentControl.DataTemplates>
|
</ContentControl.DataTemplates>
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.Git}"/>
|
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.Git}"/>
|
||||||
</TabItem.Header>
|
</TabItem.Header>
|
||||||
|
|
||||||
<Grid Margin="16,4,16,8" RowDefinitions="32,32,32,32,32,32,32,32" ColumnDefinitions="Auto,*">
|
<Grid Margin="16,4,16,8" RowDefinitions="32,32,32,32,32,32,32,32,32" ColumnDefinitions="Auto,*">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
|
@ -119,7 +119,11 @@
|
||||||
Content="{DynamicResource Text.Preferences.GPG.TagEnabled}"
|
Content="{DynamicResource Text.Preferences.GPG.TagEnabled}"
|
||||||
IsChecked="{Binding GPGTagSigningEnabled, Mode=TwoWay}"/>
|
IsChecked="{Binding GPGTagSigningEnabled, Mode=TwoWay}"/>
|
||||||
|
|
||||||
<StackPanel Grid.Row="7" Grid.Column="1" Orientation="Horizontal">
|
<CheckBox Grid.Row="7" Grid.Column="1"
|
||||||
|
Content="{DynamicResource Text.Preferences.Git.EnablePruneOnFetch}"
|
||||||
|
IsChecked="{Binding EnablePruneOnFetch, Mode=TwoWay}"/>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="8" Grid.Column="1" Orientation="Horizontal">
|
||||||
<CheckBox x:Name="AutoFetchCheckBox"
|
<CheckBox x:Name="AutoFetchCheckBox"
|
||||||
Content="{DynamicResource Text.Configure.Git.AutoFetch}"
|
Content="{DynamicResource Text.Configure.Git.AutoFetch}"
|
||||||
IsChecked="{Binding EnableAutoFetch, Mode=TwoWay}"/>
|
IsChecked="{Binding EnableAutoFetch, Mode=TwoWay}"/>
|
||||||
|
@ -340,7 +344,7 @@
|
||||||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.CustomAction}"/>
|
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.CustomAction}"/>
|
||||||
</TabItem.Header>
|
</TabItem.Header>
|
||||||
|
|
||||||
<Grid ColumnDefinitions="200,*" Height="300" Margin="0,8,0,16">
|
<Grid ColumnDefinitions="200,*" Height="340" Margin="0,8,0,16">
|
||||||
<Border Grid.Column="0"
|
<Border Grid.Column="0"
|
||||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
Background="{DynamicResource Brush.Contents}">
|
Background="{DynamicResource Brush.Contents}">
|
||||||
|
|
|
@ -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()
|
public void GotoPrevChange()
|
||||||
{
|
{
|
||||||
var blockNavigation = BlockNavigation;
|
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)
|
public override void Render(DrawingContext context)
|
||||||
{
|
{
|
||||||
base.Render(context);
|
base.Render(context);
|
||||||
|
@ -1682,6 +1712,19 @@ namespace SourceGit.Views
|
||||||
InitializeComponent();
|
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()
|
public void GotoPrevChange()
|
||||||
{
|
{
|
||||||
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||||
|
@ -1708,6 +1751,19 @@ namespace SourceGit.Views
|
||||||
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
|
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)
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnDataContextChanged(e);
|
base.OnDataContextChanged(e);
|
||||||
|
@ -1796,7 +1852,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
if (!selection.HasLeftChanges)
|
if (!selection.HasLeftChanges)
|
||||||
{
|
{
|
||||||
new Commands.Add(repo.FullPath, [change]).Exec();
|
new Commands.Add(repo.FullPath, [change.Path]).Exec();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue