Merge branch 'develop' into localization

This commit is contained in:
Katharina Sternbauer 2024-11-08 12:39:51 +01:00 committed by GitHub
commit 3d59ec525a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 690 additions and 325 deletions

View file

@ -47,7 +47,7 @@
## Translation Status
[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-96.05%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.08%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-87.72%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-90.79%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-100.00%25-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md)
[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-94.80%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.13%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-86.56%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-89.60%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-100.00%25-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md)
## How to Use

View file

@ -1,4 +1,4 @@
### de_DE.axaml: 96.05%
### de_DE.axaml: 94.80%
<details>
@ -22,11 +22,20 @@
- Text.Configure.OpenAI
- Text.Configure.OpenAI.Prefered
- Text.Configure.OpenAI.Prefered.Tip
- Text.Diff.SaveAsPatch
- Text.Diff.VisualLines.All
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.Hotkeys.Repo.CreateBranchOnCommit
- Text.Hotkeys.Repo.Fetch
- Text.Hotkeys.Repo.Pull
- Text.Hotkeys.Repo.Push
- Text.IssueLinkCM.OpenInBrowser
- Text.IssueLinkCM.CopyLink
- Text.Preference.AI.AnalyzeDiffPrompt
- Text.Preference.AI.GenerateSubjectPrompt
- Text.Preference.AI.Name
- Text.Preference.Appearance.EditorFontSize
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Stash.KeepIndex
@ -34,36 +43,22 @@
</details>
### es_ES.axaml: 97.08%
### es_ES.axaml: 99.13%
<details>
<summary>Missing Keys</summary>
- Text.ChangeCM.GenerateCommitMessage
- Text.CommitCM.CustomAction
- Text.Configure.CustomAction
- Text.Configure.CustomAction.Arguments
- Text.Configure.CustomAction.Arguments.Tip
- Text.Configure.CustomAction.Executable
- Text.Configure.CustomAction.Name
- Text.Configure.CustomAction.Scope
- Text.Configure.CustomAction.Scope.Commit
- Text.Configure.CustomAction.Scope.Repository
- Text.Configure.Git.EnablePruneOnFetch
- Text.Configure.OpenAI
- Text.Configure.OpenAI.Prefered
- Text.Configure.OpenAI.Prefered.Tip
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.Preference.AI.Name
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Stash.KeepIndex
- Text.Diff.SaveAsPatch
- Text.Hotkeys.Repo.CreateBranchOnCommit
- Text.Hotkeys.Repo.Fetch
- Text.Hotkeys.Repo.Pull
- Text.Hotkeys.Repo.Push
- Text.Preference.Appearance.EditorFontSize
</details>
### fr_FR.axaml: 87.72%
### fr_FR.axaml: 86.56%
<details>
@ -108,6 +103,8 @@
- Text.ConventionalCommit.ShortDescription
- Text.ConventionalCommit.Type
- Text.Diff.IgnoreWhitespace
- Text.Diff.SaveAsPatch
- Text.Diff.VisualLines.All
- Text.Discard.IncludeIgnored
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
@ -118,7 +115,13 @@
- Text.Histories.Tips.MacOS
- Text.Histories.Tips.Prefix
- Text.Hotkeys.Repo.CommitWithAutoStage
- Text.Hotkeys.Repo.CreateBranchOnCommit
- Text.Hotkeys.Repo.DiscardSelected
- Text.Hotkeys.Repo.Fetch
- Text.Hotkeys.Repo.Pull
- Text.Hotkeys.Repo.Push
- Text.IssueLinkCM.OpenInBrowser
- Text.IssueLinkCM.CopyLink
- Text.MoveRepositoryNode
- Text.MoveRepositoryNode.Target
- Text.Preference.AI
@ -128,6 +131,7 @@
- Text.Preference.AI.Model
- Text.Preference.AI.Name
- Text.Preference.AI.Server
- Text.Preference.Appearance.EditorFontSize
- Text.Preference.General.ShowAuthorTime
- Text.Preference.Integration
- Text.Preference.Shell
@ -156,7 +160,7 @@
</details>
### pt_BR.axaml: 90.79%
### pt_BR.axaml: 89.60%
<details>
@ -203,15 +207,24 @@
- Text.ConventionalCommit.ShortDescription
- Text.ConventionalCommit.Type
- Text.CopyAllText
- Text.Diff.SaveAsPatch
- Text.Diff.VisualLines.All
- Text.Discard.IncludeIgnored
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.FileHistory.FileContent
- Text.FileHistory.FileChange
- Text.GitLFS.Locks.OnlyMine
- Text.Hotkeys.Repo.CreateBranchOnCommit
- Text.Hotkeys.Repo.Fetch
- Text.Hotkeys.Repo.Pull
- Text.Hotkeys.Repo.Push
- Text.IssueLinkCM.OpenInBrowser
- Text.IssueLinkCM.CopyLink
- Text.MoveRepositoryNode
- Text.MoveRepositoryNode.Target
- Text.Preference.AI.Name
- Text.Preference.Appearance.EditorFontSize
- Text.Push.CheckSubmodules
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty

View file

@ -8,6 +8,10 @@ namespace SourceGit.Commands
{
[GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")]
private static partial Regex REG_INDICATOR();
[GeneratedRegex(@"^index\s([0-9a-f]{6,40})\.\.([0-9a-f]{6,40})(\s[1-9]{6})?")]
private static partial Regex REG_HASH_CHANGE();
private const string PREFIX_LFS_NEW = "+version https://git-lfs.github.com/spec/";
private const string PREFIX_LFS_DEL = "-version https://git-lfs.github.com/spec/";
private const string PREFIX_LFS_MODIFY = " version https://git-lfs.github.com/spec/";
@ -101,17 +105,31 @@ namespace SourceGit.Commands
if (_result.TextDiff.Lines.Count == 0)
{
var match = REG_INDICATOR().Match(line);
if (!match.Success)
if (line.StartsWith("Binary", StringComparison.Ordinal))
{
if (line.StartsWith("Binary", StringComparison.Ordinal))
_result.IsBinary = true;
_result.IsBinary = true;
return;
}
_oldLine = int.Parse(match.Groups[1].Value);
_newLine = int.Parse(match.Groups[2].Value);
_result.TextDiff.Lines.Add(new Models.TextDiffLine(Models.TextDiffLineType.Indicator, line, 0, 0));
if (string.IsNullOrEmpty(_result.OldHash))
{
var match = REG_HASH_CHANGE().Match(line);
if (!match.Success)
return;
_result.OldHash = match.Groups[1].Value;
_result.NewHash = match.Groups[2].Value;
}
else
{
var match = REG_INDICATOR().Match(line);
if (!match.Success)
return;
_oldLine = int.Parse(match.Groups[1].Value);
_newLine = int.Parse(match.Groups[2].Value);
_result.TextDiff.Lines.Add(new Models.TextDiffLine(Models.TextDiffLineType.Indicator, line, 0, 0));
}
}
else
{

View file

@ -30,6 +30,8 @@ namespace SourceGit.Commands
start.Environment.Add("PATH", Native.OS.CustomPathEnv);
var proc = new Process() { StartInfo = start };
var builder = new StringBuilder();
proc.OutputDataReceived += (_, e) =>
{
if (e.Data != null)
@ -39,7 +41,10 @@ namespace SourceGit.Commands
proc.ErrorDataReceived += (_, e) =>
{
if (e.Data != null)
{
outputHandler?.Invoke(e.Data);
builder.AppendLine(e.Data);
}
};
try
@ -57,7 +62,17 @@ namespace SourceGit.Commands
});
}
var exitCode = proc.ExitCode;
proc.Close();
if (exitCode != 0)
{
var errMsg = builder.ToString();
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, errMsg);
});
}
}
}
}

View file

@ -9,7 +9,7 @@ namespace SourceGit.Commands
{
public static class SaveChangesAsPatch
{
public static bool Exec(string repo, List<Models.Change> changes, bool isUnstaged, string saveTo)
public static bool ProcessLocalChanges(string repo, List<Models.Change> changes, bool isUnstaged, string saveTo)
{
using (var sw = File.Create(saveTo))
{
@ -23,6 +23,20 @@ namespace SourceGit.Commands
return true;
}
public static bool ProcessRevisionCompareChanges(string repo, List<Models.Change> changes, string baseRevision, string targetRevision, string saveTo)
{
using (var sw = File.Create(saveTo))
{
foreach (var change in changes)
{
if (!ProcessSingleChange(repo, new Models.DiffOption(baseRevision, targetRevision, change), sw))
return false;
}
}
return true;
}
private static bool ProcessSingleChange(string repo, Models.DiffOption opt, FileStream writer)
{
var starter = new ProcessStartInfo();

View file

@ -30,7 +30,7 @@ namespace SourceGit.Models
public string Arguments
{
get => _arguments;
get => _arguments;
set => SetProperty(ref _arguments, value);
}

View file

@ -63,7 +63,7 @@ namespace SourceGit.Models
{
public string File { get; set; } = string.Empty;
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
public Vector SyncScrollOffset { get; set; } = Vector.Zero;
public Vector ScrollOffset { get; set; } = Vector.Zero;
public int MaxLineNumber = 0;
public string Repo { get; set; } = null;
@ -674,6 +674,8 @@ namespace SourceGit.Models
{
public bool IsBinary { get; set; } = false;
public bool IsLFS { get; set; } = false;
public string OldHash { get; set; } = string.Empty;
public string NewHash { get; set; } = string.Empty;
public string OldMode { get; set; } = string.Empty;
public string NewMode { get; set; } = string.Empty;
public TextDiff TextDiff { get; set; } = null;

View file

@ -4,10 +4,5 @@
{
public bool IsError { get; set; } = false;
public string Message { get; set; } = string.Empty;
public void CopyMessage()
{
App.CopyText(Message);
}
}
}

View file

@ -325,8 +325,8 @@ namespace SourceGit.Native
if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is Microsoft.Win32.RegistryKey launcher)
{
// Get actual path to the executable
if (launcher.GetValue(string.Empty) is string CLSID &&
localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv &&
if (launcher.GetValue(string.Empty) is string CLSID &&
localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv &&
devenv.GetValue(string.Empty) is string localServer32)
{
return localServer32!.Trim('\"');
@ -353,23 +353,26 @@ namespace SourceGit.Native
private string GenerateCommandlineArgsForVisualStudio(string repo)
{
var sln = FindVSSolutionFile(repo, 4);
var sln = FindVSSolutionFile(new DirectoryInfo(repo), 4);
return string.IsNullOrEmpty(sln) ? $"\"{repo}\"" : $"\"{sln}\"";
}
private string FindVSSolutionFile(string path, int leftDepth)
private string FindVSSolutionFile(DirectoryInfo dir, int leftDepth)
{
var found = Directory.GetFiles(path, "*.sln", SearchOption.TopDirectoryOnly);
if (found != null && found.Length > 0)
return Path.GetFullPath(found[0]);
var files = dir.GetFiles();
foreach (var f in files)
{
if (f.Name.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))
return f.FullName;
}
if (leftDepth <= 0)
return null;
var subfolders = Directory.GetDirectories(path);
foreach (var subfolder in subfolders)
var subDirs = dir.GetDirectories();
foreach (var subDir in subDirs)
{
var first = FindVSSolutionFile(subfolder, leftDepth - 1);
var first = FindVSSolutionFile(subDir, leftDepth - 1);
if (!string.IsNullOrEmpty(first))
return first;
}

View file

@ -1,6 +1,6 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StreamGeometry x:Key="Icons.Action">M41 512c0-128 46-241 138-333C271 87 384 41 512 41s241 46 333 138c92 92 138 205 138 333s-46 241-138 333c-92 92-205 138-333 138s-241-46-333-138C87 753 41 640 41 512zm87 0c0 108 36 195 113 271s164 113 271 113c108 0 195-36 271-113s113-164 113-271-36-195-113-271c-77-77-164-113-271-113-108 0-195 36-271 113C164 317 128 404 128 512zm256 148V292l195 113L768 512l-195 113-195 113v-77zm148-113-61 36V440l61 36 61 36-61 36z</StreamGeometry>
<StreamGeometry x:Key="Icons.AIAssist">M951 419a255 255 0 00-22-209 258 258 0 00-278-124A259 259 0 00213 178a255 255 0 00-171 124 258 258 0 0032 303 255 255 0 0022 210 258 258 0 00278 124A255 255 0 00566 1024a258 258 0 00246-179 256 256 0 00171-124 258 258 0 00-32-302zM566 957a191 191 0 01-123-44l6-3 204-118a34 34 0 0017-29v-287l86 50a3 3 0 012 2v238a192 192 0 01-192 192zM154 781a191 191 0 01-23-129l6 4 204 118a33 33 0 0033 0l249-144v99a3 3 0 01-1 3L416 851a192 192 0 01-262-70zM100 337a191 191 0 01101-84V495a33 33 0 0017 29l248 143-86 50a3 3 0 01-3 0l-206-119A192 192 0 01100 336zm708 164-249-145L645 307a3 3 0 013 0l206 119a192 192 0 01-29 346v-242a34 34 0 00-17-28zm86-129-6-4-204-119a33 33 0 00-33 0L401 394V294a3 3 0 011-3l206-119a192 192 0 01285 199zm-539 176-86-50a3 3 0 01-2-2V259a192 192 0 01315-147l-6 3-204 118a34 34 0 00-17 29zm47-101 111-64 111 64v128l-111 64-111-64z</StreamGeometry>
<StreamGeometry x:Key="Icons.AIAssist">M304 464a128 128 0 01128-128c71 0 128 57 128 128v224a32 32 0 01-64 0V592h-128v95a32 32 0 01-64 0v-224zm64 1v64h128v-64a64 64 0 00-64-64c-35 0-64 29-64 64zM688 337c18 0 32 14 32 32v319a32 32 0 01-32 32c-18 0-32-14-32-32v-319a32 32 0 0132-32zM84 911l60-143A446 446 0 0164 512C64 265 265 64 512 64s448 201 448 448-201 448-448 448c-54 0-105-9-153-27l-242 22a32 32 0 01-32-44zm133-150-53 126 203-18 13 5c41 15 85 23 131 23 212 0 384-172 384-384S724 128 512 128 128 300 128 512c0 82 26 157 69 220l20 29z</StreamGeometry>
<StreamGeometry x:Key="Icons.Archive">M296 392h64v64h-64zM296 582v160h128V582h-64v-62h-64v62zm80 48v64h-32v-64h32zM360 328h64v64h-64zM296 264h64v64h-64zM360 456h64v64h-64zM360 200h64v64h-64zM855 289 639 73c-6-6-14-9-23-9H192c-18 0-32 14-32 32v832c0 18 14 32 32 32h640c18 0 32-14 32-32V311c0-9-3-17-9-23zM790 326H602V138L790 326zm2 562H232V136h64v64h64v-64h174v216c0 23 19 42 42 42h216v494z</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>
@ -65,6 +65,7 @@
<StreamGeometry x:Key="Icons.LayoutHorizontal">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zM139 832V192c0-6 4-11 11-11h331v661H149c-6 0-11-4-11-11zm747 0c0 6-4 11-11 11H544v-661H875c6 0 11 4 11 11v640z</StreamGeometry>
<StreamGeometry x:Key="Icons.LayoutVertical">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zm-725 64h725c6 0 11 4 11 11v288h-747V192c0-6 4-11 11-11zm725 661H149c-6 0-11-4-11-11V544h747V832c0 6-4 11-11 11z</StreamGeometry>
<StreamGeometry x:Key="Icons.LFS">M40 9 15 23 15 31 9 28 9 20 34 5 24 0 0 14 0 34 25 48 25 28 49 14zM26 29 26 48 49 34 49 15z</StreamGeometry>
<StreamGeometry x:Key="Icons.Lines.All">M416 192m32 0 448 0q32 0 32 32l0 0q0 32-32 32l-448 0q-32 0-32-32l0 0q0-32 32-32ZM416 448m32 0 448 0q32 0 32 32l0 0q0 32-32 32l-448 0q-32 0-32-32l0 0q0-32 32-32ZM416 704m32 0 448 0q32 0 32 32l0 0q0 32-32 32l-448 0q-32 0-32-32l0 0q0-32 32-32ZM96 320l128-192 128 192h-256zM96 640l128 192 128-192h-256zM190 320h64v320H190z</StreamGeometry>
<StreamGeometry x:Key="Icons.Lines.Incr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l132 0 0-128 64 0 0 128 132 0 0 64-132 0 0 128-64 0 0-128-132 0Z</StreamGeometry>
<StreamGeometry x:Key="Icons.Lines.Decr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l328 0 0 64-328 0Z</StreamGeometry>
<StreamGeometry x:Key="Icons.Link">M 968 418 l -95 94 c -59 59 -146 71 -218 37 L 874 331 a 64 64 0 0 0 0 -90 L 783 150 a 64 64 0 0 0 -90 0 L 475 368 c -34 -71 -22 -159 37 -218 l 94 -94 c 75 -75 196 -75 271 0 l 90 90 c 75 75 75 196 0 271 z M 332 693 a 64 64 0 0 1 0 -90 l 271 -271 c 25 -25 65 -25 90 0 s 25 65 0 90 L 422 693 a 64 64 0 0 1 -90 0 z M 151 783 l 90 90 a 64 64 0 0 0 90 0 l 218 -218 c 34 71 22 159 -37 218 l -86 94 a 192 192 0 0 1 -271 0 l -98 -98 a 192 192 0 0 1 0 -271 l 94 -86 c 59 -59 146 -71 218 -37 L 151 693 a 64 64 0 0 0 0 90 z</StreamGeometry>

View file

@ -180,15 +180,14 @@
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">Farbe</x:String>
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">Zuletzt geöffnete Tabs beim Starten wiederherstellen</x:String>
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">Konventionelle Commit-Hilfe</x:String>
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">Inkompatible Änderung:</x:String>
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">Breaking Change:</x:String>
<x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">Geschlossenes Ticket:</x:String>
<x:String x:Key="Text.ConventionalCommit.Detail" xml:space="preserve">Änderungen im Detail:</x:String>
<x:String x:Key="Text.ConventionalCommit.Scope" xml:space="preserve">Geltungsbereich:</x:String>
<x:String x:Key="Text.ConventionalCommit.Scope" xml:space="preserve">Gültigkeitsbereich:</x:String>
<x:String x:Key="Text.ConventionalCommit.ShortDescription" xml:space="preserve">Kurzbeschreibung:</x:String>
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Art der Änderung:</x:String>
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Typ der Änderung:</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Kopieren</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Kopiere gesamten Text</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COMMIT-NACHRICHT KOPIEREN</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Pfad kopieren</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Dateinamen kopieren</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Branch erstellen...</x:String>
@ -426,7 +425,6 @@
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API Schlüssel</x:String>
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generiere Nachricht Befehl</x:String>
<x:String x:Key="Text.Preference.AI.Name" xml:space="preserve">Name</x:String>
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">Server</x:String>
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Modell</x:String>
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">DARSTELLUNG</x:String>
@ -533,7 +531,7 @@
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">WEITER</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Benutzerdefinierte Aktionen</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">Keine benutzerdefinierten Aktionen</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Option '--reflog' einschalten</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Aktiviere '--reflog' Option</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Öffne im Datei-Browser</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Suche Branches/Tags/Submodule</x:String>
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">GEFILTERT:</x:String>

View file

@ -18,8 +18,8 @@
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Optional. Default is the destination folder name.</x:String>
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Track Branch:</x:String>
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Tracking remote branch</x:String>
<x:String x:Key="Text.AIAssistant" xml:space="preserve">OpenAI Assistant</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use OpenAI to generate commit message</x:String>
<x:String x:Key="Text.AIAssistant" xml:space="preserve">AI Assistant</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use AI to generate commit message</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Patch</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">Raise errors and refuses to apply the patch</x:String>
@ -166,7 +166,7 @@
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Rule Name:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">Result URL:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Please use $1, $2 to access regex groups values.</x:String>
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">OPEN AI</x:String>
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">Prefered Service:</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">If the 'Prefered Service' is set, SourceGit will only use it in this repository. Otherwise, if there is more than one service available, a context menu to choose one of them will be shown.</x:String>
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP Proxy</x:String>
@ -185,7 +185,6 @@
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Type of Change:</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Copy</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Copy All Text</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COPY MESSAGE</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Copy Path</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copy File Name</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Create Branch...</x:String>
@ -238,6 +237,7 @@
<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.Prev" xml:space="preserve">Previous Difference</x:String>
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">Save as Patch</x:String>
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Show hidden symbols</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Side-By-Side Diff</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SUBMODULE</x:String>
@ -246,6 +246,7 @@
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Line Word Wrap</x:String>
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Open in Merge Tool</x:String>
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Show All Lines</x:String>
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Decrease Number of Visible Lines</x:String>
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Increase Number of Visible Lines</x:String>
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECT FILE TO VIEW CHANGES</x:String>
@ -274,7 +275,7 @@
<x:String x:Key="Text.FileCM.DiscardMulti" xml:space="preserve">Discard {0} files...</x:String>
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">Discard Changes in Selected Line(s)</x:String>
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Open External Merge Tool</x:String>
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Save As Patch...</x:String>
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Save as Patch...</x:String>
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">Stage</x:String>
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">Stage {0} files</x:String>
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Stage Changes in Selected Line(s)</x:String>
@ -362,8 +363,12 @@
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Commit staged changes</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Commit and push staged changes</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">Stage all changes and commit</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CreateBranchOnCommit" xml:space="preserve">Creates a new branch based on selected commit</x:String>
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">Discard selected changes</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Fetch" xml:space="preserve">Fetch, starts directly</x:String>
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">Dashboard mode (Default)</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Pull" xml:space="preserve">Pull, starts directly</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Push" xml:space="preserve">Push, starts directly</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">Force to reload this repository</x:String>
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">Stage/Unstage selected changes</x:String>
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">Commit search mode</x:String>
@ -387,6 +392,8 @@
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Interactive Rebase</x:String>
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">Target Branch:</x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">On:</x:String>
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Open in Browser</x:String>
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">Copy Link</x:String>
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERROR</x:String>
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">NOTICE</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Branch</x:String>
@ -398,7 +405,7 @@
<x:String x:Key="Text.Name" xml:space="preserve">Name:</x:String>
<x:String x:Key="Text.NotConfigured" xml:space="preserve">Git has NOT been configured. Please to go [Preference] and configure it first.</x:String>
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">Open App Data Dir</x:String>
<x:String x:Key="Text.OpenWith" xml:space="preserve">Open With...</x:String>
<x:String x:Key="Text.OpenWith" xml:space="preserve">Open with...</x:String>
<x:String x:Key="Text.Optional" xml:space="preserve">Optional.</x:String>
<x:String x:Key="Text.PageTabBar.New" xml:space="preserve">Create New Page</x:String>
<x:String x:Key="Text.PageTabBar.Tab.Bookmark" xml:space="preserve">Bookmark</x:String>
@ -418,7 +425,7 @@
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">Last year</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} years ago</x:String>
<x:String x:Key="Text.Preference" xml:space="preserve">Preference</x:String>
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OPEN AI</x:String>
<x:String x:Key="Text.Preference.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API Key</x:String>
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
@ -428,6 +435,7 @@
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">APPEARANCE</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">Default Font</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">Default Font Size</x:String>
<x:String x:Key="Text.Preference.Appearance.EditorFontSize" xml:space="preserve">Editor Font Size</x:String>
<x:String x:Key="Text.Preference.Appearance.MonospaceFont" xml:space="preserve">Monospace Font</x:String>
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">Only use monospace font in text editor</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">Theme</x:String>
@ -530,15 +538,15 @@
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Custom Actions</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">No Custom Actions</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Enable '--reflog' Option</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open In File Browser</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open in File Browser</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Search Branches/Tags/Submodules</x:String>
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">FILTERED BY:</x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOCAL BRANCHES</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate To HEAD</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate to HEAD</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Enable '--first-parent' Option</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Open In {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open In External Tools</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Open in {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open in External Tools</x:String>
<x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Refresh</x:String>
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String>
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADD REMOTE</x:String>
@ -556,7 +564,7 @@
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">UPDATE SUBMODULE</x:String>
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEW TAG</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open In Terminal</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ADD WORKTREE</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>

View file

@ -73,6 +73,7 @@
<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.CheckoutFirstParentRevision" xml:space="preserve">Resetear a Revisión Padre</x:String>
<x:String x:Key="Text.ChangeCM.GenerateCommitMessage" xml:space="preserve">Generar mensaje de commit</x:String>
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">CAMBIAR MODO DE VISUALIZACIÓN</x:String>
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Mostrar como Lista de Archivos y Directorios</x:String>
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Mostrar como Lista de Rutas</x:String>
@ -110,7 +111,10 @@
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Comparar con Worktree</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copiar Información</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copiar SHA</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Acción personalizada</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Rebase Interactivo ${0}$ hasta Aquí</x:String>
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Abrir en el Navegador</x:String>
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">Copiar Enlace</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ hasta Aquí</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ hasta Aquí</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Revertir Commit</x:String>
@ -141,12 +145,21 @@
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">PLANTILLA DE COMMIT</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Nombre de la Plantilla:</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Contenido de la Plantilla:</x:String>
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">ACCIÓN PERSONALIZADA</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">Argumentos:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">${REPO} - Ruta del repositorio; ${SHA} - SHA del commit seleccionado</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.Scope" xml:space="preserve">Alcance:</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.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.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Fetch remotos automáticamente</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minuto(s)</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Remoto por Defecto</x:String>
<x:String x:Key="Text.Configure.Git.EnablePruneOnFetch" xml:space="preserve">Habilitar --prune para fetch</x:String>
<x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">Habilitar --signoff para commit</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">SEGUIMIENTO DE INCIDENCIAS</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Añadir Regla de Ejemplo para Github</x:String>
@ -158,6 +171,9 @@
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Nombre de la Regla:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">URL Resultante:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Por favor, use $1, $2 para acceder a los valores de los grupos regex.</x:String>
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">OPEN AI</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">Servicio Preferido:</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">Si el 'Servicio Preferido' está establecido, SourceGit sólo lo usará en este repositorio. De lo contrario, si hay más de un servicio disponible, se mostrará un menú de contexto para elegir uno.</x:String>
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">Proxy HTTP</x:String>
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">Proxy HTTP utilizado por este repositorio</x:String>
<x:String x:Key="Text.Configure.User" xml:space="preserve">Nombre de Usuario</x:String>
@ -174,7 +190,6 @@
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Tipo de Cambio:</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Copiar</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Copiar Todo el Texto</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COPIAR MENSAJE</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Copiar Ruta</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copiar Nombre del Archivo</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Crear Rama...</x:String>
@ -235,6 +250,7 @@
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Resaltado de Sintaxis</x:String>
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Ajuste de Línea</x:String>
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Abrir en Herramienta de Merge</x:String>
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Mostrar Todas las Líneas</x:String>
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Disminuir Número de Líneas Visibles</x:String>
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Aumentar Número de Líneas Visibles</x:String>
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECCIONA ARCHIVO PARA VER CAMBIOS</x:String>
@ -250,6 +266,8 @@
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Destino:</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Editar Grupo Seleccionado</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Editar Repositorio Seleccionado</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Ejecutar Acción Personalizada</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nombre de la Acción:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (sin checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch todos los remotos</x:String>
@ -411,6 +429,7 @@
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">Clave API</x:String>
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generar Subject Prompt</x:String>
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Modelo</x:String>
<x:String x:Key="Text.Preference.AI.Name" xml:space="preserve">Nombre</x:String>
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">Servidor</x:String>
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">APARIENCIA</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">Fuente por defecto</x:String>
@ -514,6 +533,8 @@
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Limpiar todo</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configurar este repositorio</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUAR</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Acciones Personalizadas</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">No hay ninguna Acción Personalizada</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Habilitar Opción '--reflog'</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Abrir en el Explorador</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Buscar Ramas/Etiquetas/Submódulos</x:String>
@ -576,6 +597,7 @@
<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.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.Message" xml:space="preserve">Mensaje:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Opcional. Nombre de este stash</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Solo cambios staged</x:String>

View file

@ -152,7 +152,6 @@
<x:String x:Key="Text.Copy" xml:space="preserve">Copier</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Copier tout le texte</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copier le nom de fichier</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COPIER LE MESSAGE</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Copier le chemin</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Créer une branche...</x:String>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Basé sur :</x:String>

View file

@ -148,7 +148,6 @@
<x:String x:Key="Text.Configure" xml:space="preserve">Configurar Repositório</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Copiar</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copiar Nome do Arquivo</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COPIAR MENSAGEM</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Copiar Caminho</x:String>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Baseado Em:</x:String>
<x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">Checar o branch criado</x:String>

View file

@ -189,7 +189,6 @@
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Тип изменения:</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Копировать</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Копировать весь текст</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">КОПИРОВАТЬ СООБЩЕНИЕ</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Копировать путь</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Копировать имя файла</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Создать ветку...</x:String>
@ -243,6 +242,7 @@
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Следующее различие</x:String>
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">НИКАКИХ ИЗМЕНЕНИЙ ИЛИ МЕНЯЕТСЯ ТОЛЬКО EOL</x:String>
<x:String x:Key="Text.Diff.Prev" xml:space="preserve">Предыдущее различие</x:String>
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">Сохранить как исправление</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Различие бок о бок</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">ПОДМОДУЛЬ</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">НОВЫЙ</x:String>
@ -250,6 +250,7 @@
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Подсветка синтаксиса </x:String>
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Перенос слов в строке</x:String>
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Открыть в инструменте слияния </x:String>
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Показывать все линии</x:String>
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Уменьшить количество видимых линий</x:String>
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Увеличить количество видимых линий</x:String>
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">ВЫБРАТЬ ФАЙЛ ДЛЯ ПРОСМОТРА ИЗМЕНЕНИЙ</x:String>
@ -366,9 +367,13 @@
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Зафиксировать подготовленные изменения</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Зафиксировать и выложить подготовленные изменения</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">Подготовить все изменения и зафиксировать</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CreateBranchOnCommit" xml:space="preserve">Создать новую ветку на основе выбранной ветки</x:String>
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">Отклонить выбранные изменения</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Fetch" xml:space="preserve">Извлечение, запускается непосредственно</x:String>
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">Режим доски (по-умолчанию)</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">Принудительно перезагрузить этот хранилище</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Pull" xml:space="preserve">Забрать, запускается непосредственно</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Push" xml:space="preserve">Выложить, запускается непосредственно</x:String>
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">Подготовленные/Неподготовленные выбранные изменения</x:String>
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">Режим поиска фиксаций</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewChanges" xml:space="preserve">Переключить на «Изменения»</x:String>
@ -391,7 +396,9 @@
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Интерактивное перемещение</x:String>
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">Целевая ветка:</x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">На:</x:String>
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ОШИБКА</x:String>
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Открыть в браузере</x:String>
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">Копировать ссылку</x:String>
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ОШИБКА</x:String>
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">УВЕДОМЛЕНИЕ</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Слить ветку</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">В:</x:String>
@ -432,6 +439,7 @@
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">ВИД</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">Шрифт по-умолчанию</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">Размер шрифта по-умолчанию</x:String>
<x:String x:Key="Text.Preference.Appearance.EditorFontSize" xml:space="preserve">Размер шрифта редактора</x:String>
<x:String x:Key="Text.Preference.Appearance.MonospaceFont" xml:space="preserve">Моноширный шрифт</x:String>
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">В текстовом редакторе используется только моноширный шрифт</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">Тема</x:String>

View file

@ -21,8 +21,8 @@
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">选填。默认使用目标文件夹名称。</x:String>
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟踪分支</x:String>
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">设置上游跟踪分支</x:String>
<x:String x:Key="Text.AIAssistant" xml:space="preserve">OpenAI助手</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用OpenAI助手生成提交信息</x:String>
<x:String x:Key="Text.AIAssistant" xml:space="preserve">AI助手</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用AI助手生成提交信息</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">应用补丁(apply)</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">错误</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">输出错误,并终止应用补丁</x:String>
@ -169,9 +169,9 @@
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">规则名 </x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">为ISSUE生成的URL链接 </x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">可在URL中使用$1$2等变量填入正则表达式匹配的内容</x:String>
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">OPEN AI</x:String>
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">启用特定服务 </x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">当【启用特定服务】被设置时SourceGit将在本仓库中仅使用该服务。否则将弹出可用的OpenAI服务列表供用户选择。</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">当【启用特定服务】被设置时SourceGit将在本仓库中仅使用该服务。否则将弹出可用的AI服务列表供用户选择。</x:String>
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP代理</x:String>
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP网络代理</x:String>
<x:String x:Key="Text.Configure.User" xml:space="preserve">用户名</x:String>
@ -188,7 +188,6 @@
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">类型:</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">复制</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">复制全部文本</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">复制内容</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">复制路径</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">复制文件名</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">新建分支 ...</x:String>
@ -241,6 +240,7 @@
<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.Prev" xml:space="preserve">上一个差异</x:String>
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">保存为补丁文件</x:String>
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">显示隐藏符号</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">分列对比</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">子模块</x:String>
@ -249,6 +249,7 @@
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">语法高亮</x:String>
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">自动换行</x:String>
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合并工具查看</x:String>
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">显示完整文件</x:String>
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">减少可见的行数</x:String>
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可见的行数</x:String>
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">请选择需要对比的文件</x:String>
@ -365,8 +366,12 @@
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">提交暂存区更改</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">提交暂存区更改并推送</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">自动暂存全部变更并提交</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CreateBranchOnCommit" xml:space="preserve">基于选中提交创建新分支</x:String>
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">丢弃选中的更改</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Fetch" xml:space="preserve">拉取 (fetch) 远程变更</x:String>
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">切换左边栏为分支/标签等显示模式(默认)</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Pull" xml:space="preserve">拉回 (pull) 远程变更</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Push" xml:space="preserve">推送本地变更到远程</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">重新加载仓库状态</x:String>
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">将选中的变更暂存或从暂存列表中移除</x:String>
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">切换左边栏为提交搜索模式</x:String>
@ -390,6 +395,8 @@
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">交互式变基</x:String>
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">目标分支 </x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">起始提交 </x:String>
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">在浏览器中访问</x:String>
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">复制链接地址</x:String>
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">出错了</x:String>
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系统提示</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">合并分支</x:String>
@ -421,7 +428,7 @@
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0}年前</x:String>
<x:String x:Key="Text.Preference" xml:space="preserve">偏好设置</x:String>
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OPEN AI</x:String>
<x:String x:Key="Text.Preference.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API密钥</x:String>
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
@ -431,6 +438,7 @@
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">外观配置</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">缺省字体</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">默认字体大小</x:String>
<x:String x:Key="Text.Preference.Appearance.EditorFontSize" xml:space="preserve">代码字体大小</x:String>
<x:String x:Key="Text.Preference.Appearance.MonospaceFont" xml:space="preserve">等宽字体</x:String>
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">仅在文本编辑器中使用等宽字体</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">主题</x:String>

View file

@ -21,8 +21,8 @@
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">選填。預設使用目標資料夾名稱。</x:String>
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">追蹤分支</x:String>
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">設定遠端追蹤分支</x:String>
<x:String x:Key="Text.AIAssistant" xml:space="preserve">OpenAI 助理</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用 OpenAI 產生提交訊息</x:String>
<x:String x:Key="Text.AIAssistant" xml:space="preserve">AI 助理</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用 AI 產生提交訊息</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">套用修補檔 (apply patch)</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">錯誤</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">輸出錯誤,並中止套用修補檔</x:String>
@ -169,9 +169,9 @@
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">規則名稱:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">為 Issue 產生的網址連結:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">可在網址中使用 $1、$2 等變數填入正規表達式相符的內容</x:String>
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">OpenAI</x:String>
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">偏好服務:</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">設定 [偏好服務] 後SourceGit 將於此存放庫中使用該服務,否則會顯示 OpenAI 服務列表供使用者選擇。</x:String>
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">設定 [偏好服務] 後SourceGit 將於此存放庫中使用該服務,否則會顯示 AI 服務列表供使用者選擇。</x:String>
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP 代理</x:String>
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP 網路代理</x:String>
<x:String x:Key="Text.Configure.User" xml:space="preserve">使用者名稱</x:String>
@ -188,7 +188,6 @@
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">類型:</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">複製</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">複製全部內容</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">複製內容</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">複製路徑</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">複製檔案名稱</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">新增分支...</x:String>
@ -241,6 +240,7 @@
<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.Prev" xml:space="preserve">上一個差異</x:String>
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">另存為修補檔</x:String>
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">顯示隱藏符號</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">並排對比</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">子模組</x:String>
@ -249,6 +249,7 @@
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">語法上色</x:String>
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">自動換行</x:String>
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合併工具檢視</x:String>
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">顯示檔案的全部內容</x:String>
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">減少可見的行數</x:String>
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可見的行數</x:String>
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">請選擇需要對比的檔案</x:String>
@ -365,8 +366,12 @@
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">提交暫存區變更</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">提交暫存區變更並推送</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">自動暫存全部變更並提交</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CreateBranchOnCommit" xml:space="preserve">根據選取的提交建立新的分支</x:String>
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">捨棄選取的變更</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Fetch" xml:space="preserve">提取 (fetch) 遠端的變更</x:String>
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">切換左邊欄為分支/標籤等顯示模式 (預設)</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Pull" xml:space="preserve">拉取 (pull) 遠端的變更</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Push" xml:space="preserve">推送 (push) 本地變更到遠端存放庫</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">強制重新載入存放庫</x:String>
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">暫存或取消暫存選取的變更</x:String>
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">切換左邊欄為歷史搜尋模式</x:String>
@ -390,6 +395,8 @@
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">互動式重定基底</x:String>
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">目標分支:</x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">起始提交:</x:String>
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">在瀏覽器中存取網址</x:String>
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">複製網址</x:String>
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">發生錯誤</x:String>
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系統提示</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">合併分支</x:String>
@ -421,7 +428,7 @@
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String>
<x:String x:Key="Text.Preference" xml:space="preserve">偏好設定</x:String>
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OpenAI</x:String>
<x:String x:Key="Text.Preference.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">伺服器</x:String>
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API 金鑰</x:String>
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">模型</x:String>
@ -431,6 +438,7 @@
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">外觀設定</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">預設字型</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">預設字型大小</x:String>
<x:String x:Key="Text.Preference.Appearance.EditorFontSize" xml:space="preserve">程式碼字型大小</x:String>
<x:String x:Key="Text.Preference.Appearance.MonospaceFont" xml:space="preserve">等寬字型</x:String>
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">僅在文字編輯器中使用等寬字型</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">佈景主題</x:String>

View file

@ -24,7 +24,6 @@
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<OptimizationPreference>Speed</OptimizationPreference>
</PropertyGroup>
<ItemGroup>

View file

@ -33,12 +33,6 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _fileModeChange, value);
}
public bool IsLoading
{
get => _isLoading;
private set => SetProperty(ref _isLoading, value);
}
public bool IsTextDiff
{
get => _isTextDiff;
@ -68,6 +62,7 @@ namespace SourceGit.ViewModels
_content = previous._content;
_unifiedLines = previous._unifiedLines;
_ignoreWhitespace = previous._ignoreWhitespace;
_info = previous._info;
}
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
@ -78,6 +73,12 @@ namespace SourceGit.ViewModels
LoadDiffContent();
}
public void ToggleFullTextDiff()
{
Preference.Instance.UseFullTextDiff = !Preference.Instance.UseFullTextDiff;
LoadDiffContent();
}
public void IncrUnified()
{
UnifiedLines = _unifiedLines + 1;
@ -103,15 +104,23 @@ namespace SourceGit.ViewModels
{
Content = null;
IsTextDiff = false;
IsLoading = false;
return;
}
Task.Run(() =>
{
var latest = new Commands.Diff(_repo, _option, _unifiedLines, _ignoreWhitespace).Result();
var rs = null as object;
// NOTE: Here we override the UnifiedLines value (if UseFullTextDiff is on).
// There is no way to tell a git-diff to use "ALL lines of context",
// so instead we set a very high number for the "lines of context" parameter.
var numLines = Preference.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
var latest = new Commands.Diff(_repo, _option, numLines, _ignoreWhitespace).Result();
var info = new Info(_option, numLines, _ignoreWhitespace, latest);
if (_info != null && info.IsSame(_info))
return;
_info = info;
var rs = null as object;
if (latest.TextDiff != null)
{
var count = latest.TextDiff.Lines.Count;
@ -203,12 +212,11 @@ namespace SourceGit.ViewModels
Dispatcher.UIThread.Post(() =>
{
if (_content is Models.TextDiff old && rs is Models.TextDiff cur && old.File == cur.File)
cur.SyncScrollOffset = old.SyncScrollOffset;
cur.ScrollOffset = old.ScrollOffset;
FileModeChange = latest.FileModeChange;
Content = rs;
IsTextDiff = rs is Models.TextDiff;
IsLoading = false;
});
});
}
@ -241,14 +249,41 @@ namespace SourceGit.ViewModels
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
};
private class Info
{
public string Argument { get; set; }
public int UnifiedLines { get; set; }
public bool IgnoreWhitespace { get; set; }
public string OldHash { get; set; }
public string NewHash { get; set; }
public Info(Models.DiffOption option, int unifiedLines, bool ignoreWhitespace, Models.DiffResult result)
{
Argument = option.ToString();
UnifiedLines = unifiedLines;
IgnoreWhitespace = ignoreWhitespace;
OldHash = result.OldHash;
NewHash = result.NewHash;
}
public bool IsSame(Info other)
{
return Argument.Equals(other.Argument, StringComparison.Ordinal) &&
UnifiedLines == other.UnifiedLines &&
IgnoreWhitespace == other.IgnoreWhitespace &&
OldHash.Equals(other.OldHash, StringComparison.Ordinal) &&
NewHash.Equals(other.NewHash, StringComparison.Ordinal);
}
}
private readonly string _repo;
private readonly Models.DiffOption _option = null;
private string _title;
private string _fileModeChange = string.Empty;
private int _unifiedLines = 4;
private bool _isLoading = true;
private bool _isTextDiff = false;
private bool _ignoreWhitespace = false;
private object _content = null;
private Info _info = null;
}
}

View file

@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
@ -258,6 +259,44 @@ namespace SourceGit.ViewModels
multipleMenu.Items.Add(new MenuItem() { Header = "-" });
}
var saveToPatchMultiple = new MenuItem();
saveToPatchMultiple.Icon = App.CreateMenuIcon("Icons.Diff");
saveToPatchMultiple.Header = App.Text("CommitCM.SaveAsPatch");
saveToPatchMultiple.Click += async (_, e) =>
{
var storageProvider = App.GetStorageProvider();
if (storageProvider == null)
return;
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
try
{
var picker = await storageProvider.OpenFolderPickerAsync(options);
if (picker.Count == 1)
{
var saveTo = $"{picker[0].Path.LocalPath}/patches";
var succ = false;
foreach (var c in selected)
{
succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, c.SHA, saveTo).Exec());
if (!succ)
break;
}
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}
}
catch (Exception exception)
{
App.RaiseException(_repo.FullPath, $"Failed to save as patch: {exception.Message}");
}
e.Handled = true;
};
multipleMenu.Items.Add(saveToPatchMultiple);
multipleMenu.Items.Add(new MenuItem() { Header = "-" });
var copyMultipleSHAs = new MenuItem();
copyMultipleSHAs.Header = App.Text("CommitCM.CopySHA");
copyMultipleSHAs.Icon = App.CreateMenuIcon("Icons.Copy");

View file

@ -102,6 +102,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _defaultFontSize, value);
}
public double EditorFontSize
{
get => _editorFontSize;
set => SetProperty(ref _editorFontSize, value);
}
public LayoutInfo Layout
{
get => _layout;
@ -186,6 +192,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _showHiddenSymbolsInDiffView, value);
}
public bool UseFullTextDiff
{
get => _useFullTextDiff;
set => SetProperty(ref _useFullTextDiff, value);
}
public Models.ChangeViewMode UnstagedChangeViewMode
{
get => _unstagedChangeViewMode;
@ -573,6 +585,7 @@ namespace SourceGit.ViewModels
private bool _onlyUseMonoFontInEditor = false;
private bool _useSystemWindowFrame = false;
private double _defaultFontSize = 13;
private double _editorFontSize = 13;
private LayoutInfo _layout = new LayoutInfo();
private int _maxHistoryCommits = 20000;
@ -591,6 +604,7 @@ namespace SourceGit.ViewModels
private bool _useSyntaxHighlighting = false;
private bool _enableDiffViewWordWrap = false;
private bool _showHiddenSymbolsInDiffView = false;
private bool _useFullTextDiff = false;
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;

View file

@ -24,6 +24,11 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _endPoint, value);
}
public bool CanSaveAsPatch
{
get => _canSaveAsPatch;
}
public List<Models.Change> VisibleChanges
{
get => _visibleChanges;
@ -73,6 +78,7 @@ namespace SourceGit.ViewModels
_repo = repo;
_startPoint = (object)startPoint ?? new Models.Null();
_endPoint = (object)endPoint ?? new Models.Null();
_canSaveAsPatch = startPoint != null && endPoint != null;
Task.Run(Refresh);
}
@ -105,6 +111,16 @@ namespace SourceGit.ViewModels
Task.Run(Refresh);
}
public void SaveAsPatch(string saveTo)
{
Task.Run(() =>
{
var succ = Commands.SaveChangesAsPatch.ProcessRevisionCompareChanges(_repo, _changes, GetSHA(_startPoint), GetSHA(_endPoint), saveTo);
if (succ)
Dispatcher.UIThread.Invoke(() => App.SendNotification(_repo, App.Text("SaveAsPatchSuccess")));
});
}
public void ClearSearchFilter()
{
SearchFilter = string.Empty;
@ -218,6 +234,7 @@ namespace SourceGit.ViewModels
private string _repo;
private object _startPoint = null;
private object _endPoint = null;
private bool _canSaveAsPatch = false;
private List<Models.Change> _changes = null;
private List<Models.Change> _visibleChanges = null;
private List<Models.Change> _selectedChanges = null;

View file

@ -539,7 +539,7 @@ namespace SourceGit.ViewModels
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedUnstaged, true, storageFile.Path.LocalPath));
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessLocalChanges(_repo.FullPath, _selectedUnstaged, true, storageFile.Path.LocalPath));
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}
@ -599,7 +599,8 @@ namespace SourceGit.ViewModels
byParentFolder.IsVisible = !isRooted;
byParentFolder.Click += (_, e) =>
{
Commands.GitIgnore.Add(_repo.FullPath, Path.GetDirectoryName(change.Path) + "/");
var path = Path.GetDirectoryName(change.Path).Replace("\\", "/");
Commands.GitIgnore.Add(_repo.FullPath, path + "/");
e.Handled = true;
};
addToIgnore.Items.Add(byParentFolder);
@ -620,7 +621,8 @@ namespace SourceGit.ViewModels
byExtensionInSameFolder.IsVisible = !isRooted;
byExtensionInSameFolder.Click += (_, e) =>
{
Commands.GitIgnore.Add(_repo.FullPath, Path.GetDirectoryName(change.Path) + "/*" + extension);
var path = Path.GetDirectoryName(change.Path).Replace("\\", "/");
Commands.GitIgnore.Add(_repo.FullPath, path + "/*" + extension);
e.Handled = true;
};
addToIgnore.Items.Add(byExtensionInSameFolder);
@ -858,7 +860,7 @@ namespace SourceGit.ViewModels
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedUnstaged, true, storageFile.Path.LocalPath));
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessLocalChanges(_repo.FullPath, _selectedUnstaged, true, storageFile.Path.LocalPath));
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}
@ -981,7 +983,7 @@ namespace SourceGit.ViewModels
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedStaged, false, storageFile.Path.LocalPath));
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessLocalChanges(_repo.FullPath, _selectedStaged, false, storageFile.Path.LocalPath));
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}
@ -1156,7 +1158,7 @@ namespace SourceGit.ViewModels
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedStaged, false, storageFile.Path.LocalPath));
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessLocalChanges(_repo.FullPath, _selectedStaged, false, storageFile.Path.LocalPath));
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}

View file

@ -57,6 +57,7 @@
Background="Transparent"
Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=EditorFontSize}"
BlameData="{Binding Data}"/>
<!-- Not supported mask (for binary files) -->

View file

@ -407,8 +407,8 @@ namespace SourceGit.Views
var menu = new ContextMenu();
menu.Items.Add(copy);
menu.Open(TextArea.TextView);
TextArea.TextView.OpenContextMenu(menu);
e.Handled = true;
}

View file

@ -15,7 +15,7 @@ namespace SourceGit.Views
if (DataContext is ViewModels.BranchCompare vm && sender is ChangeCollectionView view)
{
var menu = vm.CreateChangeContextMenu();
view.OpenContextMenu(menu);
menu?.Open(view);
}
e.Handled = true;

View file

@ -374,7 +374,7 @@ namespace SourceGit.Views
if (selected.Count == 1 && selected[0] is ViewModels.BranchTreeNode { Backend: Models.Remote remote })
{
var menu = repo.CreateContextMenuForRemote(remote);
this.OpenContextMenu(menu);
menu?.Open(this);
return;
}
@ -391,7 +391,7 @@ namespace SourceGit.Views
var menu = branch.IsLocal ?
repo.CreateContextMenuForLocalBranch(branch) :
repo.CreateContextMenuForRemoteBranch(branch);
this.OpenContextMenu(menu);
menu?.Open(this);
}
else if (branches.Find(x => x.IsCurrent) == null)
{
@ -405,7 +405,7 @@ namespace SourceGit.Views
ev.Handled = true;
};
menu.Items.Add(deleteMulti);
this.OpenContextMenu(menu);
menu?.Open(this);
}
}

View file

@ -141,7 +141,13 @@
Message="{Binding #ThisControl.Message}"
IssueTrackerRules="{Binding #ThisControl.IssueTrackerRules}"
HorizontalAlignment="Stretch"
TextWrapping="Wrap"/>
TextWrapping="Wrap">
<v:CommitMessagePresenter.Styles>
<Style Selector="ToolTip">
<Setter Property="MaxWidth" Value="800"/>
</Style>
</v:CommitMessagePresenter.Styles>
</v:CommitMessagePresenter>
</Grid>
</StackPanel>
</DataTemplate>

View file

@ -68,7 +68,7 @@ namespace SourceGit.Views
private void OnOpenWebLink(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.CommitDetail detail)
if (DataContext is ViewModels.CommitDetail detail && sender is Control control)
{
var links = WebLinks;
if (links.Count > 1)
@ -88,7 +88,7 @@ namespace SourceGit.Views
menu.Items.Add(item);
}
(sender as Control)?.OpenContextMenu(menu);
menu?.Open(control);
}
else if (links.Count == 1)
{

View file

@ -16,7 +16,7 @@ namespace SourceGit.Views
DataContext is ViewModels.CommitDetail vm)
{
var menu = vm.CreateChangeContextMenu(selected[0]);
view.OpenContextMenu(menu);
menu?.Open(view);
}
e.Handled = true;

View file

@ -26,7 +26,7 @@ namespace SourceGit.Views
if (DataContext is ViewModels.CommitDetail detail && sender is Grid grid && grid.DataContext is Models.Change change)
{
var menu = detail.CreateChangeContextMenu(change);
grid.OpenContextMenu(menu);
menu?.Open(grid);
}
e.Handled = true;

View file

@ -176,7 +176,38 @@ namespace SourceGit.Views
}
else
{
Native.OS.OpenBrowser(_lastHover.Link);
var point = e.GetCurrentPoint(this);
var link = _lastHover.Link;
if (point.Properties.IsLeftButtonPressed)
{
Native.OS.OpenBrowser(link);
}
else if (point.Properties.IsRightButtonPressed)
{
var open = new MenuItem();
open.Header = App.Text("IssueLinkCM.OpenInBrowser");
open.Icon = App.CreateMenuIcon("Icons.OpenWith");
open.Click += (_, ev) =>
{
Native.OS.OpenBrowser(link);
ev.Handled = true;
};
var copy = new MenuItem();
copy.Header = App.Text("IssueLinkCM.CopyLink");
copy.Icon = App.CreateMenuIcon("Icons.Copy");
copy.Click += (_, ev) =>
{
App.CopyText(link);
ev.Handled = true;
};
var menu = new ContextMenu();
menu.Items.Add(open);
menu.Items.Add(copy);
menu.Open(this);
}
}
e.Handled = true;

View file

@ -125,7 +125,7 @@ namespace SourceGit.Views
DescriptionEditor.CaretIndex = 0;
e.Handled = true;
}
else if (e.Key == Key.V && ((OperatingSystem.IsMacOS() && e.KeyModifiers == KeyModifiers.Meta) || (!OperatingSystem.IsMacOS() && e.KeyModifiers == KeyModifiers.Control)))
else if (e.Key == Key.V && e.KeyModifiers == (OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
{
e.Handled = true;

View file

@ -1,26 +0,0 @@
using System.ComponentModel;
using Avalonia.Controls;
namespace SourceGit.Views
{
public static class ContextMenuExtension
{
public static void OpenContextMenu(this Control control, ContextMenu menu)
{
if (menu == null)
return;
menu.PlacementTarget = control;
menu.Closing += OnContextMenuClosing; // Clear context menu because it is dynamic.
control.ContextMenu = menu;
control.ContextMenu?.Open();
}
private static void OnContextMenuClosing(object sender, CancelEventArgs e)
{
if (sender is ContextMenu menu && menu.PlacementTarget != null)
menu.PlacementTarget.ContextMenu = null;
}
}
}

View file

@ -39,6 +39,9 @@
Command="{Binding IncrUnified}"
IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
<Button.IsEnabled>
<Binding Source="{x:Static vm:Preference.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
</Button.IsEnabled>
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Incr}"/>
</Button>
@ -46,10 +49,26 @@
Width="32"
Command="{Binding DecrUnified}"
IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}"
IsEnabled="{Binding UnifiedLines, Converter={x:Static c:IntConverters.IsGreaterThanFour}}">
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}">
<Button.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="UnifiedLines" Mode="OneWay" Converter="{x:Static c:IntConverters.IsGreaterThanFour}"/>
<Binding Source="{x:Static vm:Preference.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
</MultiBinding>
</Button.IsEnabled>
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/>
</Button>
<ToggleButton Classes="line_path"
Width="32" Height="18"
Background="Transparent"
Padding="9,6"
Command="{Binding ToggleFullTextDiff}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.All}">
<Path Width="13" Height="13" Data="{StaticResource Icons.Lines.All}" Margin="0,3,0,0"/>
</ToggleButton>
<ToggleButton Classes="line_path"
Width="32" Height="18"
@ -211,7 +230,9 @@
<!-- Text Diff -->
<DataTemplate DataType="m:TextDiff">
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"/>
<v:TextDiffView
UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
UseFullTextDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"/>
</DataTemplate>
<!-- Empty or only EOL changes -->

View file

@ -706,7 +706,7 @@ namespace SourceGit.Views
if (DataContext is ViewModels.Histories histories && sender is ListBox { SelectedItems: { Count: > 0 } } list)
{
var menu = histories.MakeContextMenu(list);
list.OpenContextMenu(menu);
menu?.Open(list);
}
e.Handled = true;
}
@ -722,19 +722,39 @@ namespace SourceGit.Views
private void OnCommitListKeyDown(object sender, KeyEventArgs e)
{
if (sender is ListBox { SelectedItems: { Count: > 0 } selected } &&
e.Key == Key.C &&
e.KeyModifiers.HasFlag(KeyModifiers.Control))
if (!e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
return;
// These shortcuts are not mentioned in the Shortcut Reference window. Is this expected?
if (sender is ListBox { SelectedItems: { Count: > 0 } selected })
{
var builder = new StringBuilder();
foreach (var item in selected)
// CTRL/COMMAND + C -> Copy selected commit SHA and subject.
if (e.Key == Key.C)
{
if (item is Models.Commit commit)
builder.AppendLine($"{commit.SHA.Substring(0, 10)} - {commit.Subject}");
var builder = new StringBuilder();
foreach (var item in selected)
{
if (item is Models.Commit commit)
builder.AppendLine($"{commit.SHA.Substring(0, 10)} - {commit.Subject}");
}
App.CopyText(builder.ToString());
e.Handled = true;
return;
}
App.CopyText(builder.ToString());
e.Handled = true;
// CTRL/COMMAND + B -> shows Create Branch pop-up at selected commit.
if (e.Key == Key.B)
{
if (selected.Count == 1 &&
selected[0] is Models.Commit commit &&
DataContext is ViewModels.Histories histories &&
ViewModels.PopupHost.CanCreatePopup())
{
ViewModels.PopupHost.ShowPopup(new ViewModels.CreateBranch(histories.Repo, commit));
e.Handled = true;
}
}
}
}

View file

@ -71,7 +71,7 @@
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}"
Margin="0,8"/>
<Grid RowDefinitions="20,20,20,20,20,20,20,20,20,20,20" ColumnDefinitions="150,*">
<Grid RowDefinitions="20,20,20,20,20,20,20,20,20,20,20,20,20,20,20" ColumnDefinitions="150,*">
<TextBlock Grid.Row="0" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Shift+H, macOS=⌘+⇧+H}"/>
<TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.GoHome}" />
@ -102,8 +102,20 @@
<TextBlock Grid.Row="9" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Alt+Enter, macOS=⌥+Enter}"/>
<TextBlock Grid.Row="9" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.CommitAndPush}" />
<TextBlock Grid.Row="10" Grid.Column="0" Classes="primary bold" Text="F5"/>
<TextBlock Grid.Row="10" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Refresh}" />
<TextBlock Grid.Row="10" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Down, macOS=⌘+Down}"/>
<TextBlock Grid.Row="10" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Fetch}" />
<TextBlock Grid.Row="11" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Shift+Down, macOS=⌘+⇧+Down}"/>
<TextBlock Grid.Row="11" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Pull}" />
<TextBlock Grid.Row="12" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Shift+Up, macOS=⌘+⇧+Up}"/>
<TextBlock Grid.Row="12" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Push}" />
<TextBlock Grid.Row="13" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+B, macOS=⌘+B}"/>
<TextBlock Grid.Row="13" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.CreateBranchOnCommit}" />
<TextBlock Grid.Row="14" Grid.Column="0" Classes="primary bold" Text="F5"/>
<TextBlock Grid.Row="14" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Refresh}" />
</Grid>
<TextBlock Text="{DynamicResource Text.Hotkeys.TextEditor}"

View file

@ -115,8 +115,7 @@ namespace SourceGit.Views
return;
}
if ((OperatingSystem.IsMacOS() && e.KeyModifiers.HasFlag(KeyModifiers.Meta)) ||
(!OperatingSystem.IsMacOS() && e.KeyModifiers.HasFlag(KeyModifiers.Control)))
if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
{
if (e.Key == Key.W)
{
@ -250,7 +249,7 @@ namespace SourceGit.Views
if (sender is Button btn && DataContext is ViewModels.Launcher launcher)
{
var menu = launcher.CreateContextForWorkspace();
btn.OpenContextMenu(menu);
menu?.Open(btn);
}
e.Handled = true;

View file

@ -5,6 +5,7 @@
xmlns:m="using:SourceGit.Models"
xmlns:v="using:SourceGit.Views"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.LauncherPage"
x:DataType="vm:LauncherPage">
@ -38,103 +39,100 @@
</ContentControl.DataTemplates>
</ContentControl>
</Border>
<!-- Popup -->
<Grid Grid.Row="1" IsVisible="{Binding Popup, Converter={x:Static ObjectConverters.IsNotNull}}" ClipToBounds="True">
<Border Background="Transparent" PointerPressed="OnPopupCancelByClickMask"/>
<Border Width="500" HorizontalAlignment="Center" VerticalAlignment="Top" Effect="drop-shadow(0 0 8 #8F000000)" CornerRadius="0,0,8,8" ClipToBounds="True">
<ContentControl Content="{Binding Popup}" Background="{DynamicResource Brush.Popup}">
<ContentControl.DataTemplates>
<DataTemplate DataType="vm:Popup">
<StackPanel Orientation="Vertical" Background="{DynamicResource Brush.Popup}">
<!-- Popup Widget -->
<ContentPresenter Margin="8,16,8,8"
Content="{Binding View}"
IsHitTestVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}"/>
<!-- Floating -->
<Grid Grid.Row="1" ClipToBounds="True">
<Grid.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.Or}">
<Binding Path="Popup" Converter="{x:Static ObjectConverters.IsNotNull}"/>
<Binding Path="Notifications.Count" Converter="{x:Static c:IntConverters.IsGreaterThanZero}"/>
</MultiBinding>
</Grid.IsVisible>
<!-- Options -->
<StackPanel Margin="8,4,8,8"
Height="32"
Orientation="Horizontal"
HorizontalAlignment="Right"
IsVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}">
<Button Classes="flat primary"
Width="80" Height="28"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Content="{DynamicResource Text.Sure}"
Click="OnPopupSure"
HotKey="Enter"/>
<Button Classes="flat"
Width="80" Height="28"
Margin="8,0,0,0"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Content="{DynamicResource Text.Cancel}"
Click="OnPopupCancel"/>
<Border Background="Transparent"
PointerPressed="OnMaskClicked"
IsVisible="{Binding Popup, Converter={x:Static ObjectConverters.IsNotNull}}"/>
<Grid RowDefinitions="Auto,*" Width="512" HorizontalAlignment="Center">
<!-- Popup -->
<Border Grid.Row="0"
Margin="6,0"
Effect="drop-shadow(0 0 8 #8F000000)"
CornerRadius="0,0,8,8"
ClipToBounds="True"
IsVisible="{Binding Popup, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Content="{Binding Popup}" Background="{DynamicResource Brush.Popup}">
<ContentControl.DataTemplates>
<DataTemplate DataType="vm:Popup">
<StackPanel Orientation="Vertical" Background="{DynamicResource Brush.Popup}">
<!-- Popup Widget -->
<ContentPresenter Margin="8,16,8,8"
Content="{Binding View}"
IsHitTestVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}"/>
<!-- Options -->
<StackPanel Margin="8,4,8,8"
Height="32"
Orientation="Horizontal"
HorizontalAlignment="Right"
IsVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}">
<Button Classes="flat primary"
Width="80" Height="28"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Content="{DynamicResource Text.Sure}"
Click="OnPopupSure"
HotKey="Enter"/>
<Button Classes="flat"
Width="80" Height="28"
Margin="8,0,0,0"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Content="{DynamicResource Text.Cancel}"
Click="OnPopupCancel"/>
</StackPanel>
<!-- Running -->
<v:PopupRunningStatus Margin="12,8"
Description="{Binding ProgressDescription}"
IsVisible="{Binding InProgress}"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Border>
<!-- Running -->
<v:PopupRunningStatus Margin="12,8"
Description="{Binding ProgressDescription}"
IsVisible="{Binding InProgress}"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Border>
</Grid>
<!-- Notification -->
<Grid Grid.Row="1" Width="480" HorizontalAlignment="Right" VerticalAlignment="Top">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Notifications}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="m:Notification">
<Border Margin="10,6" HorizontalAlignment="Stretch" VerticalAlignment="Top" Effect="drop-shadow(0 0 12 #A0000000)">
<Border Padding="8" CornerRadius="6" Background="{DynamicResource Brush.Popup}">
<Grid RowDefinitions="26,Auto,32">
<StackPanel Grid.Row="0" Margin="8,0,0,0" Orientation="Horizontal" IsVisible="{Binding IsError}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Error}" Fill="Red"/>
<TextBlock Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.Launcher.Error}"/>
</StackPanel>
<StackPanel Grid.Row="0" Margin="8,0,0,0" Orientation="Horizontal" IsVisible="{Binding !IsError}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Info}" Fill="Green"/>
<TextBlock Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.Launcher.Info}"/>
</StackPanel>
<!-- Notifications -->
<ScrollViewer Grid.Row="1" Margin="0,6,0,0" VerticalAlignment="Top" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Notifications}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="m:Notification">
<Border Margin="6" HorizontalAlignment="Stretch" VerticalAlignment="Top" Effect="drop-shadow(0 0 12 #A0000000)">
<Border Padding="8" CornerRadius="6" Background="{DynamicResource Brush.Popup}">
<Grid RowDefinitions="26,Auto">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Margin="8,0">
<Path Grid.Column="0" Width="14" Height="14" Data="{StaticResource Icons.Error}" Fill="Red" IsVisible="{Binding IsError}"/>
<Path Grid.Column="0" Width="14" Height="14" Data="{StaticResource Icons.Info}" Fill="Green" IsVisible="{Binding !IsError}"/>
<TextBlock Grid.Column="1" Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.Launcher.Error}" IsVisible="{Binding IsError}"/>
<TextBlock Grid.Column="1" Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.Launcher.Info}" IsVisible="{Binding !IsError}"/>
<Button Grid.Column="2" Classes="icon_button" Width="16" Height="16" Click="OnDismissNotification">
<Path Width="10" Height="10" Data="{StaticResource Icons.Window.Close}"/>
</Button>
</Grid>
<TextBox Grid.Row="1"
Classes="no_background no_border"
IsReadOnly="True"
TextWrapping="Wrap"
ScrollViewer.VerticalScrollBarVisibility="Auto"
MaxHeight="100"
Margin="8" Padding="0"
VerticalContentAlignment="Top"
Text="{Binding Message}"/>
<StackPanel Grid.Row="2" Margin="0,4,0,0" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Classes="flat"
Margin="0,0,8,0"
Command="{Binding CopyMessage}"
Content="{DynamicResource Text.CopyMessage}"
IsVisible="{Binding IsError}"/>
<Button Classes="flat primary"
Margin="0,0"
Content="{DynamicResource Text.Close}"
Click="OnDismissNotification"/>
</StackPanel>
</Grid>
<ScrollViewer Grid.Row="1" Margin="8" MaxHeight="100" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<SelectableTextBlock TextWrapping="Wrap" Text="{Binding Message}"/>
</ScrollViewer>
</Grid>
</Border>
</Border>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Grid>
</Grid>
</UserControl>

View file

@ -27,7 +27,7 @@ namespace SourceGit.Views
e.Handled = true;
}
private void OnPopupCancelByClickMask(object sender, PointerPressedEventArgs e)
private void OnMaskClicked(object sender, PointerPressedEventArgs e)
{
OnPopupCancel(sender, e);
}

View file

@ -234,7 +234,7 @@ namespace SourceGit.Views
if (sender is Border border && DataContext is ViewModels.Launcher vm)
{
var menu = vm.CreateContextForPageTab(border.DataContext as ViewModels.LauncherPage);
border.OpenContextMenu(menu);
menu?.Open(border);
}
e.Handled = true;

View file

@ -121,7 +121,7 @@
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.Appearance}"/>
</TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.Appearance.Theme}"
HorizontalAlignment="Right"
@ -170,10 +170,22 @@
Value="{Binding DefaultFontSize, Mode=TwoWay}"/>
<TextBlock Grid.Row="4" Grid.Column="0"
Text="{DynamicResource Text.Preference.Appearance.EditorFontSize}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<NumericUpDown Grid.Row="4" Grid.Column="1"
Minimum="10" Maximum="18" Increment="0.5"
Height="28"
Padding="4"
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
CornerRadius="3"
Value="{Binding EditorFontSize, Mode=TwoWay}"/>
<TextBlock Grid.Row="5" Grid.Column="0"
Text="{DynamicResource Text.Preference.Appearance.ThemeOverrides}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<TextBox Grid.Row="4" Grid.Column="1"
<TextBox Grid.Row="5" Grid.Column="1"
Height="28"
CornerRadius="3"
Text="{Binding ThemeOverrides, Mode=TwoWay}">
@ -184,16 +196,16 @@
</TextBox.InnerRightContent>
</TextBox>
<CheckBox Grid.Row="5" Grid.Column="1"
<CheckBox Grid.Row="6" Grid.Column="1"
Content="{DynamicResource Text.Preference.Appearance.OnlyUseMonoFontInEditor}"
IsChecked="{Binding OnlyUseMonoFontInEditor, Mode=TwoWay}"/>
<CheckBox Grid.Row="6" Grid.Column="1"
<CheckBox Grid.Row="7" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preference.Appearance.UseFixedTabWidth}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFixedTabWidth, Mode=TwoWay}"/>
<CheckBox Grid.Row="7" Grid.Column="1"
<CheckBox Grid.Row="8" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preference.Appearance.UseNativeWindowFrame}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSystemWindowFrame, Mode=OneTime}"

View file

@ -189,7 +189,7 @@ namespace SourceGit.Views
if (sender is ListBox { SelectedItem: Models.Submodule submodule } grid && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForSubmodule(submodule.Path);
grid.OpenContextMenu(menu);
menu?.Open(grid);
}
e.Handled = true;
@ -210,7 +210,7 @@ namespace SourceGit.Views
if (sender is ListBox { SelectedItem: Models.Worktree worktree } grid && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForWorktree(worktree);
grid.OpenContextMenu(menu);
menu?.Open(grid);
}
e.Handled = true;

View file

@ -31,7 +31,7 @@
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Classes="icon_button" Width="32" Click="Fetch">
<Button Classes="icon_button" Width="32" Click="Fetch" HotKey="{OnPlatform Ctrl+Down, macOS=⌘+Down}">
<ToolTip.Tip>
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource Text.Fetch}"/>
@ -42,7 +42,7 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.Fetch}"/>
</Button>
<Button Classes="icon_button" Width="32" Margin="16,0,0,0" Click="Pull">
<Button Classes="icon_button" Width="32" Margin="16,0,0,0" Click="Pull" HotKey="{OnPlatform Ctrl+Shift+Down, macOS=⌘+Shift+Down}">
<ToolTip.Tip>
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource Text.Pull}"/>
@ -53,7 +53,7 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.Pull}"/>
</Button>
<Button Classes="icon_button" Width="32" Margin="16,0,0,0" Click="Push">
<Button Classes="icon_button" Width="32" Margin="16,0,0,0" Click="Push" HotKey="{OnPlatform Ctrl+Shift+Up, macOS=⌘+Shift+Up}">
<ToolTip.Tip>
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource Text.Push}"/>

View file

@ -1,3 +1,5 @@
using System;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
@ -17,7 +19,7 @@ namespace SourceGit.Views
if (sender is Button button && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForExternalTools();
button.OpenContextMenu(menu);
menu?.Open(button);
e.Handled = true;
}
}
@ -45,22 +47,43 @@ namespace SourceGit.Views
private void Fetch(object _, RoutedEventArgs e)
{
var launcher = this.FindAncestorOfType<Launcher>();
(DataContext as ViewModels.Repository)?.Fetch(launcher?.HasKeyModifier(KeyModifiers.Control) ?? false);
e.Handled = true;
if (launcher is not null && DataContext is ViewModels.Repository repo)
{
var startDirectly = launcher.HasKeyModifier(KeyModifiers.Control);
if (!startDirectly && OperatingSystem.IsMacOS())
startDirectly = launcher.HasKeyModifier(KeyModifiers.Meta);
repo.Fetch(startDirectly);
e.Handled = true;
}
}
private void Pull(object _, RoutedEventArgs e)
{
var launcher = this.FindAncestorOfType<Launcher>();
(DataContext as ViewModels.Repository)?.Pull(launcher?.HasKeyModifier(KeyModifiers.Control) ?? false);
e.Handled = true;
if (launcher is not null && DataContext is ViewModels.Repository repo)
{
var startDirectly = launcher.HasKeyModifier(KeyModifiers.Control);
if (!startDirectly && OperatingSystem.IsMacOS())
startDirectly = launcher.HasKeyModifier(KeyModifiers.Meta);
repo.Pull(startDirectly);
e.Handled = true;
}
}
private void Push(object _, RoutedEventArgs e)
{
var launcher = this.FindAncestorOfType<Launcher>();
(DataContext as ViewModels.Repository)?.Push(launcher?.HasKeyModifier(KeyModifiers.Control) ?? false);
e.Handled = true;
if (launcher is not null && DataContext is ViewModels.Repository repo)
{
var startDirectly = launcher.HasKeyModifier(KeyModifiers.Control);
if (!startDirectly && OperatingSystem.IsMacOS())
startDirectly = launcher.HasKeyModifier(KeyModifiers.Meta);
repo.Push(startDirectly);
e.Handled = true;
}
}
private void StashAll(object _, RoutedEventArgs e)
@ -72,10 +95,10 @@ namespace SourceGit.Views
private void OpenGitFlowMenu(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.Repository repo)
if (DataContext is ViewModels.Repository repo && sender is Control control)
{
var menu = repo.CreateContextMenuForGitFlow();
(sender as Control)?.OpenContextMenu(menu);
menu?.Open(control);
}
e.Handled = true;
@ -83,10 +106,10 @@ namespace SourceGit.Views
private void OpenGitLFSMenu(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.Repository repo)
if (DataContext is ViewModels.Repository repo && sender is Control control)
{
var menu = repo.CreateContextMenuForGitLFS();
(sender as Control)?.OpenContextMenu(menu);
menu?.Open(control);
}
e.Handled = true;
@ -94,10 +117,10 @@ namespace SourceGit.Views
private void OpenCustomActionMenu(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.Repository repo)
if (DataContext is ViewModels.Repository repo && sender is Control control)
{
var menu = repo.CreateContextMenuForCustomAction();
(sender as Control)?.OpenContextMenu(menu);
menu?.Open(control);
}
e.Handled = true;

View file

@ -35,21 +35,26 @@
<Grid RowDefinitions="50,*" Margin="4">
<!-- Compare Revision Info -->
<Grid Grid.Row="0" Margin="48,0,48,4" ColumnDefinitions="*,48,*">
<Grid Grid.Row="0" Margin="0,0,0,6" ColumnDefinitions="*,32,*,Auto">
<!-- Base Revision -->
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<ContentControl Content="{Binding StartPoint}"/>
</Border>
<!-- Swap Button -->
<!-- Swap Buttons -->
<Button Grid.Column="1" Classes="icon_button" Command="{Binding Swap}" HorizontalAlignment="Center" ToolTip.Tip="{DynamicResource Text.Diff.SwapCommits}">
<Path Width="16" Height="16" Fill="{DynamicResource Brush.FG2}" Data="{DynamicResource Icons.Compare}"/>
<Path Width="16" Height="16" Data="{DynamicResource Icons.Compare}"/>
</Button>
<!-- Right Revision -->
<Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<ContentControl Content="{Binding EndPoint}"/>
</Border>
<!-- Save As Patch Button -->
<Button Grid.Column="3" Classes="icon_button" Width="32" Click="OnSaveAsPatch" IsVisible="{Binding CanSaveAsPatch}" ToolTip.Tip="{DynamicResource Text.Diff.SaveAsPatch}">
<Path Width="16" Height="16" Data="{DynamicResource Icons.Diff}"/>
</Button>
</Grid>
<!-- Changes View -->

View file

@ -1,5 +1,7 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
namespace SourceGit.Views
{
@ -15,7 +17,7 @@ namespace SourceGit.Views
if (DataContext is ViewModels.RevisionCompare vm && sender is ChangeCollectionView view)
{
var menu = vm.CreateChangeContextMenu();
view.OpenContextMenu(menu);
menu?.Open(view);
}
e.Handled = true;
@ -28,5 +30,27 @@ namespace SourceGit.Views
e.Handled = true;
}
private async void OnSaveAsPatch(object sender, RoutedEventArgs e)
{
var topLevel = TopLevel.GetTopLevel(this);
if (topLevel == null)
return;
var vm = DataContext as ViewModels.RevisionCompare;
if (vm == null)
return;
var options = new FilePickerSaveOptions();
options.Title = App.Text("FileCM.SaveAsPatch");
options.DefaultExtension = ".patch";
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
vm.SaveAsPatch(storageFile.Path.LocalPath);
e.Handled = true;
}
}
}

View file

@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:v="using:SourceGit.Views"
xmlns:vm="using:SourceGit.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.RevisionFileContentViewer">
<UserControl.DataTemplates>
@ -19,7 +20,9 @@
</DataTemplate>
<DataTemplate DataType="m:RevisionTextFile">
<v:RevisionTextFileView FontFamily="{DynamicResource Fonts.Monospace}" Background="{DynamicResource Brush.Contents}"/>
<v:RevisionTextFileView FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=EditorFontSize}"
Background="{DynamicResource Brush.Contents}"/>
</DataTemplate>
<DataTemplate DataType="m:RevisionImageFile">

View file

@ -229,7 +229,7 @@ namespace SourceGit.Views
if (obj.Type != Models.ObjectType.Tree)
{
var menu = vm.CreateRevisionFileContextMenu(obj);
grid.OpenContextMenu(menu);
menu?.Open(grid);
}
}

View file

@ -95,8 +95,8 @@ namespace SourceGit.Views
var menu = new ContextMenu();
menu.Items.Add(copy);
menu.Open(TextArea.TextView);
TextArea.TextView.OpenContextMenu(menu);
e.Handled = true;
}

View file

@ -28,7 +28,7 @@ namespace SourceGit.Views
if (DataContext is ViewModels.StashesPage vm && sender is Border border)
{
var menu = vm.MakeContextMenu(border.DataContext as Models.Stash);
border.OpenContextMenu(menu);
menu?.Open(border);
}
e.Handled = true;
}
@ -38,7 +38,7 @@ namespace SourceGit.Views
if (DataContext is ViewModels.StashesPage vm && sender is Grid grid)
{
var menu = vm.MakeContextMenuForChange(grid.DataContext as Models.Change);
grid.OpenContextMenu(menu);
menu?.Open(grid);
}
e.Handled = true;
}

View file

@ -225,7 +225,7 @@ namespace SourceGit.Views
if (selected != null && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForTag(selected);
control.OpenContextMenu(menu);
menu?.Open(control);
}
e.Handled = true;

View file

@ -23,6 +23,7 @@
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=EditorFontSize}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
@ -44,6 +45,7 @@
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=EditorFontSize}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="False"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
@ -64,6 +66,7 @@
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=EditorFontSize}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="False"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"

View file

@ -589,8 +589,8 @@ namespace SourceGit.Views
var menu = new ContextMenu();
menu.Items.Add(copy);
menu.Open(TextArea.TextView);
TextArea.TextView.OpenContextMenu(menu);
e.Handled = true;
}
@ -902,7 +902,7 @@ namespace SourceGit.Views
var scroller = this.FindDescendantOfType<ScrollViewer>();
if (scroller != null)
{
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.TwoWay));
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay));
scroller.GotFocus += OnTextViewScrollGotFocus;
}
}
@ -1205,6 +1205,15 @@ namespace SourceGit.Views
set => SetValue(UseSideBySideDiffProperty, value);
}
public static readonly StyledProperty<bool> UseFullTextDiffProperty =
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseFullTextDiff));
public bool UseFullTextDiff
{
get => GetValue(UseFullTextDiffProperty);
set => SetValue(UseFullTextDiffProperty, value);
}
public static readonly StyledProperty<TextDiffViewChunk> SelectedChunkProperty =
AvaloniaProperty.Register<TextDiffView, TextDiffViewChunk>(nameof(SelectedChunk));
@ -1236,15 +1245,12 @@ namespace SourceGit.Views
{
UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
{
if (v.DataContext is Models.TextDiff diff)
{
diff.SyncScrollOffset = Vector.Zero;
v.RefreshContent(v.DataContext as Models.TextDiff, false);
});
if (v.UseSideBySideDiff)
v.Editor.Content = new ViewModels.TwoSideTextDiff(diff);
else
v.Editor.Content = diff;
}
UseFullTextDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
{
v.RefreshContent(v.DataContext as Models.TextDiff, false);
});
SelectedChunkProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
@ -1271,25 +1277,7 @@ namespace SourceGit.Views
protected override void OnDataContextChanged(EventArgs e)
{
base.OnDataContextChanged(e);
if (SelectedChunk != null)
SetCurrentValue(SelectedChunkProperty, null);
var diff = DataContext as Models.TextDiff;
if (diff == null)
{
Editor.Content = null;
GC.Collect();
return;
}
if (UseSideBySideDiff)
Editor.Content = new ViewModels.TwoSideTextDiff(diff, Editor.Content as ViewModels.TwoSideTextDiff);
else
Editor.Content = diff;
IsUnstagedChange = diff.Option.IsUnstaged;
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
RefreshContent(DataContext as Models.TextDiff, true);
}
protected override void OnPointerExited(PointerEventArgs e)
@ -1300,6 +1288,34 @@ namespace SourceGit.Views
SetCurrentValue(SelectedChunkProperty, null);
}
private void RefreshContent(Models.TextDiff diff, bool keepScrollOffset = true)
{
if (SelectedChunk != null)
SetCurrentValue(SelectedChunkProperty, null);
if (diff == null)
{
Editor.Content = null;
GC.Collect();
return;
}
if (UseSideBySideDiff)
{
var previousContent = Editor.Content as ViewModels.TwoSideTextDiff;
Editor.Content = new ViewModels.TwoSideTextDiff(diff, keepScrollOffset ? previousContent : null);
}
else
{
if (!keepScrollOffset)
diff.ScrollOffset = Vector.Zero;
Editor.Content = diff;
}
IsUnstagedChange = diff.Option.IsUnstaged;
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
}
private void OnStageChunk(object _1, RoutedEventArgs _2)
{
var chunk = SelectedChunk;

View file

@ -117,7 +117,7 @@ namespace SourceGit.Views
if (sender is Grid { DataContext: ViewModels.RepositoryNode node } grid)
{
var menu = ViewModels.Welcome.Instance.CreateContextMenu(node);
grid.OpenContextMenu(menu);
menu?.Open(grid);
e.Handled = true;
}
}

View file

@ -31,27 +31,27 @@ namespace SourceGit.Views
{
var menu = vm.CreateContextMenuForCommitMessages();
menu.Placement = PlacementMode.TopEdgeAlignedLeft;
button.OpenContextMenu(menu);
menu?.Open(button);
e.Handled = true;
}
}
private void OnUnstagedContextRequested(object sender, ContextRequestedEventArgs e)
{
if (DataContext is ViewModels.WorkingCopy vm)
if (DataContext is ViewModels.WorkingCopy vm && sender is Control control)
{
var menu = vm.CreateContextMenuForUnstagedChanges();
(sender as Control)?.OpenContextMenu(menu);
menu?.Open(control);
e.Handled = true;
}
}
private void OnStagedContextRequested(object sender, ContextRequestedEventArgs e)
{
if (DataContext is ViewModels.WorkingCopy vm)
if (DataContext is ViewModels.WorkingCopy vm && sender is Control control)
{
var menu = vm.CreateContextMenuForStagedChanges();
(sender as Control)?.OpenContextMenu(menu);
menu?.Open(control);
e.Handled = true;
}
}
@ -136,10 +136,10 @@ namespace SourceGit.Views
private void OnOpenOpenAIHelper(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.WorkingCopy vm)
if (DataContext is ViewModels.WorkingCopy vm && sender is Control control)
{
var menu = vm.CreateContextForOpenAI();
(sender as Button)?.OpenContextMenu(menu);
menu?.Open(control);
}
e.Handled = true;