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