Merge branch 'release/v8.37'

This commit is contained in:
leo 2024-11-04 10:07:12 +08:00
commit 9452b796a5
No known key found for this signature in database
101 changed files with 2583 additions and 1158 deletions

View file

@ -1,13 +1,17 @@
# SourceGit - Opensource Git GUI client. # SourceGit - Opensource Git GUI client.
![stars](https://img.shields.io/github/stars/sourcegit-scm/sourcegit.svg) ![forks](https://img.shields.io/github/forks/sourcegit-scm/sourcegit.svg) ![license](https://img.shields.io/github/license/sourcegit-scm/sourcegit.svg) ![latest](https://img.shields.io/github/v/release/sourcegit-scm/sourcegit.svg) ![downloads](https://img.shields.io/github/downloads/sourcegit-scm/sourcegit/total) [![stars](https://img.shields.io/github/stars/sourcegit-scm/sourcegit.svg)](https://github.com/sourcegit-scm/sourcegit/stargazers)
[![forks](https://img.shields.io/github/forks/sourcegit-scm/sourcegit.svg)](https://github.com/sourcegit-scm/sourcegit/forks)
[![license](https://img.shields.io/github/license/sourcegit-scm/sourcegit.svg)](LICENSE)
[![latest](https://img.shields.io/github/v/release/sourcegit-scm/sourcegit.svg)](https://github.com/sourcegit-scm/sourcegit/releases/latest)
[![downloads](https://img.shields.io/github/downloads/sourcegit-scm/sourcegit/total)](https://github.com/sourcegit-scm/sourcegit/releases)
## Highlights ## Highlights
* Supports Windows/macOS/Linux * Supports Windows/macOS/Linux
* Opensource/Free * Opensource/Free
* Fast * Fast
* English/Français/Deutsch/Português/Русский/简体中文/繁體中文 * Deutsch/English/Español/Français/Português/Русский/简体中文/繁體中文
* Built-in light/dark themes * Built-in light/dark themes
* Customize theme * Customize theme
* Visual commit graph * Visual commit graph
@ -43,7 +47,7 @@
## Translation Status ## 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-98.95%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-90.36%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-93.52%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-99.10%25-yellow)](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-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)
## How to Use ## How to Use
@ -80,11 +84,16 @@ For **Windows** users:
For **macOS** users: For **macOS** users:
* Download `sourcegit_x.y.osx-x64.zip` or `sourcegit_x.y.osx-arm64.zip` from Releases. `x64` for Intel and `arm64` for Apple Silicon. * Thanks [@ybeapps](https://github.com/ybeapps) for making `SourceGit` available on `Homebrew`. You can simply install it with following command:
* Move `SourceGit.app` to `Applications` folder. ```shell
* Make sure your mac trusts all software from anywhere. For more information, search `spctl --master-disable`. brew tap ybeapps/homebrew-sourcegit
brew install --cask --no-quarantine sourcegit
```
* If you want to install `SourceGit.app` from Github Release manually, you need run following command to make sure it works:
```shell
sudo xattr -cr /Applications/SourceGit.app
```
* Make sure [git-credential-manager](https://github.com/git-ecosystem/git-credential-manager/releases) is installed on your mac. * Make sure [git-credential-manager](https://github.com/git-ecosystem/git-credential-manager/releases) is installed on your mac.
* You may need to run `sudo xattr -cr /Applications/SourceGit.app` to make sure the software works.
* You can run `echo $PATH > ~/Library/Application\ Support/SourceGit/PATH` to generate a custom PATH env file to introduce `PATH` env to SourceGit. * You can run `echo $PATH > ~/Library/Application\ Support/SourceGit/PATH` to generate a custom PATH env file to introduce `PATH` env to SourceGit.
For **Linux** users: For **Linux** users:
@ -110,14 +119,15 @@ For other AI service:
This app supports open repository in external tools listed in the table below. This app supports open repository in external tools listed in the table below.
| Tool | Windows | macOS | Linux | KEY IN `external_editors.json` | | Tool | Windows | macOS | Linux |
|-------------------------------|---------|-------|-------|--------------------------------| |-------------------------------|---------|-------|-------|
| Visual Studio Code | YES | YES | YES | VSCODE | | Visual Studio Code | YES | YES | YES |
| Visual Studio Code - Insiders | YES | YES | YES | VSCODE_INSIDERS | | Visual Studio Code - Insiders | YES | YES | YES |
| VSCodium | YES | YES | YES | VSCODIUM | | VSCodium | YES | YES | YES |
| JetBrains Fleet | YES | YES | YES | FLEET | | Fleet | YES | YES | YES |
| Sublime Text | YES | YES | YES | SUBLIME_TEXT | | Sublime Text | YES | YES | YES |
| Zed | NO | YES | YES | ZED | | Zed | NO | YES | YES |
| Visual Studio | YES | NO | NO |
> [!NOTE] > [!NOTE]
> This app will try to find those tools based on some pre-defined or expected locations automatically. If you are using one portable version of these tools, it will not be detected by this app. > This app will try to find those tools based on some pre-defined or expected locations automatically. If you are using one portable version of these tools, it will not be detected by this app.
@ -125,7 +135,7 @@ This app supports open repository in external tools listed in the table below.
```json ```json
{ {
"tools": { "tools": {
"VSCODE": "D:\\VSCode\\Code.exe" "Visual Studio Code": "D:\\VSCode\\Code.exe"
} }
} }
``` ```
@ -153,4 +163,4 @@ Everyone is welcome to submit a PR. Please make sure your PR is based on the lat
Thanks to all the people who contribute. Thanks to all the people who contribute.
[![Contributors](https://contrib.rocks/image?repo=sourcegit-scm/sourcegit&columns=10)](https://github.com/sourcegit-scm/sourcegit/graphs/contributors) [![Contributors](https://contrib.rocks/image?repo=sourcegit-scm/sourcegit&columns=20)](https://github.com/sourcegit-scm/sourcegit/graphs/contributors)

View file

@ -76,6 +76,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "appimage", "appimage", "{5D
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{C54D4001-9940-477C-A0B6-E795ED0A3209}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{C54D4001-9940-477C-A0B6-E795ED0A3209}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
build\scripts\localization-check.js = build\scripts\localization-check.js
build\scripts\package.linux.sh = build\scripts\package.linux.sh build\scripts\package.linux.sh = build\scripts\package.linux.sh
build\scripts\package.osx-app.sh = build\scripts\package.osx-app.sh build\scripts\package.osx-app.sh = build\scripts\package.osx-app.sh
build\scripts\package.windows-portable.sh = build\scripts\package.windows-portable.sh build\scripts\package.windows-portable.sh = build\scripts\package.windows-portable.sh

View file

@ -1,20 +1,69 @@
### de_DE.axaml: 98.95% ### de_DE.axaml: 96.05%
<details> <details>
<summary>Missing Keys</summary> <summary>Missing Keys</summary>
- Text.BranchCM.FetchInto
- 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.Git.EnableSignOff - Text.Configure.Git.EnableSignOff
- Text.Configure.IssueTracker.AddSampleGitLabIssue - Text.Configure.IssueTracker.AddSampleGitLabIssue
- Text.Configure.IssueTracker.AddSampleGitLabMergeRequest - Text.Configure.IssueTracker.AddSampleGitLabMergeRequest
- Text.Preference.Advanced - Text.Configure.OpenAI
- Text.Configure.OpenAI.Prefered
- Text.Configure.OpenAI.Prefered.Tip
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.Preference.AI.AnalyzeDiffPrompt - Text.Preference.AI.AnalyzeDiffPrompt
- Text.Preference.AI.GenerateSubjectPrompt - Text.Preference.AI.GenerateSubjectPrompt
- Text.Preference.AI.Name
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Stash.KeepIndex
- Text.WorkingCopy.ConfirmCommitWithoutFiles - Text.WorkingCopy.ConfirmCommitWithoutFiles
</details> </details>
### fr_FR.axaml: 90.36% ### es_ES.axaml: 97.08%
<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
</details>
### fr_FR.axaml: 87.72%
<details> <details>
@ -23,16 +72,31 @@
- Text.About.Chart - Text.About.Chart
- Text.AIAssistant - Text.AIAssistant
- Text.AIAssistant.Tip - Text.AIAssistant.Tip
- Text.BranchCM.FetchInto
- Text.ChangeCM.GenerateCommitMessage
- Text.CherryPick.AppendSourceToMessage - Text.CherryPick.AppendSourceToMessage
- Text.CherryPick.Mainline - Text.CherryPick.Mainline
- Text.CherryPick.Mainline.Tips - Text.CherryPick.Mainline.Tips
- Text.CommitCM.CherryPickMultiple - Text.CommitCM.CherryPickMultiple
- Text.CommitCM.CustomAction
- Text.CommitCM.SquashCommitsSinceThis - Text.CommitCM.SquashCommitsSinceThis
- Text.CommitDetail.Info.WebLinks - Text.CommitDetail.Info.WebLinks
- 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.DefaultRemote - Text.Configure.Git.DefaultRemote
- Text.Configure.Git.EnablePruneOnFetch
- Text.Configure.Git.EnableSignOff - Text.Configure.Git.EnableSignOff
- Text.Configure.IssueTracker.AddSampleGitLabIssue - Text.Configure.IssueTracker.AddSampleGitLabIssue
- Text.Configure.IssueTracker.AddSampleGitLabMergeRequest - Text.Configure.IssueTracker.AddSampleGitLabMergeRequest
- Text.Configure.OpenAI
- Text.Configure.OpenAI.Prefered
- Text.Configure.OpenAI.Prefered.Tip
- Text.ConfigureWorkspace - Text.ConfigureWorkspace
- Text.ConfigureWorkspace.Color - Text.ConfigureWorkspace.Color
- Text.ConfigureWorkspace.Restore - Text.ConfigureWorkspace.Restore
@ -45,6 +109,8 @@
- Text.ConventionalCommit.Type - Text.ConventionalCommit.Type
- Text.Diff.IgnoreWhitespace - Text.Diff.IgnoreWhitespace
- Text.Discard.IncludeIgnored - Text.Discard.IncludeIgnored
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.FileHistory.FileChange - Text.FileHistory.FileChange
- Text.GitLFS.Locks.OnlyMine - Text.GitLFS.Locks.OnlyMine
- Text.Histories.Header.AuthorTime - Text.Histories.Header.AuthorTime
@ -55,12 +121,12 @@
- Text.Hotkeys.Repo.DiscardSelected - Text.Hotkeys.Repo.DiscardSelected
- Text.MoveRepositoryNode - Text.MoveRepositoryNode
- Text.MoveRepositoryNode.Target - Text.MoveRepositoryNode.Target
- Text.Preference.Advanced
- Text.Preference.AI - Text.Preference.AI
- Text.Preference.AI.AnalyzeDiffPrompt - Text.Preference.AI.AnalyzeDiffPrompt
- Text.Preference.AI.ApiKey - Text.Preference.AI.ApiKey
- Text.Preference.AI.GenerateSubjectPrompt - Text.Preference.AI.GenerateSubjectPrompt
- Text.Preference.AI.Model - Text.Preference.AI.Model
- Text.Preference.AI.Name
- Text.Preference.AI.Server - Text.Preference.AI.Server
- Text.Preference.General.ShowAuthorTime - Text.Preference.General.ShowAuthorTime
- Text.Preference.Integration - Text.Preference.Integration
@ -68,11 +134,14 @@
- Text.Preference.Shell.Type - Text.Preference.Shell.Type
- Text.Preference.Shell.Path - Text.Preference.Shell.Path
- Text.Repository.AutoFetching - Text.Repository.AutoFetching
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Repository.EnableReflog - Text.Repository.EnableReflog
- Text.Repository.Search.InCurrentBranch - Text.Repository.Search.InCurrentBranch
- Text.ScanRepositories - Text.ScanRepositories
- Text.ScanRepositories.RootDir - Text.ScanRepositories.RootDir
- Text.Squash.Into - Text.Squash.Into
- Text.Stash.KeepIndex
- Text.Stash.OnlyStagedChanges - Text.Stash.OnlyStagedChanges
- Text.Stash.TipForSelectedFiles - Text.Stash.TipForSelectedFiles
- Text.Statistics.Overview - Text.Statistics.Overview
@ -87,7 +156,7 @@
</details> </details>
### pt_BR.axaml: 93.52% ### pt_BR.axaml: 90.79%
<details> <details>
@ -96,18 +165,33 @@
- Text.About.Chart - Text.About.Chart
- Text.AIAssistant - Text.AIAssistant
- Text.AIAssistant.Tip - Text.AIAssistant.Tip
- Text.BranchCM.FetchInto
- Text.ChangeCM.GenerateCommitMessage
- Text.CherryPick.AppendSourceToMessage - Text.CherryPick.AppendSourceToMessage
- Text.CherryPick.Mainline - Text.CherryPick.Mainline
- Text.CherryPick.Mainline.Tips - Text.CherryPick.Mainline.Tips
- Text.CommitCM.CherryPickMultiple - Text.CommitCM.CherryPickMultiple
- Text.CommitCM.CustomAction
- Text.CommitCM.SquashCommitsSinceThis - Text.CommitCM.SquashCommitsSinceThis
- Text.CommitDetail.Info.ContainsIn - Text.CommitDetail.Info.ContainsIn
- Text.CommitDetail.Info.ContainsIn.Title - Text.CommitDetail.Info.ContainsIn.Title
- Text.CommitDetail.Info.WebLinks - Text.CommitDetail.Info.WebLinks
- 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.DefaultRemote - Text.Configure.Git.DefaultRemote
- Text.Configure.Git.EnablePruneOnFetch
- Text.Configure.Git.EnableSignOff - Text.Configure.Git.EnableSignOff
- Text.Configure.IssueTracker.AddSampleGitLabIssue - Text.Configure.IssueTracker.AddSampleGitLabIssue
- Text.Configure.IssueTracker.AddSampleGitLabMergeRequest - Text.Configure.IssueTracker.AddSampleGitLabMergeRequest
- Text.Configure.OpenAI
- Text.Configure.OpenAI.Prefered
- Text.Configure.OpenAI.Prefered.Tip
- Text.ConfigureWorkspace - Text.ConfigureWorkspace
- Text.ConfigureWorkspace.Color - Text.ConfigureWorkspace.Color
- Text.ConfigureWorkspace.Restore - Text.ConfigureWorkspace.Restore
@ -120,14 +204,19 @@
- Text.ConventionalCommit.Type - Text.ConventionalCommit.Type
- Text.CopyAllText - Text.CopyAllText
- Text.Discard.IncludeIgnored - Text.Discard.IncludeIgnored
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.FileHistory.FileContent - Text.FileHistory.FileContent
- Text.FileHistory.FileChange - Text.FileHistory.FileChange
- Text.GitLFS.Locks.OnlyMine - Text.GitLFS.Locks.OnlyMine
- Text.MoveRepositoryNode - Text.MoveRepositoryNode
- Text.MoveRepositoryNode.Target - Text.MoveRepositoryNode.Target
- Text.Preference.Advanced - Text.Preference.AI.Name
- Text.Push.CheckSubmodules - Text.Push.CheckSubmodules
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Squash.Into - Text.Squash.Into
- Text.Stash.KeepIndex
- Text.Stash.OnlyStagedChanges - Text.Stash.OnlyStagedChanges
- Text.Stash.TipForSelectedFiles - Text.Stash.TipForSelectedFiles
- Text.Statistics.Overview - Text.Statistics.Overview
@ -149,18 +238,13 @@
</details> </details>
### zh_CN.axaml: 99.10% ### zh_CN.axaml: 100.00%
<details> <details>
<summary>Missing Keys</summary> <summary>Missing Keys</summary>
- Text.Preference.AI
- Text.Preference.AI.AnalyzeDiffPrompt
- Text.Preference.AI.ApiKey
- Text.Preference.AI.GenerateSubjectPrompt
- Text.Preference.AI.Model
- Text.Preference.AI.Server
</details> </details>

View file

@ -1 +1 @@
8.36 8.37

View file

@ -5,8 +5,8 @@ Summary: Open-source & Free Git Gui Client
License: MIT License: MIT
URL: https://sourcegit-scm.github.io/ URL: https://sourcegit-scm.github.io/
Source: https://github.com/sourcegit-scm/sourcegit/archive/refs/tags/v%_version.tar.gz Source: https://github.com/sourcegit-scm/sourcegit/archive/refs/tags/v%_version.tar.gz
Requires: libX11 Requires: (libX11 or libX11-6)
Requires: libSM Requires: (libSM or libSM6)
%define _build_id_links none %define _build_id_links none

View file

@ -18,6 +18,7 @@
<ResourceInclude x:Key="ru_RU" Source="/Resources/Locales/ru_RU.axaml"/> <ResourceInclude x:Key="ru_RU" Source="/Resources/Locales/ru_RU.axaml"/>
<ResourceInclude x:Key="zh_CN" Source="/Resources/Locales/zh_CN.axaml"/> <ResourceInclude x:Key="zh_CN" Source="/Resources/Locales/zh_CN.axaml"/>
<ResourceInclude x:Key="zh_TW" Source="/Resources/Locales/zh_TW.axaml"/> <ResourceInclude x:Key="zh_TW" Source="/Resources/Locales/zh_TW.axaml"/>
<ResourceInclude x:Key="es_ES" Source="/Resources/Locales/es_ES.axaml"/>
</ResourceDictionary> </ResourceDictionary>
</Application.Resources> </Application.Resources>

View file

@ -59,6 +59,10 @@ namespace SourceGit
builder.UsePlatformDetect(); builder.UsePlatformDetect();
builder.LogToTrace(); builder.LogToTrace();
builder.WithInterFont(); builder.WithInterFont();
builder.With(new FontManagerOptions()
{
DefaultFamilyName = "fonts:Inter#Inter"
});
builder.ConfigureFonts(manager => builder.ConfigureFonts(manager =>
{ {
var monospace = new EmbeddedFontCollection( var monospace = new EmbeddedFontCollection(
@ -223,7 +227,7 @@ namespace SourceGit
if (onlyUseMonospaceFontInEditor) if (onlyUseMonospaceFontInEditor)
{ {
if (string.IsNullOrEmpty(defaultFont)) if (string.IsNullOrEmpty(defaultFont))
resDic.Add("Fonts.Primary", new FontFamily("fonts:Inter#Inter, $Default")); resDic.Add("Fonts.Primary", new FontFamily("fonts:Inter#Inter"));
else else
resDic.Add("Fonts.Primary", new FontFamily(defaultFont)); resDic.Add("Fonts.Primary", new FontFamily(defaultFont));
} }

View file

@ -0,0 +1,63 @@
using System;
using System.Diagnostics;
using System.Text;
using Avalonia.Threading;
namespace SourceGit.Commands
{
public static class ExecuteCustomAction
{
public static void Run(string repo, string file, string args, Action<string> outputHandler)
{
var start = new ProcessStartInfo();
start.FileName = file;
start.Arguments = args;
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.StandardOutputEncoding = Encoding.UTF8;
start.StandardErrorEncoding = Encoding.UTF8;
start.WorkingDirectory = repo;
// Force using en_US.UTF-8 locale to avoid GCM crash
if (OperatingSystem.IsLinux())
start.Environment.Add("LANG", "en_US.UTF-8");
// Fix macOS `PATH` env
if (OperatingSystem.IsMacOS() && !string.IsNullOrEmpty(Native.OS.CustomPathEnv))
start.Environment.Add("PATH", Native.OS.CustomPathEnv);
var proc = new Process() { StartInfo = start };
proc.OutputDataReceived += (_, e) =>
{
if (e.Data != null)
outputHandler?.Invoke(e.Data);
};
proc.ErrorDataReceived += (_, e) =>
{
if (e.Data != null)
outputHandler?.Invoke(e.Data);
};
try
{
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
}
catch (Exception e)
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, e.Message);
});
}
proc.Close();
}
}
}

View file

@ -4,7 +4,7 @@ namespace SourceGit.Commands
{ {
public class Fetch : Command public class Fetch : Command
{ {
public Fetch(string repo, string remote, bool noTags, Action<string> outputHandler) public Fetch(string repo, string remote, bool noTags, bool prune, Action<string> outputHandler)
{ {
_outputHandler = outputHandler; _outputHandler = outputHandler;
WorkingDirectory = repo; WorkingDirectory = repo;
@ -18,9 +18,22 @@ namespace SourceGit.Commands
else else
Args += "--force "; Args += "--force ";
if (prune)
Args += "--prune ";
Args += remote; Args += remote;
} }
public Fetch(string repo, Models.Branch local, Models.Branch remote, Action<string> outputHandler)
{
_outputHandler = outputHandler;
WorkingDirectory = repo;
Context = repo;
TraitErrorAsOutput = true;
SSHKey = new Config(repo).Get($"remote.{remote.Remote}.sshkey");
Args = $"fetch --progress --verbose {remote.Remote} {remote.Name}:{local.Name}";
}
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
_outputHandler?.Invoke(line); _outputHandler?.Invoke(line);

View file

@ -20,8 +20,9 @@ namespace SourceGit.Commands
} }
} }
public GenerateCommitMessage(string repo, List<Models.Change> changes, CancellationToken cancelToken, Action<string> onProgress) public GenerateCommitMessage(Models.OpenAIService service, string repo, List<Models.Change> changes, CancellationToken cancelToken, Action<string> onProgress)
{ {
_service = service;
_repo = repo; _repo = repo;
_changes = changes; _changes = changes;
_cancelToken = cancelToken; _cancelToken = cancelToken;
@ -75,7 +76,7 @@ namespace SourceGit.Commands
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd(); var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
var diff = rs.IsSuccess ? rs.StdOut : "unknown change"; var diff = rs.IsSuccess ? rs.StdOut : "unknown change";
var rsp = Models.OpenAI.Chat(Models.OpenAI.AnalyzeDiffPrompt, $"Here is the `git diff` output: {diff}", _cancelToken); var rsp = _service.Chat(_service.AnalyzeDiffPrompt, $"Here is the `git diff` output: {diff}", _cancelToken);
if (rsp != null && rsp.Choices.Count > 0) if (rsp != null && rsp.Choices.Count > 0)
return rsp.Choices[0].Message.Content; return rsp.Choices[0].Message.Content;
@ -84,13 +85,14 @@ namespace SourceGit.Commands
private string GenerateSubject(string summary) private string GenerateSubject(string summary)
{ {
var rsp = Models.OpenAI.Chat(Models.OpenAI.GenerateSubjectPrompt, $"Here are the summaries changes:\n{summary}", _cancelToken); var rsp = _service.Chat(_service.GenerateSubjectPrompt, $"Here are the summaries changes:\n{summary}", _cancelToken);
if (rsp != null && rsp.Choices.Count > 0) if (rsp != null && rsp.Choices.Count > 0)
return rsp.Choices[0].Message.Content; return rsp.Choices[0].Message.Content;
return string.Empty; return string.Empty;
} }
private Models.OpenAIService _service;
private string _repo; private string _repo;
private List<Models.Change> _changes; private List<Models.Change> _changes;
private CancellationToken _cancelToken; private CancellationToken _cancelToken;

View file

@ -4,7 +4,7 @@ namespace SourceGit.Commands
{ {
public class Pull : Command public class Pull : Command
{ {
public Pull(string repo, string remote, string branch, bool useRebase, bool noTags, Action<string> outputHandler) public Pull(string repo, string remote, string branch, bool useRebase, bool noTags, bool prune, Action<string> outputHandler)
{ {
_outputHandler = outputHandler; _outputHandler = outputHandler;
WorkingDirectory = repo; WorkingDirectory = repo;
@ -17,6 +17,8 @@ namespace SourceGit.Commands
Args += "--rebase "; Args += "--rebase ";
if (noTags) if (noTags)
Args += "--no-tags "; Args += "--no-tags ";
if (prune)
Args += "--prune ";
Args += $"{remote} {branch}"; Args += $"{remote} {branch}";
} }

View file

@ -0,0 +1,35 @@
namespace SourceGit.Commands
{
public class QueryCommitSignInfo : Command
{
public QueryCommitSignInfo(string repo, string sha, bool useFakeSignersFile)
{
WorkingDirectory = repo;
Context = repo;
const string baseArgs = "show --no-show-signature --pretty=format:\"%G?%n%GS%n%GK\" -s";
const string fakeSignersFileArg = "-c gpg.ssh.allowedSignersFile=/dev/null";
Args = $"{(useFakeSignersFile ? fakeSignersFileArg : string.Empty)} {baseArgs} {sha}";
}
public Models.CommitSignInfo Result()
{
var rs = ReadToEnd();
if (!rs.IsSuccess)
return null;
var raw = rs.StdOut.Trim();
if (raw.Length <= 1)
return null;
var lines = raw.Split('\n');
return new Models.CommitSignInfo()
{
VerifyResult = lines[0][0],
Signer = lines[1],
Key = lines[2]
};
}
}
}

View file

@ -11,7 +11,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"ls-tree {revision} -l -- {file}"; Args = $"ls-tree {revision} -l -- \"{file}\"";
} }
public long Result() public long Result()

View file

@ -17,24 +17,29 @@ namespace SourceGit.Commands
return Exec(); return Exec();
} }
public bool Push(List<Models.Change> changes, string message, bool onlyStaged) public bool Push(List<Models.Change> changes, string message, bool onlyStaged, bool keepIndex)
{ {
var pathsBuilder = new StringBuilder(); var builder = new StringBuilder();
builder.Append("stash push ");
if (onlyStaged)
builder.Append("--staged ");
if (keepIndex)
builder.Append("--keep-index ");
builder.Append("-m \"");
builder.Append(message);
builder.Append("\" -- ");
if (onlyStaged) if (onlyStaged)
{ {
foreach (var c in changes) foreach (var c in changes)
pathsBuilder.Append($"\"{c.Path}\" "); builder.Append($"\"{c.Path}\" ");
var paths = pathsBuilder.ToString();
Args = $"stash push --staged -m \"{message}\" -- {paths}";
} }
else else
{ {
var needAdd = new List<Models.Change>(); var needAdd = new List<Models.Change>();
foreach (var c in changes) foreach (var c in changes)
{ {
pathsBuilder.Append($"\"{c.Path}\" "); builder.Append($"\"{c.Path}\" ");
if (c.WorkTree == Models.ChangeState.Added || c.WorkTree == Models.ChangeState.Untracked) if (c.WorkTree == Models.ChangeState.Added || c.WorkTree == Models.ChangeState.Untracked)
{ {
@ -51,11 +56,9 @@ namespace SourceGit.Commands
new Add(WorkingDirectory, needAdd).Exec(); new Add(WorkingDirectory, needAdd).Exec();
needAdd.Clear(); needAdd.Clear();
} }
var paths = pathsBuilder.ToString();
Args = $"stash push -m \"{message}\" -- {paths}";
} }
Args = builder.ToString();
return Exec(); return Exec();
} }

View file

@ -0,0 +1,60 @@
using Avalonia.Media;
namespace SourceGit.Models
{
public class CommitSignInfo
{
public char VerifyResult { get; init; } = 'N';
public string Signer { get; init; } = string.Empty;
public string Key { get; init; } = string.Empty;
public bool HasSigner => !string.IsNullOrEmpty(Signer);
public IBrush Brush
{
get
{
switch (VerifyResult)
{
case 'G':
case 'U':
return Brushes.Green;
case 'X':
case 'Y':
case 'R':
return Brushes.DarkOrange;
case 'B':
case 'E':
return Brushes.Red;
default:
return Brushes.Transparent;
}
}
}
public string ToolTip
{
get
{
switch (VerifyResult)
{
case 'G':
return "Good signature.";
case 'U':
return "Good signature with unknown validity.";
case 'X':
return "Good signature but has expired.";
case 'Y':
return "Good signature made by expired key.";
case 'R':
return "Good signature made by a revoked key.";
case 'B':
return "Bad signature.";
case 'E':
return "Signature cannot be checked.";
default:
return "No signature.";
}
}
}
}
}

View file

@ -0,0 +1,42 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.Models
{
public enum CustomActionScope
{
Repository,
Commit,
}
public class CustomAction : ObservableObject
{
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
public CustomActionScope Scope
{
get => _scope;
set => SetProperty(ref _scope, value);
}
public string Executable
{
get => _executable;
set => SetProperty(ref _executable, value);
}
public string Arguments
{
get => _arguments;
set => SetProperty(ref _arguments, value);
}
private string _name = string.Empty;
private CustomActionScope _scope = CustomActionScope.Repository;
private string _executable = string.Empty;
private string _arguments = string.Empty;
}
}

View file

@ -13,15 +13,13 @@ namespace SourceGit.Models
public class ExternalTool public class ExternalTool
{ {
public string Name { get; private set; } public string Name { get; private set; }
public string Executable { get; private set; }
public string OpenCmdArgs { get; private set; }
public Bitmap IconImage { get; private set; } = null; public Bitmap IconImage { get; private set; } = null;
public ExternalTool(string name, string icon, string executable, string openCmdArgs) public ExternalTool(string name, string icon, string execFile, Func<string, string> execArgsGenerator = null)
{ {
Name = name; Name = name;
Executable = executable; _execFile = execFile;
OpenCmdArgs = openCmdArgs; _execArgsGenerator = execArgsGenerator ?? (repo => $"\"{repo}\"");
try try
{ {
@ -40,11 +38,14 @@ namespace SourceGit.Models
Process.Start(new ProcessStartInfo() Process.Start(new ProcessStartInfo()
{ {
WorkingDirectory = repo, WorkingDirectory = repo,
FileName = Executable, FileName = _execFile,
Arguments = string.Format(OpenCmdArgs, repo), Arguments = _execArgsGenerator.Invoke(repo),
UseShellExecute = false, UseShellExecute = false,
}); });
} }
private string _execFile = string.Empty;
private Func<string, string> _execArgsGenerator = null;
} }
public class JetBrainsState public class JetBrainsState
@ -110,48 +111,48 @@ namespace SourceGit.Models
_customPaths = new ExternalToolPaths(); _customPaths = new ExternalToolPaths();
} }
public void TryAdd(string name, string icon, string args, string key, Func<string> finder) public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null)
{ {
if (_customPaths.Tools.TryGetValue(key, out var customPath) && File.Exists(customPath)) if (_customPaths.Tools.TryGetValue(name, out var customPath) && File.Exists(customPath))
{ {
Founded.Add(new ExternalTool(name, icon, customPath, args)); Founded.Add(new ExternalTool(name, icon, customPath, execArgsGenerator));
} }
else else
{ {
var path = finder(); var path = finder();
if (!string.IsNullOrEmpty(path) && File.Exists(path)) if (!string.IsNullOrEmpty(path) && File.Exists(path))
Founded.Add(new ExternalTool(name, icon, path, args)); Founded.Add(new ExternalTool(name, icon, path, execArgsGenerator));
} }
} }
public void VSCode(Func<string> platformFinder) public void VSCode(Func<string> platformFinder)
{ {
TryAdd("Visual Studio Code", "vscode", "\"{0}\"", "VSCODE", platformFinder); TryAdd("Visual Studio Code", "vscode", platformFinder);
} }
public void VSCodeInsiders(Func<string> platformFinder) public void VSCodeInsiders(Func<string> platformFinder)
{ {
TryAdd("Visual Studio Code - Insiders", "vscode_insiders", "\"{0}\"", "VSCODE_INSIDERS", platformFinder); TryAdd("Visual Studio Code - Insiders", "vscode_insiders", platformFinder);
} }
public void VSCodium(Func<string> platformFinder) public void VSCodium(Func<string> platformFinder)
{ {
TryAdd("VSCodium", "codium", "\"{0}\"", "VSCODIUM", platformFinder); TryAdd("VSCodium", "codium", platformFinder);
} }
public void Fleet(Func<string> platformFinder) public void Fleet(Func<string> platformFinder)
{ {
TryAdd("Fleet", "fleet", "\"{0}\"", "FLEET", platformFinder); TryAdd("Fleet", "fleet", platformFinder);
} }
public void SublimeText(Func<string> platformFinder) public void SublimeText(Func<string> platformFinder)
{ {
TryAdd("Sublime Text", "sublime_text", "\"{0}\"", "SUBLIME_TEXT", platformFinder); TryAdd("Sublime Text", "sublime_text", platformFinder);
} }
public void Zed(Func<string> platformFinder) public void Zed(Func<string> platformFinder)
{ {
TryAdd("Zed", "zed", "\"{0}\"", "ZED", platformFinder); TryAdd("Zed", "zed", platformFinder);
} }
public void FindJetBrainsFromToolbox(Func<string> platformFinder) public void FindJetBrainsFromToolbox(Func<string> platformFinder)
@ -170,8 +171,7 @@ namespace SourceGit.Models
Founded.Add(new ExternalTool( Founded.Add(new ExternalTool(
$"{tool.DisplayName} {tool.DisplayVersion}", $"{tool.DisplayName} {tool.DisplayVersion}",
supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB", supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB",
Path.Combine(tool.InstallLocation, tool.LaunchCommand), Path.Combine(tool.InstallLocation, tool.LaunchCommand)));
"\"{0}\""));
} }
} }
} }

View file

@ -8,8 +8,9 @@ namespace SourceGit.Models
public string Key { get; set; } public string Key { get; set; }
public static readonly List<Locale> Supported = new List<Locale>() { public static readonly List<Locale> Supported = new List<Locale>() {
new Locale("English", "en_US"),
new Locale("Deutsch", "de_DE"), new Locale("Deutsch", "de_DE"),
new Locale("English", "en_US"),
new Locale("Español", "es_ES"),
new Locale("Français", "fr_FR"), new Locale("Français", "fr_FR"),
new Locale("Português (Brasil)", "pt_BR"), new Locale("Português (Brasil)", "pt_BR"),
new Locale("Русский", "ru_RU"), new Locale("Русский", "ru_RU"),

View file

@ -21,6 +21,10 @@
int loc2 = 0; int loc2 = 0;
bool isDigit1 = char.IsDigit(c1); bool isDigit1 = char.IsDigit(c1);
bool isDigit2 = char.IsDigit(c2);
if (isDigit1 != isDigit2)
return c1.CompareTo(c2);
do do
{ {
tmp1[loc1] = c1; tmp1[loc1] = c1;
@ -33,7 +37,6 @@
break; break;
} while (char.IsDigit(c1) == isDigit1); } while (char.IsDigit(c1) == isDigit1);
bool isDigit2 = char.IsDigit(c2);
do do
{ {
tmp2[loc2] = c2; tmp2[loc2] = c2;
@ -49,16 +52,10 @@
string sub1 = new string(tmp1, 0, loc1); string sub1 = new string(tmp1, 0, loc1);
string sub2 = new string(tmp2, 0, loc2); string sub2 = new string(tmp2, 0, loc2);
int result; int result;
if (isDigit1 && isDigit2) if (isDigit1)
{ result = loc1 == loc2 ? string.CompareOrdinal(sub1, sub2) : loc1 - loc2;
int num1 = int.Parse(sub1);
int num2 = int.Parse(sub2);
result = num1 - num2;
}
else else
{ result = string.CompareOrdinal(sub1, sub2);
result = string.Compare(sub1, sub2, System.StringComparison.Ordinal);
}
if (result != 0) if (result != 0)
return result; return result;

View file

@ -6,6 +6,8 @@ using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Threading; using System.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.Models namespace SourceGit.Models
{ {
public class OpenAIChatMessage public class OpenAIChatMessage
@ -74,44 +76,78 @@ namespace SourceGit.Models
} }
} }
public static class OpenAI public class OpenAIService : ObservableObject
{ {
public static string Server public string Name
{ {
get; get => _name;
set; set => SetProperty(ref _name, value);
} }
public static string ApiKey public string Server
{ {
get; get => _server;
set; set => SetProperty(ref _server, value);
} }
public static string Model public string ApiKey
{ {
get; get => _apiKey;
set; set => SetProperty(ref _apiKey, value);
} }
public static string AnalyzeDiffPrompt public string Model
{ {
get; get => _model;
set; set => SetProperty(ref _model, value);
} }
public static string GenerateSubjectPrompt public string AnalyzeDiffPrompt
{ {
get; get => _analyzeDiffPrompt;
set; set => SetProperty(ref _analyzeDiffPrompt, value);
} }
public static bool IsValid public string GenerateSubjectPrompt
{ {
get => !string.IsNullOrEmpty(Server) && !string.IsNullOrEmpty(Model); get => _generateSubjectPrompt;
set => SetProperty(ref _generateSubjectPrompt, value);
} }
public static OpenAIChatResponse Chat(string prompt, string question, CancellationToken cancellation) public OpenAIService()
{
AnalyzeDiffPrompt = """
You are an expert developer specialist in creating commits.
Provide a super concise one sentence overall changes summary of the user `git diff` output following strictly the next rules:
- Do not use any code snippets, imports, file routes or bullets points.
- Do not mention the route of file that has been change.
- Write clear, concise, and descriptive messages that explain the MAIN GOAL made of the changes.
- Use the present tense and active voice in the message, for example, "Fix bug" instead of "Fixed bug.".
- Use the imperative mood, which gives the message a sense of command, e.g. "Add feature" instead of "Added feature".
- Avoid using general terms like "update" or "change", be specific about what was updated or changed.
- Avoid using terms like "The main goal of", just output directly the summary in plain text
""";
GenerateSubjectPrompt = """
You are an expert developer specialist in creating commits messages.
Your only goal is to retrieve a single commit message.
Based on the provided user changes, combine them in ONE SINGLE commit message retrieving the global idea, following strictly the next rules:
- Assign the commit {type} according to the next conditions:
feat: Only when adding a new feature.
fix: When fixing a bug.
docs: When updating documentation.
style: When changing elements styles or design and/or making changes to the code style (formatting, missing semicolons, etc.) without changing the code logic.
test: When adding or updating tests.
chore: When making changes to the build process or auxiliary tools and libraries.
revert: When undoing a previous commit.
refactor: When restructuring code without changing its external behavior, or is any of the other refactor types.
- Do not add any issues numeration, explain your output nor introduce your answer.
- Output directly only one commit message in plain text with the next format: {type}: {commit_message}.
- Be as concise as possible, keep the message under 50 characters.
""";
}
public OpenAIChatResponse Chat(string prompt, string question, CancellationToken cancellation)
{ {
var chat = new OpenAIChatRequest() { Model = Model }; var chat = new OpenAIChatRequest() { Model = Model };
chat.AddMessage("system", prompt); chat.AddMessage("system", prompt);
@ -144,5 +180,12 @@ namespace SourceGit.Models
throw; throw;
} }
} }
private string _name;
private string _server;
private string _apiKey;
private string _model;
private string _analyzeDiffPrompt;
private string _generateSubjectPrompt;
} }
} }

View file

@ -16,6 +16,12 @@ namespace SourceGit.Models
set; set;
} = DealWithLocalChanges.DoNothing; } = DealWithLocalChanges.DoNothing;
public bool EnablePruneOnFetch
{
get;
set;
} = false;
public bool FetchWithoutTags public bool FetchWithoutTags
{ {
get; get;
@ -94,6 +100,12 @@ namespace SourceGit.Models
set; set;
} = new AvaloniaList<IssueTrackerRule>(); } = new AvaloniaList<IssueTrackerRule>();
public AvaloniaList<CustomAction> CustomActions
{
get;
set;
} = new AvaloniaList<CustomAction>();
public bool EnableAutoFetch public bool EnableAutoFetch
{ {
get; get;
@ -112,6 +124,30 @@ namespace SourceGit.Models
set; set;
} = false; } = false;
public bool IncludeUntrackedWhenStash
{
get;
set;
} = true;
public bool OnlyStagedWhenStash
{
get;
set;
} = false;
public bool KeepIndexWhenStash
{
get;
set;
} = false;
public string PreferedOpenAIService
{
get;
set;
} = "---";
public void PushCommitMessage(string message) public void PushCommitMessage(string message)
{ {
var existIdx = CommitMessages.IndexOf(message); var existIdx = CommitMessages.IndexOf(message);
@ -200,5 +236,22 @@ namespace SourceGit.Models
if (rule != null) if (rule != null)
IssueTrackerRules.Remove(rule); IssueTrackerRules.Remove(rule);
} }
public CustomAction AddNewCustomAction()
{
var act = new CustomAction()
{
Name = "Unnamed Custom Action",
};
CustomActions.Add(act);
return act;
}
public void RemoveCustomAction(CustomAction act)
{
if (act != null)
CustomActions.Remove(act);
}
} }
} }

View file

@ -134,6 +134,7 @@ namespace SourceGit.Native
finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe"); finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe");
finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox"); finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox");
finder.SublimeText(FindSublimeText); finder.SublimeText(FindSublimeText);
finder.TryAdd("Visual Studio", "vs", FindVisualStudio, GenerateCommandlineArgsForVisualStudio);
return finder.Founded; return finder.Founded;
} }
@ -313,6 +314,27 @@ namespace SourceGit.Native
return string.Empty; return string.Empty;
} }
private string FindVisualStudio()
{
var localMachine = Microsoft.Win32.RegistryKey.OpenBaseKey(
Microsoft.Win32.RegistryHive.LocalMachine,
Microsoft.Win32.RegistryView.Registry64);
// Get default class for VisualStudio.Launcher.sln - the handler for *.sln files
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 &&
devenv.GetValue(string.Empty) is string localServer32)
{
return localServer32!.Trim('\"');
}
}
return string.Empty;
}
#endregion #endregion
private void OpenFolderAndSelectFile(string folderPath) private void OpenFolderAndSelectFile(string folderPath)
@ -328,5 +350,31 @@ namespace SourceGit.Native
ILFree(pidl); ILFree(pidl);
} }
} }
private string GenerateCommandlineArgsForVisualStudio(string repo)
{
var sln = FindVSSolutionFile(repo, 4);
return string.IsNullOrEmpty(sln) ? $"\"{repo}\"" : $"\"{sln}\"";
}
private string FindVSSolutionFile(string path, int leftDepth)
{
var found = Directory.GetFiles(path, "*.sln", SearchOption.TopDirectoryOnly);
if (found != null && found.Length > 0)
return Path.GetFullPath(found[0]);
if (leftDepth <= 0)
return null;
var subfolders = Directory.GetDirectories(path);
foreach (var subfolder in subfolders)
{
var first = FindVSSolutionFile(subfolder, leftDepth - 1);
if (!string.IsNullOrEmpty(first))
return first;
}
return null;
}
} }
} }

View file

@ -1,4 +1,5 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <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">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.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.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.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>
@ -71,9 +72,6 @@
<StreamGeometry x:Key="Icons.Loading">M512 0C233 0 7 223 0 500C6 258 190 64 416 64c230 0 416 200 416 448c0 53 43 96 96 96s96-43 96-96c0-283-229-512-512-512zm0 1023c279 0 505-223 512-500c-6 242-190 436-416 436c-230 0-416-200-416-448c0-53-43-96-96-96s-96 43-96 96c0 283 229 512 512 512z</StreamGeometry> <StreamGeometry x:Key="Icons.Loading">M512 0C233 0 7 223 0 500C6 258 190 64 416 64c230 0 416 200 416 448c0 53 43 96 96 96s96-43 96-96c0-283-229-512-512-512zm0 1023c279 0 505-223 512-500c-6 242-190 436-416 436c-230 0-416-200-416-448c0-53-43-96-96-96s-96 43-96 96c0 283 229 512 512 512z</StreamGeometry>
<StreamGeometry x:Key="Icons.Local">M976 0h-928A48 48 0 000 48v652a48 48 0 0048 48h416V928H200a48 48 0 000 96h624a48 48 0 000-96H560v-180h416a48 48 0 0048-48V48A48 48 0 00976 0zM928 652H96V96h832v556z</StreamGeometry> <StreamGeometry x:Key="Icons.Local">M976 0h-928A48 48 0 000 48v652a48 48 0 0048 48h416V928H200a48 48 0 000 96h624a48 48 0 000-96H560v-180h416a48 48 0 0048-48V48A48 48 0 00976 0zM928 652H96V96h832v556z</StreamGeometry>
<StreamGeometry x:Key="Icons.Lock">M832 464h-68V240a128 128 0 00-128-128h-248a128 128 0 00-128 128v224H192c-18 0-32 14-32 32v384c0 18 14 32 32 32h640c18 0 32-14 32-32v-384c0-18-14-32-32-32zm-292 237v53a8 8 0 01-8 8h-40a8 8 0 01-8-8v-53a48 48 0 1156 0zm152-237H332V240a56 56 0 0156-56h248a56 56 0 0156 56v224z</StreamGeometry> <StreamGeometry x:Key="Icons.Lock">M832 464h-68V240a128 128 0 00-128-128h-248a128 128 0 00-128 128v224H192c-18 0-32 14-32 32v384c0 18 14 32 32 32h640c18 0 32-14 32-32v-384c0-18-14-32-32-32zm-292 237v53a8 8 0 01-8 8h-40a8 8 0 01-8-8v-53a48 48 0 1156 0zm152-237H332V240a56 56 0 0156-56h248a56 56 0 0156 56v224z</StreamGeometry>
<StreamGeometry x:Key="Icons.MacOS.Close">M887 774 625 511l263-260c11-11 11-28 0-39l-75-75c-5-5-12-8-20-8-7 0-14 3-20 8L512 396 250 137c-5-5-12-8-20-8-7 0-14 3-20 8L136 212c-11 11-11 28 0 39l263 260L137 774c-5 5-8 12-8 20 0 7 3 14 8 20l75 75c5 5 12 8 20 8 7 0 14-3 20-8L512 626l261 262c5 5 12 8 20 8 7 0 14-3 20-8l75-75c5-5 8-12 8-20C895 786 892 779 887 774z</StreamGeometry>
<StreamGeometry x:Key="Icons.MacOS.Minimize">M1024 750v110c0 50-41 91-91 91h-841A92 92 0 010 859v-110C0 699 41 658 91 658h841c50 0 91 41 91 91z</StreamGeometry>
<StreamGeometry x:Key="Icons.MacOS.Maximize">M0 4 0 20 16 20 0 4M4 0 20 0 20 16 4 0z</StreamGeometry>
<StreamGeometry x:Key="Icons.Menu">M192 192m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM192 512m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM192 832m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM864 160H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32zM864 480H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32zM864 800H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32z</StreamGeometry> <StreamGeometry x:Key="Icons.Menu">M192 192m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM192 512m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM192 832m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM864 160H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32zM864 480H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32zM864 800H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32z</StreamGeometry>
<StreamGeometry x:Key="Icons.Merge">M824 645V307c0-56-46-102-102-102h-102V102l-154 154 154 154V307h102v338c-46 20-82 67-82 123 0 72 61 133 133 133 72 0 133-61 133-133 0-56-36-102-82-123zm-51 195c-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72s-31 72-72 72zM384 256c0-72-61-133-133-133-72 0-133 61-133 133 0 56 36 102 82 123v266C154 666 118 712 118 768c0 72 61 133 133 133 72 0 133-61 133-133 0-56-36-102-82-123V379C348 358 384 312 384 256zM323 768c0 41-31 72-72 72-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72zM251 328c-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72s-31 72-72 72z</StreamGeometry> <StreamGeometry x:Key="Icons.Merge">M824 645V307c0-56-46-102-102-102h-102V102l-154 154 154 154V307h102v338c-46 20-82 67-82 123 0 72 61 133 133 133 72 0 133-61 133-133 0-56-36-102-82-123zm-51 195c-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72s-31 72-72 72zM384 256c0-72-61-133-133-133-72 0-133 61-133 133 0 56 36 102 82 123v266C154 666 118 712 118 768c0 72 61 133 133 133 72 0 133-61 133-133 0-56-36-102-82-123V379C348 358 384 312 384 256zM323 768c0 41-31 72-72 72-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72zM251 328c-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72s-31 72-72 72z</StreamGeometry>
<StreamGeometry x:Key="Icons.Modified">M896 64H128C96 64 64 96 64 128v768c0 32 32 64 64 64h768c32 0 64-32 64-64V128c0-32-32-64-64-64z m-64 736c0 16-17 32-32 32H224c-18 0-32-12-32-32V224c0-16 16-32 32-32h576c15 0 32 16 32 32v576zM512 384c-71 0-128 57-128 128s57 128 128 128 128-57 128-128-57-128-128-128z</StreamGeometry> <StreamGeometry x:Key="Icons.Modified">M896 64H128C96 64 64 96 64 128v768c0 32 32 64 64 64h768c32 0 64-32 64-64V128c0-32-32-64-64-64z m-64 736c0 16-17 32-32 32H224c-18 0-32-12-32-32V224c0-16 16-32 32-32h576c15 0 32 16 32 32v576zM512 384c-71 0-128 57-128 128s57 128 128 128 128-57 128-128-57-128-128-128z</StreamGeometry>
@ -121,6 +119,7 @@
<StreamGeometry x:Key="Icons.Undo">M762 1024C876 818 895 504 448 514V768L64 384l384-384v248c535-14 595 472 314 776z</StreamGeometry> <StreamGeometry x:Key="Icons.Undo">M762 1024C876 818 895 504 448 514V768L64 384l384-384v248c535-14 595 472 314 776z</StreamGeometry>
<StreamGeometry x:Key="Icons.Unlock">M832 464H332V240c0-31 25-56 56-56h248c31 0 56 25 56 56v68c0 4 4 8 8 8h56c4 0 8-4 8-8v-68c0-71-57-128-128-128H388c-71 0-128 57-128 128v224h-68c-18 0-32 14-32 32v384c0 18 14 32 32 32h640c18 0 32-14 32-32V496c0-18-14-32-32-32zM540 701v53c0 4-4 8-8 8h-40c-4 0-8-4-8-8v-53c-12-9-20-23-20-39 0-27 22-48 48-48s48 22 48 48c0 16-8 30-20 39z</StreamGeometry> <StreamGeometry x:Key="Icons.Unlock">M832 464H332V240c0-31 25-56 56-56h248c31 0 56 25 56 56v68c0 4 4 8 8 8h56c4 0 8-4 8-8v-68c0-71-57-128-128-128H388c-71 0-128 57-128 128v224h-68c-18 0-32 14-32 32v384c0 18 14 32 32 32h640c18 0 32-14 32-32V496c0-18-14-32-32-32zM540 701v53c0 4-4 8-8 8h-40c-4 0-8-4-8-8v-53c-12-9-20-23-20-39 0-27 22-48 48-48s48 22 48 48c0 16-8 30-20 39z</StreamGeometry>
<StreamGeometry x:Key="Icons.Up">M170 831l343-342L855 831l105-105-448-448L64 726 170 831z</StreamGeometry> <StreamGeometry x:Key="Icons.Up">M170 831l343-342L855 831l105-105-448-448L64 726 170 831z</StreamGeometry>
<StreamGeometry x:Key="Icons.Verified">M880 128A722 722 0 01555 13a77 77 0 00-85 0 719 719 0 01-325 115c-40 4-71 38-71 80v369c0 246 329 446 439 446 110 0 439-200 439-446V207c0-41-31-76-71-80zM465 692a36 36 0 01-53 0L305 579a42 42 0 010-57 36 36 0 0153 0l80 85L678 353a36 36 0 0153 0 42 42 0 01-0 57L465 692z</StreamGeometry>
<StreamGeometry x:Key="Icons.Waiting">M812 864h-29V654c0-21-11-40-28-52l-133-88 134-89c18-12 28-31 28-52V164h28c18 0 32-14 32-32s-14-32-32-32H212c-18 0-32 14-32 32s14 32 32 32h30v210c0 21 11 40 28 52l133 88-134 89c-18 12-28 31-28 52V864H212c-18 0-32 14-32 32s14 32 32 32h600c18 0 32-14 32-32s-14-32-32-32zM441 566c18-12 28-31 28-52s-11-40-28-52L306 373V164h414v209l-136 90c-18 12-28 31-28 52 0 21 11 40 28 52l135 89V695c-9-7-20-13-32-19-30-15-93-41-176-41-63 0-125 14-175 38-12 6-22 12-31 18v-36l136-90z</StreamGeometry> <StreamGeometry x:Key="Icons.Waiting">M812 864h-29V654c0-21-11-40-28-52l-133-88 134-89c18-12 28-31 28-52V164h28c18 0 32-14 32-32s-14-32-32-32H212c-18 0-32 14-32 32s14 32 32 32h30v210c0 21 11 40 28 52l133 88-134 89c-18 12-28 31-28 52V864H212c-18 0-32 14-32 32s14 32 32 32h600c18 0 32-14 32-32s-14-32-32-32zM441 566c18-12 28-31 28-52s-11-40-28-52L306 373V164h414v209l-136 90c-18 12-28 31-28 52 0 21 11 40 28 52l135 89V695c-9-7-20-13-32-19-30-15-93-41-176-41-63 0-125 14-175 38-12 6-22 12-31 18v-36l136-90z</StreamGeometry>
<StreamGeometry x:Key="Icons.Whitespace">M0 512M1024 512M512 0M512 1024M762 412v100h-500v-100h-150v200h800v-200h-150z</StreamGeometry> <StreamGeometry x:Key="Icons.Whitespace">M0 512M1024 512M512 0M512 1024M762 412v100h-500v-100h-150v200h800v-200h-150z</StreamGeometry>
<StreamGeometry x:Key="Icons.Window.Close">M519 459 222 162a37 37 0 10-52 52l297 297L169 809a37 37 0 1052 52l297-297 297 297a37 37 0 1052-52l-297-297 297-297a37 37 0 10-52-52L519 459z</StreamGeometry> <StreamGeometry x:Key="Icons.Window.Close">M519 459 222 162a37 37 0 10-52 52l297 297L169 809a37 37 0 1052 52l297-297 297 297a37 37 0 1052-52l-297-297 297-297a37 37 0 10-52-52L519 459z</StreamGeometry>

View file

@ -55,6 +55,7 @@
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Delete selected {0} branches</x:String> <x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Delete selected {0} branches</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Discard all changes</x:String> <x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Discard all changes</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Fast-Forward to ${0}$</x:String> <x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Fast-Forward to ${0}$</x:String>
<x:String x:Key="Text.BranchCM.FetchInto" xml:space="preserve">Fetch ${0}$ into ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git Flow - Finish ${0}$</x:String> <x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git Flow - Finish ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Merge ${0}$ into ${1}$...</x:String> <x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Merge ${0}$ into ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Pull ${0}$</x:String> <x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Pull ${0}$</x:String>
@ -69,6 +70,7 @@
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCEL</x:String> <x:String x:Key="Text.Cancel" xml:space="preserve">CANCEL</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Reset to This Revision</x:String> <x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Reset to This Revision</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Reset to Parent Revision</x:String> <x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Reset to Parent Revision</x:String>
<x:String x:Key="Text.ChangeCM.GenerateCommitMessage" xml:space="preserve">Generate commit message</x:String>
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">CHANGE DISPLAY MODE</x:String> <x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">CHANGE DISPLAY MODE</x:String>
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Show as File and Dir List</x:String> <x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Show as File and Dir List</x:String>
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Show as Path List</x:String> <x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Show as Path List</x:String>
@ -106,6 +108,7 @@
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String> <x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copy Info</x:String> <x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copy Info</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copy SHA</x:String> <x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copy SHA</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Custom Action</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactive Rebase ${0}$ to Here</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactive Rebase ${0}$ to Here</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ to Here</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ to Here</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ to Here</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ to Here</x:String>
@ -137,12 +140,21 @@
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">COMMIT TEMPLATE</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">COMMIT TEMPLATE</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Template Name:</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Template Name:</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Template Content:</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Template Content:</x:String>
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">CUSTOM ACTION</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">Arguments:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">${REPO} - Repository's path; ${SHA} - Selected commit's SHA</x:String>
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Executable File:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Name:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Scope:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String> <x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String> <x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String> <x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Fetch remotes automatically</x:String> <x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Fetch remotes automatically</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(s)</x:String> <x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(s)</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Default Remote</x:String> <x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Default Remote</x:String>
<x:String x:Key="Text.Configure.Git.EnablePruneOnFetch" xml:space="preserve">Enable --prune on fetch</x:String>
<x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">Enable --signoff for commit</x:String> <x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">Enable --signoff for commit</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE TRACKER</x:String> <x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE TRACKER</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Add Sample Github Rule</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Add Sample Github Rule</x:String>
@ -154,6 +166,9 @@
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Rule Name:</x:String> <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" 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.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.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> <x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP Proxy</x:String>
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP proxy used by this repository</x:String> <x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP proxy used by this repository</x:String>
<x:String x:Key="Text.Configure.User" xml:space="preserve">User Name</x:String> <x:String x:Key="Text.Configure.User" xml:space="preserve">User Name</x:String>
@ -246,6 +261,8 @@
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Target:</x:String> <x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Edit Selected Group</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Edit Selected Group</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Edit Selected Repository</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Edit Selected Repository</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Run Custom Action</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Action Name:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String> <x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</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 all remotes</x:String> <x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch all remotes</x:String>
@ -401,12 +418,12 @@
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">Last year</x:String> <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.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" xml:space="preserve">Preference</x:String>
<x:String x:Key="Text.Preference.Advanced" xml:space="preserve">Advanced Options</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">OPEN 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.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.ApiKey" xml:space="preserve">API Key</x:String>
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String> <x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Model</x:String> <x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Model</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.Server" xml:space="preserve">Server</x:String>
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">APPEARANCE</x:String> <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.DefaultFont" xml:space="preserve">Default Font</x:String>
@ -510,6 +527,8 @@
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String>
<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.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.Filter" xml:space="preserve">Search Branches/Tags/Submodules</x:String>
@ -572,6 +591,7 @@
<x:String x:Key="Text.Start" xml:space="preserve">START</x:String> <x:String x:Key="Text.Start" xml:space="preserve">START</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Include untracked files</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Include untracked files</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Keep staged files</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Message:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Message:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Name of this stash</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Name of this stash</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Only staged changes</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Only staged changes</x:String>

View file

@ -0,0 +1,670 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="avares://SourceGit/Resources/Locales/en_US.axaml"/>
</ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">Acerca de</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">Acerca de SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Construido con </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• El gráfico es renderizado por </x:String>
<x:String x:Key="Text.About.Copyright" xml:space="preserve">© 2024 sourcegit-scm</x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• Editor de texto de </x:String>
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• Las fuentes monoespaciadas provienen de </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• El código fuente se puede encontrar en </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Cliente Git GUI de código abierto y gratuito</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Agregar Worktree</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Qué Checkout:</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Rama Existente</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Crear Nueva Rama</x:String>
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Ubicación:</x:String>
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Ruta para este worktree. Se admite ruta relativa.</x:String>
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">Nombre de la Rama:</x:String>
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Opcional. Por defecto es el nombre de la carpeta de destino.</x:String>
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Rama de Seguimiento:</x:String>
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Seguimiento de rama remota</x:String>
<x:String x:Key="Text.AIAssistant" xml:space="preserve">Asistente OpenAI</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usar OpenAI para generar mensaje de commit</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Aplicar Patch</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Error</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Genera errores y se niega a aplicar el patch</x:String>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Error Todo</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similar a 'error', pero muestra más</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">Archivo Patch:</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Seleccionar archivo .patch para aplicar</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorar cambios de espacios en blanco</x:String>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Sin Advertencia</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Desactiva la advertencia de espacios en blanco al final</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Aplicar Patch</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Advertencia</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Genera advertencias para algunos de estos errores, pero aplica</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espacios en Blanco:</x:String>
<x:String x:Key="Text.Archive" xml:space="preserve">Archivar...</x:String>
<x:String x:Key="Text.Archive.File" xml:space="preserve">Guardar Archivo en:</x:String>
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Seleccionar ruta del archivo</x:String>
<x:String x:Key="Text.Archive.Revision" xml:space="preserve">Revisión:</x:String>
<x:String x:Key="Text.Archive.Title" xml:space="preserve">Archivar</x:String>
<x:String x:Key="Text.Askpass" xml:space="preserve">SourceGit Askpass</x:String>
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO HAY ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">¡ARCHIVO BINARIO NO SOPORTADO!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">¡BLAME EN ESTE ARCHIVO NO SOPORTADO!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Comparar con Rama</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparar con HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparar con Worktree</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copiar Nombre de Rama</x:String>
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Eliminar ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Eliminar {0} ramas seleccionadas</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Descartar todos los cambios</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Fast-Forward a ${0}$</x:String>
<x:String x:Key="Text.BranchCM.FetchInto" xml:space="preserve">Fetch ${0}$ en ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git Flow - Finalizar ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Merge ${0}$ en ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Pull ${0}$</x:String>
<x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">Pull ${0}$ en ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ en ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Renombrar ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Establecer Rama de Seguimiento</x:String>
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">Desestablecer Upstream</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Comparar Ramas</x:String>
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCELAR</x:String>
<x:String x:Key="Text.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.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>
<x:String x:Key="Text.ChangeDisplayMode.Tree" xml:space="preserve">Mostrar como Árbol de Sistema de Archivos</x:String>
<x:String x:Key="Text.Checkout" xml:space="preserve">Checkout Rama</x:String>
<x:String x:Key="Text.Checkout.Commit" xml:space="preserve">Checkout Commit</x:String>
<x:String x:Key="Text.Checkout.Commit.Warning" xml:space="preserve">Advertencia: Al hacer un checkout de commit, tu Head se separará</x:String>
<x:String x:Key="Text.Checkout.Commit.Target" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Cambios Locales:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Descartar</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.DoNothing" xml:space="preserve">No Hacer Nada</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reaplicar</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Añadir fuente al mensaje de commit</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String>
<x:String x:Key="Text.CherryPick.CommitChanges" xml:space="preserve">Commit todos los cambios</x:String>
<x:String x:Key="Text.CherryPick.Mainline" xml:space="preserve">Mainline:</x:String>
<x:String x:Key="Text.CherryPick.Mainline.Tips" xml:space="preserve">Normalmente no puedes cherry-pick un merge porque no sabes qué lado del merge debe considerarse la línea principal. Esta opción permite que cherry-pick reproduzca el cambio en relación con el padre especificado.</x:String>
<x:String x:Key="Text.ClearStashes" xml:space="preserve">Limpiar Stashes</x:String>
<x:String x:Key="Text.ClearStashes.Message" xml:space="preserve">Estás intentando limpiar todos los stashes. ¿Estás seguro de continuar?</x:String>
<x:String x:Key="Text.Clone" xml:space="preserve">Clonar Repositorio Remoto</x:String>
<x:String x:Key="Text.Clone.AdditionalParam" xml:space="preserve">Parámetros Adicionales:</x:String>
<x:String x:Key="Text.Clone.AdditionalParam.Placeholder" xml:space="preserve">Argumentos adicionales para clonar el repositorio. Opcional.</x:String>
<x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Nombre Local:</x:String>
<x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Nombre del repositorio. Opcional.</x:String>
<x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Carpeta Padre:</x:String>
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">URL del Repositorio:</x:String>
<x:String x:Key="Text.Close" xml:space="preserve">CERRAR</x:String>
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Editor</x:String>
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">Cherry-Pick Este Commit</x:String>
<x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">Cherry-Pick ...</x:String>
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Checkout Commit</x:String>
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Comparar con HEAD</x:String>
<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.InteractiveRebase" xml:space="preserve">Rebase Interactivo ${0}$ hasta Aquí</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>
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Reescribir</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Guardar como Patch...</x:String>
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash en Parent</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Squash Commits Hijos hasta Aquí</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CAMBIOS</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Buscar Cambios...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">ARCHIVOS</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">Archivo LFS</x:String>
<x:String x:Key="Text.CommitDetail.Files.Submodule" xml:space="preserve">Submódulo</x:String>
<x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">INFORMACIÓN</x:String>
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTOR</x:String>
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">CAMBIADO</x:String>
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Ver refs que contienen este commit</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">COMMIT ESTÁ CONTENIDO EN</x:String>
<x:String x:Key="Text.CommitDetail.Info.GotoChangesPage" xml:space="preserve">Muestra solo los primeros 100 cambios. Ver todos los cambios en la pestaña CAMBIOS.</x:String>
<x:String x:Key="Text.CommitDetail.Info.Message" xml:space="preserve">MENSAJE</x:String>
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">PADRES</x:String>
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">REFS</x:String>
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Abrir en Navegador</x:String>
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Introducir asunto del commit</x:String>
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Descripción</x:String>
<x:String x:Key="Text.Configure" xml:space="preserve">Configurar Repositorio</x:String>
<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.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.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>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Añadir Regla de Ejemplo para Jira</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGitLabIssue" xml:space="preserve">Añadir Regla de Ejemplo para Incidencias de GitLab</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGitLabMergeRequest" xml:space="preserve">Añadir Regla de Ejemplo para Merge Requests de GitLab</x:String>
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">Nueva Regla</x:String>
<x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">Expresión Regex para Incidencias:</x:String>
<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.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>
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">Nombre de usuario para este repositorio</x:String>
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">Espacios de Trabajo</x:String>
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">Color</x:String>
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">Restaurar pestañas al iniciar</x:String>
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">Asistente de Commit Convencional</x:String>
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">Cambio Importante:</x:String>
<x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">Incidencia Cerrada:</x:String>
<x:String x:Key="Text.ConventionalCommit.Detail" xml:space="preserve">Detalles del Cambio:</x:String>
<x:String x:Key="Text.ConventionalCommit.Scope" xml:space="preserve">Alcance:</x:String>
<x:String x:Key="Text.ConventionalCommit.ShortDescription" xml:space="preserve">Descripción Corta:</x:String>
<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>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Basado En:</x:String>
<x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">Checkout de la rama creada</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">Cambios Locales:</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.Discard" xml:space="preserve">Descartar</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.DoNothing" xml:space="preserve">No Hacer Nada</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reaplicar</x:String>
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nombre de la Nueva Rama:</x:String>
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Introduzca el nombre de la rama.</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Crear Rama Local</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">Crear Etiqueta...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Nueva Etiqueta En:</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">Firma GPG</x:String>
<x:String x:Key="Text.CreateTag.Message" xml:space="preserve">Mensaje de la Etiqueta:</x:String>
<x:String x:Key="Text.CreateTag.Message.Placeholder" xml:space="preserve">Opcional.</x:String>
<x:String x:Key="Text.CreateTag.Name" xml:space="preserve">Nombre de la Etiqueta:</x:String>
<x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">Formato recomendado: v1.0.0-alpha</x:String>
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">Push a todos los remotos después de crear</x:String>
<x:String x:Key="Text.CreateTag.Title" xml:space="preserve">Crear Nueva Etiqueta</x:String>
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">Tipo:</x:String>
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">anotada</x:String>
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">ligera</x:String>
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Mantenga Ctrl para iniciar directamente</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">Cortar</x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Eliminar Rama</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">¡Estás a punto de eliminar una rama remota!</x:String>
<x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">También eliminar la rama remota ${0}$</x:String>
<x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">Eliminar Múltiples Ramas</x:String>
<x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">Estás intentando eliminar múltiples ramas a la vez. ¡Asegúrate de revisar antes de tomar acción!</x:String>
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">Eliminar Remoto</x:String>
<x:String x:Key="Text.DeleteRemote.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">Destino:</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.TitleForGroup" xml:space="preserve">Confirmar Eliminación de Grupo</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.TitleForRepository" xml:space="preserve">Confirmar Eliminación de Repositorio</x:String>
<x:String x:Key="Text.DeleteSubmodule" xml:space="preserve">Eliminar Submódulo</x:String>
<x:String x:Key="Text.DeleteSubmodule.Path" xml:space="preserve">Ruta del Submódulo:</x:String>
<x:String x:Key="Text.DeleteTag" xml:space="preserve">Eliminar Etiqueta</x:String>
<x:String x:Key="Text.DeleteTag.Tag" xml:space="preserve">Etiqueta:</x:String>
<x:String x:Key="Text.DeleteTag.WithRemote" xml:space="preserve">Eliminar de los repositorios remotos</x:String>
<x:String x:Key="Text.Diff.Binary" xml:space="preserve">DIFERENCIA BINARIA</x:String>
<x:String x:Key="Text.Diff.Binary.New" xml:space="preserve">NUEVO</x:String>
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">ANTIGUO</x:String>
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">Copiar</x:String>
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">Modo de Archivo Cambiado</x:String>
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">Ignorar Cambio de Espacios en Blanco</x:String>
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">CAMBIO DE OBJETO LFS</x:String>
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Siguiente Diferencia</x:String>
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">SIN CAMBIOS O SOLO CAMBIOS DE EOL</x:String>
<x:String x:Key="Text.Diff.Prev" xml:space="preserve">Diferencia Anterior</x:String>
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Mostrar símbolos ocultos</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Diferencia Lado a Lado</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SUBMÓDULO</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">NUEVO</x:String>
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Intercambiar</x:String>
<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.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>
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">Abrir en Herramienta de Merge</x:String>
<x:String x:Key="Text.Discard" xml:space="preserve">Descartar Cambios</x:String>
<x:String x:Key="Text.Discard.All" xml:space="preserve">Todos los cambios locales en la copia de trabajo.</x:String>
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Cambios:</x:String>
<x:String x:Key="Text.Discard.IncludeIgnored" xml:space="preserve">Incluir archivos ignorados</x:String>
<x:String x:Key="Text.Discard.Total" xml:space="preserve">Total {0} cambios serán descartados</x:String>
<x:String x:Key="Text.Discard.Warning" xml:space="preserve">¡No puedes deshacer esta acción!</x:String>
<x:String x:Key="Text.EditRepositoryNode.Bookmark" xml:space="preserve">Marcador:</x:String>
<x:String x:Key="Text.EditRepositoryNode.Name" xml:space="preserve">Nuevo Nombre:</x:String>
<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.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>
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">Fetch sin etiquetas</x:String>
<x:String x:Key="Text.Fetch.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">Fetch Cambios Remotos</x:String>
<x:String x:Key="Text.FileCM.AssumeUnchanged" xml:space="preserve">Asumir sin cambios</x:String>
<x:String x:Key="Text.FileCM.Discard" xml:space="preserve">Descartar...</x:String>
<x:String x:Key="Text.FileCM.DiscardMulti" xml:space="preserve">Descartar {0} archivos...</x:String>
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">Descartar Cambios en Línea(s) Seleccionada(s)</x:String>
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Abrir Herramienta de Merge Externa</x:String>
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Guardar Como 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} archivos</x:String>
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Stage Cambios en Línea(s) Seleccionada(s)</x:String>
<x:String x:Key="Text.FileCM.Stash" xml:space="preserve">Stash...</x:String>
<x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">Stash {0} archivos...</x:String>
<x:String x:Key="Text.FileCM.Unstage" xml:space="preserve">Unstage</x:String>
<x:String x:Key="Text.FileCM.UnstageMulti" xml:space="preserve">Unstage {0} archivos</x:String>
<x:String x:Key="Text.FileCM.UnstageSelectedLines" xml:space="preserve">Unstage Cambios en Línea(s) Seleccionada(s)</x:String>
<x:String x:Key="Text.FileCM.UseTheirs" xml:space="preserve">Usar Suyos (checkout --theirs)</x:String>
<x:String x:Key="Text.FileCM.UseMine" xml:space="preserve">Usar Míos (checkout --ours)</x:String>
<x:String x:Key="Text.FileHistory" xml:space="preserve">Historial de Archivos</x:String>
<x:String x:Key="Text.FileHistory.FileContent" xml:space="preserve">CONTENIDO</x:String>
<x:String x:Key="Text.FileHistory.FileChange" xml:space="preserve">CAMBIO</x:String>
<x:String x:Key="Text.Filter" xml:space="preserve">FILTRO</x:String>
<x:String x:Key="Text.GitFlow" xml:space="preserve">Git-Flow</x:String>
<x:String x:Key="Text.GitFlow.DevelopBranch" xml:space="preserve">Rama de Desarrollo:</x:String>
<x:String x:Key="Text.GitFlow.Feature" xml:space="preserve">Feature:</x:String>
<x:String x:Key="Text.GitFlow.FeaturePrefix" xml:space="preserve">Prefijo de Feature:</x:String>
<x:String x:Key="Text.GitFlow.FinishFeature" xml:space="preserve">FLOW - Finalizar Feature</x:String>
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finalizar Hotfix</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finalizar Release</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Destino:</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Prefijo de Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Inicializar Git-Flow</x:String>
<x:String x:Key="Text.GitFlow.KeepBranchAfterFinish" xml:space="preserve">Mantener rama</x:String>
<x:String x:Key="Text.GitFlow.ProductionBranch" xml:space="preserve">Rama de Producción:</x:String>
<x:String x:Key="Text.GitFlow.Release" xml:space="preserve">Release:</x:String>
<x:String x:Key="Text.GitFlow.ReleasePrefix" xml:space="preserve">Prefijo de Release:</x:String>
<x:String x:Key="Text.GitFlow.StartFeature" xml:space="preserve">Iniciar Feature...</x:String>
<x:String x:Key="Text.GitFlow.StartFeatureTitle" xml:space="preserve">FLOW - Iniciar Feature</x:String>
<x:String x:Key="Text.GitFlow.StartHotfix" xml:space="preserve">Iniciar Hotfix...</x:String>
<x:String x:Key="Text.GitFlow.StartHotfixTitle" xml:space="preserve">FLOW - Iniciar Hotfix</x:String>
<x:String x:Key="Text.GitFlow.StartPlaceholder" xml:space="preserve">Introducir nombre</x:String>
<x:String x:Key="Text.GitFlow.StartRelease" xml:space="preserve">Iniciar Release...</x:String>
<x:String x:Key="Text.GitFlow.StartReleaseTitle" xml:space="preserve">FLOW - Iniciar Release</x:String>
<x:String x:Key="Text.GitFlow.TagPrefix" xml:space="preserve">Prefijo de Etiqueta de Versión:</x:String>
<x:String x:Key="Text.GitLFS" xml:space="preserve">Git LFS</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern" xml:space="preserve">Añadir Patrón de Seguimiento...</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.IsFilename" xml:space="preserve">El patrón es el nombre del archivo</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Pattern" xml:space="preserve">Patrón Personalizado:</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Title" xml:space="preserve">Añadir Patrón de Seguimiento a Git LFS</x:String>
<x:String x:Key="Text.GitLFS.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Title" xml:space="preserve">Fetch Objetos LFS</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Tips" xml:space="preserve">Ejecuta `git lfs fetch` para descargar objetos Git LFS. Esto no actualiza la copia de trabajo.</x:String>
<x:String x:Key="Text.GitLFS.Install" xml:space="preserve">Instalar hooks de Git LFS</x:String>
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">Mostrar Bloqueos</x:String>
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">No hay archivos bloqueados</x:String>
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">Bloquear</x:String>
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">Mostrar solo mis bloqueos</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">Bloqueos LFS</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Desbloquear</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Forzar Desbloqueo</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">Prune</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">Ejecuta `git lfs prune` para eliminar archivos LFS antiguos del almacenamiento local</x:String>
<x:String x:Key="Text.GitLFS.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.GitLFS.Pull.Title" xml:space="preserve">Pull Objetos LFS</x:String>
<x:String x:Key="Text.GitLFS.Pull.Tips" xml:space="preserve">Ejecuta `git lfs pull` para descargar todos los archivos Git LFS para la referencia actual y hacer checkout</x:String>
<x:String x:Key="Text.GitLFS.Push" xml:space="preserve">Push</x:String>
<x:String x:Key="Text.GitLFS.Push.Title" xml:space="preserve">Push Objetos LFS</x:String>
<x:String x:Key="Text.GitLFS.Push.Tips" xml:space="preserve">Push archivos grandes en cola al endpoint de Git LFS</x:String>
<x:String x:Key="Text.GitLFS.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.GitLFS.Track" xml:space="preserve">Seguir archivos llamados '{0}'</x:String>
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">Seguir todos los archivos *{0}</x:String>
<x:String x:Key="Text.Histories" xml:space="preserve">Historias</x:String>
<x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">Cambiar a Disposición Horizontal/Vertical</x:String>
<x:String x:Key="Text.Histories.Header.Author" xml:space="preserve">AUTOR</x:String>
<x:String x:Key="Text.Histories.Header.AuthorTime" xml:space="preserve">HORA DEL AUTOR</x:String>
<x:String x:Key="Text.Histories.Header.GraphAndSubject" xml:space="preserve">GRÁFICO &amp; ASUNTO</x:String>
<x:String x:Key="Text.Histories.Header.SHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.Histories.Header.Time" xml:space="preserve">FECHA DE COMMIT</x:String>
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">{0} COMMITS SELECCIONADOS</x:String>
<x:String x:Key="Text.Histories.Tips" xml:space="preserve">Mantén 'Ctrl' o 'Shift' para seleccionar múltiples commits.</x:String>
<x:String x:Key="Text.Histories.Tips.MacOS" xml:space="preserve">Mantén ⌘ o ⇧ para seleccionar múltiples commits.</x:String>
<x:String x:Key="Text.Histories.Tips.Prefix" xml:space="preserve">CONSEJOS:</x:String>
<x:String x:Key="Text.Hotkeys" xml:space="preserve">Referencia de Atajos de Teclado</x:String>
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">GLOBAL</x:String>
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">Cancelar popup actual</x:String>
<x:String x:Key="Text.Hotkeys.Global.CloseTab" xml:space="preserve">Cerrar página actual</x:String>
<x:String x:Key="Text.Hotkeys.Global.GotoPrevTab" xml:space="preserve">Ir a la página anterior</x:String>
<x:String x:Key="Text.Hotkeys.Global.GotoNextTab" xml:space="preserve">Ir a la siguiente página</x:String>
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Crear nueva página</x:String>
<x:String x:Key="Text.Hotkeys.Global.OpenPreference" xml:space="preserve">Abrir diálogo de preferencias</x:String>
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">REPOSITORIO</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Commit cambios staged</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Commit y push cambios staged</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">Stage todos los cambios y commit</x:String>
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">Descartar cambios seleccionados</x:String>
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">Modo Dashboard (Por Defecto)</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">Forzar a recargar este repositorio</x:String>
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">Stage/Unstage cambios seleccionados</x:String>
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">Modo de búsqueda de commits</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewChanges" xml:space="preserve">Cambiar a 'Cambios'</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewHistories" xml:space="preserve">Cambiar a 'Historias'</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewStashes" xml:space="preserve">Cambiar a 'Stashes'</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor" xml:space="preserve">EDITOR DE TEXTO</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.CloseSearch" xml:space="preserve">Cerrar panel de búsqueda</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.GotoNextMatch" xml:space="preserve">Buscar siguiente coincidencia</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.GotoPrevMatch" xml:space="preserve">Buscar coincidencia anterior</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.Search" xml:space="preserve">Abrir panel de búsqueda</x:String>
<x:String x:Key="Text.Hunk.Stage" xml:space="preserve">Stage</x:String>
<x:String x:Key="Text.Hunk.Unstage" xml:space="preserve">Unstage</x:String>
<x:String x:Key="Text.Hunk.Discard" xml:space="preserve">Descartar</x:String>
<x:String x:Key="Text.Init" xml:space="preserve">Inicializar Repositorio</x:String>
<x:String x:Key="Text.Init.Path" xml:space="preserve">Ruta:</x:String>
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Cherry-Pick en progreso. Presiona 'Abort' para restaurar el HEAD original.</x:String>
<x:String x:Key="Text.InProgress.Merge" xml:space="preserve">Merge en progreso. Presiona 'Abort' para restaurar el HEAD original.</x:String>
<x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">Rebase en progreso. Presiona 'Abort' para restaurar el HEAD original.</x:String>
<x:String x:Key="Text.InProgress.Revert" xml:space="preserve">Revert en progreso. Presiona 'Abort' para restaurar el HEAD original.</x:String>
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Rebase Interactivo</x:String>
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">Rama Objetivo:</x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">En:</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">AVISO</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Rama</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">En:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Opción de Merge:</x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">Rama Fuente:</x:String>
<x:String x:Key="Text.MoveRepositoryNode" xml:space="preserve">Mover Nodo del Repositorio</x:String>
<x:String x:Key="Text.MoveRepositoryNode.Target" xml:space="preserve">Seleccionar nodo padre para:</x:String>
<x:String x:Key="Text.Name" xml:space="preserve">Nombre:</x:String>
<x:String x:Key="Text.NotConfigured" xml:space="preserve">Git NO ha sido configurado. Por favor, ve a [Preferencias] y configúralo primero.</x:String>
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">Abrir Directorio de Datos de la App</x:String>
<x:String x:Key="Text.OpenWith" xml:space="preserve">Abrir Con...</x:String>
<x:String x:Key="Text.Optional" xml:space="preserve">Opcional.</x:String>
<x:String x:Key="Text.PageTabBar.New" xml:space="preserve">Crear Nueva Página</x:String>
<x:String x:Key="Text.PageTabBar.Tab.Bookmark" xml:space="preserve">Marcador</x:String>
<x:String x:Key="Text.PageTabBar.Tab.Close" xml:space="preserve">Cerrar Pestaña</x:String>
<x:String x:Key="Text.PageTabBar.Tab.CloseOther" xml:space="preserve">Cerrar Otras Pestañas</x:String>
<x:String x:Key="Text.PageTabBar.Tab.CloseRight" xml:space="preserve">Cerrar Pestañas a la Derecha</x:String>
<x:String x:Key="Text.PageTabBar.Tab.CopyPath" xml:space="preserve">Copiar Ruta del Repositorio</x:String>
<x:String x:Key="Text.PageTabBar.Welcome.Title" xml:space="preserve">Repositorios</x:String>
<x:String x:Key="Text.Paste" xml:space="preserve">Pegar</x:String>
<x:String x:Key="Text.Period.JustNow" xml:space="preserve">Justo ahora</x:String>
<x:String x:Key="Text.Period.MinutesAgo" xml:space="preserve">Hace {0} minutos</x:String>
<x:String x:Key="Text.Period.HoursAgo" xml:space="preserve">Hace {0} horas</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Ayer</x:String>
<x:String x:Key="Text.Period.DaysAgo" xml:space="preserve">Hace {0} días</x:String>
<x:String x:Key="Text.Period.LastMonth" xml:space="preserve">Último mes</x:String>
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">Hace {0} meses</x:String>
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">Último año</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">Hace {0} años</x:String>
<x:String x:Key="Text.Preference" xml:space="preserve">Preferencias</x:String>
<x:String x:Key="Text.Preference.Advanced" xml:space="preserve">Opciones Avanzadas</x:String>
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OPEN AI</x:String>
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analizar Diff Prompt</x:String>
<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.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>
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">Tamaño de fuente por defecto</x:String>
<x:String x:Key="Text.Preference.Appearance.MonospaceFont" xml:space="preserve">Fuente Monospace</x:String>
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">Usar solo fuente monospace en el editor de texto</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">Tema</x:String>
<x:String x:Key="Text.Preference.Appearance.ThemeOverrides" xml:space="preserve">Sobreescritura de temas</x:String>
<x:String x:Key="Text.Preference.Appearance.UseFixedTabWidth" xml:space="preserve">Usar ancho de pestaña fijo en la barra de título</x:String>
<x:String x:Key="Text.Preference.Appearance.UseNativeWindowFrame" xml:space="preserve">Usar marco de ventana nativo</x:String>
<x:String x:Key="Text.Preference.DiffMerge" xml:space="preserve">HERRAMIENTA DIFF/MERGE</x:String>
<x:String x:Key="Text.Preference.DiffMerge.Path" xml:space="preserve">Ruta de instalación</x:String>
<x:String x:Key="Text.Preference.DiffMerge.Path.Placeholder" xml:space="preserve">Introducir ruta para la herramienta diff/merge</x:String>
<x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">Herramienta</x:String>
<x:String x:Key="Text.Preference.General" xml:space="preserve">GENERAL</x:String>
<x:String x:Key="Text.Preference.General.Check4UpdatesOnStartup" xml:space="preserve">Buscar actualizaciones al iniciar</x:String>
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Idioma</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">Commits en el historial</x:String>
<x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">Mostrar hora del autor en lugar de la hora del commit en el gráfico</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Longitud de la guía del asunto</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Habilitar Auto CRLF</x:String>
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Directorio de clonado por defecto</x:String>
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">Email de usuario</x:String>
<x:String x:Key="Text.Preference.Git.Email.Placeholder" xml:space="preserve">Email global del usuario git</x:String>
<x:String x:Key="Text.Preference.Git.Path" xml:space="preserve">Ruta de instalación</x:String>
<x:String x:Key="Text.Preference.Git.User" xml:space="preserve">Nombre de usuario</x:String>
<x:String x:Key="Text.Preference.Git.User.Placeholder" xml:space="preserve">Nombre global del usuario git</x:String>
<x:String x:Key="Text.Preference.Git.Version" xml:space="preserve">Versión de Git</x:String>
<x:String x:Key="Text.Preference.Git.Invalid" xml:space="preserve">Se requiere Git (>= 2.23.0) para esta aplicación</x:String>
<x:String x:Key="Text.Preference.GPG" xml:space="preserve">FIRMA GPG</x:String>
<x:String x:Key="Text.Preference.GPG.CommitEnabled" xml:space="preserve">Firma GPG en commit</x:String>
<x:String x:Key="Text.Preference.GPG.TagEnabled" xml:space="preserve">Firma GPG en etiqueta</x:String>
<x:String x:Key="Text.Preference.GPG.Format" xml:space="preserve">Formato GPG</x:String>
<x:String x:Key="Text.Preference.GPG.Path" xml:space="preserve">Ruta de instalación del programa</x:String>
<x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">Introducir ruta para el programa gpg instalado</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">Clave de firma del usuario</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">Clave de firma gpg del usuario</x:String>
<x:String x:Key="Text.Preference.Integration" xml:space="preserve">INTEGRACIÓN</x:String>
<x:String x:Key="Text.Preference.Shell" xml:space="preserve">SHELL/TERMINAL</x:String>
<x:String x:Key="Text.Preference.Shell.Type" xml:space="preserve">Shell/Terminal</x:String>
<x:String x:Key="Text.Preference.Shell.Path" xml:space="preserve">Ruta</x:String>
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Podar Remoto</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Destino:</x:String>
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Podar Worktrees</x:String>
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Podar información de worktree en `$GIT_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch todas las ramas</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">En:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Cambios Locales:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Descartar</x:String>
<x:String x:Key="Text.Pull.LocalChanges.DoNothing" xml:space="preserve">No Hacer Nada</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reaplicar</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Fetch sin etiquetas</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Usar rebase en lugar de merge</x:String>
<x:String x:Key="Text.Push" xml:space="preserve">Push</x:String>
<x:String x:Key="Text.Push.CheckSubmodules" xml:space="preserve">Asegurarse de que los submódulos se hayan hecho push</x:String>
<x:String x:Key="Text.Push.Force" xml:space="preserve">Forzar push</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">Rama Local:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.Push.Title" xml:space="preserve">Push Cambios al Remoto</x:String>
<x:String x:Key="Text.Push.To" xml:space="preserve">Rama Remota:</x:String>
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Establecer como rama de seguimiento</x:String>
<x:String x:Key="Text.Push.WithAllTags" xml:space="preserve">Push todas las etiquetas</x:String>
<x:String x:Key="Text.PushTag" xml:space="preserve">Push Etiqueta al Remoto</x:String>
<x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">Push a todos los remotos</x:String>
<x:String x:Key="Text.PushTag.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.PushTag.Tag" xml:space="preserve">Etiqueta:</x:String>
<x:String x:Key="Text.Quit" xml:space="preserve">Salir</x:String>
<x:String x:Key="Text.Rebase" xml:space="preserve">Rebase Rama Actual</x:String>
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reaplicar cambios locales</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">En:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Refrescar</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Añadir Remoto</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nombre:</x:String>
<x:String x:Key="Text.Remote.Name.Placeholder" xml:space="preserve">Nombre remoto</x:String>
<x:String x:Key="Text.Remote.URL" xml:space="preserve">URL del Repositorio:</x:String>
<x:String x:Key="Text.Remote.URL.Placeholder" xml:space="preserve">URL del repositorio git remoto</x:String>
<x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">Copiar URL</x:String>
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">Borrar...</x:String>
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">Editar...</x:String>
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">Abrir En Navegador</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Podar (Prune)</x:String>
<x:String x:Key="Text.RemoveWorktree" xml:space="preserve">Confirmar para Eliminar Worktree</x:String>
<x:String x:Key="Text.RemoveWorktree.Force" xml:space="preserve">Utilizar Opción `--force`</x:String>
<x:String x:Key="Text.RemoveWorktree.Target" xml:space="preserve">Destino:</x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">Renombrar Rama</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">Nuevo Nombre:</x:String>
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Nombre único para esta rama</x:String>
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORTAR</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Auto fetching cambios desde remotos...</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Limpiar (GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Ejecutar comando `git gc` para este repositorio.</x:String>
<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.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>
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">FILTRAR POR:</x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">RAMAS LOCALES</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navegar a HEAD</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Habilitar Opción '--first-parent'</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Crear Rama</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Abrir en {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Abrir en Herramientas Externas</x:String>
<x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Refrescar</x:String>
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTOS</x:String>
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">AÑADIR REMOTO</x:String>
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">RESOLVER</x:String>
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Buscar Commit</x:String>
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">Archivo</x:String>
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Mensaje</x:String>
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.Repository.Search.ByUser" xml:space="preserve">Autor &amp; Committer</x:String>
<x:String x:Key="Text.Repository.Search.InCurrentBranch" xml:space="preserve">Rama Actual</x:String>
<x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">Mostrar Etiquetas como Árbol</x:String>
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Estadísticas</x:String>
<x:String x:Key="Text.Repository.Submodules" xml:space="preserve">SUBMÓDULOS</x:String>
<x:String x:Key="Text.Repository.Submodules.Add" xml:space="preserve">AÑADIR SUBMÓDULO</x:String>
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">ACTUALIZAR SUBMÓDULO</x:String>
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">ETIQUETAS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUEVA ETIQUETA</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Abrir en 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">AÑADIR WORKTREE</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>
<x:String x:Key="Text.RepositoryURL" xml:space="preserve">URL del Repositorio Git</x:String>
<x:String x:Key="Text.Reset" xml:space="preserve">Resetear Rama Actual a Revisión</x:String>
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Modo de Reset:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Mover a:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Rama Actual:</x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">Revelar en el Explorador de Archivos</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">Revertir Commit</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit revertir cambios</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Reescribir Mensaje de Commit</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Usa 'Shift+Enter' para introducir una nueva línea. 'Enter' es el atajo del botón OK</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Ejecutando. Por favor espera...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">GUARDAR</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Guardar Como...</x:String>
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">¡El patch se ha guardado exitosamente!</x:String>
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">Escanear Repositorios</x:String>
<x:String x:Key="Text.ScanRepositories.RootDir" xml:space="preserve">Directorio Raíz:</x:String>
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">Buscar Actualizaciones...</x:String>
<x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">Nueva versión de este software disponible: </x:String>
<x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">¡Error al buscar actualizaciones!</x:String>
<x:String x:Key="Text.SelfUpdate.GotoDownload" xml:space="preserve">Descargar</x:String>
<x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Omitir Esta Versión</x:String>
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Actualización de Software</x:String>
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">Actualmente no hay actualizaciones disponibles.</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Squash Commits</x:String>
<x:String x:Key="Text.Squash.Into" xml:space="preserve">En:</x:String>
<x:String x:Key="Text.SSHKey" xml:space="preserve">Clave Privada SSH:</x:String>
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Ruta de almacenamiento de la clave privada SSH</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">INICIAR</x:String>
<x:String x:Key="Text.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.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>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">¡Tanto los cambios staged como los no staged de los archivos seleccionados serán stashed!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Cambios Locales</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Aplicar</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Eliminar</x:String>
<x:String x:Key="Text.StashCM.Pop" xml:space="preserve">Pop</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Eliminar Stash</x:String>
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Eliminar:</x:String>
<x:String x:Key="Text.Stashes" xml:space="preserve">Stashes</x:String>
<x:String x:Key="Text.Stashes.Changes" xml:space="preserve">CAMBIOS</x:String>
<x:String x:Key="Text.Stashes.Stashes" xml:space="preserve">STASHES</x:String>
<x:String x:Key="Text.Statistics" xml:space="preserve">Estadísticas</x:String>
<x:String x:Key="Text.Statistics.CommitAmount" xml:space="preserve">COMMITS</x:String>
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">COMMITTER</x:String>
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">MES</x:String>
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">SEMANA</x:String>
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">COMMITS: </x:String>
<x:String x:Key="Text.Statistics.TotalAuthors" xml:space="preserve">AUTORES: </x:String>
<x:String x:Key="Text.Statistics.Overview" xml:space="preserve">GENERAL</x:String>
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMÓDULOS</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Añadir Submódulo</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Copiar Ruta Relativa</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Fetch submódulos anidados</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Abrir Repositorio del Submódulo</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Ruta Relativa:</x:String>
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Carpeta relativa para almacenar este módulo.</x:String>
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Eliminar Submódulo</x:String>
<x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String>
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">Copiar Nombre de la Etiqueta</x:String>
<x:String x:Key="Text.TagCM.CopyMessage" xml:space="preserve">Copiar Mensaje de la Etiqueta</x:String>
<x:String x:Key="Text.TagCM.Delete" xml:space="preserve">Eliminar ${0}$...</x:String>
<x:String x:Key="Text.TagCM.Push" xml:space="preserve">Push ${0}$...</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">URL:</x:String>
<x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">Actualizar Submódulos</x:String>
<x:String x:Key="Text.UpdateSubmodules.All" xml:space="preserve">Todos los submódulos</x:String>
<x:String x:Key="Text.UpdateSubmodules.Init" xml:space="preserve">Inicializar según sea necesario</x:String>
<x:String x:Key="Text.UpdateSubmodules.Recursive" xml:space="preserve">Recursivamente</x:String>
<x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Submódulo:</x:String>
<x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Usar opción --remote</x:String>
<x:String x:Key="Text.Warn" xml:space="preserve">Advertencia</x:String>
<x:String x:Key="Text.Welcome" xml:space="preserve">Página de Bienvenida</x:String>
<x:String x:Key="Text.Welcome.AddRootFolder" xml:space="preserve">Crear Grupo</x:String>
<x:String x:Key="Text.Welcome.AddSubFolder" xml:space="preserve">Crear Sub-Grupo</x:String>
<x:String x:Key="Text.Welcome.Clone" xml:space="preserve">Clonar Repositorio</x:String>
<x:String x:Key="Text.Welcome.Delete" xml:space="preserve">Eliminar</x:String>
<x:String x:Key="Text.Welcome.DragDropTip" xml:space="preserve">SOPORTA ARRASTRAR Y SOLTAR CARPETAS. SOPORTA AGRUPACIÓN PERSONALIZADA.</x:String>
<x:String x:Key="Text.Welcome.Edit" xml:space="preserve">Editar</x:String>
<x:String x:Key="Text.Welcome.Move" xml:space="preserve">Mover a Otro Grupo</x:String>
<x:String x:Key="Text.Welcome.OpenAllInNode" xml:space="preserve">Abrir Todos Los Repositorios</x:String>
<x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">Abrir Repositorio</x:String>
<x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">Abrir Terminal</x:String>
<x:String x:Key="Text.Welcome.ScanDefaultCloneDir" xml:space="preserve">Reescanear Repositorios en el Directorio de Clonado por Defecto</x:String>
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">Buscar Repositorios...</x:String>
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">Ordenar</x:String>
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">Cambios</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignorar todos los archivos *{0}</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignorar archivos *{0} en la misma carpeta</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignorar archivos en la misma carpeta</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignorar solo este archivo</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Enmendar (Amend)</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Puedes stagear este archivo ahora.</x:String>
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT &amp; PUSH</x:String>
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Plantilla/Historias</x:String>
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">Activar evento de clic</x:String>
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Stagear todos los cambios y commit</x:String>
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithoutFiles" xml:space="preserve">¡Commit vacío detectado! ¿Quieres continuar (--allow-empty)?</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLICTOS DETECTADOS</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">LOS CONFLICTOS DE ARCHIVOS ESTÁN RESUELTOS</x:String>
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUIR ARCHIVOS NO RASTREADOS</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">NO HAY MENSAJES DE ENTRADA RECIENTES</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">NO HAY PLANTILLAS DE COMMIT</x:String>
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">STAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Staged.Unstage" xml:space="preserve">UNSTAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Staged.UnstageAll" xml:space="preserve">UNSTAGE TODO</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODO</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VER ASSUME UNCHANGED</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Plantilla: ${0}$</x:String>
<x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Haz clic derecho en el(los) archivo(s) seleccionado(s) y elige tu opción para resolver conflictos.</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">ESPACIO DE TRABAJO: </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Espacios de Trabajo...</x:String>
<x:String x:Key="Text.Worktree" xml:space="preserve">WORKTREE</x:String>
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Copiar Ruta</x:String>
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">Bloquear</x:String>
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">Eliminar</x:String>
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">Desbloquear</x:String>
</ResourceDictionary>

View file

@ -16,7 +16,7 @@
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Существующую ветку</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Существующую ветку</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Создать новую ветку</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Создать новую ветку</x:String>
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Расположение:</x:String> <x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Расположение:</x:String>
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Путь к этому рабочему дереву. Поддерживается относительный путью</x:String> <x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Путь к этому рабочему дереву. Поддерживается относительный путь.</x:String>
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">Имя ветки:</x:String> <x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">Имя ветки:</x:String>
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Необязательно. По умолчанию используется имя целевой папки.</x:String> <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" xml:space="preserve">Отслеживание ветки:</x:String>
@ -27,7 +27,7 @@
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Ошибка</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> <x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Выдает ошибки и отказывается применять исправление</x:String>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Все ошибки</x:String> <x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Все ошибки</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Аналогично "ошибке", но показывает больше</x:String> <x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Аналогично «ошибке», но показывает больше</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">Файл исправлений:</x:String> <x:String x:Key="Text.Apply.File" xml:space="preserve">Файл исправлений:</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Выберите файл .patch для применения</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Выберите файл .patch для применения</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Игнорировать изменения пробелов</x:String> <x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Игнорировать изменения пробелов</x:String>
@ -58,6 +58,7 @@
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Удалить выбранные {0} ветки</x:String> <x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Удалить выбранные {0} ветки</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Отклонить все изменения.</x:String> <x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Отклонить все изменения.</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Перемотать вперёд к ${0}$</x:String> <x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Перемотать вперёд к ${0}$</x:String>
<x:String x:Key="Text.BranchCM.FetchInto" xml:space="preserve">Извлечь ${0}$ в ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Поток Git - Завершение ${0}$</x:String> <x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Поток Git - Завершение ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Слить ${0}$ в ${1}$...</x:String> <x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Слить ${0}$ в ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Забрать ${0}$</x:String> <x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Забрать ${0}$</x:String>
@ -72,6 +73,7 @@
<x:String x:Key="Text.Cancel" xml:space="preserve">ОТМЕНА</x:String> <x:String x:Key="Text.Cancel" xml:space="preserve">ОТМЕНА</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Сбросить эту ревизию</x:String> <x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Сбросить эту ревизию</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Сбросить родительскую ревизию</x:String> <x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Сбросить родительскую ревизию</x:String>
<x:String x:Key="Text.ChangeCM.GenerateCommitMessage" xml:space="preserve">Произвести сообщение о фиксации</x:String>
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">ИЗМЕНИТЬ РЕЖИМ ОТОБРАЖЕНИЯ</x:String> <x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">ИЗМЕНИТЬ РЕЖИМ ОТОБРАЖЕНИЯ</x:String>
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Показывать в виде списка файлов и каталогов</x:String> <x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Показывать в виде списка файлов и каталогов</x:String>
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Показывать в виде списка путей</x:String> <x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Показывать в виде списка путей</x:String>
@ -109,14 +111,15 @@
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим деревом</x:String> <x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим деревом</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Копировать информацию</x:String> <x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Копировать информацию</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Копировать SHA</x:String> <x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Копировать SHA</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Пользовательское действие</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Интерактивное перемещение ${0}$ сюда</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Интерактивное перемещение ${0}$ сюда</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Переместить ${0}$ сюда</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Переместить ${0}$ сюда</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Сбросить ${0}$ сюда</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Сбросить ${0}$ сюда</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Вернуть фиксацию</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Вернуть фиксацию</x:String>
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Переформулировать</x:String> <x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Переформулировать</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Сохранить как исправление...</x:String> <x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Сохранить как исправление...</x:String>
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Уплотнить в родительскую</x:String> <x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Втиснуть в родительскую</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Уплотнить дочерную фиксацию сюда</x:String> <x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Втиснуть дочерную фиксацию сюда</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">ИЗМЕНЕНИЯ</x:String> <x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">ИЗМЕНЕНИЯ</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Найти изменения....</x:String> <x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Найти изменения....</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">ФАЙЛЫ</x:String> <x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">ФАЙЛЫ</x:String>
@ -140,13 +143,22 @@
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">ШАБЛОН ФИКСАЦИИ</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">ШАБЛОН ФИКСАЦИИ</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Имя шаблона:</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Имя шаблона:</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Шаблон содержания:</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Шаблон содержания:</x:String>
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">ПОЛЬЗОВАТЕЛЬСКОЕ ДЕЙСТВИЕ</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">Аргументы:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">${REPO} - Путь хранилища; ${SHA} - Выбранные фиксации SHA</x:String>
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Исполняемый фалй:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Имя:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Диапазон:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Фиксация</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Хранилище</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Адрес электронной почты</x:String> <x:String x:Key="Text.Configure.Email" xml:space="preserve">Адрес электронной почты</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Адрес электронной почты</x:String> <x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Адрес электронной почты</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String> <x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Автоматическое извлечение внешних хранилищ</x:String> <x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Автоматическое извлечение внешних хранилищ</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Минут(а/ы)</x:String> <x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Минут(а/ы)</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Удалённое хранилище по-умолчанию</x:String>
<x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">Разрешить --signoff для фиксации</x:String> <x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">Разрешить --signoff для фиксации</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Удалённое хранилище по-умолчанию</x:String>
<x:String x:Key="Text.Configure.Git.EnablePruneOnFetch" xml:space="preserve">Разрешить --prune при извлечении</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ОТСЛЕЖИВАНИЕ ПРОБЛЕМ</x:String> <x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ОТСЛЕЖИВАНИЕ ПРОБЛЕМ</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Добавить пример правила для Git</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Добавить пример правила для Git</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Добавить пример правила Jira</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Добавить пример правила Jira</x:String>
@ -157,9 +169,12 @@
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Имя правила:</x:String> <x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Имя правила:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">Адрес результата:</x:String> <x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">Адрес результата:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Пожалуйста, используйте $1, $2 для доступа к значениям групп регулярных выражений.</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">ОТКРЫТЬ ИИ</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 будет использовать только этот хранилище. В противном случае, если доступно более одной услуги, будет отображено контекстное меню для выбора одной из них.</x:String>
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP-прокси</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.Proxy.Placeholder" xml:space="preserve">HTTP-прокси, используемый этим хранилищем</x:String>
<x:String x:Key="Text.Configure.User" xml:space="preserve">Имя пользовтаеля</x:String> <x:String x:Key="Text.Configure.User" xml:space="preserve">Имя пользователя</x:String>
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">Имя пользователя для этого хранилища</x:String> <x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">Имя пользователя для этого хранилища</x:String>
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">Рабочие пространства</x:String> <x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">Рабочие пространства</x:String>
<x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">Имя</x:String> <x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">Имя</x:String>
@ -250,6 +265,8 @@
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Цель:</x:String> <x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Цель:</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Редактировать выбранную группу</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Редактировать выбранную группу</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Редактировать выбранное хранилище</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Редактировать выбранное хранилище</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Выполнить пользовательское действие</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Имя действия:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Быстрая перемотка вперёд (без проверки)</x:String> <x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Быстрая перемотка вперёд (без проверки)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Извлечь</x:String> <x:String x:Key="Text.Fetch" xml:space="preserve">Извлечь</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Извлечь все внешние хранилища</x:String> <x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Извлечь все внешние хранилища</x:String>
@ -306,7 +323,7 @@
<x:String x:Key="Text.GitLFS.AddTrackPattern.Title" xml:space="preserve">Добавить шаблон отслеживания в ХБФ Git</x:String> <x:String x:Key="Text.GitLFS.AddTrackPattern.Title" xml:space="preserve">Добавить шаблон отслеживания в ХБФ Git</x:String>
<x:String x:Key="Text.GitLFS.Fetch" xml:space="preserve">Извлечь</x:String> <x:String x:Key="Text.GitLFS.Fetch" xml:space="preserve">Извлечь</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Title" xml:space="preserve">Извлечь объекты ХБФ</x:String> <x:String x:Key="Text.GitLFS.Fetch.Title" xml:space="preserve">Извлечь объекты ХБФ</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Tips" xml:space="preserve">Запустить `git lfs fetch", чтобы загрузить объекты ХБФ Git. При этом рабочая копия не обновляется.</x:String> <x:String x:Key="Text.GitLFS.Fetch.Tips" xml:space="preserve">Запустить «git lfs fetch», чтобы загрузить объекты ХБФ Git. При этом рабочая копия не обновляется.</x:String>
<x:String x:Key="Text.GitLFS.Install" xml:space="preserve">Установить перехват ХБФ Git</x:String> <x:String x:Key="Text.GitLFS.Install" xml:space="preserve">Установить перехват ХБФ Git</x:String>
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">Показывать блокировки</x:String> <x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">Показывать блокировки</x:String>
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">Нет заблокированных файлов</x:String> <x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">Нет заблокированных файлов</x:String>
@ -316,15 +333,15 @@
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Разблокировать</x:String> <x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Разблокировать</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Принудительно разблокировать</x:String> <x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Принудительно разблокировать</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">Обрезать</x:String> <x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">Обрезать</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">Запустите `git lfs prune", чтобы удалить старые файлы ХБФ из локального хранилища</x:String> <x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">Запустить «git lfs prune», чтобы удалить старые файлы ХБФ из локального хранилища</x:String>
<x:String x:Key="Text.GitLFS.Pull" xml:space="preserve">Забрать</x:String> <x:String x:Key="Text.GitLFS.Pull" xml:space="preserve">Забрать</x:String>
<x:String x:Key="Text.GitLFS.Pull.Title" xml:space="preserve">Забрать объекты ХБФ</x:String> <x:String x:Key="Text.GitLFS.Pull.Title" xml:space="preserve">Забрать объекты ХБФ</x:String>
<x:String x:Key="Text.GitLFS.Pull.Tips" xml:space="preserve">Запустите `git lfs pull", чтобы загрузить все файлы ХБФ Git для текущей ссылки и проверить</x:String> <x:String x:Key="Text.GitLFS.Pull.Tips" xml:space="preserve">Запустить «git lfs pull», чтобы загрузить все файлы ХБФ Git для текущей ссылки и проверить</x:String>
<x:String x:Key="Text.GitLFS.Push" xml:space="preserve">Выложить</x:String> <x:String x:Key="Text.GitLFS.Push" xml:space="preserve">Выложить</x:String>
<x:String x:Key="Text.GitLFS.Push.Title" xml:space="preserve">Выложить объекты ХБФ</x:String> <x:String x:Key="Text.GitLFS.Push.Title" xml:space="preserve">Выложить объекты ХБФ</x:String>
<x:String x:Key="Text.GitLFS.Push.Tips" xml:space="preserve">Отправляйте большие файлы, помещенные в очередь, в конечную точку ХБФ Git</x:String> <x:String x:Key="Text.GitLFS.Push.Tips" xml:space="preserve">Отправляйте большие файлы, помещенные в очередь, в конечную точку ХБФ Git</x:String>
<x:String x:Key="Text.GitLFS.Remote" xml:space="preserve">Внешнее хранилище:</x:String> <x:String x:Key="Text.GitLFS.Remote" xml:space="preserve">Внешнее хранилище:</x:String>
<x:String x:Key="Text.GitLFS.Track" xml:space="preserve">Отслеживать файлы с именем '{0}'</x:String> <x:String x:Key="Text.GitLFS.Track" xml:space="preserve">Отслеживать файлы с именем «{0}»</x:String>
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">Отслеживать все *{0} файлов</x:String> <x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">Отслеживать все *{0} файлов</x:String>
<x:String x:Key="Text.Histories" xml:space="preserve">Истории</x:String> <x:String x:Key="Text.Histories" xml:space="preserve">Истории</x:String>
<x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">Переключение горизонтального/вертикального расположения</x:String> <x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">Переключение горизонтального/вертикального расположения</x:String>
@ -334,7 +351,7 @@
<x:String x:Key="Text.Histories.Header.SHA" xml:space="preserve">SHA</x:String> <x:String x:Key="Text.Histories.Header.SHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.Histories.Header.Time" xml:space="preserve">ВРЕМЯ ФИКСАЦИИ</x:String> <x:String x:Key="Text.Histories.Header.Time" xml:space="preserve">ВРЕМЯ ФИКСАЦИИ</x:String>
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">ВЫБРАННЫЕ {0} ФИКСАЦИИ</x:String> <x:String x:Key="Text.Histories.Selected" xml:space="preserve">ВЫБРАННЫЕ {0} ФИКСАЦИИ</x:String>
<x:String x:Key="Text.Histories.Tips" xml:space="preserve">Удерживайте 'Ctrl' или 'Shift', чтобы выбрать несколько фиксаций.</x:String> <x:String x:Key="Text.Histories.Tips" xml:space="preserve">Удерживайте Ctrl или Shift, чтобы выбрать несколько фиксаций.</x:String>
<x:String x:Key="Text.Histories.Tips.MacOS" xml:space="preserve">Удерживайте ⌘ или ⇧, чтобы выбрать несколько фиксаций.</x:String> <x:String x:Key="Text.Histories.Tips.MacOS" xml:space="preserve">Удерживайте ⌘ или ⇧, чтобы выбрать несколько фиксаций.</x:String>
<x:String x:Key="Text.Histories.Tips.Prefix" xml:space="preserve">ПОДСКАЗКИ:</x:String> <x:String x:Key="Text.Histories.Tips.Prefix" xml:space="preserve">ПОДСКАЗКИ:</x:String>
<x:String x:Key="Text.Hotkeys" xml:space="preserve">Ссылка на сочетания клавиш</x:String> <x:String x:Key="Text.Hotkeys" xml:space="preserve">Ссылка на сочетания клавиш</x:String>
@ -354,9 +371,9 @@
<x:String x:Key="Text.Hotkeys.Repo.Refresh" 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.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.OpenSearchCommits" xml:space="preserve">Режим поиска фиксаций</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewChanges" xml:space="preserve">Переключить на 'Изменения'</x:String> <x:String x:Key="Text.Hotkeys.Repo.ViewChanges" xml:space="preserve">Переключить на «Изменения»</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewHistories" xml:space="preserve">Переключить на 'Истории'</x:String> <x:String x:Key="Text.Hotkeys.Repo.ViewHistories" xml:space="preserve">Переключить на «Истории»</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewStashes" xml:space="preserve">Переключить на 'Отложенные'</x:String> <x:String x:Key="Text.Hotkeys.Repo.ViewStashes" xml:space="preserve">Переключить на «Отложенные»</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor" xml:space="preserve">ТЕКСТОВЫЙ РЕДАКТОР</x:String> <x:String x:Key="Text.Hotkeys.TextEditor" xml:space="preserve">ТЕКСТОВЫЙ РЕДАКТОР</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.CloseSearch" xml:space="preserve">Закрыть панель поиска</x:String> <x:String x:Key="Text.Hotkeys.TextEditor.CloseSearch" xml:space="preserve">Закрыть панель поиска</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.GotoNextMatch" xml:space="preserve">Найти следующее совпадение</x:String> <x:String x:Key="Text.Hotkeys.TextEditor.GotoNextMatch" xml:space="preserve">Найти следующее совпадение</x:String>
@ -367,10 +384,10 @@
<x:String x:Key="Text.Hunk.Discard" xml:space="preserve">Отклонить</x:String> <x:String x:Key="Text.Hunk.Discard" xml:space="preserve">Отклонить</x:String>
<x:String x:Key="Text.Init" xml:space="preserve">Инициализировать хранилище</x:String> <x:String x:Key="Text.Init" xml:space="preserve">Инициализировать хранилище</x:String>
<x:String x:Key="Text.Init.Path" xml:space="preserve">Путь:</x:String> <x:String x:Key="Text.Init.Path" xml:space="preserve">Путь:</x:String>
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Выполняется частичный забор. Нажмите 'Отказ' для восстановления заголовка.</x:String> <x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Выполняется частичный забор. Нажмите «Отказ» для восстановления заголовка.</x:String>
<x:String x:Key="Text.InProgress.Merge" xml:space="preserve">Выполняет запрос слияния. Нажмите 'Отказ' для восстановления заголовка.</x:String> <x:String x:Key="Text.InProgress.Merge" xml:space="preserve">Выполняет запрос слияния. Нажмите «Отказ» для восстановления заголовка.</x:String>
<x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">Выполняется перенос. Нажмите 'Отказ' для восстановления заголовка.</x:String> <x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">Выполняется перенос. Нажмите «Отказ» для восстановления заголовка.</x:String>
<x:String x:Key="Text.InProgress.Revert" xml:space="preserve">Выполняется возврат. Нажмите 'Отказ' для восстановления заголовка.</x:String> <x:String x:Key="Text.InProgress.Revert" xml:space="preserve">Выполняется возврат. Нажмите «Отказ» для восстановления заголовка.</x:String>
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Интерактивное перемещение</x:String> <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.Target" xml:space="preserve">Целевая ветка:</x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">На:</x:String> <x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">На:</x:String>
@ -405,12 +422,12 @@
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">В пролому году</x:String> <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.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" xml:space="preserve">Параметры</x:String>
<x:String x:Key="Text.Preference.Advanced" xml:space="preserve">Расширенные опции</x:String>
<x:String x:Key="Text.Preference.AI" xml:space="preserve">ОТКРЫТЬ ИИ</x:String> <x:String x:Key="Text.Preference.AI" 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.ApiKey" xml:space="preserve">Ключ API</x:String>
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Запрос на анализ различий</x:String> <x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Запрос на анализ различий</x:String>
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Сгенерировать запрос на тему</x:String> <x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Произвести запрос на тему</x:String>
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Модель</x:String> <x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Модель</x:String>
<x:String x:Key="Text.Preference.AI.Name" xml:space="preserve">Имя:</x:String>
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">Сервер</x:String> <x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">Сервер</x:String>
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">ВИД</x:String> <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.DefaultFont" xml:space="preserve">Шрифт по-умолчанию</x:String>
@ -456,7 +473,7 @@
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Удалить внешнее хранилище</x:String> <x:String x:Key="Text.PruneRemote" xml:space="preserve">Удалить внешнее хранилище</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Цель:</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Цель:</x:String>
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Удалить рабочее дерево</x:String> <x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Удалить рабочее дерево</x:String>
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Информация об обрезке рабочего дерева в `$GIT_DIR/worktrees`</x:String> <x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Информация об обрезке рабочего дерева в «$GIT_DIR/worktrees»</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Забрать</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">Забрать</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Ветка:</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Ветка:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Извлечь все ветки</x:String> <x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Извлечь все ветки</x:String>
@ -501,7 +518,7 @@
<x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">Открыть в браузере</x:String> <x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">Открыть в браузере</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Удалить</x:String> <x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Удалить</x:String>
<x:String x:Key="Text.RemoveWorktree" xml:space="preserve">Подтвердить удаление рабочего дерева</x:String> <x:String x:Key="Text.RemoveWorktree" xml:space="preserve">Подтвердить удаление рабочего дерева</x:String>
<x:String x:Key="Text.RemoveWorktree.Force" xml:space="preserve">Включить опцию `--force`</x:String> <x:String x:Key="Text.RemoveWorktree.Force" xml:space="preserve">Включить опцию --force</x:String>
<x:String x:Key="Text.RemoveWorktree.Target" xml:space="preserve">Цель:</x:String> <x:String x:Key="Text.RemoveWorktree.Target" xml:space="preserve">Цель:</x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">Переименовать ветку</x:String> <x:String x:Key="Text.RenameBranch" xml:space="preserve">Переименовать ветку</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">Новое имя:</x:String> <x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">Новое имя:</x:String>
@ -510,17 +527,19 @@
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">Отказ</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">Отказ</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Автоматическое извлечение изменений с внешних хранилищ...</x:String> <x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Автоматическое извлечение изменений с внешних хранилищ...</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду `git gc` для данного хранилища.</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду «git gc» для данного хранилища.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Настройка этого хранилища</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">Настройка этого хранилища</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">ПРОДОЛЖИТЬ</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">ПРОДОЛЖИТЬ</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Разрешить опцию '--reflog'</x:String> <x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Изменить действия</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">Не изменять действия</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Разрешить опцию --reflog</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Открыть в файловом менеджере</x:String> <x:String x:Key="Text.Repository.Explore" xml:space="preserve">Открыть в файловом менеджере</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Поиск веток, меток и подмодулей</x:String> <x:String x:Key="Text.Repository.Filter" xml:space="preserve">Поиск веток, меток и подмодулей</x:String>
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">ОТФИЛЬТРОВАНО ОТ:</x:String> <x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">ОТФИЛЬТРОВАНО:</x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">ЛОКАЛЬНЫЕ ВЕТКИ</x:String> <x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">ЛОКАЛЬНЫЕ ВЕТКИ</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Навигация по заголовку</x:String> <x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Навигация по заголовку</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Включить опцию '--first-parent'</x:String> <x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Включить опцию --first-parent</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Создать ветку</x:String> <x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Создать ветку</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Открыть в {0}</x:String> <x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Открыть в {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Открыть в расширенном инструменте</x:String> <x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Открыть в расширенном инструменте</x:String>
@ -550,12 +569,12 @@
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Режим сброса:</x:String> <x:String x:Key="Text.Reset.Mode" xml:space="preserve">Режим сброса:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Переместить в:</x:String> <x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Переместить в:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Текущая ветка:</x:String> <x:String x:Key="Text.Reset.Target" xml:space="preserve">Текущая ветка:</x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">Раскрыть в файловом менеджере</x:String> <x:String x:Key="Text.RevealFile" xml:space="preserve">Открыть в файловом менеджере</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">Отменить фиксацию</x:String> <x:String x:Key="Text.Revert" xml:space="preserve">Отменить фиксацию</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Фиксация:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Фиксация:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Отмена изменений фиксации</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Отмена изменений фиксации</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Переформулировать сообщение фиксации</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Переформулировать сообщение фиксации</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Использовать "Shift+Enter" для ввода новой строки. "Enter" - это горячая клавиша кнопки OK</x:String> <x:String x:Key="Text.Reword.Tip" xml:space="preserve">Использовать «Shift+Enter» для ввода новой строки. «Enter» - это горячая клавиша кнопки OK</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Запуск. Подождите пожалуйста...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">Запуск. Подождите пожалуйста...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">СОХРАНИТЬ</x:String> <x:String x:Key="Text.Save" xml:space="preserve">СОХРАНИТЬ</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Сохранить как...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Сохранить как...</x:String>
@ -569,7 +588,7 @@
<x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Пропустить эту версию</x:String> <x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Пропустить эту версию</x:String>
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Обновление ПО</x:String> <x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Обновление ПО</x:String>
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">В настоящее время обновления недоступны.</x:String> <x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">В настоящее время обновления недоступны.</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Уплотнить фиксации</x:String> <x:String x:Key="Text.Squash" xml:space="preserve">Втиснуть фиксации</x:String>
<x:String x:Key="Text.Squash.Into" xml:space="preserve">В:</x:String> <x:String x:Key="Text.Squash.Into" xml:space="preserve">В:</x:String>
<x:String x:Key="Text.SSHKey" xml:space="preserve">Частный ключ SSH:</x:String> <x:String x:Key="Text.SSHKey" xml:space="preserve">Частный ключ SSH:</x:String>
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Путь хранения частного ключа SSH</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Путь хранения частного ключа SSH</x:String>
@ -578,6 +597,7 @@
<x:String x:Key="Text.Start" xml:space="preserve">ЗАПУСК</x:String> <x:String x:Key="Text.Start" xml:space="preserve">ЗАПУСК</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Отложить</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Отложить</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Включить неотслеживаемые файлы</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Включить неотслеживаемые файлы</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Хранить отложенные файлы</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Сообщение:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Сообщение:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Необязательно. Имя этого тайника</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Необязательно. Имя этого тайника</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Отложить локальные изменения</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Отложить локальные изменения</x:String>

View file

@ -58,6 +58,7 @@
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">删除选中的 {0} 个分支</x:String> <x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">删除选中的 {0} 个分支</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">放弃所有更改</x:String> <x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">放弃所有更改</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">快进(fast-forward)到 ${0}$</x:String> <x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">快进(fast-forward)到 ${0}$</x:String>
<x:String x:Key="Text.BranchCM.FetchInto" xml:space="preserve">拉取(fetch) ${0}$ 至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">GIT工作流 - 完成 ${0}$</x:String> <x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">GIT工作流 - 完成 ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">合并 ${0}$ 到 ${1}$...</x:String> <x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">合并 ${0}$ 到 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉回(pull) ${0}$</x:String> <x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉回(pull) ${0}$</x:String>
@ -72,6 +73,7 @@
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String> <x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重置文件到该版本</x:String> <x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重置文件到该版本</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">重置文件到上一版本</x:String> <x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">重置文件到上一版本</x:String>
<x:String x:Key="Text.ChangeCM.GenerateCommitMessage" xml:space="preserve">生成提交信息</x:String>
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切换变更显示模式</x:String> <x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切换变更显示模式</x:String>
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">文件名+路径列表模式</x:String> <x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">文件名+路径列表模式</x:String>
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">全路径列表模式</x:String> <x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">全路径列表模式</x:String>
@ -109,6 +111,7 @@
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String> <x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">复制简要信息</x:String> <x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">复制简要信息</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">复制提交指纹</x:String> <x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">复制提交指纹</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">自定义操作</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">交互式变基(rebase -i) ${0}$ 到此处</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">交互式变基(rebase -i) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 到此处</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此处</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此处</x:String>
@ -140,6 +143,14 @@
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交信息模板</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交信息模板</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">模板名 </x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">模板名 </x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">模板内容 </x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">模板内容 </x:String>
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">自定义操作</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">命令行参数 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">请使用${REPO}代替仓库路径,${SHA}代替提交哈希</x:String>
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">可执行文件路径 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">名称 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">作用目标 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">选中的提交</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">仓库</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String> <x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String> <x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT配置</x:String> <x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT配置</x:String>
@ -147,6 +158,7 @@
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">分钟</x:String> <x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">分钟</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">默认远程</x:String> <x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">默认远程</x:String>
<x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">提交信息追加署名 (--signoff)</x:String> <x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">提交信息追加署名 (--signoff)</x:String>
<x:String x:Key="Text.Configure.Git.EnablePruneOnFetch" xml:space="preserve">拉取更新时启用修剪(--prune</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE追踪</x:String> <x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE追踪</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">新增匹配Github Issue规则</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">新增匹配Github Issue规则</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">新增匹配Jira规则</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">新增匹配Jira规则</x:String>
@ -157,6 +169,9 @@
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">规则名 </x:String> <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" 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.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.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.Proxy" xml:space="preserve">HTTP代理</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.Proxy.Placeholder" xml:space="preserve">HTTP网络代理</x:String>
<x:String x:Key="Text.Configure.User" xml:space="preserve">用户名</x:String> <x:String x:Key="Text.Configure.User" xml:space="preserve">用户名</x:String>
@ -249,6 +264,8 @@
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目标 </x:String> <x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目标 </x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">编辑分组</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">编辑分组</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">编辑仓库</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">编辑仓库</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">执行自定义操作</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">自定义操作 </x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快进(fast-forward无需checkout)</x:String> <x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快进(fast-forward无需checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">拉取(fetch)</x:String> <x:String x:Key="Text.Fetch" xml:space="preserve">拉取(fetch)</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">拉取所有的远程仓库</x:String> <x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">拉取所有的远程仓库</x:String>
@ -404,7 +421,13 @@
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String> <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.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" xml:space="preserve">偏好设置</x:String>
<x:String x:Key="Text.Preference.Advanced" 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.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>
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">模型</x:String>
<x:String x:Key="Text.Preference.AI.Name" xml:space="preserve">配置名称</x:String>
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">服务地址</x:String>
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">外观配置</x:String> <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.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.DefaultFontSize" xml:space="preserve">默认字体大小</x:String>
@ -507,6 +530,8 @@
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">自定义操作</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">自定义操作未设置</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">启用 --reflog 选项</x:String> <x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">启用 --reflog 选项</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String> <x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速查找分支/标签/子模块</x:String> <x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速查找分支/标签/子模块</x:String>
@ -569,6 +594,7 @@
<x:String x:Key="Text.Start" xml:space="preserve">开 始</x:String> <x:String x:Key="Text.Start" xml:space="preserve">开 始</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">贮藏(stash)</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">贮藏(stash)</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">包含未跟踪的文件</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">包含未跟踪的文件</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">保留暂存区文件</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">信息 </x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">信息 </x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">选填,用于命名此贮藏</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">选填,用于命名此贮藏</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">仅贮藏暂存区的变更</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">仅贮藏暂存区的变更</x:String>

View file

@ -58,6 +58,7 @@
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">刪除所選的 {0} 個分支</x:String> <x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">刪除所選的 {0} 個分支</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">捨棄所有變更</x:String> <x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">捨棄所有變更</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">快轉 (fast-forward) 到 ${0}$</x:String> <x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">快轉 (fast-forward) 到 ${0}$</x:String>
<x:String x:Key="Text.BranchCM.FetchInto" xml:space="preserve">提取 (fetch) ${0}$ 到 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git 工作流 - 完成 ${0}$</x:String> <x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git 工作流 - 完成 ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">合併 ${0}$ 到 ${1}$...</x:String> <x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">合併 ${0}$ 到 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉取 (pull) ${0}$</x:String> <x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉取 (pull) ${0}$</x:String>
@ -72,6 +73,7 @@
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String> <x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重設檔案為此版本</x:String> <x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重設檔案為此版本</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">重設檔案到上一版本</x:String> <x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">重設檔案到上一版本</x:String>
<x:String x:Key="Text.ChangeCM.GenerateCommitMessage" xml:space="preserve">產生提交訊息</x:String>
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切換變更顯示模式</x:String> <x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切換變更顯示模式</x:String>
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">檔案名稱 + 路徑列表模式</x:String> <x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">檔案名稱 + 路徑列表模式</x:String>
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">全路徑列表模式</x:String> <x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">全路徑列表模式</x:String>
@ -109,6 +111,7 @@
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">與本機工作區比較</x:String> <x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">與本機工作區比較</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">複製摘要資訊</x:String> <x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">複製摘要資訊</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">複製提交編號</x:String> <x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">複製提交編號</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">自訂動作</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">互動式重定基底 (rebase -i) ${0}$ 到此處</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">互動式重定基底 (rebase -i) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 到此處</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重設 (reset) ${0}$ 到此處</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重設 (reset) ${0}$ 到此處</x:String>
@ -140,6 +143,14 @@
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交訊息範本</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交訊息範本</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">範本名稱:</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">範本名稱:</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">範本內容:</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">範本內容:</x:String>
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">自訂動作</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">指令參數:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">使用 ${REPO} 表示存放庫路徑、${SHA} 表示所選的提交編號</x:String>
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">可執行檔案路徑:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">名稱:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">執行範圍:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">選取的提交</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">存放庫</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵件</x:String> <x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵件</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">電子郵件地址</x:String> <x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">電子郵件地址</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">Git 設定</x:String> <x:String x:Key="Text.Configure.Git" xml:space="preserve">Git 設定</x:String>
@ -147,16 +158,20 @@
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">分鐘</x:String> <x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">分鐘</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">預設遠端存放庫</x:String> <x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">預設遠端存放庫</x:String>
<x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">提交訊息追加署名 (--signoff)</x:String> <x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">提交訊息追加署名 (--signoff)</x:String>
<x:String x:Key="Text.Configure.Git.EnablePruneOnFetch" xml:space="preserve">拉取變更時進行清理 (--prune)</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">Issue 追蹤</x:String> <x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">Issue 追蹤</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">新增符合 GitHub Issue 規則</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">新增符合 GitHub Issue 規則</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">新增符合 Jira 規則</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">新增符合 Jira 規則</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGitLabIssue" xml:space="preserve">新增符合 GitLab 議題規則</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGitLabIssue" xml:space="preserve">新增符合 GitLab 議題規則</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGitLabMergeRequest" xml:space="preserve">新增符合 GitLab 合併請求規則</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGitLabMergeRequest" xml:space="preserve">新增符合 GitLab 合併請求規則</x:String>
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">新增自訂規則</x:String> <x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">新增自訂規則</x:String>
<x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">符合 Issue 的正表達式:</x:String> <x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">符合 Issue 的正表達式:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">規則名稱:</x:String> <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" 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.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.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.Proxy" xml:space="preserve">HTTP 代理</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.Proxy.Placeholder" xml:space="preserve">HTTP 網路代理</x:String>
<x:String x:Key="Text.Configure.User" xml:space="preserve">使用者名稱</x:String> <x:String x:Key="Text.Configure.User" xml:space="preserve">使用者名稱</x:String>
@ -249,6 +264,8 @@
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目標:</x:String> <x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目標:</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">編輯群組</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">編輯群組</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">編輯存放庫</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">編輯存放庫</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">執行自訂動作</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">自訂動作:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快進 (fast-forward無需 checkout)</x:String> <x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快進 (fast-forward無需 checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">提取 (fetch)</x:String> <x:String x:Key="Text.Fetch" xml:space="preserve">提取 (fetch)</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">提取所有的遠端存放庫</x:String> <x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">提取所有的遠端存放庫</x:String>
@ -404,11 +421,11 @@
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String> <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.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" xml:space="preserve">偏好設定</x:String>
<x:String x:Key="Text.Preference.Advanced" 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">OpenAI</x:String>
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">伺服器</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.ApiKey" xml:space="preserve">API 金鑰</x:String>
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">模型</x:String> <x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">模型</x:String>
<x:String x:Key="Text.Preference.AI.Name" xml:space="preserve">名稱</x:String>
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">分析變更差異提示詞</x:String> <x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">分析變更差異提示詞</x:String>
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">產生提交訊息提示詞</x:String> <x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">產生提交訊息提示詞</x:String>
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">外觀設定</x:String> <x:String x:Key="Text.Preference.Appearance" xml:space="preserve">外觀設定</x:String>
@ -513,6 +530,8 @@
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">設定本存放庫</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">設定本存放庫</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">自訂動作</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">沒有自訂的動作</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">啟用 [--reflog] 選項</x:String> <x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">啟用 [--reflog] 選項</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在檔案瀏覽器中開啟</x:String> <x:String x:Key="Text.Repository.Explore" xml:space="preserve">在檔案瀏覽器中開啟</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速搜尋分支/標籤/子模組</x:String> <x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速搜尋分支/標籤/子模組</x:String>
@ -575,6 +594,7 @@
<x:String x:Key="Text.Start" xml:space="preserve">開 始</x:String> <x:String x:Key="Text.Start" xml:space="preserve">開 始</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">擱置變更 (stash)</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">擱置變更 (stash)</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">包含未追蹤的檔案</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">包含未追蹤的檔案</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">保留已暫存的變更</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">擱置變更訊息:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">擱置變更訊息:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">選填,用於命名此擱置變更</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">選填,用於命名此擱置變更</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">僅擱置已暫存的變更</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">僅擱置已暫存的變更</x:String>

View file

@ -83,7 +83,7 @@
<SolidColorBrush x:Key="Brush.Diff.DeletedHighlight" Color="{DynamicResource Color.Diff.DeletedHighlight}"/> <SolidColorBrush x:Key="Brush.Diff.DeletedHighlight" Color="{DynamicResource Color.Diff.DeletedHighlight}"/>
<SolidColorBrush x:Key="Brush.Link" Color="{DynamicResource Color.Link}"/> <SolidColorBrush x:Key="Brush.Link" Color="{DynamicResource Color.Link}"/>
<FontFamily x:Key="Fonts.Default">fonts:Inter#Inter, $Default</FontFamily> <FontFamily x:Key="Fonts.Default">fonts:Inter#Inter</FontFamily>
<FontFamily x:Key="Fonts.Monospace">fonts:SourceGit#JetBrains Mono</FontFamily> <FontFamily x:Key="Fonts.Monospace">fonts:SourceGit#JetBrains Mono</FontFamily>
<FontFamily x:Key="Fonts.Primary">fonts:SourceGit#JetBrains Mono</FontFamily> <FontFamily x:Key="Fonts.Primary">fonts:SourceGit#JetBrains Mono</FontFamily>
</ResourceDictionary> </ResourceDictionary>

View file

@ -100,7 +100,7 @@ namespace SourceGit.ViewModels
{ {
SetProgressDescription("Fetching from added remote ..."); SetProgressDescription("Fetching from added remote ...");
new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null); new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
new Commands.Fetch(_repo.FullPath, _name, false, SetProgressDescription).Exec(); new Commands.Fetch(_repo.FullPath, _name, false, false, SetProgressDescription).Exec();
} }
CallUIThread(() => CallUIThread(() =>
{ {

View file

@ -45,6 +45,12 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _fullMessage, value); private set => SetProperty(ref _fullMessage, value);
} }
public Models.CommitSignInfo SignInfo
{
get => _signInfo;
private set => SetProperty(ref _signInfo, value);
}
public List<Models.Change> Changes public List<Models.Change> Changes
{ {
get => _changes; get => _changes;
@ -131,6 +137,7 @@ namespace SourceGit.ViewModels
_visibleChanges.Clear(); _visibleChanges.Clear();
if (_selectedChanges != null) if (_selectedChanges != null)
_selectedChanges.Clear(); _selectedChanges.Clear();
_signInfo = null;
_searchChangeFilter = null; _searchChangeFilter = null;
_diffContext = null; _diffContext = null;
_viewRevisionFileContent = null; _viewRevisionFileContent = null;
@ -474,6 +481,7 @@ namespace SourceGit.ViewModels
{ {
_changes = null; _changes = null;
FullMessage = string.Empty; FullMessage = string.Empty;
SignInfo = null;
Changes = []; Changes = [];
VisibleChanges = null; VisibleChanges = null;
SelectedChanges = null; SelectedChanges = null;
@ -488,6 +496,12 @@ namespace SourceGit.ViewModels
Dispatcher.UIThread.Invoke(() => FullMessage = fullMessage); Dispatcher.UIThread.Invoke(() => FullMessage = fullMessage);
}); });
Task.Run(() =>
{
var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result();
Dispatcher.UIThread.Invoke(() => SignInfo = signInfo);
});
if (_cancelToken != null) if (_cancelToken != null)
_cancelToken.Requested = true; _cancelToken.Requested = true;
@ -637,6 +651,7 @@ namespace SourceGit.ViewModels
private int _activePageIndex = 0; private int _activePageIndex = 0;
private Models.Commit _commit = null; private Models.Commit _commit = null;
private string _fullMessage = string.Empty; private string _fullMessage = string.Empty;
private Models.CommitSignInfo _signInfo = null;
private List<Models.Change> _changes = null; private List<Models.Change> _changes = null;
private List<Models.Change> _visibleChanges = null; private List<Models.Change> _visibleChanges = null;
private List<Models.Change> _selectedChanges = null; private List<Models.Change> _selectedChanges = null;

View file

@ -0,0 +1,40 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class ExecuteCustomAction : Popup
{
public Models.CustomAction CustomAction
{
get;
private set;
}
public ExecuteCustomAction(Repository repo, Models.CustomAction action, Models.Commit commit)
{
_repo = repo;
_args = action.Arguments.Replace("${REPO}", _repo.FullPath);
if (commit != null)
_args = _args.Replace("${SHA}", commit.SHA);
CustomAction = action;
View = new Views.ExecuteCustomAction() { DataContext = this };
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Run custom action ...";
return Task.Run(() =>
{
Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, _args, SetProgressDescription);
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
}
private readonly Repository _repo = null;
private string _args = string.Empty;
}
}

View file

@ -40,6 +40,8 @@ namespace SourceGit.ViewModels
{ {
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
var notags = _repo.Settings.FetchWithoutTags;
var prune = _repo.Settings.EnablePruneOnFetch;
return Task.Run(() => return Task.Run(() =>
{ {
if (FetchAllRemotes) if (FetchAllRemotes)
@ -47,13 +49,13 @@ namespace SourceGit.ViewModels
foreach (var remote in _repo.Remotes) foreach (var remote in _repo.Remotes)
{ {
SetProgressDescription($"Fetching remote: {remote.Name}"); SetProgressDescription($"Fetching remote: {remote.Name}");
new Commands.Fetch(_repo.FullPath, remote.Name, NoTags, SetProgressDescription).Exec(); new Commands.Fetch(_repo.FullPath, remote.Name, notags, prune, SetProgressDescription).Exec();
} }
} }
else else
{ {
SetProgressDescription($"Fetching remote: {SelectedRemote.Name}"); SetProgressDescription($"Fetching remote: {SelectedRemote.Name}");
new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, NoTags, SetProgressDescription).Exec(); new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, notags, prune, SetProgressDescription).Exec();
} }
CallUIThread(() => CallUIThread(() =>

View file

@ -0,0 +1,42 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class FetchInto : Popup
{
public Models.Branch Local
{
get;
private set;
}
public Models.Branch Upstream
{
get;
private set;
}
public FetchInto(Repository repo, Models.Branch local, Models.Branch upstream)
{
_repo = repo;
Local = local;
Upstream = upstream;
View = new Views.FetchInto() { DataContext = this };
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Fast-Forward ...";
return Task.Run(() =>
{
new Commands.Fetch(_repo.FullPath, Local, Upstream, SetProgressDescription).Exec();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
}
private readonly Repository _repo = null;
}
}

View file

@ -605,6 +605,39 @@ namespace SourceGit.ViewModels
menu.Items.Add(archive); menu.Items.Add(archive);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
var actions = new List<Models.CustomAction>();
foreach (var action in _repo.Settings.CustomActions)
{
if (action.Scope == Models.CustomActionScope.Commit)
actions.Add(action);
}
if (actions.Count > 0)
{
var custom = new MenuItem();
custom.Header = App.Text("CommitCM.CustomAction");
custom.Icon = App.CreateMenuIcon("Icons.Action");
foreach (var action in actions)
{
var dup = action;
var item = new MenuItem();
item.Icon = App.CreateMenuIcon("Icons.Action");
item.Header = dup.Name;
item.Click += (_, e) =>
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new ExecuteCustomAction(_repo, dup, commit));
e.Handled = true;
};
custom.Items.Add(item);
}
menu.Items.Add(custom);
menu.Items.Add(new MenuItem() { Header = "-" });
}
var copySHA = new MenuItem(); var copySHA = new MenuItem();
copySHA.Header = App.Text("CommitCM.CopySHA"); copySHA.Header = App.Text("CommitCM.CopySHA");
copySHA.Icon = App.CreateMenuIcon("Icons.Copy"); copySHA.Icon = App.CreateMenuIcon("Icons.Copy");

View file

@ -204,12 +204,7 @@ namespace SourceGit.ViewModels
var activeIdx = Pages.IndexOf(_activePage); var activeIdx = Pages.IndexOf(_activePage);
if (removeIdx == activeIdx) if (removeIdx == activeIdx)
{ {
ActivePage = Pages[removeIdx == Pages.Count - 1 ? removeIdx - 1 : removeIdx + 1]; ActivePage = Pages[removeIdx > 0 ? removeIdx - 1 : removeIdx + 1];
CloseRepositoryInTab(page);
Pages.RemoveAt(removeIdx);
}
else if (removeIdx + 1 == activeIdx)
{
CloseRepositoryInTab(page); CloseRepositoryInTab(page);
Pages.RemoveAt(removeIdx); Pages.RemoveAt(removeIdx);
} }

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels namespace SourceGit.ViewModels
@ -25,7 +25,6 @@ namespace SourceGit.ViewModels
_instance.PrepareGit(); _instance.PrepareGit();
_instance.PrepareShellOrTerminal(); _instance.PrepareShellOrTerminal();
_instance.PrepareWorkspaces(); _instance.PrepareWorkspaces();
_instance.PrepareOpenAIPrompt();
return _instance; return _instance;
} }
@ -277,71 +276,6 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _externalMergeToolPath, value); set => SetProperty(ref _externalMergeToolPath, value);
} }
public string OpenAIServer
{
get => Models.OpenAI.Server;
set
{
if (value != Models.OpenAI.Server)
{
Models.OpenAI.Server = value;
OnPropertyChanged();
}
}
}
public string OpenAIApiKey
{
get => Models.OpenAI.ApiKey;
set
{
if (value != Models.OpenAI.ApiKey)
{
Models.OpenAI.ApiKey = value;
OnPropertyChanged();
}
}
}
public string OpenAIModel
{
get => Models.OpenAI.Model;
set
{
if (value != Models.OpenAI.Model)
{
Models.OpenAI.Model = value;
OnPropertyChanged();
}
}
}
public string OpenAIAnalyzeDiffPrompt
{
get => Models.OpenAI.AnalyzeDiffPrompt;
set
{
if (value != Models.OpenAI.AnalyzeDiffPrompt)
{
Models.OpenAI.AnalyzeDiffPrompt = value;
OnPropertyChanged();
}
}
}
public string OpenAIGenerateSubjectPrompt
{
get => Models.OpenAI.GenerateSubjectPrompt;
set
{
if (value != Models.OpenAI.GenerateSubjectPrompt)
{
Models.OpenAI.GenerateSubjectPrompt = value;
OnPropertyChanged();
}
}
}
public uint StatisticsSampleColor public uint StatisticsSampleColor
{ {
get => _statisticsSampleColor; get => _statisticsSampleColor;
@ -360,6 +294,12 @@ namespace SourceGit.ViewModels
set; set;
} = []; } = [];
public AvaloniaList<Models.OpenAIService> OpenAIServices
{
get;
set;
} = [];
public double LastCheckUpdateTime public double LastCheckUpdateTime
{ {
get => _lastCheckUpdateTime; get => _lastCheckUpdateTime;
@ -554,45 +494,6 @@ namespace SourceGit.ViewModels
} }
} }
private void PrepareOpenAIPrompt()
{
if (string.IsNullOrEmpty(Models.OpenAI.AnalyzeDiffPrompt))
{
Models.OpenAI.AnalyzeDiffPrompt = """
You are an expert developer specialist in creating commits.
Provide a super concise one sentence overall changes summary of the user `git diff` output following strictly the next rules:
- Do not use any code snippets, imports, file routes or bullets points.
- Do not mention the route of file that has been change.
- Write clear, concise, and descriptive messages that explain the MAIN GOAL made of the changes.
- Use the present tense and active voice in the message, for example, "Fix bug" instead of "Fixed bug.".
- Use the imperative mood, which gives the message a sense of command, e.g. "Add feature" instead of "Added feature".
- Avoid using general terms like "update" or "change", be specific about what was updated or changed.
- Avoid using terms like "The main goal of", just output directly the summary in plain text
""";
}
if (string.IsNullOrEmpty(Models.OpenAI.GenerateSubjectPrompt))
{
Models.OpenAI.GenerateSubjectPrompt = """
You are an expert developer specialist in creating commits messages.
Your only goal is to retrieve a single commit message.
Based on the provided user changes, combine them in ONE SINGLE commit message retrieving the global idea, following strictly the next rules:
- Assign the commit {type} according to the next conditions:
feat: Only when adding a new feature.
fix: When fixing a bug.
docs: When updating documentation.
style: When changing elements styles or design and/or making changes to the code style (formatting, missing semicolons, etc.) without changing the code logic.
test: When adding or updating tests.
chore: When making changes to the build process or auxiliary tools and libraries.
revert: When undoing a previous commit.
refactor: When restructuring code without changing its external behavior, or is any of the other refactor types.
- Do not add any issues numeration, explain your output nor introduce your answer.
- Output directly only one commit message in plain text with the next format: {type}: {commit_message}.
- Be as concise as possible, keep the message under 50 characters.
""";
}
}
private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection) private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection)
{ {
foreach (var node in collection) foreach (var node in collection)

View file

@ -147,9 +147,18 @@ namespace SourceGit.ViewModels
if (FetchAllBranches) if (FetchAllBranches)
{ {
SetProgressDescription($"Fetching remote: {_selectedRemote.Name}..."); SetProgressDescription($"Fetching remote: {_selectedRemote.Name}...");
rs = new Commands.Fetch(_repo.FullPath, _selectedRemote.Name, NoTags, SetProgressDescription).Exec(); rs = new Commands.Fetch(
_repo.FullPath,
_selectedRemote.Name,
NoTags,
_repo.Settings.EnablePruneOnFetch,
SetProgressDescription).Exec();
if (!rs) if (!rs)
{
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false; return false;
}
_repo.MarkFetched(); _repo.MarkFetched();
@ -168,7 +177,14 @@ namespace SourceGit.ViewModels
else else
{ {
SetProgressDescription($"Pull {_selectedRemote.Name}/{_selectedBranch.Name}..."); SetProgressDescription($"Pull {_selectedRemote.Name}/{_selectedBranch.Name}...");
rs = new Commands.Pull(_repo.FullPath, _selectedRemote.Name, _selectedBranch.Name, UseRebase, NoTags, SetProgressDescription).Exec(); rs = new Commands.Pull(
_repo.FullPath,
_selectedRemote.Name,
_selectedBranch.Name,
UseRebase,
NoTags,
_repo.Settings.EnablePruneOnFetch,
SetProgressDescription).Exec();
} }
if (rs && needPopStash) if (rs && needPopStash)

View file

@ -45,6 +45,11 @@ namespace SourceGit.ViewModels
get => _settings; get => _settings;
} }
public bool HasAllowedSignersFile
{
get => _hasAllowedSignersFile;
}
public int SelectedViewIndex public int SelectedViewIndex
{ {
get => _selectedViewIndex; get => _selectedViewIndex;
@ -444,6 +449,12 @@ namespace SourceGit.ViewModels
public void RefreshAll() public void RefreshAll()
{ {
Task.Run(() =>
{
var allowedSignersFile = new Commands.Config(_fullpath).Get("gpg.ssh.allowedSignersFile");
_hasAllowedSignersFile = !string.IsNullOrEmpty(allowedSignersFile);
});
Task.Run(() => Task.Run(() =>
{ {
RefreshBranches(); RefreshBranches();
@ -1276,6 +1287,45 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
public ContextMenu CreateContextMenuForCustomAction()
{
var actions = new List<Models.CustomAction>();
foreach (var action in _settings.CustomActions)
{
if (action.Scope == Models.CustomActionScope.Repository)
actions.Add(action);
}
var menu = new ContextMenu();
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
if (actions.Count > 0)
{
foreach (var action in actions)
{
var dup = action;
var item = new MenuItem();
item.Icon = App.CreateMenuIcon("Icons.Action");
item.Header = dup.Name;
item.Click += (_, e) =>
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new ExecuteCustomAction(this, dup, null));
e.Handled = true;
};
menu.Items.Add(item);
}
}
else
{
menu.Items.Add(new MenuItem() { Header = App.Text("Repository.CustomActions.Empty") });
}
return menu;
}
public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch) public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
{ {
var menu = new ContextMenu(); var menu = new ContextMenu();
@ -1354,6 +1404,7 @@ namespace SourceGit.ViewModels
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(checkout); menu.Items.Add(checkout);
menu.Items.Add(new MenuItem() { Header = "-" });
var worktree = _worktrees.Find(x => x.Branch == branch.FullName); var worktree = _worktrees.Find(x => x.Branch == branch.FullName);
var upstream = _branches.Find(x => x.FullName == branch.Upstream); var upstream = _branches.Find(x => x.FullName == branch.Upstream);
@ -1370,11 +1421,22 @@ namespace SourceGit.ViewModels
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(new MenuItem() { Header = "-" }); var fetchInto = new MenuItem();
fetchInto.Header = new Views.NameHighlightedTextBlock("BranchCM.FetchInto", upstream.FriendlyName, branch.Name);
fetchInto.Icon = App.CreateMenuIcon("Icons.Fetch");
fetchInto.IsEnabled = branch.TrackStatus.Ahead.Count == 0;
fetchInto.Click += (_, e) =>
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new FetchInto(this, branch, upstream));
e.Handled = true;
};
menu.Items.Add(fastForward); menu.Items.Add(fastForward);
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(fetchInto);
} }
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(push); menu.Items.Add(push);
var merge = new MenuItem(); var merge = new MenuItem();
@ -2114,7 +2176,7 @@ namespace SourceGit.ViewModels
IsAutoFetching = true; IsAutoFetching = true;
Dispatcher.UIThread.Invoke(() => OnPropertyChanged(nameof(IsAutoFetching))); Dispatcher.UIThread.Invoke(() => OnPropertyChanged(nameof(IsAutoFetching)));
new Commands.Fetch(_fullpath, "--all", false, null) { RaiseError = false }.Exec(); new Commands.Fetch(_fullpath, "--all", false, _settings.EnablePruneOnFetch, null) { RaiseError = false }.Exec();
_lastFetchTime = DateTime.Now; _lastFetchTime = DateTime.Now;
IsAutoFetching = false; IsAutoFetching = false;
Dispatcher.UIThread.Invoke(() => OnPropertyChanged(nameof(IsAutoFetching))); Dispatcher.UIThread.Invoke(() => OnPropertyChanged(nameof(IsAutoFetching)));
@ -2123,6 +2185,7 @@ namespace SourceGit.ViewModels
private string _fullpath = string.Empty; private string _fullpath = string.Empty;
private string _gitDir = string.Empty; private string _gitDir = string.Empty;
private Models.RepositorySettings _settings = null; private Models.RepositorySettings _settings = null;
private bool _hasAllowedSignersFile = false;
private Models.Watcher _watcher = null; private Models.Watcher _watcher = null;
private Histories _histories = null; private Histories _histories = null;

View file

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using Avalonia.Collections; using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
@ -66,6 +67,12 @@ namespace SourceGit.ViewModels
set => _repo.Settings.EnableSignOffForCommit = value; set => _repo.Settings.EnableSignOffForCommit = value;
} }
public bool EnablePruneOnFetch
{
get => _repo.Settings.EnablePruneOnFetch;
set => _repo.Settings.EnablePruneOnFetch = value;
}
public bool EnableAutoFetch public bool EnableAutoFetch
{ {
get => _repo.Settings.EnableAutoFetch; get => _repo.Settings.EnableAutoFetch;
@ -108,6 +115,29 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _selectedIssueTrackerRule, value); set => SetProperty(ref _selectedIssueTrackerRule, value);
} }
public List<string> AvailableOpenAIServices
{
get;
private set;
}
public string PreferedOpenAIService
{
get => _repo.Settings.PreferedOpenAIService;
set => _repo.Settings.PreferedOpenAIService = value;
}
public AvaloniaList<Models.CustomAction> CustomActions
{
get => _repo.Settings.CustomActions;
}
public Models.CustomAction SelectedCustomAction
{
get => _selectedCustomAction;
set => SetProperty(ref _selectedCustomAction, value);
}
public RepositoryConfigure(Repository repo) public RepositoryConfigure(Repository repo)
{ {
_repo = repo; _repo = repo;
@ -116,6 +146,13 @@ namespace SourceGit.ViewModels
foreach (var remote in _repo.Remotes) foreach (var remote in _repo.Remotes)
Remotes.Add(remote.Name); Remotes.Add(remote.Name);
AvailableOpenAIServices = new List<string>() { "---" };
foreach (var service in Preference.Instance.OpenAIServices)
AvailableOpenAIServices.Add(service.Name);
if (AvailableOpenAIServices.IndexOf(PreferedOpenAIService) == -1)
PreferedOpenAIService = "---";
_cached = new Commands.Config(repo.FullPath).ListAll(); _cached = new Commands.Config(repo.FullPath).ListAll();
if (_cached.TryGetValue("user.name", out var name)) if (_cached.TryGetValue("user.name", out var name))
UserName = name; UserName = name;
@ -207,11 +244,21 @@ namespace SourceGit.ViewModels
public void RemoveSelectedIssueTracker() public void RemoveSelectedIssueTracker()
{ {
if (_selectedIssueTrackerRule != null) _repo.Settings.RemoveIssueTracker(_selectedIssueTrackerRule);
_repo.Settings.RemoveIssueTracker(_selectedIssueTrackerRule);
SelectedIssueTrackerRule = null; SelectedIssueTrackerRule = null;
} }
public void AddNewCustomAction()
{
SelectedCustomAction = _repo.Settings.AddNewCustomAction();
}
public void RemoveSelectedCustomAction()
{
_repo.Settings.RemoveCustomAction(_selectedCustomAction);
SelectedCustomAction = null;
}
public void Save() public void Save()
{ {
SetIfChanged("user.name", UserName, ""); SetIfChanged("user.name", UserName, "");
@ -245,5 +292,6 @@ namespace SourceGit.ViewModels
private string _httpProxy; private string _httpProxy;
private Models.CommitTemplate _selectedCommitTemplate = null; private Models.CommitTemplate _selectedCommitTemplate = null;
private Models.IssueTrackerRule _selectedIssueTrackerRule = null; private Models.IssueTrackerRule _selectedIssueTrackerRule = null;
private Models.CustomAction _selectedCustomAction = null;
} }
} }

View file

@ -18,24 +18,27 @@ namespace SourceGit.ViewModels
public bool IncludeUntracked public bool IncludeUntracked
{ {
get; get => _repo.Settings.IncludeUntrackedWhenStash;
set; set => _repo.Settings.IncludeUntrackedWhenStash = value;
} }
public bool OnlyStaged public bool OnlyStaged
{ {
get; get => _repo.Settings.OnlyStagedWhenStash;
set; set => _repo.Settings.OnlyStagedWhenStash = value;
}
public bool KeepIndex
{
get => _repo.Settings.KeepIndexWhenStash;
set => _repo.Settings.KeepIndexWhenStash = value;
} }
public StashChanges(Repository repo, List<Models.Change> changes, bool hasSelectedFiles) public StashChanges(Repository repo, List<Models.Change> changes, bool hasSelectedFiles)
{ {
_repo = repo; _repo = repo;
_changes = changes; _changes = changes;
HasSelectedFiles = hasSelectedFiles; HasSelectedFiles = hasSelectedFiles;
IncludeUntracked = true;
OnlyStaged = false;
View = new Views.StashChanges() { DataContext = this }; View = new Views.StashChanges() { DataContext = this };
} }
@ -63,7 +66,7 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var succ = new Commands.Stash(_repo.FullPath).Push(jobs, Message, !HasSelectedFiles && OnlyStaged); var succ = new Commands.Stash(_repo.FullPath).Push(jobs, Message, !HasSelectedFiles && OnlyStaged, KeepIndex);
CallUIThread(() => CallUIThread(() =>
{ {
_repo.MarkWorkingCopyDirtyManually(); _repo.MarkWorkingCopyDirtyManually();

View file

@ -403,25 +403,6 @@ namespace SourceGit.ViewModels
} }
} }
public void GenerateCommitMessageByAI()
{
if (!Models.OpenAI.IsValid)
{
App.RaiseException(_repo.FullPath, "Bad configuration for OpenAI");
return;
}
if (_staged is { Count: > 0 })
{
var dialog = new Views.AIAssistant(_repo.FullPath, _staged, generated => CommitMessage = generated);
App.OpenDialog(dialog);
}
else
{
App.RaiseException(_repo.FullPath, "No files added to commit!");
}
}
public void Commit() public void Commit()
{ {
DoCommit(false, false, false); DoCommit(false, false, false);
@ -900,6 +881,44 @@ namespace SourceGit.ViewModels
return null; return null;
var menu = new ContextMenu(); var menu = new ContextMenu();
var ai = null as MenuItem;
var services = GetPreferedOpenAIServices();
if (services.Count > 0)
{
ai = new MenuItem();
ai.Icon = App.CreateMenuIcon("Icons.AIAssist");
ai.Header = App.Text("ChangeCM.GenerateCommitMessage");
if (services.Count == 1)
{
ai.Click += (_, e) =>
{
var dialog = new Views.AIAssistant(services[0], _repo.FullPath, _selectedStaged, generated => CommitMessage = generated);
App.OpenDialog(dialog);
e.Handled = true;
};
}
else
{
foreach (var service in services)
{
var dup = service;
var item = new MenuItem();
item.Header = service.Name;
item.Click += (_, e) =>
{
var dialog = new Views.AIAssistant(dup, _repo.FullPath, _selectedStaged, generated => CommitMessage = generated);
App.OpenDialog(dialog);
e.Handled = true;
};
ai.Items.Add(item);
}
}
}
if (_selectedStaged.Count == 1) if (_selectedStaged.Count == 1)
{ {
var change = _selectedStaged[0]; var change = _selectedStaged[0];
@ -980,24 +999,6 @@ namespace SourceGit.ViewModels
e.Handled = true; e.Handled = true;
}; };
var copyPath = new MenuItem();
copyPath.Header = App.Text("CopyPath");
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
copyPath.Click += (_, e) =>
{
App.CopyText(change.Path);
e.Handled = true;
};
var copyFileName = new MenuItem();
copyFileName.Header = App.Text("CopyFileName");
copyFileName.Icon = App.CreateMenuIcon("Icons.Copy");
copyFileName.Click += (_, e) =>
{
App.CopyText(Path.GetFileName(change.Path));
e.Handled = true;
};
menu.Items.Add(explore); menu.Items.Add(explore);
menu.Items.Add(openWith); menu.Items.Add(openWith);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
@ -1089,6 +1090,30 @@ namespace SourceGit.ViewModels
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
} }
if (ai != null)
{
menu.Items.Add(ai);
menu.Items.Add(new MenuItem() { Header = "-" });
}
var copyPath = new MenuItem();
copyPath.Header = App.Text("CopyPath");
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
copyPath.Click += (_, e) =>
{
App.CopyText(change.Path);
e.Handled = true;
};
var copyFileName = new MenuItem();
copyFileName.Header = App.Text("CopyFileName");
copyFileName.Icon = App.CreateMenuIcon("Icons.Copy");
copyFileName.Click += (_, e) =>
{
App.CopyText(Path.GetFileName(change.Path));
e.Handled = true;
};
menu.Items.Add(copyPath); menu.Items.Add(copyPath);
menu.Items.Add(copyFileName); menu.Items.Add(copyFileName);
} }
@ -1142,6 +1167,12 @@ namespace SourceGit.ViewModels
menu.Items.Add(unstage); menu.Items.Add(unstage);
menu.Items.Add(stash); menu.Items.Add(stash);
menu.Items.Add(patch); menu.Items.Add(patch);
if (ai != null)
{
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(ai);
}
} }
return menu; return menu;
@ -1211,6 +1242,51 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
public ContextMenu CreateContextForOpenAI()
{
if (_staged == null || _staged.Count == 0)
{
App.RaiseException(_repo.FullPath, "No files added to commit!");
return null;
}
var services = GetPreferedOpenAIServices();
if (services.Count == 0)
{
App.RaiseException(_repo.FullPath, "Bad configuration for OpenAI");
return null;
}
if (services.Count == 1)
{
var dialog = new Views.AIAssistant(services[0], _repo.FullPath, _staged, generated => CommitMessage = generated);
App.OpenDialog(dialog);
return null;
}
else
{
var menu = new ContextMenu() { Placement = PlacementMode.TopEdgeAlignedLeft };
foreach (var service in services)
{
var dup = service;
var item = new MenuItem();
item.Header = service.Name;
item.Click += (_, e) =>
{
var dialog = new Views.AIAssistant(dup, _repo.FullPath, _staged, generated => CommitMessage = generated);
App.OpenDialog(dialog);
e.Handled = true;
};
menu.Items.Add(item);
}
return menu;
}
}
private List<Models.Change> GetStagedChanges() private List<Models.Change> GetStagedChanges()
{ {
if (_useAmend) if (_useAmend)
@ -1363,6 +1439,25 @@ namespace SourceGit.ViewModels
return false; return false;
} }
private IList<Models.OpenAIService> GetPreferedOpenAIServices()
{
var services = Preference.Instance.OpenAIServices;
if (services == null || services.Count == 0)
return [];
if (services.Count == 1)
return services;
var prefered = _repo.Settings.PreferedOpenAIService;
foreach (var service in services)
{
if (service.Name.Equals(prefered, StringComparison.Ordinal))
return [service];
}
return services;
}
private Repository _repo = null; private Repository _repo = null;
private bool _isLoadingData = false; private bool _isLoadingData = false;
private bool _isStaging = false; private bool _isStaging = false;

View file

@ -15,30 +15,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,Auto"> <Grid RowDefinitions="Auto,Auto,Auto">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.AIAssist}" Data="{StaticResource Icons.AIAssist}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.AIAssistant}" Text="{DynamicResource Text.AIAssistant}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -4,7 +4,6 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading; using Avalonia.Threading;
namespace SourceGit.Views namespace SourceGit.Views
@ -17,12 +16,14 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
public AIAssistant(string repo, List<Models.Change> changes, Action<string> onDone) public AIAssistant(Models.OpenAIService service, string repo, List<Models.Change> changes, Action<string> onDone)
{ {
_service = service;
_repo = repo; _repo = repo;
_changes = changes; _changes = changes;
_onDone = onDone; _onDone = onDone;
_cancel = new CancellationTokenSource(); _cancel = new CancellationTokenSource();
InitializeComponent(); InitializeComponent();
} }
@ -35,7 +36,7 @@ namespace SourceGit.Views
Task.Run(() => Task.Run(() =>
{ {
var message = new Commands.GenerateCommitMessage(_repo, _changes, _cancel.Token, SetDescription).Result(); var message = new Commands.GenerateCommitMessage(_service, _repo, _changes, _cancel.Token, SetDescription).Result();
if (_cancel.IsCancellationRequested) if (_cancel.IsCancellationRequested)
return; return;
@ -53,16 +54,12 @@ namespace SourceGit.Views
_cancel.Cancel(); _cancel.Cancel();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void SetDescription(string message) private void SetDescription(string message)
{ {
Dispatcher.UIThread.Invoke(() => ProgressMessage.Text = message); Dispatcher.UIThread.Invoke(() => ProgressMessage.Text = message);
} }
private Models.OpenAIService _service;
private string _repo; private string _repo;
private List<Models.Change> _changes; private List<Models.Change> _changes;
private Action<string> _onDone; private Action<string> _onDone;

View file

@ -13,30 +13,23 @@
WindowStartupLocation="CenterScreen"> WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Info}" Data="{StaticResource Icons.Info}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.About}" Text="{DynamicResource Text.About}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -21,11 +21,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void OnVisitAvaloniaUI(object _, PointerPressedEventArgs e) private void OnVisitAvaloniaUI(object _, PointerPressedEventArgs e)
{ {
Native.OS.OpenBrowser("https://www.avaloniaui.net/"); Native.OS.OpenBrowser("https://www.avaloniaui.net/");

View file

@ -13,30 +13,23 @@
WindowStartupLocation="CenterScreen"> WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Password}" Data="{StaticResource Icons.Password}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.Askpass}" Text="{DynamicResource Text.Askpass}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>
@ -49,10 +42,12 @@
<TextBox Margin="16" <TextBox Margin="16"
MinWidth="300" MinWidth="300"
Height="32" Height="32"
Focusable="True"
Text="{Binding Passphrase, Mode=TwoWay}" Text="{Binding Passphrase, Mode=TwoWay}"
PasswordChar="*" PasswordChar="*"
RevealPassword="{Binding ShowPassword, Mode=OneWay}" RevealPassword="{Binding ShowPassword, Mode=OneWay}"
HorizontalAlignment="Stretch"> HorizontalAlignment="Stretch"
v:AutoFocusBehaviour.IsEnabled="True">
<TextBox.InnerRightContent> <TextBox.InnerRightContent>
<ToggleButton Grid.Column="6" <ToggleButton Grid.Column="6"
Classes="toggle_untracked" Classes="toggle_untracked"

View file

@ -1,7 +1,6 @@
using System; using System;
using Avalonia; using Avalonia;
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -42,11 +41,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2) private void CloseWindow(object _1, RoutedEventArgs _2)
{ {
Console.Out.WriteLine("No passphrase entered."); Console.Out.WriteLine("No passphrase entered.");

View file

@ -16,30 +16,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.File.Ignore}" Data="{StaticResource Icons.File.Ignore}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.AssumeUnchanged}" Text="{DynamicResource Text.AssumeUnchanged}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,5 +1,4 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -11,11 +10,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void OnRemoveButtonClicked(object sender, RoutedEventArgs e) private void OnRemoveButtonClicked(object sender, RoutedEventArgs e)
{ {
if (DataContext is ViewModels.AssumeUnchangedManager vm && sender is Button button) if (DataContext is ViewModels.AssumeUnchangedManager vm && sender is Button button)

View file

@ -19,29 +19,26 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border --> <!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="4" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
DoubleTapped="MaximizeOrRestoreWindow" DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) --> <Path Width="12" Height="12"
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}"> Margin="10,0,0,0"
<v:CaptionButtonsMacOS/> HorizontalAlignment="Left"
</Border> Data="{StaticResource Icons.Blame}"
IsVisible="{OnPlatform True, macOS=False}"/>
<!-- Icon --> <TextBlock Classes="bold"
<Path Grid.Column="1" Margin="8,0,0,0" Width="12" Height="12" Data="{StaticResource Icons.Blame}"/> Text="{DynamicResource Text.Blame}"
HorizontalAlignment="Center" VerticalAlignment="Center"
<!-- Title --> IsHitTestVisible="False"/>
<TextBlock Grid.Column="2" Margin="8,0,0,0" Text="{DynamicResource Text.Blame}" FontWeight="Bold" IsHitTestVisible="False" VerticalAlignment="Center"/>
<!-- Caption Buttons (Windows/Linux) --> <!-- Caption Buttons (Windows/Linux) -->
<Border Grid.Column="3" IsVisible="{OnPlatform True, macOS=False}"> <v:CaptionButtons HorizontalAlignment="Right" IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtons/>
</Border>
</Grid> </Grid>
<!-- File --> <!-- File -->

View file

@ -435,24 +435,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void MaximizeOrRestoreWindow(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
protected override void OnClosed(EventArgs e) protected override void OnClosed(EventArgs e)
{ {
base.OnClosed(e); base.OnClosed(e);

View file

@ -21,29 +21,26 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border --> <!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="4" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
DoubleTapped="MaximizeOrRestoreWindow" DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) --> <Path Width="12" Height="12"
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}"> Margin="10,0,0,0"
<v:CaptionButtonsMacOS/> HorizontalAlignment="Left"
</Border> Data="{StaticResource Icons.Compare}"
IsVisible="{OnPlatform True, macOS=False}"/>
<!-- Icon --> <TextBlock Classes="bold"
<Path Grid.Column="1" Margin="8,0,0,0" Width="12" Height="12" Data="{StaticResource Icons.Compare}"/> Text="{DynamicResource Text.BranchCompare}"
HorizontalAlignment="Center" VerticalAlignment="Center"
<!-- Title --> IsHitTestVisible="False"/>
<TextBlock Grid.Column="2" Margin="8,0,0,0" Text="{DynamicResource Text.BranchCompare}" FontWeight="Bold" IsHitTestVisible="False" VerticalAlignment="Center"/>
<!-- Caption Buttons (Windows/Linux) --> <!-- Caption Buttons (Windows/Linux) -->
<Border Grid.Column="3" IsVisible="{OnPlatform True, macOS=False}"> <v:CaptionButtons HorizontalAlignment="Right" IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtons/>
</Border>
</Grid> </Grid>
<!-- Compare Targets --> <!-- Compare Targets -->

View file

@ -10,24 +10,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void MaximizeOrRestoreWindow(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e) private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e)
{ {
if (DataContext is ViewModels.BranchCompare vm && sender is ChangeCollectionView view) if (DataContext is ViewModels.BranchCompare vm && sender is ChangeCollectionView view)

View file

@ -1,159 +0,0 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.CaptionButtonsMacOS"
x:Name="ThisControl">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<Color x:Key="Color.MacOS.Close">#FFED6A5E</Color>
<Color x:Key="Color.MacOS.CloseFG">#FF69110A</Color>
<Color x:Key="Color.MacOS.ClosePressed">#FFB24F46</Color>
<Color x:Key="Color.MacOS.ClosePressedFG">#FF2E0402</Color>
<Color x:Key="Color.MacOS.Minimize">#FFF4BF4F</Color>
<Color x:Key="Color.MacOS.MinimizeFG">#FF8F591D</Color>
<Color x:Key="Color.MacOS.MinimizePressed">#FFB78F3A</Color>
<Color x:Key="Color.MacOS.MinimizePressedFG">#FF522A0A</Color>
<Color x:Key="Color.MacOS.Maximize">#FF61C554</Color>
<Color x:Key="Color.MacOS.MaximizeFG">#FF296017</Color>
<Color x:Key="Color.MacOS.MaximizePressed">#FF48943F</Color>
<Color x:Key="Color.MacOS.MaximizePressedFG">#FF102F07</Color>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<Color x:Key="Color.MacOS.Close">#FFED6A5E</Color>
<Color x:Key="Color.MacOS.CloseFG">#FF8C1A10</Color>
<Color x:Key="Color.MacOS.ClosePressed">#FFF09389</Color>
<Color x:Key="Color.MacOS.ClosePressedFG">#FF69120A</Color>
<Color x:Key="Color.MacOS.Minimize">#FFF4BF4F</Color>
<Color x:Key="Color.MacOS.MinimizeFG">#FF8F591D</Color>
<Color x:Key="Color.MacOS.MinimizePressed">#FFFBEB74</Color>
<Color x:Key="Color.MacOS.MinimizePressedFG">#FF705F1B</Color>
<Color x:Key="Color.MacOS.Maximize">#FF61C554</Color>
<Color x:Key="Color.MacOS.MaximizeFG">#FF296017</Color>
<Color x:Key="Color.MacOS.MaximizePressed">#FF86F37F</Color>
<Color x:Key="Color.MacOS.MaximizePressedFG">#FF2C681A</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<SolidColorBrush x:Key="Brush.MacOS.Close" Color="{DynamicResource Color.MacOS.Close}"/>
<SolidColorBrush x:Key="Brush.MacOS.CloseFG" Color="{DynamicResource Color.MacOS.CloseFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.ClosePressed" Color="{DynamicResource Color.MacOS.ClosePressed}"/>
<SolidColorBrush x:Key="Brush.MacOS.ClosePressedFG" Color="{DynamicResource Color.MacOS.ClosePressedFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.Minimize" Color="{DynamicResource Color.MacOS.Minimize}"/>
<SolidColorBrush x:Key="Brush.MacOS.MinimizeFG" Color="{DynamicResource Color.MacOS.MinimizeFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.MinimizePressed" Color="{DynamicResource Color.MacOS.MinimizePressed}"/>
<SolidColorBrush x:Key="Brush.MacOS.MinimizePressedFG" Color="{DynamicResource Color.MacOS.MinimizePressedFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.Maximize" Color="{DynamicResource Color.MacOS.Maximize}"/>
<SolidColorBrush x:Key="Brush.MacOS.MaximizeFG" Color="{DynamicResource Color.MacOS.MaximizeFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.MaximizePressed" Color="{DynamicResource Color.MacOS.MaximizePressed}"/>
<SolidColorBrush x:Key="Brush.MacOS.MaximizePressedFG" Color="{DynamicResource Color.MacOS.MaximizePressedFG}"/>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="Width" Value="24"/>
<Setter Property="Height" Value="24"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style Selector="Button /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="Button>Grid>Ellipse">
<Setter Property="Width" Value="14"/>
<Setter Property="Height" Value="14"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="StrokeThickness" Value=".5"/>
<Setter Property="Stroke" Value="#40000000"/>
</Style>
<Style Selector="Button.close>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.Close}"/>
</Style>
<Style Selector="Button.minimize>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.Minimize}"/>
</Style>
<Style Selector="Button.maximize>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.Maximize}"/>
</Style>
<Style Selector="Button.close:pressed>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.ClosePressed}"/>
</Style>
<Style Selector="Button.minimize:pressed>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MinimizePressed}"/>
</Style>
<Style Selector="Button.maximize:pressed>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MaximizePressed}"/>
</Style>
<Style Selector="Button>Grid>Path">
<Setter Property="Stretch" Value="Fill"/>
<Setter Property="Fill" Value="Black"/>
<Setter Property="IsVisible" Value="False"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style Selector="Button.close>Grid>Path">
<Setter Property="Width" Value="6"/>
<Setter Property="Height" Value="6"/>
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.CloseFG}"/>
<Setter Property="Data" Value="{StaticResource Icons.MacOS.Close}"/>
</Style>
<Style Selector="Button.minimize>Grid>Path">
<Setter Property="Width" Value="8"/>
<Setter Property="Height" Value="2"/>
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MinimizeFG}"/>
<Setter Property="Data" Value="{StaticResource Icons.MacOS.Minimize}"/>
</Style>
<Style Selector="Button.maximize>Grid>Path">
<Setter Property="Width" Value="6"/>
<Setter Property="Height" Value="6"/>
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MaximizeFG}"/>
<Setter Property="Data" Value="{StaticResource Icons.MacOS.Maximize}"/>
</Style>
<Style Selector="Button.close:pressed>Grid>Path">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.ClosePressedFG}"/>
</Style>
<Style Selector="Button.minimize:pressed>Grid>Path">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MinimizePressedFG}"/>
</Style>
<Style Selector="Button.maximize:pressed>Grid>Path">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MaximizePressedFG}"/>
</Style>
<Style Selector="Grid.caption_button_box:pointerover>StackPanel>Button>Grid>Path">
<Setter Property="IsVisible" Value="True"/>
</Style>
</UserControl.Styles>
<Grid Classes="caption_button_box">
<StackPanel Orientation="Horizontal" Margin="8,0,0,0">
<Button Classes="close" Click="CloseWindow">
<Grid>
<Ellipse/>
<Path/>
</Grid>
</Button>
<Button Classes="minimize" Click="MinimizeWindow" IsVisible="{Binding !#ThisControl.IsCloseButtonOnly}">
<Grid>
<Ellipse/>
<Path/>
</Grid>
</Button>
<Button Classes="maximize" Click="MaximizeOrRestoreWindow" IsVisible="{Binding !#ThisControl.IsCloseButtonOnly}">
<Grid>
<Ellipse/>
<Path/>
</Grid>
</Button>
</StackPanel>
</Grid>
</UserControl>

View file

@ -1,49 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
namespace SourceGit.Views
{
public partial class CaptionButtonsMacOS : UserControl
{
public static readonly StyledProperty<bool> IsCloseButtonOnlyProperty =
AvaloniaProperty.Register<CaptionButtonsMacOS, bool>(nameof(IsCloseButtonOnly));
public bool IsCloseButtonOnly
{
get => GetValue(IsCloseButtonOnlyProperty);
set => SetValue(IsCloseButtonOnlyProperty, value);
}
public CaptionButtonsMacOS()
{
InitializeComponent();
}
private void MinimizeWindow(object _, RoutedEventArgs e)
{
var window = this.FindAncestorOfType<Window>();
if (window != null)
window.WindowState = WindowState.Minimized;
e.Handled = true;
}
private void MaximizeOrRestoreWindow(object _, RoutedEventArgs e)
{
var window = this.FindAncestorOfType<Window>();
if (window != null)
window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
e.Handled = true;
}
private void CloseWindow(object _, RoutedEventArgs e)
{
var window = this.FindAncestorOfType<Window>();
window?.Close();
e.Handled = true;
}
}
}

View file

@ -32,14 +32,35 @@ namespace SourceGit.Views
Classes.Add("custom_window_frame"); Classes.Add("custom_window_frame");
} }
} }
else else if (OperatingSystem.IsWindows())
{ {
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome; ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome;
ExtendClientAreaToDecorationsHint = true; ExtendClientAreaToDecorationsHint = true;
Classes.Add("fix_maximized_padding");
if (OperatingSystem.IsWindows())
Classes.Add("fix_maximized_padding");
} }
else
{
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome;
ExtendClientAreaToDecorationsHint = true;
}
}
public void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
public void MaximizeOrRestoreWindow(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
} }
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)

View file

@ -71,6 +71,33 @@
<Button Classes="icon_button" Width="24" Cursor="Hand" Click="OnOpenWebLink" IsVisible="{Binding #ThisControl.WebLinks, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}" ToolTip.Tip="{DynamicResource Text.CommitDetail.Info.WebLinks}"> <Button Classes="icon_button" Width="24" Cursor="Hand" Click="OnOpenWebLink" IsVisible="{Binding #ThisControl.WebLinks, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}" ToolTip.Tip="{DynamicResource Text.CommitDetail.Info.WebLinks}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Link}" Fill="{DynamicResource Brush.Link}"/> <Path Width="12" Height="12" Data="{StaticResource Icons.Link}" Fill="{DynamicResource Brush.Link}"/>
</Button> </Button>
<ContentControl Content="{Binding #ThisControl.SignInfo}">
<ContentControl.Styles>
<Style Selector="ToolTip">
<Setter Property="MaxWidth" Value="800"/>
</Style>
</ContentControl.Styles>
<ContentControl.DataTemplates>
<DataTemplate DataType="m:CommitSignInfo">
<Border Width="24" Background="Transparent">
<ToolTip.Tip>
<StackPanel Orientation="Vertical">
<TextBlock Margin="0,0,0,12" Text="{Binding ToolTip}"/>
<Grid ColumnDefinitions="Auto,8,Auto" RowDefinitions="Auto,Auto">
<TextBlock Grid.Row="0" Grid.Column="0" Text="Signer:" IsVisible="{Binding HasSigner}"/>
<TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding Signer}" IsVisible="{Binding HasSigner}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Key:"/>
<TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding Key}"/>
</Grid>
</StackPanel>
</ToolTip.Tip>
<Path Width="14" Height="14" Data="{StaticResource Icons.Verified}" Fill="{Binding Brush}"/>
</Border>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</StackPanel> </StackPanel>
<!-- PARENTS --> <!-- PARENTS -->

View file

@ -17,6 +17,15 @@ namespace SourceGit.Views
set => SetValue(MessageProperty, value); set => SetValue(MessageProperty, value);
} }
public static readonly StyledProperty<Models.CommitSignInfo> SignInfoProperty =
AvaloniaProperty.Register<CommitBaseInfo, Models.CommitSignInfo>(nameof(SignInfo));
public Models.CommitSignInfo SignInfo
{
get => GetValue(SignInfoProperty);
set => SetValue(SignInfoProperty, value);
}
public static readonly StyledProperty<bool> SupportsContainsInProperty = public static readonly StyledProperty<bool> SupportsContainsInProperty =
AvaloniaProperty.Register<CommitBaseInfo, bool>(nameof(SupportsContainsIn)); AvaloniaProperty.Register<CommitBaseInfo, bool>(nameof(SupportsContainsIn));

View file

@ -21,6 +21,7 @@
<!-- Base Information --> <!-- Base Information -->
<v:CommitBaseInfo Content="{Binding Commit}" <v:CommitBaseInfo Content="{Binding Commit}"
Message="{Binding FullMessage}" Message="{Binding FullMessage}"
SignInfo="{Binding SignInfo}"
SupportsContainsIn="True" SupportsContainsIn="True"
WebLinks="{Binding WebLinks}" WebLinks="{Binding WebLinks}"
IssueTrackerRules="{Binding IssueTrackerRules}"/> IssueTrackerRules="{Binding IssueTrackerRules}"/>

View file

@ -2,10 +2,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels" xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views" xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.ConfigureWorkspace" x:Class="SourceGit.Views.ConfigureWorkspace"
x:DataType="vm:ConfigureWorkspace" x:DataType="vm:ConfigureWorkspace"
@ -17,30 +15,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto" MinWidth="494"> <Grid RowDefinitions="Auto,Auto" MinWidth="494">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Data="{StaticResource Icons.Workspace}"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Workspace}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.ConfigureWorkspace}" Text="{DynamicResource Text.ConfigureWorkspace}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,5 +1,4 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input;
namespace SourceGit.Views namespace SourceGit.Views
{ {
@ -15,10 +14,5 @@ namespace SourceGit.Views
ViewModels.Preference.Instance.Save(); ViewModels.Preference.Instance.Save();
base.OnClosing(e); base.OnClosing(e);
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
} }
} }

View file

@ -15,30 +15,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,Auto"> <Grid RowDefinitions="Auto,Auto,Auto">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Data="{StaticResource Icons.Error}"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Error}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.Warn}" Text="{DynamicResource Text.Warn}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,4 +1,3 @@
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -10,11 +9,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void Sure(object _1, RoutedEventArgs _2) private void Sure(object _1, RoutedEventArgs _2)
{ {
if (DataContext is ViewModels.ConfirmCommitWithoutFiles vm) if (DataContext is ViewModels.ConfirmCommitWithoutFiles vm)

View file

@ -13,30 +13,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Info}" Data="{StaticResource Icons.Info}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="Restart Required" Text="Restart Required"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,8 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -14,11 +12,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2) private void CloseWindow(object _1, RoutedEventArgs _2)
{ {
Console.Out.WriteLine("No passphrase entered."); Console.Out.WriteLine("No passphrase entered.");

View file

@ -5,7 +5,6 @@
xmlns:m="using:SourceGit.Models" xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels" xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views" xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.ConventionalCommitMessageBuilder" x:Class="SourceGit.Views.ConventionalCommitMessageBuilder"
x:DataType="vm:ConventionalCommitMessageBuilder" x:DataType="vm:ConventionalCommitMessageBuilder"
@ -18,30 +17,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,Auto"> <Grid RowDefinitions="Auto,Auto,Auto">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Data="{StaticResource Icons.CommitMessageGenerator}"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.CommitMessageGenerator}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.ConventionalCommit}" Text="{DynamicResource Text.ConventionalCommit}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,4 +1,3 @@
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -10,11 +9,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void OnApplyClicked(object _, RoutedEventArgs e) private void OnApplyClicked(object _, RoutedEventArgs e)
{ {
if (DataContext is ViewModels.ConventionalCommitMessageBuilder builder) if (DataContext is ViewModels.ConventionalCommitMessageBuilder builder)

View file

@ -0,0 +1,19 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.ExecuteCustomAction"
x:DataType="vm:ExecuteCustomAction">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.ExecuteCustomAction}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0">
<TextBlock Text="{DynamicResource Text.ExecuteCustomAction.Name}"/>
<Path Width="14" Height="14" Margin="8,0,0,0" Data="{StaticResource Icons.Action}"/>
<TextBlock Text="{Binding CustomAction.Name}" Margin="8,0,0,0"/>
</StackPanel>
</StackPanel>
</UserControl>

View file

@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace SourceGit.Views
{
public partial class ExecuteCustomAction : UserControl
{
public ExecuteCustomAction()
{
InitializeComponent();
}
}
}

21
src/Views/FetchInto.axaml Normal file
View file

@ -0,0 +1,21 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.FetchInto"
x:DataType="vm:FetchInto">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.Fetch.Title}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0">
<Path Width="14" Height="14" Data="{StaticResource Icons.Branch}"/>
<TextBlock Text="{Binding Upstream.FriendlyName}" Margin="8,0,0,0"/>
<TextBlock Text="→" Margin="8,0"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Branch}"/>
<TextBlock Text="{Binding Local.Name}" Margin="8,0,0,0"/>
</StackPanel>
</StackPanel>
</UserControl>

View file

@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace SourceGit.Views
{
public partial class FetchInto : UserControl
{
public FetchInto()
{
InitializeComponent();
}
}
}

View file

@ -20,29 +20,26 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border --> <!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="4" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
DoubleTapped="MaximizeOrRestoreWindow" DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) --> <Path Width="12" Height="12"
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}"> Margin="10,0,0,0"
<v:CaptionButtonsMacOS/> HorizontalAlignment="Left"
</Border> Data="{StaticResource Icons.Histories}"
IsVisible="{OnPlatform True, macOS=False}"/>
<!-- Icon --> <TextBlock Classes="bold"
<Path Grid.Column="1" Margin="8,0,0,0" Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.Histories}"/> Text="{DynamicResource Text.FileHistory}"
HorizontalAlignment="Center" VerticalAlignment="Center"
<!-- Title --> IsHitTestVisible="False"/>
<TextBlock Grid.Column="2" Margin="4,0,0,0" Text="{DynamicResource Text.FileHistory}" FontWeight="Bold" IsHitTestVisible="False" VerticalAlignment="Center"/>
<!-- Caption Buttons (Windows/Linux) --> <!-- Caption Buttons (Windows/Linux) -->
<Border Grid.Column="3" IsVisible="{OnPlatform True, macOS=False}"> <v:CaptionButtons HorizontalAlignment="Right" IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtons/>
</Border>
</Grid> </Grid>
<!-- Body --> <!-- Body -->

View file

@ -11,24 +11,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void MaximizeOrRestoreWindow(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
private void OnPressCommitSHA(object sender, PointerPressedEventArgs e) private void OnPressCommitSHA(object sender, PointerPressedEventArgs e)
{ {
if (sender is TextBlock { DataContext: Models.Commit commit } && if (sender is TextBlock { DataContext: Models.Commit commit } &&

View file

@ -12,15 +12,15 @@
x:Name="ThisControl"> x:Name="ThisControl">
<v:LayoutableGrid UseHorizontal="{Binding Source={x:Static vm:Preference.Instance}, Path=UseTwoColumnsLayoutInHistories}"> <v:LayoutableGrid UseHorizontal="{Binding Source={x:Static vm:Preference.Instance}, Path=UseTwoColumnsLayoutInHistories}">
<v:LayoutableGrid.RowDefinitions> <v:LayoutableGrid.RowDefinitions>
<RowDefinition Height="{Binding TopArea, Mode=TwoWay}"/> <RowDefinition Height="{Binding TopArea, Mode=TwoWay}" MinHeight="100"/>
<RowDefinition Height="3"/> <RowDefinition Height="3"/>
<RowDefinition Height="{Binding BottomArea, Mode=TwoWay}"/> <RowDefinition Height="{Binding BottomArea, Mode=TwoWay}" MinHeight="200"/>
</v:LayoutableGrid.RowDefinitions> </v:LayoutableGrid.RowDefinitions>
<v:LayoutableGrid.ColumnDefinitions> <v:LayoutableGrid.ColumnDefinitions>
<ColumnDefinition Width="{Binding LeftArea, Mode=TwoWay}"/> <ColumnDefinition Width="{Binding LeftArea, Mode=TwoWay}" MinWidth="100"/>
<ColumnDefinition Width="3"/> <ColumnDefinition Width="3"/>
<ColumnDefinition Width="{Binding RightArea, Mode=TwoWay}"/> <ColumnDefinition Width="{Binding RightArea, Mode=TwoWay}" MinWidth="100"/>
</v:LayoutableGrid.ColumnDefinitions> </v:LayoutableGrid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"> <Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">

View file

@ -15,30 +15,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Hotkeys}" Data="{StaticResource Icons.Hotkeys}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.Hotkeys}" Text="{DynamicResource Text.Hotkeys}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,5 +1,3 @@
using Avalonia.Input;
namespace SourceGit.Views namespace SourceGit.Views
{ {
public partial class Hotkeys : ChromelessWindow public partial class Hotkeys : ChromelessWindow
@ -8,10 +6,5 @@ namespace SourceGit.Views
{ {
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
} }
} }

View file

@ -16,30 +16,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,*,Auto"> <Grid RowDefinitions="Auto,Auto,*,Auto">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.InteractiveRebase}" Data="{StaticResource Icons.InteractiveRebase}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.InteractiveRebase}" Text="{DynamicResource Text.InteractiveRebase}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -81,11 +81,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2) private void CloseWindow(object _1, RoutedEventArgs _2)
{ {
Close(); Close();

View file

@ -16,30 +16,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,*"> <Grid RowDefinitions="Auto,Auto,*">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Lock}" Data="{StaticResource Icons.Lock}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.GitLFS.Locks.Title}" Text="{DynamicResource Text.GitLFS.Locks.Title}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,5 +1,4 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -11,11 +10,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void OnUnlockButtonClicked(object sender, RoutedEventArgs e) private void OnUnlockButtonClicked(object sender, RoutedEventArgs e)
{ {
if (DataContext is ViewModels.LFSLocks vm && sender is Button button) if (DataContext is ViewModels.LFSLocks vm && sender is Button button)

View file

@ -25,13 +25,11 @@
<Border Grid.Column="0" Grid.ColumnSpan="4" <Border Grid.Column="0" Grid.ColumnSpan="4"
Background="{DynamicResource Brush.TitleBar}" Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
DoubleTapped="OnTitleBarDoubleTapped" DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) --> <!-- Caption Buttons (macOS) -->
<Border Grid.Column="0" VerticalAlignment="Stretch" Margin="2,0,8,3" IsVisible="{OnPlatform False, macOS=True}"> <Border Grid.Column="0" Width="72" IsVisible="{Binding #ThisControl.HasLeftCaptionButton}"/>
<v:CaptionButtonsMacOS VerticalAlignment="Bottom"/>
</Border>
<!-- Menu (Windows/Linux) --> <!-- Menu (Windows/Linux) -->
<Button Grid.Column="0" Classes="icon_button" VerticalAlignment="Bottom" Margin="6,0,2,3" IsVisible="{OnPlatform True, macOS=False}"> <Button Grid.Column="0" Classes="icon_button" VerticalAlignment="Bottom" Margin="6,0,2,3" IsVisible="{OnPlatform True, macOS=False}">

View file

@ -4,6 +4,7 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Platform;
using Avalonia.VisualTree; using Avalonia.VisualTree;
namespace SourceGit.Views namespace SourceGit.Views
@ -19,6 +20,15 @@ namespace SourceGit.Views
set => SetValue(CaptionHeightProperty, value); set => SetValue(CaptionHeightProperty, value);
} }
public static readonly StyledProperty<bool> HasLeftCaptionButtonProperty =
AvaloniaProperty.Register<Launcher, bool>(nameof(HasLeftCaptionButton));
public bool HasLeftCaptionButton
{
get => GetValue(HasLeftCaptionButtonProperty);
set => SetValue(HasLeftCaptionButtonProperty, value);
}
public bool IsRightCaptionButtonsVisible public bool IsRightCaptionButtonsVisible
{ {
get get
@ -38,10 +48,21 @@ namespace SourceGit.Views
Height = layout.LauncherHeight; Height = layout.LauncherHeight;
} }
if (UseSystemWindowFrame) if (OperatingSystem.IsMacOS())
{
HasLeftCaptionButton = true;
CaptionHeight = new GridLength(34);
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome |
ExtendClientAreaChromeHints.OSXThickTitleBar;
}
else if (UseSystemWindowFrame)
{
CaptionHeight = new GridLength(30); CaptionHeight = new GridLength(30);
}
else else
{
CaptionHeight = new GridLength(38); CaptionHeight = new GridLength(38);
}
InitializeComponent(); InitializeComponent();
} }
@ -55,8 +76,8 @@ namespace SourceGit.Views
{ {
base.OnOpened(e); base.OnOpened(e);
var layout = ViewModels.Preference.Instance.Layout; var state = ViewModels.Preference.Instance.Layout.LauncherWindowState;
if (layout.LauncherWindowState == WindowState.Maximized) if (state == WindowState.Maximized || state == WindowState.FullScreen)
WindowState = WindowState.Maximized; WindowState = WindowState.Maximized;
} }
@ -67,12 +88,11 @@ namespace SourceGit.Views
if (change.Property == WindowStateProperty) if (change.Property == WindowStateProperty)
{ {
var state = (WindowState)change.NewValue!; var state = (WindowState)change.NewValue!;
if (OperatingSystem.IsLinux() && UseSystemWindowFrame) if (!OperatingSystem.IsMacOS() && !UseSystemWindowFrame)
CaptionHeight = new GridLength(30); CaptionHeight = new GridLength(state == WindowState.Maximized ? 30 : 38);
else if (state == WindowState.Maximized)
CaptionHeight = new GridLength(OperatingSystem.IsMacOS() ? 34 : 30); if (OperatingSystem.IsMacOS())
else HasLeftCaptionButton = state != WindowState.FullScreen;
CaptionHeight = new GridLength(38);
ViewModels.Preference.Instance.Layout.LauncherWindowState = state; ViewModels.Preference.Instance.Layout.LauncherWindowState = state;
} }
@ -225,24 +245,6 @@ namespace SourceGit.Views
base.OnClosing(e); base.OnClosing(e);
} }
private void OnTitleBarDoubleTapped(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
private void OnOpenWorkspaceMenu(object sender, RoutedEventArgs e) private void OnOpenWorkspaceMenu(object sender, RoutedEventArgs e)
{ {
if (sender is Button btn && DataContext is ViewModels.Launcher launcher) if (sender is Button btn && DataContext is ViewModels.Launcher launcher)

View file

@ -60,13 +60,19 @@
HorizontalAlignment="Right" HorizontalAlignment="Right"
IsVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}"> IsVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}">
<Button Classes="flat primary" <Button Classes="flat primary"
Width="80" Width="80" Height="28"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Content="{DynamicResource Text.Sure}" Content="{DynamicResource Text.Sure}"
Click="OnPopupSure" Click="OnPopupSure"
HotKey="Enter"/> HotKey="Enter"/>
<Button Classes="flat" <Button Classes="flat"
Width="80" Width="80" Height="28"
Margin="8,0,0,0" Margin="8,0,0,0"
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Content="{DynamicResource Text.Cancel}" Content="{DynamicResource Text.Cancel}"
Click="OnPopupCancel"/> Click="OnPopupCancel"/>
</StackPanel> </StackPanel>

View file

@ -17,30 +17,23 @@
WindowStartupLocation="CenterScreen"> WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,Auto" MinWidth="600"> <Grid RowDefinitions="Auto,Auto" MinWidth="600">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Data="{StaticResource Icons.Settings}"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Settings}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.Preference}" Text="{DynamicResource Text.Preference}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>
@ -412,7 +405,7 @@
<TextBlock Classes="bold" Margin="4,0,0,0" Text="{DynamicResource Text.Preference.DiffMerge}"/> <TextBlock Classes="bold" Margin="4,0,0,0" Text="{DynamicResource Text.Preference.DiffMerge}"/>
</StackPanel> </StackPanel>
<Rectangle Margin="0,8" Fill="{DynamicResource Brush.Border2}" Height=".6" HorizontalAlignment="Stretch"/> <Rectangle Margin="0,8" Fill="{DynamicResource Brush.Border2}" Height=".6" HorizontalAlignment="Stretch"/>
<Grid Margin="8,0,0,0" RowDefinitions="32,Auto"> <Grid Margin="8,0,0,8" RowDefinitions="32,Auto">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/> <ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
@ -459,82 +452,117 @@
</TextBox.InnerRightContent> </TextBox.InnerRightContent>
</TextBox> </TextBox>
</Grid> </Grid>
<StackPanel Orientation="Horizontal" Margin="0,24,0,0">
<Path Width="12" Height="12" Data="{StaticResource Icons.AIAssist}"/>
<TextBlock Classes="bold" Margin="4,0,0,0" Text="{DynamicResource Text.Preference.AI}"/>
</StackPanel>
<Rectangle Margin="0,8" Fill="{DynamicResource Brush.Border2}" Height=".6" HorizontalAlignment="Stretch"/>
<Grid Margin="8,0,0,0" RowDefinitions="32,32,32,32,Auto,Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.AI.Server}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<TextBox Grid.Row="0" Grid.Column="1"
Height="28"
CornerRadius="3"
Text="{Binding OpenAIServer, Mode=TwoWay}"/>
<TextBlock Grid.Row="1" Grid.Column="0"
Text="{DynamicResource Text.Preference.AI.Model}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<TextBox Grid.Row="1" Grid.Column="1"
Height="28"
CornerRadius="3"
Text="{Binding OpenAIModel, Mode=TwoWay}"/>
<TextBlock Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Preference.AI.ApiKey}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<TextBox Grid.Row="2" Grid.Column="1"
Height="28"
CornerRadius="3"
PasswordChar="*"
Text="{Binding OpenAIApiKey, Mode=TwoWay}"/>
<ToggleButton Grid.Row="3" Grid.Column="1" Classes="group_expander" x:Name="OpenAIAdvancedOptions" HorizontalAlignment="Right">
<TextBlock Margin="0" Text="{DynamicResource Text.Preference.Advanced}"/>
</ToggleButton>
<TextBlock Grid.Row="4" Grid.Column="0"
Text="{DynamicResource Text.Preference.AI.AnalyzeDiffPrompt}"
HorizontalAlignment="Right"
Margin="0,0,16,0"
IsVisible="{Binding #OpenAIAdvancedOptions.IsChecked}"/>
<TextBox Grid.Row="4" Grid.Column="1"
Height="120"
Margin="0,2"
CornerRadius="3"
VerticalContentAlignment="Top"
Text="{Binding OpenAIAnalyzeDiffPrompt, Mode=TwoWay}"
AcceptsReturn="true"
TextWrapping="Wrap"
IsVisible="{Binding #OpenAIAdvancedOptions.IsChecked}"/>
<TextBlock Grid.Row="5" Grid.Column="0"
Text="{DynamicResource Text.Preference.AI.GenerateSubjectPrompt}"
HorizontalAlignment="Right"
Margin="0,0,16,0"
IsVisible="{Binding #OpenAIAdvancedOptions.IsChecked}"/>
<TextBox Grid.Row="5" Grid.Column="1"
Height="120"
Margin="0,2"
CornerRadius="3"
VerticalContentAlignment="Top"
Text="{Binding OpenAIGenerateSubjectPrompt, Mode=TwoWay}"
AcceptsReturn="true"
TextWrapping="Wrap"
IsVisible="{Binding #OpenAIAdvancedOptions.IsChecked}"/>
</Grid>
</StackPanel> </StackPanel>
</TabItem> </TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.AI}"/>
</TabItem.Header>
<Grid ColumnDefinitions="200,*" Margin="0,8,0,16" MinHeight="400">
<Border Grid.Column="0"
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
Background="{DynamicResource Brush.Contents}">
<Grid RowDefinitions="*,1,Auto">
<ListBox Grid.Row="0"
Background="Transparent"
ItemsSource="{Binding OpenAIServices}"
SelectedItem="{Binding #ThisControl.SelectedOpenAIService, Mode=TwoWay}"
SelectionMode="Single">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Height" Value="26"/>
<Setter Property="Padding" Value="4,2"/>
</Style>
</ListBox.Styles>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate DataType="m:OpenAIService">
<Grid ColumnDefinitions="Auto,*">
<Path Grid.Column="0" Width="14" Height="14" Data="{StaticResource Icons.AIAssist}"/>
<TextBlock Grid.Column="1" Text="{Binding Name}" Margin="8,0" TextTrimming="CharacterEllipsis"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="{DynamicResource Brush.ToolBar}">
<Button Classes="icon_button" Click="OnAddOpenAIService">
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
</Button>
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
<Button Classes="icon_button" Click="OnRemoveSelectedOpenAIService">
<Path Width="14" Height="14" Data="{StaticResource Icons.Window.Minimize}"/>
</Button>
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
</StackPanel>
</Grid>
</Border>
<ContentControl Grid.Column="1" Margin="16,0,0,0">
<ContentControl.Content>
<Binding Path="#ThisControl.SelectedOpenAIService">
<Binding.TargetNullValue>
<Path Width="64" Height="64"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{DynamicResource Brush.FG2}"
Data="{StaticResource Icons.Empty}"/>
</Binding.TargetNullValue>
</Binding>
</ContentControl.Content>
<ContentControl.DataTemplates>
<DataTemplate DataType="m:OpenAIService">
<StackPanel Orientation="Vertical" MaxWidth="680">
<TextBlock Text="{DynamicResource Text.Preference.AI.Name}"/>
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Name, Mode=TwoWay}"/>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preference.AI.Server}"/>
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Server, Mode=TwoWay}"/>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preference.AI.Model}"/>
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Model, Mode=TwoWay}"/>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preference.AI.ApiKey}"/>
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding ApiKey, Mode=TwoWay}" PasswordChar="*"/>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preference.AI.AnalyzeDiffPrompt}"/>
<TextBox Height="120"
Margin="0,4,0,0"
CornerRadius="3"
VerticalContentAlignment="Top"
Text="{Binding AnalyzeDiffPrompt, Mode=TwoWay}"
AcceptsReturn="true"
TextWrapping="Wrap"/>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preference.AI.GenerateSubjectPrompt}"/>
<TextBox Height="120"
Margin="0,4,0,0"
CornerRadius="3"
VerticalContentAlignment="Top"
Text="{Binding GenerateSubjectPrompt, Mode=TwoWay}"
AcceptsReturn="true"
TextWrapping="Wrap"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Grid>
</TabItem>
</TabControl> </TabControl>
</Border> </Border>
</Grid> </Grid>

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
@ -74,6 +73,15 @@ namespace SourceGit.Views
set; set;
} }
public static readonly StyledProperty<Models.OpenAIService> SelectedOpenAIServiceProperty =
AvaloniaProperty.Register<Preference, Models.OpenAIService>(nameof(SelectedOpenAIService));
public Models.OpenAIService SelectedOpenAIService
{
get => GetValue(SelectedOpenAIServiceProperty);
set => SetValue(SelectedOpenAIServiceProperty, value);
}
public Preference() public Preference()
{ {
var pref = ViewModels.Preference.Instance; var pref = ViewModels.Preference.Instance;
@ -157,11 +165,6 @@ namespace SourceGit.Views
base.OnClosing(e); base.OnClosing(e);
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private async void SelectThemeOverrideFile(object _, RoutedEventArgs e) private async void SelectThemeOverrideFile(object _, RoutedEventArgs e)
{ {
var options = new FilePickerOpenOptions() var options = new FilePickerOpenOptions()
@ -312,5 +315,24 @@ namespace SourceGit.Views
e.Handled = true; e.Handled = true;
} }
private void OnAddOpenAIService(object sender, RoutedEventArgs e)
{
var service = new Models.OpenAIService() { Name = "Unnamed Service" };
ViewModels.Preference.Instance.OpenAIServices.Add(service);
SelectedOpenAIService = service;
e.Handled = true;
}
private void OnRemoveSelectedOpenAIService(object sender, RoutedEventArgs e)
{
if (SelectedOpenAIService == null)
return;
ViewModels.Preference.Instance.OpenAIServices.Remove(SelectedOpenAIService);
SelectedOpenAIService = null;
e.Handled = true;
}
} }
} }

View file

@ -5,6 +5,7 @@
xmlns:m="using:SourceGit.Models" xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels" xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views" xmlns:v="using:SourceGit.Views"
xmlns:ac="using:Avalonia.Controls.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.RepositoryConfigure" x:Class="SourceGit.Views.RepositoryConfigure"
x:DataType="vm:RepositoryConfigure" x:DataType="vm:RepositoryConfigure"
@ -16,30 +17,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto"> <Grid RowDefinitions="Auto,Auto">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Data="{StaticResource Icons.Settings}"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Settings}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.Configure}" Text="{DynamicResource Text.Configure}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>
@ -51,7 +45,7 @@
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.Git}"/> <TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.Git}"/>
</TabItem.Header> </TabItem.Header>
<Grid Margin="16,4,16,8" RowDefinitions="32,32,32,32,32,32,32,32,32" ColumnDefinitions="Auto,*"> <Grid Margin="16,4,16,8" RowDefinitions="32,32,32,32,32,32,32,32,32,32" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
@ -130,7 +124,11 @@
Content="{DynamicResource Text.Preference.GPG.TagEnabled}" Content="{DynamicResource Text.Preference.GPG.TagEnabled}"
IsChecked="{Binding GPGTagSigningEnabled, Mode=TwoWay}"/> IsChecked="{Binding GPGTagSigningEnabled, Mode=TwoWay}"/>
<StackPanel Grid.Row="8" Grid.Column="1" Orientation="Horizontal"> <CheckBox Grid.Row="8" Grid.Column="1"
Content="{DynamicResource Text.Configure.Git.EnablePruneOnFetch}"
IsChecked="{Binding EnablePruneOnFetch, Mode=TwoWay}"/>
<StackPanel Grid.Row="9" Grid.Column="1" Orientation="Horizontal">
<CheckBox x:Name="AutoFetchCheckBox" <CheckBox x:Name="AutoFetchCheckBox"
Content="{DynamicResource Text.Configure.Git.AutoFetch}" Content="{DynamicResource Text.Configure.Git.AutoFetch}"
IsChecked="{Binding EnableAutoFetch, Mode=TwoWay}"/> IsChecked="{Binding EnableAutoFetch, Mode=TwoWay}"/>
@ -340,6 +338,149 @@
</ContentControl> </ContentControl>
</Grid> </Grid>
</TabItem> </TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.CustomAction}"/>
</TabItem.Header>
<Grid ColumnDefinitions="200,*" Height="250" Margin="0,8,0,16">
<Border Grid.Column="0"
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
Background="{DynamicResource Brush.Contents}">
<Grid RowDefinitions="*,1,Auto">
<ListBox Grid.Row="0"
Background="Transparent"
ItemsSource="{Binding CustomActions}"
SelectedItem="{Binding SelectedCustomAction, Mode=TwoWay}"
SelectionMode="Single">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Height" Value="26"/>
<Setter Property="Padding" Value="4,2"/>
</Style>
</ListBox.Styles>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate DataType="m:CustomAction">
<Grid Margin="4,0" ColumnDefinitions="Auto,*">
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Action}" Fill="{DynamicResource Brush.FG1}"/>
<TextBlock Grid.Column="1" Text="{Binding Name}" Margin="6,0,0,0" TextTrimming="CharacterEllipsis"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="{DynamicResource Brush.ToolBar}">
<Button Classes="icon_button" Command="{Binding AddNewCustomAction}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
</Button>
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
<Button Classes="icon_button" Command="{Binding RemoveSelectedCustomAction}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Window.Minimize}"/>
</Button>
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
</StackPanel>
</Grid>
</Border>
<ContentControl Grid.Column="1" Margin="16,0,0,0">
<ContentControl.Content>
<Binding Path="SelectedCustomAction">
<Binding.TargetNullValue>
<Path Width="64" Height="64"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{DynamicResource Brush.FG2}"
Data="{StaticResource Icons.Empty}"/>
</Binding.TargetNullValue>
</Binding>
</ContentControl.Content>
<ContentControl.DataTemplates>
<DataTemplate DataType="m:CustomAction">
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource Text.Configure.CustomAction.Name}"/>
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Name, Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal" Margin="0,12,0,0">
<StackPanel.Resources>
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
</StackPanel.Resources>
<TextBlock Text="{DynamicResource Text.Configure.CustomAction.Scope}"/>
<RadioButton Content="{DynamicResource Text.Configure.CustomAction.Scope.Repository}"
GroupName="CustomActionScope"
Margin="8,0"
IsChecked="{Binding Scope, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:CustomActionScope.Repository}}"/>
<RadioButton Content="{DynamicResource Text.Configure.CustomAction.Scope.Commit}"
GroupName="CustomActionScope"
IsChecked="{Binding Scope, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:CustomActionScope.Commit}}"/>
</StackPanel>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CustomAction.Executable}"/>
<TextBox Margin="0,4,0,0" Height="28" CornerRadius="3" Text="{Binding Executable, Mode=TwoWay}">
<TextBox.InnerRightContent>
<Button Classes="icon_button" Width="30" Height="30" Click="SelectExecutableForCustomAction">
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
</Button>
</TextBox.InnerRightContent>
</TextBox>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CustomAction.Arguments}"/>
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Arguments, Mode=TwoWay}"/>
<TextBlock Margin="0,2,0,0" TextWrapping="Wrap" Text="{DynamicResource Text.Configure.CustomAction.Arguments.Tip}" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Grid>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.OpenAI}"/>
</TabItem.Header>
<Grid Margin="16,4,16,8" RowDefinitions="32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.Configure.OpenAI.Prefered}"/>
<ComboBox Grid.Row="0" Grid.Column="1"
Height="28" Padding="8,0"
VerticalAlignment="Center" HorizontalAlignment="Stretch"
ItemsSource="{Binding AvailableOpenAIServices}"
SelectedItem="{Binding PreferedOpenAIService, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
<Path Width="12" Height="12" Data="{StaticResource Icons.AIAssist}" Fill="{DynamicResource Brush.FG1}"/>
<TextBlock Margin="6,0,0,0" Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Grid.Row="1" Grid.Column="1"
Margin="0,6,0,0"
Text="{DynamicResource Text.Configure.OpenAI.Prefered.Tip}"
TextWrapping="Wrap"
Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</TabItem>
</TabControl> </TabControl>
</Grid> </Grid>
</v:ChromelessWindow> </v:ChromelessWindow>

View file

@ -1,5 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
namespace SourceGit.Views namespace SourceGit.Views
{ {
@ -16,9 +17,19 @@ namespace SourceGit.Views
base.OnClosing(e); base.OnClosing(e);
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e) private async void SelectExecutableForCustomAction(object sender, RoutedEventArgs e)
{ {
BeginMoveDrag(e); var options = new FilePickerOpenOptions()
{
FileTypeFilter = [new FilePickerFileType("Executable file(script)") { Patterns = ["*.*"] }],
AllowMultiple = false,
};
var selected = await StorageProvider.OpenFilePickerAsync(options);
if (selected.Count == 1 && sender is Button { DataContext: Models.CustomAction action })
action.Executable = selected[0].Path.LocalPath;
e.Handled = true;
} }
} }
} }

View file

@ -96,6 +96,10 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.LFS}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.LFS}"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenCustomActionMenu" ToolTip.Tip="{DynamicResource Text.Repository.CustomActions}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Action}"/>
</Button>
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Command="{Binding Cleanup}" ToolTip.Tip="{DynamicResource Text.Repository.Clean}"> <Button Classes="icon_button" Width="32" Margin="8,0,0,0" Command="{Binding Cleanup}" ToolTip.Tip="{DynamicResource Text.Repository.Clean}">
<Path Width="14" Height="14" Margin="0,1,0,0" Data="{StaticResource Icons.Clean}"/> <Path Width="14" Height="14" Margin="0,1,0,0" Data="{StaticResource Icons.Clean}"/>
</Button> </Button>

View file

@ -91,6 +91,17 @@ namespace SourceGit.Views
e.Handled = true; e.Handled = true;
} }
private void OpenCustomActionMenu(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForCustomAction();
(sender as Control)?.OpenContextMenu(menu);
}
e.Handled = true;
}
} }
} }

View file

@ -17,30 +17,23 @@
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.SoftwareUpdate}" Data="{StaticResource Icons.SoftwareUpdate}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.SelfUpdate.Title}" Text="{DynamicResource Text.SelfUpdate.Title}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,5 +1,4 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -11,11 +10,6 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2) private void CloseWindow(object _1, RoutedEventArgs _2)
{ {
Close(); Close();

View file

@ -14,30 +14,23 @@
WindowStartupLocation="CenterScreen"> WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Edit}" Data="{StaticResource Icons.Edit}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.CodeEditor}" Text="{DynamicResource Text.CodeEditor}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,7 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -40,11 +39,6 @@ namespace SourceGit.Views
App.Quit(_exitCode); App.Quit(_exitCode);
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void SaveAndClose(object _1, RoutedEventArgs _2) private void SaveAndClose(object _1, RoutedEventArgs _2)
{ {
File.WriteAllText(_file, Editor.Text); File.WriteAllText(_file, Editor.Text);

View file

@ -11,7 +11,7 @@
<TextBlock FontSize="18" <TextBlock FontSize="18"
Classes="bold" Classes="bold"
Text="{DynamicResource Text.Stash.Title}"/> Text="{DynamicResource Text.Stash.Title}"/>
<Grid Margin="8,16,0,0" RowDefinitions="32,Auto,Auto" ColumnDefinitions="120,*"> <Grid Margin="8,16,0,0" RowDefinitions="32,Auto,Auto,32,Auto" ColumnDefinitions="120,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Margin="8,0" Margin="8,0"
@ -23,13 +23,6 @@
Watermark="{DynamicResource Text.Stash.Message.Placeholder}" Watermark="{DynamicResource Text.Stash.Message.Placeholder}"
v:AutoFocusBehaviour.IsEnabled="True"/> v:AutoFocusBehaviour.IsEnabled="True"/>
<TextBlock Grid.Row="1" Grid.Column="1"
Margin="0,4,0,0"
Text="{DynamicResource Text.Stash.TipForSelectedFiles}"
TextWrapping="Wrap"
Foreground="{DynamicResource Brush.FG2}"
IsVisible="{Binding HasSelectedFiles}"/>
<CheckBox Grid.Row="1" Grid.Column="1" <CheckBox Grid.Row="1" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Stash.IncludeUntracked}" Content="{DynamicResource Text.Stash.IncludeUntracked}"
@ -41,6 +34,18 @@
Content="{DynamicResource Text.Stash.OnlyStagedChanges}" Content="{DynamicResource Text.Stash.OnlyStagedChanges}"
IsChecked="{Binding OnlyStaged, Mode=TwoWay}" IsChecked="{Binding OnlyStaged, Mode=TwoWay}"
IsVisible="{Binding !HasSelectedFiles}"/> IsVisible="{Binding !HasSelectedFiles}"/>
<CheckBox Grid.Row="3" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Stash.KeepIndex}"
IsChecked="{Binding KeepIndex, Mode=TwoWay}"/>
<TextBlock Grid.Row="4" Grid.Column="1"
Margin="0,4,0,0"
Text="{DynamicResource Text.Stash.TipForSelectedFiles}"
TextWrapping="Wrap"
Foreground="{DynamicResource Brush.FG2}"
IsVisible="{Binding HasSelectedFiles}"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -9,11 +9,11 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.StashesPage" x:Class="SourceGit.Views.StashesPage"
x:DataType="vm:StashesPage"> x:DataType="vm:StashesPage">
<Grid> <Grid SizeChanged="OnMainLayoutSizeChanged">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.StashesLeftWidth, Mode=TwoWay}" MinWidth="300"/> <ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.StashesLeftWidth, Mode=TwoWay}" MinWidth="300"/>
<ColumnDefinition Width="4"/> <ColumnDefinition Width="4"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*" MinWidth="300"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- Left --> <!-- Left -->

View file

@ -9,6 +9,20 @@ namespace SourceGit.Views
InitializeComponent(); InitializeComponent();
} }
private void OnMainLayoutSizeChanged(object sender, SizeChangedEventArgs e)
{
var grid = sender as Grid;
if (grid == null)
return;
var layout = ViewModels.Preference.Instance.Layout;
var width = grid.Bounds.Width;
var maxLeft = width - 304;
if (layout.StashesLeftWidth.Value - maxLeft > 1.0)
layout.StashesLeftWidth = new GridLength(maxLeft, GridUnitType.Pixel);
}
private void OnStashContextRequested(object sender, ContextRequestedEventArgs e) private void OnStashContextRequested(object sender, ContextRequestedEventArgs e)
{ {
if (DataContext is ViewModels.StashesPage vm && sender is Border border) if (DataContext is ViewModels.StashesPage vm && sender is Border border)

View file

@ -16,30 +16,23 @@
CanResize="False"> CanResize="False">
<Grid RowDefinitions="Auto,Auto,*"> <Grid RowDefinitions="Auto,Auto,*">
<!-- Title bar --> <!-- Title bar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3" <Border Background="{DynamicResource Brush.TitleBar}"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/> PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0" <Path Width="14" Height="14"
Width="14" Height="14"
Margin="10,0,0,0" Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Statistics}" Data="{StaticResource Icons.Statistics}"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0" <TextBlock Classes="bold"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.Statistics}" Text="{DynamicResource Text.Statistics}"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2" <v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True" IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>

View file

@ -1,5 +1,3 @@
using Avalonia.Input;
namespace SourceGit.Views namespace SourceGit.Views
{ {
public partial class Statistics : ChromelessWindow public partial class Statistics : ChromelessWindow
@ -8,10 +6,5 @@ namespace SourceGit.Views
{ {
InitializeComponent(); InitializeComponent();
} }
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
} }
} }

View file

@ -8,116 +8,134 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
x:Class="SourceGit.Views.WorkingCopy" x:Class="SourceGit.Views.WorkingCopy"
x:DataType="vm:WorkingCopy"> x:DataType="vm:WorkingCopy">
<Grid> <Grid SizeChanged="OnMainLayoutSizeChanged">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.WorkingCopyLeftWidth, Mode=TwoWay}" MinWidth="300"/> <ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.WorkingCopyLeftWidth, Mode=TwoWay}" MinWidth="300"/>
<ColumnDefinition Width="5"/> <ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*" MinWidth="300"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- Left --> <!-- Left -->
<Grid Grid.Column="0" RowDefinitions="28,*,28,*"> <Grid Grid.Column="0">
<!-- Unstaged Toolbar --> <Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"> <RowDefinition Height="*" MinHeight="100"/>
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto,Auto,Auto"> <RowDefinition Height="1"/>
<Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Changes}"/> <RowDefinition Height="*" MinHeight="100"/>
<TextBlock Grid.Column="1" Text="{DynamicResource Text.WorkingCopy.Unstaged}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0"/> </Grid.RowDefinitions>
<TextBlock Grid.Column="2" FontWeight="Bold" Foreground="{DynamicResource Brush.FG2}" Text="{Binding Unstaged, Converter={x:Static c:ListConverters.ToCount}}"/>
<v:LoadingIcon Grid.Column="3" Width="14" Height="14" Margin="8,0,0,0" IsVisible="{Binding IsStaging}"/>
<Button Grid.Column="5" <!-- Unstaged -->
Classes="icon_button" <Grid Grid.Row="0" RowDefinitions="28,*">
Width="26" Height="14" <!-- Unstaged Toolbar -->
Padding="0" <Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.ViewAssumeUnchaged}" <Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto,Auto,Auto">
Command="{Binding OpenAssumeUnchanged}"> <Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Changes}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.File.Ignore}"/> <TextBlock Grid.Column="1" Text="{DynamicResource Text.WorkingCopy.Unstaged}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0"/>
</Button> <TextBlock Grid.Column="2" FontWeight="Bold" Foreground="{DynamicResource Brush.FG2}" Text="{Binding Unstaged, Converter={x:Static c:ListConverters.ToCount}}"/>
<ToggleButton Grid.Column="6" <v:LoadingIcon Grid.Column="3" Width="14" Height="14" Margin="8,0,0,0" IsVisible="{Binding IsStaging}"/>
Classes="toggle_untracked"
Width="26" Height="14"
ToolTip.Tip="{DynamicResource Text.WorkingCopy.IncludeUntracked}"
IsChecked="{Binding IncludeUntracked, Mode=TwoWay}"/>
<Button Grid.Column="7"
Classes="icon_button"
Width="26" Height="14"
Padding="0"
Click="OnStageSelectedButtonClicked">
<ToolTip.Tip>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{DynamicResource Text.WorkingCopy.Unstaged.Stage}" VerticalAlignment="Center"/>
<TextBlock Margin="16,0,0,0" Text="{OnPlatform Space/Enter, macOS=␣/Enter}" Opacity=".6" FontSize="11" VerticalAlignment="Center"/>
</StackPanel>
</ToolTip.Tip>
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
</Button>
<Button Grid.Column="8"
Classes="icon_button"
Width="26" Height="14"
Padding="0"
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.StageAll}"
Command="{Binding StageAll}">
<Path Width="14" Height="14" Data="{StaticResource Icons.DoubleDown}"/>
</Button>
<v:ChangeViewModeSwitcher Grid.Column="9"
Width="26" Height="14"
Margin="0,1,0,0"
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=UnstagedChangeViewMode, Mode=TwoWay}"/>
</Grid>
</Border>
<!-- Unstaged Changes --> <Button Grid.Column="5"
<v:ChangeCollectionView Grid.Row="1" Classes="icon_button"
x:Name="UnstagedChangesView" Width="26" Height="14"
Focusable="True" Padding="0"
IsUnstagedChange="True" ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.ViewAssumeUnchaged}"
SelectionMode="Multiple" Command="{Binding OpenAssumeUnchanged}">
Background="{DynamicResource Brush.Contents}" <Path Width="14" Height="14" Data="{StaticResource Icons.File.Ignore}"/>
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=UnstagedChangeViewMode}" </Button>
Changes="{Binding Unstaged}" <ToggleButton Grid.Column="6"
SelectedChanges="{Binding SelectedUnstaged, Mode=TwoWay}" Classes="toggle_untracked"
ContextRequested="OnUnstagedContextRequested" Width="26" Height="14"
ChangeDoubleTapped="OnUnstagedChangeDoubleTapped" ToolTip.Tip="{DynamicResource Text.WorkingCopy.IncludeUntracked}"
KeyDown="OnUnstagedKeyDown"/> IsChecked="{Binding IncludeUntracked, Mode=TwoWay}"/>
<Button Grid.Column="7"
Classes="icon_button"
Width="26" Height="14"
Padding="0"
Click="OnStageSelectedButtonClicked">
<ToolTip.Tip>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{DynamicResource Text.WorkingCopy.Unstaged.Stage}" VerticalAlignment="Center"/>
<TextBlock Margin="16,0,0,0" Text="{OnPlatform Space/Enter, macOS=␣/Enter}" Opacity=".6" FontSize="11" VerticalAlignment="Center"/>
</StackPanel>
</ToolTip.Tip>
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
</Button>
<Button Grid.Column="8"
Classes="icon_button"
Width="26" Height="14"
Padding="0"
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.StageAll}"
Command="{Binding StageAll}">
<Path Width="14" Height="14" Data="{StaticResource Icons.DoubleDown}"/>
</Button>
<v:ChangeViewModeSwitcher Grid.Column="9"
Width="26" Height="14"
Margin="0,1,0,0"
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=UnstagedChangeViewMode, Mode=TwoWay}"/>
</Grid>
</Border>
<!-- Staged Toolbar --> <!-- Unstaged Changes -->
<Border Grid.Row="2" BorderThickness="0,1" BorderBrush="{DynamicResource Brush.Border0}"> <v:ChangeCollectionView Grid.Row="1"
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto"> x:Name="UnstagedChangesView"
<Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Changes}"/> Focusable="True"
<TextBlock Grid.Column="1" Text="{DynamicResource Text.WorkingCopy.Staged}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0"/> IsUnstagedChange="True"
<TextBlock Grid.Column="2" FontWeight="Bold" Foreground="{DynamicResource Brush.FG2}" Text="{Binding Staged, Converter={x:Static c:ListConverters.ToCount}}"/> SelectionMode="Multiple"
<v:LoadingIcon Grid.Column="3" Width="14" Height="14" Margin="8,0,0,0" IsVisible="{Binding IsUnstaging}"/> Background="{DynamicResource Brush.Contents}"
<Button Grid.Column="5" Classes="icon_button" Width="26" Height="14" Padding="0" Click="OnUnstageSelectedButtonClicked"> ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=UnstagedChangeViewMode}"
<ToolTip.Tip> Changes="{Binding Unstaged}"
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"> SelectedChanges="{Binding SelectedUnstaged, Mode=TwoWay}"
<TextBlock Text="{DynamicResource Text.WorkingCopy.Staged.Unstage}" VerticalAlignment="Center"/> ContextRequested="OnUnstagedContextRequested"
<TextBlock Margin="16,0,0,0" Text="{OnPlatform Space/Enter, macOS=␣/Enter}" Opacity=".6" FontSize="11" VerticalAlignment="Center"/> ChangeDoubleTapped="OnUnstagedChangeDoubleTapped"
</StackPanel> KeyDown="OnUnstagedKeyDown"/>
</ToolTip.Tip> </Grid>
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
</Button>
<Button Grid.Column="6" Classes="icon_button" Width="26" Height="14" Padding="0" ToolTip.Tip="{DynamicResource Text.WorkingCopy.Staged.UnstageAll}" Command="{Binding UnstageAll}">
<Path Width="14" Height="14" Data="{StaticResource Icons.DoubleUp}"/>
</Button>
<v:ChangeViewModeSwitcher Grid.Column="7"
Width="26" Height="14"
Margin="0,1,0,0"
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=StagedChangeViewMode, Mode=TwoWay}"/>
</Grid>
</Border>
<!-- Staged Changes --> <!-- Splitter -->
<v:ChangeCollectionView Grid.Row="3" <GridSplitter Grid.Row="1"
x:Name="StagedChangesView" MinHeight="1"
Focusable="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
SelectionMode="Multiple" Background="{DynamicResource Brush.Border0}"/>
Background="{DynamicResource Brush.Contents}"
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=StagedChangeViewMode}" <!-- Staged -->
Changes="{Binding Staged}" <Grid Grid.Row="2" RowDefinitions="28,*">
SelectedChanges="{Binding SelectedStaged, Mode=TwoWay}" <!-- Staged Toolbar -->
ContextRequested="OnStagedContextRequested" <Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
ChangeDoubleTapped="OnStagedChangeDoubleTapped" <Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto">
KeyDown="OnStagedKeyDown"/> <Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Changes}"/>
<TextBlock Grid.Column="1" Text="{DynamicResource Text.WorkingCopy.Staged}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0"/>
<TextBlock Grid.Column="2" FontWeight="Bold" Foreground="{DynamicResource Brush.FG2}" Text="{Binding Staged, Converter={x:Static c:ListConverters.ToCount}}"/>
<v:LoadingIcon Grid.Column="3" Width="14" Height="14" Margin="8,0,0,0" IsVisible="{Binding IsUnstaging}"/>
<Button Grid.Column="5" Classes="icon_button" Width="26" Height="14" Padding="0" Click="OnUnstageSelectedButtonClicked">
<ToolTip.Tip>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{DynamicResource Text.WorkingCopy.Staged.Unstage}" VerticalAlignment="Center"/>
<TextBlock Margin="16,0,0,0" Text="{OnPlatform Space/Enter, macOS=␣/Enter}" Opacity=".6" FontSize="11" VerticalAlignment="Center"/>
</StackPanel>
</ToolTip.Tip>
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
</Button>
<Button Grid.Column="6" Classes="icon_button" Width="26" Height="14" Padding="0" ToolTip.Tip="{DynamicResource Text.WorkingCopy.Staged.UnstageAll}" Command="{Binding UnstageAll}">
<Path Width="14" Height="14" Data="{StaticResource Icons.DoubleUp}"/>
</Button>
<v:ChangeViewModeSwitcher Grid.Column="7"
Width="26" Height="14"
Margin="0,1,0,0"
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=StagedChangeViewMode, Mode=TwoWay}"/>
</Grid>
</Border>
<!-- Staged Changes -->
<v:ChangeCollectionView Grid.Row="1"
x:Name="StagedChangesView"
Focusable="True"
SelectionMode="Multiple"
Background="{DynamicResource Brush.Contents}"
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=StagedChangeViewMode}"
Changes="{Binding Staged}"
SelectedChanges="{Binding SelectedStaged, Mode=TwoWay}"
ContextRequested="OnStagedContextRequested"
ChangeDoubleTapped="OnStagedChangeDoubleTapped"
KeyDown="OnStagedKeyDown"/>
</Grid>
</Grid> </Grid>
<GridSplitter Grid.Column="1" <GridSplitter Grid.Column="1"
@ -199,7 +217,7 @@
<Button Grid.Column="1" <Button Grid.Column="1"
Classes="icon_button" Classes="icon_button"
Margin="4,2,0,0" Margin="4,2,0,0"
Command="{Binding GenerateCommitMessageByAI}" Click="OnOpenOpenAIHelper"
ToolTip.Tip="{DynamicResource Text.AIAssistant.Tip}" ToolTip.Tip="{DynamicResource Text.AIAssistant.Tip}"
ToolTip.Placement="Top" ToolTip.Placement="Top"
ToolTip.VerticalOffset="0"> ToolTip.VerticalOffset="0">

Some files were not shown because too many files have changed in this diff Show more