mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-26 21:17:20 -08:00
Compare commits
19 commits
fba84c8297
...
dcf5093406
Author | SHA1 | Date | |
---|---|---|---|
|
dcf5093406 | ||
|
a5aa2254f6 | ||
|
6209326fe0 | ||
|
8d4afafd2d | ||
|
1a8acbf934 | ||
|
779b38be28 | ||
|
ad01eb442d | ||
|
635396008d | ||
|
2f628b0f06 | ||
|
fb9e342ee0 | ||
|
25028efa4d | ||
|
163e8cc0a4 | ||
|
64860950c7 | ||
|
310c786693 | ||
|
921b8599df | ||
|
9452b796a5 | ||
|
5966b8ac08 | ||
|
6b348fbd1a | ||
|
1d0098703e |
36 changed files with 352 additions and 172 deletions
21
README.md
21
README.md
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
## Translation Status
|
## Translation Status
|
||||||
|
|
||||||
[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-96.05%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.08%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-87.72%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-90.79%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-100.00%25-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md)
|
[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-95.63%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-96.65%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-87.34%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-90.39%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.56%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md)
|
||||||
|
|
||||||
## How to Use
|
## How to Use
|
||||||
|
|
||||||
|
@ -119,14 +119,15 @@ For other AI service:
|
||||||
|
|
||||||
This app supports open repository in external tools listed in the table below.
|
This app supports open repository in external tools listed in the table below.
|
||||||
|
|
||||||
| Tool | Windows | macOS | Linux | KEY IN `external_editors.json` |
|
| Tool | Windows | macOS | Linux |
|
||||||
|-------------------------------|---------|-------|-------|--------------------------------|
|
|-------------------------------|---------|-------|-------|
|
||||||
| Visual Studio Code | YES | YES | YES | VSCODE |
|
| Visual Studio Code | YES | YES | YES |
|
||||||
| Visual Studio Code - Insiders | YES | YES | YES | VSCODE_INSIDERS |
|
| Visual Studio Code - Insiders | YES | YES | YES |
|
||||||
| VSCodium | YES | YES | YES | VSCODIUM |
|
| VSCodium | YES | YES | YES |
|
||||||
| JetBrains Fleet | YES | YES | YES | FLEET |
|
| Fleet | YES | YES | YES |
|
||||||
| Sublime Text | YES | YES | YES | SUBLIME_TEXT |
|
| Sublime Text | YES | YES | YES |
|
||||||
| Zed | NO | YES | YES | ZED |
|
| Zed | NO | YES | YES |
|
||||||
|
| Visual Studio | YES | NO | NO |
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> This app will try to find those tools based on some pre-defined or expected locations automatically. If you are using one portable version of these tools, it will not be detected by this app.
|
> This app will try to find those tools based on some pre-defined or expected locations automatically. If you are using one portable version of these tools, it will not be detected by this app.
|
||||||
|
@ -134,7 +135,7 @@ This app supports open repository in external tools listed in the table below.
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"tools": {
|
"tools": {
|
||||||
"VSCODE": "D:\\VSCode\\Code.exe"
|
"Visual Studio Code": "D:\\VSCode\\Code.exe"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
### de_DE.axaml: 96.05%
|
### de_DE.axaml: 95.63%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -22,8 +22,11 @@
|
||||||
- Text.Configure.OpenAI
|
- Text.Configure.OpenAI
|
||||||
- Text.Configure.OpenAI.Prefered
|
- Text.Configure.OpenAI.Prefered
|
||||||
- Text.Configure.OpenAI.Prefered.Tip
|
- Text.Configure.OpenAI.Prefered.Tip
|
||||||
|
- Text.Diff.VisualLines.All
|
||||||
- Text.ExecuteCustomAction
|
- Text.ExecuteCustomAction
|
||||||
- Text.ExecuteCustomAction.Name
|
- Text.ExecuteCustomAction.Name
|
||||||
|
- Text.IssueLinkCM.OpenInBrowser
|
||||||
|
- Text.IssueLinkCM.CopyLink
|
||||||
- Text.Preference.AI.AnalyzeDiffPrompt
|
- Text.Preference.AI.AnalyzeDiffPrompt
|
||||||
- Text.Preference.AI.GenerateSubjectPrompt
|
- Text.Preference.AI.GenerateSubjectPrompt
|
||||||
- Text.Preference.AI.Name
|
- Text.Preference.AI.Name
|
||||||
|
@ -34,7 +37,7 @@
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### es_ES.axaml: 97.08%
|
### es_ES.axaml: 96.65%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -54,8 +57,11 @@
|
||||||
- Text.Configure.OpenAI
|
- Text.Configure.OpenAI
|
||||||
- Text.Configure.OpenAI.Prefered
|
- Text.Configure.OpenAI.Prefered
|
||||||
- Text.Configure.OpenAI.Prefered.Tip
|
- Text.Configure.OpenAI.Prefered.Tip
|
||||||
|
- Text.Diff.VisualLines.All
|
||||||
- Text.ExecuteCustomAction
|
- Text.ExecuteCustomAction
|
||||||
- Text.ExecuteCustomAction.Name
|
- Text.ExecuteCustomAction.Name
|
||||||
|
- Text.IssueLinkCM.OpenInBrowser
|
||||||
|
- Text.IssueLinkCM.CopyLink
|
||||||
- Text.Preference.AI.Name
|
- Text.Preference.AI.Name
|
||||||
- Text.Repository.CustomActions
|
- Text.Repository.CustomActions
|
||||||
- Text.Repository.CustomActions.Empty
|
- Text.Repository.CustomActions.Empty
|
||||||
|
@ -63,7 +69,7 @@
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### fr_FR.axaml: 87.72%
|
### fr_FR.axaml: 87.34%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -108,6 +114,7 @@
|
||||||
- Text.ConventionalCommit.ShortDescription
|
- Text.ConventionalCommit.ShortDescription
|
||||||
- Text.ConventionalCommit.Type
|
- Text.ConventionalCommit.Type
|
||||||
- Text.Diff.IgnoreWhitespace
|
- Text.Diff.IgnoreWhitespace
|
||||||
|
- Text.Diff.VisualLines.All
|
||||||
- Text.Discard.IncludeIgnored
|
- Text.Discard.IncludeIgnored
|
||||||
- Text.ExecuteCustomAction
|
- Text.ExecuteCustomAction
|
||||||
- Text.ExecuteCustomAction.Name
|
- Text.ExecuteCustomAction.Name
|
||||||
|
@ -119,6 +126,8 @@
|
||||||
- Text.Histories.Tips.Prefix
|
- Text.Histories.Tips.Prefix
|
||||||
- Text.Hotkeys.Repo.CommitWithAutoStage
|
- Text.Hotkeys.Repo.CommitWithAutoStage
|
||||||
- Text.Hotkeys.Repo.DiscardSelected
|
- Text.Hotkeys.Repo.DiscardSelected
|
||||||
|
- Text.IssueLinkCM.OpenInBrowser
|
||||||
|
- Text.IssueLinkCM.CopyLink
|
||||||
- Text.MoveRepositoryNode
|
- Text.MoveRepositoryNode
|
||||||
- Text.MoveRepositoryNode.Target
|
- Text.MoveRepositoryNode.Target
|
||||||
- Text.Preference.AI
|
- Text.Preference.AI
|
||||||
|
@ -156,7 +165,7 @@
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### pt_BR.axaml: 90.79%
|
### pt_BR.axaml: 90.39%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -203,12 +212,15 @@
|
||||||
- Text.ConventionalCommit.ShortDescription
|
- Text.ConventionalCommit.ShortDescription
|
||||||
- Text.ConventionalCommit.Type
|
- Text.ConventionalCommit.Type
|
||||||
- Text.CopyAllText
|
- Text.CopyAllText
|
||||||
|
- Text.Diff.VisualLines.All
|
||||||
- Text.Discard.IncludeIgnored
|
- Text.Discard.IncludeIgnored
|
||||||
- Text.ExecuteCustomAction
|
- Text.ExecuteCustomAction
|
||||||
- Text.ExecuteCustomAction.Name
|
- Text.ExecuteCustomAction.Name
|
||||||
- Text.FileHistory.FileContent
|
- Text.FileHistory.FileContent
|
||||||
- Text.FileHistory.FileChange
|
- Text.FileHistory.FileChange
|
||||||
- Text.GitLFS.Locks.OnlyMine
|
- Text.GitLFS.Locks.OnlyMine
|
||||||
|
- Text.IssueLinkCM.OpenInBrowser
|
||||||
|
- Text.IssueLinkCM.CopyLink
|
||||||
- Text.MoveRepositoryNode
|
- Text.MoveRepositoryNode
|
||||||
- Text.MoveRepositoryNode.Target
|
- Text.MoveRepositoryNode.Target
|
||||||
- Text.Preference.AI.Name
|
- Text.Preference.AI.Name
|
||||||
|
@ -228,13 +240,15 @@
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### ru_RU.axaml: 100.00%
|
### ru_RU.axaml: 99.56%
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing Keys</summary>
|
<summary>Missing Keys</summary>
|
||||||
|
|
||||||
|
- Text.Diff.VisualLines.All
|
||||||
|
- Text.IssueLinkCM.OpenInBrowser
|
||||||
|
- Text.IssueLinkCM.CopyLink
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
8.36
|
8.37
|
|
@ -8,6 +8,10 @@ namespace SourceGit.Commands
|
||||||
{
|
{
|
||||||
[GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")]
|
[GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")]
|
||||||
private static partial Regex REG_INDICATOR();
|
private static partial Regex REG_INDICATOR();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^index\s([0-9a-f]{6,40})\.\.([0-9a-f]{6,40})(\s[1-9]{6})?")]
|
||||||
|
private static partial Regex REG_HASH_CHANGE();
|
||||||
|
|
||||||
private const string PREFIX_LFS_NEW = "+version https://git-lfs.github.com/spec/";
|
private const string PREFIX_LFS_NEW = "+version https://git-lfs.github.com/spec/";
|
||||||
private const string PREFIX_LFS_DEL = "-version https://git-lfs.github.com/spec/";
|
private const string PREFIX_LFS_DEL = "-version https://git-lfs.github.com/spec/";
|
||||||
private const string PREFIX_LFS_MODIFY = " version https://git-lfs.github.com/spec/";
|
private const string PREFIX_LFS_MODIFY = " version https://git-lfs.github.com/spec/";
|
||||||
|
@ -101,17 +105,31 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
if (_result.TextDiff.Lines.Count == 0)
|
if (_result.TextDiff.Lines.Count == 0)
|
||||||
{
|
{
|
||||||
var match = REG_INDICATOR().Match(line);
|
if (line.StartsWith("Binary", StringComparison.Ordinal))
|
||||||
if (!match.Success)
|
|
||||||
{
|
{
|
||||||
if (line.StartsWith("Binary", StringComparison.Ordinal))
|
_result.IsBinary = true;
|
||||||
_result.IsBinary = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_oldLine = int.Parse(match.Groups[1].Value);
|
if (string.IsNullOrEmpty(_result.OldHash))
|
||||||
_newLine = int.Parse(match.Groups[2].Value);
|
{
|
||||||
_result.TextDiff.Lines.Add(new Models.TextDiffLine(Models.TextDiffLineType.Indicator, line, 0, 0));
|
var match = REG_HASH_CHANGE().Match(line);
|
||||||
|
if (!match.Success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_result.OldHash = match.Groups[1].Value;
|
||||||
|
_result.NewHash = match.Groups[2].Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var match = REG_INDICATOR().Match(line);
|
||||||
|
if (!match.Success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_oldLine = int.Parse(match.Groups[1].Value);
|
||||||
|
_newLine = int.Parse(match.Groups[2].Value);
|
||||||
|
_result.TextDiff.Lines.Add(new Models.TextDiffLine(Models.TextDiffLineType.Indicator, line, 0, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace SourceGit.Models
|
||||||
|
|
||||||
public string Arguments
|
public string Arguments
|
||||||
{
|
{
|
||||||
get => _arguments;
|
get => _arguments;
|
||||||
set => SetProperty(ref _arguments, value);
|
set => SetProperty(ref _arguments, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace SourceGit.Models
|
||||||
{
|
{
|
||||||
public string File { get; set; } = string.Empty;
|
public string File { get; set; } = string.Empty;
|
||||||
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
|
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
|
||||||
public Vector SyncScrollOffset { get; set; } = Vector.Zero;
|
public Vector ScrollOffset { get; set; } = Vector.Zero;
|
||||||
public int MaxLineNumber = 0;
|
public int MaxLineNumber = 0;
|
||||||
|
|
||||||
public string Repo { get; set; } = null;
|
public string Repo { get; set; } = null;
|
||||||
|
@ -674,6 +674,8 @@ namespace SourceGit.Models
|
||||||
{
|
{
|
||||||
public bool IsBinary { get; set; } = false;
|
public bool IsBinary { get; set; } = false;
|
||||||
public bool IsLFS { get; set; } = false;
|
public bool IsLFS { get; set; } = false;
|
||||||
|
public string OldHash { get; set; } = string.Empty;
|
||||||
|
public string NewHash { get; set; } = string.Empty;
|
||||||
public string OldMode { get; set; } = string.Empty;
|
public string OldMode { get; set; } = string.Empty;
|
||||||
public string NewMode { get; set; } = string.Empty;
|
public string NewMode { get; set; } = string.Empty;
|
||||||
public TextDiff TextDiff { get; set; } = null;
|
public TextDiff TextDiff { get; set; } = null;
|
||||||
|
|
|
@ -13,15 +13,13 @@ namespace SourceGit.Models
|
||||||
public class ExternalTool
|
public class ExternalTool
|
||||||
{
|
{
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
public string Executable { get; private set; }
|
|
||||||
public string OpenCmdArgs { get; private set; }
|
|
||||||
public Bitmap IconImage { get; private set; } = null;
|
public Bitmap IconImage { get; private set; } = null;
|
||||||
|
|
||||||
public ExternalTool(string name, string icon, string executable, string openCmdArgs)
|
public ExternalTool(string name, string icon, string execFile, Func<string, string> execArgsGenerator = null)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Executable = executable;
|
_execFile = execFile;
|
||||||
OpenCmdArgs = openCmdArgs;
|
_execArgsGenerator = execArgsGenerator ?? (repo => $"\"{repo}\"");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -40,11 +38,14 @@ namespace SourceGit.Models
|
||||||
Process.Start(new ProcessStartInfo()
|
Process.Start(new ProcessStartInfo()
|
||||||
{
|
{
|
||||||
WorkingDirectory = repo,
|
WorkingDirectory = repo,
|
||||||
FileName = Executable,
|
FileName = _execFile,
|
||||||
Arguments = string.Format(OpenCmdArgs, repo),
|
Arguments = _execArgsGenerator.Invoke(repo),
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string _execFile = string.Empty;
|
||||||
|
private Func<string, string> _execArgsGenerator = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class JetBrainsState
|
public class JetBrainsState
|
||||||
|
@ -110,48 +111,48 @@ namespace SourceGit.Models
|
||||||
_customPaths = new ExternalToolPaths();
|
_customPaths = new ExternalToolPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TryAdd(string name, string icon, string args, string key, Func<string> finder)
|
public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null)
|
||||||
{
|
{
|
||||||
if (_customPaths.Tools.TryGetValue(key, out var customPath) && File.Exists(customPath))
|
if (_customPaths.Tools.TryGetValue(name, out var customPath) && File.Exists(customPath))
|
||||||
{
|
{
|
||||||
Founded.Add(new ExternalTool(name, icon, customPath, args));
|
Founded.Add(new ExternalTool(name, icon, customPath, execArgsGenerator));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var path = finder();
|
var path = finder();
|
||||||
if (!string.IsNullOrEmpty(path) && File.Exists(path))
|
if (!string.IsNullOrEmpty(path) && File.Exists(path))
|
||||||
Founded.Add(new ExternalTool(name, icon, path, args));
|
Founded.Add(new ExternalTool(name, icon, path, execArgsGenerator));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void VSCode(Func<string> platformFinder)
|
public void VSCode(Func<string> platformFinder)
|
||||||
{
|
{
|
||||||
TryAdd("Visual Studio Code", "vscode", "\"{0}\"", "VSCODE", platformFinder);
|
TryAdd("Visual Studio Code", "vscode", platformFinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void VSCodeInsiders(Func<string> platformFinder)
|
public void VSCodeInsiders(Func<string> platformFinder)
|
||||||
{
|
{
|
||||||
TryAdd("Visual Studio Code - Insiders", "vscode_insiders", "\"{0}\"", "VSCODE_INSIDERS", platformFinder);
|
TryAdd("Visual Studio Code - Insiders", "vscode_insiders", platformFinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void VSCodium(Func<string> platformFinder)
|
public void VSCodium(Func<string> platformFinder)
|
||||||
{
|
{
|
||||||
TryAdd("VSCodium", "codium", "\"{0}\"", "VSCODIUM", platformFinder);
|
TryAdd("VSCodium", "codium", platformFinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Fleet(Func<string> platformFinder)
|
public void Fleet(Func<string> platformFinder)
|
||||||
{
|
{
|
||||||
TryAdd("Fleet", "fleet", "\"{0}\"", "FLEET", platformFinder);
|
TryAdd("Fleet", "fleet", platformFinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SublimeText(Func<string> platformFinder)
|
public void SublimeText(Func<string> platformFinder)
|
||||||
{
|
{
|
||||||
TryAdd("Sublime Text", "sublime_text", "\"{0}\"", "SUBLIME_TEXT", platformFinder);
|
TryAdd("Sublime Text", "sublime_text", platformFinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Zed(Func<string> platformFinder)
|
public void Zed(Func<string> platformFinder)
|
||||||
{
|
{
|
||||||
TryAdd("Zed", "zed", "\"{0}\"", "ZED", platformFinder);
|
TryAdd("Zed", "zed", platformFinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FindJetBrainsFromToolbox(Func<string> platformFinder)
|
public void FindJetBrainsFromToolbox(Func<string> platformFinder)
|
||||||
|
@ -170,8 +171,7 @@ namespace SourceGit.Models
|
||||||
Founded.Add(new ExternalTool(
|
Founded.Add(new ExternalTool(
|
||||||
$"{tool.DisplayName} {tool.DisplayVersion}",
|
$"{tool.DisplayName} {tool.DisplayVersion}",
|
||||||
supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB",
|
supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB",
|
||||||
Path.Combine(tool.InstallLocation, tool.LaunchCommand),
|
Path.Combine(tool.InstallLocation, tool.LaunchCommand)));
|
||||||
"\"{0}\""));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,7 @@ namespace SourceGit.Native
|
||||||
finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe");
|
finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe");
|
||||||
finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox");
|
finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox");
|
||||||
finder.SublimeText(FindSublimeText);
|
finder.SublimeText(FindSublimeText);
|
||||||
|
finder.TryAdd("Visual Studio", "vs", FindVisualStudio, GenerateCommandlineArgsForVisualStudio);
|
||||||
return finder.Founded;
|
return finder.Founded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,6 +314,27 @@ namespace SourceGit.Native
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string FindVisualStudio()
|
||||||
|
{
|
||||||
|
var localMachine = Microsoft.Win32.RegistryKey.OpenBaseKey(
|
||||||
|
Microsoft.Win32.RegistryHive.LocalMachine,
|
||||||
|
Microsoft.Win32.RegistryView.Registry64);
|
||||||
|
|
||||||
|
// Get default class for VisualStudio.Launcher.sln - the handler for *.sln files
|
||||||
|
if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is Microsoft.Win32.RegistryKey launcher)
|
||||||
|
{
|
||||||
|
// Get actual path to the executable
|
||||||
|
if (launcher.GetValue(string.Empty) is string CLSID &&
|
||||||
|
localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv &&
|
||||||
|
devenv.GetValue(string.Empty) is string localServer32)
|
||||||
|
{
|
||||||
|
return localServer32!.Trim('\"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void OpenFolderAndSelectFile(string folderPath)
|
private void OpenFolderAndSelectFile(string folderPath)
|
||||||
|
@ -328,5 +350,34 @@ namespace SourceGit.Native
|
||||||
ILFree(pidl);
|
ILFree(pidl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateCommandlineArgsForVisualStudio(string repo)
|
||||||
|
{
|
||||||
|
var sln = FindVSSolutionFile(new DirectoryInfo(repo), 4);
|
||||||
|
return string.IsNullOrEmpty(sln) ? $"\"{repo}\"" : $"\"{sln}\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FindVSSolutionFile(DirectoryInfo dir, int leftDepth)
|
||||||
|
{
|
||||||
|
var files = dir.GetFiles();
|
||||||
|
foreach (var f in files)
|
||||||
|
{
|
||||||
|
if (f.Name.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return f.FullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leftDepth <= 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var subDirs = dir.GetDirectories();
|
||||||
|
foreach (var subDir in subDirs)
|
||||||
|
{
|
||||||
|
var first = FindVSSolutionFile(subDir, leftDepth - 1);
|
||||||
|
if (!string.IsNullOrEmpty(first))
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
<StreamGeometry x:Key="Icons.LayoutHorizontal">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zM139 832V192c0-6 4-11 11-11h331v661H149c-6 0-11-4-11-11zm747 0c0 6-4 11-11 11H544v-661H875c6 0 11 4 11 11v640z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.LayoutHorizontal">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zM139 832V192c0-6 4-11 11-11h331v661H149c-6 0-11-4-11-11zm747 0c0 6-4 11-11 11H544v-661H875c6 0 11 4 11 11v640z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.LayoutVertical">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zm-725 64h725c6 0 11 4 11 11v288h-747V192c0-6 4-11 11-11zm725 661H149c-6 0-11-4-11-11V544h747V832c0 6-4 11-11 11z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.LayoutVertical">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zm-725 64h725c6 0 11 4 11 11v288h-747V192c0-6 4-11 11-11zm725 661H149c-6 0-11-4-11-11V544h747V832c0 6-4 11-11 11z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.LFS">M40 9 15 23 15 31 9 28 9 20 34 5 24 0 0 14 0 34 25 48 25 28 49 14zM26 29 26 48 49 34 49 15z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.LFS">M40 9 15 23 15 31 9 28 9 20 34 5 24 0 0 14 0 34 25 48 25 28 49 14zM26 29 26 48 49 34 49 15z</StreamGeometry>
|
||||||
|
<StreamGeometry x:Key="Icons.Lines.All">M416 192m32 0 448 0q32 0 32 32l0 0q0 32-32 32l-448 0q-32 0-32-32l0 0q0-32 32-32ZM416 448m32 0 448 0q32 0 32 32l0 0q0 32-32 32l-448 0q-32 0-32-32l0 0q0-32 32-32ZM416 704m32 0 448 0q32 0 32 32l0 0q0 32-32 32l-448 0q-32 0-32-32l0 0q0-32 32-32ZM96 320l128-192 128 192h-256zM96 640l128 192 128-192h-256zM190 320h64v320H190z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Lines.Incr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l132 0 0-128 64 0 0 128 132 0 0 64-132 0 0 128-64 0 0-128-132 0Z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Lines.Incr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l132 0 0-128 64 0 0 128 132 0 0 64-132 0 0 128-64 0 0-128-132 0Z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Lines.Decr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l328 0 0 64-328 0Z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Lines.Decr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l328 0 0 64-328 0Z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Link">M 968 418 l -95 94 c -59 59 -146 71 -218 37 L 874 331 a 64 64 0 0 0 0 -90 L 783 150 a 64 64 0 0 0 -90 0 L 475 368 c -34 -71 -22 -159 37 -218 l 94 -94 c 75 -75 196 -75 271 0 l 90 90 c 75 75 75 196 0 271 z M 332 693 a 64 64 0 0 1 0 -90 l 271 -271 c 25 -25 65 -25 90 0 s 25 65 0 90 L 422 693 a 64 64 0 0 1 -90 0 z M 151 783 l 90 90 a 64 64 0 0 0 90 0 l 218 -218 c 34 71 22 159 -37 218 l -86 94 a 192 192 0 0 1 -271 0 l -98 -98 a 192 192 0 0 1 0 -271 l 94 -86 c 59 -59 146 -71 218 -37 L 151 693 a 64 64 0 0 0 0 90 z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Link">M 968 418 l -95 94 c -59 59 -146 71 -218 37 L 874 331 a 64 64 0 0 0 0 -90 L 783 150 a 64 64 0 0 0 -90 0 L 475 368 c -34 -71 -22 -159 37 -218 l 94 -94 c 75 -75 196 -75 271 0 l 90 90 c 75 75 75 196 0 271 z M 332 693 a 64 64 0 0 1 0 -90 l 271 -271 c 25 -25 65 -25 90 0 s 25 65 0 90 L 422 693 a 64 64 0 0 1 -90 0 z M 151 783 l 90 90 a 64 64 0 0 0 90 0 l 218 -218 c 34 71 22 159 -37 218 l -86 94 a 192 192 0 0 1 -271 0 l -98 -98 a 192 192 0 0 1 0 -271 l 94 -86 c 59 -59 146 -71 218 -37 L 151 693 a 64 64 0 0 0 0 90 z</StreamGeometry>
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Optional. Default is the destination folder name.</x:String>
|
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Optional. Default is the destination folder name.</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Track Branch:</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Track Branch:</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Tracking remote branch</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Tracking remote branch</x:String>
|
||||||
<x:String x:Key="Text.AIAssistant" xml:space="preserve">OpenAI Assistant</x:String>
|
<x:String x:Key="Text.AIAssistant" xml:space="preserve">AI Assistant</x:String>
|
||||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use OpenAI to generate commit message</x:String>
|
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use AI to generate commit message</x:String>
|
||||||
<x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String>
|
<x:String x:Key="Text.Apply" 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" 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.Error.Desc" xml:space="preserve">Raise errors and refuses to apply the patch</x:String>
|
||||||
|
@ -166,7 +166,7 @@
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Rule Name:</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Rule Name:</x:String>
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">Result URL:</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">Result URL:</x:String>
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Please use $1, $2 to access regex groups values.</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Please use $1, $2 to access regex groups values.</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">OPEN AI</x:String>
|
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">Prefered Service:</x:String>
|
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">Prefered Service:</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">If the 'Prefered Service' is set, SourceGit will only use it in this repository. Otherwise, if there is more than one service available, a context menu to choose one of them will be shown.</x:String>
|
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">If the 'Prefered Service' is set, SourceGit will only use it in this repository. Otherwise, if there is more than one service available, a context menu to choose one of them will be shown.</x:String>
|
||||||
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP Proxy</x:String>
|
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP Proxy</x:String>
|
||||||
|
@ -246,6 +246,7 @@
|
||||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
|
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
|
||||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Line Word Wrap</x:String>
|
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Line Word Wrap</x:String>
|
||||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Open in Merge Tool</x:String>
|
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Open in Merge Tool</x:String>
|
||||||
|
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Show All Lines</x:String>
|
||||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Decrease Number of Visible Lines</x:String>
|
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Decrease Number of Visible Lines</x:String>
|
||||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Increase Number of Visible Lines</x:String>
|
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Increase Number of Visible Lines</x:String>
|
||||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECT FILE TO VIEW CHANGES</x:String>
|
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECT FILE TO VIEW CHANGES</x:String>
|
||||||
|
@ -274,7 +275,7 @@
|
||||||
<x:String x:Key="Text.FileCM.DiscardMulti" xml:space="preserve">Discard {0} files...</x:String>
|
<x:String x:Key="Text.FileCM.DiscardMulti" xml:space="preserve">Discard {0} files...</x:String>
|
||||||
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">Discard Changes in Selected Line(s)</x:String>
|
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">Discard Changes in Selected Line(s)</x:String>
|
||||||
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Open External Merge Tool</x:String>
|
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Open External Merge Tool</x:String>
|
||||||
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Save As Patch...</x:String>
|
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Save as Patch...</x:String>
|
||||||
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">Stage</x:String>
|
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">Stage</x:String>
|
||||||
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">Stage {0} files</x:String>
|
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">Stage {0} files</x:String>
|
||||||
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Stage Changes in Selected Line(s)</x:String>
|
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Stage Changes in Selected Line(s)</x:String>
|
||||||
|
@ -387,6 +388,8 @@
|
||||||
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Interactive Rebase</x:String>
|
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Interactive Rebase</x:String>
|
||||||
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">Target Branch:</x:String>
|
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">Target Branch:</x:String>
|
||||||
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">On:</x:String>
|
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">On:</x:String>
|
||||||
|
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Open in Browser</x:String>
|
||||||
|
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">Copy Link</x:String>
|
||||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERROR</x:String>
|
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERROR</x:String>
|
||||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">NOTICE</x:String>
|
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">NOTICE</x:String>
|
||||||
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Branch</x:String>
|
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Branch</x:String>
|
||||||
|
@ -398,7 +401,7 @@
|
||||||
<x:String x:Key="Text.Name" xml:space="preserve">Name:</x:String>
|
<x:String x:Key="Text.Name" xml:space="preserve">Name:</x:String>
|
||||||
<x:String x:Key="Text.NotConfigured" xml:space="preserve">Git has NOT been configured. Please to go [Preference] and configure it first.</x:String>
|
<x:String x:Key="Text.NotConfigured" xml:space="preserve">Git has NOT been configured. Please to go [Preference] and configure it first.</x:String>
|
||||||
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">Open App Data Dir</x:String>
|
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">Open App Data Dir</x:String>
|
||||||
<x:String x:Key="Text.OpenWith" xml:space="preserve">Open With...</x:String>
|
<x:String x:Key="Text.OpenWith" xml:space="preserve">Open with...</x:String>
|
||||||
<x:String x:Key="Text.Optional" xml:space="preserve">Optional.</x:String>
|
<x:String x:Key="Text.Optional" xml:space="preserve">Optional.</x:String>
|
||||||
<x:String x:Key="Text.PageTabBar.New" xml:space="preserve">Create New Page</x:String>
|
<x:String x:Key="Text.PageTabBar.New" xml:space="preserve">Create New Page</x:String>
|
||||||
<x:String x:Key="Text.PageTabBar.Tab.Bookmark" xml:space="preserve">Bookmark</x:String>
|
<x:String x:Key="Text.PageTabBar.Tab.Bookmark" xml:space="preserve">Bookmark</x:String>
|
||||||
|
@ -418,7 +421,7 @@
|
||||||
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">Last year</x:String>
|
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">Last year</x:String>
|
||||||
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} years ago</x:String>
|
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} years ago</x:String>
|
||||||
<x:String x:Key="Text.Preference" xml:space="preserve">Preference</x:String>
|
<x:String x:Key="Text.Preference" xml:space="preserve">Preference</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OPEN AI</x:String>
|
<x:String x:Key="Text.Preference.AI" xml:space="preserve">AI</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
|
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API Key</x:String>
|
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API Key</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
|
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
|
||||||
|
@ -530,15 +533,15 @@
|
||||||
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Custom Actions</x:String>
|
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Custom Actions</x:String>
|
||||||
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">No Custom Actions</x:String>
|
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">No Custom Actions</x:String>
|
||||||
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Enable '--reflog' Option</x:String>
|
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Enable '--reflog' Option</x:String>
|
||||||
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open In File Browser</x:String>
|
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open in File Browser</x:String>
|
||||||
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Search Branches/Tags/Submodules</x:String>
|
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Search Branches/Tags/Submodules</x:String>
|
||||||
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">FILTERED BY:</x:String>
|
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">FILTERED BY:</x:String>
|
||||||
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOCAL BRANCHES</x:String>
|
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOCAL BRANCHES</x:String>
|
||||||
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate To HEAD</x:String>
|
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate to HEAD</x:String>
|
||||||
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Enable '--first-parent' Option</x:String>
|
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Enable '--first-parent' Option</x:String>
|
||||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
|
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
|
||||||
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Open In {0}</x:String>
|
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Open in {0}</x:String>
|
||||||
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open In External Tools</x:String>
|
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open in External Tools</x:String>
|
||||||
<x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Refresh</x:String>
|
<x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Refresh</x:String>
|
||||||
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String>
|
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String>
|
||||||
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADD REMOTE</x:String>
|
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADD REMOTE</x:String>
|
||||||
|
@ -556,7 +559,7 @@
|
||||||
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">UPDATE SUBMODULE</x:String>
|
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">UPDATE SUBMODULE</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEW TAG</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEW TAG</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open In Terminal</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String>
|
||||||
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
|
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
|
||||||
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ADD WORKTREE</x:String>
|
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ADD WORKTREE</x:String>
|
||||||
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>
|
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">选填。默认使用目标文件夹名称。</x:String>
|
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">选填。默认使用目标文件夹名称。</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟踪分支</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">跟踪分支</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">设置上游跟踪分支</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">设置上游跟踪分支</x:String>
|
||||||
<x:String x:Key="Text.AIAssistant" xml:space="preserve">OpenAI助手</x:String>
|
<x:String x:Key="Text.AIAssistant" xml:space="preserve">AI助手</x:String>
|
||||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用OpenAI助手生成提交信息</x:String>
|
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用AI助手生成提交信息</x:String>
|
||||||
<x:String x:Key="Text.Apply" xml:space="preserve">应用补丁(apply)</x:String>
|
<x:String x:Key="Text.Apply" 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" xml:space="preserve">错误</x:String>
|
||||||
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">输出错误,并终止应用补丁</x:String>
|
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">输出错误,并终止应用补丁</x:String>
|
||||||
|
@ -169,9 +169,9 @@
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">规则名 :</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">规则名 :</x:String>
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">为ISSUE生成的URL链接 :</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">为ISSUE生成的URL链接 :</x:String>
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">可在URL中使用$1,$2等变量填入正则表达式匹配的内容</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">可在URL中使用$1,$2等变量填入正则表达式匹配的内容</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">OPEN AI</x:String>
|
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">启用特定服务 :</x:String>
|
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">启用特定服务 :</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">当【启用特定服务】被设置时,SourceGit将在本仓库中仅使用该服务。否则将弹出可用的OpenAI服务列表供用户选择。</x:String>
|
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">当【启用特定服务】被设置时,SourceGit将在本仓库中仅使用该服务。否则将弹出可用的AI服务列表供用户选择。</x:String>
|
||||||
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP代理</x:String>
|
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP代理</x:String>
|
||||||
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP网络代理</x:String>
|
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP网络代理</x:String>
|
||||||
<x:String x:Key="Text.Configure.User" xml:space="preserve">用户名</x:String>
|
<x:String x:Key="Text.Configure.User" xml:space="preserve">用户名</x:String>
|
||||||
|
@ -249,6 +249,7 @@
|
||||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">语法高亮</x:String>
|
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">语法高亮</x:String>
|
||||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">自动换行</x:String>
|
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">自动换行</x:String>
|
||||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合并工具查看</x:String>
|
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合并工具查看</x:String>
|
||||||
|
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">显示完整文件</x:String>
|
||||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">减少可见的行数</x:String>
|
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">减少可见的行数</x:String>
|
||||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可见的行数</x:String>
|
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可见的行数</x:String>
|
||||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">请选择需要对比的文件</x:String>
|
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">请选择需要对比的文件</x:String>
|
||||||
|
@ -390,6 +391,8 @@
|
||||||
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">交互式变基</x:String>
|
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">交互式变基</x:String>
|
||||||
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">目标分支 :</x:String>
|
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">目标分支 :</x:String>
|
||||||
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">起始提交 :</x:String>
|
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">起始提交 :</x:String>
|
||||||
|
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">在浏览器中访问</x:String>
|
||||||
|
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">复制链接地址</x:String>
|
||||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">出错了</x:String>
|
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">出错了</x:String>
|
||||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系统提示</x:String>
|
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系统提示</x:String>
|
||||||
<x:String x:Key="Text.Merge" xml:space="preserve">合并分支</x:String>
|
<x:String x:Key="Text.Merge" xml:space="preserve">合并分支</x:String>
|
||||||
|
@ -421,7 +424,7 @@
|
||||||
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String>
|
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String>
|
||||||
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0}年前</x:String>
|
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0}年前</x:String>
|
||||||
<x:String x:Key="Text.Preference" xml:space="preserve">偏好设置</x:String>
|
<x:String x:Key="Text.Preference" xml:space="preserve">偏好设置</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OPEN AI</x:String>
|
<x:String x:Key="Text.Preference.AI" xml:space="preserve">AI</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
|
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API密钥</x:String>
|
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API密钥</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
|
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">選填。預設使用目標資料夾名稱。</x:String>
|
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">選填。預設使用目標資料夾名稱。</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">追蹤分支</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">追蹤分支</x:String>
|
||||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">設定遠端追蹤分支</x:String>
|
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">設定遠端追蹤分支</x:String>
|
||||||
<x:String x:Key="Text.AIAssistant" xml:space="preserve">OpenAI 助理</x:String>
|
<x:String x:Key="Text.AIAssistant" xml:space="preserve">AI 助理</x:String>
|
||||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用 OpenAI 產生提交訊息</x:String>
|
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">使用 AI 產生提交訊息</x:String>
|
||||||
<x:String x:Key="Text.Apply" xml:space="preserve">套用修補檔 (apply patch)</x:String>
|
<x:String x:Key="Text.Apply" 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" xml:space="preserve">錯誤</x:String>
|
||||||
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">輸出錯誤,並中止套用修補檔</x:String>
|
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">輸出錯誤,並中止套用修補檔</x:String>
|
||||||
|
@ -169,9 +169,9 @@
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">規則名稱:</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">規則名稱:</x:String>
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">為 Issue 產生的網址連結:</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">為 Issue 產生的網址連結:</x:String>
|
||||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">可在網址中使用 $1、$2 等變數填入正規表達式相符的內容</x:String>
|
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">可在網址中使用 $1、$2 等變數填入正規表達式相符的內容</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">OpenAI</x:String>
|
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">偏好服務:</x:String>
|
<x:String x:Key="Text.Configure.OpenAI.Prefered" xml:space="preserve">偏好服務:</x:String>
|
||||||
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">設定 [偏好服務] 後,SourceGit 將於此存放庫中使用該服務,否則會顯示 OpenAI 服務列表供使用者選擇。</x:String>
|
<x:String x:Key="Text.Configure.OpenAI.Prefered.Tip" xml:space="preserve">設定 [偏好服務] 後,SourceGit 將於此存放庫中使用該服務,否則會顯示 AI 服務列表供使用者選擇。</x:String>
|
||||||
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP 代理</x:String>
|
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP 代理</x:String>
|
||||||
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP 網路代理</x:String>
|
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP 網路代理</x:String>
|
||||||
<x:String x:Key="Text.Configure.User" xml:space="preserve">使用者名稱</x:String>
|
<x:String x:Key="Text.Configure.User" xml:space="preserve">使用者名稱</x:String>
|
||||||
|
@ -249,6 +249,7 @@
|
||||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">語法上色</x:String>
|
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">語法上色</x:String>
|
||||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">自動換行</x:String>
|
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">自動換行</x:String>
|
||||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合併工具檢視</x:String>
|
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合併工具檢視</x:String>
|
||||||
|
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">顯示檔案的全部內容</x:String>
|
||||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">減少可見的行數</x:String>
|
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">減少可見的行數</x:String>
|
||||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可見的行數</x:String>
|
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可見的行數</x:String>
|
||||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">請選擇需要對比的檔案</x:String>
|
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">請選擇需要對比的檔案</x:String>
|
||||||
|
@ -390,6 +391,8 @@
|
||||||
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">互動式重定基底</x:String>
|
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">互動式重定基底</x:String>
|
||||||
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">目標分支:</x:String>
|
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">目標分支:</x:String>
|
||||||
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">起始提交:</x:String>
|
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">起始提交:</x:String>
|
||||||
|
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">在瀏覽器中存取網址</x:String>
|
||||||
|
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">複製網址</x:String>
|
||||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">發生錯誤</x:String>
|
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">發生錯誤</x:String>
|
||||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系統提示</x:String>
|
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系統提示</x:String>
|
||||||
<x:String x:Key="Text.Merge" xml:space="preserve">合併分支</x:String>
|
<x:String x:Key="Text.Merge" xml:space="preserve">合併分支</x:String>
|
||||||
|
@ -421,7 +424,7 @@
|
||||||
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String>
|
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String>
|
||||||
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String>
|
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String>
|
||||||
<x:String x:Key="Text.Preference" xml:space="preserve">偏好設定</x:String>
|
<x:String x:Key="Text.Preference" xml:space="preserve">偏好設定</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OpenAI</x:String>
|
<x:String x:Key="Text.Preference.AI" xml:space="preserve">AI</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">伺服器</x:String>
|
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">伺服器</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API 金鑰</x:String>
|
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API 金鑰</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">模型</x:String>
|
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">模型</x:String>
|
||||||
|
|
|
@ -33,12 +33,6 @@ namespace SourceGit.ViewModels
|
||||||
private set => SetProperty(ref _fileModeChange, value);
|
private set => SetProperty(ref _fileModeChange, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsLoading
|
|
||||||
{
|
|
||||||
get => _isLoading;
|
|
||||||
private set => SetProperty(ref _isLoading, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsTextDiff
|
public bool IsTextDiff
|
||||||
{
|
{
|
||||||
get => _isTextDiff;
|
get => _isTextDiff;
|
||||||
|
@ -68,6 +62,7 @@ namespace SourceGit.ViewModels
|
||||||
_content = previous._content;
|
_content = previous._content;
|
||||||
_unifiedLines = previous._unifiedLines;
|
_unifiedLines = previous._unifiedLines;
|
||||||
_ignoreWhitespace = previous._ignoreWhitespace;
|
_ignoreWhitespace = previous._ignoreWhitespace;
|
||||||
|
_info = previous._info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
|
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
|
||||||
|
@ -78,6 +73,12 @@ namespace SourceGit.ViewModels
|
||||||
LoadDiffContent();
|
LoadDiffContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ToggleFullTextDiff()
|
||||||
|
{
|
||||||
|
Preference.Instance.UseFullTextDiff = !Preference.Instance.UseFullTextDiff;
|
||||||
|
LoadDiffContent();
|
||||||
|
}
|
||||||
|
|
||||||
public void IncrUnified()
|
public void IncrUnified()
|
||||||
{
|
{
|
||||||
UnifiedLines = _unifiedLines + 1;
|
UnifiedLines = _unifiedLines + 1;
|
||||||
|
@ -103,15 +104,23 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
Content = null;
|
Content = null;
|
||||||
IsTextDiff = false;
|
IsTextDiff = false;
|
||||||
IsLoading = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
var latest = new Commands.Diff(_repo, _option, _unifiedLines, _ignoreWhitespace).Result();
|
// NOTE: Here we override the UnifiedLines value (if UseFullTextDiff is on).
|
||||||
var rs = null as object;
|
// There is no way to tell a git-diff to use "ALL lines of context",
|
||||||
|
// so instead we set a very high number for the "lines of context" parameter.
|
||||||
|
var numLines = Preference.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
|
||||||
|
var latest = new Commands.Diff(_repo, _option, numLines, _ignoreWhitespace).Result();
|
||||||
|
var info = new Info(_option, numLines, _ignoreWhitespace, latest);
|
||||||
|
if (_info != null && info.IsSame(_info))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_info = info;
|
||||||
|
|
||||||
|
var rs = null as object;
|
||||||
if (latest.TextDiff != null)
|
if (latest.TextDiff != null)
|
||||||
{
|
{
|
||||||
var count = latest.TextDiff.Lines.Count;
|
var count = latest.TextDiff.Lines.Count;
|
||||||
|
@ -203,12 +212,11 @@ namespace SourceGit.ViewModels
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
if (_content is Models.TextDiff old && rs is Models.TextDiff cur && old.File == cur.File)
|
if (_content is Models.TextDiff old && rs is Models.TextDiff cur && old.File == cur.File)
|
||||||
cur.SyncScrollOffset = old.SyncScrollOffset;
|
cur.ScrollOffset = old.ScrollOffset;
|
||||||
|
|
||||||
FileModeChange = latest.FileModeChange;
|
FileModeChange = latest.FileModeChange;
|
||||||
Content = rs;
|
Content = rs;
|
||||||
IsTextDiff = rs is Models.TextDiff;
|
IsTextDiff = rs is Models.TextDiff;
|
||||||
IsLoading = false;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -241,14 +249,41 @@ namespace SourceGit.ViewModels
|
||||||
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
|
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private class Info
|
||||||
|
{
|
||||||
|
public string Argument { get; set; }
|
||||||
|
public int UnifiedLines { get; set; }
|
||||||
|
public bool IgnoreWhitespace { get; set; }
|
||||||
|
public string OldHash { get; set; }
|
||||||
|
public string NewHash { get; set; }
|
||||||
|
|
||||||
|
public Info(Models.DiffOption option, int unifiedLines, bool ignoreWhitespace, Models.DiffResult result)
|
||||||
|
{
|
||||||
|
Argument = option.ToString();
|
||||||
|
UnifiedLines = unifiedLines;
|
||||||
|
IgnoreWhitespace = ignoreWhitespace;
|
||||||
|
OldHash = result.OldHash;
|
||||||
|
NewHash = result.NewHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSame(Info other)
|
||||||
|
{
|
||||||
|
return Argument.Equals(other.Argument, StringComparison.Ordinal) &&
|
||||||
|
UnifiedLines == other.UnifiedLines &&
|
||||||
|
IgnoreWhitespace == other.IgnoreWhitespace &&
|
||||||
|
OldHash.Equals(other.OldHash, StringComparison.Ordinal) &&
|
||||||
|
NewHash.Equals(other.NewHash, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly string _repo;
|
private readonly string _repo;
|
||||||
private readonly Models.DiffOption _option = null;
|
private readonly Models.DiffOption _option = null;
|
||||||
private string _title;
|
private string _title;
|
||||||
private string _fileModeChange = string.Empty;
|
private string _fileModeChange = string.Empty;
|
||||||
private int _unifiedLines = 4;
|
private int _unifiedLines = 4;
|
||||||
private bool _isLoading = true;
|
|
||||||
private bool _isTextDiff = false;
|
private bool _isTextDiff = false;
|
||||||
private bool _ignoreWhitespace = false;
|
private bool _ignoreWhitespace = false;
|
||||||
private object _content = null;
|
private object _content = null;
|
||||||
|
private Info _info = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,12 @@ namespace SourceGit.ViewModels
|
||||||
set => SetProperty(ref _showHiddenSymbolsInDiffView, value);
|
set => SetProperty(ref _showHiddenSymbolsInDiffView, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool UseFullTextDiff
|
||||||
|
{
|
||||||
|
get => _useFullTextDiff;
|
||||||
|
set => SetProperty(ref _useFullTextDiff, value);
|
||||||
|
}
|
||||||
|
|
||||||
public Models.ChangeViewMode UnstagedChangeViewMode
|
public Models.ChangeViewMode UnstagedChangeViewMode
|
||||||
{
|
{
|
||||||
get => _unstagedChangeViewMode;
|
get => _unstagedChangeViewMode;
|
||||||
|
@ -591,6 +597,7 @@ namespace SourceGit.ViewModels
|
||||||
private bool _useSyntaxHighlighting = false;
|
private bool _useSyntaxHighlighting = false;
|
||||||
private bool _enableDiffViewWordWrap = false;
|
private bool _enableDiffViewWordWrap = false;
|
||||||
private bool _showHiddenSymbolsInDiffView = false;
|
private bool _showHiddenSymbolsInDiffView = false;
|
||||||
|
private bool _useFullTextDiff = false;
|
||||||
|
|
||||||
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
|
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
|
||||||
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;
|
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;
|
||||||
|
|
|
@ -407,8 +407,8 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
menu.Items.Add(copy);
|
menu.Items.Add(copy);
|
||||||
|
menu.Open(TextArea.TextView);
|
||||||
|
|
||||||
TextArea.TextView.OpenContextMenu(menu);
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace SourceGit.Views
|
||||||
if (DataContext is ViewModels.BranchCompare vm && sender is ChangeCollectionView view)
|
if (DataContext is ViewModels.BranchCompare vm && sender is ChangeCollectionView view)
|
||||||
{
|
{
|
||||||
var menu = vm.CreateChangeContextMenu();
|
var menu = vm.CreateChangeContextMenu();
|
||||||
view.OpenContextMenu(menu);
|
menu?.Open(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -374,7 +374,7 @@ namespace SourceGit.Views
|
||||||
if (selected.Count == 1 && selected[0] is ViewModels.BranchTreeNode { Backend: Models.Remote remote })
|
if (selected.Count == 1 && selected[0] is ViewModels.BranchTreeNode { Backend: Models.Remote remote })
|
||||||
{
|
{
|
||||||
var menu = repo.CreateContextMenuForRemote(remote);
|
var menu = repo.CreateContextMenuForRemote(remote);
|
||||||
this.OpenContextMenu(menu);
|
menu?.Open(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ namespace SourceGit.Views
|
||||||
var menu = branch.IsLocal ?
|
var menu = branch.IsLocal ?
|
||||||
repo.CreateContextMenuForLocalBranch(branch) :
|
repo.CreateContextMenuForLocalBranch(branch) :
|
||||||
repo.CreateContextMenuForRemoteBranch(branch);
|
repo.CreateContextMenuForRemoteBranch(branch);
|
||||||
this.OpenContextMenu(menu);
|
menu?.Open(this);
|
||||||
}
|
}
|
||||||
else if (branches.Find(x => x.IsCurrent) == null)
|
else if (branches.Find(x => x.IsCurrent) == null)
|
||||||
{
|
{
|
||||||
|
@ -405,7 +405,7 @@ namespace SourceGit.Views
|
||||||
ev.Handled = true;
|
ev.Handled = true;
|
||||||
};
|
};
|
||||||
menu.Items.Add(deleteMulti);
|
menu.Items.Add(deleteMulti);
|
||||||
this.OpenContextMenu(menu);
|
menu?.Open(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void OnOpenWebLink(object sender, RoutedEventArgs e)
|
private void OnOpenWebLink(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is ViewModels.CommitDetail detail)
|
if (DataContext is ViewModels.CommitDetail detail && sender is Control control)
|
||||||
{
|
{
|
||||||
var links = WebLinks;
|
var links = WebLinks;
|
||||||
if (links.Count > 1)
|
if (links.Count > 1)
|
||||||
|
@ -88,7 +88,7 @@ namespace SourceGit.Views
|
||||||
menu.Items.Add(item);
|
menu.Items.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
(sender as Control)?.OpenContextMenu(menu);
|
menu?.Open(control);
|
||||||
}
|
}
|
||||||
else if (links.Count == 1)
|
else if (links.Count == 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace SourceGit.Views
|
||||||
DataContext is ViewModels.CommitDetail vm)
|
DataContext is ViewModels.CommitDetail vm)
|
||||||
{
|
{
|
||||||
var menu = vm.CreateChangeContextMenu(selected[0]);
|
var menu = vm.CreateChangeContextMenu(selected[0]);
|
||||||
view.OpenContextMenu(menu);
|
menu?.Open(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace SourceGit.Views
|
||||||
if (DataContext is ViewModels.CommitDetail detail && sender is Grid grid && grid.DataContext is Models.Change change)
|
if (DataContext is ViewModels.CommitDetail detail && sender is Grid grid && grid.DataContext is Models.Change change)
|
||||||
{
|
{
|
||||||
var menu = detail.CreateChangeContextMenu(change);
|
var menu = detail.CreateChangeContextMenu(change);
|
||||||
grid.OpenContextMenu(menu);
|
menu?.Open(grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -176,7 +176,38 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Native.OS.OpenBrowser(_lastHover.Link);
|
var point = e.GetCurrentPoint(this);
|
||||||
|
var link = _lastHover.Link;
|
||||||
|
|
||||||
|
if (point.Properties.IsLeftButtonPressed)
|
||||||
|
{
|
||||||
|
Native.OS.OpenBrowser(link);
|
||||||
|
}
|
||||||
|
else if (point.Properties.IsRightButtonPressed)
|
||||||
|
{
|
||||||
|
var open = new MenuItem();
|
||||||
|
open.Header = App.Text("IssueLinkCM.OpenInBrowser");
|
||||||
|
open.Icon = App.CreateMenuIcon("Icons.OpenWith");
|
||||||
|
open.Click += (_, ev) =>
|
||||||
|
{
|
||||||
|
Native.OS.OpenBrowser(link);
|
||||||
|
ev.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var copy = new MenuItem();
|
||||||
|
copy.Header = App.Text("IssueLinkCM.CopyLink");
|
||||||
|
copy.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||||
|
copy.Click += (_, ev) =>
|
||||||
|
{
|
||||||
|
App.CopyText(link);
|
||||||
|
ev.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var menu = new ContextMenu();
|
||||||
|
menu.Items.Add(open);
|
||||||
|
menu.Items.Add(copy);
|
||||||
|
menu.Open(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
using System.ComponentModel;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
|
|
||||||
namespace SourceGit.Views
|
|
||||||
{
|
|
||||||
public static class ContextMenuExtension
|
|
||||||
{
|
|
||||||
public static void OpenContextMenu(this Control control, ContextMenu menu)
|
|
||||||
{
|
|
||||||
if (menu == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
menu.PlacementTarget = control;
|
|
||||||
menu.Closing += OnContextMenuClosing; // Clear context menu because it is dynamic.
|
|
||||||
|
|
||||||
control.ContextMenu = menu;
|
|
||||||
control.ContextMenu?.Open();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void OnContextMenuClosing(object sender, CancelEventArgs e)
|
|
||||||
{
|
|
||||||
if (sender is ContextMenu menu && menu.PlacementTarget != null)
|
|
||||||
menu.PlacementTarget.ContextMenu = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -39,6 +39,9 @@
|
||||||
Command="{Binding IncrUnified}"
|
Command="{Binding IncrUnified}"
|
||||||
IsVisible="{Binding IsTextDiff}"
|
IsVisible="{Binding IsTextDiff}"
|
||||||
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
|
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
|
||||||
|
<Button.IsEnabled>
|
||||||
|
<Binding Source="{x:Static vm:Preference.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
|
||||||
|
</Button.IsEnabled>
|
||||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Incr}"/>
|
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Incr}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
@ -46,10 +49,26 @@
|
||||||
Width="32"
|
Width="32"
|
||||||
Command="{Binding DecrUnified}"
|
Command="{Binding DecrUnified}"
|
||||||
IsVisible="{Binding IsTextDiff}"
|
IsVisible="{Binding IsTextDiff}"
|
||||||
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}"
|
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}">
|
||||||
IsEnabled="{Binding UnifiedLines, Converter={x:Static c:IntConverters.IsGreaterThanFour}}">
|
<Button.IsEnabled>
|
||||||
|
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||||
|
<Binding Path="UnifiedLines" Mode="OneWay" Converter="{x:Static c:IntConverters.IsGreaterThanFour}"/>
|
||||||
|
<Binding Source="{x:Static vm:Preference.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
|
||||||
|
</MultiBinding>
|
||||||
|
</Button.IsEnabled>
|
||||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/>
|
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<ToggleButton Classes="line_path"
|
||||||
|
Width="32" Height="18"
|
||||||
|
Background="Transparent"
|
||||||
|
Padding="9,6"
|
||||||
|
Command="{Binding ToggleFullTextDiff}"
|
||||||
|
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
|
||||||
|
IsVisible="{Binding IsTextDiff}"
|
||||||
|
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.All}">
|
||||||
|
<Path Width="13" Height="13" Data="{StaticResource Icons.Lines.All}" Margin="0,3,0,0"/>
|
||||||
|
</ToggleButton>
|
||||||
|
|
||||||
<ToggleButton Classes="line_path"
|
<ToggleButton Classes="line_path"
|
||||||
Width="32" Height="18"
|
Width="32" Height="18"
|
||||||
|
@ -211,7 +230,9 @@
|
||||||
|
|
||||||
<!-- Text Diff -->
|
<!-- Text Diff -->
|
||||||
<DataTemplate DataType="m:TextDiff">
|
<DataTemplate DataType="m:TextDiff">
|
||||||
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"/>
|
<v:TextDiffView
|
||||||
|
UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
|
||||||
|
UseFullTextDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<!-- Empty or only EOL changes -->
|
<!-- Empty or only EOL changes -->
|
||||||
|
|
|
@ -706,7 +706,7 @@ namespace SourceGit.Views
|
||||||
if (DataContext is ViewModels.Histories histories && sender is ListBox { SelectedItems: { Count: > 0 } } list)
|
if (DataContext is ViewModels.Histories histories && sender is ListBox { SelectedItems: { Count: > 0 } } list)
|
||||||
{
|
{
|
||||||
var menu = histories.MakeContextMenu(list);
|
var menu = histories.MakeContextMenu(list);
|
||||||
list.OpenContextMenu(menu);
|
menu?.Open(list);
|
||||||
}
|
}
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,7 +250,7 @@ namespace SourceGit.Views
|
||||||
if (sender is Button btn && DataContext is ViewModels.Launcher launcher)
|
if (sender is Button btn && DataContext is ViewModels.Launcher launcher)
|
||||||
{
|
{
|
||||||
var menu = launcher.CreateContextForWorkspace();
|
var menu = launcher.CreateContextForWorkspace();
|
||||||
btn.OpenContextMenu(menu);
|
menu?.Open(btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -234,7 +234,7 @@ namespace SourceGit.Views
|
||||||
if (sender is Border border && DataContext is ViewModels.Launcher vm)
|
if (sender is Border border && DataContext is ViewModels.Launcher vm)
|
||||||
{
|
{
|
||||||
var menu = vm.CreateContextForPageTab(border.DataContext as ViewModels.LauncherPage);
|
var menu = vm.CreateContextForPageTab(border.DataContext as ViewModels.LauncherPage);
|
||||||
border.OpenContextMenu(menu);
|
menu?.Open(border);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -189,7 +189,7 @@ namespace SourceGit.Views
|
||||||
if (sender is ListBox { SelectedItem: Models.Submodule submodule } grid && DataContext is ViewModels.Repository repo)
|
if (sender is ListBox { SelectedItem: Models.Submodule submodule } grid && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
var menu = repo.CreateContextMenuForSubmodule(submodule.Path);
|
var menu = repo.CreateContextMenuForSubmodule(submodule.Path);
|
||||||
grid.OpenContextMenu(menu);
|
menu?.Open(grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
@ -210,7 +210,7 @@ namespace SourceGit.Views
|
||||||
if (sender is ListBox { SelectedItem: Models.Worktree worktree } grid && DataContext is ViewModels.Repository repo)
|
if (sender is ListBox { SelectedItem: Models.Worktree worktree } grid && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
var menu = repo.CreateContextMenuForWorktree(worktree);
|
var menu = repo.CreateContextMenuForWorktree(worktree);
|
||||||
grid.OpenContextMenu(menu);
|
menu?.Open(grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace SourceGit.Views
|
||||||
if (sender is Button button && DataContext is ViewModels.Repository repo)
|
if (sender is Button button && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
var menu = repo.CreateContextMenuForExternalTools();
|
var menu = repo.CreateContextMenuForExternalTools();
|
||||||
button.OpenContextMenu(menu);
|
menu?.Open(button);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,10 +72,10 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void OpenGitFlowMenu(object sender, RoutedEventArgs e)
|
private void OpenGitFlowMenu(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is ViewModels.Repository repo)
|
if (DataContext is ViewModels.Repository repo && sender is Control control)
|
||||||
{
|
{
|
||||||
var menu = repo.CreateContextMenuForGitFlow();
|
var menu = repo.CreateContextMenuForGitFlow();
|
||||||
(sender as Control)?.OpenContextMenu(menu);
|
menu?.Open(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
@ -83,10 +83,10 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void OpenGitLFSMenu(object sender, RoutedEventArgs e)
|
private void OpenGitLFSMenu(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is ViewModels.Repository repo)
|
if (DataContext is ViewModels.Repository repo && sender is Control control)
|
||||||
{
|
{
|
||||||
var menu = repo.CreateContextMenuForGitLFS();
|
var menu = repo.CreateContextMenuForGitLFS();
|
||||||
(sender as Control)?.OpenContextMenu(menu);
|
menu?.Open(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
@ -94,10 +94,10 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void OpenCustomActionMenu(object sender, RoutedEventArgs e)
|
private void OpenCustomActionMenu(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is ViewModels.Repository repo)
|
if (DataContext is ViewModels.Repository repo && sender is Control control)
|
||||||
{
|
{
|
||||||
var menu = repo.CreateContextMenuForCustomAction();
|
var menu = repo.CreateContextMenuForCustomAction();
|
||||||
(sender as Control)?.OpenContextMenu(menu);
|
menu?.Open(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace SourceGit.Views
|
||||||
if (DataContext is ViewModels.RevisionCompare vm && sender is ChangeCollectionView view)
|
if (DataContext is ViewModels.RevisionCompare vm && sender is ChangeCollectionView view)
|
||||||
{
|
{
|
||||||
var menu = vm.CreateChangeContextMenu();
|
var menu = vm.CreateChangeContextMenu();
|
||||||
view.OpenContextMenu(menu);
|
menu?.Open(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -229,7 +229,7 @@ namespace SourceGit.Views
|
||||||
if (obj.Type != Models.ObjectType.Tree)
|
if (obj.Type != Models.ObjectType.Tree)
|
||||||
{
|
{
|
||||||
var menu = vm.CreateRevisionFileContextMenu(obj);
|
var menu = vm.CreateRevisionFileContextMenu(obj);
|
||||||
grid.OpenContextMenu(menu);
|
menu?.Open(grid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,8 +95,8 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
menu.Items.Add(copy);
|
menu.Items.Add(copy);
|
||||||
|
menu.Open(TextArea.TextView);
|
||||||
|
|
||||||
TextArea.TextView.OpenContextMenu(menu);
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace SourceGit.Views
|
||||||
if (DataContext is ViewModels.StashesPage vm && sender is Border border)
|
if (DataContext is ViewModels.StashesPage vm && sender is Border border)
|
||||||
{
|
{
|
||||||
var menu = vm.MakeContextMenu(border.DataContext as Models.Stash);
|
var menu = vm.MakeContextMenu(border.DataContext as Models.Stash);
|
||||||
border.OpenContextMenu(menu);
|
menu?.Open(border);
|
||||||
}
|
}
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ namespace SourceGit.Views
|
||||||
if (DataContext is ViewModels.StashesPage vm && sender is Grid grid)
|
if (DataContext is ViewModels.StashesPage vm && sender is Grid grid)
|
||||||
{
|
{
|
||||||
var menu = vm.MakeContextMenuForChange(grid.DataContext as Models.Change);
|
var menu = vm.MakeContextMenuForChange(grid.DataContext as Models.Change);
|
||||||
grid.OpenContextMenu(menu);
|
menu?.Open(grid);
|
||||||
}
|
}
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,7 +225,7 @@ namespace SourceGit.Views
|
||||||
if (selected != null && DataContext is ViewModels.Repository repo)
|
if (selected != null && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
var menu = repo.CreateContextMenuForTag(selected);
|
var menu = repo.CreateContextMenuForTag(selected);
|
||||||
control.OpenContextMenu(menu);
|
menu?.Open(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
|
@ -589,8 +589,8 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
menu.Items.Add(copy);
|
menu.Items.Add(copy);
|
||||||
|
menu.Open(TextArea.TextView);
|
||||||
|
|
||||||
TextArea.TextView.OpenContextMenu(menu);
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -902,7 +902,7 @@ namespace SourceGit.Views
|
||||||
var scroller = this.FindDescendantOfType<ScrollViewer>();
|
var scroller = this.FindDescendantOfType<ScrollViewer>();
|
||||||
if (scroller != null)
|
if (scroller != null)
|
||||||
{
|
{
|
||||||
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.TwoWay));
|
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.TwoWay));
|
||||||
scroller.GotFocus += OnTextViewScrollGotFocus;
|
scroller.GotFocus += OnTextViewScrollGotFocus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1205,6 +1205,15 @@ namespace SourceGit.Views
|
||||||
set => SetValue(UseSideBySideDiffProperty, value);
|
set => SetValue(UseSideBySideDiffProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> UseFullTextDiffProperty =
|
||||||
|
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseFullTextDiff));
|
||||||
|
|
||||||
|
public bool UseFullTextDiff
|
||||||
|
{
|
||||||
|
get => GetValue(UseFullTextDiffProperty);
|
||||||
|
set => SetValue(UseFullTextDiffProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<TextDiffViewChunk> SelectedChunkProperty =
|
public static readonly StyledProperty<TextDiffViewChunk> SelectedChunkProperty =
|
||||||
AvaloniaProperty.Register<TextDiffView, TextDiffViewChunk>(nameof(SelectedChunk));
|
AvaloniaProperty.Register<TextDiffView, TextDiffViewChunk>(nameof(SelectedChunk));
|
||||||
|
|
||||||
|
@ -1236,15 +1245,12 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
|
UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
|
||||||
{
|
{
|
||||||
if (v.DataContext is Models.TextDiff diff)
|
v.RefreshContent(v.DataContext as Models.TextDiff, false);
|
||||||
{
|
});
|
||||||
diff.SyncScrollOffset = Vector.Zero;
|
|
||||||
|
|
||||||
if (v.UseSideBySideDiff)
|
UseFullTextDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
|
||||||
v.Editor.Content = new ViewModels.TwoSideTextDiff(diff);
|
{
|
||||||
else
|
v.RefreshContent(v.DataContext as Models.TextDiff, false);
|
||||||
v.Editor.Content = diff;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
SelectedChunkProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
|
SelectedChunkProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
|
||||||
|
@ -1271,25 +1277,7 @@ namespace SourceGit.Views
|
||||||
protected override void OnDataContextChanged(EventArgs e)
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnDataContextChanged(e);
|
base.OnDataContextChanged(e);
|
||||||
|
RefreshContent(DataContext as Models.TextDiff, true);
|
||||||
if (SelectedChunk != null)
|
|
||||||
SetCurrentValue(SelectedChunkProperty, null);
|
|
||||||
|
|
||||||
var diff = DataContext as Models.TextDiff;
|
|
||||||
if (diff == null)
|
|
||||||
{
|
|
||||||
Editor.Content = null;
|
|
||||||
GC.Collect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UseSideBySideDiff)
|
|
||||||
Editor.Content = new ViewModels.TwoSideTextDiff(diff, Editor.Content as ViewModels.TwoSideTextDiff);
|
|
||||||
else
|
|
||||||
Editor.Content = diff;
|
|
||||||
|
|
||||||
IsUnstagedChange = diff.Option.IsUnstaged;
|
|
||||||
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPointerExited(PointerEventArgs e)
|
protected override void OnPointerExited(PointerEventArgs e)
|
||||||
|
@ -1300,6 +1288,34 @@ namespace SourceGit.Views
|
||||||
SetCurrentValue(SelectedChunkProperty, null);
|
SetCurrentValue(SelectedChunkProperty, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RefreshContent(Models.TextDiff diff, bool keepScrollOffset = true)
|
||||||
|
{
|
||||||
|
if (SelectedChunk != null)
|
||||||
|
SetCurrentValue(SelectedChunkProperty, null);
|
||||||
|
|
||||||
|
if (diff == null)
|
||||||
|
{
|
||||||
|
Editor.Content = null;
|
||||||
|
GC.Collect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UseSideBySideDiff)
|
||||||
|
{
|
||||||
|
var previousContent = Editor.Content as ViewModels.TwoSideTextDiff;
|
||||||
|
Editor.Content = new ViewModels.TwoSideTextDiff(diff, keepScrollOffset ? previousContent : null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!keepScrollOffset)
|
||||||
|
diff.ScrollOffset = Vector.Zero;
|
||||||
|
Editor.Content = diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsUnstagedChange = diff.Option.IsUnstaged;
|
||||||
|
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnStageChunk(object _1, RoutedEventArgs _2)
|
private void OnStageChunk(object _1, RoutedEventArgs _2)
|
||||||
{
|
{
|
||||||
var chunk = SelectedChunk;
|
var chunk = SelectedChunk;
|
||||||
|
|
|
@ -117,7 +117,7 @@ namespace SourceGit.Views
|
||||||
if (sender is Grid { DataContext: ViewModels.RepositoryNode node } grid)
|
if (sender is Grid { DataContext: ViewModels.RepositoryNode node } grid)
|
||||||
{
|
{
|
||||||
var menu = ViewModels.Welcome.Instance.CreateContextMenu(node);
|
var menu = ViewModels.Welcome.Instance.CreateContextMenu(node);
|
||||||
grid.OpenContextMenu(menu);
|
menu?.Open(grid);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,27 +31,27 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
var menu = vm.CreateContextMenuForCommitMessages();
|
var menu = vm.CreateContextMenuForCommitMessages();
|
||||||
menu.Placement = PlacementMode.TopEdgeAlignedLeft;
|
menu.Placement = PlacementMode.TopEdgeAlignedLeft;
|
||||||
button.OpenContextMenu(menu);
|
menu?.Open(button);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUnstagedContextRequested(object sender, ContextRequestedEventArgs e)
|
private void OnUnstagedContextRequested(object sender, ContextRequestedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is ViewModels.WorkingCopy vm)
|
if (DataContext is ViewModels.WorkingCopy vm && sender is Control control)
|
||||||
{
|
{
|
||||||
var menu = vm.CreateContextMenuForUnstagedChanges();
|
var menu = vm.CreateContextMenuForUnstagedChanges();
|
||||||
(sender as Control)?.OpenContextMenu(menu);
|
menu?.Open(control);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStagedContextRequested(object sender, ContextRequestedEventArgs e)
|
private void OnStagedContextRequested(object sender, ContextRequestedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is ViewModels.WorkingCopy vm)
|
if (DataContext is ViewModels.WorkingCopy vm && sender is Control control)
|
||||||
{
|
{
|
||||||
var menu = vm.CreateContextMenuForStagedChanges();
|
var menu = vm.CreateContextMenuForStagedChanges();
|
||||||
(sender as Control)?.OpenContextMenu(menu);
|
menu?.Open(control);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,10 +136,10 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void OnOpenOpenAIHelper(object sender, RoutedEventArgs e)
|
private void OnOpenOpenAIHelper(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (DataContext is ViewModels.WorkingCopy vm)
|
if (DataContext is ViewModels.WorkingCopy vm && sender is Control control)
|
||||||
{
|
{
|
||||||
var menu = vm.CreateContextForOpenAI();
|
var menu = vm.CreateContextForOpenAI();
|
||||||
(sender as Button)?.OpenContextMenu(menu);
|
menu?.Open(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|
Loading…
Reference in a new issue