Merge branch 'release/v2025.10'

This commit is contained in:
leo 2025-03-24 09:44:50 +08:00
commit 7581d761cc
No known key found for this signature in database
121 changed files with 1196 additions and 1030 deletions

View file

@ -18,8 +18,8 @@
* Supports SSH access with each remote * Supports SSH access with each remote
* GIT commands with GUI * GIT commands with GUI
* Clone/Fetch/Pull/Push... * Clone/Fetch/Pull/Push...
* Merge/Rebase/Reset/Revert/Amend/Cherry-pick... * Merge/Rebase/Reset/Revert/Cherry-pick...
* Amend/Reword * Amend/Reword/Squash
* Interactive rebase * Interactive rebase
* Branches * Branches
* Remotes * Remotes
@ -40,6 +40,7 @@
* Git LFS * Git LFS
* Issue Link * Issue Link
* Workspace * Workspace
* Custom Action
* Using AI to generate commit message (C# port of [anjerodev/commitollama](https://github.com/anjerodev/commitollama)) * Using AI to generate commit message (C# port of [anjerodev/commitollama](https://github.com/anjerodev/commitollama))
> [!WARNING] > [!WARNING]
@ -47,10 +48,7 @@
## Translation Status ## Translation Status
[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.07%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-91.66%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-91.39%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)](TRANSLATION.md) You can find the current translation status in [TRANSLATION.md](TRANSLATION.md)
> [!NOTE]
> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md)
## How to Use ## How to Use
@ -201,3 +199,7 @@ dotnet run --project src/SourceGit.csproj
Thanks to all the people who contribute. Thanks to all the people who contribute.
[![Contributors](https://contrib.rocks/image?repo=sourcegit-scm/sourcegit&columns=20)](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)
## Third-Party Components
For detailed license information, see [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md).

86
THIRD-PARTY-LICENSES.md Normal file
View file

@ -0,0 +1,86 @@
# Third-Party Licenses
This project incorporates components from the following third parties:
## Packages
### AvaloniaUI
- **Source**: https://github.com/AvaloniaUI/Avalonia
- **Version**: 11.2.5
- **License**: MIT License
- **License Link**: https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md
### AvaloniaEdit
- **Source**: https://github.com/AvaloniaUI/AvaloniaEdit
- **Version**: 11.2.0
- **License**: MIT License
- **License Link**: https://github.com/AvaloniaUI/AvaloniaEdit/blob/master/LICENSE
### LiveChartsCore.SkiaSharpView.Avalonia
- **Source**: https://github.com/beto-rodriguez/LiveCharts2
- **Version**: 2.0.0-rc5.4
- **License**: MIT License
- **License Link**: https://github.com/beto-rodriguez/LiveCharts2/blob/master/LICENSE
### TextMateSharp
- **Source**: https://github.com/danipen/TextMateSharp
- **Version**: 1.0.66
- **License**: MIT License
- **License Link**: https://github.com/danipen/TextMateSharp/blob/master/LICENSE.md
### OpenAI .NET SDK
- **Source**: https://github.com/openai/openai-dotnet
- **Version**: 2.2.0-beta2
- **License**: MIT License
- **License Link**: https://github.com/openai/openai-dotnet/blob/main/LICENSE
### Azure.AI.OpenAI
- **Source**: https://github.com/Azure/azure-sdk-for-net
- **Version**: 2.2.0-beta2
- **License**: MIT License
- **License Link**: https://github.com/Azure/azure-sdk-for-net/blob/main/LICENSE.txt
## Fonts
### JetBrainsMono
- **Source**: https://github.com/JetBrains/JetBrainsMono
- **Commit**: v2.304
- **License**: SIL Open Font License, Version 1.1
- **License Link**: https://github.com/JetBrains/JetBrainsMono/blob/v2.304/OFL.txt
## Grammar Files
### haxe-TmLanguage
- **Source**: https://github.com/vshaxe/haxe-TmLanguage
- **Commit**: ddad8b4c6d0781ac20be0481174ec1be772c5da5
- **License**: MIT License
- **License Link**: https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md
### coc-toml
- **Source**: https://github.com/kkiyama117/coc-toml
- **Commit**: aac3e0c65955c03314b2733041b19f903b7cc447
- **License**: MIT License
- **License Link**: https://github.com/kkiyama117/coc-toml/blob/aac3e0c65955c03314b2733041b19f903b7cc447/LICENSE
### eclipse-buildship
- **Source**: https://github.com/eclipse/buildship
- **Commit**: 6bb773e7692f913dec27105129ebe388de34e68b
- **License**: Eclipse Public License 1.0
- **License Link**: https://github.com/eclipse-buildship/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/README.md
### vscode-jsp-lang
- **Source**: https://github.com/samuel-weinhardt/vscode-jsp-lang
- **Commit**: 0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355
- **License**: MIT License
- **License Link**: https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/LICENSE

View file

@ -1,8 +1,15 @@
### de_DE.axaml: 99.07% # Translation Status
This document shows the translation status of each locale file in the repository.
## Details
### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)
### ![de__DE](https://img.shields.io/badge/de__DE-98.92%25-yellow)
<details> <details>
<summary>Missing Keys</summary> <summary>Missing keys in de_DE.axaml</summary>
- Text.BranchUpstreamInvalid - Text.BranchUpstreamInvalid
- Text.Configure.CustomAction.WaitForExit - Text.Configure.CustomAction.WaitForExit
@ -10,107 +17,35 @@
- Text.Diff.Last - Text.Diff.Last
- Text.Preferences.AI.Streaming - Text.Preferences.AI.Streaming
- Text.Preferences.Appearance.EditorTabWidth - Text.Preferences.Appearance.EditorTabWidth
- Text.Preferences.General.ShowTagsInGraph
- Text.StashCM.SaveAsPatch - Text.StashCM.SaveAsPatch
</details> </details>
### es_ES.axaml: 100.00% ### ![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow)
<details> <details>
<summary>Missing Keys</summary> <summary>Missing keys in es_ES.axaml</summary>
- Text.Preferences.General.ShowTagsInGraph
</details> </details>
### fr_FR.axaml: 91.66% ### ![fr__FR](https://img.shields.io/badge/fr__FR-%E2%88%9A-brightgreen)
### ![it__IT](https://img.shields.io/badge/it__IT-99.87%25-yellow)
<details> <details>
<summary>Missing Keys</summary> <summary>Missing keys in it_IT.axaml</summary>
- Text.AIAssistant.Regen - Text.Preferences.General.ShowTagsInGraph
- Text.AIAssistant.Use
- Text.ApplyStash
- Text.ApplyStash.DropAfterApply
- Text.ApplyStash.RestoreIndex
- Text.ApplyStash.Stash
- Text.BranchCM.CustomAction
- Text.BranchUpstreamInvalid
- Text.Clone.RecurseSubmodules
- Text.Configure.CustomAction.Scope.Branch
- Text.Configure.CustomAction.WaitForExit
- Text.CreateBranch.Name.WarnSpace
- Text.DeleteRepositoryNode.Path
- Text.DeleteRepositoryNode.TipForGroup
- Text.DeleteRepositoryNode.TipForRepository
- Text.Diff.First
- Text.Diff.Last
- Text.InProgress.CherryPick.Head
- Text.InProgress.Merge.Operating
- Text.InProgress.Rebase.StoppedAt
- Text.InProgress.Revert.Head
- Text.Merge.Source
- Text.MergeMultiple
- Text.MergeMultiple.CommitChanges
- Text.MergeMultiple.Strategy
- Text.MergeMultiple.Targets
- Text.Preferences.AI.Streaming
- Text.Preferences.Appearance.EditorTabWidth
- Text.Preferences.Appearance.FontSize
- Text.Preferences.Appearance.FontSize.Default
- Text.Preferences.Appearance.FontSize.Editor
- Text.Preferences.General.DateFormat
- Text.Preferences.General.ShowChildren
- Text.Preferences.Git.SSLVerify
- Text.Repository.CustomActions
- Text.Repository.FilterCommits
- Text.Repository.FilterCommits.Default
- Text.Repository.FilterCommits.Exclude
- Text.Repository.FilterCommits.Include
- Text.Repository.HistoriesLayout
- Text.Repository.HistoriesLayout.Horizontal
- Text.Repository.HistoriesLayout.Vertical
- Text.Repository.HistoriesOrder
- Text.Repository.HistoriesOrder.ByDate
- Text.Repository.HistoriesOrder.Topo
- Text.Repository.Notifications.Clear
- Text.Repository.Skip
- Text.Repository.Tags.OrderByCreatorDate
- Text.Repository.Tags.OrderByNameAsc
- Text.Repository.Tags.OrderByNameDes
- Text.Repository.Tags.Sort
- Text.Repository.UseRelativeTimeInHistories
- Text.ScanRepositories
- Text.SetUpstream
- Text.SetUpstream.Local
- Text.SetUpstream.Unset
- Text.SetUpstream.Upstream
- Text.SHALinkCM.NavigateTo
- Text.Stash.AutoRestore
- Text.Stash.AutoRestore.Tip
- Text.StashCM.SaveAsPatch
- Text.WorkingCopy.CommitToEdit
- Text.WorkingCopy.SignOff
</details> </details>
### it_IT.axaml: 99.87% ### ![pt__BR](https://img.shields.io/badge/pt__BR-91.12%25-yellow)
<details> <details>
<summary>Missing Keys</summary> <summary>Missing keys in pt_BR.axaml</summary>
- Text.Preferences.Appearance.EditorTabWidth
</details>
### pt_BR.axaml: 91.39%
<details>
<summary>Missing Keys</summary>
- Text.AIAssistant.Regen - Text.AIAssistant.Regen
- Text.AIAssistant.Use - Text.AIAssistant.Use
@ -153,6 +88,7 @@
- Text.Preferences.Appearance.EditorTabWidth - Text.Preferences.Appearance.EditorTabWidth
- Text.Preferences.General.DateFormat - Text.Preferences.General.DateFormat
- Text.Preferences.General.ShowChildren - Text.Preferences.General.ShowChildren
- Text.Preferences.General.ShowTagsInGraph
- Text.Preferences.Git.SSLVerify - Text.Preferences.Git.SSLVerify
- Text.Repository.FilterCommits - Text.Repository.FilterCommits
- Text.Repository.HistoriesLayout - Text.Repository.HistoriesLayout
@ -180,32 +116,8 @@
</details> </details>
### ru_RU.axaml: 100.00% ### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)
### ![zh__CN](https://img.shields.io/badge/zh__CN-%E2%88%9A-brightgreen)
<details> ### ![zh__TW](https://img.shields.io/badge/zh__TW-%E2%88%9A-brightgreen)
<summary>Missing Keys</summary>
</details>
### zh_CN.axaml: 100.00%
<details>
<summary>Missing Keys</summary>
</details>
### zh_TW.axaml: 100.00%
<details>
<summary>Missing Keys</summary>
</details>

View file

@ -1 +1 @@
2025.09 2025.10

View file

@ -6,7 +6,6 @@ const repoRoot = path.join(__dirname, '../../');
const localesDir = path.join(repoRoot, 'src/Resources/Locales'); const localesDir = path.join(repoRoot, 'src/Resources/Locales');
const enUSFile = path.join(localesDir, 'en_US.axaml'); const enUSFile = path.join(localesDir, 'en_US.axaml');
const outputFile = path.join(repoRoot, 'TRANSLATION.md'); const outputFile = path.join(repoRoot, 'TRANSLATION.md');
const readmeFile = path.join(repoRoot, 'README.md');
const parser = new xml2js.Parser(); const parser = new xml2js.Parser();
@ -18,46 +17,36 @@ async function parseXml(filePath) {
async function calculateTranslationRate() { async function calculateTranslationRate() {
const enUSData = await parseXml(enUSFile); const enUSData = await parseXml(enUSFile);
const enUSKeys = new Set(enUSData.ResourceDictionary['x:String'].map(item => item.$['x:Key'])); const enUSKeys = new Set(enUSData.ResourceDictionary['x:String'].map(item => item.$['x:Key']));
const translationRates = [];
const badges = [];
const files = (await fs.readdir(localesDir)).filter(file => file !== 'en_US.axaml' && file.endsWith('.axaml')); const files = (await fs.readdir(localesDir)).filter(file => file !== 'en_US.axaml' && file.endsWith('.axaml'));
// Add en_US badge first const lines = [];
badges.push(`[![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)](TRANSLATION.md)`);
lines.push('# Translation Status');
lines.push('This document shows the translation status of each locale file in the repository.');
lines.push(`## Details`);
lines.push(`### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)`);
for (const file of files) { for (const file of files) {
const locale = file.replace('.axaml', '').replace('_', '__');
const filePath = path.join(localesDir, file); const filePath = path.join(localesDir, file);
const localeData = await parseXml(filePath); const localeData = await parseXml(filePath);
const localeKeys = new Set(localeData.ResourceDictionary['x:String'].map(item => item.$['x:Key'])); const localeKeys = new Set(localeData.ResourceDictionary['x:String'].map(item => item.$['x:Key']));
const missingKeys = [...enUSKeys].filter(key => !localeKeys.has(key)); const missingKeys = [...enUSKeys].filter(key => !localeKeys.has(key));
const translationRate = ((enUSKeys.size - missingKeys.length) / enUSKeys.size) * 100;
translationRates.push(`### ${file}: ${translationRate.toFixed(2)}%\n`); if (missingKeys.length > 0) {
translationRates.push(`<details>\n<summary>Missing Keys</summary>\n\n${missingKeys.map(key => `- ${key}`).join('\n')}\n\n</details>`); const progress = ((enUSKeys.size - missingKeys.length) / enUSKeys.size) * 100;
const badgeColor = progress >= 75 ? 'yellow' : 'red';
// Add badges lines.push(`### ![${locale}](https://img.shields.io/badge/${locale}-${progress.toFixed(2)}%25-${badgeColor})`);
const locale = file.replace('.axaml', '').replace('_', '__'); lines.push(`<details>\n<summary>Missing keys in ${file}</summary>\n\n${missingKeys.map(key => `- ${key}`).join('\n')}\n\n</details>`)
if (translationRate === 100) {
badges.push(`[![${locale}](https://img.shields.io/badge/${locale}-%E2%88%9A-brightgreen)](TRANSLATION.md)`);
} else { } else {
const badgeColor = translationRate >= 75 ? 'yellow' : 'red'; lines.push(`### ![${locale}](https://img.shields.io/badge/${locale}-%E2%88%9A-brightgreen)`);
badges.push(`[![${locale}](https://img.shields.io/badge/${locale}-${translationRate.toFixed(2)}%25-${badgeColor})](TRANSLATION.md)`);
} }
} }
console.log(translationRates.join('\n\n')); const content = lines.join('\n\n');
console.log(content);
await fs.writeFile(outputFile, translationRates.join('\n\n') + '\n', 'utf8'); await fs.writeFile(outputFile, content, 'utf8');
// Update README.md
let readmeContent = await fs.readFile(readmeFile, 'utf8');
const badgeSection = `## Translation Status\n\n${badges.join(' ')}`;
console.log(badgeSection);
readmeContent = readmeContent.replace(/## Translation Status\n\n.*\n\n/, badgeSection + '\n\n');
await fs.writeFile(readmeFile, readmeContent, 'utf8');
} }
calculateTranslationRate().catch(err => console.error(err)); calculateTranslationRate().catch(err => console.error(err));

View file

@ -532,7 +532,7 @@ namespace SourceGit
catch (Exception e) catch (Exception e)
{ {
if (manually) if (manually)
ShowSelfUpdateResult(e); ShowSelfUpdateResult(new Models.SelfUpdateFailed(e));
} }
}); });
} }

View file

@ -6,7 +6,7 @@ namespace SourceGit.Commands
{ {
public partial class CompareRevisions : Command public partial class CompareRevisions : Command
{ {
[GeneratedRegex(@"^(\s?[\w\?]{1,4})\s+(.+)$")] [GeneratedRegex(@"^([MADRC])\s+(.+)$")]
private static partial Regex REG_FORMAT(); private static partial Regex REG_FORMAT();
public CompareRevisions(string repo, string start, string end) public CompareRevisions(string repo, string start, string end)

View file

@ -29,7 +29,7 @@ namespace SourceGit.Commands
var rs = new Dictionary<string, string>(); var rs = new Dictionary<string, string>();
if (output.IsSuccess) if (output.IsSuccess)
{ {
var lines = output.StdOut.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
var idx = line.IndexOf('=', StringComparison.Ordinal); var idx = line.IndexOf('=', StringComparison.Ordinal);

View file

@ -16,7 +16,7 @@ namespace SourceGit.Commands
var rs = ReadToEnd(); var rs = ReadToEnd();
if (rs.IsSuccess) if (rs.IsSuccess)
{ {
var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
return lines.Length; return lines.Length;
} }

View file

@ -82,7 +82,7 @@ namespace SourceGit.Commands
var rs = cmd.ReadToEnd(); var rs = cmd.ReadToEnd();
if (rs.IsSuccess) if (rs.IsSuccess)
{ {
var lines = rs.StdOut.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
var match = REG_LOCK().Match(line); var match = REG_LOCK().Match(line);

View file

@ -24,7 +24,7 @@ namespace SourceGit.Commands
if (!rs.IsSuccess) if (!rs.IsSuccess)
return branches; return branches;
var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
var remoteBranches = new HashSet<string>(); var remoteBranches = new HashSet<string>();
foreach (var line in lines) foreach (var line in lines)
{ {

View file

@ -9,7 +9,7 @@ namespace SourceGit.Commands
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
_commit = commit; _commit = commit;
Args = $"rev-list -{max} --parents --branches --remotes --ancestry-path={commit} ^{commit}"; Args = $"rev-list -{max} --parents --branches --remotes --ancestry-path ^{commit}";
} }
public List<string> Result() public List<string> Result()

View file

@ -6,7 +6,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"show --no-show-signature --pretty=format:%B -s {sha}"; Args = $"show --no-show-signature --format=%B -s {sha}";
} }
public string Result() public string Result()

View file

@ -7,7 +7,7 @@
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
const string baseArgs = "show --no-show-signature --pretty=format:\"%G?%n%GS%n%GK\" -s"; const string baseArgs = "show --no-show-signature --format=%G?%n%GS%n%GK -s";
const string fakeSignersFileArg = "-c gpg.ssh.allowedSignersFile=/dev/null"; const string fakeSignersFileArg = "-c gpg.ssh.allowedSignersFile=/dev/null";
Args = $"{(useFakeSignersFile ? fakeSignersFileArg : string.Empty)} {baseArgs} {sha}"; Args = $"{(useFakeSignersFile ? fakeSignersFileArg : string.Empty)} {baseArgs} {sha}";
} }
@ -18,7 +18,7 @@
if (!rs.IsSuccess) if (!rs.IsSuccess)
return null; return null;
var raw = rs.StdOut.Trim(); var raw = rs.StdOut.Trim().ReplaceLineEndings("\n");
if (raw.Length <= 1) if (raw.Length <= 1)
return null; return null;
@ -29,7 +29,6 @@
Signer = lines[1], Signer = lines[1],
Key = lines[2] Key = lines[2]
}; };
} }
} }
} }

View file

@ -10,7 +10,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"log --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s {limits}"; Args = $"log --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s {limits}";
_findFirstMerged = needFindHead; _findFirstMerged = needFindHead;
} }
@ -35,7 +35,7 @@ namespace SourceGit.Commands
var argsBuilder = new StringBuilder(); var argsBuilder = new StringBuilder();
argsBuilder.Append(search); argsBuilder.Append(search);
var words = filter.Split(new[] { ' ', '\t', '\r' }, StringSplitOptions.RemoveEmptyEntries); var words = filter.Split([' ', '\t', '\r'], StringSplitOptions.RemoveEmptyEntries);
foreach (var word in words) foreach (var word in words)
{ {
var escaped = word.Trim().Replace("\"", "\\\"", StringComparison.Ordinal); var escaped = word.Trim().Replace("\"", "\\\"", StringComparison.Ordinal);
@ -48,7 +48,7 @@ namespace SourceGit.Commands
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"log -1000 --date-order --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s " + search; Args = $"log -1000 --date-order --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s " + search;
_findFirstMerged = false; _findFirstMerged = false;
} }
@ -124,7 +124,7 @@ namespace SourceGit.Commands
Args = $"log --since=\"{_commits[^1].CommitterTimeStr}\" --format=\"%H\""; Args = $"log --since=\"{_commits[^1].CommitterTimeStr}\" --format=\"%H\"";
var rs = ReadToEnd(); var rs = ReadToEnd();
var shas = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); var shas = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
if (shas.Length == 0) if (shas.Length == 0)
return; return;

View file

@ -11,7 +11,7 @@ namespace SourceGit.Commands
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD"; Args = $"log --date-order --no-show-signature --decorate=full --format=\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD";
} }
public List<Models.InteractiveCommit> Result() public List<Models.InteractiveCommit> Result()

View file

@ -0,0 +1,26 @@
using System.IO;
namespace SourceGit.Commands
{
public class QueryGitCommonDir : Command
{
public QueryGitCommonDir(string workDir)
{
WorkingDirectory = workDir;
Args = "rev-parse --git-common-dir";
RaiseError = false;
}
public string Result()
{
var rs = ReadToEnd().StdOut;
if (string.IsNullOrEmpty(rs))
return null;
rs = rs.Trim();
if (Path.IsPathRooted(rs))
return rs;
return Path.GetFullPath(Path.Combine(WorkingDirectory, rs));
}
}
}

View file

@ -20,7 +20,7 @@ namespace SourceGit.Commands
if (!output.IsSuccess) if (!output.IsSuccess)
return rs; return rs;
var lines = output.StdOut.Split('\n'); var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
if (line.EndsWith("/HEAD", StringComparison.Ordinal)) if (line.EndsWith("/HEAD", StringComparison.Ordinal))

View file

@ -8,7 +8,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"show --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s -s {sha}"; Args = $"show --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s -s {sha}";
} }
public Models.Commit Result() public Models.Commit Result()

View file

@ -24,7 +24,7 @@ namespace SourceGit.Commands
if (rs.IsSuccess) if (rs.IsSuccess)
{ {
var changes = new List<Models.Change>(); var changes = new List<Models.Change>();
var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
var match = REG_FORMAT2().Match(line); var match = REG_FORMAT2().Match(line);

View file

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace SourceGit.Commands
{
/// <summary>
/// Query stash changes. Requires git >= 2.32.0
/// </summary>
public partial class QueryStashChanges : Command
{
[GeneratedRegex(@"^([MADRC])\s+(.+)$")]
private static partial Regex REG_FORMAT();
public QueryStashChanges(string repo, string stash)
{
WorkingDirectory = repo;
Context = repo;
Args = $"stash show -u --name-status \"{stash}\"";
}
public List<Models.Change> Result()
{
var rs = ReadToEnd();
if (!rs.IsSuccess)
return [];
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
var outs = new List<Models.Change>();
foreach (var line in lines)
{
var match = REG_FORMAT().Match(line);
if (!match.Success)
continue;
var change = new Models.Change() { Path = match.Groups[2].Value };
var status = match.Groups[1].Value;
switch (status[0])
{
case 'M':
change.Set(Models.ChangeState.Modified);
outs.Add(change);
break;
case 'A':
change.Set(Models.ChangeState.Added);
outs.Add(change);
break;
case 'D':
change.Set(Models.ChangeState.Deleted);
outs.Add(change);
break;
case 'R':
change.Set(Models.ChangeState.Renamed);
outs.Add(change);
break;
case 'C':
change.Set(Models.ChangeState.Copied);
outs.Add(change);
break;
}
}
outs.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
return outs;
}
}
}

View file

@ -9,7 +9,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = "stash list --pretty=format:%H%n%P%n%ct%n%gd%n%s"; Args = "stash list --format=%H%n%P%n%ct%n%gd%n%s";
} }
public List<Models.Stash> Result() public List<Models.Stash> Result()

View file

@ -26,7 +26,7 @@ namespace SourceGit.Commands
var rs = ReadToEnd(); var rs = ReadToEnd();
var builder = new StringBuilder(); var builder = new StringBuilder();
var lines = rs.StdOut.Split('\n', System.StringSplitOptions.RemoveEmptyEntries); var lines = rs.StdOut.Split(['\r', '\n'], System.StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
var match = REG_FORMAT1().Match(line); var match = REG_FORMAT1().Match(line);
@ -55,7 +55,7 @@ namespace SourceGit.Commands
return submodules; return submodules;
var dirty = new HashSet<string>(); var dirty = new HashSet<string>();
lines = rs.StdOut.Split('\n', System.StringSplitOptions.RemoveEmptyEntries); lines = rs.StdOut.Split(['\r', '\n'], System.StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
var match = REG_FORMAT_STATUS().Match(line); var match = REG_FORMAT_STATUS().Match(line);

View file

@ -19,7 +19,7 @@ namespace SourceGit.Commands
if (!rs.IsSuccess) if (!rs.IsSuccess)
return status; return status;
var lines = rs.StdOut.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
if (line[0] == '>') if (line[0] == '>')

View file

@ -8,7 +8,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"log --date-order --branches --remotes -{max} --pretty=format:\"%ct$%aN\""; Args = $"log --date-order --branches --remotes -{max} --format=%ct$%aN";
} }
public Models.Statistics Result() public Models.Statistics Result()

View file

@ -21,7 +21,7 @@ namespace SourceGit.Commands
var last = null as Models.Worktree; var last = null as Models.Worktree;
if (rs.IsSuccess) if (rs.IsSuccess)
{ {
var lines = rs.StdOut.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
{ {
if (line.StartsWith("worktree ", StringComparison.Ordinal)) if (line.StartsWith("worktree ", StringComparison.Ordinal))

View file

@ -2,14 +2,22 @@
{ {
public class ApplyWhiteSpaceMode public class ApplyWhiteSpaceMode
{ {
public static readonly ApplyWhiteSpaceMode[] Supported =
[
new ApplyWhiteSpaceMode("No Warn", "Turns off the trailing whitespace warning", "nowarn"),
new ApplyWhiteSpaceMode("Warn", "Outputs warnings for a few such errors, but applies", "warn"),
new ApplyWhiteSpaceMode("Error", "Raise errors and refuses to apply the patch", "error"),
new ApplyWhiteSpaceMode("Error All", "Similar to 'error', but shows more", "error-all"),
];
public string Name { get; set; } public string Name { get; set; }
public string Desc { get; set; } public string Desc { get; set; }
public string Arg { get; set; } public string Arg { get; set; }
public ApplyWhiteSpaceMode(string n, string d, string a) public ApplyWhiteSpaceMode(string n, string d, string a)
{ {
Name = App.Text(n); Name = n;
Desc = App.Text(d); Desc = d;
Arg = a; Arg = a;
} }
} }

View file

@ -13,13 +13,18 @@
public static readonly System.Version ADD_WITH_PATHSPECFILE = new System.Version(2, 25, 0); public static readonly System.Version ADD_WITH_PATHSPECFILE = new System.Version(2, 25, 0);
/// <summary> /// <summary>
/// The minimal version of Git that supports the `stash` command with the `--pathspec-from-file` option. /// The minimal version of Git that supports the `stash push` command with the `--pathspec-from-file` option.
/// </summary> /// </summary>
public static readonly System.Version STASH_WITH_PATHSPECFILE = new System.Version(2, 26, 0); public static readonly System.Version STASH_PUSH_WITH_PATHSPECFILE = new System.Version(2, 26, 0);
/// <summary> /// <summary>
/// The minimal version of Git that supports the `stash` command with the `--staged` option. /// The minimal version of Git that supports the `stash push` command with the `--staged` option.
/// </summary> /// </summary>
public static readonly System.Version STASH_ONLY_STAGED = new System.Version(2, 35, 0); public static readonly System.Version STASH_PUSH_ONLY_STAGED = new System.Version(2, 35, 0);
/// <summary>
/// The minimal version of Git that supports the `stash show` command with the `-u` option.
/// </summary>
public static readonly System.Version STASH_SHOW_WITH_UNTRACKED = new System.Version(2, 32, 0);
} }
} }

View file

@ -2,9 +2,6 @@
{ {
public interface IRepository public interface IRepository
{ {
string FullPath { get; set; }
string GitDir { get; set; }
void RefreshBranches(); void RefreshBranches();
void RefreshWorktrees(); void RefreshWorktrees();
void RefreshTags(); void RefreshTags();

View file

@ -5,8 +5,9 @@
public static readonly MergeMode[] Supported = public static readonly MergeMode[] Supported =
[ [
new MergeMode("Default", "Fast-forward if possible", ""), new MergeMode("Default", "Fast-forward if possible", ""),
new MergeMode("Fast-forward", "Refuse to merge when fast-forward is not possible", "--ff-only"),
new MergeMode("No Fast-forward", "Always create a merge commit", "--no-ff"), new MergeMode("No Fast-forward", "Always create a merge commit", "--no-ff"),
new MergeMode("Squash", "Use '--squash'", "--squash"), new MergeMode("Squash", "Squash merge", "--squash"),
new MergeMode("Don't commit", "Merge without commit", "--no-ff --no-commit"), new MergeMode("Don't commit", "Merge without commit", "--no-ff --no-commit"),
]; ];

View file

@ -1,4 +1,5 @@
using System.Reflection; using System;
using System.Reflection;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace SourceGit.Models namespace SourceGit.Models
@ -32,5 +33,24 @@ namespace SourceGit.Models
} }
} }
public class AlreadyUpToDate { } public class AlreadyUpToDate
{
}
public class SelfUpdateFailed
{
public string Reason
{
get;
private set;
}
public SelfUpdateFailed(Exception e)
{
if (e.InnerException is { } inner)
Reason = inner.Message;
else
Reason = e.Message;
}
}
} }

View file

@ -10,7 +10,6 @@ namespace SourceGit.Models
public List<string> Parents { get; set; } = []; public List<string> Parents { get; set; } = [];
public ulong Time { get; set; } = 0; public ulong Time { get; set; } = 0;
public string Message { get; set; } = ""; public string Message { get; set; } = "";
public bool HasUntracked => Parents.Count == 3;
public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
} }

View file

@ -21,10 +21,11 @@ namespace SourceGit.Models
{ {
private static readonly ExtraGrammar[] s_extraGrammars = private static readonly ExtraGrammar[] s_extraGrammars =
[ [
new ExtraGrammar("source.toml", ".toml", "toml.json"), new ExtraGrammar("source.toml", [".toml"], "toml.json"),
new ExtraGrammar("source.kotlin", ".kotlin", "kotlin.json"), new ExtraGrammar("source.kotlin", [".kotlin", ".kt", ".kts"], "kotlin.json"),
new ExtraGrammar("source.hx", ".hx", "haxe.json"), new ExtraGrammar("source.hx", [".hx"], "haxe.json"),
new ExtraGrammar("source.hxml", ".hxml", "hxml.json"), new ExtraGrammar("source.hxml", [".hxml"], "hxml.json"),
new ExtraGrammar("text.html.jsp", [".jsp", ".jspf", ".tag"], "jsp.json"),
]; ];
public static string GetScope(string file, RegistryOptions reg) public static string GetScope(string file, RegistryOptions reg)
@ -36,14 +37,15 @@ namespace SourceGit.Models
extension = ".xml"; extension = ".xml";
else if (extension == ".command") else if (extension == ".command")
extension = ".sh"; extension = ".sh";
else if (extension == ".kt" || extension == ".kts")
extension = ".kotlin";
foreach (var grammar in s_extraGrammars) foreach (var grammar in s_extraGrammars)
{ {
if (grammar.Extension.Equals(extension, StringComparison.OrdinalIgnoreCase)) foreach (var ext in grammar.Extensions)
{
if (ext.Equals(extension, StringComparison.OrdinalIgnoreCase))
return grammar.Scope; return grammar.Scope;
} }
}
return reg.GetScopeByExtension(extension); return reg.GetScopeByExtension(extension);
} }
@ -71,10 +73,10 @@ namespace SourceGit.Models
return reg.GetGrammar(scopeName); return reg.GetGrammar(scopeName);
} }
private record ExtraGrammar(string Scope, string Extension, string File) private record ExtraGrammar(string Scope, List<string> Extensions, string File)
{ {
public readonly string Scope = Scope; public readonly string Scope = Scope;
public readonly string Extension = Extension; public readonly List<string> Extensions = Extensions;
public readonly string File = File; public readonly string File = File;
} }
} }

View file

@ -8,12 +8,12 @@ namespace SourceGit.Models
{ {
public class Watcher : IDisposable public class Watcher : IDisposable
{ {
public Watcher(IRepository repo) public Watcher(IRepository repo, string fullpath, string gitDir)
{ {
_repo = repo; _repo = repo;
_wcWatcher = new FileSystemWatcher(); _wcWatcher = new FileSystemWatcher();
_wcWatcher.Path = _repo.FullPath; _wcWatcher.Path = fullpath;
_wcWatcher.Filter = "*"; _wcWatcher.Filter = "*";
_wcWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime; _wcWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime;
_wcWatcher.IncludeSubdirectories = true; _wcWatcher.IncludeSubdirectories = true;
@ -23,15 +23,8 @@ namespace SourceGit.Models
_wcWatcher.Deleted += OnWorkingCopyChanged; _wcWatcher.Deleted += OnWorkingCopyChanged;
_wcWatcher.EnableRaisingEvents = true; _wcWatcher.EnableRaisingEvents = true;
// If this repository is a worktree repository, just watch the main repository's gitdir.
var gitDirNormalized = _repo.GitDir.Replace("\\", "/");
var worktreeIdx = gitDirNormalized.IndexOf(".git/worktrees/", StringComparison.Ordinal);
var repoWatchDir = _repo.GitDir;
if (worktreeIdx > 0)
repoWatchDir = _repo.GitDir.Substring(0, worktreeIdx + 4);
_repoWatcher = new FileSystemWatcher(); _repoWatcher = new FileSystemWatcher();
_repoWatcher.Path = repoWatchDir; _repoWatcher.Path = gitDir;
_repoWatcher.Filter = "*"; _repoWatcher.Filter = "*";
_repoWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName; _repoWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName;
_repoWatcher.IncludeSubdirectories = true; _repoWatcher.IncludeSubdirectories = true;

View file

@ -1,7 +1,9 @@
{ {
"information_for_contributors": [ "information_for_contributors": [
"This file has been copied from https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/haxe.tmLanguage", "This file has been copied from https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/haxe.tmLanguage",
"and converted to JSON using https://marketplace.visualstudio.com/items?itemName=pedro-w.tmlanguage" "and converted to JSON using https://marketplace.visualstudio.com/items?itemName=pedro-w.tmlanguage",
"The original file was licensed under the MIT License",
"https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md"
], ],
"fileTypes": [ "fileTypes": [
"hx", "hx",

View file

@ -1,7 +1,9 @@
{ {
"information_for_contributors": [ "information_for_contributors": [
"This file has been copied from https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/hxml.tmLanguage", "This file has been copied from https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/hxml.tmLanguage",
"and converted to JSON using https://marketplace.visualstudio.com/items?itemName=pedro-w.tmlanguage" "and converted to JSON using https://marketplace.visualstudio.com/items?itemName=pedro-w.tmlanguage",
"The original file was licensed under the MIT License",
"https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md"
], ],
"fileTypes": [ "fileTypes": [
"hxml" "hxml"

View file

@ -0,0 +1,100 @@
{
"information_for_contributors": [
"This file has been copied from https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/syntaxes/jsp.tmLanguage.json",
"The original file was licensed under the MIT License",
"https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/LICENSE"
],
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "Jakarta Server Pages",
"fileTypes": ["jsp", "jspf", "tag"],
"scopeName": "text.html.jsp",
"patterns": [
{ "include": "#comment" },
{ "include": "#directive" },
{ "include": "#expression" },
{ "include": "text.html.derivative" }
],
"injections": {
"L:text.html.jsp -comment -meta.tag.directive.jsp -meta.tag.scriptlet.jsp": {
"patterns": [
{ "include": "#scriptlet" }
],
"comment": "allow scriptlets anywhere except comments and nested"
},
"L:meta.attribute (string.quoted.single.html | string.quoted.double.html) -string.template.expression.jsp": {
"patterns": [
{ "include": "#expression" },
{ "include": "text.html.derivative" }
],
"comment": "allow expressions and tags within HTML attributes (not nested)"
}
},
"repository": {
"comment": {
"name": "comment.block.jsp",
"begin": "<%--",
"end": "--%>"
},
"directive": {
"name": "meta.tag.directive.jsp",
"begin": "(<)(%@)",
"end": "(%)(>)",
"beginCaptures": {
"1": { "name": "punctuation.definition.tag.jsp" },
"2": { "name": "entity.name.tag.jsp" }
},
"endCaptures": {
"1": { "name": "entity.name.tag.jsp" },
"2": { "name": "punctuation.definition.tag.jsp" }
},
"patterns": [
{
"match": "\\b(attribute|include|page|tag|taglib|variable)\\b(?!\\s*=)",
"name": "keyword.control.directive.jsp"
},
{ "include": "text.html.basic#attribute" }
]
},
"scriptlet": {
"name": "meta.tag.scriptlet.jsp",
"contentName": "meta.embedded.block.java",
"begin": "(<)(%[\\s!=])",
"end": "(%)(>)",
"beginCaptures": {
"1": { "name": "punctuation.definition.tag.jsp" },
"2": { "name": "entity.name.tag.jsp" }
},
"endCaptures": {
"1": { "name": "entity.name.tag.jsp" },
"2": { "name": "punctuation.definition.tag.jsp" }
},
"patterns": [
{
"match": "\\{(?=\\s*(%>|$))",
"comment": "consume trailing curly brackets for fragmented scriptlets"
},
{ "include": "source.java" }
]
},
"expression": {
"name": "string.template.expression.jsp",
"contentName": "meta.embedded.block.java",
"begin": "[$#]\\{",
"end": "\\}",
"beginCaptures": {
"0": { "name": "punctuation.definition.template-expression.begin.jsp" }
},
"endCaptures": {
"0": { "name": "punctuation.definition.template-expression.end.jsp" }
},
"patterns": [
{ "include": "#escape" },
{ "include": "source.java" }
]
},
"escape": {
"match": "\\\\.",
"name": "constant.character.escape.jsp"
}
}
}

View file

@ -1,6 +1,8 @@
{ {
"information_for_contributors": [ "information_for_contributors": [
"This file has been copied from https://github.com/eclipse/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/org.eclipse.buildship.kotlindsl.provider/kotlin.tmLanguage.json" "This file has been copied from https://github.com/eclipse/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/org.eclipse.buildship.kotlindsl.provider/kotlin.tmLanguage.json",
"The original file was licensed under the Eclipse Public License, Version 1.0",
"https://github.com/eclipse-buildship/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/README.md"
], ],
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "Kotlin", "name": "Kotlin",

View file

@ -3,7 +3,10 @@
"scopeName": "source.toml", "scopeName": "source.toml",
"uuid": "8b4e5008-c50d-11ea-a91b-54ee75aeeb97", "uuid": "8b4e5008-c50d-11ea-a91b-54ee75aeeb97",
"information_for_contributors": [ "information_for_contributors": [
"Originally was maintained by aster (galaster@foxmail.com). This notice is only kept here for the record, please don't send e-mails about bugs and other issues." "Originally was maintained by aster (galaster@foxmail.com). This notice is only kept here for the record, please don't send e-mails about bugs and other issues.",
"This file has been copied from https://github.com/kkiyama117/coc-toml/blob/main/toml.tmLanguage.json",
"The original file was licensed under the MIT License",
"https://github.com/kkiyama117/coc-toml/blob/main/LICENSE"
], ],
"patterns": [ "patterns": [
{ {

View file

@ -54,6 +54,7 @@
<StreamGeometry x:Key="Icons.GitFlow.Feature">M939 94v710L512 998 85 805V94h-64A21 21 0 010 73v-0C0 61 10 51 21 51h981c12 0 21 10 21 21v0c0 12-10 21-21 21h-64zm-536 588L512 624l109 58c6 3 13 4 20 3a32 32 0 0026-37l-21-122 88-87c5-5 8-11 9-18a32 32 0 00-27-37l-122-18-54-111a32 32 0 00-57 0l-54 111-122 18c-7 1-13 4-18 9a33 33 0 001 46l88 87-21 122c-1 7-0 14 3 20a32 32 0 0043 14z</StreamGeometry> <StreamGeometry x:Key="Icons.GitFlow.Feature">M939 94v710L512 998 85 805V94h-64A21 21 0 010 73v-0C0 61 10 51 21 51h981c12 0 21 10 21 21v0c0 12-10 21-21 21h-64zm-536 588L512 624l109 58c6 3 13 4 20 3a32 32 0 0026-37l-21-122 88-87c5-5 8-11 9-18a32 32 0 00-27-37l-122-18-54-111a32 32 0 00-57 0l-54 111-122 18c-7 1-13 4-18 9a33 33 0 001 46l88 87-21 122c-1 7-0 14 3 20a32 32 0 0043 14z</StreamGeometry>
<StreamGeometry x:Key="Icons.GitFlow.Hotfix">M236 542a32 32 0 109 63l86-12a180 180 0 0022 78l-71 47a32 32 0 1035 53l75-50a176 176 0 00166 40L326 529zM512 16C238 16 16 238 16 512s222 496 496 496 496-222 496-496S786 16 512 16zm0 896c-221 0-400-179-400-400a398 398 0 0186-247l561 561A398 398 0 01512 912zm314-154L690 622a179 179 0 004-29l85 12a32 32 0 109-63l-94-13v-49l94-13a32 32 0 10-9-63l-87 12a180 180 0 00-20-62l71-47A32 32 0 10708 252l-75 50a181 181 0 00-252 10l-115-115A398 398 0 01512 112c221 0 400 179 400 400a398 398 0 01-86 247z</StreamGeometry> <StreamGeometry x:Key="Icons.GitFlow.Hotfix">M236 542a32 32 0 109 63l86-12a180 180 0 0022 78l-71 47a32 32 0 1035 53l75-50a176 176 0 00166 40L326 529zM512 16C238 16 16 238 16 512s222 496 496 496 496-222 496-496S786 16 512 16zm0 896c-221 0-400-179-400-400a398 398 0 0186-247l561 561A398 398 0 01512 912zm314-154L690 622a179 179 0 004-29l85 12a32 32 0 109-63l-94-13v-49l94-13a32 32 0 10-9-63l-87 12a180 180 0 00-20-62l71-47A32 32 0 10708 252l-75 50a181 181 0 00-252 10l-115-115A398 398 0 01512 112c221 0 400 179 400 400a398 398 0 01-86 247z</StreamGeometry>
<StreamGeometry x:Key="Icons.GitFlow.Release">M884 159l-18-18a43 43 0 00-38-12l-235 43a166 166 0 00-101 60L400 349a128 128 0 00-148 47l-120 171a21 21 0 005 29l17 12a128 128 0 00178-32l27-38 124 124-38 27a128 128 0 00-32 178l12 17a21 21 0 0029 5l171-120a128 128 0 0047-148l117-92A166 166 0 00853 431l43-235a43 43 0 00-12-38zm-177 249a64 64 0 110-90 64 64 0 010 90zm-373 312a21 21 0 010 30l-139 139a21 21 0 01-30 0l-30-30a21 21 0 010-30l139-139a21 21 0 0130 0z</StreamGeometry> <StreamGeometry x:Key="Icons.GitFlow.Release">M884 159l-18-18a43 43 0 00-38-12l-235 43a166 166 0 00-101 60L400 349a128 128 0 00-148 47l-120 171a21 21 0 005 29l17 12a128 128 0 00178-32l27-38 124 124-38 27a128 128 0 00-32 178l12 17a21 21 0 0029 5l171-120a128 128 0 0047-148l117-92A166 166 0 00853 431l43-235a43 43 0 00-12-38zm-177 249a64 64 0 110-90 64 64 0 010 90zm-373 312a21 21 0 010 30l-139 139a21 21 0 01-30 0l-30-30a21 21 0 010-30l139-139a21 21 0 0130 0z</StreamGeometry>
<StreamGeometry x:Key="Icons.Github">M525 0C235 0 0 235 0 525c0 232 150 429 359 498 26 5 36-11 36-25 0-12-1-54-1-97-146 31-176-63-176-63-23-61-58-76-58-76-48-32 3-32 3-32 53 3 81 54 81 54 47 80 123 57 153 43 4-34 18-57 33-70-116-12-239-57-239-259 0-57 21-104 54-141-5-13-23-67 5-139 0 0 44-14 144 54 42-11 87-17 131-17s90 6 131 17C756 203 801 217 801 217c29 72 10 126 5 139 34 37 54 83 54 141 0 202-123 246-240 259 19 17 36 48 36 97 0 70-1 127-1 144 0 14 10 30 36 25 209-70 359-266 359-498C1050 235 814 0 525 0z</StreamGeometry>
<StreamGeometry x:Key="Icons.GitIgnore">M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z</StreamGeometry> <StreamGeometry x:Key="Icons.GitIgnore">M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z</StreamGeometry>
<StreamGeometry x:Key="Icons.Grid">M30 271l241 0 0-241-241 0 0 241zM392 271l241 0 0-241-241 0 0 241zM753 30l0 241 241 0 0-241-241 0zM30 632l241 0 0-241-241 0 0 241zM392 632l241 0 0-241-241 0 0 241zM753 632l241 0 0-241-241 0 0 241zM30 994l241 0 0-241-241 0 0 241zM392 994l241 0 0-241-241 0 0 241zM753 994l241 0 0-241-241 0 0 241z</StreamGeometry> <StreamGeometry x:Key="Icons.Grid">M30 271l241 0 0-241-241 0 0 241zM392 271l241 0 0-241-241 0 0 241zM753 30l0 241 241 0 0-241-241 0zM30 632l241 0 0-241-241 0 0 241zM392 632l241 0 0-241-241 0 0 241zM753 632l241 0 0-241-241 0 0 241zM30 994l241 0 0-241-241 0 0 241zM392 994l241 0 0-241-241 0 0 241zM753 994l241 0 0-241-241 0 0 241z</StreamGeometry>
<StreamGeometry x:Key="Icons.Head">M0 512M1024 512M512 0M512 1024M955 323q0 23-16 39l-414 414-78 78q-16 16-39 16t-39-16l-78-78-207-207q-16-16-16-39t16-39l78-78q16-16 39-16t39 16l168 169 375-375q16-16 39-16t39 16l78 78q16 16 16 39z</StreamGeometry> <StreamGeometry x:Key="Icons.Head">M0 512M1024 512M512 0M512 1024M955 323q0 23-16 39l-414 414-78 78q-16 16-39 16t-39-16l-78-78-207-207q-16-16-16-39t16-39l78-78q16-16 39-16t39 16l168 169 375-375q16-16 39-16t39 16l78 78q16 16 16 39z</StreamGeometry>

View file

@ -4,11 +4,6 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">Info</x:String> <x:String x:Key="Text.About" xml:space="preserve">Info</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">Über SourceGit</x:String> <x:String x:Key="Text.About.Menu" xml:space="preserve">Über SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Erstellt mit </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• Grafik gerendert durch </x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• Texteditor von </x:String>
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• Monospace-Schriftarten von </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Quelltext findest du auf </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Open Source &amp; freier Git GUI Client</x:String> <x:String x:Key="Text.About.SubTitle" xml:space="preserve">Open Source &amp; freier Git GUI Client</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Worktree hinzufügen</x:String> <x:String x:Key="Text.AddWorktree" xml:space="preserve">Worktree hinzufügen</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Was auschecken:</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Was auschecken:</x:String>
@ -25,18 +20,10 @@
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Verwende OpenAI, um Commit-Nachrichten zu generieren</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Verwende OpenAI, um Commit-Nachrichten zu generieren</x:String>
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">Als Commit-Nachricht verwenden</x:String> <x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">Als Commit-Nachricht verwenden</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String> <x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Fehler</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Fehler werfen und anwenden des Patches verweigern</x:String>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Alle Fehler</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Ähnlich wie 'Fehler', zeigt aber mehr an</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">Patch-Datei:</x:String> <x:String x:Key="Text.Apply.File" xml:space="preserve">Patch-Datei:</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Wähle die anzuwendende .patch-Datei</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Wähle die anzuwendende .patch-Datei</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignoriere Leerzeichenänderungen</x:String> <x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignoriere Leerzeichenänderungen</x:String>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Keine Warnungen</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Keine Warnung vor Leerzeichen am Zeilenende</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Patch anwenden</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">Patch anwenden</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Warnen</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Gibt eine Warnung für ein paar solcher Fehler aus, aber wendet es an</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Leerzeichen:</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">Leerzeichen:</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">Stash anwenden</x:String> <x:String x:Key="Text.ApplyStash" xml:space="preserve">Stash anwenden</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Nach dem Anwenden löschen</x:String> <x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Nach dem Anwenden löschen</x:String>
@ -509,7 +496,7 @@
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Remote löschen</x:String> <x:String x:Key="Text.PruneRemote" xml:space="preserve">Remote löschen</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Ziel:</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Ziel:</x:String>
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Worktrees löschen</x:String> <x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Worktrees löschen</x:String>
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Worktree Informationen in `$GIT_DIR/worktrees` löschen</x:String> <x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Worktree Informationen in `$GIT_COMMON_DIR/worktrees` löschen</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Remote-Branch:</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Remote-Branch:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Alle Branches fetchen</x:String> <x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Alle Branches fetchen</x:String>

View file

@ -1,11 +1,6 @@
<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">
<x:String x:Key="Text.About" xml:space="preserve">About</x:String> <x:String x:Key="Text.About" xml:space="preserve">About</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">About SourceGit</x:String> <x:String x:Key="Text.About.Menu" xml:space="preserve">About SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Build with </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• Chart is rendered by </x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• TextEditor from </x:String>
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• Monospace fonts come from </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Source code can be found at </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Opensource &amp; Free Git GUI Client</x:String> <x:String x:Key="Text.About.SubTitle" xml:space="preserve">Opensource &amp; Free Git GUI Client</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Add Worktree</x:String> <x:String x:Key="Text.AddWorktree" xml:space="preserve">Add Worktree</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">What to Checkout:</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">What to Checkout:</x:String>
@ -22,18 +17,10 @@
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use AI to generate commit message</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use AI to generate commit message</x:String>
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APPLY AS COMMIT MESSAGE</x:String> <x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APPLY AS COMMIT MESSAGE</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String> <x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Error</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Raise errors and refuses to apply the patch</x:String>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Error All</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similar to 'error', but shows more</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">Patch File:</x:String> <x:String x:Key="Text.Apply.File" xml:space="preserve">Patch File:</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Select .patch file to apply</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Select .patch file to apply</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignore whitespace changes</x:String> <x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignore whitespace changes</x:String>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">No Warn</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Turns off the trailing whitespace warning</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Apply Patch</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">Apply Patch</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Warn</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Outputs warnings for a few such errors, but applies</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Whitespace:</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">Whitespace:</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">Apply Stash</x:String> <x:String x:Key="Text.ApplyStash" xml:space="preserve">Apply Stash</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Delete after applying</x:String> <x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Delete after applying</x:String>
@ -484,6 +471,7 @@
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String> <x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Show author time instead of commit time in graph</x:String> <x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Show author time instead of commit time in graph</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Show children in the commit details</x:String> <x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Show children in the commit details</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Show tags in commit graph</x:String>
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String> <x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String>
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String> <x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Enable Auto CRLF</x:String> <x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Enable Auto CRLF</x:String>
@ -512,7 +500,7 @@
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Prune Remote</x:String> <x:String x:Key="Text.PruneRemote" xml:space="preserve">Prune Remote</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Target:</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Prune Worktrees</x:String> <x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Prune Worktrees</x:String>
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Prune worktree information in `$GIT_DIR/worktrees`</x:String> <x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Prune worktree information in `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Remote Branch:</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Remote Branch:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch all branches</x:String> <x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch all branches</x:String>

View file

@ -4,11 +4,6 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">Acerca de</x:String> <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.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.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.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" 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" xml:space="preserve">Qué Checkout:</x:String>
@ -25,18 +20,10 @@
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usar OpenAI para generar mensaje de commit</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usar OpenAI para generar mensaje de commit</x:String>
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APLICAR CÓMO MENSAJE DE COMMIT</x:String> <x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APLICAR CÓMO MENSAJE DE COMMIT</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Aplicar Parche</x:String> <x:String x:Key="Text.Apply" xml:space="preserve">Aplicar Parche</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 parche</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 del Parche:</x:String> <x:String x:Key="Text.Apply.File" xml:space="preserve">Archivo del Parche:</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.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.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 Parche</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">Aplicar Parche</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.Apply.WS" xml:space="preserve">Espacios en Blanco:</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">Aplicar Stash</x:String> <x:String x:Key="Text.ApplyStash" xml:space="preserve">Aplicar Stash</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Borrar después de aplicar</x:String> <x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Borrar después de aplicar</x:String>
@ -516,7 +503,7 @@
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Podar Remoto</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.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" 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.PruneWorktrees.Tip" xml:space="preserve">Podar información de worktree en `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</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 Remota:</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Rama Remota:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch todas las ramas</x:String> <x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch todas las ramas</x:String>

View file

@ -4,11 +4,6 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">À propos</x:String> <x:String x:Key="Text.About" xml:space="preserve">À propos</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">À propos de SourceGit</x:String> <x:String x:Key="Text.About.Menu" xml:space="preserve">À propos de SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Compilé avec </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• Le graphique est rendu par </x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• TextEditor de </x:String>
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• Les polices Monospace proviennent de </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Le code source est disponible sur </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Client Git Open Source et Gratuit</x:String> <x:String x:Key="Text.About.SubTitle" xml:space="preserve">Client Git Open Source et Gratuit</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Ajouter un Worktree</x:String> <x:String x:Key="Text.AddWorktree" xml:space="preserve">Ajouter un Worktree</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Que récupérer :</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Que récupérer :</x:String>
@ -23,18 +18,10 @@
<x:String x:Key="Text.AIAssistant" xml:space="preserve">Assistant IA</x:String> <x:String x:Key="Text.AIAssistant" xml:space="preserve">Assistant IA</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Utiliser l'IA pour générer un message de commit</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Utiliser l'IA pour générer un message de commit</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Appliquer</x:String> <x:String x:Key="Text.Apply" xml:space="preserve">Appliquer</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Erreur</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Soulever les erreurs et refuser d'appliquer le patch</x:String>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Toutes les erreurs</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similaire à 'Erreur', mais plus détaillé</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">Fichier de patch :</x:String> <x:String x:Key="Text.Apply.File" xml:space="preserve">Fichier de patch :</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Selectionner le fichier .patch à appliquer</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Selectionner le fichier .patch à appliquer</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorer les changements d'espaces blancs</x:String> <x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorer les changements d'espaces blancs</x:String>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Pas d'avertissement</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Désactiver l'avertissement sur les espaces blancs terminaux</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Appliquer le patch</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">Appliquer le patch</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Avertissement</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Affiche des avertissements pour ce type d'erreurs tout en appliquant le patch</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espaces blancs :</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">Espaces blancs :</x:String>
<x:String x:Key="Text.Archive" xml:space="preserve">Archiver...</x:String> <x:String x:Key="Text.Archive" xml:space="preserve">Archiver...</x:String>
<x:String x:Key="Text.Archive.File" xml:space="preserve">Enregistrer l'archive sous :</x:String> <x:String x:Key="Text.Archive.File" xml:space="preserve">Enregistrer l'archive sous :</x:String>
@ -484,7 +471,7 @@
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Élaguer une branche distant</x:String> <!-- If it is indeed about a branch --> <x:String x:Key="Text.PruneRemote" xml:space="preserve">Élaguer une branche distant</x:String> <!-- If it is indeed about a branch -->
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Cible :</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Cible :</x:String>
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Élaguer les Worktrees</x:String> <x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Élaguer les Worktrees</x:String>
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve"> Élaguer les information de worktree dans `$GIT_DIR/worktrees`</x:String> <x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve"> Élaguer les information de worktree dans `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branche distante :</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branche distante :</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch toutes les branches</x:String> <x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch toutes les branches</x:String>
@ -697,4 +684,68 @@
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">Verrouiller</x:String> <x:String x:Key="Text.Worktree.Lock" xml:space="preserve">Verrouiller</x:String>
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">Supprimer</x:String> <x:String x:Key="Text.Worktree.Remove" xml:space="preserve">Supprimer</x:String>
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">Déverrouiller</x:String> <x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">Déverrouiller</x:String>
<x:String x:Key="Text.AIAssistant.Regen" xml:space="preserve">RE-GÉNÉRER</x:String>
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APPLIQUER COMME MESSAGE DE COMMIT</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">Appliquer le Stash</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Supprimer après l'application</x:String>
<x:String x:Key="Text.ApplyStash.RestoreIndex" xml:space="preserve">Rétablir les modifications de l'index</x:String>
<x:String x:Key="Text.ApplyStash.Stash" xml:space="preserve">Stash:</x:String>
<x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Action personnalisée</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Branche en amont invalide!</x:String>
<x:String x:Key="Text.Clone.RecurseSubmodules" xml:space="preserve">Initialiser et mettre à jour les sous-modules</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Branch" xml:space="preserve">Branche</x:String>
<x:String x:Key="Text.Configure.CustomAction.WaitForExit" xml:space="preserve">Attendre la fin de l'action</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Les espaces seront remplacés par des tirets.</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.Path" xml:space="preserve">Chemin:</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.TipForGroup" xml:space="preserve">Tous les enfants seront retirés de la liste.</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.TipForRepository" xml:space="preserve">Cela le supprimera uniquement de la liste, pas du disque !</x:String>
<x:String x:Key="Text.Diff.First" xml:space="preserve">Première différence</x:String>
<x:String x:Key="Text.Diff.Last" xml:space="preserve">Dernière différence</x:String>
<x:String x:Key="Text.InProgress.CherryPick.Head" xml:space="preserve">Traitement du commit</x:String>
<x:String x:Key="Text.InProgress.Merge.Operating" xml:space="preserve">Fusionnement</x:String>
<x:String x:Key="Text.InProgress.Rebase.StoppedAt" xml:space="preserve">Arrêté à</x:String>
<x:String x:Key="Text.InProgress.Revert.Head" xml:space="preserve">Annulation du commit</x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">Source:</x:String>
<x:String x:Key="Text.MergeMultiple" xml:space="preserve">Fusionner (Plusieurs)</x:String>
<x:String x:Key="Text.MergeMultiple.CommitChanges" xml:space="preserve">Commit tous les changement</x:String>
<x:String x:Key="Text.MergeMultiple.Strategy" xml:space="preserve">Stratégie:</x:String>
<x:String x:Key="Text.MergeMultiple.Targets" xml:space="preserve">Cibles:</x:String>
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Activer le streaming</x:String>
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Largeur de tab dans l'éditeur</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Taille de police</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Défaut</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Éditeur</x:String>
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">Format de date</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Afficher les enfants dans les détails du commit</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Afficher les tags dans le graphique des commits</x:String>
<x:String x:Key="Text.Preferences.Git.SSLVerify" xml:space="preserve">Activer la vérification HTTP SSL</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Actions personnalisées</x:String>
<x:String x:Key="Text.Repository.FilterCommits" xml:space="preserve">Visibilité dans le graphique</x:String>
<x:String x:Key="Text.Repository.FilterCommits.Default" xml:space="preserve">Réinitialiser</x:String>
<x:String x:Key="Text.Repository.FilterCommits.Exclude" xml:space="preserve">Cacher dans le graphique des commits</x:String>
<x:String x:Key="Text.Repository.FilterCommits.Include" xml:space="preserve">Filtrer dans le graphique des commits</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout" xml:space="preserve">DISPOSITION</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout.Horizontal" xml:space="preserve">Horizontal</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout.Vertical" xml:space="preserve">Vertical</x:String>
<x:String x:Key="Text.Repository.HistoriesOrder" xml:space="preserve">ORDRE DES COMMITS</x:String>
<x:String x:Key="Text.Repository.HistoriesOrder.ByDate" xml:space="preserve">Date du commit</x:String>
<x:String x:Key="Text.Repository.HistoriesOrder.Topo" xml:space="preserve">Topologiquement</x:String>
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">EFFACER LES NOTIFICATIONS</x:String>
<x:String x:Key="Text.Repository.Skip" xml:space="preserve">PASSER</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Par date de créateur</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Par nom (Croissant)</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Par nom (Décroissant)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Trier</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Utiliser le temps relatif dans les historiques</x:String>
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">Analyser les repositories</x:String>
<x:String x:Key="Text.SetUpstream" xml:space="preserve">Définir la branche suivie</x:String>
<x:String x:Key="Text.SetUpstream.Local" xml:space="preserve">Branche:</x:String>
<x:String x:Key="Text.SetUpstream.Unset" xml:space="preserve">Retirer la branche amont</x:String>
<x:String x:Key="Text.SetUpstream.Upstream" xml:space="preserve">En amont:</x:String>
<x:String x:Key="Text.SHALinkCM.NavigateTo" xml:space="preserve">Aller sur</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Restauration automatique après le stashing</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">Vos fichiers de travail restent inchangés, mais une sauvegarde est enregistrée.</x:String>
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Sauvegarder en tant que patch...</x:String>
<x:String x:Key="Text.WorkingCopy.CommitToEdit" xml:space="preserve">Commit (Modifier)</x:String>
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">SignOff</x:String>
</ResourceDictionary> </ResourceDictionary>

View file

@ -4,11 +4,6 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">Informazioni</x:String> <x:String x:Key="Text.About" xml:space="preserve">Informazioni</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">Informazioni su SourceGit</x:String> <x:String x:Key="Text.About.Menu" xml:space="preserve">Informazioni su SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Creato con </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• Il grafico è reso da </x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• Editor di testo da </x:String>
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• I font monospaziati provengono da </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Il codice sorgente è disponibile su </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Client GUI Git open source e gratuito</x:String> <x:String x:Key="Text.About.SubTitle" xml:space="preserve">Client GUI Git open source e gratuito</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Aggiungi Worktree</x:String> <x:String x:Key="Text.AddWorktree" xml:space="preserve">Aggiungi Worktree</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Di cosa fare il checkout:</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Di cosa fare il checkout:</x:String>
@ -25,18 +20,10 @@
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usa AI per generare il messaggio di commit</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usa AI per generare il messaggio di commit</x:String>
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APPLICA COME MESSAGGIO DI COMMIT</x:String> <x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APPLICA COME MESSAGGIO DI COMMIT</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Applica</x:String> <x:String x:Key="Text.Apply" xml:space="preserve">Applica</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Errore</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Genera errori e si rifiuta di applicare la patch</x:String>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Tutti gli errori</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Simile a 'errore', ma mostra di più</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">File Patch:</x:String> <x:String x:Key="Text.Apply.File" xml:space="preserve">File Patch:</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Seleziona file .patch da applicare</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Seleziona file .patch da applicare</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignora modifiche agli spazi</x:String> <x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignora modifiche agli spazi</x:String>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Nessun avviso</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Disattiva l'avviso sugli spazi finali</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Applica Patch</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">Applica Patch</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Avviso</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Mostra avvisi per alcuni errori, ma applica comunque</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Spazi:</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">Spazi:</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">Applica lo stash</x:String> <x:String x:Key="Text.ApplyStash" xml:space="preserve">Applica lo stash</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Rimuovi dopo aver applicato</x:String> <x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Rimuovi dopo aver applicato</x:String>
@ -467,7 +454,8 @@
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Abilita streaming</x:String> <x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Abilita streaming</x:String>
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">ASPETTO</x:String> <x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">ASPETTO</x:String>
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Font Predefinito</x:String> <x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Font Predefinito</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Font Size</x:String> <x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Larghezza della Tab Editor</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Dimensione Font</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Dimensione Font Predefinita</x:String> <x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Dimensione Font Predefinita</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Dimensione Font Editor</x:String> <x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Dimensione Font Editor</x:String>
<x:String x:Key="Text.Preferences.Appearance.MonospaceFont" xml:space="preserve">Font Monospaziato</x:String> <x:String x:Key="Text.Preferences.Appearance.MonospaceFont" xml:space="preserve">Font Monospaziato</x:String>
@ -515,7 +503,7 @@
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Potatura Remota</x:String> <x:String x:Key="Text.PruneRemote" xml:space="preserve">Potatura Remota</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Destinazione:</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Destinazione:</x:String>
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Potatura Worktrees</x:String> <x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Potatura Worktrees</x:String>
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Potatura delle informazioni di worktree in `$GIT_DIR/worktrees`</x:String> <x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Potatura delle informazioni di worktree in `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Scarica</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">Scarica</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch Remoto:</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch Remoto:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Recupera tutti i branch</x:String> <x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Recupera tutti i branch</x:String>

View file

@ -29,11 +29,6 @@
<x:String x:Key="Text.About" xml:space="preserve">Sobre</x:String> <x:String x:Key="Text.About" xml:space="preserve">Sobre</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">Sobre o SourceGit</x:String> <x:String x:Key="Text.About.Menu" xml:space="preserve">Sobre o SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Construído com </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• Gráfico desenhado por </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">• Fontes monoespaçadas de </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Código-fonte pode ser encontrado em </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Cliente Git GUI Livre e de Código Aberto</x:String> <x:String x:Key="Text.About.SubTitle" xml:space="preserve">Cliente Git GUI Livre e de Código Aberto</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Adicionar Worktree</x:String> <x:String x:Key="Text.AddWorktree" xml:space="preserve">Adicionar Worktree</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">O que Checar:</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">O que Checar:</x:String>
@ -48,18 +43,10 @@
<x:String x:Key="Text.AIAssistant" xml:space="preserve">Assietente IA</x:String> <x:String x:Key="Text.AIAssistant" xml:space="preserve">Assietente IA</x:String>
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Utilizar IA para gerar mensagem de commit</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Utilizar IA para gerar mensagem de commit</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String> <x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Erro</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Erros levantados e se recusa a aplicar o patch</x:String>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Erro Total</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Semelhante a 'erro', mas mostra mais</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">Arquivo de Patch:</x:String> <x:String x:Key="Text.Apply.File" xml:space="preserve">Arquivo de Patch:</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Selecione o arquivo .patch para aplicar</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Selecione o arquivo .patch para aplicar</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorar mudanças de espaço em branco</x:String> <x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorar mudanças de espaço em branco</x:String>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Sem Aviso</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Desativa o aviso de espaço em branco no final</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Aplicar Patch</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">Aviso</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Emite avisos para alguns erros, mas aplica</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espaço em Branco:</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">Espaço em Branco:</x:String>
<x:String x:Key="Text.Archive" xml:space="preserve">Arquivar...</x:String> <x:String x:Key="Text.Archive" xml:space="preserve">Arquivar...</x:String>
<x:String x:Key="Text.Archive.File" xml:space="preserve">Salvar Arquivo Como:</x:String> <x:String x:Key="Text.Archive.File" xml:space="preserve">Salvar Arquivo Como:</x:String>
@ -498,7 +485,7 @@
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Prunar Remoto</x:String> <x:String x:Key="Text.PruneRemote" xml:space="preserve">Prunar Remoto</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Alvo:</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Alvo:</x:String>
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Podar Worktrees</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 informações de worktree em `$GIT_DIR/worktrees`</x:String> <x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Podar informações de worktree em `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Puxar</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">Puxar</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch Remoto:</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch Remoto:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Buscar todos os branches</x:String> <x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Buscar todos os branches</x:String>

View file

@ -4,11 +4,6 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">О программе</x:String> <x:String x:Key="Text.About" xml:space="preserve">О программе</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">О SourceGit</x:String> <x:String x:Key="Text.About.Menu" xml:space="preserve">О SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Сборка с </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• Диаграмма отображается с помощью</x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• Текстовый редактор от </x:String>
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• Моноширинные шрифты взяты из </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Исходный код можно найти по адресу </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Бесплатный графический клиент Git с исходным кодом</x:String> <x:String x:Key="Text.About.SubTitle" xml:space="preserve">Бесплатный графический клиент Git с исходным кодом</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Добавить рабочий каталог</x:String> <x:String x:Key="Text.AddWorktree" xml:space="preserve">Добавить рабочий каталог</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Переключиться на:</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">Переключиться на:</x:String>
@ -25,18 +20,10 @@
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Использовать OpenAI для создания сообщения о ревизии</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Использовать OpenAI для создания сообщения о ревизии</x:String>
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">ПРИМЕНИТЬ КАК СООБЩЕНИЕ РЕВИЗИИ</x:String> <x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">ПРИМЕНИТЬ КАК СООБЩЕНИЕ РЕВИЗИИ</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Исправить </x:String> <x:String x:Key="Text.Apply" 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.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.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>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Нет предупреждений</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Отключить предупреждения о пробелах в конце</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Применить заплатку</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">Применить заплатку</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Предупреждать</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Выдавать предупреждения о нескольких таких ошибках, но применять</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Пробел:</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">Пробел:</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">Отложить</x:String> <x:String x:Key="Text.ApplyStash" xml:space="preserve">Отложить</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Удалить после применения</x:String> <x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Удалить после применения</x:String>
@ -488,6 +475,7 @@
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Максимальная длина истории</x:String> <x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Максимальная длина истории</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Показывать время автора вместо времени ревизии на графике</x:String> <x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Показывать время автора вместо времени ревизии на графике</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Показать наследника в деталях комментария</x:String> <x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Показать наследника в деталях комментария</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Показывать метки на графике</x:String>
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Длина темы ревизии</x:String> <x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Длина темы ревизии</x:String>
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String> <x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Включить автозавершение CRLF</x:String> <x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Включить автозавершение CRLF</x:String>
@ -516,7 +504,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_COMMON_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>

View file

@ -4,11 +4,6 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">关于软件</x:String> <x:String x:Key="Text.About" xml:space="preserve">关于软件</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">关于本软件</x:String> <x:String x:Key="Text.About.Menu" xml:space="preserve">关于本软件</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• 项目依赖于 </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• 图表绘制组件来自 </x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• 文本编辑器使用 </x:String>
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• 等宽字体来自于 </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• 项目源代码地址 </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">开源免费的Git客户端</x:String> <x:String x:Key="Text.About.SubTitle" xml:space="preserve">开源免费的Git客户端</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作树</x:String> <x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作树</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">检出分支方式 </x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">检出分支方式 </x:String>
@ -25,18 +20,10 @@
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用AI助手生成提交信息</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用AI助手生成提交信息</x:String>
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">应用本次生成</x:String> <x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">应用本次生成</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">应用补丁(apply)</x:String> <x:String x:Key="Text.Apply" xml:space="preserve">应用补丁(apply)</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">错误</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">输出错误,并终止应用补丁</x:String>
<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.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">选择补丁文件</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">选择补丁文件</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>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">忽略</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">关闭所有警告</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">应用补丁</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">应用补丁</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">警告</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">应用补丁,输出关于空白符的警告</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">空白符号处理 </x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">空白符号处理 </x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">应用贮藏</x:String> <x:String x:Key="Text.ApplyStash" xml:space="preserve">应用贮藏</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">在成功应用后丢弃该贮藏</x:String> <x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">在成功应用后丢弃该贮藏</x:String>
@ -488,6 +475,7 @@
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">最大历史提交数</x:String> <x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">最大历史提交数</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">在提交路线图中显示修改时间而非提交时间</x:String> <x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">在提交路线图中显示修改时间而非提交时间</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">在提交详情页中显示子提交列表</x:String> <x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">在提交详情页中显示子提交列表</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">在提交路线图中显示标签</x:String>
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">SUBJECT字数检测</x:String> <x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">SUBJECT字数检测</x:String>
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT配置</x:String> <x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT配置</x:String>
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">自动换行转换</x:String> <x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">自动换行转换</x:String>
@ -516,7 +504,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_COMMON_DIR/worktrees`中的无效工作树信息</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</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>

View file

@ -4,11 +4,6 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">關於</x:String> <x:String x:Key="Text.About" xml:space="preserve">關於</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">關於 SourceGit</x:String> <x:String x:Key="Text.About.Menu" xml:space="preserve">關於 SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• 專案依賴於 </x:String>
<x:String x:Key="Text.About.Chart" xml:space="preserve">• 圖表繪製元件來自 </x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• 文字編輯器使用 </x:String>
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• 等寬字型來自於 </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• 專案原始碼網址 </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">開源免費的 Git 客戶端</x:String> <x:String x:Key="Text.About.SubTitle" xml:space="preserve">開源免費的 Git 客戶端</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作區</x:String> <x:String x:Key="Text.AddWorktree" xml:space="preserve">新增工作區</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">簽出分支方式:</x:String> <x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">簽出分支方式:</x:String>
@ -25,18 +20,10 @@
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用 AI 產生提交訊息</x:String> <x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用 AI 產生提交訊息</x:String>
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">套用為提交訊息</x:String> <x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">套用為提交訊息</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">套用修補檔 (apply patch)</x:String> <x:String x:Key="Text.Apply" xml:space="preserve">套用修補檔 (apply patch)</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">錯誤</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">輸出錯誤,並中止套用修補檔</x:String>
<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.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">選擇修補檔</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">選擇修補檔</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>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">忽略</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">關閉所有警告</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">套用修補檔</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">套用修補檔</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">警告</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">套用修補檔,輸出關於空白字元的警告</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">空白字元處理:</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">空白字元處理:</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">套用擱置變更</x:String> <x:String x:Key="Text.ApplyStash" xml:space="preserve">套用擱置變更</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">套用擱置變更後刪除</x:String> <x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">套用擱置變更後刪除</x:String>
@ -487,6 +474,7 @@
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">最大歷史提交數</x:String> <x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">最大歷史提交數</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">在提交路線圖中顯示修改時間而非提交時間</x:String> <x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">在提交路線圖中顯示修改時間而非提交時間</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">在提交詳細資訊中顯示後續提交</x:String> <x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">在提交詳細資訊中顯示後續提交</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">在路線圖中顯示標籤</x:String>
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">提交標題字數偵測</x:String> <x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">提交標題字數偵測</x:String>
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">Git 設定</x:String> <x:String x:Key="Text.Preferences.Git" xml:space="preserve">Git 設定</x:String>
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">自動換行轉換</x:String> <x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">自動換行轉換</x:String>
@ -515,7 +503,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_COMMON_DIR/worktrees` 中的無效工作區資訊</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">拉取 (pull)</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">拉取 (pull)</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>

View file

@ -10,7 +10,6 @@
<Color x:Key="Color.Contents">#FFFAFAFA</Color> <Color x:Key="Color.Contents">#FFFAFAFA</Color>
<Color x:Key="Color.Badge">#FFB0CEE8</Color> <Color x:Key="Color.Badge">#FFB0CEE8</Color>
<Color x:Key="Color.BadgeFG">#FF1F1F1F</Color> <Color x:Key="Color.BadgeFG">#FF1F1F1F</Color>
<Color x:Key="Color.DecoratorTag">DarkGreen</Color>
<Color x:Key="Color.Conflict">#FF836C2E</Color> <Color x:Key="Color.Conflict">#FF836C2E</Color>
<Color x:Key="Color.ConflictForeground">#FFFFFFFF</Color> <Color x:Key="Color.ConflictForeground">#FFFFFFFF</Color>
<Color x:Key="Color.Border0">#FFCFCFCF</Color> <Color x:Key="Color.Border0">#FFCFCFCF</Color>
@ -37,7 +36,6 @@
<Color x:Key="Color.Contents">#FF1C1C1C</Color> <Color x:Key="Color.Contents">#FF1C1C1C</Color>
<Color x:Key="Color.Badge">#FF8F8F8F</Color> <Color x:Key="Color.Badge">#FF8F8F8F</Color>
<Color x:Key="Color.BadgeFG">#FFDDDDDD</Color> <Color x:Key="Color.BadgeFG">#FFDDDDDD</Color>
<Color x:Key="Color.DecoratorTag">#84c88a</Color>
<Color x:Key="Color.Conflict">#FFFAFAD2</Color> <Color x:Key="Color.Conflict">#FFFAFAD2</Color>
<Color x:Key="Color.ConflictForeground">#FF252525</Color> <Color x:Key="Color.ConflictForeground">#FF252525</Color>
<Color x:Key="Color.Border0">#FF181818</Color> <Color x:Key="Color.Border0">#FF181818</Color>
@ -64,7 +62,6 @@
<SolidColorBrush x:Key="Brush.Contents" Color="{DynamicResource Color.Contents}"/> <SolidColorBrush x:Key="Brush.Contents" Color="{DynamicResource Color.Contents}"/>
<SolidColorBrush x:Key="Brush.Badge" Color="{DynamicResource Color.Badge}"/> <SolidColorBrush x:Key="Brush.Badge" Color="{DynamicResource Color.Badge}"/>
<SolidColorBrush x:Key="Brush.BadgeFG" Color="{DynamicResource Color.BadgeFG}"/> <SolidColorBrush x:Key="Brush.BadgeFG" Color="{DynamicResource Color.BadgeFG}"/>
<SolidColorBrush x:Key="Brush.DecoratorTag" Color="{DynamicResource Color.DecoratorTag}"/>
<SolidColorBrush x:Key="Brush.Conflict" Color="{DynamicResource Color.Conflict}"/> <SolidColorBrush x:Key="Brush.Conflict" Color="{DynamicResource Color.Conflict}"/>
<SolidColorBrush x:Key="Brush.ConflictForeground" Color="{DynamicResource Color.ConflictForeground}"/> <SolidColorBrush x:Key="Brush.ConflictForeground" Color="{DynamicResource Color.ConflictForeground}"/>
<SolidColorBrush x:Key="Brush.Border0" Color="{DynamicResource Color.Border0}"/> <SolidColorBrush x:Key="Brush.Border0" Color="{DynamicResource Color.Border0}"/>

View file

@ -46,8 +46,8 @@
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.5" /> <PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.5" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.5" /> <PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.5" />
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.5" Condition="'$(Configuration)' == 'Debug'" /> <PackageReference Include="Avalonia.Diagnostics" Version="11.2.5" Condition="'$(Configuration)' == 'Debug'" />
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.1.0" /> <PackageReference Include="Avalonia.AvaloniaEdit" Version="11.2.0" />
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" /> <PackageReference Include="AvaloniaEdit.TextMate" Version="11.2.0" />
<PackageReference Include="Azure.AI.OpenAI" Version="2.2.0-beta.2" /> <PackageReference Include="Azure.AI.OpenAI" Version="2.2.0-beta.2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" /> <PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" />

View file

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -21,12 +20,6 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _ignoreWhiteSpace, value); set => SetProperty(ref _ignoreWhiteSpace, value);
} }
public List<Models.ApplyWhiteSpaceMode> WhiteSpaceModes
{
get;
private set;
}
public Models.ApplyWhiteSpaceMode SelectedWhiteSpaceMode public Models.ApplyWhiteSpaceMode SelectedWhiteSpaceMode
{ {
get; get;
@ -37,23 +30,14 @@ namespace SourceGit.ViewModels
{ {
_repo = repo; _repo = repo;
WhiteSpaceModes = new List<Models.ApplyWhiteSpaceMode> { SelectedWhiteSpaceMode = Models.ApplyWhiteSpaceMode.Supported[0];
new Models.ApplyWhiteSpaceMode("Apply.NoWarn", "Apply.NoWarn.Desc", "nowarn"),
new Models.ApplyWhiteSpaceMode("Apply.Warn", "Apply.Warn.Desc", "warn"),
new Models.ApplyWhiteSpaceMode("Apply.Error", "Apply.Error.Desc", "error"),
new Models.ApplyWhiteSpaceMode("Apply.ErrorAll", "Apply.ErrorAll.Desc", "error-all")
};
SelectedWhiteSpaceMode = WhiteSpaceModes[0];
View = new Views.Apply() { DataContext = this }; View = new Views.Apply() { DataContext = this };
} }
public static ValidationResult ValidatePatchFile(string file, ValidationContext _) public static ValidationResult ValidatePatchFile(string file, ValidationContext _)
{ {
if (File.Exists(file)) if (File.Exists(file))
{
return ValidationResult.Success; return ValidationResult.Success;
}
return new ValidationResult($"File '{file}' can NOT be found!!!"); return new ValidationResult($"File '{file}' can NOT be found!!!");
} }

View file

@ -871,7 +871,7 @@ namespace SourceGit.ViewModels
return; return;
if (_repo.CanCreatePopup()) if (_repo.CanCreatePopup())
_repo.ShowAndStartPopup(new Merge(_repo, b, current.Name)); _repo.ShowAndStartPopup(new Merge(_repo, b, current.Name, true));
e.Handled = true; e.Handled = true;
}; };
@ -972,7 +972,7 @@ namespace SourceGit.ViewModels
merge.Click += (_, e) => merge.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) if (_repo.CanCreatePopup())
_repo.ShowPopup(new Merge(_repo, branch, current.Name)); _repo.ShowPopup(new Merge(_repo, branch, current.Name, false));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(merge); submenu.Items.Add(merge);
@ -1060,7 +1060,7 @@ namespace SourceGit.ViewModels
merge.Click += (_, e) => merge.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) if (_repo.CanCreatePopup())
_repo.ShowPopup(new Merge(_repo, branch, current.Name)); _repo.ShowPopup(new Merge(_repo, branch, current.Name, false));
e.Handled = true; e.Handled = true;
}; };

View file

@ -15,20 +15,20 @@ namespace SourceGit.ViewModels
get; get;
} }
public Models.MergeMode SelectedMode public Models.MergeMode Mode
{ {
get; get;
set; set;
} }
public Merge(Repository repo, Models.Branch source, string into) public Merge(Repository repo, Models.Branch source, string into, bool forceFastForward)
{ {
_repo = repo; _repo = repo;
_sourceName = source.FriendlyName; _sourceName = source.FriendlyName;
Source = source; Source = source;
Into = into; Into = into;
SelectedMode = AutoSelectMergeMode(); Mode = forceFastForward ? Models.MergeMode.Supported[1] : AutoSelectMergeMode();
View = new Views.Merge() { DataContext = this }; View = new Views.Merge() { DataContext = this };
} }
@ -39,7 +39,7 @@ namespace SourceGit.ViewModels
Source = source; Source = source;
Into = into; Into = into;
SelectedMode = AutoSelectMergeMode(); Mode = AutoSelectMergeMode();
View = new Views.Merge() { DataContext = this }; View = new Views.Merge() { DataContext = this };
} }
@ -50,7 +50,7 @@ namespace SourceGit.ViewModels
Source = source; Source = source;
Into = into; Into = into;
SelectedMode = AutoSelectMergeMode(); Mode = AutoSelectMergeMode();
View = new Views.Merge() { DataContext = this }; View = new Views.Merge() { DataContext = this };
} }
@ -61,7 +61,7 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
new Commands.Merge(_repo.FullPath, _sourceName, SelectedMode.Arg, SetProgressDescription).Exec(); new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg, SetProgressDescription).Exec();
CallUIThread(() => _repo.SetWatcherEnabled(true)); CallUIThread(() => _repo.SetWatcherEnabled(true));
return true; return true;
}); });
@ -72,12 +72,14 @@ namespace SourceGit.ViewModels
var config = new Commands.Config(_repo.FullPath).Get($"branch.{Into}.mergeoptions"); var config = new Commands.Config(_repo.FullPath).Get($"branch.{Into}.mergeoptions");
if (string.IsNullOrEmpty(config)) if (string.IsNullOrEmpty(config))
return Models.MergeMode.Supported[0]; return Models.MergeMode.Supported[0];
if (config.Equals("--no-ff", StringComparison.Ordinal)) if (config.Equals("--ff-only", StringComparison.Ordinal))
return Models.MergeMode.Supported[1]; return Models.MergeMode.Supported[1];
if (config.Equals("--squash", StringComparison.Ordinal)) if (config.Equals("--no-ff", StringComparison.Ordinal))
return Models.MergeMode.Supported[2]; return Models.MergeMode.Supported[2];
if (config.Equals("--no-commit", StringComparison.Ordinal) || config.Equals("--no-ff --no-commit", StringComparison.Ordinal)) if (config.Equals("--squash", StringComparison.Ordinal))
return Models.MergeMode.Supported[3]; return Models.MergeMode.Supported[3];
if (config.Equals("--no-commit", StringComparison.Ordinal) || config.Equals("--no-ff --no-commit", StringComparison.Ordinal))
return Models.MergeMode.Supported[4];
return Models.MergeMode.Supported[0]; return Models.MergeMode.Supported[0];
} }

View file

@ -183,6 +183,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _showTagsAsTree, value); set => SetProperty(ref _showTagsAsTree, value);
} }
public bool ShowTagsInGraph
{
get => _showTagsInGraph;
set => SetProperty(ref _showTagsInGraph, value);
}
public bool UseTwoColumnsLayoutInHistories public bool UseTwoColumnsLayoutInHistories
{ {
get => _useTwoColumnsLayoutInHistories; get => _useTwoColumnsLayoutInHistories;
@ -643,6 +649,7 @@ namespace SourceGit.ViewModels
private string _ignoreUpdateTag = string.Empty; private string _ignoreUpdateTag = string.Empty;
private bool _showTagsAsTree = false; private bool _showTagsAsTree = false;
private bool _showTagsInGraph = true;
private bool _useTwoColumnsLayoutInHistories = false; private bool _useTwoColumnsLayoutInHistories = false;
private bool _displayTimeAsPeriodInHistories = false; private bool _displayTimeAsPeriodInHistories = false;
private bool _useSideBySideDiff = false; private bool _useSideBySideDiff = false;

View file

@ -118,20 +118,6 @@ namespace SourceGit.ViewModels
} }
} }
public bool EnableTopoOrderInHistories
{
get => _settings.EnableTopoOrderInHistories;
set
{
if (value != _settings.EnableTopoOrderInHistories)
{
_settings.EnableTopoOrderInHistories = value;
OnPropertyChanged();
Task.Run(RefreshCommits);
}
}
}
public bool OnlyHighlightCurrentBranchInHistories public bool OnlyHighlightCurrentBranchInHistories
{ {
get => _settings.OnlyHighlighCurrentBranchInHistories; get => _settings.OnlyHighlighCurrentBranchInHistories;
@ -145,20 +131,6 @@ namespace SourceGit.ViewModels
} }
} }
public Models.TagSortMode TagSortMode
{
get => _settings.TagSortMode;
set
{
if (value != _settings.TagSortMode)
{
_settings.TagSortMode = value;
OnPropertyChanged();
VisibleTags = BuildVisibleTags();
}
}
}
public string Filter public string Filter
{ {
get => _filter; get => _filter;
@ -457,7 +429,16 @@ namespace SourceGit.ViewModels
try try
{ {
_watcher = new Models.Watcher(this); // For worktrees, we need to watch the $GIT_COMMON_DIR instead of the $GIT_DIR.
var gitDirForWatcher = _gitDir;
if (_gitDir.Replace("\\", "/").IndexOf("/worktrees/", StringComparison.Ordinal) > 0)
{
var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result();
if (!string.IsNullOrEmpty(commonDir))
gitDirForWatcher = commonDir;
}
_watcher = new Models.Watcher(this, _fullpath, gitDirForWatcher);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1461,6 +1442,80 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
public ContextMenu CreateContextMenuForHistoriesPage()
{
var layout = new MenuItem();
layout.Header = App.Text("Repository.HistoriesLayout");
layout.IsEnabled = false;
var isHorizontal = Preferences.Instance.UseTwoColumnsLayoutInHistories;
var horizontal = new MenuItem();
horizontal.Header = App.Text("Repository.HistoriesLayout.Horizontal");
if (isHorizontal)
horizontal.Icon = App.CreateMenuIcon("Icons.Check");
horizontal.Click += (_, ev) =>
{
Preferences.Instance.UseTwoColumnsLayoutInHistories = true;
ev.Handled = true;
};
var vertical = new MenuItem();
vertical.Header = App.Text("Repository.HistoriesLayout.Vertical");
if (!isHorizontal)
vertical.Icon = App.CreateMenuIcon("Icons.Check");
vertical.Click += (_, ev) =>
{
Preferences.Instance.UseTwoColumnsLayoutInHistories = false;
ev.Handled = true;
};
var order = new MenuItem();
order.Header = App.Text("Repository.HistoriesOrder");
order.IsEnabled = false;
var dateOrder = new MenuItem();
dateOrder.Header = App.Text("Repository.HistoriesOrder.ByDate");
dateOrder.SetValue(Views.MenuItemExtension.CommandProperty, "--date-order");
if (!_settings.EnableTopoOrderInHistories)
dateOrder.Icon = App.CreateMenuIcon("Icons.Check");
dateOrder.Click += (_, ev) =>
{
if (_settings.EnableTopoOrderInHistories)
{
_settings.EnableTopoOrderInHistories = false;
Task.Run(RefreshCommits);
}
ev.Handled = true;
};
var topoOrder = new MenuItem();
topoOrder.Header = App.Text("Repository.HistoriesOrder.Topo");
topoOrder.SetValue(Views.MenuItemExtension.CommandProperty, "--top-order");
if (_settings.EnableTopoOrderInHistories)
topoOrder.Icon = App.CreateMenuIcon("Icons.Check");
topoOrder.Click += (_, ev) =>
{
if (!_settings.EnableTopoOrderInHistories)
{
_settings.EnableTopoOrderInHistories = true;
Task.Run(RefreshCommits);
}
ev.Handled = true;
};
var menu = new ContextMenu();
menu.Items.Add(layout);
menu.Items.Add(horizontal);
menu.Items.Add(vertical);
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(order);
menu.Items.Add(dateOrder);
menu.Items.Add(topoOrder);
return menu;
}
public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch) public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
{ {
var menu = new ContextMenu(); var menu = new ContextMenu();
@ -1507,7 +1562,7 @@ namespace SourceGit.ViewModels
return; return;
if (CanCreatePopup()) if (CanCreatePopup())
ShowAndStartPopup(new Merge(this, b, branch.Name)); ShowAndStartPopup(new Merge(this, b, branch.Name, true));
e.Handled = true; e.Handled = true;
}; };
@ -1586,7 +1641,7 @@ namespace SourceGit.ViewModels
merge.Click += (_, e) => merge.Click += (_, e) =>
{ {
if (CanCreatePopup()) if (CanCreatePopup())
ShowPopup(new Merge(this, branch, _currentBranch.Name)); ShowPopup(new Merge(this, branch, _currentBranch.Name, false));
e.Handled = true; e.Handled = true;
}; };
@ -1867,7 +1922,7 @@ namespace SourceGit.ViewModels
merge.Click += (_, e) => merge.Click += (_, e) =>
{ {
if (CanCreatePopup()) if (CanCreatePopup())
ShowPopup(new Merge(this, branch, _currentBranch.Name)); ShowPopup(new Merge(this, branch, _currentBranch.Name, false));
e.Handled = true; e.Handled = true;
}; };
@ -2056,6 +2111,55 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
public ContextMenu CreateContextMenuForTagSortMode()
{
var mode = _settings.TagSortMode;
var changeMode = new Action<Models.TagSortMode>((m) =>
{
if (_settings.TagSortMode != m)
{
_settings.TagSortMode = m;
VisibleTags = BuildVisibleTags();
}
});
var byCreatorDate = new MenuItem();
byCreatorDate.Header = App.Text("Repository.Tags.OrderByCreatorDate");
if (mode == Models.TagSortMode.CreatorDate)
byCreatorDate.Icon = App.CreateMenuIcon("Icons.Check");
byCreatorDate.Click += (_, ev) =>
{
changeMode(Models.TagSortMode.CreatorDate);
ev.Handled = true;
};
var byNameAsc = new MenuItem();
byNameAsc.Header = App.Text("Repository.Tags.OrderByNameAsc");
if (mode == Models.TagSortMode.NameInAscending)
byNameAsc.Icon = App.CreateMenuIcon("Icons.Check");
byNameAsc.Click += (_, ev) =>
{
changeMode(Models.TagSortMode.NameInAscending);
ev.Handled = true;
};
var byNameDes = new MenuItem();
byNameDes.Header = App.Text("Repository.Tags.OrderByNameDes");
if (mode == Models.TagSortMode.NameInDescending)
byNameDes.Icon = App.CreateMenuIcon("Icons.Check");
byNameDes.Click += (_, ev) =>
{
changeMode(Models.TagSortMode.NameInDescending);
ev.Handled = true;
};
var menu = new ContextMenu();
menu.Items.Add(byCreatorDate);
menu.Items.Add(byNameAsc);
menu.Items.Add(byNameDes);
return menu;
}
public ContextMenu CreateContextMenuForSubmodule(string submodule) public ContextMenu CreateContextMenuForSubmodule(string submodule)
{ {
var open = new MenuItem(); var open = new MenuItem();

View file

@ -64,7 +64,7 @@ namespace SourceGit.ViewModels
{ {
if (OnlyStaged) if (OnlyStaged)
{ {
if (Native.OS.GitVersion >= Models.GitVersions.STASH_ONLY_STAGED) if (Native.OS.GitVersion >= Models.GitVersions.STASH_PUSH_ONLY_STAGED)
{ {
succ = new Commands.Stash(_repo.FullPath).PushOnlyStaged(Message, KeepIndex); succ = new Commands.Stash(_repo.FullPath).PushOnlyStaged(Message, KeepIndex);
} }
@ -109,7 +109,7 @@ namespace SourceGit.ViewModels
return true; return true;
var succ = false; var succ = false;
if (Native.OS.GitVersion >= Models.GitVersions.STASH_WITH_PATHSPECFILE) if (Native.OS.GitVersion >= Models.GitVersions.STASH_PUSH_WITH_PATHSPECFILE)
{ {
var paths = new List<string>(); var paths = new List<string>();
foreach (var c in changes) foreach (var c in changes)

View file

@ -58,25 +58,29 @@ namespace SourceGit.ViewModels
{ {
Task.Run(() => Task.Run(() =>
{ {
var changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result(); var changes = null as List<Models.Change>;
var untracked = new HashSet<string>();
if (value.HasUntracked) if (Native.OS.GitVersion >= Models.GitVersions.STASH_SHOW_WITH_UNTRACKED)
{ {
var untrackedChanges = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result(); changes = new Commands.QueryStashChanges(_repo.FullPath, value.Name).Result();
foreach (var c in untrackedChanges) }
else
{ {
untracked.Add(c.Path); changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result();
if (value.Parents.Count == 3)
{
var untracked = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result();
var needSort = changes.Count > 0;
foreach (var c in untracked)
changes.Add(c); changes.Add(c);
if (needSort)
changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
} }
} }
changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path)); Dispatcher.UIThread.Invoke(() => Changes = changes);
Dispatcher.UIThread.Invoke(() =>
{
Changes = changes;
_untrackedChanges = untracked;
});
}); });
} }
} }
@ -102,7 +106,7 @@ namespace SourceGit.ViewModels
{ {
if (value == null) if (value == null)
DiffContext = null; DiffContext = null;
else if (_untrackedChanges.Contains(value.Path)) else if (value.Index == Models.ChangeState.Added && _selectedStash.Parents.Count == 3)
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], value), _diffContext); DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], value), _diffContext);
else else
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, value), _diffContext); DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, value), _diffContext);
@ -178,7 +182,7 @@ namespace SourceGit.ViewModels
var opts = new List<Models.DiffOption>(); var opts = new List<Models.DiffOption>();
foreach (var c in _changes) foreach (var c in _changes)
{ {
if (_untrackedChanges.Contains(c.Path)) if (c.Index == Models.ChangeState.Added && _selectedStash.Parents.Count == 3)
opts.Add(new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], c)); opts.Add(new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], c));
else else
opts.Add(new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, c)); opts.Add(new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, c));
@ -303,7 +307,6 @@ namespace SourceGit.ViewModels
private List<Models.Stash> _visibleStashes = new List<Models.Stash>(); private List<Models.Stash> _visibleStashes = new List<Models.Stash>();
private string _searchFilter = string.Empty; private string _searchFilter = string.Empty;
private Models.Stash _selectedStash = null; private Models.Stash _selectedStash = null;
private HashSet<string> _untrackedChanges = new HashSet<string>();
private List<Models.Change> _changes = null; private List<Models.Change> _changes = null;
private Models.Change _selectedChange = null; private Models.Change _selectedChange = null;
private DiffContext _diffContext = null; private DiffContext _diffContext = null;

View file

@ -3,12 +3,12 @@
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:v="using:SourceGit.Views" xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="520" d:DesignHeight="230"
x:Class="SourceGit.Views.About" x:Class="SourceGit.Views.About"
x:Name="ThisControl" x:Name="ThisControl"
Icon="/App.ico" Icon="/App.ico"
Title="{DynamicResource Text.About}" Title="{DynamicResource Text.About}"
SizeToContent="WidthAndHeight" Width="520" Height="230"
CanResize="False" CanResize="False"
WindowStartupLocation="CenterScreen"> WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
@ -34,7 +34,7 @@
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
</Grid> </Grid>
<Grid Grid.Row="1" ColumnDefinitions="Auto,*"> <Grid Grid.Row="1" Height="200" ColumnDefinitions="Auto,Auto">
<Image Grid.Column="0" <Image Grid.Column="0"
Width="200" Height="200" Width="200" Height="200"
Margin="8,0" Margin="8,0"
@ -42,41 +42,28 @@
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center"/> VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Vertical" Margin="0,8,32,16"> <StackPanel Grid.Column="1" Orientation="Vertical" VerticalAlignment="Center">
<StackPanel Height="48" Orientation="Horizontal"> <StackPanel Height="40" Orientation="Horizontal">
<TextBlock Classes="bold" Text="SourceGit" FontSize="32" /> <TextBlock Classes="bold" Text="SourceGit" FontSize="32" />
<Border Margin="12,0,0,0" Height="20" CornerRadius="10" Background="{DynamicResource Brush.Accent}" Effect="drop-shadow(0 0 6 #40000000)"> <Border Margin="12,0,0,0" Height="20" CornerRadius="10" Background="{DynamicResource Brush.Accent}" Effect="drop-shadow(0 0 6 #40000000)">
<TextBlock x:Name="TxtVersion" Classes="primary" Margin="8,0" FontSize="12" Foreground="White"/> <TextBlock x:Name="TxtVersion" Classes="primary" Margin="8,0" FontSize="12" Foreground="White"/>
</Border> </Border>
</StackPanel> </StackPanel>
<TextBlock Margin="2,0,0,0" Text="{DynamicResource Text.About.SubTitle}" FontSize="16"/> <TextBlock Margin="2,4,0,0" Text="{DynamicResource Text.About.SubTitle}" FontSize="16"/>
<TextBlock x:Name="TxtCopyright" Margin="2,8,0,0" Foreground="{DynamicResource Brush.FG2}"/> <StackPanel Orientation="Horizontal" Margin="0,8,0,0">
<Button Width="18" Height="18" Classes="icon_button" Click="OnVisitWebsite" ToolTip.Tip="https://sourcegit-scm.github.io/">
<Path Width="16" Height="16" Data="{StaticResource Icons.Remotes}"/>
</Button>
<StackPanel Orientation="Vertical" Margin="0,24,0,0"> <Button Width="18" Height="18" Margin="8,0,0,0" Classes="icon_button" Click="OnVisitSourceCode" ToolTip.Tip="https://github.com/sourcegit-scm/sourcegit">
<StackPanel Orientation="Horizontal" Height="18"> <Path Width="16" Height="16" Data="{StaticResource Icons.Github}"/>
<TextBlock Text="{DynamicResource Text.About.BuildWith}" /> </Button>
<TextBlock Text="Avalonia UI" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitAvaloniaUI"/>
<TextBlock Text=" &amp; " />
<TextBlock Text="AvaloniaEdit" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitAvaloniaEdit"/>
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" Height="18" Margin="0,2,0,0">
<TextBlock Text="{DynamicResource Text.About.Fonts}" />
<TextBlock Text="JetBrains Mono" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitJetBrainsMonoFont"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="18" Margin="0,2,0,0"> <TextBlock x:Name="TxtCopyright" Margin="0,40,0,0" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Text="{DynamicResource Text.About.Chart}" />
<TextBlock Text="LiveCharts2" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitLiveCharts2"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="18" Margin="0,2,0,0">
<TextBlock Text="{DynamicResource Text.About.SourceCode}" />
<TextBlock Text="Github" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitSourceCode"/>
</StackPanel>
</StackPanel>
</StackPanel> </StackPanel>
</Grid> </Grid>
</Grid> </Grid>

View file

@ -1,5 +1,5 @@
using System.Reflection; using System.Reflection;
using Avalonia.Input; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
{ {
@ -19,31 +19,13 @@ namespace SourceGit.Views
TxtCopyright.Text = copyright.Copyright; TxtCopyright.Text = copyright.Copyright;
} }
private void OnVisitAvaloniaUI(object _, PointerPressedEventArgs e) private void OnVisitWebsite(object _, RoutedEventArgs e)
{ {
Native.OS.OpenBrowser("https://www.avaloniaui.net/"); Native.OS.OpenBrowser("https://sourcegit-scm.github.io/");
e.Handled = true; e.Handled = true;
} }
private void OnVisitAvaloniaEdit(object _, PointerPressedEventArgs e) private void OnVisitSourceCode(object _, RoutedEventArgs e)
{
Native.OS.OpenBrowser("https://github.com/AvaloniaUI/AvaloniaEdit");
e.Handled = true;
}
private void OnVisitJetBrainsMonoFont(object _, PointerPressedEventArgs e)
{
Native.OS.OpenBrowser("https://www.jetbrains.com/lp/mono/");
e.Handled = true;
}
private void OnVisitLiveCharts2(object _, PointerPressedEventArgs e)
{
Native.OS.OpenBrowser("https://livecharts.dev/");
e.Handled = true;
}
private void OnVisitSourceCode(object _, PointerPressedEventArgs e)
{ {
Native.OS.OpenBrowser("https://github.com/sourcegit-scm/sourcegit"); Native.OS.OpenBrowser("https://github.com/sourcegit-scm/sourcegit");
e.Handled = true; e.Handled = true;

View file

@ -39,17 +39,34 @@
<ComboBox Grid.Row="1" Grid.Column="1" <ComboBox Grid.Row="1" Grid.Column="1"
Height="28" Padding="8,0" Height="28" Padding="8,0"
VerticalAlignment="Center" HorizontalAlignment="Stretch" VerticalAlignment="Center" HorizontalAlignment="Stretch"
ItemsSource="{Binding WhiteSpaceModes}" ItemsSource="{Binding Source={x:Static m:ApplyWhiteSpaceMode.Supported}}"
SelectedItem="{Binding SelectedWhiteSpaceMode, Mode=TwoWay}" SelectedItem="{Binding SelectedWhiteSpaceMode, Mode=TwoWay}"
IsEnabled="{Binding !IgnoreWhiteSpace}"> IsEnabled="{Binding !IgnoreWhiteSpace}"
Grid.IsSharedSizeScope="True">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate x:DataType="{x:Type m:ApplyWhiteSpaceMode}"> <DataTemplate DataType="m:ApplyWhiteSpaceMode">
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center"> <Grid Height="20" VerticalAlignment="Center">
<TextBlock Text="{Binding Name}"/> <Grid.ColumnDefinitions>
<TextBlock Text="{Binding Desc}" Margin="8,0,0,0" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/> <ColumnDefinition Width="Auto" SharedSizeGroup="ApplyModeNameColumn"/>
</StackPanel> <ColumnDefinition Width="Auto" SharedSizeGroup="ApplyModeDescColumn"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="ApplyModeArgsColumn"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}"/>
<TextBlock Grid.Column="1" Text="{Binding Desc}" Margin="8,0" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="2" Text="{Binding Arg}" HorizontalAlignment="Right" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</DataTemplate> </DataTemplate>
</ComboBox.ItemTemplate> </ComboBox.ItemTemplate>
<ComboBox.SelectionBoxItemTemplate>
<DataTemplate DataType="m:ApplyWhiteSpaceMode">
<Grid ColumnDefinitions="Auto,*">
<TextBlock Grid.Column="0" Text="{Binding Name}" Margin="0,0,8,0"/>
<TextBlock Grid.Column="1" Text="{Binding Desc}" HorizontalAlignment="Right" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</DataTemplate>
</ComboBox.SelectionBoxItemTemplate>
</ComboBox> </ComboBox>
<CheckBox Grid.Row="2" Grid.Column="1" <CheckBox Grid.Row="2" Grid.Column="1"

View file

@ -173,8 +173,7 @@
<!-- REFS --> <!-- REFS -->
<TextBlock Grid.Row="3" Grid.Column="0" Classes="info_label" VerticalAlignment="Top" Margin="0,4,0,0" Text="{DynamicResource Text.CommitDetail.Info.Refs}" IsVisible="{Binding HasDecorators}"/> <TextBlock Grid.Row="3" Grid.Column="0" Classes="info_label" VerticalAlignment="Top" Margin="0,4,0,0" Text="{DynamicResource Text.CommitDetail.Info.Refs}" IsVisible="{Binding HasDecorators}"/>
<Border Grid.Row="3" Grid.Column="1" Margin="12,0,0,0" MinHeight="24" IsVisible="{Binding HasDecorators}"> <Border Grid.Row="3" Grid.Column="1" Margin="12,0,0,0" MinHeight="24" IsVisible="{Binding HasDecorators}">
<v:CommitRefsPresenter TagBackground="{DynamicResource Brush.DecoratorTag}" <v:CommitRefsPresenter Foreground="{DynamicResource Brush.FG1}"
Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}" FontFamily="{DynamicResource Fonts.Primary}"
FontSize="11" FontSize="11"
AllowWrap="True" AllowWrap="True"

View file

@ -64,15 +64,6 @@ namespace SourceGit.Views
set => SetValue(UseGraphColorProperty, value); set => SetValue(UseGraphColorProperty, value);
} }
public static readonly StyledProperty<IBrush> TagBackgroundProperty =
AvaloniaProperty.Register<CommitRefsPresenter, IBrush>(nameof(TagBackground), Brushes.White);
public IBrush TagBackground
{
get => GetValue(TagBackgroundProperty);
set => SetValue(TagBackgroundProperty, value);
}
public static readonly StyledProperty<bool> AllowWrapProperty = public static readonly StyledProperty<bool> AllowWrapProperty =
AvaloniaProperty.Register<CommitRefsPresenter, bool>(nameof(AllowWrap)); AvaloniaProperty.Register<CommitRefsPresenter, bool>(nameof(AllowWrap));
@ -82,6 +73,15 @@ namespace SourceGit.Views
set => SetValue(AllowWrapProperty, value); set => SetValue(AllowWrapProperty, value);
} }
public static readonly StyledProperty<bool> ShowTagsProperty =
AvaloniaProperty.Register<CommitRefsPresenter, bool>(nameof(ShowTags), true);
public bool ShowTags
{
get => GetValue(ShowTagsProperty);
set => SetValue(ShowTagsProperty, value);
}
static CommitRefsPresenter() static CommitRefsPresenter()
{ {
AffectsMeasure<CommitRefsPresenter>( AffectsMeasure<CommitRefsPresenter>(
@ -89,8 +89,8 @@ namespace SourceGit.Views
FontSizeProperty, FontSizeProperty,
ForegroundProperty, ForegroundProperty,
UseGraphColorProperty, UseGraphColorProperty,
TagBackgroundProperty, BackgroundProperty,
BackgroundProperty); ShowTagsProperty);
} }
public override void Render(DrawingContext context) public override void Render(DrawingContext context)
@ -171,15 +171,18 @@ namespace SourceGit.Views
var typefaceBold = new Typeface(FontFamily, FontStyle.Normal, FontWeight.Bold); var typefaceBold = new Typeface(FontFamily, FontStyle.Normal, FontWeight.Bold);
var fg = Foreground; var fg = Foreground;
var normalBG = UseGraphColor ? commit.Brush : Brushes.Gray; var normalBG = UseGraphColor ? commit.Brush : Brushes.Gray;
var tagBG = UseGraphColor ? TagBackground : Brushes.Gray;
var labelSize = FontSize; var labelSize = FontSize;
var requiredWidth = 0.0; var requiredWidth = 0.0;
var requiredHeight = 16.0; var requiredHeight = 16.0;
var x = 0.0; var x = 0.0;
var allowWrap = AllowWrap; var allowWrap = AllowWrap;
var showTags = ShowTags;
foreach (var decorator in refs) foreach (var decorator in refs)
{ {
if (!showTags && decorator.Type == Models.DecoratorType.Tag)
continue;
var isHead = decorator.Type == Models.DecoratorType.CurrentBranchHead || var isHead = decorator.Type == Models.DecoratorType.CurrentBranchHead ||
decorator.Type == Models.DecoratorType.CurrentCommitHead; decorator.Type == Models.DecoratorType.CurrentCommitHead;
@ -209,7 +212,7 @@ namespace SourceGit.Views
geo = this.FindResource("Icons.Remote") as StreamGeometry; geo = this.FindResource("Icons.Remote") as StreamGeometry;
break; break;
case Models.DecoratorType.Tag: case Models.DecoratorType.Tag:
item.Brush = tagBG; item.Brush = Brushes.Gray;
geo = this.FindResource("Icons.Tag") as StreamGeometry; geo = this.FindResource("Icons.Tag") as StreamGeometry;
break; break;
default: default:

View file

@ -46,7 +46,6 @@
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Data="{StaticResource Icons.Commit}"/> <Path Width="12" Height="12" Data="{StaticResource Icons.Commit}"/>
<v:CommitRefsPresenter Margin="8,0,0,0" <v:CommitRefsPresenter Margin="8,0,0,0"
TagBackground="{DynamicResource Brush.DecoratorTag}"
Foreground="{DynamicResource Brush.FG1}" Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}" FontFamily="{DynamicResource Fonts.Primary}"
FontSize="11" FontSize="11"

View file

@ -285,10 +285,9 @@
<!-- Text Diff --> <!-- Text Diff -->
<DataTemplate DataType="m:TextDiff"> <DataTemplate DataType="m:TextDiff">
<v:TextDiffView <v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
UseSideBySideDiff="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
UseBlockNavigation="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=OneWay}" UseBlockNavigation="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=OneWay}"
BlockNavigationIndicator="{Binding #BlockNavigationIndicator.Text, Mode=OneWayToSource}"/> BlockNavigationChanged="OnBlockNavigationChanged"/>
</DataTemplate> </DataTemplate>
<!-- Empty or only EOL changes --> <!-- Empty or only EOL changes -->

View file

@ -13,30 +13,32 @@ namespace SourceGit.Views
private void OnGotoFirstChange(object _, RoutedEventArgs e) private void OnGotoFirstChange(object _, RoutedEventArgs e)
{ {
var textDiff = this.FindDescendantOfType<TextDiffView>(); this.FindDescendantOfType<TextDiffView>()?.GotoFirstChange();
textDiff?.GotoFirstChange();
e.Handled = true; e.Handled = true;
} }
private void OnGotoPrevChange(object _, RoutedEventArgs e) private void OnGotoPrevChange(object _, RoutedEventArgs e)
{ {
var textDiff = this.FindDescendantOfType<TextDiffView>(); this.FindDescendantOfType<TextDiffView>()?.GotoPrevChange();
textDiff?.GotoPrevChange();
e.Handled = true; e.Handled = true;
} }
private void OnGotoNextChange(object _, RoutedEventArgs e) private void OnGotoNextChange(object _, RoutedEventArgs e)
{ {
var textDiff = this.FindDescendantOfType<TextDiffView>(); this.FindDescendantOfType<TextDiffView>()?.GotoNextChange();
textDiff?.GotoNextChange();
e.Handled = true; e.Handled = true;
} }
private void OnGotoLastChange(object _, RoutedEventArgs e) private void OnGotoLastChange(object _, RoutedEventArgs e)
{ {
var textDiff = this.FindDescendantOfType<TextDiffView>(); this.FindDescendantOfType<TextDiffView>()?.GotoLastChange();
textDiff?.GotoLastChange();
e.Handled = true; e.Handled = true;
} }
private void OnBlockNavigationChanged(object sender, RoutedEventArgs e)
{
if (sender is TextDiffView textDiff)
BlockNavigationIndicator.Text = textDiff.BlockNavigation?.Indicator ?? string.Empty;
}
} }
} }

View file

@ -140,9 +140,9 @@
<v:CommitRefsPresenter Grid.Column="1" <v:CommitRefsPresenter Grid.Column="1"
Background="{DynamicResource Brush.Contents}" Background="{DynamicResource Brush.Contents}"
TagBackground="{DynamicResource Brush.DecoratorTag}"
Foreground="{DynamicResource Brush.FG1}" Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}" FontFamily="{DynamicResource Fonts.Primary}"
ShowTags="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowTagsInGraph}"
FontSize="11" FontSize="11"
VerticalAlignment="Center"> VerticalAlignment="Center">
<v:CommitRefsPresenter.UseGraphColor> <v:CommitRefsPresenter.UseGraphColor>

View file

@ -12,7 +12,7 @@ namespace SourceGit.Views
public class HistoriesLayout : Grid public class HistoriesLayout : Grid
{ {
public static readonly StyledProperty<bool> UseHorizontalProperty = public static readonly StyledProperty<bool> UseHorizontalProperty =
AvaloniaProperty.Register<HistoriesLayout, bool>(nameof(UseHorizontal)); AvaloniaProperty.Register<HistoriesLayout, bool>(nameof(UseHorizontal), false);
public bool UseHorizontal public bool UseHorizontal
{ {
@ -22,16 +22,17 @@ namespace SourceGit.Views
protected override Type StyleKeyOverride => typeof(Grid); protected override Type StyleKeyOverride => typeof(Grid);
public HistoriesLayout()
{
RefreshLayout();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{ {
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
if (change.Property == UseHorizontalProperty) if (change.Property == UseHorizontalProperty && IsLoaded)
RefreshLayout();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
RefreshLayout(); RefreshLayout();
} }

View file

@ -60,15 +60,32 @@
Height="28" Padding="8,0" Height="28" Padding="8,0"
VerticalAlignment="Center" HorizontalAlignment="Stretch" VerticalAlignment="Center" HorizontalAlignment="Stretch"
ItemsSource="{Binding Source={x:Static m:MergeMode.Supported}}" ItemsSource="{Binding Source={x:Static m:MergeMode.Supported}}"
SelectedItem="{Binding SelectedMode, Mode=TwoWay}"> SelectedItem="{Binding Mode, Mode=TwoWay}"
Grid.IsSharedSizeScope="True">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate DataType="m:MergeMode"> <DataTemplate DataType="m:MergeMode">
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center"> <Grid Height="20">
<TextBlock Text="{Binding Name}"/> <Grid.ColumnDefinitions>
<TextBlock Text="{Binding Desc}" Margin="8,0,0,0" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/> <ColumnDefinition Width="Auto" SharedSizeGroup="MergeModeNameColumn"/>
</StackPanel> <ColumnDefinition Width="Auto" SharedSizeGroup="MergeModeDescriptionColumn"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="MergeModeOptionColumn"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}"/>
<TextBlock Grid.Column="1" Text="{Binding Desc}" Margin="8,0" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="2" Text="{Binding Arg}" HorizontalAlignment="Right" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</DataTemplate> </DataTemplate>
</ComboBox.ItemTemplate> </ComboBox.ItemTemplate>
<ComboBox.SelectionBoxItemTemplate>
<DataTemplate DataType="m:MergeMode">
<Grid ColumnDefinitions="Auto,*">
<TextBlock Grid.Column="0" Text="{Binding Name}" Margin="0,0,8,0"/>
<TextBlock Grid.Column="1" Text="{Binding Desc}" HorizontalAlignment="Right" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</DataTemplate>
</ComboBox.SelectionBoxItemTemplate>
</ComboBox> </ComboBox>
</Grid> </Grid>
</StackPanel> </StackPanel>

View file

@ -46,7 +46,7 @@
<TabItem.Header> <TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preferences.General}"/> <TextBlock Classes="tab_header" Text="{DynamicResource Text.Preferences.General}"/>
</TabItem.Header> </TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*"> <Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preferences.General.Locale}" Text="{DynamicResource Text.Preferences.General.Locale}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
@ -132,11 +132,16 @@
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowAuthorTimeInGraph, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowAuthorTimeInGraph, Mode=TwoWay}"/>
<CheckBox Grid.Row="6" Grid.Column="1" <CheckBox Grid.Row="6" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preferences.General.ShowTagsInGraph}"
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowTagsInGraph, Mode=TwoWay}"/>
<CheckBox Grid.Row="7" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Preferences.General.ShowChildren}" Content="{DynamicResource Text.Preferences.General.ShowChildren}"
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowChildren, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowChildren, Mode=TwoWay}"/>
<CheckBox Grid.Row="7" Grid.Column="1" <CheckBox Grid.Row="8" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Preferences.General.Check4UpdatesOnStartup}" Content="{DynamicResource Text.Preferences.General.Check4UpdatesOnStartup}"
IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}" IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}"

View file

@ -396,66 +396,8 @@ namespace SourceGit.Views
{ {
if (sender is Button button && DataContext is ViewModels.Repository repo) if (sender is Button button && DataContext is ViewModels.Repository repo)
{ {
var layout = new MenuItem(); var menu = repo.CreateContextMenuForHistoriesPage();
layout.Header = App.Text("Repository.HistoriesLayout"); menu?.Open(button);
layout.IsEnabled = false;
var isHorizontal = ViewModels.Preferences.Instance.UseTwoColumnsLayoutInHistories;
var horizontal = new MenuItem();
horizontal.Header = App.Text("Repository.HistoriesLayout.Horizontal");
if (isHorizontal)
horizontal.Icon = App.CreateMenuIcon("Icons.Check");
horizontal.Click += (_, ev) =>
{
ViewModels.Preferences.Instance.UseTwoColumnsLayoutInHistories = true;
ev.Handled = true;
};
var vertical = new MenuItem();
vertical.Header = App.Text("Repository.HistoriesLayout.Vertical");
if (!isHorizontal)
vertical.Icon = App.CreateMenuIcon("Icons.Check");
vertical.Click += (_, ev) =>
{
ViewModels.Preferences.Instance.UseTwoColumnsLayoutInHistories = false;
ev.Handled = true;
};
var order = new MenuItem();
order.Header = App.Text("Repository.HistoriesOrder");
order.IsEnabled = false;
var dateOrder = new MenuItem();
dateOrder.Header = App.Text("Repository.HistoriesOrder.ByDate");
dateOrder.SetValue(MenuItemExtension.CommandProperty, "--date-order");
if (!repo.EnableTopoOrderInHistories)
dateOrder.Icon = App.CreateMenuIcon("Icons.Check");
dateOrder.Click += (_, ev) =>
{
repo.EnableTopoOrderInHistories = false;
ev.Handled = true;
};
var topoOrder = new MenuItem();
topoOrder.Header = App.Text("Repository.HistoriesOrder.Topo");
topoOrder.SetValue(MenuItemExtension.CommandProperty, "--top-order");
if (repo.EnableTopoOrderInHistories)
topoOrder.Icon = App.CreateMenuIcon("Icons.Check");
topoOrder.Click += (_, ev) =>
{
repo.EnableTopoOrderInHistories = true;
ev.Handled = true;
};
var menu = new ContextMenu();
menu.Items.Add(layout);
menu.Items.Add(horizontal);
menu.Items.Add(vertical);
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(order);
menu.Items.Add(dateOrder);
menu.Items.Add(topoOrder);
menu.Open(button);
} }
e.Handled = true; e.Handled = true;
@ -465,41 +407,8 @@ namespace SourceGit.Views
{ {
if (sender is Button button && DataContext is ViewModels.Repository repo) if (sender is Button button && DataContext is ViewModels.Repository repo)
{ {
var byCreatorDate = new MenuItem(); var menu = repo.CreateContextMenuForTagSortMode();
byCreatorDate.Header = App.Text("Repository.Tags.OrderByCreatorDate"); menu?.Open(button);
if (repo.TagSortMode == Models.TagSortMode.CreatorDate)
byCreatorDate.Icon = App.CreateMenuIcon("Icons.Check");
byCreatorDate.Click += (_, ev) =>
{
repo.TagSortMode = Models.TagSortMode.CreatorDate;
ev.Handled = true;
};
var byNameAsc = new MenuItem();
byNameAsc.Header = App.Text("Repository.Tags.OrderByNameAsc");
if (repo.TagSortMode == Models.TagSortMode.NameInAscending)
byNameAsc.Icon = App.CreateMenuIcon("Icons.Check");
byNameAsc.Click += (_, ev) =>
{
repo.TagSortMode = Models.TagSortMode.NameInAscending;
ev.Handled = true;
};
var byNameDes = new MenuItem();
byNameDes.Header = App.Text("Repository.Tags.OrderByNameDes");
if (repo.TagSortMode == Models.TagSortMode.NameInDescending)
byNameDes.Icon = App.CreateMenuIcon("Icons.Check");
byNameDes.Click += (_, ev) =>
{
repo.TagSortMode = Models.TagSortMode.NameInDescending;
ev.Handled = true;
};
var menu = new ContextMenu();
menu.Items.Add(byCreatorDate);
menu.Items.Add(byNameAsc);
menu.Items.Add(byNameDes);
menu.Open(button);
} }
e.Handled = true; e.Handled = true;

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:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.SelfUpdate" x:Class="SourceGit.Views.SelfUpdate"
x:DataType="vm:SelfUpdate" x:DataType="vm:SelfUpdate"
@ -87,26 +86,6 @@
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
<DataTemplate DataType="sys:Exception">
<StackPanel Orientation="Vertical" Margin="16,8">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Path Width="14" Height="14" Data="{StaticResource Icons.Error}" Fill="Red"/>
<TextBlock Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.SelfUpdate.Error}"/>
</StackPanel>
<TextBlock Text="{Binding Message}" MaxWidth="500" TextWrapping="Wrap" Margin="0,8"/>
<Button Classes="flat primary"
Height="30"
Margin="4,0"
Click="CloseWindow"
Content="{DynamicResource Text.Close}"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="m:AlreadyUpToDate"> <DataTemplate DataType="m:AlreadyUpToDate">
<StackPanel Orientation="Vertical" Margin="16,8"> <StackPanel Orientation="Vertical" Margin="16,8">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,8"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,8">
@ -124,6 +103,26 @@
VerticalContentAlignment="Center"/> VerticalContentAlignment="Center"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
<DataTemplate DataType="m:SelfUpdateFailed">
<StackPanel Orientation="Vertical" Margin="16,8">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Path Width="14" Height="14" Data="{StaticResource Icons.Error}" Fill="Red"/>
<TextBlock Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.SelfUpdate.Error}"/>
</StackPanel>
<TextBlock Text="{Binding Reason}" MaxWidth="500" TextWrapping="Wrap" Margin="0,8"/>
<Button Classes="flat primary"
Height="30"
Margin="4,0"
Click="CloseWindow"
Content="{DynamicResource Text.Close}"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates> </ContentControl.DataTemplates>
</ContentControl> </ContentControl>
</Grid> </Grid>

View file

@ -92,7 +92,7 @@
<Border BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1" Padding="4" Background="Transparent" ContextRequested="OnStashContextRequested"> <Border BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1" Padding="4" Background="Transparent" ContextRequested="OnStashContextRequested">
<Grid RowDefinitions="Auto,*" > <Grid RowDefinitions="Auto,*" >
<Grid Grid.Row="0" ColumnDefinitions="*,Auto"> <Grid Grid.Row="0" ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Classes="primary" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" TextDecorations="Underline" Cursor="Hand"/> <TextBlock Grid.Column="0" Classes="primary" Text="{Binding Name}" Foreground="DarkOrange"/>
<TextBlock Grid.Column="1" Classes="primary" Text="{Binding TimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/> <TextBlock Grid.Column="1" Classes="primary" Text="{Binding TimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
</Grid> </Grid>

View file

@ -553,7 +553,7 @@ namespace SourceGit.Views
{ {
} }
public void GotoFirstChange() public virtual void GotoFirstChange()
{ {
var blockNavigation = BlockNavigation; var blockNavigation = BlockNavigation;
if (blockNavigation != null) if (blockNavigation != null)
@ -565,10 +565,9 @@ namespace SourceGit.Views
ScrollToLine(prev.Start); ScrollToLine(prev.Start);
} }
} }
// NOTE: Not implemented (button hidden) for non-block navigation.
} }
public void GotoPrevChange() public virtual void GotoPrevChange()
{ {
var blockNavigation = BlockNavigation; var blockNavigation = BlockNavigation;
if (blockNavigation != null) if (blockNavigation != null)
@ -624,7 +623,7 @@ namespace SourceGit.Views
} }
} }
public void GotoNextChange() public virtual void GotoNextChange()
{ {
var blockNavigation = BlockNavigation; var blockNavigation = BlockNavigation;
if (blockNavigation != null) if (blockNavigation != null)
@ -666,7 +665,7 @@ namespace SourceGit.Views
} }
} }
public void GotoLastChange() public virtual void GotoLastChange()
{ {
var blockNavigation = BlockNavigation; var blockNavigation = BlockNavigation;
if (blockNavigation != null) if (blockNavigation != null)
@ -678,7 +677,6 @@ namespace SourceGit.Views
ScrollToLine(next.Start); ScrollToLine(next.Start);
} }
} }
// NOTE: Not implemented (button hidden) for non-block navigation.
} }
public override void Render(DrawingContext context) public override void Render(DrawingContext context)
@ -768,15 +766,13 @@ namespace SourceGit.Views
{ {
var oldValue = change.OldValue as ViewModels.BlockNavigation; var oldValue = change.OldValue as ViewModels.BlockNavigation;
if (oldValue != null) if (oldValue != null)
{
oldValue.PropertyChanged -= OnBlockNavigationPropertyChanged; oldValue.PropertyChanged -= OnBlockNavigationPropertyChanged;
if (oldValue.Current != -1)
TextArea?.TextView?.Redraw();
}
var newValue = change.NewValue as ViewModels.BlockNavigation; var newValue = change.NewValue as ViewModels.BlockNavigation;
if (newValue != null) if (newValue != null)
newValue.PropertyChanged += OnBlockNavigationPropertyChanged; newValue.PropertyChanged += OnBlockNavigationPropertyChanged;
TextArea?.TextView?.Redraw();
} }
} }
@ -795,8 +791,9 @@ namespace SourceGit.Views
base.OnKeyDown(e); base.OnKeyDown(e);
} }
private void OnBlockNavigationPropertyChanged(object _1, PropertyChangedEventArgs _2) private void OnBlockNavigationPropertyChanged(object _1, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == "Current")
TextArea?.TextView?.Redraw(); TextArea?.TextView?.Redraw();
} }
@ -1225,19 +1222,18 @@ namespace SourceGit.Views
{ {
base.OnLoaded(e); base.OnLoaded(e);
var scroller = this.FindDescendantOfType<ScrollViewer>(); _scrollViewer = this.FindDescendantOfType<ScrollViewer>();
if (scroller != null) if (_scrollViewer != null)
{ {
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay)); _scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay));
scroller.GotFocus += OnTextViewScrollGotFocus; _scrollViewer.ScrollChanged += OnTextViewScrollChanged;
} }
} }
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
{ {
var scroller = this.FindDescendantOfType<ScrollViewer>(); if (_scrollViewer != null)
if (scroller != null) _scrollViewer.ScrollChanged -= OnTextViewScrollChanged;
scroller.GotFocus -= OnTextViewScrollGotFocus;
base.OnUnloaded(e); base.OnUnloaded(e);
} }
@ -1274,11 +1270,13 @@ namespace SourceGit.Views
GC.Collect(); GC.Collect();
} }
private void OnTextViewScrollGotFocus(object sender, GotFocusEventArgs e) private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e)
{ {
if (EnableChunkSelection && !TextArea.IsPointerOver) if (!TextArea.TextView.IsPointerOver)
TrySetChunk(null); TrySetChunk(null);
} }
private ScrollViewer _scrollViewer = null;
} }
public class SingleSideTextDiffPresenter : ThemedTextDiffPresenter public class SingleSideTextDiffPresenter : ThemedTextDiffPresenter
@ -1290,14 +1288,6 @@ namespace SourceGit.Views
TextArea.LeftMargins.Add(new LineModifyTypeMargin()); TextArea.LeftMargins.Add(new LineModifyTypeMargin());
} }
public void ForceSyncScrollOffset()
{
if (_scrollViewer == null)
return;
if (DataContext is ViewModels.TwoSideTextDiff diff)
diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero;
}
public override List<Models.TextDiffLine> GetLines() public override List<Models.TextDiffLine> GetLines()
{ {
if (DataContext is ViewModels.TwoSideTextDiff diff) if (DataContext is ViewModels.TwoSideTextDiff diff)
@ -1312,6 +1302,30 @@ namespace SourceGit.Views
return 0; return 0;
} }
public override void GotoFirstChange()
{
base.GotoFirstChange();
DirectSyncScrollOffset();
}
public override void GotoPrevChange()
{
base.GotoPrevChange();
DirectSyncScrollOffset();
}
public override void GotoNextChange()
{
base.GotoNextChange();
DirectSyncScrollOffset();
}
public override void GotoLastChange()
{
base.GotoLastChange();
DirectSyncScrollOffset();
}
public override void UpdateSelectedChunk(double y) public override void UpdateSelectedChunk(double y)
{ {
var diff = DataContext as ViewModels.TwoSideTextDiff; var diff = DataContext as ViewModels.TwoSideTextDiff;
@ -1446,12 +1460,9 @@ namespace SourceGit.Views
_scrollViewer = this.FindDescendantOfType<ScrollViewer>(); _scrollViewer = this.FindDescendantOfType<ScrollViewer>();
if (_scrollViewer != null) if (_scrollViewer != null)
{ {
_scrollViewer.GotFocus += OnTextViewScrollGotFocus;
_scrollViewer.ScrollChanged += OnTextViewScrollChanged; _scrollViewer.ScrollChanged += OnTextViewScrollChanged;
_scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.OneWay)); _scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.OneWay));
} }
TextArea.PointerWheelChanged += OnTextAreaPointerWheelChanged;
} }
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
@ -1459,12 +1470,9 @@ namespace SourceGit.Views
if (_scrollViewer != null) if (_scrollViewer != null)
{ {
_scrollViewer.ScrollChanged -= OnTextViewScrollChanged; _scrollViewer.ScrollChanged -= OnTextViewScrollChanged;
_scrollViewer.GotFocus -= OnTextViewScrollGotFocus;
_scrollViewer = null; _scrollViewer = null;
} }
TextArea.PointerWheelChanged -= OnTextAreaPointerWheelChanged;
base.OnUnloaded(e); base.OnUnloaded(e);
GC.Collect(); GC.Collect();
} }
@ -1499,22 +1507,21 @@ namespace SourceGit.Views
} }
} }
private void OnTextViewScrollGotFocus(object sender, GotFocusEventArgs e)
{
if (EnableChunkSelection && !TextArea.IsPointerOver)
TrySetChunk(null);
}
private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e) private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e)
{ {
if (TextArea.IsFocused && DataContext is ViewModels.TwoSideTextDiff diff) if (IsPointerOver && DataContext is ViewModels.TwoSideTextDiff diff)
{
diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero; diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero;
if (!TextArea.TextView.IsPointerOver)
TrySetChunk(null);
}
} }
private void OnTextAreaPointerWheelChanged(object sender, PointerWheelEventArgs e) private void DirectSyncScrollOffset()
{ {
if (!TextArea.IsFocused) if (_scrollViewer is { } && DataContext is ViewModels.TwoSideTextDiff diff)
Focus(); diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero;
} }
private ScrollViewer _scrollViewer = null; private ScrollViewer _scrollViewer = null;
@ -1694,13 +1701,13 @@ namespace SourceGit.Views
set => SetValue(BlockNavigationProperty, value); set => SetValue(BlockNavigationProperty, value);
} }
public static readonly StyledProperty<string> BlockNavigationIndicatorProperty = public static readonly RoutedEvent<RoutedEventArgs> BlockNavigationChangedEvent =
AvaloniaProperty.Register<TextDiffView, string>(nameof(BlockNavigationIndicator)); RoutedEvent.Register<TextDiffView, RoutedEventArgs>(nameof(BlockNavigationChanged), RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
public string BlockNavigationIndicator public event EventHandler<RoutedEventArgs> BlockNavigationChanged
{ {
get => GetValue(BlockNavigationIndicatorProperty); add { AddHandler(BlockNavigationChangedEvent, value); }
set => SetValue(BlockNavigationIndicatorProperty, value); remove { RemoveHandler(BlockNavigationChangedEvent, value); }
} }
static TextDiffView() static TextDiffView()
@ -1738,54 +1745,26 @@ namespace SourceGit.Views
public void GotoFirstChange() public void GotoFirstChange()
{ {
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>(); this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoFirstChange();
if (presenter == null) TryRaiseBlockNavigationChanged();
return;
presenter.GotoFirstChange();
if (presenter is SingleSideTextDiffPresenter singleSide)
singleSide.ForceSyncScrollOffset();
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
} }
public void GotoPrevChange() public void GotoPrevChange()
{ {
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>(); this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoPrevChange();
if (presenter == null) TryRaiseBlockNavigationChanged();
return;
presenter.GotoPrevChange();
if (presenter is SingleSideTextDiffPresenter singleSide)
singleSide.ForceSyncScrollOffset();
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
} }
public void GotoNextChange() public void GotoNextChange()
{ {
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>(); this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoNextChange();
if (presenter == null) TryRaiseBlockNavigationChanged();
return;
presenter.GotoNextChange();
if (presenter is SingleSideTextDiffPresenter singleSide)
singleSide.ForceSyncScrollOffset();
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
} }
public void GotoLastChange() public void GotoLastChange()
{ {
var presenter = this.FindDescendantOfType<ThemedTextDiffPresenter>(); this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoLastChange();
if (presenter == null) TryRaiseBlockNavigationChanged();
return;
presenter.GotoLastChange();
if (presenter is SingleSideTextDiffPresenter singleSide)
singleSide.ForceSyncScrollOffset();
BlockNavigationIndicator = BlockNavigation?.Indicator ?? string.Empty;
} }
protected override void OnDataContextChanged(EventArgs e) protected override void OnDataContextChanged(EventArgs e)
@ -1835,15 +1814,11 @@ namespace SourceGit.Views
private void RefreshBlockNavigation() private void RefreshBlockNavigation()
{ {
if (UseBlockNavigation) if (UseBlockNavigation)
{
BlockNavigation = new ViewModels.BlockNavigation(Editor.Content); BlockNavigation = new ViewModels.BlockNavigation(Editor.Content);
BlockNavigationIndicator = BlockNavigation.Indicator;
}
else else
{
BlockNavigation = null; BlockNavigation = null;
BlockNavigationIndicator = "-/-";
} TryRaiseBlockNavigationChanged();
} }
private void OnStageChunk(object _1, RoutedEventArgs _2) private void OnStageChunk(object _1, RoutedEventArgs _2)
@ -2015,5 +1990,11 @@ namespace SourceGit.Views
repo.MarkWorkingCopyDirtyManually(); repo.MarkWorkingCopyDirtyManually();
repo.SetWatcherEnabled(true); repo.SetWatcherEnabled(true);
} }
private void TryRaiseBlockNavigationChanged()
{
if (UseBlockNavigation)
RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent));
}
} }
} }