Merge branch 'release/v8.18'

This commit is contained in:
leo 2024-06-24 10:09:03 +08:00
commit 9a82d04b18
No known key found for this signature in database
102 changed files with 3238 additions and 928 deletions

View file

@ -45,7 +45,7 @@ jobs:
- name: Publish - name: Publish
run: dotnet publish src/SourceGit.csproj -c Release -o publish -r osx-x64 -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained run: dotnet publish src/SourceGit.csproj -c Release -o publish -r osx-x64 -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained
- name: Packing Program - name: Packing Program
run: tar -cvf sourcegit.osx-x64.tar publish/ run: tar -cvf sourcegit.osx-x64.tar -C publish/ .
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@ -68,7 +68,7 @@ jobs:
- name: Publish - name: Publish
run: dotnet publish src/SourceGit.csproj -c Release -o publish -r osx-arm64 -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained run: dotnet publish src/SourceGit.csproj -c Release -o publish -r osx-arm64 -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained
- name: Packing Program - name: Packing Program
run: tar -cvf sourcegit.osx-arm64.tar publish/ run: tar -cvf sourcegit.osx-arm64.tar -C publish/ .
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@ -93,7 +93,7 @@ jobs:
- name: Rename Executable File - name: Rename Executable File
run: mv publish/SourceGit publish/sourcegit run: mv publish/SourceGit publish/sourcegit
- name: Packing Program - name: Packing Program
run: tar -cvf sourcegit.linux-x64.tar publish/ run: tar -cvf sourcegit.linux-x64.tar -C publish/ .
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:

View file

@ -14,6 +14,8 @@ Opensource Git GUI client.
* Supports SSH access with each remote * Supports SSH access with each remote
* GIT commands with GUI * GIT commands with GUI
* Clone/Fetch/Pull/Push... * Clone/Fetch/Pull/Push...
* Merge/Rebase/Reset/Revert/Amend/Cherry-pick...
* Interactive rebase (Basic)
* Branches * Branches
* Remotes * Remotes
* Tags * Tags
@ -26,10 +28,11 @@ Opensource Git GUI client.
* Blame * Blame
* Revision Diffs * Revision Diffs
* Branch Diff * Branch Diff
* Image Diff * Image Diff - Side-By-Side/Swipe/Blend
* GitFlow support * GitFlow support
* Git LFS support
> **Linux** only tested on **Ubuntu 22.04** on **X11**. > **Linux** only tested on **Debian 12** on both **X11** & **Wayland**.
## How to Use ## How to Use
@ -110,8 +113,6 @@ This app supports open repository in external tools listed in the table below.
| Color.Border2 | Border color used in visual lines, like seperators, Rectange, etc. | | Color.Border2 | Border color used in visual lines, like seperators, Rectange, etc. |
| Color.FlatButton.Background | Flat button background color, like `Cancel`, `Commit & Push` button | | Color.FlatButton.Background | Flat button background color, like `Cancel`, `Commit & Push` button |
| Color.FlatButton.BackgroundHovered | Flat button background color when hovered, like `Cancel` button | | Color.FlatButton.BackgroundHovered | Flat button background color when hovered, like `Cancel` button |
| Color.FlatButton.PrimaryBackground | Primary flat button background color, like `Ok`, `Commit` button |
| Color.FlatButton.PrimaryBackgroundHovered | Primary flat button background color when hovered, like `Ok`, `Commit` button |
| Color.FG1 | Primary foreground color for all text elements | | Color.FG1 | Primary foreground color for all text elements |
| Color.FG2 | Secondary foreground color for all text elements | | Color.FG2 | Secondary foreground color for all text elements |
| Color.Diff.EmptyBG | Background color used in empty lines in diff viewer | | Color.Diff.EmptyBG | Background color used in empty lines in diff viewer |

View file

@ -1 +1 @@
8.17 8.18

View file

@ -6,6 +6,7 @@ namespace SourceGit
[JsonSourceGenerationOptions(WriteIndented = true, IgnoreReadOnlyFields = true, IgnoreReadOnlyProperties = true)] [JsonSourceGenerationOptions(WriteIndented = true, IgnoreReadOnlyFields = true, IgnoreReadOnlyProperties = true)]
[JsonSerializable(typeof(Models.Version))] [JsonSerializable(typeof(Models.Version))]
[JsonSerializable(typeof(Models.JetBrainsState))] [JsonSerializable(typeof(Models.JetBrainsState))]
[JsonSerializable(typeof(List<Models.InteractiveRebaseJob>))]
[JsonSerializable(typeof(Dictionary<string, string>))] [JsonSerializable(typeof(Dictionary<string, string>))]
[JsonSerializable(typeof(ViewModels.Preference))] [JsonSerializable(typeof(ViewModels.Preference))]
internal partial class JsonCodeGen : JsonSerializerContext { } internal partial class JsonCodeGen : JsonSerializerContext { }

View file

@ -45,14 +45,15 @@ namespace SourceGit
{ {
try try
{ {
if (args.Length > 1 && args[0].Equals("--rebase-editor", StringComparison.Ordinal))
Environment.Exit(Models.InteractiveRebaseEditor.Process(args[1]));
else
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
} }
catch (Exception ex) catch (Exception ex)
{ {
var builder = new StringBuilder(); var builder = new StringBuilder();
builder.Append("Crash: "); builder.Append($"Crash::: {ex.GetType().FullName}: {ex.Message}\n\n");
builder.Append(ex.Message);
builder.Append("\n\n");
builder.Append("----------------------------\n"); builder.Append("----------------------------\n");
builder.Append($"Version: {Assembly.GetExecutingAssembly().GetName().Version}\n"); builder.Append($"Version: {Assembly.GetExecutingAssembly().GetName().Version}\n");
builder.Append($"OS: {Environment.OSVersion.ToString()}\n"); builder.Append($"OS: {Environment.OSVersion.ToString()}\n");
@ -191,6 +192,10 @@ namespace SourceGit
var fmt = Current.FindResource($"Text.{key}") as string; var fmt = Current.FindResource($"Text.{key}") as string;
if (string.IsNullOrWhiteSpace(fmt)) if (string.IsNullOrWhiteSpace(fmt))
return $"Text.{key}"; return $"Text.{key}";
if (args == null || args.Length == 0)
return fmt;
return string.Format(fmt, args); return string.Format(fmt, args);
} }
@ -313,6 +318,18 @@ namespace SourceGit
}); });
} }
public static async Task<string> GetClipboardTextAsync()
{
if (Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
if (desktop.MainWindow.Clipboard is { } clipboard)
{
return await clipboard.GetTextAsync();
}
}
return default;
}
private ResourceDictionary _activeLocale = null; private ResourceDictionary _activeLocale = null;
private ResourceDictionary _colorOverrides = null; private ResourceDictionary _colorOverrides = null;
private Models.INotificationReceiver _notificationReceiver = null; private Models.INotificationReceiver _notificationReceiver = null;

View file

@ -43,9 +43,7 @@ namespace SourceGit.Commands
// Force using en_US.UTF-8 locale to avoid GCM crash // Force using en_US.UTF-8 locale to avoid GCM crash
if (OperatingSystem.IsLinux()) if (OperatingSystem.IsLinux())
{
start.Environment.Add("LANG", "en_US.UTF-8"); start.Environment.Add("LANG", "en_US.UTF-8");
}
if (!string.IsNullOrEmpty(WorkingDirectory)) if (!string.IsNullOrEmpty(WorkingDirectory))
start.WorkingDirectory = WorkingDirectory; start.WorkingDirectory = WorkingDirectory;

View file

@ -14,6 +14,9 @@ namespace SourceGit.Commands
public Dictionary<string, string> ListAll() public Dictionary<string, string> ListAll()
{ {
if (string.IsNullOrEmpty(WorkingDirectory))
Args = "config --global -l";
else
Args = "config -l"; Args = "config -l";
var output = ReadToEnd(); var output = ReadToEnd();

View file

@ -8,9 +8,9 @@ namespace SourceGit.Commands
{ {
var file = Path.Combine(repo, ".gitignore"); var file = Path.Combine(repo, ".gitignore");
if (!File.Exists(file)) if (!File.Exists(file))
File.WriteAllLines(file, [ pattern ]); File.WriteAllLines(file, [pattern]);
else else
File.AppendAllLines(file, [ pattern ]); File.AppendAllLines(file, [pattern]);
} }
} }
} }

View file

@ -1,17 +1,22 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.RegularExpressions;
namespace SourceGit.Commands namespace SourceGit.Commands
{ {
public class LFS public partial class LFS
{ {
class PruneCmd : Command [GeneratedRegex(@"^(.+)\s+(\w+)\s+\w+:(\d+)$")]
private static partial Regex REG_LOCK();
class SubCmd : Command
{ {
public PruneCmd(string repo, Action<string> onProgress) public SubCmd(string repo, string args, Action<string> onProgress)
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = "lfs prune"; Args = args;
TraitErrorAsOutput = true; TraitErrorAsOutput = true;
_outputHandler = onProgress; _outputHandler = onProgress;
} }
@ -39,9 +44,73 @@ namespace SourceGit.Commands
return content.Contains("git lfs pre-push"); return content.Contains("git lfs pre-push");
} }
public bool Install()
{
return new SubCmd(_repo, $"lfs install", null).Exec();
}
public bool Track(string pattern, bool isFilenameMode = false)
{
var opt = isFilenameMode ? "--filename" : "";
return new SubCmd(_repo, $"lfs track {opt} \"{pattern}\"", null).Exec();
}
public void Fetch(Action<string> outputHandler)
{
new SubCmd(_repo, $"lfs fetch", outputHandler).Exec();
}
public void Pull(Action<string> outputHandler)
{
new SubCmd(_repo, $"lfs pull", outputHandler).Exec();
}
public void Prune(Action<string> outputHandler) public void Prune(Action<string> outputHandler)
{ {
new PruneCmd(_repo, outputHandler).Exec(); new SubCmd(_repo, "lfs prune", outputHandler).Exec();
}
public List<Models.LFSLock> Locks()
{
var locks = new List<Models.LFSLock>();
var cmd = new SubCmd(_repo, "lfs locks", null);
var rs = cmd.ReadToEnd();
if (rs.IsSuccess)
{
var lines = rs.StdOut.Split(new char[] {'\n', '\r'}, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var match = REG_LOCK().Match(line);
if (match.Success)
{
locks.Add(new Models.LFSLock()
{
File = match.Groups[1].Value,
User = match.Groups[2].Value,
ID = long.Parse(match.Groups[3].Value),
});
}
}
}
return locks;
}
public bool Lock(string file)
{
return new SubCmd(_repo, $"lfs lock \"{file}\"", null).Exec();
}
public bool Unlock(string file, bool force)
{
var opt = force ? "-f" : "";
return new SubCmd(_repo, $"lfs unlock {opt} \"{file}\"", null).Exec();
}
public bool Unlock(long id, bool force)
{
var opt = force ? "-f" : "";
return new SubCmd(_repo, $"lfs unlock {opt} --id={id}", null).Exec();
} }
private readonly string _repo; private readonly string _repo;

View file

@ -6,57 +6,63 @@ namespace SourceGit.Commands
{ {
public static class MergeTool public static class MergeTool
{ {
public static bool OpenForMerge(string repo, string tool, string mergeCmd, string file) public static bool OpenForMerge(string repo, int toolType, string toolPath, string file)
{ {
if (string.IsNullOrWhiteSpace(tool) || string.IsNullOrWhiteSpace(mergeCmd))
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, "Invalid external merge tool settings!");
});
return false;
}
if (!File.Exists(tool))
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, $"Can NOT found external merge tool in '{tool}'!");
});
return false;
}
var cmd = new Command(); var cmd = new Command();
cmd.WorkingDirectory = repo; cmd.WorkingDirectory = repo;
cmd.RaiseError = false; cmd.Context = repo;
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{tool}\\\" {mergeCmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit \"{file}\""; cmd.RaiseError = true;
if (toolType == 0)
{
cmd.Args = $"mergetool \"{file}\"";
return cmd.Exec(); return cmd.Exec();
} }
public static bool OpenForDiff(string repo, string tool, string diffCmd, Models.DiffOption option) if (!File.Exists(toolPath))
{ {
if (string.IsNullOrWhiteSpace(tool) || string.IsNullOrWhiteSpace(diffCmd)) Dispatcher.UIThread.Post(() => App.RaiseException(repo, $"Can NOT found external merge tool in '{toolPath}'!"));
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, "Invalid external merge tool settings!");
});
return false; return false;
} }
if (!File.Exists(tool)) var supported = Models.ExternalMerger.Supported.Find(x => x.Type == toolType);
if (supported == null)
{ {
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Post(() => App.RaiseException(repo, "Invalid merge tool in preference setting!"));
{
App.RaiseException(repo, $"Can NOT found external merge tool in '{tool}'!");
});
return false; return false;
} }
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.Cmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit \"{file}\"";
return cmd.Exec();
}
public static bool OpenForDiff(string repo, int toolType, string toolPath, Models.DiffOption option)
{
var cmd = new Command(); var cmd = new Command();
cmd.WorkingDirectory = repo; cmd.WorkingDirectory = repo;
cmd.RaiseError = false; cmd.Context = repo;
cmd.Args = $"-c difftool.sourcegit.cmd=\"\\\"{tool}\\\" {diffCmd}\" difftool --tool=sourcegit --no-prompt {option}"; cmd.RaiseError = true;
if (toolType == 0)
{
cmd.Args = $"difftool -g --no-prompt {option}";
return cmd.Exec();
}
if (!File.Exists(toolPath))
{
Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, $"Can NOT found external diff tool in '{toolPath}'!"));
return false;
}
var supported = Models.ExternalMerger.Supported.Find(x => x.Type == toolType);
if (supported == null)
{
Dispatcher.UIThread.Post(() => App.RaiseException(repo, "Invalid merge tool in preference setting!"));
return false;
}
cmd.Args = $"-c difftool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.DiffCmd}\" difftool --tool=sourcegit --no-prompt {option}";
return cmd.Exec(); return cmd.Exec();
} }
} }

View file

@ -1,4 +1,6 @@
namespace SourceGit.Commands using System.Diagnostics;
namespace SourceGit.Commands
{ {
public class Rebase : Command public class Rebase : Command
{ {
@ -12,4 +14,17 @@
Args += basedOn; Args += basedOn;
} }
} }
public class InteractiveRebase : Command
{
public InteractiveRebase(string repo, string basedOn)
{
var exec = Process.GetCurrentProcess().MainModule.FileName;
var editor = $"\\\"{exec}\\\" --rebase-editor";
WorkingDirectory = repo;
Context = repo;
Args = $"-c core.editor=\"{editor}\" -c sequence.editor=\"{editor}\" -c rebase.abbreviateCommands=true rebase -i --autosquash {basedOn}";
}
}
} }

View file

@ -0,0 +1,19 @@
using Avalonia.Data.Converters;
namespace SourceGit.Converters
{
public static class DoubleConverters
{
public static readonly FuncValueConverter<double, double> Increase =
new FuncValueConverter<double, double>(v => v + 1.0);
public static readonly FuncValueConverter<double, double> Decrease =
new FuncValueConverter<double, double>(v => v - 1.0);
public static readonly FuncValueConverter<double, string> ToPercentage =
new FuncValueConverter<double, string>(v => (v * 100).ToString("F3") + "%");
public static readonly FuncValueConverter<double, string> OneMinusToPercentage =
new FuncValueConverter<double, string>(v => ((1.0 - v) * 100).ToString("F3") + "%");
}
}

View file

@ -1,13 +0,0 @@
using Avalonia.Data.Converters;
namespace SourceGit.Converters
{
public static class FontSizeModifyConverters
{
public static readonly FuncValueConverter<double, double> Increase =
new FuncValueConverter<double, double>(v => v + 1.0);
public static readonly FuncValueConverter<double, double> Decrease =
new FuncValueConverter<double, double>(v => v - 1.0);
}
}

View file

@ -18,5 +18,11 @@ namespace SourceGit.Converters
public static readonly FuncValueConverter<int, bool> IsNotOne = public static readonly FuncValueConverter<int, bool> IsNotOne =
new FuncValueConverter<int, bool>(v => v != 1); new FuncValueConverter<int, bool>(v => v != 1);
public static readonly FuncValueConverter<int, bool> IsSubjectLengthBad =
new FuncValueConverter<int, bool>(v => v > ViewModels.Preference.Instance.SubjectGuideLength);
public static readonly FuncValueConverter<int, bool> IsSubjectLengthGood =
new FuncValueConverter<int, bool>(v => v <= ViewModels.Preference.Instance.SubjectGuideLength);
} }
} }

View file

@ -0,0 +1,51 @@
using Avalonia.Data.Converters;
using Avalonia.Media;
namespace SourceGit.Converters
{
public static class InteractiveRebaseActionConverters
{
public static readonly FuncValueConverter<Models.InteractiveRebaseAction, IBrush> ToIconBrush =
new FuncValueConverter<Models.InteractiveRebaseAction, IBrush>(v =>
{
switch (v)
{
case Models.InteractiveRebaseAction.Pick:
return Brushes.Green;
case Models.InteractiveRebaseAction.Edit:
return Brushes.Orange;
case Models.InteractiveRebaseAction.Reword:
return Brushes.Orange;
case Models.InteractiveRebaseAction.Squash:
return Brushes.LightGray;
case Models.InteractiveRebaseAction.Fixup:
return Brushes.LightGray;
default:
return Brushes.Red;
}
});
public static readonly FuncValueConverter<Models.InteractiveRebaseAction, string> ToName =
new FuncValueConverter<Models.InteractiveRebaseAction, string>(v =>
{
switch (v)
{
case Models.InteractiveRebaseAction.Pick:
return "Pick";
case Models.InteractiveRebaseAction.Edit:
return "Edit";
case Models.InteractiveRebaseAction.Reword:
return "Reword";
case Models.InteractiveRebaseAction.Squash:
return "Squash";
case Models.InteractiveRebaseAction.Fixup:
return "Fixup";
default:
return "Drop";
}
});
public static readonly FuncValueConverter<Models.InteractiveRebaseAction, bool> CanEditMessage =
new FuncValueConverter<Models.InteractiveRebaseAction, bool>(v => v == Models.InteractiveRebaseAction.Reword || v == Models.InteractiveRebaseAction.Squash);
}
}

View file

@ -81,6 +81,16 @@ namespace SourceGit.Converters
return true; return true;
}); });
public static readonly FuncValueConverter<string, string> TrimRefsPrefix =
new FuncValueConverter<string, string>(v =>
{
if (v.StartsWith("refs/heads/", StringComparison.Ordinal))
return v.Substring(11);
if (v.StartsWith("refs/remotes/", StringComparison.Ordinal))
return v.Substring(13);
return v;
});
[GeneratedRegex(@"^[\s\w]*(\d+)\.(\d+)[\.\-](\d+).*$")] [GeneratedRegex(@"^[\s\w]*(\d+)\.(\d+)[\.\-](\d+).*$")]
private static partial Regex REG_GIT_VERSION(); private static partial Regex REG_GIT_VERSION();

View file

@ -2,8 +2,8 @@
{ {
public enum DealWithLocalChanges public enum DealWithLocalChanges
{ {
DoNothing,
StashAndReaply, StashAndReaply,
Discard, Discard,
DoNothing,
} }
} }

View file

@ -587,16 +587,10 @@ namespace SourceGit.Models
public string New { get; set; } = string.Empty; public string New { get; set; } = string.Empty;
} }
public class SubmoduleRevision
{
public Commit Commit { get; set; } = null;
public string FullMessage { get; set; } = string.Empty;
}
public class SubmoduleDiff public class SubmoduleDiff
{ {
public SubmoduleRevision Old { get; set; } = null; public RevisionSubmodule Old { get; set; } = null;
public SubmoduleRevision New { get; set; } = null; public RevisionSubmodule New { get; set; } = null;
} }
public class DiffResult public class DiffResult

View file

@ -32,7 +32,7 @@ namespace SourceGit.Models
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
Supported = new List<ExternalMerger>() { Supported = new List<ExternalMerger>() {
new ExternalMerger(0, "custom_diff", "Custom", "", "", ""), new ExternalMerger(0, "git", "Use Git Settings", "", "", ""),
new ExternalMerger(1, "vscode", "Visual Studio Code", "Code.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(1, "vscode", "Visual Studio Code", "Code.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(2, "vscode_insiders", "Visual Studio Code - Insiders", "Code - Insiders.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(2, "vscode_insiders", "Visual Studio Code - Insiders", "Code - Insiders.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(3, "vs", "Visual Studio", "vsDiffMerge.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" /m", "\"$LOCAL\" \"$REMOTE\""), new ExternalMerger(3, "vs", "Visual Studio", "vsDiffMerge.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" /m", "\"$LOCAL\" \"$REMOTE\""),
@ -41,36 +41,39 @@ namespace SourceGit.Models
new ExternalMerger(6, "beyond_compare", "Beyond Compare", "BComp.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), new ExternalMerger(6, "beyond_compare", "Beyond Compare", "BComp.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(7, "win_merge", "WinMerge", "WinMergeU.exe", "-u -e \"$REMOTE\" \"$LOCAL\" \"$MERGED\"", "-u -e \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(7, "win_merge", "WinMerge", "WinMergeU.exe", "-u -e \"$REMOTE\" \"$LOCAL\" \"$MERGED\"", "-u -e \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(8, "codium", "VSCodium", "VSCodium.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(8, "codium", "VSCodium", "VSCodium.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(9, "p4merge", "P4Merge", "p4merge.exe", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""),
}; };
} }
else if (OperatingSystem.IsMacOS()) else if (OperatingSystem.IsMacOS())
{ {
Supported = new List<ExternalMerger>() { Supported = new List<ExternalMerger>() {
new ExternalMerger(0, "custom_diff", "Custom", "", "", ""), new ExternalMerger(0, "git", "Use Git Settings", "", "", ""),
new ExternalMerger(1, "xcode", "FileMerge", "/usr/bin/opendiff", "\"$BASE\" \"$LOCAL\" \"$REMOTE\" -ancestor \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), new ExternalMerger(1, "xcode", "FileMerge", "/usr/bin/opendiff", "\"$BASE\" \"$LOCAL\" \"$REMOTE\" -ancestor \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(2, "vscode", "Visual Studio Code", "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(2, "vscode", "Visual Studio Code", "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(3, "vscode_insiders", "Visual Studio Code - Insiders", "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(3, "vscode_insiders", "Visual Studio Code - Insiders", "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(4, "kdiff3", "KDiff3", "/Applications/kdiff3.app/Contents/MacOS/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), new ExternalMerger(4, "kdiff3", "KDiff3", "/Applications/kdiff3.app/Contents/MacOS/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(5, "beyond_compare", "Beyond Compare", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), new ExternalMerger(5, "beyond_compare", "Beyond Compare", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(6, "codium", "VSCodium", "/Applications/VSCodium.app/Contents/Resources/app/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(6, "codium", "VSCodium", "/Applications/VSCodium.app/Contents/Resources/app/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(7, "p4merge", "P4Merge", "/Applications/p4merge.app/Contents/Resources/launchp4merge", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""),
}; };
} }
else if (OperatingSystem.IsLinux()) else if (OperatingSystem.IsLinux())
{ {
Supported = new List<ExternalMerger>() { Supported = new List<ExternalMerger>() {
new ExternalMerger(0, "custom_diff", "Custom", "", "", ""), new ExternalMerger(0, "git", "Use Git Settings", "", "", ""),
new ExternalMerger(1, "vscode", "Visual Studio Code", "/usr/share/code/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(1, "vscode", "Visual Studio Code", "/usr/share/code/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(2, "vscode_insiders", "Visual Studio Code - Insiders", "/usr/share/code-insiders/code-insiders", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(2, "vscode_insiders", "Visual Studio Code - Insiders", "/usr/share/code-insiders/code-insiders", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(3, "kdiff3", "KDiff3", "/usr/bin/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), new ExternalMerger(3, "kdiff3", "KDiff3", "/usr/bin/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(4, "beyond_compare", "Beyond Compare", "/usr/bin/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), new ExternalMerger(4, "beyond_compare", "Beyond Compare", "/usr/bin/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(5, "meld", "Meld", "/usr/bin/meld", "\"$LOCAL\" \"$BASE\" \"$REMOTE\" -output \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), new ExternalMerger(5, "meld", "Meld", "/usr/bin/meld", "\"$LOCAL\" \"$BASE\" \"$REMOTE\" -output \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(6, "codium", "VSCodium", "/usr/share/codium/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMerger(6, "codium", "VSCodium", "/usr/share/codium/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(7, "p4merge", "P4Merge", "/usr/local/bin/p4merge", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""),
}; };
} }
else else
{ {
Supported = new List<ExternalMerger>() { Supported = new List<ExternalMerger>() {
new ExternalMerger(0, "custom_diff", "Custom", "", "", ""), new ExternalMerger(0, "git", "Use Git Settings", "", "", ""),
}; };
} }
} }

View file

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
namespace SourceGit.Models
{
public enum InteractiveRebaseAction
{
Pick,
Edit,
Reword,
Squash,
Fixup,
Drop,
}
public class InteractiveRebaseJob
{
public string SHA { get; set; } = string.Empty;
public InteractiveRebaseAction Action { get; set; } = InteractiveRebaseAction.Pick;
public string Message { get; set; } = string.Empty;
}
public static class InteractiveRebaseEditor
{
public static int Process(string file)
{
try
{
var filename = Path.GetFileName(file);
if (filename.Equals("git-rebase-todo", StringComparison.OrdinalIgnoreCase))
{
var dirInfo = new DirectoryInfo(Path.GetDirectoryName(file));
if (!dirInfo.Exists || !dirInfo.Name.Equals("rebase-merge", StringComparison.Ordinal))
return -1;
var jobsFile = Path.Combine(dirInfo.Parent.FullName, "sourcegit_rebase_jobs.json");
if (!File.Exists(jobsFile))
return -1;
var jobs = JsonSerializer.Deserialize(File.ReadAllText(jobsFile), JsonCodeGen.Default.ListInteractiveRebaseJob);
var lines = new List<string>();
foreach (var job in jobs)
{
switch (job.Action)
{
case InteractiveRebaseAction.Pick:
lines.Add($"p {job.SHA}");
break;
case InteractiveRebaseAction.Edit:
lines.Add($"e {job.SHA}");
break;
case InteractiveRebaseAction.Reword:
lines.Add($"r {job.SHA}");
break;
case InteractiveRebaseAction.Squash:
lines.Add($"s {job.SHA}");
break;
case InteractiveRebaseAction.Fixup:
lines.Add($"f {job.SHA}");
break;
default:
lines.Add($"d {job.SHA}");
break;
}
}
File.WriteAllLines(file, lines);
}
else if (filename.Equals("COMMIT_EDITMSG", StringComparison.OrdinalIgnoreCase))
{
var jobsFile = Path.Combine(Path.GetDirectoryName(file), "sourcegit_rebase_jobs.json");
if (!File.Exists(jobsFile))
return 0;
var jobs = JsonSerializer.Deserialize(File.ReadAllText(jobsFile), JsonCodeGen.Default.ListInteractiveRebaseJob);
var doneFile = Path.Combine(Path.GetDirectoryName(file), "rebase-merge", "done");
if (!File.Exists(doneFile))
return -1;
var done = File.ReadAllText(doneFile).Split(new char[] {'\n', '\r'}, StringSplitOptions.RemoveEmptyEntries);
if (done.Length > jobs.Count)
return -1;
var job = jobs[done.Length - 1];
File.WriteAllText(file, job.Message);
}
return 0;
}
catch
{
return -1;
}
}
}
}

9
src/Models/LFSLock.cs Normal file
View file

@ -0,0 +1,9 @@
namespace SourceGit.Models
{
public class LFSLock
{
public string File { get; set; } = string.Empty;
public string User { get; set; } = string.Empty;
public long ID { get; set; } = 0;
}
}

View file

@ -1,16 +1,20 @@
using System.Text.RegularExpressions; using System;
using System.Text.RegularExpressions;
namespace SourceGit.Models namespace SourceGit.Models
{ {
public partial class Remote public partial class Remote
{ {
[GeneratedRegex(@"^http[s]?://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/[\w\-/]+/[\w\-\.]+(\.git)?$")] [GeneratedRegex(@"^http[s]?://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/[\w\-/~]+/[\w\-\.]+(\.git)?$")]
private static partial Regex REG_HTTPS(); private static partial Regex REG_HTTPS();
[GeneratedRegex(@"^[\w\-]+@[\w\.\-]+(\:[0-9]+)?:[\w\-/]+/[\w\-\.]+(\.git)?$")] [GeneratedRegex(@"^[\w\-]+@[\w\.\-]+(\:[0-9]+)?:[\w\-/~]+/[\w\-\.]+(\.git)?$")]
private static partial Regex REG_SSH1(); private static partial Regex REG_SSH1();
[GeneratedRegex(@"^ssh://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/[\w\-/]+/[\w\-\.]+(\.git)?$")] [GeneratedRegex(@"^ssh://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/[\w\-/~]+/[\w\-\.]+(\.git)?$")]
private static partial Regex REG_SSH2(); private static partial Regex REG_SSH2();
[GeneratedRegex(@"^git@([\w\.\-]+):([\w\-/~]+/[\w\-\.]+)\.git$")]
private static partial Regex REG_TO_VISIT_URL_CAPTURE();
private static readonly Regex[] URL_FORMATS = [ private static readonly Regex[] URL_FORMATS = [
REG_HTTPS(), REG_HTTPS(),
REG_SSH1(), REG_SSH1(),
@ -43,5 +47,29 @@ namespace SourceGit.Models
} }
return false; return false;
} }
public bool TryGetVisitURL(out string url)
{
url = null;
if (URL.StartsWith("http", StringComparison.Ordinal))
{
if (URL.EndsWith(".git"))
url = URL.Substring(0, URL.Length - 4);
else
url = URL;
return true;
}
var match = REG_TO_VISIT_URL_CAPTURE().Match(URL);
if (match.Success)
{
url = $"https://{match.Groups[1].Value}/{match.Groups[2].Value}";
return true;
}
return false;
}
} }
} }

View file

@ -25,6 +25,7 @@ namespace SourceGit.Models
public class RevisionSubmodule public class RevisionSubmodule
{ {
public string SHA { get; set; } public Commit Commit { get; set; } = null;
public string FullMessage { get; set; } = string.Empty;
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View file

@ -12,12 +12,10 @@
<StreamGeometry x:Key="Icons.Error">M576 832C576 867 547 896 512 896 477 896 448 867 448 832 448 797 477 768 512 768 547 768 576 797 576 832ZM512 256C477 256 448 285 448 320L448 640C448 675 477 704 512 704 547 704 576 675 576 640L576 320C576 285 547 256 512 256ZM1024 896C1024 967 967 1024 896 1024L128 1024C57 1024 0 967 0 896 0 875 5 855 14 837L14 837 398 69 398 69C420 28 462 0 512 0 562 0 604 28 626 69L1008 835C1018 853 1024 874 1024 896ZM960 896C960 885 957 875 952 865L952 864 951 863 569 98C557 77 536 64 512 64 488 64 466 77 455 99L452 105 92 825 93 825 71 867C66 876 64 886 64 896 64 931 93 960 128 960L896 960C931 960 960 931 960 896Z</StreamGeometry> <StreamGeometry x:Key="Icons.Error">M576 832C576 867 547 896 512 896 477 896 448 867 448 832 448 797 477 768 512 768 547 768 576 797 576 832ZM512 256C477 256 448 285 448 320L448 640C448 675 477 704 512 704 547 704 576 675 576 640L576 320C576 285 547 256 512 256ZM1024 896C1024 967 967 1024 896 1024L128 1024C57 1024 0 967 0 896 0 875 5 855 14 837L14 837 398 69 398 69C420 28 462 0 512 0 562 0 604 28 626 69L1008 835C1018 853 1024 874 1024 896ZM960 896C960 885 957 875 952 865L952 864 951 863 569 98C557 77 536 64 512 64 488 64 466 77 455 99L452 105 92 825 93 825 71 867C66 876 64 886 64 896 64 931 93 960 128 960L896 960C931 960 960 931 960 896Z</StreamGeometry>
<StreamGeometry x:Key="Icons.Conflict">M608 0q48 0 88 23t63 63 23 87v70h55q35 0 67 14t57 38 38 57 14 67V831q0 34-14 66t-38 57-57 38-67 13H426q-34 0-66-13t-57-38-38-57-14-66v-70h-56q-34 0-66-14t-57-38-38-57-13-67V174q0-47 23-87T109 23 196 0h412m175 244H426q-46 0-86 22T278 328t-26 85v348H608q47 0 86-22t63-62 25-85l1-348m-269 318q18 0 31 13t13 31-13 31-31 13-31-13-13-31 13-31 31-13m0-212q13 0 22 9t11 22v125q0 14-9 23t-22 10-23-7-11-22l-1-126q0-13 10-23t23-10z</StreamGeometry> <StreamGeometry x:Key="Icons.Conflict">M608 0q48 0 88 23t63 63 23 87v70h55q35 0 67 14t57 38 38 57 14 67V831q0 34-14 66t-38 57-57 38-67 13H426q-34 0-66-13t-57-38-38-57-14-66v-70h-56q-34 0-66-14t-57-38-38-57-13-67V174q0-47 23-87T109 23 196 0h412m175 244H426q-46 0-86 22T278 328t-26 85v348H608q47 0 86-22t63-62 25-85l1-348m-269 318q18 0 31 13t13 31-13 31-31 13-31-13-13-31 13-31 31-13m0-212q13 0 22 9t11 22v125q0 14-9 23t-22 10-23-7-11-22l-1-126q0-13 10-23t23-10z</StreamGeometry>
<StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry> <StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry>
<StreamGeometry x:Key="Icons.Settings1">M716.3 383.1c0 38.4-6.5 76-19.4 111.8l-10.7 29.7 229.6 229.5c44.5 44.6 44.5 117.1 0 161.6a113.6 113.6 0 01-80.8 33.5a113.6 113.6 0 01-80.8-33.5L529 694l-32 13a331.6 331.6 0 01-111.9 19.4A333.5 333.5 0 0150 383.1c0-39 6.8-77.2 20-113.6L285 482l194-195-214-210A331 331 0 01383.1 50A333.5 333.5 0 01716.3 383.1zM231.6 31.6l-22.9 9.9a22.2 22.2 0 00-5.9 4.2a19.5 19.5 0 000 27.5l215 215.2L288.4 417.8 77.8 207.1a26 26 0 00-17.2-7.1a22.8 22.8 0 00-21.5 15a400.5 400.5 0 00-7.5 16.6A381.6 381.6 0 000 384c0 211.7 172.2 384 384 384c44.3 0 87.6-7.5 129-22.3L743.1 975.8A163.5 163.5 0 00859.5 1024c43.9 0 85.3-17.1 116.4-48.2a164.8 164.8 0 000-233L745.5 513C760.5 471.5 768 428 768 384C768 172 596 0 384 0c-53 0-104 10.5-152.5 31.5z</StreamGeometry> <StreamGeometry x:Key="Icons.Settings">M928 500a21 21 0 00-19-20L858 472a11 11 0 01-9-9c-1-6-2-13-3-19a11 11 0 015-12l46-25a21 21 0 0010-26l-8-22a21 21 0 00-24-13l-51 10a11 11 0 01-12-6c-3-6-6-11-10-17a11 11 0 011-13l34-39a21 21 0 001-28l-15-18a20 20 0 00-27-4l-45 27a11 11 0 01-13-1c-5-4-10-9-15-12a11 11 0 01-3-12l19-49a21 21 0 00-9-26l-20-12a21 21 0 00-27 6L650 193a9 9 0 01-11 3c-1-1-12-5-20-7a11 11 0 01-7-10l1-52a21 21 0 00-17-22l-23-4a21 21 0 00-24 14L532 164a11 11 0 01-11 7h-20a11 11 0 01-11-7l-17-49a21 21 0 00-24-15l-23 4a21 21 0 00-17 22l1 52a11 11 0 01-8 11c-5 2-15 6-19 7c-4 1-8 0-12-4l-33-40A21 21 0 00313 146l-20 12A21 21 0 00285 184l19 49a11 11 0 01-3 12c-5 4-10 8-15 12a11 11 0 01-13 1L228 231a21 21 0 00-27 4L186 253a21 21 0 001 28L221 320a11 11 0 011 13c-3 5-7 11-10 17a11 11 0 01-12 6l-51-10a21 21 0 00-24 13l-8 22a21 21 0 0010 26l46 25a11 11 0 015 12l0 3c-1 6-2 11-3 16a11 11 0 01-9 9l-51 8A21 21 0 0096 500v23A21 21 0 00114 544l51 8a11 11 0 019 9c1 6 2 13 3 19a11 11 0 01-5 12l-46 25a21 21 0 00-10 26l8 22a21 21 0 0024 13l51-10a11 11 0 0112 6c3 6 6 11 10 17a11 11 0 01-1 13l-34 39a21 21 0 00-1 28l15 18a20 20 0 0027 4l45-27a11 11 0 0113 1c5 4 10 9 15 12a11 11 0 013 12l-19 49a21 21 0 009 26l20 12a21 21 0 0027-6L374 832c3-3 7-5 10-4c7 3 12 5 20 7a11 11 0 018 10l-1 52a21 21 0 0017 22l23 4a21 21 0 0024-14l17-50a11 11 0 0111-7h20a11 11 0 0111 7l17 49a21 21 0 0020 15a19 19 0 004 0l23-4a21 21 0 0017-22l-1-52a11 11 0 018-10c8-3 13-5 18-7l1 0c6-2 9 0 11 3l34 41A21 21 0 00710 878l20-12a21 21 0 009-26l-18-49a11 11 0 013-12c5-4 10-8 15-12a11 11 0 0113-1l45 27a21 21 0 0027-4l15-18a21 21 0 00-1-28l-34-39a11 11 0 01-1-13c3-5 7-11 10-17a11 11 0 0112-6l51 10a21 21 0 0024-13l8-22a21 21 0 00-10-26l-46-25a11 11 0 01-5-12l0-3c1-6 2-11 3-16a11 11 0 019-9l51-8a21 21 0 0018-21v-23zm-565 188a32 32 0 01-51 5a270 270 0 011-363a32 32 0 0151 6l91 161a32 32 0 010 31zM512 782a270 270 0 01-57-6a32 32 0 01-20-47l92-160a32 32 0 0127-16h184a32 32 0 0130 41c-35 109-137 188-257 188zm15-328L436 294a32 32 0 0121-47a268 268 0 0155-6c120 0 222 79 257 188a32 32 0 01-30 41h-184a32 32 0 01-28-16z</StreamGeometry>
<StreamGeometry x:Key="Icons.Settings2">M928 500a21 21 0 00-19-20L858 472a11 11 0 01-9-9c-1-6-2-13-3-19a11 11 0 015-12l46-25a21 21 0 0010-26l-8-22a21 21 0 00-24-13l-51 10a11 11 0 01-12-6c-3-6-6-11-10-17a11 11 0 011-13l34-39a21 21 0 001-28l-15-18a20 20 0 00-27-4l-45 27a11 11 0 01-13-1c-5-4-10-9-15-12a11 11 0 01-3-12l19-49a21 21 0 00-9-26l-20-12a21 21 0 00-27 6L650 193a9 9 0 01-11 3c-1-1-12-5-20-7a11 11 0 01-7-10l1-52a21 21 0 00-17-22l-23-4a21 21 0 00-24 14L532 164a11 11 0 01-11 7h-20a11 11 0 01-11-7l-17-49a21 21 0 00-24-15l-23 4a21 21 0 00-17 22l1 52a11 11 0 01-8 11c-5 2-15 6-19 7c-4 1-8 0-12-4l-33-40A21 21 0 00313 146l-20 12A21 21 0 00285 184l19 49a11 11 0 01-3 12c-5 4-10 8-15 12a11 11 0 01-13 1L228 231a21 21 0 00-27 4L186 253a21 21 0 001 28L221 320a11 11 0 011 13c-3 5-7 11-10 17a11 11 0 01-12 6l-51-10a21 21 0 00-24 13l-8 22a21 21 0 0010 26l46 25a11 11 0 015 12l0 3c-1 6-2 11-3 16a11 11 0 01-9 9l-51 8A21 21 0 0096 500v23A21 21 0 00114 544l51 8a11 11 0 019 9c1 6 2 13 3 19a11 11 0 01-5 12l-46 25a21 21 0 00-10 26l8 22a21 21 0 0024 13l51-10a11 11 0 0112 6c3 6 6 11 10 17a11 11 0 01-1 13l-34 39a21 21 0 00-1 28l15 18a20 20 0 0027 4l45-27a11 11 0 0113 1c5 4 10 9 15 12a11 11 0 013 12l-19 49a21 21 0 009 26l20 12a21 21 0 0027-6L374 832c3-3 7-5 10-4c7 3 12 5 20 7a11 11 0 018 10l-1 52a21 21 0 0017 22l23 4a21 21 0 0024-14l17-50a11 11 0 0111-7h20a11 11 0 0111 7l17 49a21 21 0 0020 15a19 19 0 004 0l23-4a21 21 0 0017-22l-1-52a11 11 0 018-10c8-3 13-5 18-7l1 0c6-2 9 0 11 3l34 41A21 21 0 00710 878l20-12a21 21 0 009-26l-18-49a11 11 0 013-12c5-4 10-8 15-12a11 11 0 0113-1l45 27a21 21 0 0027-4l15-18a21 21 0 00-1-28l-34-39a11 11 0 01-1-13c3-5 7-11 10-17a11 11 0 0112-6l51 10a21 21 0 0024-13l8-22a21 21 0 00-10-26l-46-25a11 11 0 01-5-12l0-3c1-6 2-11 3-16a11 11 0 019-9l51-8a21 21 0 0018-21v-23zm-565 188a32 32 0 01-51 5a270 270 0 011-363a32 32 0 0151 6l91 161a32 32 0 010 31zM512 782a270 270 0 01-57-6a32 32 0 01-20-47l92-160a32 32 0 0127-16h184a32 32 0 0130 41c-35 109-137 188-257 188zm15-328L436 294a32 32 0 0121-47a268 268 0 0155-6c120 0 222 79 257 188a32 32 0 01-30 41h-184a32 32 0 01-28-16z</StreamGeometry>
<StreamGeometry x:Key="Icons.Info">M512 0C229 0 0 229 0 512s229 512 512 512 512-229 512-512S795 0 512 0zM512 928c-230 0-416-186-416-416S282 96 512 96s416 186 416 416S742 928 512 928zM538 343c47 0 83-38 83-78 0-32-21-61-62-61-55 0-82 45-82 77C475 320 498 343 538 343zM533 729c-8 0-11-10-3-40l43-166c16-61 11-100-22-100-39 0-131 40-211 108l16 27c25-17 68-35 78-35 8 0 7 10 0 36l-38 158c-23 89 1 110 34 110 33 0 118-30 196-110l-19-25C575 717 543 729 533 729z</StreamGeometry> <StreamGeometry x:Key="Icons.Info">M512 0C229 0 0 229 0 512s229 512 512 512 512-229 512-512S795 0 512 0zM512 928c-230 0-416-186-416-416S282 96 512 96s416 186 416 416S742 928 512 928zM538 343c47 0 83-38 83-78 0-32-21-61-62-61-55 0-82 45-82 77C475 320 498 343 538 343zM533 729c-8 0-11-10-3-40l43-166c16-61 11-100-22-100-39 0-131 40-211 108l16 27c25-17 68-35 78-35 8 0 7 10 0 36l-38 158c-23 89 1 110 34 110 33 0 118-30 196-110l-19-25C575 717 543 729 533 729z</StreamGeometry>
<StreamGeometry x:Key="Icons.Search">M702 677 590 565a148 148 0 10-25 27L676 703zm-346-200a115 115 0 11115 115A115 115 0 01355 478z</StreamGeometry> <StreamGeometry x:Key="Icons.Search">M702 677 590 565a148 148 0 10-25 27L676 703zm-346-200a115 115 0 11115 115A115 115 0 01355 478z</StreamGeometry>
<StreamGeometry x:Key="Icons.Clear">M512 57c251 0 455 204 455 455S763 967 512 967 57 763 57 512 261 57 512 57zm181 274c-11-11-29-11-40 0L512 472 371 331c-11-11-29-11-40 0-11 11-11 29 0 40L471 512 331 653c-11 11-11 29 0 40 11 11 29 11 40 0l141-141 141 141c11 11 29 11 40 0 11-11 11-29 0-40L552 512l141-141c11-11 11-29 0-40z</StreamGeometry> <StreamGeometry x:Key="Icons.Clear">M512 57c251 0 455 204 455 455S763 967 512 967 57 763 57 512 261 57 512 57zm181 274c-11-11-29-11-40 0L512 472 371 331c-11-11-29-11-40 0-11 11-11 29 0 40L471 512 331 653c-11 11-11 29 0 40 11 11 29 11 40 0l141-141 141 141c11 11 29 11 40 0 11-11 11-29 0-40L552 512l141-141c11-11 11-29 0-40z</StreamGeometry>
<StreamGeometry x:Key="Icons.Clear2">M899 870l-53-306H864c14 0 26-12 26-26V346c0-14-12-26-26-26H618V138c0-14-12-26-26-26H432c-14 0-26 12-26 26v182H160c-14 0-26 12-26 26v192c0 14 12 26 26 26h18l-53 306c0 2 0 3 0 4c0 14 12 26 26 26h723c2 0 3 0 4 0c14-2 24-16 21-30zM204 390h272V182h72v208h272v104H204V390zm468 440V674c0-4-4-8-8-8h-48c-4 0-8 4-8 8v156H416V674c0-4-4-8-8-8h-48c-4 0-8 4-8 8v156H203l45-260H776l45 260H672z</StreamGeometry>
<StreamGeometry x:Key="Icons.Repositories">M960 146v91C960 318 759 384 512 384S64 318 64 238V146C64 66 265 0 512 0s448 66 448 146zM960 352v206C960 638 759 704 512 704S64 638 64 558V352c96 66 272 97 448 97S864 418 960 352zm0 320v206C960 958 759 1024 512 1024S64 958 64 878V672c96 66 272 97 448 97S864 738 960 672z</StreamGeometry> <StreamGeometry x:Key="Icons.Repositories">M960 146v91C960 318 759 384 512 384S64 318 64 238V146C64 66 265 0 512 0s448 66 448 146zM960 352v206C960 638 759 704 512 704S64 638 64 558V352c96 66 272 97 448 97S864 418 960 352zm0 320v206C960 958 759 1024 512 1024S64 958 64 878V672c96 66 272 97 448 97S864 738 960 672z</StreamGeometry>
<StreamGeometry x:Key="Icons.Bookmark">M800 928l-512 0 0-704 224 0 0 292 113-86 111 86 0-292 128 0 0 640c0 35-29 64-64 64zM625 388l-81 64 0-260 160 0 0 260-79-64zM192 160l0 32c0 18 14 32 32 32l32 0 0 704-32 0c-35 0-64-29-64-64l0-704c0-35 29-64 64-64l576 0c24 0 44 13 55 32l-631 0c-18 0-32 14-32 32z</StreamGeometry> <StreamGeometry x:Key="Icons.Bookmark">M800 928l-512 0 0-704 224 0 0 292 113-86 111 86 0-292 128 0 0 640c0 35-29 64-64 64zM625 388l-81 64 0-260 160 0 0 260-79-64zM192 160l0 32c0 18 14 32 32 32l32 0 0 704-32 0c-35 0-64-29-64-64l0-704c0-35 29-64 64-64l576 0c24 0 44 13 55 32l-631 0c-18 0-32 14-32 32z</StreamGeometry>
<StreamGeometry x:Key="Icons.Folder">M64 864h896V288h-396a64 64 0 01-57-35L460 160H64v704zm-64 32V128a32 32 0 0132-32h448a32 32 0 0129 18L564 224H992a32 32 0 0132 32v640a32 32 0 01-32 32H32a32 32 0 01-32-32z</StreamGeometry> <StreamGeometry x:Key="Icons.Folder">M64 864h896V288h-396a64 64 0 01-57-35L460 160H64v704zm-64 32V128a32 32 0 0132-32h448a32 32 0 0129 18L564 224H992a32 32 0 0132 32v640a32 32 0 01-32 32H32a32 32 0 01-32-32z</StreamGeometry>
@ -61,7 +59,6 @@
<StreamGeometry x:Key="Icons.Tag.Add">M683 537h-144v-142h-142V283H239a44 44 0 00-41 41v171a56 56 0 0014 34l321 321a41 41 0 0058 0l174-174a41 41 0 000-58zm-341-109a41 41 0 110-58a41 41 0 010 58zM649 284V142h-69v142h-142v68h142v142h69v-142h142v-68h-142z</StreamGeometry> <StreamGeometry x:Key="Icons.Tag.Add">M683 537h-144v-142h-142V283H239a44 44 0 00-41 41v171a56 56 0 0014 34l321 321a41 41 0 0058 0l174-174a41 41 0 000-58zm-341-109a41 41 0 110-58a41 41 0 010 58zM649 284V142h-69v142h-142v68h142v142h69v-142h142v-68h-142z</StreamGeometry>
<StreamGeometry x:Key="Icons.Submodule">M557.7 545.3 789.9 402.7c24-15 31.3-46.5 16.4-70.5c-14.8-23.8-46-31.2-70-16.7L506.5 456.6 277.1 315.4c-24.1-14.8-55.6-7.3-70.5 16.8c-14.8 24.1-7.3 55.6 16.8 70.5l231.8 142.6V819.1c0 28.3 22.9 51.2 51.2 51.2c28.3 0 51.2-22.9 51.2-51.2V545.3h.1zM506.5 0l443.4 256v511.9L506.5 1023.9 63.1 767.9v-511.9L506.5 0z</StreamGeometry> <StreamGeometry x:Key="Icons.Submodule">M557.7 545.3 789.9 402.7c24-15 31.3-46.5 16.4-70.5c-14.8-23.8-46-31.2-70-16.7L506.5 456.6 277.1 315.4c-24.1-14.8-55.6-7.3-70.5 16.8c-14.8 24.1-7.3 55.6 16.8 70.5l231.8 142.6V819.1c0 28.3 22.9 51.2 51.2 51.2c28.3 0 51.2-22.9 51.2-51.2V545.3h.1zM506.5 0l443.4 256v511.9L506.5 1023.9 63.1 767.9v-511.9L506.5 0z</StreamGeometry>
<StreamGeometry x:Key="Icons.Submodule.Add">M770 320a41 41 0 00-56-14l-252 153L207 306a41 41 0 10-43 70l255 153 2 296a41 41 0 0082 0l-2-295 255-155a41 41 0 0014-56zM481 935a42 42 0 01-42 0L105 741a42 42 0 01-21-36v-386a42 42 0 0121-36L439 89a42 42 0 0142 0l335 193a42 42 0 0121 36v87h84v-87a126 126 0 00-63-109L523 17a126 126 0 00-126 0L63 210a126 126 0 00-63 109v386a126 126 0 0063 109l335 193a126 126 0 00126 0l94-54-42-72zM1029 700h-126v-125a42 42 0 00-84 0v126h-126a42 42 0 000 84h126v126a42 42 0 1084 0v-126h126a42 42 0 000-84z</StreamGeometry> <StreamGeometry x:Key="Icons.Submodule.Add">M770 320a41 41 0 00-56-14l-252 153L207 306a41 41 0 10-43 70l255 153 2 296a41 41 0 0082 0l-2-295 255-155a41 41 0 0014-56zM481 935a42 42 0 01-42 0L105 741a42 42 0 01-21-36v-386a42 42 0 0121-36L439 89a42 42 0 0142 0l335 193a42 42 0 0121 36v87h84v-87a126 126 0 00-63-109L523 17a126 126 0 00-126 0L63 210a126 126 0 00-63 109v386a126 126 0 0063 109l335 193a126 126 0 00126 0l94-54-42-72zM1029 700h-126v-125a42 42 0 00-84 0v126h-126a42 42 0 000 84h126v126a42 42 0 1084 0v-126h126a42 42 0 000-84z</StreamGeometry>
<StreamGeometry x:Key="Icons.LFS">M170 470l0 84 86 0 0-84-86 0zM86 598l0-172 852 0 0 172-852 0zM256 298l0-84-86 0 0 84 86 0zM86 170l852 0 0 172-852 0 0-172zM170 726l0 84 86 0 0-84-86 0zM86 854l0-172 852 0 0 172-852 0z</StreamGeometry>
<StreamGeometry x:Key="Icons.Waiting">M812 864h-29V654c0-21-11-40-28-52l-133-88 134-89c18-12 28-31 28-52V164h28c18 0 32-14 32-32s-14-32-32-32H212c-18 0-32 14-32 32s14 32 32 32h30v210c0 21 11 40 28 52l133 88-134 89c-18 12-28 31-28 52V864H212c-18 0-32 14-32 32s14 32 32 32h600c18 0 32-14 32-32s-14-32-32-32zM441 566c18-12 28-31 28-52s-11-40-28-52L306 373V164h414v209l-136 90c-18 12-28 31-28 52 0 21 11 40 28 52l135 89V695c-9-7-20-13-32-19-30-15-93-41-176-41-63 0-125 14-175 38-12 6-22 12-31 18v-36l136-90z</StreamGeometry> <StreamGeometry x:Key="Icons.Waiting">M812 864h-29V654c0-21-11-40-28-52l-133-88 134-89c18-12 28-31 28-52V164h28c18 0 32-14 32-32s-14-32-32-32H212c-18 0-32 14-32 32s14 32 32 32h30v210c0 21 11 40 28 52l133 88-134 89c-18 12-28 31-28 52V864H212c-18 0-32 14-32 32s14 32 32 32h600c18 0 32-14 32-32s-14-32-32-32zM441 566c18-12 28-31 28-52s-11-40-28-52L306 373V164h414v209l-136 90c-18 12-28 31-28 52 0 21 11 40 28 52l135 89V695c-9-7-20-13-32-19-30-15-93-41-176-41-63 0-125 14-175 38-12 6-22 12-31 18v-36l136-90z</StreamGeometry>
<StreamGeometry x:Key="Icons.Loading">M512 0C233 0 7 223 0 500C6 258 190 64 416 64c230 0 416 200 416 448c0 53 43 96 96 96s96-43 96-96c0-283-229-512-512-512zm0 1023c279 0 505-223 512-500c-6 242-190 436-416 436c-230 0-416-200-416-448c0-53-43-96-96-96s-96 43-96 96c0 283 229 512 512 512z</StreamGeometry> <StreamGeometry x:Key="Icons.Loading">M512 0C233 0 7 223 0 500C6 258 190 64 416 64c230 0 416 200 416 448c0 53 43 96 96 96s96-43 96-96c0-283-229-512-512-512zm0 1023c279 0 505-223 512-500c-6 242-190 436-416 436c-230 0-416-200-416-448c0-53-43-96-96-96s-96 43-96 96c0 283 229 512 512 512z</StreamGeometry>
<StreamGeometry x:Key="Icons.Detail">M888.8 0H135.2c-32.3 0-58.9 26.1-58.9 58.9v906.2c0 32.3 26.1 58.9 58.9 58.9h753.2c32.3 0 58.9-26.1 58.9-58.9v-906.2c.5-32.8-26.1-58.9-58.4-58.9zm-164.9 176.6c30.7 0 55.8 25.1 55.8 55.8s-25.1 55.8-55.8 55.8s-55.8-25.1-55.8-55.8s24.6-55.8 55.8-55.8zm-212 0c30.7 0 55.8 25.1 55.8 55.8S542.7 288.3 512 288.3s-55.8-25.1-55.8-55.8S481.3 176.6 512 176.6zm-212 0c30.7 0 55.8 25.1 55.8 55.8s-25.1 55.8-55.8 55.8s-55.8-25.1-55.8-55.8s25.1-55.8 55.8-55.8zm208.9 606.2H285.2c-24.6 0-44-20-44-44c0-24.6 20-44 44-44h223.7c24.6 0 44 20 44 44c0 24.1-19.5 44-44 44zm229.9-212H285.2c-24.6 0-44-20-44-44c0-24.6 20-44 44-44h453.1c24.6 0 44 20 44 44c.5 24.1-19.5 44-43.5 44z</StreamGeometry> <StreamGeometry x:Key="Icons.Detail">M888.8 0H135.2c-32.3 0-58.9 26.1-58.9 58.9v906.2c0 32.3 26.1 58.9 58.9 58.9h753.2c32.3 0 58.9-26.1 58.9-58.9v-906.2c.5-32.8-26.1-58.9-58.4-58.9zm-164.9 176.6c30.7 0 55.8 25.1 55.8 55.8s-25.1 55.8-55.8 55.8s-55.8-25.1-55.8-55.8s24.6-55.8 55.8-55.8zm-212 0c30.7 0 55.8 25.1 55.8 55.8S542.7 288.3 512 288.3s-55.8-25.1-55.8-55.8S481.3 176.6 512 176.6zm-212 0c30.7 0 55.8 25.1 55.8 55.8s-25.1 55.8-55.8 55.8s-55.8-25.1-55.8-55.8s25.1-55.8 55.8-55.8zm208.9 606.2H285.2c-24.6 0-44-20-44-44c0-24.6 20-44 44-44h223.7c24.6 0 44 20 44 44c0 24.1-19.5 44-44 44zm229.9-212H285.2c-24.6 0-44-20-44-44c0-24.6 20-44 44-44h453.1c24.6 0 44 20 44 44c.5 24.1-19.5 44-43.5 44z</StreamGeometry>
@ -90,7 +87,7 @@
<StreamGeometry x:Key="Icons.Target">M765 118 629 239l-16 137-186 160 54 59 183-168 144 4 136-129 47-43-175-12L827 67zM489 404c-66 0-124 55-124 125s54 121 124 121c66 0 120-55 120-121H489l23-121c-8-4-16-4-23-4zM695 525c0 114-93 207-206 207s-206-94-206-207 93-207 206-207c16 0 27 0 43 4l43-207c-27-4-54-8-85-8-229 0-416 188-416 419s187 419 416 419c225 0 408-180 416-403v-12l-210-4z</StreamGeometry> <StreamGeometry x:Key="Icons.Target">M765 118 629 239l-16 137-186 160 54 59 183-168 144 4 136-129 47-43-175-12L827 67zM489 404c-66 0-124 55-124 125s54 121 124 121c66 0 120-55 120-121H489l23-121c-8-4-16-4-23-4zM695 525c0 114-93 207-206 207s-206-94-206-207 93-207 206-207c16 0 27 0 43 4l43-207c-27-4-54-8-85-8-229 0-416 188-416 419s187 419 416 419c225 0 408-180 416-403v-12l-210-4z</StreamGeometry>
<StreamGeometry x:Key="Icons.Incoming">M973 358a51 51 0 0151 51v563a51 51 0 01-51 51H51a51 51 0 01-51-51V410a51 51 0 0151-51h256a51 51 0 110 102H102v461h819V461h-205a51 51 0 110-102h256zM51 102a51 51 0 110-102h256c141 0 256 115 256 256v388l66-66a51 51 0 1172 72l-154 154a51 51 0 01-72 0l-154-154a51 51 0 1172-72L461 644V256c0-85-69-154-154-154H51z</StreamGeometry> <StreamGeometry x:Key="Icons.Incoming">M973 358a51 51 0 0151 51v563a51 51 0 01-51 51H51a51 51 0 01-51-51V410a51 51 0 0151-51h256a51 51 0 110 102H102v461h819V461h-205a51 51 0 110-102h256zM51 102a51 51 0 110-102h256c141 0 256 115 256 256v388l66-66a51 51 0 1172 72l-154 154a51 51 0 01-72 0l-154-154a51 51 0 1172-72L461 644V256c0-85-69-154-154-154H51z</StreamGeometry>
<StreamGeometry x:Key="Icons.Local">M976 0h-928A48 48 0 000 48v652a48 48 0 0048 48h416V928H200a48 48 0 000 96h624a48 48 0 000-96H560v-180h416a48 48 0 0048-48V48A48 48 0 00976 0zM928 652H96V96h832v556z</StreamGeometry> <StreamGeometry x:Key="Icons.Local">M976 0h-928A48 48 0 000 48v652a48 48 0 0048 48h416V928H200a48 48 0 000 96h624a48 48 0 000-96H560v-180h416a48 48 0 0048-48V48A48 48 0 00976 0zM928 652H96V96h832v556z</StreamGeometry>
<StreamGeometry x:Key="Icons.GitFlow.Init">M412 66C326 132 271 233 271 347c0 17 1 34 4 50-41-48-98-79-162-83a444 444 0 00-46 196c0 207 142 382 337 439h2c19 0 34 15 34 33 0 11-6 21-14 26l1 14C183 973 0 763 0 511 0 272 166 70 393 7A35 35 0 01414 0c19 0 34 15 34 33a33 33 0 01-36 33zm200 893c86-66 141-168 141-282 0-17-1-34-4-50 41 48 98 79 162 83a444 444 0 0046-196c0-207-142-382-337-439h-2a33 33 0 01-34-33c0-11 6-21 14-26L596 0C841 51 1024 261 1024 513c0 239-166 441-393 504A35 35 0 01610 1024a33 33 0 01-34-33 33 33 0 0136-33zM512 704a192 192 0 110-384 192 192 0 010 384z</StreamGeometry> <StreamGeometry x:Key="Icons.Init">M412 66C326 132 271 233 271 347c0 17 1 34 4 50-41-48-98-79-162-83a444 444 0 00-46 196c0 207 142 382 337 439h2c19 0 34 15 34 33 0 11-6 21-14 26l1 14C183 973 0 763 0 511 0 272 166 70 393 7A35 35 0 01414 0c19 0 34 15 34 33a33 33 0 01-36 33zm200 893c86-66 141-168 141-282 0-17-1-34-4-50 41 48 98 79 162 83a444 444 0 0046-196c0-207-142-382-337-439h-2a33 33 0 01-34-33c0-11 6-21 14-26L596 0C841 51 1024 261 1024 513c0 239-166 441-393 504A35 35 0 01610 1024a33 33 0 01-34-33 33 33 0 0136-33zM512 704a192 192 0 110-384 192 192 0 010 384z</StreamGeometry>
<StreamGeometry x:Key="Icons.GitFlow.Feature">M939 94v710L512 998 85 805V94h-64A21 21 0 010 73v-0C0 61 10 51 21 51h981c12 0 21 10 21 21v0c0 12-10 21-21 21h-64zm-536 588L512 624l109 58c6 3 13 4 20 3a32 32 0 0026-37l-21-122 88-87c5-5 8-11 9-18a32 32 0 00-27-37l-122-18-54-111a32 32 0 00-57 0l-54 111-122 18c-7 1-13 4-18 9a33 33 0 001 46l88 87-21 122c-1 7-0 14 3 20a32 32 0 0043 14z</StreamGeometry> <StreamGeometry x:Key="Icons.GitFlow.Feature">M939 94v710L512 998 85 805V94h-64A21 21 0 010 73v-0C0 61 10 51 21 51h981c12 0 21 10 21 21v0c0 12-10 21-21 21h-64zm-536 588L512 624l109 58c6 3 13 4 20 3a32 32 0 0026-37l-21-122 88-87c5-5 8-11 9-18a32 32 0 00-27-37l-122-18-54-111a32 32 0 00-57 0l-54 111-122 18c-7 1-13 4-18 9a33 33 0 001 46l88 87-21 122c-1 7-0 14 3 20a32 32 0 0043 14z</StreamGeometry>
<StreamGeometry x:Key="Icons.GitFlow.Hotfix">M236 542a32 32 0 109 63l86-12a180 180 0 0022 78l-71 47a32 32 0 1035 53l75-50a176 176 0 00166 40L326 529zM512 16C238 16 16 238 16 512s222 496 496 496 496-222 496-496S786 16 512 16zm0 896c-221 0-400-179-400-400a398 398 0 0186-247l561 561A398 398 0 01512 912zm314-154L690 622a179 179 0 004-29l85 12a32 32 0 109-63l-94-13v-49l94-13a32 32 0 10-9-63l-87 12a180 180 0 00-20-62l71-47A32 32 0 10708 252l-75 50a181 181 0 00-252 10l-115-115A398 398 0 01512 112c221 0 400 179 400 400a398 398 0 01-86 247z</StreamGeometry> <StreamGeometry x:Key="Icons.GitFlow.Hotfix">M236 542a32 32 0 109 63l86-12a180 180 0 0022 78l-71 47a32 32 0 1035 53l75-50a176 176 0 00166 40L326 529zM512 16C238 16 16 238 16 512s222 496 496 496 496-222 496-496S786 16 512 16zm0 896c-221 0-400-179-400-400a398 398 0 0186-247l561 561A398 398 0 01512 912zm314-154L690 622a179 179 0 004-29l85 12a32 32 0 109-63l-94-13v-49l94-13a32 32 0 10-9-63l-87 12a180 180 0 00-20-62l71-47A32 32 0 10708 252l-75 50a181 181 0 00-252 10l-115-115A398 398 0 01512 112c221 0 400 179 400 400a398 398 0 01-86 247z</StreamGeometry>
<StreamGeometry x:Key="Icons.GitFlow.Release">M884 159l-18-18a43 43 0 00-38-12l-235 43a166 166 0 00-101 60L400 349a128 128 0 00-148 47l-120 171a21 21 0 005 29l17 12a128 128 0 00178-32l27-38 124 124-38 27a128 128 0 00-32 178l12 17a21 21 0 0029 5l171-120a128 128 0 0047-148l117-92A166 166 0 00853 431l43-235a43 43 0 00-12-38zm-177 249a64 64 0 110-90 64 64 0 010 90zm-373 312a21 21 0 010 30l-139 139a21 21 0 01-30 0l-30-30a21 21 0 010-30l139-139a21 21 0 0130 0z</StreamGeometry> <StreamGeometry x:Key="Icons.GitFlow.Release">M884 159l-18-18a43 43 0 00-38-12l-235 43a166 166 0 00-101 60L400 349a128 128 0 00-148 47l-120 171a21 21 0 005 29l17 12a128 128 0 00178-32l27-38 124 124-38 27a128 128 0 00-32 178l12 17a21 21 0 0029 5l171-120a128 128 0 0047-148l117-92A166 166 0 00853 431l43-235a43 43 0 00-12-38zm-177 249a64 64 0 110-90 64 64 0 010 90zm-373 312a21 21 0 010 30l-139 139a21 21 0 01-30 0l-30-30a21 21 0 010-30l139-139a21 21 0 0130 0z</StreamGeometry>
@ -100,4 +97,10 @@
<StreamGeometry x:Key="Icons.WordWrap">M248 221a77 77 0 00-30-21c-18-7-40-10-68-5a224 224 0 00-45 13c-5 2-10 5-15 8l-3 2v68l11-9c10-8 21-14 34-19 13-5 26-7 39-7 12 0 21 3 28 10 6 6 9 16 9 29l-62 9c-14 2-26 6-36 11a80 80 0 00-25 20c-7 8-12 17-15 27-6 21-6 44 1 65a70 70 0 0041 43c10 4 21 6 34 6a80 80 0 0063-28v22h64V298c0-16-2-31-6-44a91 91 0 00-18-33zm-41 121v15c0 8-1 15-4 22a48 48 0 01-24 29 44 44 0 01-33 2 29 29 0 01-10-6 25 25 0 01-6-9 30 30 0 01-2-12c0-5 1-9 2-14a21 21 0 015-9 28 28 0 0110-7 83 83 0 0120-5l42-6zm323-68a144 144 0 00-16-42 87 87 0 00-28-29 75 75 0 00-41-11 73 73 0 00-44 14c-6 5-12 11-17 17V64H326v398h59v-18c8 10 18 17 30 21 6 2 13 3 21 3 16 0 31-4 43-11 12-7 23-18 31-31a147 147 0 0019-46 248 248 0 006-57c0-17-2-33-5-49zm-55 49c0 15-1 28-4 39-2 11-6 20-10 27a41 41 0 01-15 15 37 37 0 01-36 1 44 44 0 01-13-12 59 59 0 01-9-18A76 76 0 01384 352v-33c0-10 1-20 4-29 2-8 6-15 10-22a43 43 0 0115-13 37 37 0 0119-5 35 35 0 0132 18c4 6 7 14 9 23 2 9 3 20 3 31zM154 634a58 58 0 0120-15c14-6 35-7 49-1 7 3 13 6 20 12l21 17V572l-6-4a124 124 0 00-58-14c-20 0-38 4-54 11-16 7-30 17-41 30-12 13-20 29-26 46-6 17-9 36-9 57 0 18 3 36 8 52 6 16 14 30 24 42 10 12 23 21 38 28 15 7 32 10 50 10 15 0 28-2 39-5 11-3 21-8 30-14l5-4v-57l-13 6a26 26 0 01-5 2c-3 1-6 2-8 3-2 1-15 6-15 6-4 2-9 3-14 4a63 63 0 01-38-4 53 53 0 01-20-14 70 70 0 01-13-24 111 111 0 01-5-34c0-13 2-26 5-36 3-10 8-19 14-26zM896 384h-256V320h288c21 1 32 12 32 32v384c0 18-12 32-32 32H504l132 133-45 45-185-185c-16-21-16-25 0-45l185-185L637 576l-128 128H896V384z</StreamGeometry> <StreamGeometry x:Key="Icons.WordWrap">M248 221a77 77 0 00-30-21c-18-7-40-10-68-5a224 224 0 00-45 13c-5 2-10 5-15 8l-3 2v68l11-9c10-8 21-14 34-19 13-5 26-7 39-7 12 0 21 3 28 10 6 6 9 16 9 29l-62 9c-14 2-26 6-36 11a80 80 0 00-25 20c-7 8-12 17-15 27-6 21-6 44 1 65a70 70 0 0041 43c10 4 21 6 34 6a80 80 0 0063-28v22h64V298c0-16-2-31-6-44a91 91 0 00-18-33zm-41 121v15c0 8-1 15-4 22a48 48 0 01-24 29 44 44 0 01-33 2 29 29 0 01-10-6 25 25 0 01-6-9 30 30 0 01-2-12c0-5 1-9 2-14a21 21 0 015-9 28 28 0 0110-7 83 83 0 0120-5l42-6zm323-68a144 144 0 00-16-42 87 87 0 00-28-29 75 75 0 00-41-11 73 73 0 00-44 14c-6 5-12 11-17 17V64H326v398h59v-18c8 10 18 17 30 21 6 2 13 3 21 3 16 0 31-4 43-11 12-7 23-18 31-31a147 147 0 0019-46 248 248 0 006-57c0-17-2-33-5-49zm-55 49c0 15-1 28-4 39-2 11-6 20-10 27a41 41 0 01-15 15 37 37 0 01-36 1 44 44 0 01-13-12 59 59 0 01-9-18A76 76 0 01384 352v-33c0-10 1-20 4-29 2-8 6-15 10-22a43 43 0 0115-13 37 37 0 0119-5 35 35 0 0132 18c4 6 7 14 9 23 2 9 3 20 3 31zM154 634a58 58 0 0120-15c14-6 35-7 49-1 7 3 13 6 20 12l21 17V572l-6-4a124 124 0 00-58-14c-20 0-38 4-54 11-16 7-30 17-41 30-12 13-20 29-26 46-6 17-9 36-9 57 0 18 3 36 8 52 6 16 14 30 24 42 10 12 23 21 38 28 15 7 32 10 50 10 15 0 28-2 39-5 11-3 21-8 30-14l5-4v-57l-13 6a26 26 0 01-5 2c-3 1-6 2-8 3-2 1-15 6-15 6-4 2-9 3-14 4a63 63 0 01-38-4 53 53 0 01-20-14 70 70 0 01-13-24 111 111 0 01-5-34c0-13 2-26 5-36 3-10 8-19 14-26zM896 384h-256V320h288c21 1 32 12 32 32v384c0 18-12 32-32 32H504l132 133-45 45-185-185c-16-21-16-25 0-45l185-185L637 576l-128 128H896V384z</StreamGeometry>
<StreamGeometry x:Key="Icons.Detached">M128 183C128 154 154 128 183 128h521c30 0 55 26 55 55v38c0 17-17 34-34 34s-34-17-34-34v-26H196v495h26c17 0 34 17 34 34s-17 34-34 34h-38c-30 0-55-26-55-55V183zM380 896h-34c-26 0-47-21-47-47v-90h68V828h64V896H380c4 0 0 0 0 0zM759 828V896h90c26 0 47-21 47-47v-90h-68V828h-68zM828 435H896V346c0-26-21-47-47-47h-90v68H828v68zM435 299v68H367V439H299V346C299 320 320 299 346 299h90zM367 649H299v-107h68v107zM546 367V299h107v68h-107zM828 546H896v107h-68v-107zM649 828V896h-107v-68h107zM730 508v188c0 17-17 34-34 34h-188c-17 0-34-17-34-34s17-34 34-34h102l-124-124c-13-13-13-34 0-47 13-13 34-13 47 0l124 124V512c0-17 17-34 34-34 21-4 38 9 38 30z</StreamGeometry> <StreamGeometry x:Key="Icons.Detached">M128 183C128 154 154 128 183 128h521c30 0 55 26 55 55v38c0 17-17 34-34 34s-34-17-34-34v-26H196v495h26c17 0 34 17 34 34s-17 34-34 34h-38c-30 0-55-26-55-55V183zM380 896h-34c-26 0-47-21-47-47v-90h68V828h64V896H380c4 0 0 0 0 0zM759 828V896h90c26 0 47-21 47-47v-90h-68V828h-68zM828 435H896V346c0-26-21-47-47-47h-90v68H828v68zM435 299v68H367V439H299V346C299 320 320 299 346 299h90zM367 649H299v-107h68v107zM546 367V299h107v68h-107zM828 546H896v107h-68v-107zM649 828V896h-107v-68h107zM730 508v188c0 17-17 34-34 34h-188c-17 0-34-17-34-34s17-34 34-34h102l-124-124c-13-13-13-34 0-47 13-13 34-13 47 0l124 124V512c0-17 17-34 34-34 21-4 38 9 38 30z</StreamGeometry>
<StreamGeometry x:Key="Icons.GitIgnore">M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z</StreamGeometry> <StreamGeometry x:Key="Icons.GitIgnore">M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z</StreamGeometry>
<StreamGeometry x:Key="Icons.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.Lock">M832 464h-68V240a128 128 0 00-128-128h-248a128 128 0 00-128 128v224H192c-18 0-32 14-32 32v384c0 18 14 32 32 32h640c18 0 32-14 32-32v-384c0-18-14-32-32-32zm-292 237v53a8 8 0 01-8 8h-40a8 8 0 01-8-8v-53a48 48 0 1156 0zm152-237H332V240a56 56 0 0156-56h248a56 56 0 0156 56v224z</StreamGeometry>
<StreamGeometry x:Key="Icons.Unlock">M832 464H332V240c0-31 25-56 56-56h248c31 0 56 25 56 56v68c0 4 4 8 8 8h56c4 0 8-4 8-8v-68c0-71-57-128-128-128H388c-71 0-128 57-128 128v224h-68c-18 0-32 14-32 32v384c0 18 14 32 32 32h640c18 0 32-14 32-32V496c0-18-14-32-32-32zM540 701v53c0 4-4 8-8 8h-40c-4 0-8-4-8-8v-53c-12-9-20-23-20-39 0-27 22-48 48-48s48 22 48 48c0 16-8 30-20 39z</StreamGeometry>
<StreamGeometry x:Key="Icons.Track">M897 673v13c0 51-42 93-93 93h-10c-1 0-2 0-2 0H220c-23 0-42 19-42 42v13c0 23 19 42 42 42h552c14 0 26 12 26 26 0 14-12 26-26 26H220c-51 0-93-42-93-93v-13c0-51 42-93 93-93h20c1-0 2-0 2-0h562c23 0 42-19 42-42v-13c0-11-5-22-13-29-8-7-17-11-28-10H660c-14 0-26-12-26-26 0-14 12-26 26-26h144c24-1 47 7 65 24 18 17 29 42 29 67zM479 98c-112 0-203 91-203 203 0 44 14 85 38 118l132 208c15 24 50 24 66 0l133-209c23-33 37-73 37-117 0-112-91-203-203-203zm0 327c-68 0-122-55-122-122s55-122 122-122 122 55 122 122-55 122-122 122z</StreamGeometry>
<StreamGeometry x:Key="Icons.Whitespace">M416 64H768v64h-64v704h64v64H448v-64h64V512H416a224 224 0 1 1 0-448zM576 832h64V128H576v704zM416 128H512v320H416a160 160 0 0 1 0-320z</StreamGeometry>
<StreamGeometry x:Key="Icons.InteractiveRebase">M512 64A447 447 0 0064 512c0 248 200 448 448 448s448-200 448-448S760 64 512 64zM218 295h31c54 0 105 19 145 55 13 12 13 31 3 43a35 35 0 01-22 10 36 36 0 01-21-7 155 155 0 00-103-39h-31a32 32 0 01-31-31c0-18 13-31 30-31zm31 433h-31a32 32 0 01-31-31c0-16 13-31 31-31h31A154 154 0 00403 512 217 217 0 01620 295h75l-93-67a33 33 0 01-7-43 33 33 0 0143-7l205 148-205 148a29 29 0 01-18 6 32 32 0 01-31-31c0-10 4-19 13-25l93-67H620a154 154 0 00-154 154c0 122-97 220-217 220zm390 118a29 29 0 01-18 6 32 32 0 01-31-31c0-10 4-19 13-25l93-67h-75c-52 0-103-19-143-54-12-12-13-31-1-43a30 30 0 0142-3 151 151 0 00102 39h75L602 599a33 33 0 01-7-43 33 33 0 0143-7l205 148-203 151z</StreamGeometry>
</ResourceDictionary> </ResourceDictionary>

View file

@ -12,7 +12,7 @@
<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>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Error All</x:String> <x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Error All</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similar to 'error', but shows more</x:String> <x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similar to 'error', but shows more</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">Patch File :</x:String> <x:String x:Key="Text.Apply.File" xml:space="preserve">Patch File:</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Select .patch file to apply</x:String> <x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Select .patch file to apply</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignore whitespace changes</x:String> <x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignore whitespace changes</x:String>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">No Warn</x:String> <x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">No Warn</x:String>
@ -20,11 +20,11 @@
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Apply Patch</x:String> <x:String x:Key="Text.Apply.Title" xml:space="preserve">Apply Patch</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Warn</x:String> <x:String x:Key="Text.Apply.Warn" xml:space="preserve">Warn</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Outputs warnings for a few such errors, but applies</x:String> <x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Outputs warnings for a few such errors, but applies</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Whitespace :</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">Whitespace:</x:String>
<x:String x:Key="Text.Archive" xml:space="preserve">Archive ...</x:String> <x:String x:Key="Text.Archive" xml:space="preserve">Archive...</x:String>
<x:String x:Key="Text.Archive.File" xml:space="preserve">Save Archive To :</x:String> <x:String x:Key="Text.Archive.File" xml:space="preserve">Save Archive To:</x:String>
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Select archive file path</x:String> <x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Select archive file path</x:String>
<x:String x:Key="Text.Archive.Revision" xml:space="preserve">Revision :</x:String> <x:String x:Key="Text.Archive.Revision" xml:space="preserve">Revision:</x:String>
<x:String x:Key="Text.Archive.Title" xml:space="preserve">Archive</x:String> <x:String x:Key="Text.Archive.Title" xml:space="preserve">Archive</x:String>
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILES ASSUME UNCHANGED</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILES ASSUME UNCHANGED</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO FILES ASSUMED AS UNCHANGED</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO FILES ASSUMED AS UNCHANGED</x:String>
@ -32,23 +32,23 @@
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINARY FILE NOT SUPPORTED!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINARY FILE NOT SUPPORTED!!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME ON THIS FILE IS NOT SUPPORTED!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME ON THIS FILE IS NOT SUPPORTED!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout${0}$</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Compare with Branch</x:String> <x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Compare with Branch</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copy Branch Name</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copy Branch Name</x:String>
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Delete${0}$</x:String> <x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Delete ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Delete selected {0} branches</x:String> <x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Delete selected {0} branches</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Discard all changes</x:String> <x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Discard all changes</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Fast-Forward to${0}$</x:String> <x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Fast-Forward to ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git Flow - Finish${0}$</x:String> <x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git Flow - Finish ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Merge${0}$into${1}$</x:String> <x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Merge ${0}$ into ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Pull${0}$</x:String> <x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Pull ${0}$</x:String>
<x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">Pull${0}$into${1}$</x:String> <x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">Pull ${0}$ into ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push${0}$</x:String> <x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase${0}$on${1}$</x:String> <x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ on ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename${0}$</x:String> <x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Tracking ...</x:String> <x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Set Tracking Branch</x:String>
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">Unset Upstream</x:String> <x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">Unset Upstream</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Compare</x:String> <x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Compare</x:String>
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String> <x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
@ -60,39 +60,40 @@
<x:String x:Key="Text.Checkout" xml:space="preserve">Checkout Branch</x:String> <x:String x:Key="Text.Checkout" xml:space="preserve">Checkout Branch</x:String>
<x:String x:Key="Text.Checkout.Commit" xml:space="preserve">Checkout Commit</x:String> <x:String x:Key="Text.Checkout.Commit" xml:space="preserve">Checkout Commit</x:String>
<x:String x:Key="Text.Checkout.Commit.Warning" xml:space="preserve">Warning: By doing a commit checkout, your Head will be detached</x:String> <x:String x:Key="Text.Checkout.Commit.Warning" xml:space="preserve">Warning: By doing a commit checkout, your Head will be detached</x:String>
<x:String x:Key="Text.Checkout.Commit.Target" xml:space="preserve">Commit :</x:String> <x:String x:Key="Text.Checkout.Commit.Target" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch :</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Local Changes :</x:String> <x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Local Changes:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Discard</x:String> <x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Discard</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.DoNothing" xml:space="preserve">Do Nothing</x:String> <x:String x:Key="Text.Checkout.LocalChanges.DoNothing" xml:space="preserve">Do Nothing</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry-Pick This Commit</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry-Pick This Commit</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit :</x:String> <x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.CherryPick.CommitChanges" xml:space="preserve">Commit all changes</x:String> <x:String x:Key="Text.CherryPick.CommitChanges" xml:space="preserve">Commit all changes</x:String>
<x:String x:Key="Text.CherryPick.Title" xml:space="preserve">Cherry Pick</x:String> <x:String x:Key="Text.CherryPick.Title" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.ClearStashes" xml:space="preserve">Clear Stashes</x:String> <x:String x:Key="Text.ClearStashes" xml:space="preserve">Clear Stashes</x:String>
<x:String x:Key="Text.ClearStashes.Message" xml:space="preserve">You are trying to clear all stashes. Are you sure to continue?</x:String> <x:String x:Key="Text.ClearStashes.Message" xml:space="preserve">You are trying to clear all stashes. Are you sure to continue?</x:String>
<x:String x:Key="Text.Clone" xml:space="preserve">Clone Remote Repository</x:String> <x:String x:Key="Text.Clone" xml:space="preserve">Clone Remote Repository</x:String>
<x:String x:Key="Text.Clone.AdditionalParam" xml:space="preserve">Extra Parameters :</x:String> <x:String x:Key="Text.Clone.AdditionalParam" xml:space="preserve">Extra Parameters:</x:String>
<x:String x:Key="Text.Clone.AdditionalParam.Placeholder" xml:space="preserve">Additional arguments to clone repository. Optional.</x:String> <x:String x:Key="Text.Clone.AdditionalParam.Placeholder" xml:space="preserve">Additional arguments to clone repository. Optional.</x:String>
<x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Local Name :</x:String> <x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Local Name:</x:String>
<x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Repository name. Optional.</x:String> <x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Repository name. Optional.</x:String>
<x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Parent Folder :</x:String> <x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Parent Folder:</x:String>
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">Repository URL :</x:String> <x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">Repository URL:</x:String>
<x:String x:Key="Text.Close" xml:space="preserve">CLOSE</x:String> <x:String x:Key="Text.Close" xml:space="preserve">CLOSE</x:String>
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">Cherry-Pick This Commit</x:String> <x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">Cherry-Pick This Commit</x:String>
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Checkout Commit</x:String> <x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Checkout Commit</x:String>
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String> <x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String>
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String> <x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copy SHA</x:String> <x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copy SHA</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase${0}$to Here</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactive Rebase ${0}$ to Here</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset${0}$to Here</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ to Here</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ to Here</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Revert Commit</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Revert Commit</x:String>
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Reword</x:String> <x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Reword</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Save as Patch ...</x:String> <x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Save as Patch...</x:String>
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash Into Parent</x:String> <x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash Into Parent</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CHANGES</x:String> <x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CHANGES</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Search Changes ...</x:String> <x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Search Changes...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">FILES</x:String> <x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">FILES</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">LFS File</x:String> <x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">LFS File</x:String>
<x:String x:Key="Text.CommitDetail.Files.Submodule" xml:space="preserve">Submodule</x:String> <x:String x:Key="Text.CommitDetail.Files.Submodule" xml:space="preserve">Submodule</x:String>
@ -104,6 +105,8 @@
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">PARENTS</x:String> <x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">PARENTS</x:String>
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">REFS</x:String> <x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">REFS</x:String>
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String> <x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.CommitMessageTextBox.Placeholder" xml:space="preserve">Enter commit subject &amp; message</x:String>
<x:String x:Key="Text.CommitMessageTextBox.Tip" xml:space="preserve">Git uses an empty line to separate the subject and extra message body.</x:String>
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Configure</x:String> <x:String x:Key="Text.Configure" xml:space="preserve">Repository Configure</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String> <x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String> <x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String>
@ -114,43 +117,44 @@
<x:String x:Key="Text.Copy" xml:space="preserve">Copy</x:String> <x:String x:Key="Text.Copy" xml:space="preserve">Copy</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Copy Path</x:String> <x:String x:Key="Text.CopyPath" xml:space="preserve">Copy Path</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copy File Name</x:String> <x:String x:Key="Text.CopyFileName" xml:space="preserve">Copy File Name</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Create Branch</x:String> <x:String x:Key="Text.CreateBranch" xml:space="preserve">Create Branch...</x:String>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Based On :</x:String> <x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Based On:</x:String>
<x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">Check out after created</x:String> <x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">Check out the created branch</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">Local Changes :</x:String> <x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">Local Changes:</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.Discard" xml:space="preserve">Discard</x:String> <x:String x:Key="Text.CreateBranch.LocalChanges.Discard" xml:space="preserve">Discard</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.DoNothing" xml:space="preserve">Do Nothing</x:String> <x:String x:Key="Text.CreateBranch.LocalChanges.DoNothing" xml:space="preserve">Do Nothing</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String> <x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String>
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">New Branch Name :</x:String> <x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">New Branch Name:</x:String>
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Enter branch name.</x:String> <x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Enter branch name.</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Create Local Branch</x:String> <x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Create Local Branch</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">Create Tag</x:String> <x:String x:Key="Text.CreateTag" xml:space="preserve">Create Tag...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">New Tag At :</x:String> <x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">New Tag At:</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">GPG signing</x:String> <x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">GPG signing</x:String>
<x:String x:Key="Text.CreateTag.Message" xml:space="preserve">Tag Message :</x:String> <x:String x:Key="Text.CreateTag.Message" xml:space="preserve">Tag Message:</x:String>
<x:String x:Key="Text.CreateTag.Message.Placeholder" xml:space="preserve">Optional.</x:String> <x:String x:Key="Text.CreateTag.Message.Placeholder" xml:space="preserve">Optional.</x:String>
<x:String x:Key="Text.CreateTag.Name" xml:space="preserve">Tag Name :</x:String> <x:String x:Key="Text.CreateTag.Name" xml:space="preserve">Tag Name:</x:String>
<x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">Recommended format v1.0.0-alpha</x:String> <x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">Recommended format: v1.0.0-alpha</x:String>
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">Push to all remotes after created</x:String> <x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">Push to all remotes after created</x:String>
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">Kind </x:String> <x:String x:Key="Text.CreateTag.Title" xml:space="preserve">Create New Tag</x:String>
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">Kind:</x:String>
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">annotated</x:String> <x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">annotated</x:String>
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">lightweight</x:String> <x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">lightweight</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">Cut</x:String> <x:String x:Key="Text.Cut" xml:space="preserve">Cut</x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Delete Branch</x:String> <x:String x:Key="Text.DeleteBranch" xml:space="preserve">Delete Branch</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Branch :</x:String> <x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">You are about to delete a remote branch!!!</x:String> <x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">You are about to delete a remote branch!!!</x:String>
<x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">Also delete remote branch${0}$</x:String> <x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">Also delete remote branch ${0}$</x:String>
<x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">Delete Multiple Branches</x:String> <x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">Delete Multiple Branches</x:String>
<x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">You are trying to delete multiple branches at one time. Be sure to double-check before taking action!</x:String> <x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">You are trying to delete multiple branches at one time. Be sure to double-check before taking action!</x:String>
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">Delete Remote</x:String> <x:String x:Key="Text.DeleteRemote" xml:space="preserve">Delete Remote</x:String>
<x:String x:Key="Text.DeleteRemote.Remote" xml:space="preserve">Remote :</x:String> <x:String x:Key="Text.DeleteRemote.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">Target :</x:String> <x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.TitleForGroup" xml:space="preserve">Confirm Deleting Group</x:String> <x:String x:Key="Text.DeleteRepositoryNode.TitleForGroup" xml:space="preserve">Confirm Deleting Group</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.TitleForRepository" xml:space="preserve">Confirm Deleting Repository</x:String> <x:String x:Key="Text.DeleteRepositoryNode.TitleForRepository" xml:space="preserve">Confirm Deleting Repository</x:String>
<x:String x:Key="Text.DeleteSubmodule" xml:space="preserve">Delete Submodule</x:String> <x:String x:Key="Text.DeleteSubmodule" xml:space="preserve">Delete Submodule</x:String>
<x:String x:Key="Text.DeleteSubmodule.Path" xml:space="preserve">Submodule Path </x:String> <x:String x:Key="Text.DeleteSubmodule.Path" xml:space="preserve">Submodule Path:</x:String>
<x:String x:Key="Text.DeleteTag" xml:space="preserve">Delete Tag</x:String> <x:String x:Key="Text.DeleteTag" xml:space="preserve">Delete Tag</x:String>
<x:String x:Key="Text.DeleteTag.Tag" xml:space="preserve">Tag :</x:String> <x:String x:Key="Text.DeleteTag.Tag" xml:space="preserve">Tag:</x:String>
<x:String x:Key="Text.DeleteTag.WithRemote" xml:space="preserve">Delete from remote repositories</x:String> <x:String x:Key="Text.DeleteTag.WithRemote" xml:space="preserve">Delete from remote repositories</x:String>
<x:String x:Key="Text.Diff.Binary" xml:space="preserve">BINARY DIFF</x:String> <x:String x:Key="Text.Diff.Binary" xml:space="preserve">BINARY DIFF</x:String>
<x:String x:Key="Text.Diff.Binary.New" xml:space="preserve">NEW</x:String> <x:String x:Key="Text.Diff.Binary.New" xml:space="preserve">NEW</x:String>
@ -170,22 +174,23 @@
<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>
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Show hidden symbols</x:String>
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">Open In Merge Tool</x:String> <x:String x:Key="Text.DiffWithMerger" xml:space="preserve">Open In Merge Tool</x:String>
<x:String x:Key="Text.Discard" xml:space="preserve">Discard Changes</x:String> <x:String x:Key="Text.Discard" xml:space="preserve">Discard Changes</x:String>
<x:String x:Key="Text.Discard.All" xml:space="preserve">All local changes in working copy.</x:String> <x:String x:Key="Text.Discard.All" xml:space="preserve">All local changes in working copy.</x:String>
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Changes :</x:String> <x:String x:Key="Text.Discard.Changes" xml:space="preserve">Changes:</x:String>
<x:String x:Key="Text.Discard.Total" xml:space="preserve">Total {0} changes will be discard</x:String> <x:String x:Key="Text.Discard.Total" xml:space="preserve">Total {0} changes will be discard</x:String>
<x:String x:Key="Text.Discard.Warning" xml:space="preserve">You can't undo this action!!!</x:String> <x:String x:Key="Text.Discard.Warning" xml:space="preserve">You can't undo this action!!!</x:String>
<x:String x:Key="Text.EditRepositoryNode.Bookmark" xml:space="preserve">Bookmark :</x:String> <x:String x:Key="Text.EditRepositoryNode.Bookmark" xml:space="preserve">Bookmark:</x:String>
<x:String x:Key="Text.EditRepositoryNode.Name" xml:space="preserve">New Name :</x:String> <x:String x:Key="Text.EditRepositoryNode.Name" xml:space="preserve">New Name:</x:String>
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Target :</x:String> <x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Edit Selected Group</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Edit Selected Group</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Edit Selected Repository</x:String> <x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Edit Selected Repository</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String> <x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String> <x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch all remotes</x:String> <x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch all remotes</x:String>
<x:String x:Key="Text.Fetch.Prune" xml:space="preserve">Prune remote dead branches</x:String> <x:String x:Key="Text.Fetch.Prune" xml:space="preserve">Prune remote dead branches</x:String>
<x:String x:Key="Text.Fetch.Remote" xml:space="preserve">Remote :</x:String> <x:String x:Key="Text.Fetch.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">Fetch Remote Changes</x:String> <x:String x:Key="Text.Fetch.Title" xml:space="preserve">Fetch Remote Changes</x:String>
<x:String x:Key="Text.FileCM.AssumeUnchanged" xml:space="preserve">Assume unchanged</x:String> <x:String x:Key="Text.FileCM.AssumeUnchanged" xml:space="preserve">Assume unchanged</x:String>
<x:String x:Key="Text.FileCM.Discard" xml:space="preserve">Discard...</x:String> <x:String x:Key="Text.FileCM.Discard" xml:space="preserve">Discard...</x:String>
@ -193,8 +198,8 @@
<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>
<x:String x:Key="Text.FileCM.Stash" xml:space="preserve">Stash...</x:String> <x:String x:Key="Text.FileCM.Stash" xml:space="preserve">Stash...</x:String>
<x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">Stash {0} files...</x:String> <x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">Stash {0} files...</x:String>
@ -206,28 +211,50 @@
<x:String x:Key="Text.FileHistory" xml:space="preserve">File History</x:String> <x:String x:Key="Text.FileHistory" xml:space="preserve">File History</x:String>
<x:String x:Key="Text.Filter" xml:space="preserve">FILTER</x:String> <x:String x:Key="Text.Filter" xml:space="preserve">FILTER</x:String>
<x:String x:Key="Text.GitFlow" xml:space="preserve">Git-Flow</x:String> <x:String x:Key="Text.GitFlow" xml:space="preserve">Git-Flow</x:String>
<x:String x:Key="Text.GitFlow.DevelopBranch" xml:space="preserve">Development Branch :</x:String> <x:String x:Key="Text.GitFlow.DevelopBranch" xml:space="preserve">Development Branch:</x:String>
<x:String x:Key="Text.GitFlow.Feature" xml:space="preserve">Feature :</x:String> <x:String x:Key="Text.GitFlow.Feature" xml:space="preserve">Feature:</x:String>
<x:String x:Key="Text.GitFlow.FeaturePrefix" xml:space="preserve">Feature Prefix :</x:String> <x:String x:Key="Text.GitFlow.FeaturePrefix" xml:space="preserve">Feature Prefix:</x:String>
<x:String x:Key="Text.GitFlow.FinishFeature" xml:space="preserve">FLOW - Finish Feature</x:String> <x:String x:Key="Text.GitFlow.FinishFeature" xml:space="preserve">FLOW - Finish Feature</x:String>
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finish Hotfix</x:String> <x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finish Hotfix</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finish Release</x:String> <x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finish Release</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Target :</x:String> <x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix :</x:String> <x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Hotfix Prefix :</x:String> <x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Hotfix Prefix:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Initialize Git-Flow</x:String> <x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Initialize Git-Flow</x:String>
<x:String x:Key="Text.GitFlow.KeepBranchAfterFinish" xml:space="preserve">Keep branch</x:String> <x:String x:Key="Text.GitFlow.KeepBranchAfterFinish" xml:space="preserve">Keep branch</x:String>
<x:String x:Key="Text.GitFlow.ProductionBranch" xml:space="preserve">Production Branch :</x:String> <x:String x:Key="Text.GitFlow.ProductionBranch" xml:space="preserve">Production Branch:</x:String>
<x:String x:Key="Text.GitFlow.Release" xml:space="preserve">Release :</x:String> <x:String x:Key="Text.GitFlow.Release" xml:space="preserve">Release:</x:String>
<x:String x:Key="Text.GitFlow.ReleasePrefix" xml:space="preserve">Release Prefix :</x:String> <x:String x:Key="Text.GitFlow.ReleasePrefix" xml:space="preserve">Release Prefix:</x:String>
<x:String x:Key="Text.GitFlow.StartFeature" xml:space="preserve">Start Feature ...</x:String> <x:String x:Key="Text.GitFlow.StartFeature" xml:space="preserve">Start Feature...</x:String>
<x:String x:Key="Text.GitFlow.StartFeatureTitle" xml:space="preserve">FLOW - Start Feature</x:String> <x:String x:Key="Text.GitFlow.StartFeatureTitle" xml:space="preserve">FLOW - Start Feature</x:String>
<x:String x:Key="Text.GitFlow.StartHotfix" xml:space="preserve">Start Hotfix ...</x:String> <x:String x:Key="Text.GitFlow.StartHotfix" xml:space="preserve">Start Hotfix...</x:String>
<x:String x:Key="Text.GitFlow.StartHotfixTitle" xml:space="preserve">FLOW - Start Hotfix</x:String> <x:String x:Key="Text.GitFlow.StartHotfixTitle" xml:space="preserve">FLOW - Start Hotfix</x:String>
<x:String x:Key="Text.GitFlow.StartPlaceholder" xml:space="preserve">Enter name</x:String> <x:String x:Key="Text.GitFlow.StartPlaceholder" xml:space="preserve">Enter name</x:String>
<x:String x:Key="Text.GitFlow.StartRelease" xml:space="preserve">Start Release ...</x:String> <x:String x:Key="Text.GitFlow.StartRelease" xml:space="preserve">Start Release...</x:String>
<x:String x:Key="Text.GitFlow.StartReleaseTitle" xml:space="preserve">FLOW - Start Release</x:String> <x:String x:Key="Text.GitFlow.StartReleaseTitle" xml:space="preserve">FLOW - Start Release</x:String>
<x:String x:Key="Text.GitFlow.TagPrefix" xml:space="preserve">Version Tag Prefix :</x:String> <x:String x:Key="Text.GitFlow.TagPrefix" xml:space="preserve">Version Tag Prefix:</x:String>
<x:String x:Key="Text.GitLFS" xml:space="preserve">Git LFS</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern" xml:space="preserve">Add Track Pattern...</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.IsFilename" xml:space="preserve">Pattern is file name</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Pattern" xml:space="preserve">Custom Pattern:</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Title" xml:space="preserve">Add Track Pattern to Git LFS</x:String>
<x:String x:Key="Text.GitLFS.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Title" xml:space="preserve">Fetch LFS Objects</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Tips" xml:space="preserve">Run `git lfs fetch` to download Git LFS objects. This does not update the working copy.</x:String>
<x:String x:Key="Text.GitLFS.Install" xml:space="preserve">Install Git LFS hooks</x:String>
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">Show Locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">No Locked Files</x:String>
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">Lock</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS Locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Unlock</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Force Unlock</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">Prune</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">Run `git lfs prune` to delete old LFS files from local storage</x:String>
<x:String x:Key="Text.GitLFS.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.GitLFS.Pull.Title" xml:space="preserve">Pull LFS Objects</x:String>
<x:String x:Key="Text.GitLFS.Pull.Tips" xml:space="preserve">Run `git lfs pull` to download all Git LFS files for current ref &amp; checkout</x:String>
<x:String x:Key="Text.GitLFS.Track" xml:space="preserve">Track files named '{0}'</x:String>
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">Track all *{0} files</x:String>
<x:String x:Key="Text.Histories" xml:space="preserve">Histories</x:String> <x:String x:Key="Text.Histories" xml:space="preserve">Histories</x:String>
<x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">Switch Horizontal/Vertical Layout</x:String> <x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">Switch Horizontal/Vertical Layout</x:String>
<x:String x:Key="Text.Histories.GraphMode" xml:space="preserve">Switch Curve/Polyline Graph Mode</x:String> <x:String x:Key="Text.Histories.GraphMode" xml:space="preserve">Switch Curve/Polyline Graph Mode</x:String>
@ -257,25 +284,30 @@
<x:String x:Key="Text.Hotkeys.TextEditor.GotoPrevMatch" xml:space="preserve">Find previous match</x:String> <x:String x:Key="Text.Hotkeys.TextEditor.GotoPrevMatch" xml:space="preserve">Find previous match</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.Search" xml:space="preserve">Open search panel</x:String> <x:String x:Key="Text.Hotkeys.TextEditor.Search" xml:space="preserve">Open search panel</x:String>
<x:String x:Key="Text.Init" xml:space="preserve">Initialize Repository</x:String> <x:String x:Key="Text.Init" xml:space="preserve">Initialize Repository</x:String>
<x:String x:Key="Text.Init.Path" xml:space="preserve">Path :</x:String> <x:String x:Key="Text.Init.Path" xml:space="preserve">Path:</x:String>
<x:String x:Key="Text.Init.Tip" xml:space="preserve">Invalid repository detected. Run `git init` under this path?</x:String> <x:String x:Key="Text.Init.Tip" xml:space="preserve">Invalid repository detected. Run `git init` under this path?</x:String>
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Cherry-Pick in progress. Press 'Abort' to restore original HEAD.</x:String> <x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Cherry-Pick in progress. Press 'Abort' to restore original HEAD.</x:String>
<x:String x:Key="Text.InProgress.Merge" xml:space="preserve">Merge request in progress. Press 'Abort' to restore original HEAD.</x:String> <x:String x:Key="Text.InProgress.Merge" xml:space="preserve">Merge request in progress. Press 'Abort' to restore original HEAD.</x:String>
<x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">Rebase in progress. Press 'Abort' to restore original HEAD.</x:String> <x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">Rebase in progress. Press 'Abort' to restore original HEAD.</x:String>
<x:String x:Key="Text.InProgress.Revert" xml:space="preserve">Revert in progress. Press 'Abort' to restore original HEAD.</x:String> <x:String x:Key="Text.InProgress.Revert" xml:space="preserve">Revert in progress. Press 'Abort' to restore original HEAD.</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.On" xml:space="preserve">On:</x:String>
<x:String x:Key="Text.InteractiveRebase.MoveUp" xml:space="preserve">Move Up</x:String>
<x:String x:Key="Text.InteractiveRebase.MoveDown" xml:space="preserve">Move Down</x:String>
<x:String x:Key="Text.Launcher" xml:space="preserve">Source Git</x:String> <x:String x:Key="Text.Launcher" xml:space="preserve">Source Git</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.Launcher.Menu" xml:space="preserve">Open Main Menu</x:String> <x:String x:Key="Text.Launcher.Menu" xml:space="preserve">Open Main Menu</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>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">Into :</x:String> <x:String x:Key="Text.Merge.Into" xml:space="preserve">Into:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Merge Option :</x:String> <x:String x:Key="Text.Merge.Mode" xml:space="preserve">Merge Option:</x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">Source Branch :</x:String> <x:String x:Key="Text.Merge.Source" xml:space="preserve">Source Branch:</x:String>
<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.Notice" xml:space="preserve">NOTICE</x:String> <x:String x:Key="Text.Notice" xml:space="preserve">NOTICE</x:String>
<x:String x:Key="Text.OpenFolder" xml:space="preserve">SELECT FOLDER</x:String> <x:String x:Key="Text.OpenFolder" xml:space="preserve">SELECT FOLDER</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>
@ -298,6 +330,7 @@
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Language</x:String> <x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Language</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String> <x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String>
<x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">Restore windows</x:String> <x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">Restore windows</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String>
<x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">Use fixed tab width in titlebar</x:String> <x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">Use fixed tab width in titlebar</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String> <x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Fetch remotes automatically</x:String> <x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Fetch remotes automatically</x:String>
@ -321,63 +354,66 @@
<x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">Input path for installed gpg program</x:String> <x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">Input path for installed gpg program</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">User Signing Key</x:String> <x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">User Signing Key</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">User's gpg signing key</x:String> <x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">User's gpg signing key</x:String>
<x:String x:Key="Text.Preference.Merger" xml:space="preserve">EXTERNAL MERGE TOOL</x:String> <x:String x:Key="Text.Preference.DiffMerge" xml:space="preserve">DIFF/MERGE TOOL</x:String>
<x:String x:Key="Text.Preference.Merger.CustomDiffCmd" xml:space="preserve">Diff Command</x:String> <x:String x:Key="Text.Preference.DiffMerge.Path" xml:space="preserve">Install Path</x:String>
<x:String x:Key="Text.Preference.Merger.CustomMergeCmd" xml:space="preserve">Merge Command</x:String> <x:String x:Key="Text.Preference.DiffMerge.Path.Placeholder" xml:space="preserve">Input path for diff/merge tool</x:String>
<x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">Install Path</x:String> <x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">Tool</x:String>
<x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">Input path for merge tool</x:String> <x:String x:Key="Text.PruneRemote" xml:space="preserve">Prune Remote</x:String>
<x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">Merger</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch :</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">Into :</x:String> <x:String x:Key="Text.Pull.Into" xml:space="preserve">Into:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Local Changes :</x:String> <x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Local Changes:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Discard</x:String> <x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Discard</x:String>
<x:String x:Key="Text.Pull.LocalChanges.DoNothing" xml:space="preserve">Do Nothing</x:String> <x:String x:Key="Text.Pull.LocalChanges.DoNothing" xml:space="preserve">Do Nothing</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String> <x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remote :</x:String> <x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String> <x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Use rebase instead of merge</x:String> <x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Use rebase instead of merge</x:String>
<x:String x:Key="Text.Push" xml:space="preserve">Push</x:String> <x:String x:Key="Text.Push" xml:space="preserve">Push</x:String>
<x:String x:Key="Text.Push.Force" xml:space="preserve">Force push</x:String> <x:String x:Key="Text.Push.Force" xml:space="preserve">Force push</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">Local Branch :</x:String> <x:String x:Key="Text.Push.Local" xml:space="preserve">Local Branch:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote :</x:String> <x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Push.Title" xml:space="preserve">Push Changes To Remote</x:String> <x:String x:Key="Text.Push.Title" xml:space="preserve">Push Changes To Remote</x:String>
<x:String x:Key="Text.Push.To" xml:space="preserve">Remote Branch :</x:String> <x:String x:Key="Text.Push.To" xml:space="preserve">Remote Branch:</x:String>
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Tracking remote branch</x:String> <x:String x:Key="Text.Push.Tracking" xml:space="preserve">Set as tracking branch</x:String>
<x:String x:Key="Text.Push.WithAllTags" xml:space="preserve">Push all tags</x:String> <x:String x:Key="Text.Push.WithAllTags" xml:space="preserve">Push all tags</x:String>
<x:String x:Key="Text.PushTag" xml:space="preserve">Push Tag To Remote</x:String> <x:String x:Key="Text.PushTag" xml:space="preserve">Push Tag To Remote</x:String>
<x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">Push to all remotes</x:String> <x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">Push to all remotes</x:String>
<x:String x:Key="Text.PushTag.Remote" xml:space="preserve">Remote :</x:String> <x:String x:Key="Text.PushTag.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.PushTag.Tag" xml:space="preserve">Tag :</x:String> <x:String x:Key="Text.PushTag.Tag" xml:space="preserve">Tag:</x:String>
<x:String x:Key="Text.Quit" xml:space="preserve">Quit</x:String> <x:String x:Key="Text.Quit" xml:space="preserve">Quit</x:String>
<x:String x:Key="Text.Rebase" xml:space="preserve">Rebase Current Branch</x:String> <x:String x:Key="Text.Rebase" xml:space="preserve">Rebase Current Branch</x:String>
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reapply local changes</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reapply local changes</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">On :</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase :</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Refresh</x:String> <x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Refresh</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Add Remote</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Add Remote</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Edit Remote</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Edit Remote</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Name :</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String>
<x:String x:Key="Text.Remote.Name.Placeholder" xml:space="preserve">Remote name</x:String> <x:String x:Key="Text.Remote.Name.Placeholder" xml:space="preserve">Remote name</x:String>
<x:String x:Key="Text.Remote.URL" xml:space="preserve">Repository URL :</x:String> <x:String x:Key="Text.Remote.URL" xml:space="preserve">Repository URL:</x:String>
<x:String x:Key="Text.Remote.URL.Placeholder" xml:space="preserve">Remote git repository URL</x:String> <x:String x:Key="Text.Remote.URL.Placeholder" xml:space="preserve">Remote git repository URL</x:String>
<x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">Copy URL</x:String> <x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">Copy URL</x:String>
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">Delete ...</x:String> <x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">Delete...</x:String>
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">Edit ...</x:String> <x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">Edit...</x:String>
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">Fetch ...</x:String> <x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">Open In Browser</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Prune</x:String> <x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Prune</x:String>
<x:String x:Key="Text.RemoteCM.Prune.Target" xml:space="preserve">Target :</x:String> <x:String x:Key="Text.RemoteCM.Prune.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">Rename Branch</x:String> <x:String x:Key="Text.RenameBranch" xml:space="preserve">Rename Branch</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">New Name :</x:String> <x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">New Name:</x:String>
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Unique name for this branch</x:String> <x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Unique name for this branch</x:String>
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch :</x:String> <x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORT</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORT</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Cleanup(GC &amp; Prune)</x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">Cleanup(GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Run `gc` command and do `lfs prune` if LFS is installed.</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Run `git gc` command for this repository.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String>
<x:String x:Key="Text.Repository.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.FilterBranchTip" xml:space="preserve">Filter Branches</x:String> <x:String x:Key="Text.Repository.FilterBranchTip" xml:space="preserve">Filter Branches</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.NewBranch" xml:space="preserve">Create Branch</x:String> <x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
@ -401,21 +437,21 @@
<x:String x:Key="Text.Repository.Workspace" xml:space="preserve">WORKSPACE</x:String> <x:String x:Key="Text.Repository.Workspace" xml:space="preserve">WORKSPACE</x:String>
<x:String x:Key="Text.RepositoryURL" xml:space="preserve">Git Repository URL</x:String> <x:String x:Key="Text.RepositoryURL" xml:space="preserve">Git Repository URL</x:String>
<x:String x:Key="Text.Reset" xml:space="preserve">Reset Current Branch To Revision</x:String> <x:String x:Key="Text.Reset" xml:space="preserve">Reset Current Branch To Revision</x:String>
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Reset Mode :</x:String> <x:String x:Key="Text.Reset.Mode" xml:space="preserve">Reset Mode:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Move To :</x:String> <x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Move To:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Current Branch :</x:String> <x:String x:Key="Text.Reset.Target" xml:space="preserve">Current Branch:</x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">Reveal in File Explorer</x:String> <x:String x:Key="Text.RevealFile" xml:space="preserve">Reveal in File Explorer</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">Revert Commit</x:String> <x:String x:Key="Text.Revert" xml:space="preserve">Revert Commit</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit :</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit revert changes</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit revert changes</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Reword Commit Message</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Reword Commit Message</x:String>
<x:String x:Key="Text.Reword.Message" xml:space="preserve">Message :</x:String> <x:String x:Key="Text.Reword.Message" xml:space="preserve">Message:</x:String>
<x:String x:Key="Text.Reword.On" xml:space="preserve">On :</x:String> <x:String x:Key="Text.Reword.On" xml:space="preserve">On:</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Running. Please wait ...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">Running. Please wait...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">SAVE</x:String> <x:String x:Key="Text.Save" xml:space="preserve">SAVE</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Save As ...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Save As...</x:String>
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">Patch has been saved successfully!</x:String> <x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">Patch has been saved successfully!</x:String>
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">Check for Updates ...</x:String> <x:String x:Key="Text.SelfUpdate" xml:space="preserve">Check for Updates...</x:String>
<x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">New version of this software is available: </x:String> <x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">New version of this software is available: </x:String>
<x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">Check for updates failed!</x:String> <x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">Check for updates failed!</x:String>
<x:String x:Key="Text.SelfUpdate.GotoDownload" xml:space="preserve">Download</x:String> <x:String x:Key="Text.SelfUpdate.GotoDownload" xml:space="preserve">Download</x:String>
@ -423,22 +459,22 @@
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Software Update</x:String> <x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Software Update</x:String>
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">There are currently no updates available.</x:String> <x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">There are currently no updates available.</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Squash HEAD Into Parent</x:String> <x:String x:Key="Text.Squash" xml:space="preserve">Squash HEAD Into Parent</x:String>
<x:String x:Key="Text.Squash.Head" xml:space="preserve">HEAD :</x:String> <x:String x:Key="Text.Squash.Head" xml:space="preserve">HEAD:</x:String>
<x:String x:Key="Text.Squash.Message" xml:space="preserve">Reword :</x:String> <x:String x:Key="Text.Squash.Message" xml:space="preserve">Reword:</x:String>
<x:String x:Key="Text.Squash.To" xml:space="preserve">To :</x:String> <x:String x:Key="Text.Squash.To" xml:space="preserve">To:</x:String>
<x:String x:Key="Text.SSHKey" xml:space="preserve">SSH Private Key :</x:String> <x:String x:Key="Text.SSHKey" xml:space="preserve">SSH Private Key:</x:String>
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Private SSH key store path</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Private SSH key store path</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">START</x:String> <x:String x:Key="Text.Start" xml:space="preserve">START</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Include untracked files</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Include untracked files</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Message :</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Message:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Name of this stash</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Name of this stash</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Local Changes</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Local Changes</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Apply</x:String> <x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Apply</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Drop</x:String> <x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Drop</x:String>
<x:String x:Key="Text.StashCM.Pop" xml:space="preserve">Pop</x:String> <x:String x:Key="Text.StashCM.Pop" xml:space="preserve">Pop</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Drop Stash</x:String> <x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Drop Stash</x:String>
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Drop :</x:String> <x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Drop:</x:String>
<x:String x:Key="Text.Stashes" xml:space="preserve">Stashes</x:String> <x:String x:Key="Text.Stashes" xml:space="preserve">Stashes</x:String>
<x:String x:Key="Text.Stashes.Changes" xml:space="preserve">CHANGES</x:String> <x:String x:Key="Text.Stashes.Changes" xml:space="preserve">CHANGES</x:String>
<x:String x:Key="Text.Stashes.Stashes" xml:space="preserve">STASHES</x:String> <x:String x:Key="Text.Stashes.Stashes" xml:space="preserve">STASHES</x:String>
@ -455,14 +491,14 @@
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Copy Relative Path</x:String> <x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Copy Relative Path</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Fetch nested submodules</x:String> <x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Fetch nested submodules</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Open Submodule Repository</x:String> <x:String x:Key="Text.Submodule.Open" xml:space="preserve">Open Submodule Repository</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Relative Path :</x:String> <x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Relative Path:</x:String>
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Relative folder to store this module.</x:String> <x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Relative folder to store this module.</x:String>
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Delete Submodule</x:String> <x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Delete Submodule</x:String>
<x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String> <x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String>
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">Copy Tag Name</x:String> <x:String x:Key="Text.TagCM.Copy" xml:space="preserve">Copy Tag Name</x:String>
<x:String x:Key="Text.TagCM.Delete" xml:space="preserve">Delete${0}$</x:String> <x:String x:Key="Text.TagCM.Delete" xml:space="preserve">Delete ${0}$...</x:String>
<x:String x:Key="Text.TagCM.Push" xml:space="preserve">Push${0}$</x:String> <x:String x:Key="Text.TagCM.Push" xml:space="preserve">Push ${0}$...</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">URL :</x:String> <x:String x:Key="Text.URL" xml:space="preserve">URL:</x:String>
<x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">Update Submodules</x:String> <x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">Update Submodules</x:String>
<x:String x:Key="Text.UpdateSubmodules.Tip" xml:space="preserve">Run `submodule update` command for this repository.</x:String> <x:String x:Key="Text.UpdateSubmodules.Tip" xml:space="preserve">Run `submodule update` command for this repository.</x:String>
<x:String x:Key="Text.Warn" xml:space="preserve">Warning</x:String> <x:String x:Key="Text.Warn" xml:space="preserve">Warning</x:String>
@ -472,12 +508,13 @@
<x:String x:Key="Text.Welcome.Delete" xml:space="preserve">Delete</x:String> <x:String x:Key="Text.Welcome.Delete" xml:space="preserve">Delete</x:String>
<x:String x:Key="Text.Welcome.DragDropTip" xml:space="preserve">DRAG &amp; DROP FOLDER SUPPORTED. CUSTOM GROUPING SUPPORTED.</x:String> <x:String x:Key="Text.Welcome.DragDropTip" xml:space="preserve">DRAG &amp; DROP FOLDER SUPPORTED. CUSTOM GROUPING SUPPORTED.</x:String>
<x:String x:Key="Text.Welcome.Edit" xml:space="preserve">Edit</x:String> <x:String x:Key="Text.Welcome.Edit" xml:space="preserve">Edit</x:String>
<x:String x:Key="Text.Welcome.OpenAllInNode" xml:space="preserve">Open All Repositories</x:String>
<x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">Open Repository</x:String> <x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">Open Repository</x:String>
<x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">Open Terminal</x:String> <x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">Open Terminal</x:String>
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">Search Repositories ...</x:String> <x:String x:Key="Text.Welcome.Search" xml:space="preserve">Search Repositories...</x:String>
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">Sort</x:String> <x:String x:Key="Text.Welcome.Sort" xml:space="preserve">Sort</x:String>
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">Changes</x:String> <x:String x:Key="Text.WorkingCopy" xml:space="preserve">Changes</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Add To .gitignore ...</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignore all *{0} files</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignore all *{0} files</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignore *{0} files in the same folder</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignore *{0} files in the same folder</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignore files in the same folder</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignore files in the same folder</x:String>
@ -486,7 +523,6 @@
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">You can stage this file now.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">You can stage this file now.</x:String>
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String> <x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT &amp; PUSH</x:String> <x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT &amp; PUSH</x:String>
<x:String x:Key="Text.WorkingCopy.CommitMessageTip" xml:space="preserve">Enter commit message</x:String>
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String> <x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLICTS DETECTED</x:String> <x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLICTS DETECTED</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">FILE CONFLICTS ARE RESOLVED</x:String> <x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">FILE CONFLICTS ARE RESOLVED</x:String>

View file

@ -35,23 +35,23 @@
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二进制文件不支持该操作!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二进制文件不支持该操作!!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">选中文件不支持该操作!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">选中文件不支持该操作!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">检出(checkout)${0}$</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">检出(checkout) ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">与其他分支对比</x:String> <x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">与其他分支对比</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">与当前HEAD比较</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">与当前HEAD比较</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">复制分支名</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">复制分支名</x:String>
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">删除${0}$</x:String> <x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">删除 ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">删除选中的 {0} 个分支</x:String> <x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">删除选中的 {0} 个分支</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">放弃所有更改</x:String> <x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">放弃所有更改</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">快进(fast-forward)到${0}$</x:String> <x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">快进(fast-forward)到 ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">GIT工作流 - 完成${0}$</x:String> <x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">GIT工作流 - 完成 ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">合并${0}$到${1}$</x:String> <x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">合并 ${0}$ ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉回(pull)${0}$</x:String> <x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉回(pull) ${0}$</x:String>
<x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">拉回(pull)${0}$内容至${1}$</x:String> <x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">拉回(pull) ${0}$ 内容至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">推送(push)${0}$</x:String> <x:String x:Key="Text.BranchCM.Push" xml:space="preserve">推送(push)${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">变基(rebase)${0}$分支至${1}$</x:String> <x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 分支至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名${0}$</x:String> <x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名 ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支...</x:String> <x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支</x:String>
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">取消追踪</x:String> <x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">取消追踪</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比较</x:String> <x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比较</x:String>
<x:String x:Key="Text.Bytes" xml:space="preserve">字节</x:String> <x:String x:Key="Text.Bytes" xml:space="preserve">字节</x:String>
@ -88,8 +88,9 @@
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">与当前HEAD比较</x:String> <x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">与当前HEAD比较</x:String>
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String> <x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">复制提交指纹</x:String> <x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">复制提交指纹</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase)${0}$到此处</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">交互式变基(rebase -i) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset)${0}$到此处</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">回滚此提交</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">回滚此提交</x:String>
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">编辑提交信息</x:String> <x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">编辑提交信息</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">另存为补丁 ...</x:String> <x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">另存为补丁 ...</x:String>
@ -107,6 +108,8 @@
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String> <x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String>
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">相关引用</x:String> <x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">相关引用</x:String>
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">提交指纹</x:String> <x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">提交指纹</x:String>
<x:String x:Key="Text.CommitMessageTextBox.Placeholder" xml:space="preserve">填写提交信息</x:String>
<x:String x:Key="Text.CommitMessageTextBox.Tip" xml:space="preserve">Git使用空白行来划分提交信息中的主题与内容</x:String>
<x:String x:Key="Text.Configure" xml:space="preserve">仓库配置</x:String> <x:String x:Key="Text.Configure" xml:space="preserve">仓库配置</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String> <x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String> <x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String>
@ -117,7 +120,7 @@
<x:String x:Key="Text.Copy" xml:space="preserve">复制</x:String> <x:String x:Key="Text.Copy" xml:space="preserve">复制</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">复制路径</x:String> <x:String x:Key="Text.CopyPath" xml:space="preserve">复制路径</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">复制文件名</x:String> <x:String x:Key="Text.CopyFileName" xml:space="preserve">复制文件名</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">新建分支</x:String> <x:String x:Key="Text.CreateBranch" xml:space="preserve">新建分支 ...</x:String>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">新分支基于 </x:String> <x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">新分支基于 </x:String>
<x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">完成后切换到新分支</x:String> <x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">完成后切换到新分支</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">未提交更改 </x:String> <x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">未提交更改 </x:String>
@ -127,7 +130,7 @@
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">新分支名 </x:String> <x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">新分支名 </x:String>
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">填写分支名称。</x:String> <x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">填写分支名称。</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">创建本地分支</x:String> <x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">创建本地分支</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">新建标签</x:String> <x:String x:Key="Text.CreateTag" xml:space="preserve">新建标签 ...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">标签位于 </x:String> <x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">标签位于 </x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">使用GPG签名</x:String> <x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">使用GPG签名</x:String>
<x:String x:Key="Text.CreateTag.Message" xml:space="preserve">标签描述 </x:String> <x:String x:Key="Text.CreateTag.Message" xml:space="preserve">标签描述 </x:String>
@ -135,6 +138,7 @@
<x:String x:Key="Text.CreateTag.Name" xml:space="preserve">标签名 </x:String> <x:String x:Key="Text.CreateTag.Name" xml:space="preserve">标签名 </x:String>
<x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">推荐格式 v1.0.0-alpha</x:String> <x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">推荐格式 v1.0.0-alpha</x:String>
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">推送到所有远程仓库</x:String> <x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">推送到所有远程仓库</x:String>
<x:String x:Key="Text.CreateTag.Title" xml:space="preserve">新建标签</x:String>
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">类型 </x:String> <x:String x:Key="Text.CreateTag.Type" xml:space="preserve">类型 </x:String>
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">附注标签</x:String> <x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">附注标签</x:String>
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">轻量标签</x:String> <x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">轻量标签</x:String>
@ -142,7 +146,7 @@
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">删除分支确认</x:String> <x:String x:Key="Text.DeleteBranch" xml:space="preserve">删除分支确认</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">分支名 </x:String> <x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">分支名 </x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">您正在删除远程上的分支,请务必小心!!!</x:String> <x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">您正在删除远程上的分支,请务必小心!!!</x:String>
<x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">同时删除远程分支${0}$</x:String> <x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">同时删除远程分支 ${0}$</x:String>
<x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">删除多个分支</x:String> <x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">删除多个分支</x:String>
<x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">您正在尝试一次性删除多个分支,请务必仔细检查后再执行操作!</x:String> <x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">您正在尝试一次性删除多个分支,请务必仔细检查后再执行操作!</x:String>
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">删除远程确认</x:String> <x:String x:Key="Text.DeleteRemote" xml:space="preserve">删除远程确认</x:String>
@ -173,6 +177,7 @@
<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>
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">显示隐藏符号</x:String>
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">使用外部比对工具查看</x:String> <x:String x:Key="Text.DiffWithMerger" xml:space="preserve">使用外部比对工具查看</x:String>
<x:String x:Key="Text.Discard" xml:space="preserve">放弃更改确认</x:String> <x:String x:Key="Text.Discard" xml:space="preserve">放弃更改确认</x:String>
<x:String x:Key="Text.Discard.All" xml:space="preserve">所有本地址未提交的修改。</x:String> <x:String x:Key="Text.Discard.All" xml:space="preserve">所有本地址未提交的修改。</x:String>
@ -196,8 +201,8 @@
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">放弃选中的更改</x:String> <x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">放弃选中的更改</x:String>
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">使用外部合并工具打开</x:String> <x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">使用外部合并工具打开</x:String>
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">另存为补丁...</x:String> <x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">另存为补丁...</x:String>
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">暂存(add)...</x:String> <x:String x:Key="Text.FileCM.Stage" xml:space="preserve">暂存(add)</x:String>
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">暂存(add){0} 个文件...</x:String> <x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">暂存(add){0} 个文件</x:String>
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">暂存选中的更改</x:String> <x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">暂存选中的更改</x:String>
<x:String x:Key="Text.FileCM.Stash" xml:space="preserve">贮藏(stash)...</x:String> <x:String x:Key="Text.FileCM.Stash" xml:space="preserve">贮藏(stash)...</x:String>
<x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">贮藏(stash)选中的 {0} 个文件...</x:String> <x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">贮藏(stash)选中的 {0} 个文件...</x:String>
@ -231,6 +236,28 @@
<x:String x:Key="Text.GitFlow.StartRelease" xml:space="preserve">开始版本分支...</x:String> <x:String x:Key="Text.GitFlow.StartRelease" xml:space="preserve">开始版本分支...</x:String>
<x:String x:Key="Text.GitFlow.StartReleaseTitle" xml:space="preserve">开始版本分支</x:String> <x:String x:Key="Text.GitFlow.StartReleaseTitle" xml:space="preserve">开始版本分支</x:String>
<x:String x:Key="Text.GitFlow.TagPrefix" xml:space="preserve">版本标签前缀 </x:String> <x:String x:Key="Text.GitFlow.TagPrefix" xml:space="preserve">版本标签前缀 </x:String>
<x:String x:Key="Text.GitLFS" xml:space="preserve">Git LFS</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern" xml:space="preserve">添加追踪文件规则...</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.IsFilename" xml:space="preserve">匹配完整文件名</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Pattern" xml:space="preserve">规则 </x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Title" xml:space="preserve">添加LFS追踪文件规则</x:String>
<x:String x:Key="Text.GitLFS.Fetch" xml:space="preserve">拉取LFS对象 (fetch)</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Title" xml:space="preserve">拉取LFS对象</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Tips" xml:space="preserve">执行`git lfs prune`命令下载远程LFS对象但不会更新工作副本。</x:String>
<x:String x:Key="Text.GitLFS.Install" xml:space="preserve">启用Git LFS支持</x:String>
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">显示LFS对象锁</x:String>
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">没有锁定的LFS文件</x:String>
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">锁定</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS对象锁状态</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">解锁</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">强制解锁</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">精简本地LFS对象存储</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">运行`git lfs prune`命令从本地存储中精简当前版本不需要的LFS对象</x:String>
<x:String x:Key="Text.GitLFS.Pull" xml:space="preserve">拉回LFS对象 (pull)</x:String>
<x:String x:Key="Text.GitLFS.Pull.Title" xml:space="preserve">拉回LFS对象</x:String>
<x:String x:Key="Text.GitLFS.Pull.Tips" xml:space="preserve">运行`git lfs pull`命令下载远程LFS对象并更新工作副本。</x:String>
<x:String x:Key="Text.GitLFS.Track" xml:space="preserve">跟踪名为'{0}'的文件</x:String>
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">跟踪所有 *{0} 文件</x:String>
<x:String x:Key="Text.Histories" xml:space="preserve">历史记录</x:String> <x:String x:Key="Text.Histories" xml:space="preserve">历史记录</x:String>
<x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">切换横向/纵向显示</x:String> <x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">切换横向/纵向显示</x:String>
<x:String x:Key="Text.Histories.GraphMode" xml:space="preserve">切换曲线/折线显示</x:String> <x:String x:Key="Text.Histories.GraphMode" xml:space="preserve">切换曲线/折线显示</x:String>
@ -266,6 +293,11 @@
<x:String x:Key="Text.InProgress.Merge" xml:space="preserve">合并操作进行中。点击【终止】回滚到操作前的状态。</x:String> <x:String x:Key="Text.InProgress.Merge" xml:space="preserve">合并操作进行中。点击【终止】回滚到操作前的状态。</x:String>
<x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">变基Rebase操作进行中。点击【终止】回滚到操作前的状态。</x:String> <x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">变基Rebase操作进行中。点击【终止】回滚到操作前的状态。</x:String>
<x:String x:Key="Text.InProgress.Revert" xml:space="preserve">回滚提交操作进行中。点击【终止】回滚到操作前的状态。</x:String> <x:String x:Key="Text.InProgress.Revert" xml:space="preserve">回滚提交操作进行中。点击【终止】回滚到操作前的状态。</x:String>
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">交互式变基</x:String>
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">目标分支 </x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">起始提交 </x:String>
<x:String x:Key="Text.InteractiveRebase.MoveUp" xml:space="preserve">向上移动</x:String>
<x:String x:Key="Text.InteractiveRebase.MoveDown" xml:space="preserve">向下移动</x:String>
<x:String x:Key="Text.Launcher" xml:space="preserve">Source Git</x:String> <x:String x:Key="Text.Launcher" xml:space="preserve">Source Git</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>
@ -301,6 +333,7 @@
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">显示语言</x:String> <x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">显示语言</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">最大历史提交数</x:String> <x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">最大历史提交数</x:String>
<x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">启动时恢复上次打开的仓库</x:String> <x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">启动时恢复上次打开的仓库</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">SUBJECT字数检测</x:String>
<x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">使用固定宽度的标题栏标签</x:String> <x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">使用固定宽度的标题栏标签</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT配置</x:String> <x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT配置</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">启用定时自动拉取远程更新</x:String> <x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">启用定时自动拉取远程更新</x:String>
@ -324,12 +357,12 @@
<x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">签名程序所在路径</x:String> <x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">签名程序所在路径</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">用户签名KEY</x:String> <x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">用户签名KEY</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">输入签名提交所使用的KEY</x:String> <x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">输入签名提交所使用的KEY</x:String>
<x:String x:Key="Text.Preference.Merger" xml:space="preserve">外部合并工具</x:String> <x:String x:Key="Text.Preference.DiffMerge" xml:space="preserve">对比/合并工具</x:String>
<x:String x:Key="Text.Preference.Merger.CustomDiffCmd" xml:space="preserve">对比模式启动参数</x:String> <x:String x:Key="Text.Preference.DiffMerge.Path" xml:space="preserve">安装路径</x:String>
<x:String x:Key="Text.Preference.Merger.CustomMergeCmd" xml:space="preserve">合并模式启动参数</x:String> <x:String x:Key="Text.Preference.DiffMerge.Path.Placeholder" xml:space="preserve">填写工具可执行文件所在位置</x:String>
<x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">安装路径</x:String> <x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">工具</x:String>
<x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">填写工具可执行文件所在位置</x:String> <x:String x:Key="Text.PruneRemote" xml:space="preserve">清理远程已删除分支</x:String>
<x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">工具</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">目标 </x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String> <x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String>
@ -367,20 +400,22 @@
<x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">复制远程地址</x:String> <x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">复制远程地址</x:String>
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">删除 ...</x:String> <x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">删除 ...</x:String>
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">编辑 ...</x:String> <x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">编辑 ...</x:String>
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">拉取(fetch)更新 ...</x:String> <x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">拉取(fetch)更新</x:String>
<x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">在浏览器中打开</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">清理远程已删除分支</x:String> <x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">清理远程已删除分支</x:String>
<x:String x:Key="Text.RemoteCM.Prune.Target" xml:space="preserve">目标 </x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">分支重命名</x:String> <x:String x:Key="Text.RenameBranch" xml:space="preserve">分支重命名</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">新的名称 </x:String> <x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">新的名称 </x:String>
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能与现有分支名相同</x:String> <x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能与现有分支名相同</x:String>
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支 </x:String> <x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支 </x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">终止合并</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">终止合并</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本仓库(GC)</x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本仓库(GC)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作将执行`gc`对于启用LFS的仓库也会执行`lfs prune`。</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作将执行`git gc`命令。</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String> <x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String>
<x:String x:Key="Text.Repository.FilterBranchTip" xml:space="preserve">过滤显示分支</x:String> <x:String x:Key="Text.Repository.FilterBranchTip" xml:space="preserve">过滤显示分支</x:String>
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">过滤规则 </x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">本地分支</x:String> <x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">本地分支</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">定位HEAD</x:String> <x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">定位HEAD</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String> <x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String>
@ -463,8 +498,8 @@
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">删除子模块</x:String> <x:String x:Key="Text.Submodule.Remove" xml:space="preserve">删除子模块</x:String>
<x:String x:Key="Text.Sure" xml:space="preserve">确 定</x:String> <x:String x:Key="Text.Sure" xml:space="preserve">确 定</x:String>
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">复制标签名</x:String> <x:String x:Key="Text.TagCM.Copy" xml:space="preserve">复制标签名</x:String>
<x:String x:Key="Text.TagCM.Delete" xml:space="preserve">删除${0}$</x:String> <x:String x:Key="Text.TagCM.Delete" xml:space="preserve">删除 ${0}$...</x:String>
<x:String x:Key="Text.TagCM.Push" xml:space="preserve">推送${0}$</x:String> <x:String x:Key="Text.TagCM.Push" xml:space="preserve">推送 ${0}$...</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">仓库地址 </x:String> <x:String x:Key="Text.URL" xml:space="preserve">仓库地址 </x:String>
<x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">更新子模块</x:String> <x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">更新子模块</x:String>
<x:String x:Key="Text.UpdateSubmodules.Tip" xml:space="preserve">为此仓库执行`submodule update`命令,更新所有的子模块。</x:String> <x:String x:Key="Text.UpdateSubmodules.Tip" xml:space="preserve">为此仓库执行`submodule update`命令,更新所有的子模块。</x:String>
@ -475,12 +510,13 @@
<x:String x:Key="Text.Welcome.Delete" xml:space="preserve">删除</x:String> <x:String x:Key="Text.Welcome.Delete" xml:space="preserve">删除</x:String>
<x:String x:Key="Text.Welcome.DragDropTip" xml:space="preserve">支持拖放目录添加。支持自定义分组。</x:String> <x:String x:Key="Text.Welcome.DragDropTip" xml:space="preserve">支持拖放目录添加。支持自定义分组。</x:String>
<x:String x:Key="Text.Welcome.Edit" xml:space="preserve">编辑</x:String> <x:String x:Key="Text.Welcome.Edit" xml:space="preserve">编辑</x:String>
<x:String x:Key="Text.Welcome.OpenAllInNode" xml:space="preserve">打开所有包含仓库</x:String>
<x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">打开本地仓库</x:String> <x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">打开本地仓库</x:String>
<x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">打开终端</x:String> <x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">打开终端</x:String>
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">快速查找仓库...</x:String> <x:String x:Key="Text.Welcome.Search" xml:space="preserve">快速查找仓库...</x:String>
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">排序</x:String> <x:String x:Key="Text.Welcome.Sort" xml:space="preserve">排序</x:String>
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">本地更改</x:String> <x:String x:Key="Text.WorkingCopy" xml:space="preserve">本地更改</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">添加至 .gitignore 忽略列表 ...</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">添加至 .gitignore 忽略列表</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 文件</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 文件</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同目录下所有 *{0} 文件</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同目录下所有 *{0} 文件</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">忽略同目录下所有文件</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">忽略同目录下所有文件</x:String>
@ -489,7 +525,6 @@
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">现在您已可将其加入暂存区中</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">现在您已可将其加入暂存区中</x:String>
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String> <x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String>
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">提交并推送</x:String> <x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">提交并推送</x:String>
<x:String x:Key="Text.WorkingCopy.CommitMessageTip" xml:space="preserve">填写提交信息</x:String>
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String> <x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">检测到冲突</x:String> <x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">检测到冲突</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">文件冲突已解决</x:String> <x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">文件冲突已解决</x:String>

View file

@ -35,23 +35,23 @@
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二進位制檔案不支援該操作!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二進位制檔案不支援該操作!!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">選中檔案不支援該操作!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">選中檔案不支援該操作!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">檢出(checkout)${0}$</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">檢出(checkout) ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">與其他分支比較</x:String> <x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">與其他分支比較</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">與當前HEAD比較</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">與當前HEAD比較</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">與本地工作樹比較</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">與本地工作樹比較</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">複製分支名</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">複製分支名</x:String>
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">刪除${0}$</x:String> <x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">刪除 ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">刪除選中的 {0} 個分支</x:String> <x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">刪除選中的 {0} 個分支</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">放棄所有更改</x:String> <x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">放棄所有更改</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">快進(fast-forward)到${0}$</x:String> <x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">快進(fast-forward)到 ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">GIT工作流 - 完成${0}$</x:String> <x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">GIT工作流 - 完成 ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">合併${0}$到${1}$</x:String> <x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">合併 ${0}$ ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉回(pull)${0}$</x:String> <x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉回(pull) ${0}$</x:String>
<x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">拉回(pull)${0}$內容至${1}$</x:String> <x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">拉回(pull) ${0}$ 內容至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">推送(push)${0}$</x:String> <x:String x:Key="Text.BranchCM.Push" xml:space="preserve">推送(push)${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">變基(rebase)${0}$分支至${1}$</x:String> <x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">變基(rebase) ${0}$ 分支至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名${0}$</x:String> <x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名 ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支...</x:String> <x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支</x:String>
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">取消追蹤</x:String> <x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">取消追蹤</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比較</x:String> <x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比較</x:String>
<x:String x:Key="Text.Bytes" xml:space="preserve">位元組</x:String> <x:String x:Key="Text.Bytes" xml:space="preserve">位元組</x:String>
@ -88,8 +88,9 @@
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">與當前HEAD比較</x:String> <x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">與當前HEAD比較</x:String>
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">與本地工作樹比較</x:String> <x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">與本地工作樹比較</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">複製提交指紋</x:String> <x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">複製提交指紋</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">變基(rebase)${0}$到此處</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">互動式變基(rebase -i) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset)${0}$到此處</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">變基(rebase) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">回滾此提交</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">回滾此提交</x:String>
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">編輯提交資訊</x:String> <x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">編輯提交資訊</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">另存為補丁 ...</x:String> <x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">另存為補丁 ...</x:String>
@ -107,6 +108,8 @@
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String> <x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String>
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">相關引用</x:String> <x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">相關引用</x:String>
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">提交指紋</x:String> <x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">提交指紋</x:String>
<x:String x:Key="Text.CommitMessageTextBox.Placeholder" xml:space="preserve">填寫提交資訊</x:String>
<x:String x:Key="Text.CommitMessageTextBox.Tip" xml:space="preserve">Git使用空白行來劃分提交資訊中的主題與內容</x:String>
<x:String x:Key="Text.Configure" xml:space="preserve">倉庫配置</x:String> <x:String x:Key="Text.Configure" xml:space="preserve">倉庫配置</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵箱</x:String> <x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵箱</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">郵箱地址</x:String> <x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">郵箱地址</x:String>
@ -117,7 +120,7 @@
<x:String x:Key="Text.Copy" xml:space="preserve">複製</x:String> <x:String x:Key="Text.Copy" xml:space="preserve">複製</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">複製路徑</x:String> <x:String x:Key="Text.CopyPath" xml:space="preserve">複製路徑</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">複製檔名</x:String> <x:String x:Key="Text.CopyFileName" xml:space="preserve">複製檔名</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">新建分支</x:String> <x:String x:Key="Text.CreateBranch" xml:space="preserve">新建分支 ...</x:String>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">新分支基於 </x:String> <x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">新分支基於 </x:String>
<x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">完成後切換到新分支</x:String> <x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">完成後切換到新分支</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">未提交更改 </x:String> <x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">未提交更改 </x:String>
@ -127,7 +130,7 @@
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">新分支名 </x:String> <x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">新分支名 </x:String>
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">填寫分支名稱。</x:String> <x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">填寫分支名稱。</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">建立本地分支</x:String> <x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">建立本地分支</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">新建標籤</x:String> <x:String x:Key="Text.CreateTag" xml:space="preserve">新建標籤 ...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">標籤位於 </x:String> <x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">標籤位於 </x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">使用GPG簽名</x:String> <x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">使用GPG簽名</x:String>
<x:String x:Key="Text.CreateTag.Message" xml:space="preserve">標籤描述 </x:String> <x:String x:Key="Text.CreateTag.Message" xml:space="preserve">標籤描述 </x:String>
@ -135,6 +138,7 @@
<x:String x:Key="Text.CreateTag.Name" xml:space="preserve">標籤名 </x:String> <x:String x:Key="Text.CreateTag.Name" xml:space="preserve">標籤名 </x:String>
<x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">推薦格式 v1.0.0-alpha</x:String> <x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">推薦格式 v1.0.0-alpha</x:String>
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">推送到所有遠端倉庫</x:String> <x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">推送到所有遠端倉庫</x:String>
<x:String x:Key="Text.CreateTag.Title" xml:space="preserve">新建標籤</x:String>
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">型別 </x:String> <x:String x:Key="Text.CreateTag.Type" xml:space="preserve">型別 </x:String>
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">附註標籤</x:String> <x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">附註標籤</x:String>
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">輕量標籤</x:String> <x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">輕量標籤</x:String>
@ -142,7 +146,7 @@
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">刪除分支確認</x:String> <x:String x:Key="Text.DeleteBranch" xml:space="preserve">刪除分支確認</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">分支名 </x:String> <x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">分支名 </x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">您正在刪除遠端上的分支,請務必小心!!!</x:String> <x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">您正在刪除遠端上的分支,請務必小心!!!</x:String>
<x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">同時刪除遠端分支${0}$</x:String> <x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">同時刪除遠端分支 ${0}$</x:String>
<x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">刪除多個分支</x:String> <x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">刪除多個分支</x:String>
<x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">您正在嘗試一次性刪除多個分支,請務必仔細檢查後再執行操作!</x:String> <x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">您正在嘗試一次性刪除多個分支,請務必仔細檢查後再執行操作!</x:String>
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">刪除遠端確認</x:String> <x:String x:Key="Text.DeleteRemote" xml:space="preserve">刪除遠端確認</x:String>
@ -173,6 +177,7 @@
<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>
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">顯示隱藏符號</x:String>
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">使用外部比對工具檢視</x:String> <x:String x:Key="Text.DiffWithMerger" xml:space="preserve">使用外部比對工具檢視</x:String>
<x:String x:Key="Text.Discard" xml:space="preserve">放棄更改確認</x:String> <x:String x:Key="Text.Discard" xml:space="preserve">放棄更改確認</x:String>
<x:String x:Key="Text.Discard.All" xml:space="preserve">所有本地址未提交的修改。</x:String> <x:String x:Key="Text.Discard.All" xml:space="preserve">所有本地址未提交的修改。</x:String>
@ -196,8 +201,8 @@
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">放棄選中的更改</x:String> <x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">放棄選中的更改</x:String>
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">使用外部合併工具開啟</x:String> <x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">使用外部合併工具開啟</x:String>
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">另存為補丁...</x:String> <x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">另存為補丁...</x:String>
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">暫存(add)...</x:String> <x:String x:Key="Text.FileCM.Stage" xml:space="preserve">暫存(add)</x:String>
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">暫存(add){0} 個檔案...</x:String> <x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">暫存(add){0} 個檔案</x:String>
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">暫存選中的更改</x:String> <x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">暫存選中的更改</x:String>
<x:String x:Key="Text.FileCM.Stash" xml:space="preserve">儲藏(stash)...</x:String> <x:String x:Key="Text.FileCM.Stash" xml:space="preserve">儲藏(stash)...</x:String>
<x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">儲藏(stash)選中的 {0} 個檔案...</x:String> <x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">儲藏(stash)選中的 {0} 個檔案...</x:String>
@ -231,6 +236,28 @@
<x:String x:Key="Text.GitFlow.StartRelease" xml:space="preserve">開始版本分支...</x:String> <x:String x:Key="Text.GitFlow.StartRelease" xml:space="preserve">開始版本分支...</x:String>
<x:String x:Key="Text.GitFlow.StartReleaseTitle" xml:space="preserve">開始版本分支</x:String> <x:String x:Key="Text.GitFlow.StartReleaseTitle" xml:space="preserve">開始版本分支</x:String>
<x:String x:Key="Text.GitFlow.TagPrefix" xml:space="preserve">版本標籤字首 </x:String> <x:String x:Key="Text.GitFlow.TagPrefix" xml:space="preserve">版本標籤字首 </x:String>
<x:String x:Key="Text.GitLFS" xml:space="preserve">Git LFS</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern" xml:space="preserve">添加追蹤檔案規則...</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.IsFilename" xml:space="preserve">匹配完整檔案名</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Pattern" xml:space="preserve">規則 </x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Title" xml:space="preserve">添加LFS追蹤檔案規則</x:String>
<x:String x:Key="Text.GitLFS.Fetch" xml:space="preserve">拉取LFS物件 (fetch)</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Title" xml:space="preserve">拉取LFS物件</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Tips" xml:space="preserve">執行`git lfs fetch`命令下載遠端LFS物件但不會更新工作副本。</x:String>
<x:String x:Key="Text.GitLFS.Install" xml:space="preserve">啟用Git LFS支援</x:String>
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">顯示LFS物件鎖</x:String>
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">沒有鎖定的LFS物件</x:String>
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">鎖定</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS物件鎖</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">解鎖</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">強制解鎖</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">精簡本地LFS物件存儲</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">執行`git lfs prune`命令從本地存儲中精簡當前版本不需要的LFS物件</x:String>
<x:String x:Key="Text.GitLFS.Pull" xml:space="preserve">拉回LFS物件 (pull)</x:String>
<x:String x:Key="Text.GitLFS.Pull.Title" xml:space="preserve">拉回LFS物件</x:String>
<x:String x:Key="Text.GitLFS.Pull.Tips" xml:space="preserve">執行`git lfs pull`命令下載遠端LFS物件并更新工作副本。</x:String>
<x:String x:Key="Text.GitLFS.Track" xml:space="preserve">跟蹤名為'{0}'的檔案</x:String>
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">跟蹤所有 *{0} 檔案</x:String>
<x:String x:Key="Text.Histories" xml:space="preserve">歷史記錄</x:String> <x:String x:Key="Text.Histories" xml:space="preserve">歷史記錄</x:String>
<x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">切換橫向/縱向顯示</x:String> <x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">切換橫向/縱向顯示</x:String>
<x:String x:Key="Text.Histories.GraphMode" xml:space="preserve">切換曲線/折線顯示</x:String> <x:String x:Key="Text.Histories.GraphMode" xml:space="preserve">切換曲線/折線顯示</x:String>
@ -266,6 +293,11 @@
<x:String x:Key="Text.InProgress.Merge" xml:space="preserve">合併操作進行中。點選【終止】回滾到操作前的狀態。</x:String> <x:String x:Key="Text.InProgress.Merge" xml:space="preserve">合併操作進行中。點選【終止】回滾到操作前的狀態。</x:String>
<x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">變基Rebase操作進行中。點選【終止】回滾到操作前的狀態。</x:String> <x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">變基Rebase操作進行中。點選【終止】回滾到操作前的狀態。</x:String>
<x:String x:Key="Text.InProgress.Revert" xml:space="preserve">回滾提交操作進行中。點選【終止】回滾到操作前的狀態。</x:String> <x:String x:Key="Text.InProgress.Revert" xml:space="preserve">回滾提交操作進行中。點選【終止】回滾到操作前的狀態。</x:String>
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">互動式變基</x:String>
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">目標分支 </x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">起始提交 </x:String>
<x:String x:Key="Text.InteractiveRebase.MoveUp" xml:space="preserve">向上移動</x:String>
<x:String x:Key="Text.InteractiveRebase.MoveDown" xml:space="preserve">向下移動</x:String>
<x:String x:Key="Text.Launcher" xml:space="preserve">Source Git</x:String> <x:String x:Key="Text.Launcher" xml:space="preserve">Source Git</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>
@ -301,6 +333,7 @@
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">顯示語言</x:String> <x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">顯示語言</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">最大歷史提交數</x:String> <x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">最大歷史提交數</x:String>
<x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">啟動時恢復上次開啟的倉庫</x:String> <x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">啟動時恢復上次開啟的倉庫</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">SUBJECT字數檢測</x:String>
<x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">使用固定寬度的標題欄標籤</x:String> <x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">使用固定寬度的標題欄標籤</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT配置</x:String> <x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT配置</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">啟用定時自動拉取遠端更新</x:String> <x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">啟用定時自動拉取遠端更新</x:String>
@ -324,12 +357,12 @@
<x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">gpg.exe所在路徑</x:String> <x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">gpg.exe所在路徑</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">使用者簽名KEY</x:String> <x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">使用者簽名KEY</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">輸入簽名提交所使用的KEY</x:String> <x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">輸入簽名提交所使用的KEY</x:String>
<x:String x:Key="Text.Preference.Merger" xml:space="preserve">外部合併工具</x:String> <x:String x:Key="Text.Preference.DiffMerge" xml:space="preserve">對比/合併工具</x:String>
<x:String x:Key="Text.Preference.Merger.CustomDiffCmd" xml:space="preserve">對比模式啟動引數</x:String> <x:String x:Key="Text.Preference.DiffMerge.Path" xml:space="preserve">安裝路徑</x:String>
<x:String x:Key="Text.Preference.Merger.CustomMergeCmd" xml:space="preserve">合併模式啟動引數</x:String> <x:String x:Key="Text.Preference.DiffMerge.Path.Placeholder" xml:space="preserve">填寫工具可執行檔案所在位置</x:String>
<x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">安裝路徑</x:String> <x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">工具</x:String>
<x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">填寫工具可執行檔案所在位置</x:String> <x:String x:Key="Text.PruneRemote" xml:space="preserve">清理遠端已刪除分支</x:String>
<x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">工具</x:String> <x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">目標 </x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String> <x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String>
@ -367,20 +400,22 @@
<x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">複製遠端地址</x:String> <x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">複製遠端地址</x:String>
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">刪除 ...</x:String> <x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">刪除 ...</x:String>
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">編輯 ...</x:String> <x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">編輯 ...</x:String>
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">拉取(fetch)更新 ...</x:String> <x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">拉取(fetch)更新</x:String>
<x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">在瀏覽器中訪問網址</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">清理遠端已刪除分支</x:String> <x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">清理遠端已刪除分支</x:String>
<x:String x:Key="Text.RemoteCM.Prune.Target" xml:space="preserve">目標 </x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">分支重新命名</x:String> <x:String x:Key="Text.RenameBranch" xml:space="preserve">分支重新命名</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">新的名稱 </x:String> <x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">新的名稱 </x:String>
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能與現有分支名相同</x:String> <x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能與現有分支名相同</x:String>
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支 </x:String> <x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支 </x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">終止合併</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">終止合併</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本倉庫(GC)</x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本倉庫(GC)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作將執行`gc`對於啟用LFS的倉庫也會執行`lfs prune`。</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作將執行`git gc`命令。</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空過濾規則</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本倉庫</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本倉庫</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在檔案瀏覽器中開啟</x:String> <x:String x:Key="Text.Repository.Explore" xml:space="preserve">在檔案瀏覽器中開啟</x:String>
<x:String x:Key="Text.Repository.FilterBranchTip" xml:space="preserve">過濾顯示分支</x:String> <x:String x:Key="Text.Repository.FilterBranchTip" xml:space="preserve">過濾顯示分支</x:String>
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">過濾規則 </x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">本地分支</x:String> <x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">本地分支</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">定位HEAD</x:String> <x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">定位HEAD</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String> <x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String>
@ -463,8 +498,8 @@
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">刪除子模組</x:String> <x:String x:Key="Text.Submodule.Remove" xml:space="preserve">刪除子模組</x:String>
<x:String x:Key="Text.Sure" xml:space="preserve">確 定</x:String> <x:String x:Key="Text.Sure" xml:space="preserve">確 定</x:String>
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">複製標籤名</x:String> <x:String x:Key="Text.TagCM.Copy" xml:space="preserve">複製標籤名</x:String>
<x:String x:Key="Text.TagCM.Delete" xml:space="preserve">刪除${0}$</x:String> <x:String x:Key="Text.TagCM.Delete" xml:space="preserve">刪除 ${0}$...</x:String>
<x:String x:Key="Text.TagCM.Push" xml:space="preserve">推送${0}$</x:String> <x:String x:Key="Text.TagCM.Push" xml:space="preserve">推送 ${0}$...</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">倉庫地址 </x:String> <x:String x:Key="Text.URL" xml:space="preserve">倉庫地址 </x:String>
<x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">更新子模組</x:String> <x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">更新子模組</x:String>
<x:String x:Key="Text.UpdateSubmodules.Tip" xml:space="preserve">本操作將執行 `submodule update` 。</x:String> <x:String x:Key="Text.UpdateSubmodules.Tip" xml:space="preserve">本操作將執行 `submodule update` 。</x:String>
@ -475,12 +510,13 @@
<x:String x:Key="Text.Welcome.Delete" xml:space="preserve">刪除</x:String> <x:String x:Key="Text.Welcome.Delete" xml:space="preserve">刪除</x:String>
<x:String x:Key="Text.Welcome.DragDropTip" xml:space="preserve">支援拖放目錄新增。支援自定義分組。</x:String> <x:String x:Key="Text.Welcome.DragDropTip" xml:space="preserve">支援拖放目錄新增。支援自定義分組。</x:String>
<x:String x:Key="Text.Welcome.Edit" xml:space="preserve">編輯</x:String> <x:String x:Key="Text.Welcome.Edit" xml:space="preserve">編輯</x:String>
<x:String x:Key="Text.Welcome.OpenAllInNode" xml:space="preserve">打開所有包含倉庫</x:String>
<x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">開啟本地倉庫</x:String> <x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">開啟本地倉庫</x:String>
<x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">開啟終端</x:String> <x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">開啟終端</x:String>
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">快速查詢倉庫...</x:String> <x:String x:Key="Text.Welcome.Search" xml:space="preserve">快速查詢倉庫...</x:String>
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">排序</x:String> <x:String x:Key="Text.Welcome.Sort" xml:space="preserve">排序</x:String>
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">本地更改</x:String> <x:String x:Key="Text.WorkingCopy" xml:space="preserve">本地更改</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">添加至 .gitignore 忽略清單 ...</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">添加至 .gitignore 忽略清單</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 檔案</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 檔案</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同路徑下所有 *{0} 檔案</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同路徑下所有 *{0} 檔案</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">忽略同路徑下所有檔案</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">忽略同路徑下所有檔案</x:String>
@ -489,7 +525,6 @@
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">現在您已可將其加入暫存區中</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">現在您已可將其加入暫存區中</x:String>
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String> <x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String>
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">提交併推送</x:String> <x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">提交併推送</x:String>
<x:String x:Key="Text.WorkingCopy.CommitMessageTip" xml:space="preserve">填寫提交資訊</x:String>
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String> <x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">檢測到衝突</x:String> <x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">檢測到衝突</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">檔案衝突已解決</x:String> <x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">檔案衝突已解決</x:String>

View file

@ -1,7 +1,6 @@
<Styles xmlns="https://github.com/avaloniaui" <Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:SourceGit.ViewModels" xmlns:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
xmlns:ae="using:AvaloniaEdit" xmlns:ae="using:AvaloniaEdit"
xmlns:aes="using:AvaloniaEdit.Search"> xmlns:aes="using:AvaloniaEdit.Search">
<Design.PreviewWith> <Design.PreviewWith>
@ -160,6 +159,11 @@
<Setter Property="FontSize" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize}"/> <Setter Property="FontSize" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize}"/>
</Style> </Style>
<Style Selector="FlyoutPresenter">
<Setter Property="MaxWidth" Value="1024"/>
<Setter Property="MaxHeight" Value="768"/>
</Style>
<Style Selector="Path"> <Style Selector="Path">
<Setter Property="Fill" Value="{DynamicResource Brush.FG1}"/> <Setter Property="Fill" Value="{DynamicResource Brush.FG1}"/>
<Setter Property="Stretch" Value="Uniform"/> <Setter Property="Stretch" Value="Uniform"/>
@ -405,7 +409,8 @@
</Style> </Style>
<Style Selector="Button.flat"> <Style Selector="Button.flat">
<Setter Property="BorderThickness" Value="0"/> <Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border2}"/>
<Setter Property="FontWeight" Value="Bold"/> <Setter Property="FontWeight" Value="Bold"/>
<Setter Property="TextBlock.TextAlignment" Value="Center"/> <Setter Property="TextBlock.TextAlignment" Value="Center"/>
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/> <Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
@ -415,15 +420,12 @@
<ControlTemplate> <ControlTemplate>
<Grid> <Grid>
<Border x:Name="PART_Border" <Border x:Name="PART_Border"
Margin="2"
Background="{TemplateBinding Background}" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}" CornerRadius="{TemplateBinding CornerRadius}"/>
Effect="drop-shadow(0 0 2 #80000000)"/>
<ContentPresenter x:Name="PART_ContentPresenter" <ContentPresenter x:Name="PART_ContentPresenter"
Margin="2"
Background="Transparent" Background="Transparent"
Padding="{TemplateBinding Padding}" Padding="{TemplateBinding Padding}"
Content="{TemplateBinding Content}" Content="{TemplateBinding Content}"
@ -441,14 +443,18 @@
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent"/>
</Style> </Style>
<Style Selector="Button.flat.primary"> <Style Selector="Button.flat.primary">
<Setter Property="Background" Value="{DynamicResource Brush.FlatButton.PrimaryBackground}"/> <Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrush}"/>
<Setter Property="Background" Value="{DynamicResource AccentButtonBackground}"/>
</Style> </Style>
<Style Selector="Button.flat.primary:pointerover /template/ Border#PART_Border"> <Style Selector="Button.flat.primary:pointerover /template/ Border#PART_Border">
<Setter Property="Background" Value="{DynamicResource Brush.FlatButton.PrimaryBackgroundHovered}"/> <Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPointerOver}"/>
</Style> </Style>
<Style Selector="Button.flat.primary:pointerover /template/ ContentPresenter#PART_ContentPresenter"> <Style Selector="Button.flat.primary:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent"/>
</Style> </Style>
<Style Selector="Button.flat.primary TextBlock">
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForeground}"/>
</Style>
<Style Selector="aes|SearchPanel"> <Style Selector="aes|SearchPanel">
<Setter Property="Template"> <Setter Property="Template">

View file

@ -21,8 +21,6 @@
<Color x:Key="Color.Border2">#FFCFCFCF</Color> <Color x:Key="Color.Border2">#FFCFCFCF</Color>
<Color x:Key="Color.FlatButton.Background">#FFF8F8F8</Color> <Color x:Key="Color.FlatButton.Background">#FFF8F8F8</Color>
<Color x:Key="Color.FlatButton.BackgroundHovered">White</Color> <Color x:Key="Color.FlatButton.BackgroundHovered">White</Color>
<Color x:Key="Color.FlatButton.PrimaryBackground">#FF4295FF</Color>
<Color x:Key="Color.FlatButton.PrimaryBackgroundHovered">#FF529DFB</Color>
<Color x:Key="Color.FG1">#FF1F1F1F</Color> <Color x:Key="Color.FG1">#FF1F1F1F</Color>
<Color x:Key="Color.FG2">#FF6F6F6F</Color> <Color x:Key="Color.FG2">#FF6F6F6F</Color>
<Color x:Key="Color.Diff.EmptyBG">#3C000000</Color> <Color x:Key="Color.Diff.EmptyBG">#3C000000</Color>
@ -52,8 +50,6 @@
<Color x:Key="Color.Border2">#FF404040</Color> <Color x:Key="Color.Border2">#FF404040</Color>
<Color x:Key="Color.FlatButton.Background">#FF303030</Color> <Color x:Key="Color.FlatButton.Background">#FF303030</Color>
<Color x:Key="Color.FlatButton.BackgroundHovered">#FF333333</Color> <Color x:Key="Color.FlatButton.BackgroundHovered">#FF333333</Color>
<Color x:Key="Color.FlatButton.PrimaryBackground">#FF3A3A3A</Color>
<Color x:Key="Color.FlatButton.PrimaryBackgroundHovered">#FF404040</Color>
<Color x:Key="Color.FG1">#FFDDDDDD</Color> <Color x:Key="Color.FG1">#FFDDDDDD</Color>
<Color x:Key="Color.FG2">#40F1F1F1</Color> <Color x:Key="Color.FG2">#40F1F1F1</Color>
<Color x:Key="Color.Diff.EmptyBG">#3C000000</Color> <Color x:Key="Color.Diff.EmptyBG">#3C000000</Color>
@ -83,8 +79,6 @@
<SolidColorBrush x:Key="Brush.Border2" Color="{DynamicResource Color.Border2}"/> <SolidColorBrush x:Key="Brush.Border2" Color="{DynamicResource Color.Border2}"/>
<SolidColorBrush x:Key="Brush.FlatButton.Background" Color="{DynamicResource Color.FlatButton.Background}"/> <SolidColorBrush x:Key="Brush.FlatButton.Background" Color="{DynamicResource Color.FlatButton.Background}"/>
<SolidColorBrush x:Key="Brush.FlatButton.BackgroundHovered" Color="{DynamicResource Color.FlatButton.BackgroundHovered}"/> <SolidColorBrush x:Key="Brush.FlatButton.BackgroundHovered" Color="{DynamicResource Color.FlatButton.BackgroundHovered}"/>
<SolidColorBrush x:Key="Brush.FlatButton.PrimaryBackground" Color="{DynamicResource Color.FlatButton.PrimaryBackground}"/>
<SolidColorBrush x:Key="Brush.FlatButton.PrimaryBackgroundHovered" Color="{DynamicResource Color.FlatButton.PrimaryBackgroundHovered}"/>
<SolidColorBrush x:Key="Brush.FG1" Color="{DynamicResource Color.FG1}"/> <SolidColorBrush x:Key="Brush.FG1" Color="{DynamicResource Color.FG1}"/>
<SolidColorBrush x:Key="Brush.FG2" Color="{DynamicResource Color.FG2}"/> <SolidColorBrush x:Key="Brush.FG2" Color="{DynamicResource Color.FG2}"/>
<SolidColorBrush x:Key="Brush.Accent" Color="{DynamicResource SystemAccentColor}"/> <SolidColorBrush x:Key="Brush.Accent" Color="{DynamicResource SystemAccentColor}"/>

View file

@ -133,19 +133,11 @@ namespace SourceGit.ViewModels
diffWithMerger.Icon = App.CreateMenuIcon("Icons.Diff"); diffWithMerger.Icon = App.CreateMenuIcon("Icons.Diff");
diffWithMerger.Click += (_, ev) => diffWithMerger.Click += (_, ev) =>
{ {
var toolType = Preference.Instance.ExternalMergeToolType;
var toolPath = Preference.Instance.ExternalMergeToolPath;
var opt = new Models.DiffOption(Base.Head, To.Head, change); var opt = new Models.DiffOption(Base.Head, To.Head, change);
var type = Preference.Instance.ExternalMergeToolType;
var exec = Preference.Instance.ExternalMergeToolPath;
var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type); Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, opt));
if (tool == null || !File.Exists(exec))
{
App.RaiseException(_repo, "Invalid merge tool in preference setting!");
return;
}
var args = tool.Type != 0 ? tool.DiffCmd : Preference.Instance.ExternalMergeToolDiffCmd;
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, exec, args, opt));
ev.Handled = true; ev.Handled = true;
}; };
menu.Items.Add(diffWithMerger); menu.Items.Add(diffWithMerger);

View file

@ -78,6 +78,6 @@ namespace SourceGit.ViewModels
} }
private readonly Repository _repo = null; private readonly Repository _repo = null;
private Models.DealWithLocalChanges _preAction = Models.DealWithLocalChanges.StashAndReaply; private Models.DealWithLocalChanges _preAction = Models.DealWithLocalChanges.DoNothing;
} }
} }

View file

@ -18,14 +18,6 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
new Commands.GC(_repo.FullPath, SetProgressDescription).Exec(); new Commands.GC(_repo.FullPath, SetProgressDescription).Exec();
var lfs = new Commands.LFS(_repo.FullPath);
if (lfs.IsEnabled())
{
SetProgressDescription("Run LFS prune ...");
lfs.Prune(SetProgressDescription);
}
CallUIThread(() => _repo.SetWatcherEnabled(true)); CallUIThread(() => _repo.SetWatcherEnabled(true));
return true; return true;
}); });

View file

@ -56,6 +56,22 @@ namespace SourceGit.ViewModels
_page = launcher.ActivePage; _page = launcher.ActivePage;
View = new Views.Clone() { DataContext = this }; View = new Views.Clone() { DataContext = this };
App.GetClipboardTextAsync()
.ContinueWith(t =>
{
if (t.IsFaulted)
{
t.Exception.Handle(static _ => true);
}
else if (t.IsCompleted)
{
var result = t.Result;
if (Models.Remote.IsValidURL(result))
{
Remote = result;
}
}
});
} }
public static ValidationResult ValidateRemote(string remote, ValidationContext _) public static ValidationResult ValidateRemote(string remote, ValidationContext _)

View file

@ -201,7 +201,34 @@ namespace SourceGit.ViewModels
}); });
break; break;
case Models.ObjectType.Commit: case Models.ObjectType.Commit:
ViewRevisionFileContent = new Models.RevisionSubmodule() { SHA = file.SHA }; Task.Run(() =>
{
var submoduleRoot = Path.Combine(_repo, file.Path);
var commit = new Commands.QuerySingleCommit(submoduleRoot, file.SHA).Result();
if (commit != null)
{
var body = new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result();
Dispatcher.UIThread.Invoke(() =>
{
ViewRevisionFileContent = new Models.RevisionSubmodule()
{
Commit = commit,
FullMessage = body,
};
});
}
else
{
Dispatcher.UIThread.Invoke(() =>
{
ViewRevisionFileContent = new Models.RevisionSubmodule()
{
Commit = new Models.Commit() { SHA = file.SHA },
FullMessage = string.Empty,
};
});
}
});
break; break;
default: default:
ViewRevisionFileContent = null; ViewRevisionFileContent = null;
@ -218,19 +245,11 @@ namespace SourceGit.ViewModels
diffWithMerger.Icon = App.CreateMenuIcon("Icons.Diff"); diffWithMerger.Icon = App.CreateMenuIcon("Icons.Diff");
diffWithMerger.Click += (_, ev) => diffWithMerger.Click += (_, ev) =>
{ {
var toolType = Preference.Instance.ExternalMergeToolType;
var toolPath = Preference.Instance.ExternalMergeToolPath;
var opt = new Models.DiffOption(_commit, change); var opt = new Models.DiffOption(_commit, change);
var type = Preference.Instance.ExternalMergeToolType;
var exec = Preference.Instance.ExternalMergeToolPath;
var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type); Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, opt));
if (tool == null || !File.Exists(exec))
{
App.RaiseException(_repo, "Invalid merge tool in preference setting!");
return;
}
var args = tool.Type != 0 ? tool.DiffCmd : Preference.Instance.ExternalMergeToolDiffCmd;
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, exec, args, opt));
ev.Handled = true; ev.Handled = true;
}; };
menu.Items.Add(diffWithMerger); menu.Items.Add(diffWithMerger);

View file

@ -138,6 +138,6 @@ namespace SourceGit.ViewModels
private readonly Repository _repo = null; private readonly Repository _repo = null;
private string _name = null; private string _name = null;
private readonly string _baseOnRevision = null; private readonly string _baseOnRevision = null;
private Models.DealWithLocalChanges _preAction = Models.DealWithLocalChanges.StashAndReaply; private Models.DealWithLocalChanges _preAction = Models.DealWithLocalChanges.DoNothing;
} }
} }

View file

@ -98,18 +98,9 @@ namespace SourceGit.ViewModels
public void OpenExternalMergeTool() public void OpenExternalMergeTool()
{ {
var type = Preference.Instance.ExternalMergeToolType; var toolType = Preference.Instance.ExternalMergeToolType;
var exec = Preference.Instance.ExternalMergeToolPath; var toolPath = Preference.Instance.ExternalMergeToolPath;
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, _option));
var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type);
if (tool == null || !File.Exists(exec))
{
App.RaiseException(_repo, "Invalid merge tool in preference setting!");
return;
}
var args = tool.Type != 0 ? tool.DiffCmd : Preference.Instance.ExternalMergeToolDiffCmd;
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, exec, args, _option));
} }
private void LoadDiffContent() private void LoadDiffContent()
@ -219,16 +210,16 @@ namespace SourceGit.ViewModels
return size > 0 ? (new Bitmap(stream), size) : (null, size); return size > 0 ? (new Bitmap(stream), size) : (null, size);
} }
private Models.SubmoduleRevision QuerySubmoduleRevision(string repo, string sha) private Models.RevisionSubmodule QuerySubmoduleRevision(string repo, string sha)
{ {
var commit = new Commands.QuerySingleCommit(repo, sha).Result(); var commit = new Commands.QuerySingleCommit(repo, sha).Result();
if (commit != null) if (commit != null)
{ {
var body = new Commands.QueryCommitFullMessage(repo, sha).Result(); var body = new Commands.QueryCommitFullMessage(repo, sha).Result();
return new Models.SubmoduleRevision() { Commit = commit, FullMessage = body }; return new Models.RevisionSubmodule() { Commit = commit, FullMessage = body };
} }
return new Models.SubmoduleRevision() return new Models.RevisionSubmodule()
{ {
Commit = new Models.Commit() { SHA = sha }, Commit = new Models.Commit() { SHA = sha },
FullMessage = string.Empty, FullMessage = string.Empty,

View file

@ -277,6 +277,18 @@ namespace SourceGit.ViewModels
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(revert); menu.Items.Add(revert);
var interactiveRebase = new MenuItem();
interactiveRebase.Header = new Views.NameHighlightedTextBlock("CommitCM.InteractiveRebase", current.Name);
interactiveRebase.Icon = App.CreateMenuIcon("Icons.InteractiveRebase");
interactiveRebase.IsVisible = current.Head != commit.SHA;
interactiveRebase.Click += (o, e) =>
{
var dialog = new Views.InteractiveRebase() { DataContext = new InteractiveRebase(_repo, current, commit) };
dialog.ShowDialog(App.GetTopLevel() as Window);
e.Handled = true;
};
menu.Items.Add(interactiveRebase);
} }
if (current.Head != commit.SHA) if (current.Head != commit.SHA)

View file

@ -1,4 +1,5 @@
using System.IO; using System.Diagnostics;
using System.IO;
namespace SourceGit.ViewModels namespace SourceGit.ViewModels
{ {
@ -57,12 +58,24 @@ namespace SourceGit.ViewModels
public override bool Continue() public override bool Continue()
{ {
var succ = base.Continue(); var exec = Process.GetCurrentProcess().MainModule.FileName;
var editor = $"\\\"{exec}\\\" --rebase-editor";
var succ = new Commands.Command()
{
WorkingDirectory = Repository,
Context = Repository,
Args = $"-c core.editor=\"{editor}\" rebase --continue",
}.Exec();
if (succ) if (succ)
{ {
var jobsFile = Path.Combine(_gitDir, "sourcegit_rebase_jobs.json");
var rebaseMergeHead = Path.Combine(_gitDir, "REBASE_HEAD"); var rebaseMergeHead = Path.Combine(_gitDir, "REBASE_HEAD");
var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge"); var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge");
var rebaseApplyFolder = Path.Combine(_gitDir, "rebase-apply"); var rebaseApplyFolder = Path.Combine(_gitDir, "rebase-apply");
if (File.Exists(jobsFile))
File.Delete(jobsFile);
if (File.Exists(rebaseMergeHead)) if (File.Exists(rebaseMergeHead))
File.Delete(rebaseMergeHead); File.Delete(rebaseMergeHead);
if (Directory.Exists(rebaseMergeFolder)) if (Directory.Exists(rebaseMergeFolder))

View file

@ -0,0 +1,199 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Avalonia.Collections;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class InteractiveRebaseItem : ObservableObject
{
public Models.Commit Commit
{
get;
private set;
}
public Models.InteractiveRebaseAction Action
{
get => _action;
private set => SetProperty(ref _action, value);
}
public string Subject
{
get => _subject;
private set => SetProperty(ref _subject, value);
}
public string FullMessage
{
get => _fullMessage;
set
{
if (SetProperty(ref _fullMessage, value))
{
var normalized = value.ReplaceLineEndings("\n");
var idx = normalized.IndexOf("\n\n", StringComparison.Ordinal);
if (idx > 0)
Subject = normalized.Substring(0, idx).ReplaceLineEndings(" ");
else
Subject = value.ReplaceLineEndings(" ");
}
}
}
public InteractiveRebaseItem(Models.Commit c, string message)
{
Commit = c;
_subject = c.Subject;
_fullMessage = message;
}
public void SetAction(object param)
{
Action = (Models.InteractiveRebaseAction)param;
}
private Models.InteractiveRebaseAction _action = Models.InteractiveRebaseAction.Pick;
private string _subject = string.Empty;
private string _fullMessage = string.Empty;
}
public class InteractiveRebase : ObservableObject
{
public Models.Branch Current
{
get;
private set;
}
public Models.Commit On
{
get;
private set;
}
public bool IsLoading
{
get => _isLoading;
private set => SetProperty(ref _isLoading, value);
}
public AvaloniaList<InteractiveRebaseItem> Items
{
get;
private set;
} = new AvaloniaList<InteractiveRebaseItem>();
public InteractiveRebaseItem SelectedItem
{
get => _selectedItem;
set
{
if (SetProperty(ref _selectedItem, value))
DetailContext.Commit = value != null ? value.Commit : null;
}
}
public CommitDetail DetailContext
{
get;
private set;
}
public InteractiveRebase(Repository repo, Models.Branch current, Models.Commit on)
{
var repoPath = repo.FullPath;
_repo = repo;
Current = current;
On = on;
IsLoading = true;
DetailContext = new CommitDetail(repoPath);
Task.Run(() =>
{
var commits = new Commands.QueryCommits(repoPath, $"{on.SHA}...HEAD", false).Result();
var messages = new Dictionary<string, string>();
foreach (var c in commits)
{
var fullMessage = new Commands.QueryCommitFullMessage(repoPath, c.SHA).Result();
messages.Add(c.SHA, fullMessage);
}
Dispatcher.UIThread.Invoke(() =>
{
var list = new List<InteractiveRebaseItem>();
foreach (var c in commits)
list.Add(new InteractiveRebaseItem(c, messages[c.SHA]));
Items.AddRange(list);
IsLoading = false;
});
});
}
public void MoveItemUp(InteractiveRebaseItem item)
{
var idx = Items.IndexOf(item);
if (idx > 0)
{
var prev = Items[idx - 1];
Items.RemoveAt(idx - 1);
Items.Insert(idx, prev);
}
}
public void MoveItemDown(InteractiveRebaseItem item)
{
var idx = Items.IndexOf(item);
if (idx < Items.Count - 1)
{
var next = Items[idx + 1];
Items.RemoveAt(idx + 1);
Items.Insert(idx, next);
}
}
public Task<bool> Start()
{
_repo.SetWatcherEnabled(false);
var saveFile = Path.Combine(_repo.GitDir, "sourcegit_rebase_jobs.json");
var jobs = new List<Models.InteractiveRebaseJob>();
for (int i = Items.Count - 1; i >= 0; i--)
{
var item = Items[i];
jobs.Add(new Models.InteractiveRebaseJob()
{
SHA = item.Commit.SHA,
Action = item.Action,
Message = item.FullMessage,
});
}
File.WriteAllText(saveFile, JsonSerializer.Serialize(jobs, JsonCodeGen.Default.ListInteractiveRebaseJob));
return Task.Run(() =>
{
var succ = new Commands.InteractiveRebase(_repo.FullPath, On.SHA).Exec();
if (succ)
File.Delete(saveFile);
Dispatcher.UIThread.Invoke(() => _repo.SetWatcherEnabled(true));
return succ;
});
}
private Repository _repo = null;
private bool _isLoading = false;
private InteractiveRebaseItem _selectedItem = null;
}
}

View file

@ -0,0 +1,27 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class LFSFetch : Popup
{
public LFSFetch(Repository repo)
{
_repo = repo;
View = new Views.LFSFetch() { DataContext = this };
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Fetching LFS objects from remote ...";
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Fetch(SetProgressDescription);
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
}
private readonly Repository _repo = null;
}
}

View file

@ -0,0 +1,73 @@
using System.Threading.Tasks;
using Avalonia.Collections;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class LFSLocks : ObservableObject
{
public bool IsLoading
{
get => _isLoading;
private set => SetProperty(ref _isLoading, value);
}
public bool IsEmpty
{
get => _isEmpty;
private set => SetProperty(ref _isEmpty, value);
}
public AvaloniaList<Models.LFSLock> Locks
{
get;
private set;
}
public LFSLocks(string repo)
{
_repo = repo;
Locks = new AvaloniaList<Models.LFSLock>();
Task.Run(() =>
{
var collect = new Commands.LFS(_repo).Locks();
Dispatcher.UIThread.Invoke(() =>
{
if (collect.Count > 0)
Locks.AddRange(collect);
IsLoading = false;
IsEmpty = collect.Count == 0;
});
});
}
public void Unlock(Models.LFSLock lfsLock, bool force)
{
if (_isLoading)
return;
IsLoading = true;
Task.Run(() =>
{
var succ = new Commands.LFS(_repo).Unlock(lfsLock.ID, force);
Dispatcher.UIThread.Invoke(() =>
{
if (succ)
Locks.Remove(lfsLock);
IsLoading = false;
IsEmpty = Locks.Count == 0;
});
});
}
private string _repo = string.Empty;
private bool _isLoading = true;
private bool _isEmpty = false;
}
}

View file

@ -0,0 +1,28 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class LFSPrune : Popup
{
public LFSPrune(Repository repo)
{
_repo = repo;
View = new Views.LFSPrune() { DataContext = this };
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "LFS prune ...";
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Prune(SetProgressDescription);
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
}
private readonly Repository _repo = null;
}
}

27
src/ViewModels/LFSPull.cs Normal file
View file

@ -0,0 +1,27 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class LFSPull : Popup
{
public LFSPull(Repository repo)
{
_repo = repo;
View = new Views.LFSPull() { DataContext = this };
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Pull LFS objects from remote ...";
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Pull(SetProgressDescription);
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
}
private readonly Repository _repo = null;
}
}

View file

@ -0,0 +1,43 @@
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class LFSTrackCustomPattern : Popup
{
[Required(ErrorMessage = "LFS track pattern is required!!!")]
public string Pattern
{
get => _pattern;
set => SetProperty(ref _pattern, value, true);
}
public bool IsFilename
{
get;
set;
} = false;
public LFSTrackCustomPattern(Repository repo)
{
_repo = repo;
View = new Views.LFSTrackCustomPattern() { DataContext = this };
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding custom LFS tracking pattern ...";
return Task.Run(() =>
{
var succ = new Commands.LFS(_repo.FullPath).Track(_pattern, IsFilename);
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
}
private readonly Repository _repo = null;
private string _pattern = string.Empty;
}
}

View file

@ -134,6 +134,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _maxHistoryCommits, value); set => SetProperty(ref _maxHistoryCommits, value);
} }
public int SubjectGuideLength
{
get => _subjectGuideLength;
set => SetProperty(ref _subjectGuideLength, value);
}
public bool RestoreTabs public bool RestoreTabs
{ {
get => _restoreTabs; get => _restoreTabs;
@ -182,6 +188,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _enableDiffViewWordWrap, value); set => SetProperty(ref _enableDiffViewWordWrap, value);
} }
public bool ShowHiddenSymbolsInDiffView
{
get => _showHiddenSymbolsInDiffView;
set => SetProperty(ref _showHiddenSymbolsInDiffView, value);
}
public Models.ChangeViewMode UnstagedChangeViewMode public Models.ChangeViewMode UnstagedChangeViewMode
{ {
get => _unstagedChangeViewMode; get => _unstagedChangeViewMode;
@ -290,18 +302,6 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _externalMergeToolPath, value); set => SetProperty(ref _externalMergeToolPath, value);
} }
public string ExternalMergeToolCmd
{
get => _externalMergeToolCmd;
set => SetProperty(ref _externalMergeToolCmd, value);
}
public string ExternalMergeToolDiffCmd
{
get => _externalMergeToolDiffCmd;
set => SetProperty(ref _externalMergeToolDiffCmd, value);
}
public List<Repository> Repositories public List<Repository> Repositories
{ {
get; get;
@ -540,13 +540,16 @@ namespace SourceGit.ViewModels
private LayoutInfo _layout = new LayoutInfo(); private LayoutInfo _layout = new LayoutInfo();
private int _maxHistoryCommits = 20000; private int _maxHistoryCommits = 20000;
private int _subjectGuideLength = 50;
private bool _restoreTabs = false; private bool _restoreTabs = false;
private bool _useFixedTabWidth = true; private bool _useFixedTabWidth = true;
private bool _check4UpdatesOnStartup = true; private bool _check4UpdatesOnStartup = true;
private bool _useTwoColumnsLayoutInHistories = false; private bool _useTwoColumnsLayoutInHistories = false;
private bool _useSideBySideDiff = false; private bool _useSideBySideDiff = false;
private bool _useSyntaxHighlighting = false; private bool _useSyntaxHighlighting = false;
private bool _enableDiffViewWordWrap = false; private bool _enableDiffViewWordWrap = false;
private bool _showHiddenSymbolsInDiffView = 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;
@ -556,8 +559,6 @@ namespace SourceGit.ViewModels
private int _externalMergeToolType = 0; private int _externalMergeToolType = 0;
private string _externalMergeToolPath = string.Empty; private string _externalMergeToolPath = string.Empty;
private string _externalMergeToolCmd = string.Empty;
private string _externalMergeToolDiffCmd = string.Empty;
private AvaloniaList<RepositoryNode> _repositoryNodes = new AvaloniaList<RepositoryNode>(); private AvaloniaList<RepositoryNode> _repositoryNodes = new AvaloniaList<RepositoryNode>();
} }

View file

@ -55,9 +55,9 @@ namespace SourceGit.ViewModels
public bool UseRebase public bool UseRebase
{ {
get; get => _repo.PreferRebaseInsteadOfMerge;
set; set => _repo.PreferRebaseInsteadOfMerge = value;
} = true; }
public Pull(Repository repo, Models.Branch specifiedRemoteBranch) public Pull(Repository repo, Models.Branch specifiedRemoteBranch)
{ {
@ -162,6 +162,6 @@ namespace SourceGit.ViewModels
private Models.Remote _selectedRemote = null; private Models.Remote _selectedRemote = null;
private List<Models.Branch> _remoteBranches = null; private List<Models.Branch> _remoteBranches = null;
private Models.Branch _selectedBranch = null; private Models.Branch _selectedBranch = null;
private Models.DealWithLocalChanges _preAction = Models.DealWithLocalChanges.StashAndReaply; private Models.DealWithLocalChanges _preAction = Models.DealWithLocalChanges.DoNothing;
} }
} }

View file

@ -19,27 +19,9 @@ namespace SourceGit.ViewModels
set set
{ {
if (SetProperty(ref _selectedLocalBranch, value)) if (SetProperty(ref _selectedLocalBranch, value))
{
// If selected local branch has upstream branch. Try to find it's remote.
if (!string.IsNullOrEmpty(value.Upstream))
{
var branch = _repo.Branches.Find(x => x.FullName == value.Upstream);
if (branch != null)
{
var remote = _repo.Remotes.Find(x => x.Name == branch.Remote);
if (remote != null && remote != _selectedRemote)
{
SelectedRemote = remote;
return;
}
}
}
// Re-generate remote branches and auto-select remote branches.
AutoSelectBranchByRemote(); AutoSelectBranchByRemote();
} }
} }
}
public List<Models.Branch> LocalBranches public List<Models.Branch> LocalBranches
{ {
@ -73,7 +55,11 @@ namespace SourceGit.ViewModels
public Models.Branch SelectedRemoteBranch public Models.Branch SelectedRemoteBranch
{ {
get => _selectedRemoteBranch; get => _selectedRemoteBranch;
set => SetProperty(ref _selectedRemoteBranch, value); set
{
if (SetProperty(ref _selectedRemoteBranch, value))
IsSetTrackOptionVisible = value != null && _selectedLocalBranch.Upstream != value.FullName;
}
} }
public bool PushAllTags public bool PushAllTags
@ -82,6 +68,12 @@ namespace SourceGit.ViewModels
set; set;
} }
public bool IsSetTrackOptionVisible
{
get => _isSetTrackOptionVisible;
private set => SetProperty(ref _isSetTrackOptionVisible, value);
}
public bool Tracking public bool Tracking
{ {
get; get;
@ -160,7 +152,7 @@ namespace SourceGit.ViewModels
remoteBranchName, remoteBranchName,
PushAllTags, PushAllTags,
ForcePush, ForcePush,
Tracking, _isSetTrackOptionVisible && Tracking,
SetProgressDescription).Exec(); SetProgressDescription).Exec();
CallUIThread(() => _repo.SetWatcherEnabled(true)); CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ; return succ;
@ -218,5 +210,6 @@ namespace SourceGit.ViewModels
private Models.Remote _selectedRemote = null; private Models.Remote _selectedRemote = null;
private List<Models.Branch> _remoteBranches = new List<Models.Branch>(); private List<Models.Branch> _remoteBranches = new List<Models.Branch>();
private Models.Branch _selectedRemoteBranch = null; private Models.Branch _selectedRemoteBranch = null;
private bool _isSetTrackOptionVisible = false;
} }
} }

View file

@ -39,6 +39,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _gitDir, value); set => SetProperty(ref _gitDir, value);
} }
public bool PreferRebaseInsteadOfMerge
{
get;
set;
} = true;
public AvaloniaList<string> Filters public AvaloniaList<string> Filters
{ {
get; get;
@ -404,6 +410,18 @@ namespace SourceGit.ViewModels
PopupHost.ShowPopup(new RepositoryConfigure(this)); PopupHost.ShowPopup(new RepositoryConfigure(this));
} }
public void ClearHistoriesFilter()
{
Filters.Clear();
Task.Run(() =>
{
RefreshBranches();
RefreshTags();
RefreshCommits();
});
}
public void ClearSearchCommitFilter() public void ClearSearchCommitFilter()
{ {
SearchCommitFilter = string.Empty; SearchCommitFilter = string.Empty;
@ -602,9 +620,19 @@ namespace SourceGit.ViewModels
validFilters.Add(filter); validFilters.Add(filter);
} }
} }
if (validFilters.Count > 0) if (validFilters.Count > 0)
{ {
limits += string.Join(" ", validFilters); limits += string.Join(" ", validFilters);
if (Filters.Count != validFilters.Count)
{
Dispatcher.UIThread.Post(() =>
{
Filters.Clear();
Filters.AddRange(validFilters);
});
}
} }
else else
{ {
@ -814,7 +842,7 @@ namespace SourceGit.ViewModels
{ {
var init = new MenuItem(); var init = new MenuItem();
init.Header = App.Text("GitFlow.Init"); init.Header = App.Text("GitFlow.Init");
init.Icon = App.CreateMenuIcon("Icons.GitFlow.Init"); init.Icon = App.CreateMenuIcon("Icons.Init");
init.Click += (o, e) => init.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) if (PopupHost.CanCreatePopup())
@ -826,6 +854,108 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
public ContextMenu CreateContextMenuForGitLFS()
{
var menu = new ContextMenu();
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
var lfs = new Commands.LFS(_fullpath);
if (lfs.IsEnabled())
{
var addPattern = new MenuItem();
addPattern.Header = App.Text("GitLFS.AddTrackPattern");
addPattern.Icon = App.CreateMenuIcon("Icons.File.Add");
addPattern.Click += (o, e) =>
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new LFSTrackCustomPattern(this));
e.Handled = true;
};
menu.Items.Add(addPattern);
menu.Items.Add(new MenuItem() { Header = "-" });
var fetch = new MenuItem();
fetch.Header = App.Text("GitLFS.Fetch");
fetch.Icon = App.CreateMenuIcon("Icons.Fetch");
fetch.IsEnabled = Remotes.Count > 0;
fetch.Click += (o, e) =>
{
if (PopupHost.CanCreatePopup())
{
if (Remotes.Count == 1)
PopupHost.ShowAndStartPopup(new LFSFetch(this));
else
PopupHost.ShowPopup(new LFSFetch(this));
}
e.Handled = true;
};
menu.Items.Add(fetch);
var pull = new MenuItem();
pull.Header = App.Text("GitLFS.Pull");
pull.Icon = App.CreateMenuIcon("Icons.Pull");
pull.IsEnabled = Remotes.Count > 0;
pull.Click += (o, e) =>
{
if (PopupHost.CanCreatePopup())
{
if (Remotes.Count == 1)
PopupHost.ShowAndStartPopup(new LFSPull(this));
else
PopupHost.ShowPopup(new LFSPull(this));
}
e.Handled = true;
};
menu.Items.Add(pull);
var prune = new MenuItem();
prune.Header = App.Text("GitLFS.Prune");
prune.Icon = App.CreateMenuIcon("Icons.Clean");
prune.Click += (o, e) =>
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new LFSPrune(this));
e.Handled = true;
};
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(prune);
var locks = new MenuItem();
locks.Header = App.Text("GitLFS.Locks");
locks.Icon = App.CreateMenuIcon("Icons.Lock");
locks.Click += (o, e) =>
{
var dialog = new Views.LFSLocks() { DataContext = new LFSLocks(_fullpath) };
dialog.Show(App.GetTopLevel() as Window);
e.Handled = true;
};
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(locks);
}
else
{
var install = new MenuItem();
install.Header = App.Text("GitLFS.Install");
install.Icon = App.CreateMenuIcon("Icons.Init");
install.Click += (o, e) =>
{
var succ = new Commands.LFS(_fullpath).Install();
if (succ)
App.SendNotification(_fullpath, $"LFS enabled successfully!");
e.Handled = true;
};
menu.Items.Add(install);
}
return menu;
}
public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch) public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
{ {
var menu = new ContextMenu(); var menu = new ContextMenu();
@ -1058,7 +1188,7 @@ namespace SourceGit.ViewModels
{ {
var tracking = new MenuItem(); var tracking = new MenuItem();
tracking.Header = App.Text("BranchCM.Tracking"); tracking.Header = App.Text("BranchCM.Tracking");
tracking.Icon = App.CreateMenuIcon("Icons.Branch"); tracking.Icon = App.CreateMenuIcon("Icons.Track");
foreach (var b in remoteBranches) foreach (var b in remoteBranches)
{ {
@ -1125,6 +1255,21 @@ namespace SourceGit.ViewModels
{ {
var menu = new ContextMenu(); var menu = new ContextMenu();
if (remote.TryGetVisitURL(out string visitURL))
{
var visit = new MenuItem();
visit.Header = App.Text("RemoteCM.OpenInBrowser");
visit.Icon = App.CreateMenuIcon("Icons.OpenWith");
visit.Click += (o, e) =>
{
Native.OS.OpenBrowser(visitURL);
e.Handled = true;
};
menu.Items.Add(visit);
menu.Items.Add(new MenuItem() { Header = "-" });
}
var fetch = new MenuItem(); var fetch = new MenuItem();
fetch.Header = App.Text("RemoteCM.Fetch"); fetch.Header = App.Text("RemoteCM.Fetch");
fetch.Icon = App.CreateMenuIcon("Icons.Fetch"); fetch.Icon = App.CreateMenuIcon("Icons.Fetch");
@ -1137,7 +1282,7 @@ namespace SourceGit.ViewModels
var prune = new MenuItem(); var prune = new MenuItem();
prune.Header = App.Text("RemoteCM.Prune"); prune.Header = App.Text("RemoteCM.Prune");
prune.Icon = App.CreateMenuIcon("Icons.Clear2"); prune.Icon = App.CreateMenuIcon("Icons.Clean");
prune.Click += (o, e) => prune.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) if (PopupHost.CanCreatePopup())
@ -1393,16 +1538,12 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
public ContextMenu CreateContextMenuForSubmodule(string submodule) public void OpenSubmodule(string submodule)
{
var open = new MenuItem();
open.Header = App.Text("Submodule.Open");
open.Icon = App.CreateMenuIcon("Icons.Folder.Open");
open.Click += (o, ev) =>
{ {
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule)); var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
var gitDir = new Commands.QueryGitDir(root).Result(); var gitDir = new Commands.QueryGitDir(root).Result();
var repo = Preference.AddRepository(root, gitDir); var repo = Preference.AddRepository(root, gitDir);
var node = new RepositoryNode() var node = new RepositoryNode()
{ {
Id = repo.FullPath, Id = repo.FullPath,
@ -1416,7 +1557,16 @@ namespace SourceGit.ViewModels
{ {
launcher.OpenRepositoryInTab(node, null); launcher.OpenRepositoryInTab(node, null);
} }
}
public ContextMenu CreateContextMenuForSubmodule(string submodule)
{
var open = new MenuItem();
open.Header = App.Text("Submodule.Open");
open.Icon = App.CreateMenuIcon("Icons.Folder.Open");
open.Click += (o, ev) =>
{
OpenSubmodule(submodule);
ev.Handled = true; ev.Handled = true;
}; };

View file

@ -52,7 +52,7 @@ namespace SourceGit.ViewModels
UserEmail = email; UserEmail = email;
if (_cached.TryGetValue("commit.gpgsign", out var gpgCommitSign)) if (_cached.TryGetValue("commit.gpgsign", out var gpgCommitSign))
GPGCommitSigningEnabled = gpgCommitSign == "true"; GPGCommitSigningEnabled = gpgCommitSign == "true";
if (_cached.TryGetValue("tag.gpgSign", out var gpgTagSign)) if (_cached.TryGetValue("tag.gpgsign", out var gpgTagSign))
GPGTagSigningEnabled = gpgTagSign == "true"; GPGTagSigningEnabled = gpgTagSign == "true";
if (_cached.TryGetValue("user.signingkey", out var signingKey)) if (_cached.TryGetValue("user.signingkey", out var signingKey))
GPGUserSigningKey = signingKey; GPGUserSigningKey = signingKey;
@ -67,7 +67,7 @@ namespace SourceGit.ViewModels
SetIfChanged("user.name", UserName); SetIfChanged("user.name", UserName);
SetIfChanged("user.email", UserEmail); SetIfChanged("user.email", UserEmail);
SetIfChanged("commit.gpgsign", GPGCommitSigningEnabled ? "true" : "false"); SetIfChanged("commit.gpgsign", GPGCommitSigningEnabled ? "true" : "false");
SetIfChanged("tag.gpgSign", GPGTagSigningEnabled ? "true" : "false"); SetIfChanged("tag.gpgsign", GPGTagSigningEnabled ? "true" : "false");
SetIfChanged("user.signingkey", GPGUserSigningKey); SetIfChanged("user.signingkey", GPGUserSigningKey);
SetIfChanged("http.proxy", HttpProxy); SetIfChanged("http.proxy", HttpProxy);
return null; return null;

View file

@ -142,18 +142,10 @@ namespace SourceGit.ViewModels
diffWithMerger.Click += (_, ev) => diffWithMerger.Click += (_, ev) =>
{ {
var opt = new Models.DiffOption(StartPoint.SHA, _endPoint, change); var opt = new Models.DiffOption(StartPoint.SHA, _endPoint, change);
var type = Preference.Instance.ExternalMergeToolType; var toolType = Preference.Instance.ExternalMergeToolType;
var exec = Preference.Instance.ExternalMergeToolPath; var toolPath = Preference.Instance.ExternalMergeToolPath;
var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type); Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, opt));
if (tool == null || !File.Exists(exec))
{
App.RaiseException(_repo, "Invalid merge tool in preference setting!");
return;
}
var args = tool.Type != 0 ? tool.DiffCmd : Preference.Instance.ExternalMergeToolDiffCmd;
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, exec, args, opt));
ev.Handled = true; ev.Handled = true;
}; };
menu.Items.Add(diffWithMerger); menu.Items.Add(diffWithMerger);

View file

@ -92,6 +92,26 @@ namespace SourceGit.ViewModels
var menu = new ContextMenu(); var menu = new ContextMenu();
var hasRepo = Preference.FindRepository(node.Id) != null; var hasRepo = Preference.FindRepository(node.Id) != null;
if (!node.IsRepository && node.SubNodes.Count > 0)
{
var openAll = new MenuItem();
openAll.Header = App.Text("Welcome.OpenAllInNode");
openAll.Icon = App.CreateMenuIcon("Icons.Folder.Open");
openAll.Click += (_, e) =>
{
if (App.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var launcher = desktop.MainWindow.DataContext as Launcher;
OpenAllInNode(launcher, node);
}
e.Handled = true;
};
menu.Items.Add(openAll);
menu.Items.Add(new MenuItem() { Header = "-" });
}
var edit = new MenuItem(); var edit = new MenuItem();
edit.Header = App.Text("Welcome.Edit"); edit.Header = App.Text("Welcome.Edit");
edit.Icon = App.CreateMenuIcon("Icons.Edit"); edit.Icon = App.CreateMenuIcon("Icons.Edit");
@ -201,6 +221,17 @@ namespace SourceGit.ViewModels
} }
} }
private void OpenAllInNode(Launcher launcher, RepositoryNode node)
{
foreach (var subNode in node.SubNodes)
{
if (subNode.IsRepository)
launcher.OpenRepositoryInTab(subNode, null);
else if (subNode.SubNodes.Count > 0)
OpenAllInNode(launcher, subNode);
}
}
private static Welcome _instance = new Welcome(); private static Welcome _instance = new Welcome();
private string _searchFilter = string.Empty; private string _searchFilter = string.Empty;
} }

View file

@ -131,7 +131,7 @@ namespace SourceGit.ViewModels
} }
else else
{ {
SelectedStaged = null; SelectedStaged = [];
if (value.Count == 1) if (value.Count == 1)
SetDetail(value[0]); SetDetail(value[0]);
@ -156,7 +156,7 @@ namespace SourceGit.ViewModels
} }
else else
{ {
SelectedUnstaged = null; SelectedUnstaged = [];
if (value.Count == 1) if (value.Count == 1)
SetDetail(value[0]); SetDetail(value[0]);
@ -190,29 +190,17 @@ namespace SourceGit.ViewModels
{ {
_repo = null; _repo = null;
if (_selectedUnstaged != null)
{
_selectedUnstaged.Clear(); _selectedUnstaged.Clear();
OnPropertyChanged(nameof(SelectedUnstaged)); OnPropertyChanged(nameof(SelectedUnstaged));
}
if (_selectedStaged != null)
{
_selectedStaged.Clear(); _selectedStaged.Clear();
OnPropertyChanged(nameof(SelectedStaged)); OnPropertyChanged(nameof(SelectedStaged));
}
if (_unstaged != null)
{
_unstaged.Clear(); _unstaged.Clear();
OnPropertyChanged(nameof(Unstaged)); OnPropertyChanged(nameof(Unstaged));
}
if (_staged != null)
{
_staged.Clear(); _staged.Clear();
OnPropertyChanged(nameof(Staged)); OnPropertyChanged(nameof(Staged));
}
_detailContext = null; _detailContext = null;
_commitMessage = string.Empty; _commitMessage = string.Empty;
@ -557,6 +545,8 @@ namespace SourceGit.ViewModels
menu.Items.Add(history); menu.Items.Add(history);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
var extension = Path.GetExtension(change.Path);
var hasExtra = false;
if (change.WorkTree == Models.ChangeState.Untracked) if (change.WorkTree == Models.ChangeState.Untracked)
{ {
var isRooted = change.Path.IndexOf('/', StringComparison.Ordinal) <= 0; var isRooted = change.Path.IndexOf('/', StringComparison.Ordinal) <= 0;
@ -583,7 +573,6 @@ namespace SourceGit.ViewModels
}; };
addToIgnore.Items.Add(byParentFolder); addToIgnore.Items.Add(byParentFolder);
var extension = Path.GetExtension(change.Path);
if (!string.IsNullOrEmpty(extension)) if (!string.IsNullOrEmpty(extension))
{ {
var byExtension = new MenuItem(); var byExtension = new MenuItem();
@ -607,8 +596,82 @@ namespace SourceGit.ViewModels
} }
menu.Items.Add(addToIgnore); menu.Items.Add(addToIgnore);
menu.Items.Add(new MenuItem() { Header = "-" }); hasExtra = true;
} }
var lfsEnabled = new Commands.LFS(_repo.FullPath).IsEnabled();
if (lfsEnabled)
{
var lfs = new MenuItem();
lfs.Header = App.Text("GitLFS");
lfs.Icon = App.CreateMenuIcon("Icons.LFS");
var isLFSFiltered = new Commands.IsLFSFiltered(_repo.FullPath, change.Path).Result();
if (!isLFSFiltered)
{
var filename = Path.GetFileName(change.Path);
var lfsTrackThisFile = new MenuItem();
lfsTrackThisFile.Header = App.Text("GitLFS.Track", filename);
lfsTrackThisFile.Click += async (_, e) =>
{
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Track(filename, true));
if (succ)
App.SendNotification(_repo.FullPath, $"Tracking file named {filename} successfully!");
e.Handled = true;
};
lfs.Items.Add(lfsTrackThisFile);
if (!string.IsNullOrEmpty(extension))
{
var lfsTrackByExtension = new MenuItem();
lfsTrackByExtension.Header = App.Text("GitLFS.TrackByExtension", extension);
lfsTrackByExtension.Click += async (_, e) =>
{
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Track("*" + extension, false));
if (succ)
App.SendNotification(_repo.FullPath, $"Tracking all *{extension} files successfully!");
e.Handled = true;
};
lfs.Items.Add(lfsTrackByExtension);
}
lfs.Items.Add(new MenuItem() { Header = "-" });
}
var lfsLock = new MenuItem();
lfsLock.Header = App.Text("GitLFS.Locks.Lock");
lfsLock.Icon = App.CreateMenuIcon("Icons.Lock");
lfsLock.Click += async (_, e) =>
{
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Lock(change.Path));
if (succ)
App.SendNotification(_repo.FullPath, $"Lock file \"{change.Path}\" successfully!");
e.Handled = true;
};
lfs.Items.Add(lfsLock);
var lfsUnlock = new MenuItem();
lfsUnlock.Header = App.Text("GitLFS.Locks.Unlock");
lfsUnlock.Icon = App.CreateMenuIcon("Icons.Unlock");
lfsUnlock.Click += async (_, e) =>
{
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Unlock(change.Path, false));
if (succ)
App.SendNotification(_repo.FullPath, $"Unlock file \"{change.Path}\" successfully!");
e.Handled = true;
};
lfs.Items.Add(lfsUnlock);
menu.Items.Add(lfs);
hasExtra = true;
}
if (hasExtra)
menu.Items.Add(new MenuItem() { Header = "-" });
} }
var copy = new MenuItem(); var copy = new MenuItem();
@ -702,9 +765,8 @@ namespace SourceGit.ViewModels
stash.Click += (_, e) => stash.Click += (_, e) =>
{ {
if (PopupHost.CanCreatePopup()) if (PopupHost.CanCreatePopup())
{
PopupHost.ShowPopup(new StashChanges(_repo, _selectedUnstaged, false)); PopupHost.ShowPopup(new StashChanges(_repo, _selectedUnstaged, false));
}
e.Handled = true; e.Handled = true;
}; };
@ -797,9 +859,8 @@ namespace SourceGit.ViewModels
stash.Click += (_, e) => stash.Click += (_, e) =>
{ {
if (PopupHost.CanCreatePopup()) if (PopupHost.CanCreatePopup())
{
PopupHost.ShowPopup(new StashChanges(_repo, _selectedStaged, false)); PopupHost.ShowPopup(new StashChanges(_repo, _selectedStaged, false));
}
e.Handled = true; e.Handled = true;
}; };
@ -854,6 +915,45 @@ namespace SourceGit.ViewModels
menu.Items.Add(stash); menu.Items.Add(stash);
menu.Items.Add(patch); menu.Items.Add(patch);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
var lfsEnabled = new Commands.LFS(_repo.FullPath).IsEnabled();
if (lfsEnabled)
{
var lfs = new MenuItem();
lfs.Header = App.Text("GitLFS");
lfs.Icon = App.CreateMenuIcon("Icons.LFS");
var lfsLock = new MenuItem();
lfsLock.Header = App.Text("GitLFS.Locks.Lock");
lfsLock.Icon = App.CreateMenuIcon("Icons.Lock");
lfsLock.Click += async (_, e) =>
{
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Lock(change.Path));
if (succ)
App.SendNotification(_repo.FullPath, $"Lock file \"{change.Path}\" successfully!");
e.Handled = true;
};
lfs.Items.Add(new MenuItem() { Header = "-" });
lfs.Items.Add(lfsLock);
var lfsUnlock = new MenuItem();
lfsUnlock.Header = App.Text("GitLFS.Locks.Unlock");
lfsUnlock.Icon = App.CreateMenuIcon("Icons.Unlock");
lfsUnlock.Click += async (_, e) =>
{
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Unlock(change.Path, false));
if (succ)
App.SendNotification(_repo.FullPath, $"Unlock file \"{change.Path}\" successfully!");
e.Handled = true;
};
lfs.Items.Add(lfsUnlock);
menu.Items.Add(lfs);
menu.Items.Add(new MenuItem() { Header = "-" });
}
menu.Items.Add(copyPath); menu.Items.Add(copyPath);
menu.Items.Add(copyFileName); menu.Items.Add(copyFileName);
} }
@ -1013,20 +1113,11 @@ namespace SourceGit.ViewModels
private async void UseExternalMergeTool(Models.Change change) private async void UseExternalMergeTool(Models.Change change)
{ {
var type = Preference.Instance.ExternalMergeToolType; var toolType = Preference.Instance.ExternalMergeToolType;
var exec = Preference.Instance.ExternalMergeToolPath; var toolPath = Preference.Instance.ExternalMergeToolPath;
var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type);
if (tool == null)
{
App.RaiseException(_repo.FullPath, "Invalid merge tool in preference setting!");
return;
}
var args = tool.Type != 0 ? tool.Cmd : Preference.Instance.ExternalMergeToolCmd;
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, exec, args, change.Path)); await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, toolType, toolPath, change.Path));
_repo.SetWatcherEnabled(true); _repo.SetWatcherEnabled(true);
} }
@ -1107,10 +1198,10 @@ namespace SourceGit.ViewModels
private bool _isCommitting = false; private bool _isCommitting = false;
private bool _useAmend = false; private bool _useAmend = false;
private bool _canCommitWithPush = false; private bool _canCommitWithPush = false;
private List<Models.Change> _unstaged = null; private List<Models.Change> _unstaged = [];
private List<Models.Change> _staged = null; private List<Models.Change> _staged = [];
private List<Models.Change> _selectedUnstaged = null; private List<Models.Change> _selectedUnstaged = [];
private List<Models.Change> _selectedStaged = null; private List<Models.Change> _selectedStaged = [];
private int _count = 0; private int _count = 0;
private object _detailContext = null; private object _detailContext = null;
private string _commitMessage = string.Empty; private string _commitMessage = string.Empty;

View file

@ -32,17 +32,17 @@
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/> <ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
</StackPanel.Resources> </StackPanel.Resources>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}"
GroupName="LocalChanges"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}" <RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}"
GroupName="LocalChanges" GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/> IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}" <RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}"
GroupName="LocalChanges" GroupName="LocalChanges"
Margin="8,0,0,0" Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/> IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}"
GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
</StackPanel> </StackPanel>

View file

@ -25,7 +25,7 @@
</DockPanel> </DockPanel>
<SelectableTextBlock Text="{Binding AuthorTimeStr}" <SelectableTextBlock Text="{Binding AuthorTimeStr}"
Margin="2,0,0,0" Margin="2,0,0,0"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Decrease}}" FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
Foreground="{DynamicResource Brush.FG2}"/> Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
@ -41,7 +41,7 @@
</DockPanel> </DockPanel>
<SelectableTextBlock Text="{Binding CommitterTimeStr}" <SelectableTextBlock Text="{Binding CommitterTimeStr}"
Margin="2,0,0,0" Margin="2,0,0,0"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Decrease}}" FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
Foreground="{DynamicResource Brush.FG2}"/> Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel> </StackPanel>
</Grid> </Grid>

View file

@ -15,6 +15,12 @@ namespace SourceGit.Views
if (DataContext is ViewModels.CommitDetail detail) if (DataContext is ViewModels.CommitDetail detail)
{ {
var datagrid = sender as DataGrid; var datagrid = sender as DataGrid;
if (datagrid.SelectedItem == null)
{
e.Handled = true;
return;
}
detail.ActivePageIndex = 1; detail.ActivePageIndex = 1;
detail.SelectedChanges = new() { datagrid.SelectedItem as Models.Change }; detail.SelectedChanges = new() { datagrid.SelectedItem as Models.Change };
} }

View file

@ -0,0 +1,64 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ae="using:AvaloniaEdit"
xmlns:c="using:SourceGit.Converters"
xmlns:vm="using:SourceGit.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.CommitMessageTextBox"
x:Name="ThisControl">
<Border Background="{DynamicResource Brush.Contents}"
BorderThickness="1"
BorderBrush="{DynamicResource Brush.Border2}"
CornerRadius="4">
<Grid RowDefinitions="*,Auto">
<Grid Grid.Row="0">
<Rectangle x:Name="SubjectGuideLine"
Height="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
IsHitTestVisible="False"
Fill="{DynamicResource Brush.Border2}"/>
<ae:TextEditor x:Name="TextEditor"
Foreground="{DynamicResource Brush.FG1}"
Background="Transparent"
Padding="2,1"
BorderThickness="0"
WordWrap="True"
Document="{Binding #ThisControl.Document}"
TextChanged="OnTextEditorTextChanged"
LayoutUpdated="OnTextEditorLayoutUpdated"/>
<TextBlock Text="{DynamicResource Text.CommitMessageTextBox.Placeholder}"
Foreground="{DynamicResource Brush.FG2}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="2,1"
IsVisible="{Binding #ThisControl.Text, Converter={x:Static StringConverters.IsNullOrEmpty}}"
IsHitTestVisible="False"/>
</Grid>
<Border Grid.Row="1" CornerRadius="0,0,4,4" BorderThickness="0,1,0,0" BorderBrush="{DynamicResource Brush.Border2}" Background="{DynamicResource Brush.Window}" ClipToBounds="True">
<Grid ColumnDefinitions="Auto,*,Auto">
<Border Grid.Column="0" Background="Transparent" Width="16" Height="16" ToolTip.Tip="{DynamicResource Text.CommitMessageTextBox.Tip}">
<Path Height="12" Width="12" Margin="4,0,0,0" Data="{DynamicResource Icons.Info}"/>
</Border>
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="4,2">
<TextBlock Text="Subject:" FontSize="10" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Classes="monospace" Margin="2,0,0,0" FontSize="11" Text="{Binding #ThisControl.SubjectLength}" IsVisible="{Binding #ThisControl.SubjectLength, Converter={x:Static c:IntConverters.IsSubjectLengthGood}}"/>
<TextBlock Classes="monospace" Margin="2,0,0,0" FontSize="11" Foreground="DarkGoldenrod" Text="{Binding #ThisControl.SubjectLength}" IsVisible="{Binding #ThisControl.SubjectLength, Converter={x:Static c:IntConverters.IsSubjectLengthBad}}"/>
<TextBlock Classes="monospace" FontSize="11" Text="/"/>
<TextBlock Classes="monospace" FontSize="11" Text="{Binding Source={x:Static vm:Preference.Instance}, Path=SubjectGuideLength}"/>
<Path Width="10" Height="10" Margin="4,0,0,0" Data="{StaticResource Icons.Error}" Fill="DarkGoldenrod" IsVisible="{Binding #ThisControl.SubjectLength, Converter={x:Static c:IntConverters.IsSubjectLengthBad}}"/>
<TextBlock Margin="8,0,0,0" Text="Total:" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Classes="monospace" Margin="2,0,0,0" FontSize="11" Text="{Binding #ThisControl.Text.Length}"/>
</StackPanel>
</Grid>
</Border>
</Grid>
</Border>
</UserControl>

View file

@ -0,0 +1,103 @@
using System;
using Avalonia;
using Avalonia.Controls;
using AvaloniaEdit.Document;
using AvaloniaEdit.Rendering;
namespace SourceGit.Views
{
public partial class CommitMessageTextBox : UserControl
{
public static readonly StyledProperty<string> TextProperty =
AvaloniaProperty.Register<CommitMessageTextBox, string>(nameof(Text), string.Empty);
public static readonly StyledProperty<int> SubjectLengthProperty =
AvaloniaProperty.Register<CommitMessageTextBox, int>(nameof(SubjectLength));
public string Text
{
get => GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public int SubjectLength
{
get => GetValue(SubjectLengthProperty);
set => SetValue(SubjectLengthProperty, value);
}
public TextDocument Document
{
get;
}
public CommitMessageTextBox()
{
Document = new TextDocument(Text);
InitializeComponent();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == TextProperty && !_isDocumentTextChanging)
Document.Text = Text;
}
private void OnTextEditorLayoutUpdated(object sender, EventArgs e)
{
var view = TextEditor.TextArea?.TextView;
if (view is { VisualLinesValid: true })
{
if (_subjectEndLineNumber == 0)
{
SubjectGuideLine.Margin = new Thickness(1, view.DefaultLineHeight + 2, 1, 0);
SubjectGuideLine.IsVisible = true;
return;
}
foreach (var line in view.VisualLines)
{
var lineNumber = line.FirstDocumentLine.LineNumber;
if (lineNumber == _subjectEndLineNumber)
{
var y = line.GetTextLineVisualYPosition(line.TextLines[^1], VisualYPosition.TextBottom) - view.VerticalOffset + 2;
SubjectGuideLine.Margin = new Thickness(1, y, 1, 0);
SubjectGuideLine.IsVisible = true;
return;
}
}
}
SubjectGuideLine.IsVisible = false;
}
private void OnTextEditorTextChanged(object sender, EventArgs e)
{
_isDocumentTextChanging = true;
SetCurrentValue(TextProperty, Document.Text);
_isDocumentTextChanging = false;
for (var i = 0; i < Document.LineCount; i++)
{
var line = Document.Lines[i];
if (line.LineNumber > 1 && line.Length == 0)
{
var subject = Text[..line.Offset].ReplaceLineEndings(" ").Trim();
SetCurrentValue(SubjectLengthProperty, subject.Length);
return;
}
_subjectEndLineNumber = line.LineNumber;
}
SetCurrentValue(SubjectLengthProperty, Text.ReplaceLineEndings(" ").Trim().Length);
}
private bool _isDocumentTextChanging = false;
private int _subjectEndLineNumber = 0;
}
}

View file

@ -13,7 +13,7 @@
<StackPanel Orientation="Vertical" Margin="8,0"> <StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18" <TextBlock FontSize="18"
Classes="bold" Classes="bold"
Text="{DynamicResource Text.CreateBranch}"/> Text="{DynamicResource Text.CreateBranch.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32" ColumnDefinitions="140,*"> <Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32" ColumnDefinitions="140,*">
<TextBlock Grid.Column="0" <TextBlock Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
@ -54,6 +54,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
CornerRadius="2" CornerRadius="2"
Text="{Binding Name, Mode=TwoWay}" Text="{Binding Name, Mode=TwoWay}"
Watermark="{DynamicResource Text.CreateBranch.Name.Placeholder}"
v:AutoFocusBehaviour.IsEnabled="True"/> v:AutoFocusBehaviour.IsEnabled="True"/>
<TextBlock Grid.Row="2" Grid.Column="0" <TextBlock Grid.Row="2" Grid.Column="0"
@ -65,17 +66,17 @@
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/> <ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
</StackPanel.Resources> </StackPanel.Resources>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}"
GroupName="LocalChanges"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}" <RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}"
GroupName="LocalChanges" GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/> IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}" <RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}"
GroupName="LocalChanges" GroupName="LocalChanges"
Margin="8,0,0,0" Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/> IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}"
GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
</StackPanel> </StackPanel>
<CheckBox Grid.Row="3" Grid.Column="1" <CheckBox Grid.Row="3" Grid.Column="1"

View file

@ -12,13 +12,13 @@
<StackPanel Orientation="Vertical" Margin="8,0,0,0"> <StackPanel Orientation="Vertical" Margin="8,0,0,0">
<TextBlock FontSize="18" <TextBlock FontSize="18"
Classes="bold" Classes="bold"
Text="{DynamicResource Text.CreateTag}"/> Text="{DynamicResource Text.CreateTag.Title}"/>
<Grid Margin="0,16,8,0" RowDefinitions="32,32,32,Auto,Auto,32" ColumnDefinitions="120,*"> <Grid Margin="0,16,8,0" RowDefinitions="32,32,32,Auto,Auto,32" ColumnDefinitions="120,*">
<TextBlock Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
Text="{DynamicResource Text.CreateTag.BasedOn}"/> Text="{DynamicResource Text.CreateTag.BasedOn}"/>
<ContentControl Grid.Column="1" Content="{Binding BasedOn}"> <ContentControl Grid.Row="0" Grid.Column="1" Content="{Binding BasedOn}">
<ContentControl.DataTemplates> <ContentControl.DataTemplates>
<DataTemplate DataType="m:Branch"> <DataTemplate DataType="m:Branch">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
@ -46,6 +46,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
CornerRadius="2" CornerRadius="2"
Text="{Binding TagName, Mode=TwoWay}" Text="{Binding TagName, Mode=TwoWay}"
Watermark="{DynamicResource Text.CreateTag.Name.Placeholder}"
v:AutoFocusBehaviour.IsEnabled="True"/> v:AutoFocusBehaviour.IsEnabled="True"/>
<TextBlock Grid.Row="2" Grid.Column="0" <TextBlock Grid.Row="2" Grid.Column="0"

View file

@ -62,6 +62,14 @@
<Path Width="12" Height="12" Data="{StaticResource Icons.WordWrap}" Margin="0,2,0,0"/> <Path Width="12" Height="12" Data="{StaticResource Icons.WordWrap}" Margin="0,2,0,0"/>
</ToggleButton> </ToggleButton>
<ToggleButton Classes="line_path"
Width="32"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView, Mode=TwoWay}"
IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.ShowHiddenSymbols}">
<Path Width="11" Height="11" Stretch="Uniform" Data="{StaticResource Icons.Whitespace}" Margin="0,1,0,0"/>
</ToggleButton>
<ToggleButton Classes="line_path" <ToggleButton Classes="line_path"
Width="32" Height="18" Width="32" Height="18"
Background="Transparent" Background="Transparent"
@ -151,7 +159,7 @@
<Border IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}"> <Border IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Content="{Binding Old}"> <ContentControl Content="{Binding Old}">
<ContentControl.DataTemplates> <ContentControl.DataTemplates>
<DataTemplate DataType="m:SubmoduleRevision"> <DataTemplate DataType="m:RevisionSubmodule">
<Border Margin="0,0,0,8" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Background="{DynamicResource Brush.Window}"> <Border Margin="0,0,0,8" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Background="{DynamicResource Brush.Window}">
<v:CommitBaseInfo MaxHeight="256" Margin="0,0,0,4" CanNavigate="False" Content="{Binding Commit}" Message="{Binding FullMessage}"/> <v:CommitBaseInfo MaxHeight="256" Margin="0,0,0,4" CanNavigate="False" Content="{Binding Commit}" Message="{Binding FullMessage}"/>
</Border> </Border>
@ -176,60 +184,7 @@
<!-- Image Diff --> <!-- Image Diff -->
<DataTemplate DataType="m:ImageDiff"> <DataTemplate DataType="m:ImageDiff">
<Grid RowDefinitions="Auto,*" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="8,16,8,0"> <v:ImageDiffView/>
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto" HorizontalAlignment="Center">
<Border Grid.Column="0" Height="16" Background="{DynamicResource Brush.Badge}" CornerRadius="8" VerticalAlignment="Center">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.Old}" Margin="8,0" FontSize="10"/>
</Border>
<TextBlock Grid.Column="1" Classes="monospace" Text="{Binding OldImageSize}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="2" Classes="monospace" Text="{Binding OldFileSize}" Foreground="{DynamicResource Brush.FG2}" Margin="16,0,0,0" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="3" Classes="monospace" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
<Border Grid.Column="4" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center" Margin="32,0,0,0">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
</Border>
<TextBlock Grid.Column="5" Classes="monospace" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="6" Classes="monospace" Text="{Binding NewFileSize}" Foreground="{DynamicResource Brush.FG2}" Margin="16,0,0,0" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="7" Classes="monospace" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
</Grid>
<Grid Grid.Row="1" RowDefinitions="*,Auto,Auto" Margin="0,16,0,0" HorizontalAlignment="Center">
<Border Grid.Row="0" Background="{DynamicResource Brush.Window}" Effect="drop-shadow(0 0 8 #A0000000)">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Margin="8">
<v:ImageDiffView Alpha="{Binding #ImageDiffSlider.Value}"
OldImage="{Binding Old}"
NewImage="{Binding New}"
RenderOptions.BitmapInterpolationMode="HighQuality"/>
</Border>
</Border>
<Grid Grid.Row="1" ColumnDefinitions="*,*" Margin="0,8,0,0">
<TextBlock Grid.Column="0" Classes="monospace" Text="{DynamicResource Text.Diff.Binary.Old}" Foreground="{DynamicResource Brush.FG2}" FontSize="10"/>
<TextBlock Grid.Column="1" Classes="monospace" Text="{DynamicResource Text.Diff.Binary.New}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Right" FontSize="10"/>
</Grid>
<Slider Grid.Row="2"
x:Name="ImageDiffSlider"
Minimum="0" Maximum="1"
VerticalAlignment="Top"
TickPlacement="None"
Margin="8,4,8,0"
MinHeight="0"
Foreground="{DynamicResource Brush.Border1}"
Value="0.5">
<Slider.Resources>
<Thickness x:Key="SliderTopHeaderMargin">0,0,0,4</Thickness>
<GridLength x:Key="SliderPreContentMargin">0</GridLength>
<GridLength x:Key="SliderPostContentMargin">0</GridLength>
<CornerRadius x:Key="SliderThumbCornerRadius">8</CornerRadius>
<x:Double x:Key="SliderHorizontalThumbWidth">16</x:Double>
<x:Double x:Key="SliderHorizontalThumbHeight">16</x:Double>
</Slider.Resources>
</Slider>
</Grid>
</Grid>
</DataTemplate> </DataTemplate>
<!-- Text Diff --> <!-- Text Diff -->

View file

@ -1,164 +1,7 @@
using System;
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Styling;
namespace SourceGit.Views namespace SourceGit.Views
{ {
public class ImageDiffView : Control
{
public static readonly StyledProperty<double> AlphaProperty =
AvaloniaProperty.Register<ImageDiffView, double>(nameof(Alpha), 0.5);
public double Alpha
{
get => GetValue(AlphaProperty);
set => SetValue(AlphaProperty, value);
}
public static readonly StyledProperty<Bitmap> OldImageProperty =
AvaloniaProperty.Register<ImageDiffView, Bitmap>(nameof(OldImage), null);
public Bitmap OldImage
{
get => GetValue(OldImageProperty);
set => SetValue(OldImageProperty, value);
}
public static readonly StyledProperty<Bitmap> NewImageProperty =
AvaloniaProperty.Register<ImageDiffView, Bitmap>(nameof(NewImage), null);
public Bitmap NewImage
{
get => GetValue(NewImageProperty);
set => SetValue(NewImageProperty, value);
}
static ImageDiffView()
{
AffectsMeasure<ImageDiffView>(OldImageProperty, NewImageProperty);
AffectsRender<ImageDiffView>(AlphaProperty);
}
public override void Render(DrawingContext context)
{
if (_bgBrush == null)
{
var maskBrush = new SolidColorBrush(ActualThemeVariant == ThemeVariant.Dark ? 0xFF404040 : 0xFFBBBBBB);
var bg = new DrawingGroup()
{
Children =
{
new GeometryDrawing() { Brush = maskBrush, Geometry = new RectangleGeometry(new Rect(0, 0, 12, 12)) },
new GeometryDrawing() { Brush = maskBrush, Geometry = new RectangleGeometry(new Rect(12, 12, 12, 12)) },
}
};
_bgBrush = new DrawingBrush(bg)
{
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top,
DestinationRect = new RelativeRect(new Size(24, 24), RelativeUnit.Absolute),
Stretch = Stretch.None,
TileMode = TileMode.Tile,
};
}
context.FillRectangle(_bgBrush, new Rect(Bounds.Size));
var alpha = Alpha;
var w = Bounds.Width - 16;
var h = Bounds.Height - 16;
var x = w * alpha;
var left = OldImage;
if (left != null && alpha > 0)
{
var src = new Rect(0, 0, left.Size.Width * alpha, left.Size.Height);
var dst = new Rect(8, 8, x, h);
context.DrawImage(left, src, dst);
}
var right = NewImage;
if (right != null && alpha < 1)
{
var src = new Rect(right.Size.Width * alpha, 0, right.Size.Width * (1 - alpha), right.Size.Height);
var dst = new Rect(x + 8, 8, w - x, h);
context.DrawImage(right, src, dst);
}
context.DrawLine(new Pen(Brushes.DarkGreen, 2), new Point(x + 8, 0), new Point(x + 8, Bounds.Height));
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property.Name == "ActualThemeVariant")
{
_bgBrush = null;
InvalidateVisual();
}
}
protected override Size MeasureOverride(Size availableSize)
{
var left = OldImage;
var right = NewImage;
if (left != null)
{
var lSize = GetDesiredSize(left.Size, availableSize);
if (right != null)
{
var rSize = GetDesiredSize(right.Size, availableSize);
if (rSize.Width > lSize.Width)
return rSize;
return lSize;
}
else
{
return lSize;
}
}
else if (right != null)
{
return GetDesiredSize(right.Size, availableSize);
}
else
{
return availableSize;
}
}
private Size GetDesiredSize(Size img, Size available)
{
var w = available.Width - 16;
var h = available.Height - 16;
if (img.Width <= w)
{
if (img.Height <= h)
{
return new Size(img.Width + 16, img.Height + 16);
}
else
{
return new Size(h * img.Width / img.Height + 16, available.Height);
}
}
else
{
var s = Math.Max(img.Width / w, img.Height / h);
return new Size(img.Width / s + 16, img.Height / s + 16);
}
}
private DrawingBrush _bgBrush = null;
}
public partial class DiffView : UserControl public partial class DiffView : UserControl
{ {
public DiffView() public DiffView()

View file

@ -56,7 +56,10 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<DataGrid Grid.Column="0" <DataGrid Grid.Column="0"
Background="Transparent" Background="{DynamicResource Brush.Contents}"
BorderThickness="1"
Margin="8,4,4,8"
BorderBrush="{DynamicResource Brush.Border2}"
ItemsSource="{Binding Commits}" ItemsSource="{Binding Commits}"
SelectedItem="{Binding SelectedCommit, Mode=TwoWay}" SelectedItem="{Binding SelectedCommit, Mode=TwoWay}"
SelectionMode="Single" SelectionMode="Single"
@ -96,15 +99,15 @@
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="Transparent" Background="Transparent"
BorderThickness="1,0,0,0" BorderThickness="1,0,0,0"
BorderBrush="{DynamicResource Brush.Border2}"/> BorderBrush="{DynamicResource Brush.Border0}"/>
<v:LoadingIcon Grid.Column="2" <v:LoadingIcon Grid.Column="2"
Width="48" Height="48" Width="48" Height="48"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsLoading}"/> IsVisible="{Binding IsLoading}"/>
<Grid Grid.Column="2" RowDefinitions="*,3,*" Margin="0,4,4,4" IsVisible="{Binding !IsLoading}"> <Grid Grid.Column="2" RowDefinitions="*,3,*" IsVisible="{Binding !IsLoading}">
<ContentControl Grid.Row="0" Content="{Binding DiffContext}"> <ContentControl Grid.Row="0" Margin="4,4,8,0" Content="{Binding DiffContext}">
<ContentControl.DataTemplates> <ContentControl.DataTemplates>
<DataTemplate DataType="vm:DiffContext"> <DataTemplate DataType="vm:DiffContext">
<v:DiffView/> <v:DiffView/>
@ -117,7 +120,7 @@
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="Transparent"/> Background="Transparent"/>
<Grid Grid.Row="2"> <Grid Grid.Row="2" Margin="0,0,4,4">
<Border Background="{DynamicResource Brush.Window}"> <Border Background="{DynamicResource Brush.Window}">
<Path Width="128" Height="128" <Path Width="128" Height="128"
Data="{StaticResource Icons.Detail}" Data="{StaticResource Icons.Detail}"

View file

@ -90,7 +90,7 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn MaxWidth="100" Header="AUTHOR"> <DataGridTemplateColumn Header="AUTHOR">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type m:Commit}"> <DataTemplate x:DataType="{x:Type m:Commit}">
<TextBlock Classes="monospace" <TextBlock Classes="monospace"

View file

@ -55,7 +55,7 @@
<TextBlock Text="{DynamicResource Text.Hotkeys.Global}" <TextBlock Text="{DynamicResource Text.Hotkeys.Global}"
Foreground="{DynamicResource Brush.FG2}" Foreground="{DynamicResource Brush.FG2}"
FontWeight="Bold" FontWeight="Bold"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Increase}}" FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}"
Margin="0,0,0,8"/> Margin="0,0,0,8"/>
<Grid RowDefinitions="20,20,20,20,20,20" ColumnDefinitions="150,*"> <Grid RowDefinitions="20,20,20,20,20,20" ColumnDefinitions="150,*">
@ -81,7 +81,7 @@
<TextBlock Text="{DynamicResource Text.Hotkeys.Repo}" <TextBlock Text="{DynamicResource Text.Hotkeys.Repo}"
Foreground="{DynamicResource Brush.FG2}" Foreground="{DynamicResource Brush.FG2}"
FontWeight="Bold" FontWeight="Bold"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Increase}}" FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}"
Margin="0,8"/> Margin="0,8"/>
<Grid RowDefinitions="20,20,20,20,20,20,20,20" ColumnDefinitions="150,*"> <Grid RowDefinitions="20,20,20,20,20,20,20,20" ColumnDefinitions="150,*">
@ -113,7 +113,7 @@
<TextBlock Text="{DynamicResource Text.Hotkeys.TextEditor}" <TextBlock Text="{DynamicResource Text.Hotkeys.TextEditor}"
Foreground="{DynamicResource Brush.FG2}" Foreground="{DynamicResource Brush.FG2}"
FontWeight="Bold" FontWeight="Bold"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Increase}}" FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}"
Margin="0,8"/> Margin="0,8"/>
<Grid RowDefinitions="20,20,20,20" ColumnDefinitions="150,*"> <Grid RowDefinitions="20,20,20,20" ColumnDefinitions="150,*">

View file

@ -0,0 +1,182 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.ImageDiffView"
x:DataType="m:ImageDiff">
<TabControl Margin="0,0,0,8" TabStripPlacement="Bottom">
<TabControl.Styles>
<Style Selector="TabControl /template/ ItemsPresenter#PART_ItemsPresenter > WrapPanel">
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</TabControl.Styles>
<TabItem>
<TabItem.Header>
<TextBlock Text="SIDE-BY-SIDE" FontSize="11"/>
</TabItem.Header>
<UniformGrid Rows="1" Margin="0,16" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid RowDefinitions="Auto,*" Margin="16,0" IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center">
<Border Height="16" Background="{DynamicResource Brush.Badge}" CornerRadius="8" VerticalAlignment="Center">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.Old}" Margin="8,0" FontSize="10"/>
</Border>
<TextBlock Classes="monospace" Text="{Binding OldImageSize}" Margin="8,0,0,0"/>
<TextBlock Classes="monospace" Text="{Binding OldFileSize}" Foreground="{DynamicResource Brush.FG2}" Margin="16,0,0,0" HorizontalAlignment="Right"/>
<TextBlock Classes="monospace" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
</StackPanel>
<Border Grid.Row="1" Margin="0,12,0,0" Effect="drop-shadow(0 0 8 #A0000000)">
<Border Background="{DynamicResource Brush.Popup}" HorizontalAlignment="Center" Padding="8">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}">
<Grid>
<v:ImageContainer/>
<Image Source="{Binding Old}" Stretch="Uniform" VerticalAlignment="Center"/>
</Grid>
</Border>
</Border>
</Border>
</Grid>
<Grid RowDefinitions="Auto,*" Margin="16,0" IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center">
<Border Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
</Border>
<TextBlock Classes="monospace" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
<TextBlock Classes="monospace" Text="{Binding NewFileSize}" Foreground="{DynamicResource Brush.FG2}" Margin="16,0,0,0" HorizontalAlignment="Right"/>
<TextBlock Classes="monospace" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
</StackPanel>
<Border Grid.Row="1" Margin="0,12,0,0" Effect="drop-shadow(0 0 8 #A0000000)">
<Border Background="{DynamicResource Brush.Popup}" HorizontalAlignment="Center" Padding="8">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}">
<Grid>
<v:ImageContainer/>
<Image Source="{Binding New}" Stretch="Uniform" VerticalAlignment="Center"/>
</Grid>
</Border>
</Border>
</Border>
</Grid>
</UniformGrid>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Text="SWIPE" FontSize="11"/>
</TabItem.Header>
<Grid RowDefinitions="Auto,*" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="8,16">
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto" HorizontalAlignment="Center">
<Border Grid.Column="0" Height="16" Background="{DynamicResource Brush.Badge}" CornerRadius="8" VerticalAlignment="Center">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.Old}" Margin="8,0" FontSize="10"/>
</Border>
<TextBlock Grid.Column="1" Classes="monospace" Text="{Binding OldImageSize}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="2" Classes="monospace" Text="{Binding OldFileSize}" Foreground="{DynamicResource Brush.FG2}" Margin="16,0,0,0" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="3" Classes="monospace" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
<Border Grid.Column="4" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center" Margin="32,0,0,0">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
</Border>
<TextBlock Grid.Column="5" Classes="monospace" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="6" Classes="monospace" Text="{Binding NewFileSize}" Foreground="{DynamicResource Brush.FG2}" Margin="16,0,0,0" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="7" Classes="monospace" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
</Grid>
<Border Grid.Row="1" Margin="0,12,0,0" Effect="drop-shadow(0 0 8 #A0000000)">
<Border HorizontalAlignment="Center" Background="{DynamicResource Brush.Window}">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Margin="8">
<v:ImagesSwipeControl OldImage="{Binding Old}"
NewImage="{Binding New}"
RenderOptions.BitmapInterpolationMode="HighQuality"/>
</Border>
</Border>
</Border>
</Grid>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Text="BLEND" FontSize="11"/>
</TabItem.Header>
<Grid RowDefinitions="Auto,*,Auto" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="8,16,8,0">
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto" HorizontalAlignment="Center">
<Border Grid.Column="0" Height="16" Background="{DynamicResource Brush.Badge}" CornerRadius="8" VerticalAlignment="Center">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.Old}" Margin="8,0" FontSize="10"/>
</Border>
<TextBlock Grid.Column="1" Classes="monospace" Text="{Binding OldImageSize}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="2" Classes="monospace" Text="{Binding OldFileSize}" Foreground="{DynamicResource Brush.FG2}" Margin="16,0,0,0" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="3" Classes="monospace" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
<Border Grid.Column="4" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center" Margin="32,0,0,0">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
</Border>
<TextBlock Grid.Column="5" Classes="monospace" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="6" Classes="monospace" Text="{Binding NewFileSize}" Foreground="{DynamicResource Brush.FG2}" Margin="16,0,0,0" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="7" Classes="monospace" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
</Grid>
<Border Grid.Row="1" Margin="0,12,0,0" Effect="drop-shadow(0 0 8 #A0000000)">
<Border HorizontalAlignment="Center" Background="{DynamicResource Brush.Window}">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Margin="8">
<v:ImageBlendControl Alpha="{Binding #ImageBlendSlider.Value}"
OldImage="{Binding Old}"
NewImage="{Binding New}"/>
</Border>
</Border>
</Border>
<Grid Grid.Row="2" ColumnDefinitions="100,200,100" Margin="0,12,0,0" HorizontalAlignment="Center">
<StackPanel Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,0,8,0">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.Old}"/>
<TextBlock Classes="monospace"
Margin="8,0,0,0"
Text="{Binding #ImageBlendSlider.Value, Converter={x:Static c:DoubleConverters.OneMinusToPercentage}}"
Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
<Slider Grid.Column="1"
x:Name="ImageBlendSlider"
Minimum="0" Maximum="1"
VerticalAlignment="Top"
TickPlacement="None"
Margin="0"
MinHeight="0"
Foreground="{DynamicResource Brush.Border1}"
Value="0.5">
<Slider.Resources>
<Thickness x:Key="SliderTopHeaderMargin">0,0,0,4</Thickness>
<GridLength x:Key="SliderPreContentMargin">0</GridLength>
<GridLength x:Key="SliderPostContentMargin">0</GridLength>
<CornerRadius x:Key="SliderThumbCornerRadius">8</CornerRadius>
<x:Double x:Key="SliderHorizontalThumbWidth">16</x:Double>
<x:Double x:Key="SliderHorizontalThumbHeight">16</x:Double>
</Slider.Resources>
</Slider>
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Top" Margin="8,0,0,0">
<TextBlock Classes="monospace" Text="{DynamicResource Text.Diff.Binary.New}"/>
<TextBlock Classes="monospace"
Margin="8,0,0,0"
Text="{Binding #ImageBlendSlider.Value, Converter={x:Static c:DoubleConverters.ToPercentage}}"
Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
</Grid>
</Grid>
</TabItem>
</TabControl>
</UserControl>

View file

@ -0,0 +1,318 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Styling;
namespace SourceGit.Views
{
public class ImageContainer : Control
{
public override void Render(DrawingContext context)
{
if (_bgBrush == null)
{
var maskBrush = new SolidColorBrush(ActualThemeVariant == ThemeVariant.Dark ? 0xFF404040 : 0xFFBBBBBB);
var bg = new DrawingGroup()
{
Children =
{
new GeometryDrawing() { Brush = maskBrush, Geometry = new RectangleGeometry(new Rect(0, 0, 12, 12)) },
new GeometryDrawing() { Brush = maskBrush, Geometry = new RectangleGeometry(new Rect(12, 12, 12, 12)) },
}
};
_bgBrush = new DrawingBrush(bg)
{
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top,
DestinationRect = new RelativeRect(new Size(24, 24), RelativeUnit.Absolute),
Stretch = Stretch.None,
TileMode = TileMode.Tile,
};
}
context.FillRectangle(_bgBrush, new Rect(Bounds.Size));
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property.Name == "ActualThemeVariant")
{
_bgBrush = null;
InvalidateVisual();
}
}
private DrawingBrush _bgBrush = null;
}
public class ImagesSwipeControl : ImageContainer
{
public static readonly StyledProperty<double> AlphaProperty =
AvaloniaProperty.Register<ImagesSwipeControl, double>(nameof(Alpha), 0.5);
public double Alpha
{
get => GetValue(AlphaProperty);
set => SetValue(AlphaProperty, value);
}
public static readonly StyledProperty<Bitmap> OldImageProperty =
AvaloniaProperty.Register<ImagesSwipeControl, Bitmap>(nameof(OldImage), null);
public Bitmap OldImage
{
get => GetValue(OldImageProperty);
set => SetValue(OldImageProperty, value);
}
public static readonly StyledProperty<Bitmap> NewImageProperty =
AvaloniaProperty.Register<ImagesSwipeControl, Bitmap>(nameof(NewImage), null);
public Bitmap NewImage
{
get => GetValue(NewImageProperty);
set => SetValue(NewImageProperty, value);
}
static ImagesSwipeControl()
{
AffectsMeasure<ImagesSwipeControl>(OldImageProperty, NewImageProperty);
AffectsRender<ImagesSwipeControl>(AlphaProperty);
}
public override void Render(DrawingContext context)
{
base.Render(context);
var alpha = Alpha;
var w = Bounds.Width;
var h = Bounds.Height;
var x = w * alpha;
var left = OldImage;
if (left != null && alpha > 0)
{
var src = new Rect(0, 0, left.Size.Width * alpha, left.Size.Height);
var dst = new Rect(0, 0, x, h);
context.DrawImage(left, src, dst);
}
var right = NewImage;
if (right != null && alpha < 1)
{
var src = new Rect(right.Size.Width * alpha, 0, right.Size.Width * (1 - alpha), right.Size.Height);
var dst = new Rect(x, 0, w - x, h);
context.DrawImage(right, src, dst);
}
context.DrawLine(new Pen(Brushes.DarkGreen, 2), new Point(x, 0), new Point(x, Bounds.Height));
}
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
var p = e.GetPosition(this);
var hitbox = new Rect(Math.Max(Bounds.Width * Alpha - 2, 0), 0, 4, Bounds.Height);
var pointer = e.GetCurrentPoint(this);
if (pointer.Properties.IsLeftButtonPressed && hitbox.Contains(p))
{
_pressedOnSlider = true;
Cursor = new Cursor(StandardCursorType.SizeWestEast);
e.Pointer.Capture(this);
e.Handled = true;
}
}
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
base.OnPointerReleased(e);
_pressedOnSlider = false;
}
protected override void OnPointerMoved(PointerEventArgs e)
{
var w = Bounds.Width;
var p = e.GetPosition(this);
if (_pressedOnSlider)
{
SetCurrentValue(AlphaProperty, Math.Clamp(p.X, 0, w) / w);
}
else
{
var hitbox = new Rect(Math.Max(w * Alpha - 2, 0), 0, 4, Bounds.Height);
if (hitbox.Contains(p))
{
if (!_lastInSlider)
{
_lastInSlider = true;
Cursor = new Cursor(StandardCursorType.SizeWestEast);
}
}
else
{
if (_lastInSlider)
{
_lastInSlider = false;
Cursor = null;
}
}
}
}
protected override Size MeasureOverride(Size availableSize)
{
var left = OldImage;
var right = NewImage;
if (left == null)
return right == null ? availableSize : GetDesiredSize(right.Size, availableSize);
if (right == null)
return GetDesiredSize(left.Size, availableSize);
var ls = GetDesiredSize(left.Size, availableSize);
var rs = GetDesiredSize(right.Size, availableSize);
return ls.Width > rs.Width ? ls : rs;
}
private Size GetDesiredSize(Size img, Size available)
{
var w = available.Width;
var h = available.Height;
var sw = available.Width / img.Width;
var sh = available.Height / img.Height;
var scale = Math.Min(sw, sh);
return new Size(scale * img.Width, scale * img.Height);
}
private bool _pressedOnSlider = false;
private bool _lastInSlider = false;
}
public class ImageBlendControl : ImageContainer
{
public static readonly StyledProperty<double> AlphaProperty =
AvaloniaProperty.Register<ImageBlendControl, double>(nameof(Alpha), 1.0);
public double Alpha
{
get => GetValue(AlphaProperty);
set => SetValue(AlphaProperty, value);
}
public static readonly StyledProperty<Bitmap> OldImageProperty =
AvaloniaProperty.Register<ImageBlendControl, Bitmap>(nameof(OldImage), null);
public Bitmap OldImage
{
get => GetValue(OldImageProperty);
set => SetValue(OldImageProperty, value);
}
public static readonly StyledProperty<Bitmap> NewImageProperty =
AvaloniaProperty.Register<ImageBlendControl, Bitmap>(nameof(NewImage), null);
public Bitmap NewImage
{
get => GetValue(NewImageProperty);
set => SetValue(NewImageProperty, value);
}
static ImageBlendControl()
{
AffectsMeasure<ImageBlendControl>(OldImageProperty, NewImageProperty);
AffectsRender<ImageBlendControl>(AlphaProperty);
}
public override void Render(DrawingContext context)
{
base.Render(context);
var rect = new Rect(0, 0, Bounds.Width, Bounds.Height);
var alpha = Alpha;
var left = OldImage;
var right = NewImage;
var drawLeft = left != null && alpha < 1.0;
var drawRight = right != null && alpha > 0;
if (drawLeft && drawRight)
{
using (var rt = new RenderTargetBitmap(right.PixelSize, right.Dpi))
{
var rtRect = new Rect(rt.Size);
using (var dc = rt.CreateDrawingContext())
{
using (dc.PushRenderOptions(RO_SRC))
using (dc.PushOpacity(1 - alpha))
dc.DrawImage(left, rtRect);
using (dc.PushRenderOptions(RO_DST))
using (dc.PushOpacity(alpha))
dc.DrawImage(right, rtRect);
}
context.DrawImage(rt, rtRect, rect);
}
}
else if (drawLeft)
{
using (context.PushOpacity(1 - alpha))
context.DrawImage(left, rect);
}
else if (drawRight)
{
using (context.PushOpacity(alpha))
context.DrawImage(right, rect);
}
}
protected override Size MeasureOverride(Size availableSize)
{
var left = OldImage;
var right = NewImage;
if (left == null)
return right == null ? availableSize : GetDesiredSize(right.Size, availableSize);
if (right == null)
return GetDesiredSize(left.Size, availableSize);
var ls = GetDesiredSize(left.Size, availableSize);
var rs = GetDesiredSize(right.Size, availableSize);
return ls.Width > rs.Width ? ls : rs;
}
private Size GetDesiredSize(Size img, Size available)
{
var w = available.Width;
var h = available.Height;
var sw = available.Width / img.Width;
var sh = available.Height / img.Height;
var scale = Math.Min(sw, sh);
return new Size(scale * img.Width, scale * img.Height);
}
private static readonly RenderOptions RO_SRC = new RenderOptions() { BitmapBlendingMode = BitmapBlendingMode.Source, BitmapInterpolationMode = BitmapInterpolationMode.HighQuality };
private static readonly RenderOptions RO_DST = new RenderOptions() { BitmapBlendingMode = BitmapBlendingMode.Plus, BitmapInterpolationMode = BitmapInterpolationMode.HighQuality };
}
public partial class ImageDiffView : UserControl
{
public ImageDiffView()
{
InitializeComponent();
}
}
}

View file

@ -0,0 +1,296 @@
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.InteractiveRebase"
x:DataType="vm:InteractiveRebase"
Icon="/App.ico"
Title="{DynamicResource Text.InteractiveRebase}"
Width="1080" Height="720"
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,*,Auto">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
Margin="10,0,0,0"
Data="{StaticResource Icons.InteractiveRebase}"
IsVisible="{OnPlatform True, macOS=False}"/>
<Grid Grid.Column="0" Classes="caption_button_box" Margin="2,4,0,0" IsVisible="{OnPlatform False, macOS=True}">
<Button Classes="caption_button_macos" Click="CloseWindow">
<Grid>
<Ellipse Fill="{DynamicResource Brush.MacOS.Close}"/>
<Path Height="6" Width="6" Stretch="Fill" Fill="#404040" Stroke="#404040" StrokeThickness="1" Data="{StaticResource Icons.Window.Close}"/>
</Grid>
</Button>
</Grid>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.InteractiveRebase}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<Button Grid.Column="2"
Classes="caption_button"
Click="CloseWindow"
IsVisible="{OnPlatform True, macOS=False}">
<Path Data="{StaticResource Icons.Window.Close}"/>
</Button>
</Grid>
<!-- Operation Information -->
<Grid Grid.Row="1" ColumnDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,*" Margin="8">
<TextBlock Grid.Column="0" Text="{DynamicResource Text.InteractiveRebase.Target}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold"/>
<Path Grid.Column="1" Width="14" Height="14" Margin="8,0,0,0" Data="{StaticResource Icons.Branch}"/>
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding Current, Converter={x:Static c:BranchConverters.ToName}}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="3" Margin="48,0,0,0" Text="{DynamicResource Text.InteractiveRebase.On}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold"/>
<Path Grid.Column="4" Width="14" Height="14" Margin="8,8,0,0" Data="{StaticResource Icons.Commit}"/>
<TextBlock Grid.Column="5" Classes="monospace" VerticalAlignment="Center" Text="{Binding On.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
<TextBlock Grid.Column="6" VerticalAlignment="Center" Text="{Binding On.Subject}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis"/>
</Grid>
<!-- Body -->
<Border Grid.Row="2" Margin="8,0,8,8" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
<Grid RowDefinitions="*,3,*">
<DataGrid Grid.Row="0"
Background="{DynamicResource Brush.Contents}"
ItemsSource="{Binding Items}"
SelectionMode="Single"
SelectedItem="{Binding SelectedItem, Mode=OneWayToSource}"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
DragDrop.AllowDrop="True"
IsReadOnly="True"
HeadersVisibility="None"
Focusable="False"
RowHeight="28"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
KeyDown="OnDataGridKeyDown">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Option">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type vm:InteractiveRebaseItem}">
<Button Opacity="1" Margin="4,0,0,0" Padding="8,2" Background="Transparent">
<Button.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedLeft" VerticalOffset="-4">
<MenuItem InputGesture="P" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Pick}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="Green"/>
</MenuItem.Icon>
<MenuItem.Header>
<Grid ColumnDefinitions="64,240">
<TextBlock Grid.Column="0" Classes="monospace" Margin="4,0" Text="Pick"/>
<TextBlock Grid.Column="1" Text="Use this commit" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="E" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Edit}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="Orange"/>
</MenuItem.Icon>
<MenuItem.Header>
<Grid ColumnDefinitions="64,240">
<TextBlock Grid.Column="0" Classes="monospace" Margin="4,0" Text="Edit"/>
<TextBlock Grid.Column="1" Text="Stop for amending" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="R" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Reword}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="Orange"/>
</MenuItem.Icon>
<MenuItem.Header>
<Grid ColumnDefinitions="64,240">
<TextBlock Grid.Column="0" Classes="monospace" Margin="4,0" Text="Reword"/>
<TextBlock Grid.Column="1" Text="Edit the commit message" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="S" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Squash}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="LightGray"/>
</MenuItem.Icon>
<MenuItem.Header>
<Grid ColumnDefinitions="64,240">
<TextBlock Grid.Column="0" Classes="monospace" Margin="4,0" Text="Squash"/>
<TextBlock Grid.Column="1" Text="Meld into previous commit" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="F" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Fixup}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="LightGray"/>
</MenuItem.Icon>
<MenuItem.Header>
<Grid ColumnDefinitions="64,240">
<TextBlock Grid.Column="0" Classes="monospace" Margin="4,0" Text="Fixup"/>
<TextBlock Grid.Column="1" Text="Like 'Squash' but discard message" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="D" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Drop}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="Red"/>
</MenuItem.Icon>
<MenuItem.Header>
<Grid ColumnDefinitions="64,240">
<TextBlock Grid.Column="0" Classes="monospace" Margin="4,0" Text="Drop"/>
<TextBlock Grid.Column="1" Text="Remove commit" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</MenuItem.Header>
</MenuItem>
</MenuFlyout>
</Button.Flyout>
<StackPanel Orientation="Horizontal">
<Ellipse Width="14" Height="14" Fill="{Binding Action, Converter={x:Static c:InteractiveRebaseActionConverters.ToIconBrush}}"/>
<TextBlock Classes="monospace" Margin="8,0" Text="{Binding Action, Converter={x:Static c:InteractiveRebaseActionConverters.ToName}}"/>
</StackPanel>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="SUBJECT">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type vm:InteractiveRebaseItem}">
<StackPanel Orientation="Horizontal">
<Button Classes="icon_button" IsVisible="{Binding Action, Converter={x:Static c:InteractiveRebaseActionConverters.CanEditMessage}}">
<Button.Flyout>
<Flyout Placement="BottomEdgeAlignedLeft">
<Panel Width="600" Height="120">
<v:CommitMessageTextBox Text="{Binding FullMessage, Mode=TwoWay}"/>
</Panel>
</Flyout>
</Button.Flyout>
<Path Width="14" Height="14" Margin="0,4,0,0" Data="{StaticResource Icons.Edit}"/>
</Button>
<TextBlock Classes="monospace" Text="{Binding Subject}" Margin="8,0,0,0"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="AVATAR">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type vm:InteractiveRebaseItem}">
<v:Avatar Width="16" Height="16"
Margin="16,0,8,0"
VerticalAlignment="Center"
IsHitTestVisible="False"
User="{Binding Commit.Author}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn MaxWidth="100" Header="AUTHOR">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type vm:InteractiveRebaseItem}">
<TextBlock Classes="monospace" Text="{Binding Commit.Author.Name}" Margin="0,0,8,0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="SHA">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type vm:InteractiveRebaseItem}">
<TextBlock Classes="monospace"
Text="{Binding Commit.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
Margin="12,0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="TIME">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type vm:InteractiveRebaseItem}">
<TextBlock Classes="monospace" Text="{Binding Commit.CommitterTimeStr}" Margin="8,0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="32" Header="MOVE UP">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type vm:InteractiveRebaseItem}">
<Button Classes="icon_button" Click="OnMoveItemUp" ToolTip.Tip="{DynamicResource Text.InteractiveRebase.MoveUp}">
<Path Width="14" Height="14" Margin="0,4,0,0" Data="{StaticResource Icons.Up}"/>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="32" Header="MOVE DOWN">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="{x:Type vm:InteractiveRebaseItem}">
<Button Classes="icon_button" Click="OnMoveItemDown" ToolTip.Tip="{DynamicResource Text.InteractiveRebase.MoveDown}">
<Path Width="14" Height="14" Margin="0,4,0,0" Data="{StaticResource Icons.Down}"/>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<v:LoadingIcon Grid.Row="0" Width="48" Height="48" HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="{Binding IsLoading}"/>
<GridSplitter Grid.Row="1"
MinHeight="1"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="Transparent"
BorderThickness="0,1,0,0"
BorderBrush="{DynamicResource Brush.Border2}"/>
<Border Grid.Row="2" Background="{DynamicResource Brush.Window}">
<Path Width="128" Height="128"
Data="{StaticResource Icons.Detail}"
HorizontalAlignment="Center"
Fill="{DynamicResource Brush.FG2}"/>
</Border>
<Grid Grid.Row="2" IsVisible="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Content="{Binding DetailContext}">
<ContentControl.DataTemplates>
<DataTemplate DataType="vm:CommitDetail">
<v:CommitDetail/>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Grid>
</Grid>
</Border>
<!-- Options -->
<Grid Grid.Row="3" ColumnDefinitions="*,Auto,Auto" Margin="8,0,8,8">
<ProgressBar x:Name="Running"
Grid.Column="0"
Margin="0,0,32,0"
Background="{DynamicResource Brush.FG2}"
Foreground="{DynamicResource Brush.Accent}"
Minimum="0"
Maximum="100"
IsVisible="False"/>
<Button Grid.Column="1" Classes="flat primary" MinWidth="80" Content="{DynamicResource Text.Start}" Click="StartJobs"/>
<Button Grid.Column="2" Classes="flat" Margin="8,0,0,0" MinWidth="80" Content="{DynamicResource Text.Cancel}" Click="CloseWindow"/>
</Grid>
</Grid>
</v:ChromelessWindow>

View file

@ -0,0 +1,75 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
{
public partial class InteractiveRebase : ChromelessWindow
{
public InteractiveRebase()
{
InitializeComponent();
}
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object sender, RoutedEventArgs e)
{
Close();
}
private void OnMoveItemUp(object sender, RoutedEventArgs e)
{
if (sender is Control control && DataContext is ViewModels.InteractiveRebase vm)
{
vm.MoveItemUp(control.DataContext as ViewModels.InteractiveRebaseItem);
e.Handled = true;
}
}
private void OnMoveItemDown(object sender, RoutedEventArgs e)
{
if (sender is Control control && DataContext is ViewModels.InteractiveRebase vm)
{
vm.MoveItemDown(control.DataContext as ViewModels.InteractiveRebaseItem);
e.Handled = true;
}
}
private void OnDataGridKeyDown(object sender, KeyEventArgs e)
{
var datagrid = sender as DataGrid;
var item = datagrid.SelectedItem as ViewModels.InteractiveRebaseItem;
if (item == null)
return;
var vm = DataContext as ViewModels.InteractiveRebase;
if (e.Key == Key.P)
item.SetAction(Models.InteractiveRebaseAction.Pick);
else if (e.Key == Key.E)
item.SetAction(Models.InteractiveRebaseAction.Edit);
else if (e.Key == Key.R)
item.SetAction(Models.InteractiveRebaseAction.Reword);
else if (e.Key == Key.S)
item.SetAction(Models.InteractiveRebaseAction.Squash);
else if (e.Key == Key.F)
item.SetAction(Models.InteractiveRebaseAction.Fixup);
else if (e.Key == Key.D)
item.SetAction(Models.InteractiveRebaseAction.Drop);
}
private async void StartJobs(object sender, RoutedEventArgs e)
{
Running.IsVisible = true;
Running.IsIndeterminate = true;
var vm = DataContext as ViewModels.InteractiveRebase;
await vm.Start();
Running.IsIndeterminate = false;
Running.IsVisible = false;
Close();
}
}
}

18
src/Views/LFSFetch.axaml Normal file
View file

@ -0,0 +1,18 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.LFSFetch">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitLFS.Fetch.Title}"/>
<TextBlock Text="{DynamicResource Text.GitLFS.Fetch.Tips}"
Margin="8,16,8,0"
HorizontalAlignment="Center"
TextWrapping="Wrap"/>
</StackPanel>
</UserControl>

View file

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

125
src/Views/LFSLocks.axaml Normal file
View file

@ -0,0 +1,125 @@
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.LFSLocks"
x:DataType="vm:LFSLocks"
Icon="/App.ico"
Title="{DynamicResource Text.GitLFS.Locks.Title}"
Width="600" Height="400"
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
Margin="10,0,0,0"
Data="{StaticResource Icons.Lock}"
IsVisible="{OnPlatform True, macOS=False}"/>
<Grid Grid.Column="0" Classes="caption_button_box" Margin="2,4,0,0" IsVisible="{OnPlatform False, macOS=True}">
<Button Classes="caption_button_macos" Click="CloseWindow">
<Grid>
<Ellipse Fill="{DynamicResource Brush.MacOS.Close}"/>
<Path Height="6" Width="6" Stretch="Fill" Fill="#404040" Stroke="#404040" StrokeThickness="1" Data="{StaticResource Icons.Window.Close}"/>
</Grid>
</Button>
</Grid>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="{DynamicResource Text.GitLFS.Locks.Title}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<Button Grid.Column="2"
Classes="caption_button"
Click="CloseWindow"
IsVisible="{OnPlatform True, macOS=False}">
<Path Data="{StaticResource Icons.Window.Close}"/>
</Button>
</Grid>
<!-- Locked Files -->
<Grid Grid.Row="1">
<DataGrid Margin="8"
Background="{DynamicResource Brush.Contents}"
ItemsSource="{Binding Locks}"
SelectionMode="Single"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
IsReadOnly="True"
HeadersVisibility="None"
Focusable="False"
RowHeight="26"
BorderThickness="1"
BorderBrush="{DynamicResource Brush.Border2}"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTemplateColumn Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Path Width="14" Height="14" Margin="8,0,4,0" Data="{StaticResource Icons.File}"/>
<TextBlock Text="{Binding File}" Margin="4,0"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding User}" Padding="16,0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Classes="icon_button" Click="OnUnlockButtonClicked" ToolTip.Tip="{DynamicResource Text.GitLFS.Locks.Unlock}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Unlock}"/>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Classes="icon_button" Click="OnForceUnlockButtonClicked" ToolTip.Tip="{DynamicResource Text.GitLFS.Locks.UnlockForce}">
<Path Width="14" Height="14" Fill="Red" Data="{StaticResource Icons.Unlock}"/>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<!-- Empty -->
<StackPanel Orientation="Vertical"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsEmpty}">
<Path Width="48" Height="48" Data="{StaticResource Icons.Empty}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Margin="0,16,0,0" Text="{DynamicResource Text.GitLFS.Locks.Empty}" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
<!-- Loading -->
<v:LoadingIcon Width="48" Height="48"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsLoading}"/>
</Grid>
</Grid>
</v:ChromelessWindow>

View file

@ -0,0 +1,40 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
{
public partial class LFSLocks : ChromelessWindow
{
public LFSLocks()
{
InitializeComponent();
}
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object sender, RoutedEventArgs e)
{
Close();
}
private void OnUnlockButtonClicked(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.LFSLocks vm && sender is Button button)
vm.Unlock(button.DataContext as Models.LFSLock, false);
e.Handled = true;
}
private void OnForceUnlockButtonClicked(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.LFSLocks vm && sender is Button button)
vm.Unlock(button.DataContext as Models.LFSLock, true);
e.Handled = true;
}
}
}

16
src/Views/LFSPrune.axaml Normal file
View file

@ -0,0 +1,16 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.LFSPrune">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitLFS.Prune}"/>
<TextBlock Text="{DynamicResource Text.GitLFS.Prune.Tips}"
Margin="8,16,8,0"
HorizontalAlignment="Center"
TextWrapping="Wrap"/>
</StackPanel>
</UserControl>

View file

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

18
src/Views/LFSPull.axaml Normal file
View file

@ -0,0 +1,18 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.LFSPull">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitLFS.Pull.Title}"/>
<TextBlock Text="{DynamicResource Text.GitLFS.Pull.Tips}"
Margin="8,16,8,0"
HorizontalAlignment="Center"
TextWrapping="Wrap"/>
</StackPanel>
</UserControl>

View file

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

View file

@ -0,0 +1,33 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.LFSTrackCustomPattern"
x:DataType="vm:LFSTrackCustomPattern">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitLFS.AddTrackPattern.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="150,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.GitLFS.AddTrackPattern.Pattern}"/>
<TextBox Grid.Row="0" Grid.Column="1"
Height="28"
CornerRadius="3"
Text="{Binding Pattern, Mode=TwoWay}"
v:AutoFocusBehaviour.IsEnabled="True"/>
<CheckBox Grid.Row="1" Grid.Column="1"
Content="{DynamicResource Text.GitLFS.AddTrackPattern.IsFilename}"
IsChecked="{Binding IsFilename, Mode=TwoWay}"/>
</Grid>
</StackPanel>
</UserControl>

View file

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

View file

@ -50,7 +50,7 @@
<MenuFlyout Placement="BottomEdgeAlignedLeft" VerticalOffset="-8"> <MenuFlyout Placement="BottomEdgeAlignedLeft" VerticalOffset="-8">
<MenuItem Header="{DynamicResource Text.Preference}" Command="{x:Static s:App.OpenPreferenceCommand}" InputGesture="Ctrl+Shift+P"> <MenuItem Header="{DynamicResource Text.Preference}" Command="{x:Static s:App.OpenPreferenceCommand}" InputGesture="Ctrl+Shift+P">
<MenuItem.Icon> <MenuItem.Icon>
<Path Width="14" Height="14" Data="{StaticResource Icons.Settings2}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Settings}"/>
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="{DynamicResource Text.Hotkeys}" Command="{x:Static s:App.OpenHotkeysCommand}"> <MenuItem Header="{DynamicResource Text.Hotkeys}" Command="{x:Static s:App.OpenHotkeysCommand}">

View file

@ -258,6 +258,16 @@ namespace SourceGit.Views
private void OnPointerPressedTab(object sender, PointerPressedEventArgs e) private void OnPointerPressedTab(object sender, PointerPressedEventArgs e)
{ {
var border = sender as Border;
var point = e.GetCurrentPoint(border);
if (point.Properties.IsMiddleButtonPressed)
{
var vm = DataContext as ViewModels.Launcher;
vm.CloseTab(border.DataContext as ViewModels.LauncherPage);
e.Handled = true;
return;
}
_pressedTab = true; _pressedTab = true;
_startDragTab = false; _startDragTab = false;
_pressedTabPosition = e.GetPosition(sender as Border); _pressedTabPosition = e.GetPosition(sender as Border);

View file

@ -81,7 +81,6 @@ namespace SourceGit.Views
return; return;
var normalTypeface = new Typeface(FontFamily, FontStyle.Normal, FontWeight.Normal, FontStretch.Normal); var normalTypeface = new Typeface(FontFamily, FontStyle.Normal, FontWeight.Normal, FontStretch.Normal);
//var highlightTypeface = new Typeface(FontFamily, FontStyle.Normal, FontWeight.Bold, FontStretch.Normal);
var underlinePen = new Pen(Foreground, 1); var underlinePen = new Pen(Foreground, 1);
var offsetX = 0.0; var offsetX = 0.0;
@ -99,7 +98,6 @@ namespace SourceGit.Views
part, part,
CultureInfo.CurrentCulture, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight, FlowDirection.LeftToRight,
//isName ? highlightTypeface : normalTypeface,
normalTypeface, normalTypeface,
FontSize, FontSize,
Foreground); Foreground);
@ -107,15 +105,14 @@ namespace SourceGit.Views
if (isName) if (isName)
{ {
var lineY = formatted.Baseline + 2; var lineY = formatted.Baseline + 2;
offsetX += 4;
context.DrawText(formatted, new Point(offsetX, 0)); context.DrawText(formatted, new Point(offsetX, 0));
context.DrawLine(underlinePen, new Point(offsetX, lineY), new Point(offsetX + formatted.Width, lineY)); context.DrawLine(underlinePen, new Point(offsetX, lineY), new Point(offsetX + formatted.Width, lineY));
offsetX += formatted.Width + 4; offsetX += formatted.WidthIncludingTrailingWhitespace;
} }
else else
{ {
context.DrawText(formatted, new Point(offsetX, 0)); context.DrawText(formatted, new Point(offsetX, 0));
offsetX += formatted.Width; offsetX += formatted.WidthIncludingTrailingWhitespace;
} }
isName = !isName; isName = !isName;

View file

@ -18,7 +18,7 @@
<TextBlock x:Name="txtDesc" <TextBlock x:Name="txtDesc"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
TextWrapping="Wrap" TextWrapping="Wrap"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Decrease}}" FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
FontStyle="Italic" FontStyle="Italic"
Text="{Binding #me.Description}"/> Text="{Binding #me.Description}"/>

View file

@ -27,7 +27,7 @@
<Path Grid.Column="0" <Path Grid.Column="0"
Width="14" Height="14" Width="14" Height="14"
Data="{StaticResource Icons.Settings2}" Data="{StaticResource Icons.Settings}"
Margin="10,0,0,0" Margin="10,0,0,0"
IsVisible="{OnPlatform True, macOS=False}"/> IsVisible="{OnPlatform True, macOS=False}"/>
@ -58,7 +58,7 @@
<TabItem.Header> <TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/> <TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/>
</TabItem.Header> </TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32" ColumnDefinitions="Auto,*"> <Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.Locale}" Text="{DynamicResource Text.Preference.General.Locale}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
@ -87,10 +87,23 @@
</ComboBox> </ComboBox>
<TextBlock Grid.Row="2" Grid.Column="0" <TextBlock Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.SubjectGuideLength}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<NumericUpDown Grid.Row="2" Grid.Column="1"
Minimum="50" Maximum="1000" Increment="1"
Height="28"
Padding="4"
ShowButtonSpinner="False"
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
CornerRadius="3"
Value="{Binding SubjectGuideLength, Mode=TwoWay}"/>
<TextBlock Grid.Row="3" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.MaxHistoryCommits}" Text="{DynamicResource Text.Preference.General.MaxHistoryCommits}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Margin="0,0,16,0"/> Margin="0,0,16,0"/>
<Grid Grid.Row="2" Grid.Column="1" ColumnDefinitions="*,64"> <Grid Grid.Row="3" Grid.Column="1" ColumnDefinitions="*,64">
<Slider Grid.Column="0" <Slider Grid.Column="0"
Minimum="20000" Maximum="100000" Minimum="20000" Maximum="100000"
TickPlacement="BottomRight" TickFrequency="5000" TickPlacement="BottomRight" TickFrequency="5000"
@ -114,16 +127,16 @@
Text="{Binding MaxHistoryCommits}"/> Text="{Binding MaxHistoryCommits}"/>
</Grid> </Grid>
<CheckBox Grid.Row="3" Grid.Column="1" <CheckBox Grid.Row="4" Grid.Column="1"
Content="{DynamicResource Text.Preference.General.RestoreTabs}" Content="{DynamicResource Text.Preference.General.RestoreTabs}"
IsChecked="{Binding RestoreTabs, Mode=TwoWay}"/> IsChecked="{Binding RestoreTabs, Mode=TwoWay}"/>
<CheckBox Grid.Row="4" Grid.Column="1" <CheckBox Grid.Row="5" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Preference.General.UseFixedTabWidth}" Content="{DynamicResource Text.Preference.General.UseFixedTabWidth}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFixedTabWidth, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFixedTabWidth, Mode=TwoWay}"/>
<CheckBox Grid.Row="5" Grid.Column="1" <CheckBox Grid.Row="6" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}" Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=Check4UpdatesOnStartup, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=Check4UpdatesOnStartup, Mode=TwoWay}"/>
@ -449,12 +462,12 @@
<TabItem> <TabItem>
<TabItem.Header> <TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.Merger}"/> <TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.DiffMerge}"/>
</TabItem.Header> </TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,Auto,Auto" ColumnDefinitions="Auto,*"> <Grid Margin="8" RowDefinitions="32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.Merger.Type}" Text="{DynamicResource Text.Preference.DiffMerge.Type}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Margin="0,0,16,0"/> Margin="0,0,16,0"/>
<ComboBox Grid.Row="0" Grid.Column="1" <ComboBox Grid.Row="0" Grid.Column="1"
@ -477,41 +490,22 @@
</ComboBox> </ComboBox>
<TextBlock Grid.Row="1" Grid.Column="0" <TextBlock Grid.Row="1" Grid.Column="0"
Text="{DynamicResource Text.Preference.Merger.Path}" Text="{DynamicResource Text.Preference.DiffMerge.Path}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Margin="0,0,16,0"/> Margin="0,0,16,0"
IsVisible="{Binding ExternalMergeToolType, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"/>
<TextBox Grid.Row="1" Grid.Column="1" <TextBox Grid.Row="1" Grid.Column="1"
Height="28" Height="28"
CornerRadius="3" CornerRadius="3"
Text="{Binding ExternalMergeToolPath, Mode=TwoWay}"> Text="{Binding ExternalMergeToolPath, Mode=TwoWay}"
Watermark="{DynamicResource Text.Preference.DiffMerge.Path.Placeholder}"
IsVisible="{Binding ExternalMergeToolType, Converter={x:Static c:IntConverters.IsGreaterThanZero}}">
<TextBox.InnerRightContent> <TextBox.InnerRightContent>
<Button Classes="icon_button" Width="30" Height="30" Click="SelectExternalMergeTool"> <Button Classes="icon_button" Width="30" Height="30" Click="SelectExternalMergeTool">
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/> <Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
</Button> </Button>
</TextBox.InnerRightContent> </TextBox.InnerRightContent>
</TextBox> </TextBox>
<TextBlock Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Preference.Merger.CustomMergeCmd}"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,16,0"
IsVisible="{Binding ExternalMergeToolType, Converter={x:Static c:IntConverters.IsZero}}"/>
<TextBox Grid.Row="2" Grid.Column="1"
Height="28" Margin="0,2"
CornerRadius="3"
Text="{Binding ExternalMergeToolCmd, Mode=TwoWay}"
IsVisible="{Binding ExternalMergeToolType, Converter={x:Static c:IntConverters.IsZero}}"/>
<TextBlock Grid.Row="3" Grid.Column="0"
Text="{DynamicResource Text.Preference.Merger.CustomDiffCmd}"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,16,0"
IsVisible="{Binding ExternalMergeToolType, Converter={x:Static c:IntConverters.IsZero}}"/>
<TextBox Grid.Row="3" Grid.Column="1"
Height="28" Margin="0,2"
CornerRadius="3"
Text="{Binding ExternalMergeToolDiffCmd, Mode=TwoWay}"
IsVisible="{Binding ExternalMergeToolType, Converter={x:Static c:IntConverters.IsZero}}"/>
</Grid> </Grid>
</TabItem> </TabItem>
</TabControl> </TabControl>

View file

@ -43,7 +43,7 @@ namespace SourceGit.Views
{ {
get; get;
set; set;
} } = Models.CRLFMode.Supported[0];
public static readonly StyledProperty<string> GitVersionProperty = public static readonly StyledProperty<string> GitVersionProperty =
AvaloniaProperty.Register<Preference, string>(nameof(GitVersion)); AvaloniaProperty.Register<Preference, string>(nameof(GitVersion));
@ -157,13 +157,13 @@ namespace SourceGit.Views
CRLFMode = Models.CRLFMode.Supported.Find(x => x.Value == crlf); CRLFMode = Models.CRLFMode.Supported.Find(x => x.Value == crlf);
if (config.TryGetValue("commit.gpgsign", out var gpgCommitSign)) if (config.TryGetValue("commit.gpgsign", out var gpgCommitSign))
EnableGPGCommitSigning = (gpgCommitSign == "true"); EnableGPGCommitSigning = (gpgCommitSign == "true");
if (config.TryGetValue("tag.gpgSign", out var gpgTagSign)) if (config.TryGetValue("tag.gpgsign", out var gpgTagSign))
EnableGPGTagSigning = (gpgTagSign == "true"); EnableGPGTagSigning = (gpgTagSign == "true");
if (config.TryGetValue("gpg.format", out var gpgFormat)) if (config.TryGetValue("gpg.format", out var gpgFormat))
GPGFormat = Models.GPGFormat.Supported.Find(x => x.Value == gpgFormat) ?? Models.GPGFormat.Supported[0]; GPGFormat = Models.GPGFormat.Supported.Find(x => x.Value == gpgFormat) ?? Models.GPGFormat.Supported[0];
if (GPGFormat.Value == "opengpg" && config.TryGetValue("gpg.program", out var opengpg)) if (GPGFormat.Value == "openpgp" && config.TryGetValue("gpg.program", out var openpgp))
GPGExecutableFile = opengpg; GPGExecutableFile = openpgp;
else if (config.TryGetValue($"gpg.{GPGFormat.Value}.program", out var gpgProgram)) else if (config.TryGetValue($"gpg.{GPGFormat.Value}.program", out var gpgProgram))
GPGExecutableFile = gpgProgram; GPGExecutableFile = gpgProgram;
@ -174,6 +174,20 @@ namespace SourceGit.Views
GitVersion = ver; GitVersion = ver;
} }
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == GPGFormatProperty)
{
var config = new Commands.Config(null).ListAll();
if (GPGFormat.Value == "openpgp" && config.TryGetValue("gpg.program", out var openpgp))
GPGExecutableFile = openpgp;
else if (config.TryGetValue($"gpg.{GPGFormat.Value}.program", out var gpgProgram))
GPGExecutableFile = gpgProgram;
}
}
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
{ {
BeginMoveDrag(e); BeginMoveDrag(e);
@ -181,34 +195,17 @@ namespace SourceGit.Views
private void CloseWindow(object sender, RoutedEventArgs e) private void CloseWindow(object sender, RoutedEventArgs e)
{ {
var cmd = new Commands.Config(null); var config = new Commands.Config(null).ListAll();
SetIfChanged(config, "user.name", DefaultUser);
SetIfChanged(config, "user.email", DefaultEmail);
SetIfChanged(config, "user.signingkey", GPGUserKey);
SetIfChanged(config, "core.autocrlf", CRLFMode.Value);
SetIfChanged(config, "commit.gpgsign", EnableGPGCommitSigning ? "true" : "false");
SetIfChanged(config, "tag.gpgsign", EnableGPGTagSigning ? "true" : "false");
SetIfChanged(config, "gpg.format", GPGFormat.Value);
var config = cmd.ListAll(); if (!GPGFormat.Value.Equals("ssh", StringComparison.Ordinal))
var oldUser = config.TryGetValue("user.name", out var user) ? user : string.Empty; SetIfChanged(config, $"gpg.{GPGFormat.Value}.program", GPGExecutableFile);
var oldEmail = config.TryGetValue("user.email", out var email) ? email : string.Empty;
var oldGPGSignKey = config.TryGetValue("user.signingkey", out var signingKey) ? signingKey : string.Empty;
var oldCRLF = config.TryGetValue("core.autocrlf", out var crlf) ? crlf : string.Empty;
var oldGPGFormat = config.TryGetValue("gpg.format", out var gpgFormat) ? gpgFormat : "opengpg";
var oldGPGCommitSignEnable = config.TryGetValue("commit.gpgsign", out var gpgCommitSign) ? gpgCommitSign : "false";
var oldGPGTagSignEnable = config.TryGetValue("tag.gpgSign", out var gpgTagSign) ? gpgTagSign : "false";
var oldGPGExec = config.TryGetValue("gpg.program", out var program) ? program : string.Empty;
if (DefaultUser != oldUser)
cmd.Set("user.name", DefaultUser);
if (DefaultEmail != oldEmail)
cmd.Set("user.email", DefaultEmail);
if (GPGUserKey != oldGPGSignKey)
cmd.Set("user.signingkey", GPGUserKey);
if (CRLFMode != null && CRLFMode.Value != oldCRLF)
cmd.Set("core.autocrlf", CRLFMode.Value);
if (EnableGPGCommitSigning != (oldGPGCommitSignEnable == "true"))
cmd.Set("commit.gpgsign", EnableGPGCommitSigning ? "true" : "false");
if (EnableGPGTagSigning != (oldGPGTagSignEnable == "true"))
cmd.Set("tag.gpgSign", EnableGPGTagSigning ? "true" : "false");
if (GPGFormat.Value != oldGPGFormat)
cmd.Set("gpg.format", GPGFormat.Value);
if (GPGExecutableFile != oldGPGExec)
cmd.Set($"gpg.{GPGFormat.Value}.program", GPGExecutableFile);
Close(); Close();
} }
@ -287,6 +284,7 @@ namespace SourceGit.Views
{ {
ViewModels.Preference.Instance.ExternalMergeToolType = 0; ViewModels.Preference.Instance.ExternalMergeToolType = 0;
type = 0; type = 0;
return;
} }
var tool = Models.ExternalMerger.Supported[type]; var tool = Models.ExternalMerger.Supported[type];
@ -302,5 +300,17 @@ namespace SourceGit.Views
ViewModels.Preference.Instance.ExternalMergeToolPath = selected[0].Path.LocalPath; ViewModels.Preference.Instance.ExternalMergeToolPath = selected[0].Path.LocalPath;
} }
} }
private void SetIfChanged(Dictionary<string, string> cached, string key, string value)
{
bool changed = false;
if (cached.TryGetValue(key, out var old))
changed = old != value;
else if (!string.IsNullOrEmpty(value))
changed = true;
if (changed)
new Commands.Config(null).Set(key, value);
}
} }
} }

View file

@ -9,9 +9,9 @@
<StackPanel Orientation="Vertical" Margin="8,0"> <StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18" <TextBlock FontSize="18"
Classes="bold" Classes="bold"
Text="{DynamicResource Text.RemoteCM.Prune}"/> Text="{DynamicResource Text.PruneRemote}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0">
<TextBlock Text="{DynamicResource Text.RemoteCM.Prune.Target}"/> <TextBlock Text="{DynamicResource Text.PruneRemote.Target}"/>
<Path Width="14" Height="14" Margin="8,6,8,0" Data="{StaticResource Icons.Remote}"/> <Path Width="14" Height="14" Margin="8,6,8,0" Data="{StaticResource Icons.Remote}"/>
<TextBlock Text="{Binding Remote.Name}"/> <TextBlock Text="{Binding Remote.Name}"/>
</StackPanel> </StackPanel>

View file

@ -72,17 +72,17 @@
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/> <ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
</StackPanel.Resources> </StackPanel.Resources>
<RadioButton Content="{DynamicResource Text.Pull.LocalChanges.DoNothing}"
GroupName="LocalChanges"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
<RadioButton Content="{DynamicResource Text.Pull.LocalChanges.StashAndReply}" <RadioButton Content="{DynamicResource Text.Pull.LocalChanges.StashAndReply}"
GroupName="LocalChanges" GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/> IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/>
<RadioButton Content="{DynamicResource Text.Pull.LocalChanges.Discard}" <RadioButton Content="{DynamicResource Text.Pull.LocalChanges.Discard}"
GroupName="LocalChanges" GroupName="LocalChanges"
Margin="8,0,0,0" Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/> IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/>
<RadioButton Content="{DynamicResource Text.Pull.LocalChanges.DoNothing}"
GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
</StackPanel> </StackPanel>
<CheckBox Grid.Row="4" Grid.Column="1" <CheckBox Grid.Row="4" Grid.Column="1"

View file

@ -13,7 +13,7 @@
Classes="bold" Classes="bold"
Text="{DynamicResource Text.Push.Title}"/> Text="{DynamicResource Text.Push.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32,32,32" ColumnDefinitions="150,*"> <Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,32,32" ColumnDefinitions="150,*">
<TextBlock Grid.Column="0" <TextBlock Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
@ -73,8 +73,10 @@
</ComboBox> </ComboBox>
<CheckBox Grid.Row="3" Grid.Column="1" <CheckBox Grid.Row="3" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Push.Tracking}" Content="{DynamicResource Text.Push.Tracking}"
IsChecked="{Binding Tracking, Mode=TwoWay}"/> IsChecked="{Binding Tracking, Mode=TwoWay}"
IsVisible="{Binding IsSetTrackOptionVisible}"/>
<CheckBox Grid.Row="4" Grid.Column="1" <CheckBox Grid.Row="4" Grid.Column="1"
Content="{DynamicResource Text.Push.WithAllTags}" Content="{DynamicResource Text.Push.WithAllTags}"

View file

@ -72,6 +72,10 @@
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenGitFlowMenu" ToolTip.Tip="{DynamicResource Text.GitFlow}"> <Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenGitFlowMenu" ToolTip.Tip="{DynamicResource Text.GitFlow}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Flow}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Flow}"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenGitLFSMenu" ToolTip.Tip="{DynamicResource Text.GitLFS}">
<Path Width="14" Height="14" Data="{StaticResource Icons.LFS}"/>
</Button>
</StackPanel> </StackPanel>
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,4,0"> <StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,4,0">
@ -94,7 +98,7 @@
</Button> </Button>
<Button Classes="icon_button" Width="32" Command="{Binding OpenConfigure}" ToolTip.Tip="{DynamicResource Text.Repository.Configure}"> <Button Classes="icon_button" Width="32" Command="{Binding OpenConfigure}" ToolTip.Tip="{DynamicResource Text.Repository.Configure}">
<Path Width="15" Height="15" Data="{StaticResource Icons.Settings1}"/> <Path Width="15" Height="15" Data="{StaticResource Icons.Settings}"/>
</Button> </Button>
</StackPanel> </StackPanel>
</Grid> </Grid>
@ -453,6 +457,7 @@
HorizontalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
ContextRequested="OnSubmoduleContextRequested" ContextRequested="OnSubmoduleContextRequested"
DoubleTapped="OnDoubleTappedSubmodule"
IsVisible="{Binding IsSubmoduleGroupExpanded, Mode=OneWay}"> IsVisible="{Binding IsSubmoduleGroupExpanded, Mode=OneWay}">
<DataGrid.Styles> <DataGrid.Styles>
<Style Selector="DataGridRow"> <Style Selector="DataGridRow">
@ -610,8 +615,8 @@
BorderBrush="{DynamicResource Brush.Border0}"/> BorderBrush="{DynamicResource Brush.Border0}"/>
<!-- Right --> <!-- Right -->
<Grid Grid.Column="2" RowDefinitions="Auto,*"> <Grid Grid.Column="2" RowDefinitions="Auto,Auto,*">
<Grid Grid.Row="0" Height="26" ColumnDefinitions="*,Auto,Auto,Auto" Background="{DynamicResource Brush.Conflict}" IsVisible="{Binding InProgressContext, Converter={x:Static ObjectConverters.IsNotNull}}"> <Grid Grid.Row="0" Height="28" ColumnDefinitions="*,Auto,Auto,Auto" Background="{DynamicResource Brush.Conflict}" IsVisible="{Binding InProgressContext, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Grid.Column="0" Margin="8,0" Content="{Binding InProgressContext}"> <ContentControl Grid.Column="0" Margin="8,0" Content="{Binding InProgressContext}">
<ContentControl.DataTemplates> <ContentControl.DataTemplates>
<DataTemplate DataType="vm:CherryPickInProgress"> <DataTemplate DataType="vm:CherryPickInProgress">
@ -632,17 +637,68 @@
</ContentControl.DataTemplates> </ContentControl.DataTemplates>
</ContentControl> </ContentControl>
<Button Grid.Column="1" Classes="flat" FontWeight="Regular" Content="{DynamicResource Text.Repository.Resolve}" Height="20" Padding="8,0" Margin="4,0" Command="{Binding GotoResolve}"> <Button Grid.Column="1"
Classes="flat"
FontWeight="Regular"
BorderThickness="0"
Content="{DynamicResource Text.Repository.Resolve}"
Padding="8,0" Margin="4,0"
Command="{Binding GotoResolve}">
<Button.IsVisible> <Button.IsVisible>
<Binding Path="SelectedViewIndex" Converter="{x:Static c:IntConverters.IsNotOne}"/> <Binding Path="SelectedViewIndex" Converter="{x:Static c:IntConverters.IsNotOne}"/>
</Button.IsVisible> </Button.IsVisible>
</Button> </Button>
<Button Grid.Column="2"
<Button Grid.Column="2" Classes="flat primary" FontWeight="Regular" Content="{DynamicResource Text.Repository.Continue}" Height="20" Padding="8,0" Margin="4,0" Command="{Binding ContinueMerge}" IsVisible="{Binding !HasUnsolvedConflicts}"/> Classes="flat primary"
<Button Grid.Column="3" Classes="flat" FontWeight="Regular" Content="{DynamicResource Text.Repository.Abort}" Height="20" Padding="8,0" Margin="4,0" Command="{Binding AbortMerge}"/> FontWeight="Regular"
BorderThickness="0"
Content="{DynamicResource Text.Repository.Continue}"
Padding="8,0" Margin="4,0"
Command="{Binding ContinueMerge}"
IsVisible="{Binding !HasUnsolvedConflicts}"/>
<Button Grid.Column="3"
Classes="flat"
FontWeight="Regular"
BorderThickness="0"
Content="{DynamicResource Text.Repository.Abort}"
Padding="8,0" Margin="4,0"
Command="{Binding AbortMerge}"/>
</Grid> </Grid>
<ContentControl Grid.Row="1" Content="{Binding SelectedView}"> <Border Grid.Row="1" Background="{DynamicResource Brush.Window}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
<Border.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="SelectedViewIndex" Converter="{x:Static c:IntConverters.IsZero}"/>
<Binding Path="Filters.Count" Converter="{x:Static c:IntConverters.IsGreaterThanZero}"/>
</MultiBinding>
</Border.IsVisible>
<Grid Height="28" ColumnDefinitions="Auto,*,Auto">
<TextBlock Grid.Column="0" Margin="8,0,0,0" Classes="info_label" Text="{DynamicResource Text.Repository.FilterCommitPrefix}"/>
<ItemsControl Grid.Column="1" Margin="8,0,0,0" ItemsSource="{Binding Filters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" VerticalAlignment="Center"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Height="20" Margin="0,0,6,0" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}" CornerRadius="12">
<TextBlock Classes="monospace" Text="{Binding Converter={x:Static c:StringConverters.TrimRefsPrefix}}" Margin="8,0"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Grid.Column="2" Classes="icon_button" Command="{Binding ClearHistoriesFilter}">
<TextBlock Margin="16,0,8,0" Text="{DynamicResource Text.Repository.ClearAllCommitsFilter}" Foreground="{DynamicResource Brush.Accent}"/>
</Button>
</Grid>
</Border>
<ContentControl Grid.Row="2" Content="{Binding SelectedView}">
<ContentControl.DataTemplates> <ContentControl.DataTemplates>
<DataTemplate DataType="vm:Histories"> <DataTemplate DataType="vm:Histories">
<v:Histories NavigationId="{Binding NavigationId}"/> <v:Histories NavigationId="{Binding NavigationId}"/>

View file

@ -37,6 +37,17 @@ namespace SourceGit.Views
e.Handled = true; e.Handled = true;
} }
private void OpenGitLFSMenu(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForGitLFS();
(sender as Control)?.OpenContextMenu(menu);
}
e.Handled = true;
}
private async void OpenStatistics(object sender, RoutedEventArgs e) private async void OpenStatistics(object sender, RoutedEventArgs e)
{ {
if (DataContext is ViewModels.Repository repo) if (DataContext is ViewModels.Repository repo)
@ -321,5 +332,16 @@ namespace SourceGit.Views
outs.Add(b); outs.Add(b);
} }
} }
private void OnDoubleTappedSubmodule(object sender, TappedEventArgs e)
{
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo)
{
var submodule = datagrid.SelectedItem as string;
(DataContext as ViewModels.Repository).OpenSubmodule(submodule);
}
e.Handled = true;
}
} }
} }

View file

@ -2,11 +2,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ae="using:AvaloniaEdit"
xmlns:m="using:SourceGit.Models" xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels" xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views" xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.RevisionFiles" x:Class="SourceGit.Views.RevisionFiles"
x:DataType="vm:CommitDetail"> x:DataType="vm:CommitDetail">
@ -58,9 +56,14 @@
</DataTemplate> </DataTemplate>
<DataTemplate DataType="m:RevisionImageFile"> <DataTemplate DataType="m:RevisionImageFile">
<Border Background="{DynamicResource Brush.Window}" Effect="drop-shadow(0 0 8 #A0000000)" Margin="0,8" VerticalAlignment="Center" HorizontalAlignment="Center"> <Border Margin="0,8" VerticalAlignment="Center" HorizontalAlignment="Center" Effect="drop-shadow(0 0 8 #A0000000)">
<Border Background="{DynamicResource Brush.Window}">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Margin="8"> <Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Margin="8">
<v:RevisionImageFileView Source="{Binding Image}" RenderOptions.BitmapInterpolationMode="HighQuality"/> <Grid>
<v:ImageContainer/>
<Image Source="{Binding Image}" Stretch="Uniform" VerticalAlignment="Center" RenderOptions.BitmapInterpolationMode="HighQuality"/>
</Grid>
</Border>
</Border> </Border>
</Border> </Border>
</DataTemplate> </DataTemplate>
@ -78,10 +81,9 @@
</DataTemplate> </DataTemplate>
<DataTemplate DataType="m:RevisionSubmodule"> <DataTemplate DataType="m:RevisionSubmodule">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Margin="8,8,8,0">
<TextBlock Text="{DynamicResource Text.CommitDetail.Files.Submodule}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/> <TextBlock Text="{DynamicResource Text.CommitDetail.Files.Submodule}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<Path Width="64" Height="64" Margin="0,16,0,0" Data="{StaticResource Icons.Submodule}" Fill="{DynamicResource Brush.FG2}"/> <v:CommitBaseInfo Margin="0,16,0,0" CanNavigate="False" Content="{Binding Commit}" Message="{Binding FullMessage}"/>
<SelectableTextBlock Margin="0,16,0,0" Text="{Binding SHA}" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</ContentControl.DataTemplates> </ContentControl.DataTemplates>

View file

@ -59,7 +59,7 @@ namespace SourceGit.Views
disposable.Dispose(); disposable.Dispose();
var vm = DataContext as ViewModels.CommitDetail; var vm = DataContext as ViewModels.CommitDetail;
if (vm == null) if (vm == null || vm.Commit == null)
{ {
Content = null; Content = null;
GC.Collect(); GC.Collect();
@ -164,90 +164,6 @@ namespace SourceGit.Views
} }
} }
public class RevisionImageFileView : Control
{
public static readonly StyledProperty<Bitmap> SourceProperty =
AvaloniaProperty.Register<RevisionImageFileView, Bitmap>(nameof(Source), null);
public Bitmap Source
{
get => GetValue(SourceProperty);
set => SetValue(SourceProperty, value);
}
static RevisionImageFileView()
{
AffectsMeasure<RevisionImageFileView>(SourceProperty);
}
public override void Render(DrawingContext context)
{
if (_bgBrush == null)
{
var maskBrush = new SolidColorBrush(ActualThemeVariant == ThemeVariant.Dark ? 0xFF404040 : 0xFFBBBBBB);
var bg = new DrawingGroup()
{
Children =
{
new GeometryDrawing() { Brush = maskBrush, Geometry = new RectangleGeometry(new Rect(0, 0, 12, 12)) },
new GeometryDrawing() { Brush = maskBrush, Geometry = new RectangleGeometry(new Rect(12, 12, 12, 12)) },
}
};
_bgBrush = new DrawingBrush(bg)
{
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top,
DestinationRect = new RelativeRect(new Size(24, 24), RelativeUnit.Absolute),
Stretch = Stretch.None,
TileMode = TileMode.Tile,
};
}
context.FillRectangle(_bgBrush, new Rect(Bounds.Size));
var source = Source;
if (source != null)
context.DrawImage(source, new Rect(source.Size), new Rect(8, 8, Bounds.Width - 16, Bounds.Height - 16));
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property.Name == "ActualThemeVariant")
{
_bgBrush = null;
InvalidateVisual();
}
}
protected override Size MeasureOverride(Size availableSize)
{
var source = Source;
if (source == null)
return availableSize;
var w = availableSize.Width - 16;
var h = availableSize.Height - 16;
var size = source.Size;
if (size.Width <= w)
{
if (size.Height <= h)
return new Size(size.Width + 16, size.Height + 16);
else
return new Size(h * size.Width / size.Height + 16, availableSize.Height);
}
else
{
var scale = Math.Max(size.Width / w, size.Height / h);
return new Size(size.Width / scale + 16, size.Height / scale + 16);
}
}
private DrawingBrush _bgBrush = null;
}
public class RevisionTextFileView : TextEditor public class RevisionTextFileView : TextEditor
{ {
protected override Type StyleKeyOverride => typeof(TextEditor); protected override Type StyleKeyOverride => typeof(TextEditor);

View file

@ -30,7 +30,7 @@
Padding="0" Padding="0"
Command="{Binding Clear}" Command="{Binding Clear}"
IsEnabled="{Binding Stashes.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"> IsEnabled="{Binding Stashes.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Clear2}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Clean}"/>
</Button> </Button>
</Grid> </Grid>
</Border> </Border>

View file

@ -76,8 +76,13 @@
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent"/>
</Style> </Style>
<Style Selector="ListBoxItem Border.switcher_bg">
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border2}"/>
</Style>
<Style Selector="ListBoxItem:selected Border.switcher_bg"> <Style Selector="ListBoxItem:selected Border.switcher_bg">
<Setter Property="Background" Value="{DynamicResource Brush.Contents}"/> <Setter Property="Background" Value="{DynamicResource Brush.Accent}"/>
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
</Style> </Style>
<Style Selector="TextBlock.view_mode_switcher"> <Style Selector="TextBlock.view_mode_switcher">
@ -86,24 +91,24 @@
</Style> </Style>
<Style Selector="ListBoxItem:selected TextBlock.view_mode_switcher"> <Style Selector="ListBoxItem:selected TextBlock.view_mode_switcher">
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/> <Setter Property="Foreground" Value="White"/>
</Style> </Style>
</ListBox.Styles> </ListBox.Styles>
<ListBoxItem> <ListBoxItem>
<Border Classes="switcher_bg" Height="28" Padding="16,0" BorderThickness="1,1,0,1" BorderBrush="{DynamicResource Brush.Border1}" CornerRadius="14,0,0,14"> <Border Classes="switcher_bg" Height="28" Padding="16,0" BorderThickness="1,1,0,1" CornerRadius="14,0,0,14">
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.Statistics.ThisYear}"/> <TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.Statistics.ThisYear}"/>
</Border> </Border>
</ListBoxItem> </ListBoxItem>
<ListBoxItem> <ListBoxItem>
<Border Classes="switcher_bg" Height="28" Padding="16,0" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"> <Border Classes="switcher_bg" Height="28" Padding="16,0" BorderThickness="1">
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.Statistics.ThisMonth}"/> <TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.Statistics.ThisMonth}"/>
</Border> </Border>
</ListBoxItem> </ListBoxItem>
<ListBoxItem> <ListBoxItem>
<Border Classes="switcher_bg" Height="28" Padding="16,0" BorderThickness="0,1,1,1" BorderBrush="{DynamicResource Brush.Border1}" CornerRadius="0,14,14,0"> <Border Classes="switcher_bg" Height="28" Padding="16,0" BorderThickness="0,1,1,1" CornerRadius="0,14,14,0">
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.Statistics.ThisWeek}"/> <TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.Statistics.ThisWeek}"/>
</Border> </Border>
</ListBoxItem> </ListBoxItem>
@ -125,12 +130,32 @@
HeadersVisibility="Column" HeadersVisibility="Column"
GridLinesVisibility="All" GridLinesVisibility="All"
BorderThickness="1" BorderThickness="1"
BorderBrush="{DynamicResource Brush.Border1}" BorderBrush="{DynamicResource Brush.Border2}"
Background="{DynamicResource Brush.Contents}" Background="{DynamicResource Brush.Contents}"
HorizontalGridLinesBrush="{DynamicResource Brush.Border2}"
VerticalGridLinesBrush="{DynamicResource Brush.Border2}"
IsReadOnly="True" IsReadOnly="True"
RowHeight="26" RowHeight="26"
HorizontalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"> VerticalScrollBarVisibility="Auto">
<DataGrid.Styles>
<Style Selector="DataGridColumnHeader">
<Setter Property="Background" Value="{DynamicResource Brush.Window}"/>
<Setter Property="Padding" Value="8,0,0,0"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border2}"/>
<Setter Property="SeparatorBrush" Value="{DynamicResource Brush.Border2}" />
<Style Selector="^:pointerover /template/ Grid#PART_ColumnHeaderRoot">
<Setter Property="Background" Value="{DynamicResource Brush.Window}"/>
</Style>
<Style Selector="^:pressed /template/ Grid#PART_ColumnHeaderRoot">
<Setter Property="Background" Value="{DynamicResource Brush.Window}"/>
</Style>
</Style>
</DataGrid.Styles>
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Width="150" Header="{DynamicResource Text.Statistics.Committer}" Binding="{Binding Name}"/> <DataGridTextColumn Width="150" Header="{DynamicResource Text.Statistics.Committer}" Binding="{Binding Name}"/>
<DataGridTextColumn Width="*" Header="{DynamicResource Text.Statistics.CommitAmount}" Binding="{Binding Count}"/> <DataGridTextColumn Width="*" Header="{DynamicResource Text.Statistics.CommitAmount}" Binding="{Binding Count}"/>
@ -156,7 +181,8 @@
<!-- Graph --> <!-- Graph -->
<v:Chart Grid.Column="1" <v:Chart Grid.Column="1"
Margin="16,0,0,0" Margin="16,0,0,0"
LineBrush="{DynamicResource Brush.Border1}" LabelBrush="{DynamicResource Brush.FG1}"
LineBrush="{DynamicResource Brush.Border2}"
ShapeBrush="{DynamicResource Brush.Accent}" ShapeBrush="{DynamicResource Brush.Accent}"
Samples="{Binding Samples}"/> Samples="{Binding Samples}"/>
</Grid> </Grid>

View file

@ -12,6 +12,15 @@ namespace SourceGit.Views
{ {
public class Chart : Control public class Chart : Control
{ {
public static readonly StyledProperty<IBrush> LabelBrushProperty =
AvaloniaProperty.Register<Chart, IBrush>(nameof(LabelBrush), Brushes.Black);
public IBrush LabelBrush
{
get => GetValue(LabelBrushProperty);
set => SetValue(LabelBrushProperty, value);
}
public static readonly StyledProperty<IBrush> LineBrushProperty = public static readonly StyledProperty<IBrush> LineBrushProperty =
AvaloniaProperty.Register<Chart, IBrush>(nameof(LineBrush), Brushes.Gray); AvaloniaProperty.Register<Chart, IBrush>(nameof(LineBrush), Brushes.Gray);
@ -63,33 +72,19 @@ namespace SourceGit.Views
} }
if (maxV < 5) if (maxV < 5)
{
maxV = 5; maxV = 5;
}
else if (maxV < 10) else if (maxV < 10)
{
maxV = 10; maxV = 10;
}
else if (maxV < 50) else if (maxV < 50)
{
maxV = 50; maxV = 50;
}
else if (maxV < 100) else if (maxV < 100)
{
maxV = 100; maxV = 100;
}
else if (maxV < 200) else if (maxV < 200)
{
maxV = 200; maxV = 200;
}
else if (maxV < 500) else if (maxV < 500)
{
maxV = 500; maxV = 500;
}
else else
{
maxV = (int)Math.Ceiling(maxV / 500.0) * 500; maxV = (int)Math.Ceiling(maxV / 500.0) * 500;
}
var typeface = new Typeface("fonts:SourceGit#JetBrains Mono"); var typeface = new Typeface("fonts:SourceGit#JetBrains Mono");
var pen = new Pen(LineBrush, 1); var pen = new Pen(LineBrush, 1);
@ -100,7 +95,7 @@ namespace SourceGit.Views
context.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width, height)); context.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width, height));
// Draw coordinate // Draw coordinate
var maxLabel = new FormattedText($"{maxV}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12.0, LineBrush); var maxLabel = new FormattedText($"{maxV}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12.0, LabelBrush);
var horizonStart = maxLabel.Width + 8; var horizonStart = maxLabel.Width + 8;
var labelHeight = maxLabel.Height; var labelHeight = maxLabel.Height;
context.DrawText(maxLabel, new Point(0, -maxLabel.Height * 0.5)); context.DrawText(maxLabel, new Point(0, -maxLabel.Height * 0.5));
@ -122,7 +117,7 @@ namespace SourceGit.Views
FlowDirection.LeftToRight, FlowDirection.LeftToRight,
typeface, typeface,
12.0, 12.0,
LineBrush); LabelBrush);
var dashHeight = i * stepV; var dashHeight = i * stepV;
var vy = Math.Max(0, dashHeight - vLabel.Height * 0.5); var vy = Math.Max(0, dashHeight - vLabel.Height * 0.5);
@ -155,7 +150,7 @@ namespace SourceGit.Views
FlowDirection.LeftToRight, FlowDirection.LeftToRight,
typeface, typeface,
10.0, 10.0,
LineBrush); LabelBrush);
var rect = _hitBoxes[i]; var rect = _hitBoxes[i];
var xLabel = rect.X - (hLabel.Width - rect.Width) * 0.5; var xLabel = rect.X - (hLabel.Width - rect.Width) * 0.5;
var yLabel = height - labelHeight + 4; var yLabel = height - labelHeight + 4;
@ -188,7 +183,7 @@ namespace SourceGit.Views
FlowDirection.LeftToRight, FlowDirection.LeftToRight,
typeface, typeface,
12.0, 12.0,
LineBrush); LabelBrush);
var tx = rect.X - (tooltip.Width - rect.Width) * 0.5; var tx = rect.X - (tooltip.Width - rect.Width) * 0.5;
var ty = rect.Y - tooltip.Height - 4; var ty = rect.Y - tooltip.Height - 4;

View file

@ -22,7 +22,9 @@
IndicatorForeground="{DynamicResource Brush.FG2}" IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}" FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}" UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/> WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
/>
</DataTemplate> </DataTemplate>
<DataTemplate DataType="vm:TwoSideTextDiff"> <DataTemplate DataType="vm:TwoSideTextDiff">
@ -40,7 +42,9 @@
IndicatorForeground="{DynamicResource Brush.FG2}" IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}" FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}" UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/> WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
/>
<Rectangle Grid.Column="1" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/> <Rectangle Grid.Column="1" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
@ -57,7 +61,9 @@
IndicatorForeground="{DynamicResource Brush.FG2}" IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}" FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}" UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/> WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
/>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</UserControl.DataTemplates> </UserControl.DataTemplates>

View file

@ -105,6 +105,15 @@ namespace SourceGit.Views
set => SetValue(UseSyntaxHighlightingProperty, value); set => SetValue(UseSyntaxHighlightingProperty, value);
} }
public static readonly StyledProperty<bool> ShowHiddenSymbolsProperty =
AvaloniaProperty.Register<IThemedTextDiffPresenter, bool>(nameof(ShowHiddenSymbols), false);
public bool ShowHiddenSymbols
{
get => GetValue(ShowHiddenSymbolsProperty);
set => SetValue(ShowHiddenSymbolsProperty, value);
}
protected override Type StyleKeyOverride => typeof(TextEditor); protected override Type StyleKeyOverride => typeof(TextEditor);
public IThemedTextDiffPresenter(TextArea area, TextDocument doc) : base(area, doc) public IThemedTextDiffPresenter(TextArea area, TextDocument doc) : base(area, doc)
@ -140,12 +149,24 @@ namespace SourceGit.Views
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
if (change.Property == UseSyntaxHighlightingProperty) if (change.Property == UseSyntaxHighlightingProperty)
{
UpdateTextMate(); UpdateTextMate();
}
else if (change.Property == ShowHiddenSymbolsProperty)
{
var val = change.NewValue is true;
Options.ShowTabs = val;
Options.ShowSpaces = val;
}
else if (change.Property == FileNameProperty) else if (change.Property == FileNameProperty)
{
Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName); Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName);
}
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null) else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
{
Models.TextMateHelper.SetThemeByApp(_textMate); Models.TextMateHelper.SetThemeByApp(_textMate);
} }
}
protected void UpdateTextMate() protected void UpdateTextMate()
{ {

View file

@ -117,7 +117,7 @@
Classes="italic" Classes="italic"
Margin="0,0,8,0" Margin="0,0,8,0"
HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Decrease}}" FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
Text="{DynamicResource Text.Welcome.DragDropTip}" Text="{DynamicResource Text.Welcome.DragDropTip}"
Foreground="{DynamicResource Brush.FG2}"/> Foreground="{DynamicResource Brush.FG2}"/>
</Grid> </Grid>

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