mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-11-01 13:13:21 -07:00
Merge branch 'release/v8.14'
This commit is contained in:
commit
e52eb174f2
72 changed files with 1106 additions and 323 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
8.13
|
||||
8.14
|
0
build/build.linux.sh
Normal file → Executable file
0
build/build.linux.sh
Normal file → Executable file
|
@ -1,2 +1,2 @@
|
|||
#!/bin/bash
|
||||
exec /opt/sourcegit/sourcegit
|
||||
exec /opt/sourcegit/sourcegit $1
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
return cmd.Exec();
|
||||
}
|
||||
|
||||
public static bool Delete(string repo, string name)
|
||||
public static bool DeleteLocal(string repo, string name)
|
||||
{
|
||||
var cmd = new Command();
|
||||
cmd.WorkingDirectory = repo;
|
||||
|
@ -44,5 +44,25 @@
|
|||
cmd.Args = $"branch -D {name}";
|
||||
return cmd.Exec();
|
||||
}
|
||||
|
||||
public static bool DeleteRemote(string repo, string remote, string name)
|
||||
{
|
||||
var cmd = new Command();
|
||||
cmd.WorkingDirectory = repo;
|
||||
cmd.Context = repo;
|
||||
|
||||
var sshKey = new Config(repo).Get($"remote.{remote}.sshkey");
|
||||
if (!string.IsNullOrEmpty(sshKey))
|
||||
{
|
||||
cmd.Args = $"-c core.sshCommand=\"ssh -i '{sshKey}'\" ";
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.Args = "-c credential.helper=manager ";
|
||||
}
|
||||
|
||||
cmd.Args += $"push {remote} --delete {name}";
|
||||
return cmd.Exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,14 @@ namespace SourceGit.Commands
|
|||
return Exec();
|
||||
}
|
||||
|
||||
public bool Commit(string commitId, Action<string> onProgress)
|
||||
{
|
||||
Args = $"checkout --detach --progress {commitId}";
|
||||
TraitErrorAsOutput = true;
|
||||
_outputHandler = onProgress;
|
||||
return Exec();
|
||||
}
|
||||
|
||||
public bool Files(List<string> files)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
|
|
@ -12,11 +12,11 @@ namespace SourceGit.Commands
|
|||
private const string PREFIX_LFS_DEL = "-version https://git-lfs.github.com/spec/";
|
||||
private const string PREFIX_LFS_MODIFY = " version https://git-lfs.github.com/spec/";
|
||||
|
||||
public Diff(string repo, Models.DiffOption opt)
|
||||
public Diff(string repo, Models.DiffOption opt, int unified)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"diff --ignore-cr-at-eol --unified=4 {opt}";
|
||||
Args = $"diff --ignore-cr-at-eol --unified={unified} {opt}";
|
||||
}
|
||||
|
||||
public Models.DiffResult Result()
|
||||
|
|
|
@ -33,31 +33,6 @@ namespace SourceGit.Commands
|
|||
Args += $"{remote} {local}:{remoteBranch}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only used to delete a remote branch!!!!!!
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="remote"></param>
|
||||
/// <param name="branch"></param>
|
||||
public Push(string repo, string remote, string branch)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
TraitErrorAsOutput = true;
|
||||
|
||||
var sshKey = new Config(repo).Get($"remote.{remote}.sshkey");
|
||||
if (!string.IsNullOrEmpty(sshKey))
|
||||
{
|
||||
Args = $"-c core.sshCommand=\"ssh -i '{sshKey}'\" ";
|
||||
}
|
||||
else
|
||||
{
|
||||
Args = "-c credential.helper=manager ";
|
||||
}
|
||||
|
||||
Args += $"push {remote} --delete {branch}";
|
||||
}
|
||||
|
||||
public Push(string repo, string remote, string tag, bool isDelete)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace SourceGit.Commands
|
|||
{
|
||||
private const string PREFIX_LOCAL = "refs/heads/";
|
||||
private const string PREFIX_REMOTE = "refs/remotes/";
|
||||
private const string PREFIX_DETACHED = "(HEAD detached at";
|
||||
|
||||
[GeneratedRegex(@"^(\d+)\s(\d+)$")]
|
||||
private static partial Regex REG_AHEAD_BEHIND();
|
||||
|
@ -51,7 +52,12 @@ namespace SourceGit.Commands
|
|||
var refName = parts[0];
|
||||
if (refName.EndsWith("/HEAD", StringComparison.Ordinal))
|
||||
return;
|
||||
|
||||
|
||||
if (refName.StartsWith(PREFIX_DETACHED, StringComparison.Ordinal))
|
||||
{
|
||||
branch.IsHead = true;
|
||||
}
|
||||
|
||||
if (refName.StartsWith(PREFIX_LOCAL, StringComparison.Ordinal))
|
||||
{
|
||||
branch.Name = refName.Substring(PREFIX_LOCAL.Length);
|
||||
|
|
|
@ -146,6 +146,15 @@ namespace SourceGit.Commands
|
|||
Name = d.Substring(19).Trim(),
|
||||
});
|
||||
}
|
||||
else if (d.Equals("HEAD"))
|
||||
{
|
||||
isHeadOfCurrent = true;
|
||||
decorators.Add(new Models.Decorator()
|
||||
{
|
||||
Type = Models.DecoratorType.CurrentCommitHead,
|
||||
Name = d.Trim(),
|
||||
});
|
||||
}
|
||||
else if (d.StartsWith("refs/heads/", StringComparison.Ordinal))
|
||||
{
|
||||
decorators.Add(new Models.Decorator()
|
||||
|
|
|
@ -5,12 +5,22 @@ namespace SourceGit.Commands
|
|||
{
|
||||
public static class Tag
|
||||
{
|
||||
public static bool Add(string repo, string name, string basedOn, string message)
|
||||
public static bool Add(string repo, string name, string basedOn)
|
||||
{
|
||||
var cmd = new Command();
|
||||
cmd.WorkingDirectory = repo;
|
||||
cmd.Context = repo;
|
||||
cmd.Args = $"tag -a {name} {basedOn} ";
|
||||
cmd.Args = $"tag {name} {basedOn}";
|
||||
return cmd.Exec();
|
||||
}
|
||||
|
||||
public static bool Add(string repo, string name, string basedOn, string message, bool sign)
|
||||
{
|
||||
var param = sign ? "-s -a" : "-a";
|
||||
var cmd = new Command();
|
||||
cmd.WorkingDirectory = repo;
|
||||
cmd.Context = repo;
|
||||
cmd.Args = $"tag {param} {name} {basedOn} ";
|
||||
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
|
|
|
@ -38,6 +38,9 @@ namespace SourceGit.Converters
|
|||
});
|
||||
|
||||
public static readonly FuncValueConverter<Models.DecoratorType, FontWeight> ToFontWeight =
|
||||
new FuncValueConverter<Models.DecoratorType, FontWeight>(v => v == Models.DecoratorType.CurrentBranchHead ? FontWeight.Bold : FontWeight.Regular);
|
||||
new FuncValueConverter<Models.DecoratorType, FontWeight>(v =>
|
||||
v is Models.DecoratorType.CurrentBranchHead or Models.DecoratorType.CurrentCommitHead
|
||||
? FontWeight.Bold : FontWeight.Regular
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ namespace SourceGit.Converters
|
|||
public static readonly FuncValueConverter<int, bool> IsGreaterThanZero =
|
||||
new FuncValueConverter<int, bool>(v => v > 0);
|
||||
|
||||
public static readonly FuncValueConverter<int, bool> IsGreaterThanFour =
|
||||
new FuncValueConverter<int, bool>(v => v > 4);
|
||||
|
||||
public static readonly FuncValueConverter<int, bool> IsZero =
|
||||
new FuncValueConverter<int, bool>(v => v == 0);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace SourceGit.Converters
|
|||
{
|
||||
if (state == WindowState.Maximized)
|
||||
{
|
||||
return new GridLength(30);
|
||||
return new GridLength(OperatingSystem.IsMacOS() ? 34 : 30);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -10,5 +10,6 @@
|
|||
public string Upstream { get; set; }
|
||||
public string UpstreamTrackStatus { get; set; }
|
||||
public string Remote { get; set; }
|
||||
public bool IsHead { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace SourceGit.Models
|
|||
|
||||
public bool IsCurrentHead
|
||||
{
|
||||
get => Decorators.Find(x => x.Type == DecoratorType.CurrentBranchHead) != null;
|
||||
get => Decorators.Find(x => x.Type is DecoratorType.CurrentBranchHead or DecoratorType.CurrentCommitHead) != null;
|
||||
}
|
||||
|
||||
public string FullMessage
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace SourceGit.Models
|
|||
None,
|
||||
CurrentBranchHead,
|
||||
LocalBranchHead,
|
||||
CurrentCommitHead,
|
||||
RemoteBranchHead,
|
||||
Tag,
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ namespace SourceGit.Models
|
|||
{
|
||||
[GeneratedRegex(@"^http[s]?://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/[\w\-/]+/[\w\-\.]+\.git$")]
|
||||
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();
|
||||
[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 readonly Regex[] URL_FORMATS = [
|
||||
|
|
|
@ -95,4 +95,6 @@
|
|||
<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.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.Lines.Incr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l132 0 0-128 64 0 0 128 132 0 0 64-132 0 0 128-64 0 0-128-132 0Z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Lines.Decr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l328 0 0 64-328 0Z</StreamGeometry>
|
||||
</ResourceDictionary>
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout${0}$</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.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.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>
|
||||
|
@ -53,6 +54,9 @@
|
|||
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Show as List</x:String>
|
||||
<x:String x:Key="Text.ChangeDisplayMode.Tree" xml:space="preserve">Show as Tree</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.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.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.StashAndReply" xml:space="preserve">Stash & Reapply</x:String>
|
||||
|
@ -73,6 +77,7 @@
|
|||
<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.CopySHA" xml:space="preserve">Copy SHA</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Checkout Commit</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>
|
||||
|
@ -80,9 +85,10 @@
|
|||
<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.CommitDetail.Changes" xml:space="preserve">CHANGES</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Search Files ...</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.LFS" xml:space="preserve">LFS File</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Search" xml:space="preserve">Search Files ...</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Submodule" xml:space="preserve">Submodule</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Tag" xml:space="preserve">Tag</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Tree" xml:space="preserve">Tree</x:String>
|
||||
|
@ -109,20 +115,28 @@
|
|||
<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.StashAndReply" xml:space="preserve">Stash & Reapply</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.DoNothing" xml:space="preserve">Do Nothing</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.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.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.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.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.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.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.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.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.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.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.Remote" xml:space="preserve">Remote :</x:String>
|
||||
<x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">Target :</x:String>
|
||||
|
@ -145,6 +159,8 @@
|
|||
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Side-By-Side Diff</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Open In Merge Tool</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Decrease Number of Visible Lines</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Increase Number of Visible Lines</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECT FILE TO VIEW CHANGES</x:String>
|
||||
<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>
|
||||
|
@ -310,8 +326,10 @@
|
|||
<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.To" xml:space="preserve">Remote Branch :</x:String>
|
||||
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Tracking remote branch(--set-upstream)</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.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.Tag" xml:space="preserve">Tag :</x:String>
|
||||
<x:String x:Key="Text.Quit" xml:space="preserve">Quit</x:String>
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">检出(checkout)${0}$</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.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.FastForward" xml:space="preserve">快进(fast-forward)到${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">GIT工作流 - 完成${0}$</x:String>
|
||||
|
@ -53,6 +54,9 @@
|
|||
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">列表模式</x:String>
|
||||
<x:String x:Key="Text.ChangeDisplayMode.Tree" xml:space="preserve">树形模式</x:String>
|
||||
<x:String x:Key="Text.Checkout" xml:space="preserve">检出(checkout)分支</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit" xml:space="preserve">检出(checkout)提交</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit.Warning" xml:space="preserve">注意:执行该操作后,当前HEAD会变为游离(detached)状态!</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit.Target" xml:space="preserve">提交 :</x:String>
|
||||
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目标分支 :</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">未提交更改 :</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">贮藏(stash)并自动恢复</x:String>
|
||||
|
@ -72,6 +76,7 @@
|
|||
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">远程仓库 :</x:String>
|
||||
<x:String x:Key="Text.Close" xml:space="preserve">关闭</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">挑选(cherry-pick)此提交</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" 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.Reset" xml:space="preserve">重置(reset)${0}$到此处</x:String>
|
||||
|
@ -80,9 +85,10 @@
|
|||
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">另存为补丁 ...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">合并此提交到上一个提交</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">变更对比</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">查找文件...</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">查找变更...</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">文件列表</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">LFS文件</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Search" xml:space="preserve">查找文件...</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Submodule" xml:space="preserve">子模块</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Tag" xml:space="preserve">标签文件</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Tree" xml:space="preserve">子树</x:String>
|
||||
|
@ -107,22 +113,30 @@
|
|||
<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.LocalChanges" xml:space="preserve">未提交更改 :</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.Discard" xml:space="preserve">忽略</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">贮藏(stash)并自动恢复</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.Discard" xml:space="preserve">放弃所有</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.DoNothing" xml:space="preserve">GIT默认</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.Title" 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.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.Placeholder" 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.PushToAllRemotes" 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.Lightweight" xml:space="preserve">轻量标签</x:String>
|
||||
<x:String x:Key="Text.Cut" 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.IsRemoteTip" xml:space="preserve">您正在删除远程上的分支,请务必小心!!!</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.Tip" xml:space="preserve">您正在尝试一次性删除多个分支,请务必仔细检查后再执行操作!</x:String>
|
||||
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">删除远程确认</x:String>
|
||||
<x:String x:Key="Text.DeleteRemote.Remote" xml:space="preserve">远程名 :</x:String>
|
||||
<x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">目标 :</x:String>
|
||||
|
@ -145,6 +159,8 @@
|
|||
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">分列对比</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">语法高亮</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合并工具查看</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">减少可见的行数</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可见的行数</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">请选择需要对比的文件</x:String>
|
||||
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">使用外部比对工具查看</x:String>
|
||||
<x:String x:Key="Text.Discard" xml:space="preserve">放弃更改确认</x:String>
|
||||
|
@ -310,8 +326,10 @@
|
|||
<x:String x:Key="Text.Push.Remote" xml:space="preserve">远程仓库 :</x:String>
|
||||
<x:String x:Key="Text.Push.Title" xml:space="preserve">推送到远程仓库</x:String>
|
||||
<x:String x:Key="Text.Push.To" xml:space="preserve">远程分支 :</x:String>
|
||||
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">跟踪远程分支(--set-upstream)</x:String>
|
||||
<x:String x:Key="Text.Push.WithAllTags" xml:space="preserve">同时推送标签</x:String>
|
||||
<x:String x:Key="Text.PushTag" xml:space="preserve">推送标签到远程仓库</x:String>
|
||||
<x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">推送到所有远程仓库</x:String>
|
||||
<x:String x:Key="Text.PushTag.Remote" xml:space="preserve">远程仓库 :</x:String>
|
||||
<x:String x:Key="Text.PushTag.Tag" xml:space="preserve">标签 :</x:String>
|
||||
<x:String x:Key="Text.Quit" xml:space="preserve">退出</x:String>
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
<Style.Resources>
|
||||
<x:Double x:Key="ScrollBarSize">12</x:Double>
|
||||
</Style.Resources>
|
||||
|
||||
<Setter Property="ShowDelay" Value="0:0:0.1"/>
|
||||
<Setter Property="HideDelay" Value="0:0:0.2"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ContentPresenter">
|
||||
|
@ -133,12 +136,12 @@
|
|||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="TextBox:pointerover /template/ Border#PART_BorderElement">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent1}"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Contents}"/>
|
||||
</Style>
|
||||
<Style Selector="TextBox:focus /template/ Border#PART_BorderElement">
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent1}"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Contents}"/>
|
||||
</Style>
|
||||
<Style Selector="TextBox:disabled /template/ Border#PART_BorderElement">
|
||||
|
@ -242,6 +245,9 @@
|
|||
<Style Selector="Button.icon_button:pointerover /template/ ContentPresenter#PART_ContentPresenter, RepeatButton.icon_button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
</Style>
|
||||
<Style Selector="Button.icon_button:disabled Path">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.FG2}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Button.flat">
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
|
@ -483,37 +489,15 @@
|
|||
</Style>
|
||||
|
||||
<Style Selector="ListBox.page_switcher ListBoxItem">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<ContentPresenter Name="PART_ContentPresenter"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
Content="{TemplateBinding Content}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" />
|
||||
|
||||
<Border Background="{DynamicResource Brush.FG2}"
|
||||
Width="4"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Stretch"
|
||||
IsHitTestVisible="False"
|
||||
IsVisible="{TemplateBinding IsSelected}"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="ListBox.page_switcher ListBoxItem:selected /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.SwitcherBG}"/>
|
||||
<Setter Property="Margin" Value="4,0,2,0"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
</Style>
|
||||
<Style Selector="ListBox.page_switcher ListBoxItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.SwitcherHover}"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
<Style Selector="ListBox.page_switcher ListBoxItem:selected:pointerover /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.SwitcherBG}"/>
|
||||
<Style Selector="ListBox.page_switcher ListBoxItem:selected /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ContextMenu">
|
||||
|
@ -722,7 +706,7 @@
|
|||
<Thickness x:Key="ComboBoxDropdownBorderPadding">4,0</Thickness>
|
||||
<Thickness x:Key="ComboBoxItemThemePadding">6,4</Thickness>
|
||||
<SolidColorBrush x:Key="ComboBoxDropDownBackground" Color="{DynamicResource Color.Contents}"/>
|
||||
<SolidColorBrush x:Key="ComboBoxDropDownBorderBrush" Color="{DynamicResource Color.Accent1}"/>
|
||||
<SolidColorBrush x:Key="ComboBoxDropDownBorderBrush" Color="{DynamicResource SystemAccentColor}"/>
|
||||
</Style.Resources>
|
||||
|
||||
<Setter Property="MinHeight" Value="20"/>
|
||||
|
@ -734,7 +718,7 @@
|
|||
<Setter Property="VerticalOffset" Value="2"/>
|
||||
</Style>
|
||||
<Style Selector="^:pointerover /template/ Border#Background">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent1}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}" />
|
||||
</Style>
|
||||
<Style Selector="^:disabled">
|
||||
<Setter Property="Opacity" Value=".6"/>
|
||||
|
@ -758,7 +742,7 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border x:Name="Border" Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" BorderBrush="{DynamicResource Brush.Border1}" BorderThickness="1" Background="Transparent" CornerRadius="2">
|
||||
<Path x:Name="Icon" Height="12" Width="12" Data="{DynamicResource Icons.Check}" Fill="{DynamicResource Brush.Accent1}" IsVisible="False" Margin="0,2,0,0"/>
|
||||
<Path x:Name="Icon" Height="12" Width="12" Data="{DynamicResource Icons.Check}" Fill="{DynamicResource Brush.Accent}" IsVisible="False" Margin="0,2,0,0"/>
|
||||
</Border>
|
||||
|
||||
<ContentPresenter x:Name="ContentPresenter"
|
||||
|
@ -773,7 +757,7 @@
|
|||
</Setter>
|
||||
|
||||
<Style Selector="^:pointerover /template/ Border#Border">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent1}"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
<Style Selector="^:checked /template/ Path#Icon">
|
||||
<Setter Property="IsVisible" Value="True"/>
|
||||
|
@ -817,10 +801,10 @@
|
|||
</Setter>
|
||||
|
||||
<Style Selector="^:pointerover /template/ Ellipse#Border">
|
||||
<Setter Property="Stroke" Value="{DynamicResource Brush.Accent1}"/>
|
||||
<Setter Property="Stroke" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
<Style Selector="^:checked /template/ Ellipse#Dot">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent1}"/>
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
|
@ -897,7 +881,7 @@
|
|||
<Setter Property="Fill" Value="{DynamicResource Brush.FG2}"/>
|
||||
</Style>
|
||||
<Style Selector="ToggleButton.filter:pointerover /template/ Path#PART_IndicatorIcon">
|
||||
<Setter Property="Stroke" Value="{DynamicResource Brush.Accent2}"/>
|
||||
<Setter Property="Stroke" Value="{DynamicResource Brush.AccentHovered}"/>
|
||||
</Style>
|
||||
<Style Selector="ToggleButton.tree_expander">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
|
@ -964,7 +948,7 @@
|
|||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
<Style Selector="ToggleButton.line_path:checked Path">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent1}"/>
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ToggleButton.toggle_untracked">
|
||||
|
@ -1002,6 +986,7 @@
|
|||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="10,0"/>
|
||||
<Setter Property="MinHeight" Value="24"/>
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
|
||||
<Style.Resources>
|
||||
<x:Double x:Key="TabItemPipeThickness">1</x:Double>
|
||||
|
@ -1009,10 +994,12 @@
|
|||
</Style>
|
||||
|
||||
<Style Selector="TabItem:pointerover TextBlock.tab_header">
|
||||
<Setter Property="Opacity" Value=".8"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TabItem:selected TextBlock.tab_header">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Accent}"/>
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
</Style>
|
||||
|
||||
|
@ -1075,11 +1062,11 @@
|
|||
</Setter>
|
||||
|
||||
<Style Selector="^ /template/ Border#PART_LayoutRoot:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Accent2}" />
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:selected /template/ Border#PART_LayoutRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Accent1}" />
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="TreeViewItem[IsExpanded=True] Path.folder_icon">
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
<Color x:Key="Color.Decorator">#FF6F6F6F</Color>
|
||||
<Color x:Key="Color.DecoratorIcon">#FFF8F8F8</Color>
|
||||
<Color x:Key="Color.Conflict">#FF836C2E</Color>
|
||||
<Color x:Key="Color.SwitcherHover">#FFDFDFDF</Color>
|
||||
<Color x:Key="Color.SwitcherBG">#FFCFCFCF</Color>
|
||||
<Color x:Key="Color.Border0">#FFCFCFCF</Color>
|
||||
<Color x:Key="Color.Border1">#FF898989</Color>
|
||||
<Color x:Key="Color.Border2">#FFCFCFCF</Color>
|
||||
|
@ -27,9 +25,6 @@
|
|||
<Color x:Key="Color.FG1">#FF1F1F1F</Color>
|
||||
<Color x:Key="Color.FG2">#FF6F6F6F</Color>
|
||||
<Color x:Key="Color.FG3">#FFFFFFFF</Color>
|
||||
<Color x:Key="Color.Accent1">#FF4295FF</Color>
|
||||
<Color x:Key="Color.Accent1Hovered">#FF529DFB</Color>
|
||||
<Color x:Key="Color.Accent2">#4C007ACC</Color>
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
|
@ -45,8 +40,6 @@
|
|||
<Color x:Key="Color.Decorator">#FF505050</Color>
|
||||
<Color x:Key="Color.DecoratorIcon">#FFF8F8F8</Color>
|
||||
<Color x:Key="Color.Conflict">#FFFAFAD2</Color>
|
||||
<Color x:Key="Color.SwitcherHover">#FF323232</Color>
|
||||
<Color x:Key="Color.SwitcherBG">#FF3F3F3F</Color>
|
||||
<Color x:Key="Color.Border0">#FF181818</Color>
|
||||
<Color x:Key="Color.Border1">#FF7C7C7C</Color>
|
||||
<Color x:Key="Color.Border2">#FF404040</Color>
|
||||
|
@ -58,9 +51,6 @@
|
|||
<Color x:Key="Color.FG1">#FFF1F1F1</Color>
|
||||
<Color x:Key="Color.FG2">#40F1F1F1</Color>
|
||||
<Color x:Key="Color.FG3">#FF252525</Color>
|
||||
<Color x:Key="Color.Accent1">#FF007ACC</Color>
|
||||
<Color x:Key="Color.Accent1Hovered">#FF006BBE</Color>
|
||||
<Color x:Key="Color.Accent2">#8C007ACC</Color>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
|
@ -76,8 +66,6 @@
|
|||
<SolidColorBrush x:Key="Brush.Decorator" Color="{DynamicResource Color.Decorator}"/>
|
||||
<SolidColorBrush x:Key="Brush.DecoratorIcon" Color="{DynamicResource Color.DecoratorIcon}"/>
|
||||
<SolidColorBrush x:Key="Brush.Conflict" Color="{DynamicResource Color.Conflict}"/>
|
||||
<SolidColorBrush x:Key="Brush.SwitcherHover" Color="{DynamicResource Color.SwitcherHover}"/>
|
||||
<SolidColorBrush x:Key="Brush.SwitcherBG" Color="{DynamicResource Color.SwitcherBG}"/>
|
||||
<SolidColorBrush x:Key="Brush.Border0" Color="{DynamicResource Color.Border0}"/>
|
||||
<SolidColorBrush x:Key="Brush.Border1" Color="{DynamicResource Color.Border1}"/>
|
||||
<SolidColorBrush x:Key="Brush.Border2" Color="{DynamicResource Color.Border2}"/>
|
||||
|
@ -89,7 +77,6 @@
|
|||
<SolidColorBrush x:Key="Brush.FG1" Color="{DynamicResource Color.FG1}"/>
|
||||
<SolidColorBrush x:Key="Brush.FG2" Color="{DynamicResource Color.FG2}"/>
|
||||
<SolidColorBrush x:Key="Brush.FG3" Color="{DynamicResource Color.FG3}"/>
|
||||
<SolidColorBrush x:Key="Brush.Accent1" Color="{DynamicResource Color.Accent1}"/>
|
||||
<SolidColorBrush x:Key="Brush.Accent1Hovered" Color="{DynamicResource Color.Accent1Hovered}"/>
|
||||
<SolidColorBrush x:Key="Brush.Accent2" Color="{DynamicResource Color.Accent2}"/>
|
||||
<SolidColorBrush x:Key="Brush.Accent" Color="{DynamicResource SystemAccentColor}"/>
|
||||
<SolidColorBrush x:Key="Brush.AccentHovered" Color="{DynamicResource SystemListLowColor}"/>
|
||||
</ResourceDictionary>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
|
@ -29,13 +30,18 @@ namespace SourceGit.ViewModels
|
|||
public bool UseSSH
|
||||
{
|
||||
get => _useSSH;
|
||||
set => SetProperty(ref _useSSH, value);
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _useSSH, value))
|
||||
ValidateProperty(_sshkey, nameof(SSHKey));
|
||||
}
|
||||
}
|
||||
|
||||
[CustomValidation(typeof(AddRemote), nameof(ValidateSSHKey))]
|
||||
public string SSHKey
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get => _sshkey;
|
||||
set => SetProperty(ref _sshkey, value, true);
|
||||
}
|
||||
|
||||
public AddRemote(Repository repo)
|
||||
|
@ -71,6 +77,20 @@ namespace SourceGit.ViewModels
|
|||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
public static ValidationResult ValidateSSHKey(string sshkey, ValidationContext ctx)
|
||||
{
|
||||
if (ctx.ObjectInstance is AddRemote add && add._useSSH)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sshkey))
|
||||
return new ValidationResult("SSH private key is required");
|
||||
|
||||
if (!File.Exists(sshkey))
|
||||
return new ValidationResult("Given SSH private key can NOT be found!");
|
||||
}
|
||||
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
public override Task<bool> Sure()
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
@ -84,11 +104,8 @@ namespace SourceGit.ViewModels
|
|||
SetProgressDescription("Fetching from added remote ...");
|
||||
new Commands.Fetch(_repo.FullPath, _name, true, SetProgressDescription).Exec();
|
||||
|
||||
if (_useSSH)
|
||||
{
|
||||
SetProgressDescription("Post processing ...");
|
||||
new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", SSHKey);
|
||||
}
|
||||
SetProgressDescription("Post processing ...");
|
||||
new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
|
||||
}
|
||||
CallUIThread(() =>
|
||||
{
|
||||
|
@ -103,5 +120,6 @@ namespace SourceGit.ViewModels
|
|||
private string _name = string.Empty;
|
||||
private string _url = string.Empty;
|
||||
private bool _useSSH = false;
|
||||
private string _sshkey = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public enum BranchTreeNodeType
|
||||
{
|
||||
DetachedHead,
|
||||
Remote,
|
||||
Folder,
|
||||
Branch,
|
||||
}
|
||||
|
||||
public class BranchTreeNode
|
||||
public class BranchTreeNode : ObservableObject
|
||||
{
|
||||
public const double DEFAULT_CORNER = 4.0;
|
||||
|
||||
public string Name { get; set; }
|
||||
public BranchTreeNodeType Type { get; set; }
|
||||
public object Backend { get; set; }
|
||||
|
@ -45,12 +52,54 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
get => Type == BranchTreeNodeType.Branch;
|
||||
}
|
||||
|
||||
public bool IsDetachedHead
|
||||
{
|
||||
get => Type == BranchTreeNodeType.DetachedHead;
|
||||
}
|
||||
|
||||
public bool IsCurrent
|
||||
{
|
||||
get => IsBranch && (Backend as Models.Branch).IsCurrent;
|
||||
}
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
set => SetProperty(ref _isSelected, value);
|
||||
}
|
||||
|
||||
public CornerRadius CornerRadius
|
||||
{
|
||||
get => _cornerRadius;
|
||||
set => SetProperty(ref _cornerRadius, value);
|
||||
}
|
||||
|
||||
public void UpdateCornerRadius(ref BranchTreeNode prev)
|
||||
{
|
||||
if (_isSelected && prev != null && prev.IsSelected)
|
||||
{
|
||||
var prevTop = prev.CornerRadius.TopLeft;
|
||||
prev.CornerRadius = new CornerRadius(prevTop, 0);
|
||||
CornerRadius = new CornerRadius(0, DEFAULT_CORNER);
|
||||
}
|
||||
else if (CornerRadius.TopLeft != DEFAULT_CORNER ||
|
||||
CornerRadius.BottomLeft != DEFAULT_CORNER)
|
||||
{
|
||||
CornerRadius = new CornerRadius(DEFAULT_CORNER);
|
||||
}
|
||||
|
||||
prev = this;
|
||||
|
||||
if (!IsBranch && IsExpanded)
|
||||
{
|
||||
foreach (var child in Children)
|
||||
child.UpdateCornerRadius(ref prev);
|
||||
}
|
||||
}
|
||||
private bool _isSelected = false;
|
||||
private CornerRadius _cornerRadius = new CornerRadius(DEFAULT_CORNER);
|
||||
|
||||
public class Builder
|
||||
{
|
||||
public List<BranchTreeNode> Locals => _locals;
|
||||
|
@ -170,11 +219,11 @@ namespace SourceGit.ViewModels
|
|||
start = sepIdx + 1;
|
||||
sepIdx = branch.Name.IndexOf('/', start);
|
||||
}
|
||||
|
||||
|
||||
lastFolder.Children.Add(new BranchTreeNode()
|
||||
{
|
||||
Name = Path.GetFileName(branch.Name),
|
||||
Type = BranchTreeNodeType.Branch,
|
||||
Type = branch.IsHead ? BranchTreeNodeType.DetachedHead : BranchTreeNodeType.Branch,
|
||||
Backend = branch,
|
||||
IsExpanded = false,
|
||||
IsFiltered = isFiltered,
|
||||
|
@ -185,14 +234,16 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
nodes.Sort((l, r) =>
|
||||
{
|
||||
if (l.Type == BranchTreeNodeType.DetachedHead)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (l.Type == r.Type)
|
||||
{
|
||||
return l.Name.CompareTo(r.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)l.Type - (int)r.Type;
|
||||
}
|
||||
|
||||
return (int)l.Type - (int)r.Type;
|
||||
});
|
||||
|
||||
foreach (var node in nodes)
|
||||
|
|
87
src/ViewModels/CheckoutCommit.cs
Normal file
87
src/ViewModels/CheckoutCommit.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class CheckoutCommit: Popup
|
||||
{
|
||||
public Models.Commit Commit
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool HasLocalChanges
|
||||
{
|
||||
get => _repo.WorkingCopyChangesCount > 0;
|
||||
}
|
||||
|
||||
public bool AutoStash
|
||||
{
|
||||
get => _autoStash;
|
||||
set => SetProperty(ref _autoStash, value);
|
||||
}
|
||||
|
||||
public CheckoutCommit(Repository repo, Models.Commit commit)
|
||||
{
|
||||
_repo = repo;
|
||||
Commit = commit;
|
||||
View = new Views.CheckoutCommit() { DataContext = this };
|
||||
}
|
||||
|
||||
public override Task<bool> Sure()
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
ProgressDescription = $"Checkout Commit '{Commit.SHA}' ...";
|
||||
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var needPopStash = false;
|
||||
if (HasLocalChanges)
|
||||
{
|
||||
if (AutoStash)
|
||||
{
|
||||
SetProgressDescription("Adding untracked changes ...");
|
||||
var succ = new Commands.Add(_repo.FullPath).Exec();
|
||||
if (succ)
|
||||
{
|
||||
SetProgressDescription("Stash local changes ...");
|
||||
succ = new Commands.Stash(_repo.FullPath).Push("CHECKOUT_AUTO_STASH");
|
||||
}
|
||||
|
||||
if (!succ)
|
||||
{
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
return false;
|
||||
}
|
||||
|
||||
needPopStash = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetProgressDescription("Discard local changes ...");
|
||||
Commands.Discard.All(_repo.FullPath);
|
||||
}
|
||||
}
|
||||
|
||||
SetProgressDescription("Checkout commit ...");
|
||||
var rs = new Commands.Checkout(_repo.FullPath).Commit(Commit.SHA, SetProgressDescription);
|
||||
|
||||
if (needPopStash)
|
||||
{
|
||||
SetProgressDescription("Re-apply local changes...");
|
||||
rs = new Commands.Stash(_repo.FullPath).Apply("stash@{0}");
|
||||
if (rs)
|
||||
{
|
||||
rs = new Commands.Stash(_repo.FullPath).Drop("stash@{0}");
|
||||
}
|
||||
}
|
||||
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
return rs;
|
||||
});
|
||||
}
|
||||
|
||||
private readonly Repository _repo = null;
|
||||
private bool _autoStash = true;
|
||||
}
|
||||
}
|
|
@ -113,7 +113,7 @@ namespace SourceGit.ViewModels
|
|||
CallUIThread(() =>
|
||||
{
|
||||
var repo = Preference.AddRepository(path, Path.Combine(path, ".git"));
|
||||
var node = Preference.FindOrAddNodeByRepositoryPath(repo.FullPath, null);
|
||||
var node = Preference.FindOrAddNodeByRepositoryPath(repo.FullPath, null, true);
|
||||
_launcher.OpenRepositoryInTab(node, _page);
|
||||
});
|
||||
|
||||
|
|
|
@ -3,6 +3,13 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public enum BeforeCreateBranchAction
|
||||
{
|
||||
StashAndReaply,
|
||||
Discard,
|
||||
DoNothing,
|
||||
}
|
||||
|
||||
public class CreateBranch : Popup
|
||||
{
|
||||
[Required(ErrorMessage = "Branch name is required!")]
|
||||
|
@ -19,14 +26,14 @@ namespace SourceGit.ViewModels
|
|||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool CheckoutAfterCreated
|
||||
|
||||
public BeforeCreateBranchAction PreAction
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = true;
|
||||
|
||||
public bool AutoStash
|
||||
get => _preAction;
|
||||
set => SetProperty(ref _preAction, value);
|
||||
}
|
||||
|
||||
public bool CheckoutAfterCreated
|
||||
{
|
||||
get;
|
||||
set;
|
||||
|
@ -90,7 +97,7 @@ namespace SourceGit.ViewModels
|
|||
bool needPopStash = false;
|
||||
if (_repo.WorkingCopyChangesCount > 0)
|
||||
{
|
||||
if (AutoStash)
|
||||
if (_preAction == BeforeCreateBranchAction.StashAndReaply)
|
||||
{
|
||||
SetProgressDescription("Adding untracked changes...");
|
||||
var succ = new Commands.Add(_repo.FullPath).Exec();
|
||||
|
@ -108,7 +115,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
needPopStash = true;
|
||||
}
|
||||
else
|
||||
else if (_preAction == BeforeCreateBranchAction.Discard)
|
||||
{
|
||||
SetProgressDescription("Discard local changes...");
|
||||
Commands.Discard.All(_repo.FullPath);
|
||||
|
@ -137,5 +144,6 @@ namespace SourceGit.ViewModels
|
|||
private readonly Repository _repo = null;
|
||||
private string _name = null;
|
||||
private readonly string _baseOnRevision = null;
|
||||
private BeforeCreateBranchAction _preAction = BeforeCreateBranchAction.StashAndReaply;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class CreateTag : Popup
|
||||
{
|
||||
public object BasedOn
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Required(ErrorMessage = "Tag name is required!")]
|
||||
[RegularExpression(@"^[\w\-\.]+$", ErrorMessage = "Bad tag name format!")]
|
||||
[CustomValidation(typeof(CreateTag), nameof(ValidateTagName))]
|
||||
|
@ -22,11 +26,23 @@ namespace SourceGit.ViewModels
|
|||
set;
|
||||
}
|
||||
|
||||
public object BasedOn
|
||||
public bool Annotated
|
||||
{
|
||||
get => _annotated;
|
||||
set => SetProperty(ref _annotated, value);
|
||||
}
|
||||
|
||||
public bool SignTag
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
set;
|
||||
} = false;
|
||||
|
||||
public bool PushToAllRemotes
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = true;
|
||||
|
||||
public CreateTag(Repository repo, Models.Branch branch)
|
||||
{
|
||||
|
@ -65,14 +81,29 @@ namespace SourceGit.ViewModels
|
|||
|
||||
return Task.Run(() =>
|
||||
{
|
||||
Commands.Tag.Add(_repo.FullPath, TagName, _basedOn, Message);
|
||||
var succ = false;
|
||||
if (_annotated)
|
||||
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn, Message, SignTag);
|
||||
else
|
||||
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn);
|
||||
|
||||
if (succ && PushToAllRemotes)
|
||||
{
|
||||
foreach (var remote in _repo.Remotes)
|
||||
{
|
||||
SetProgressDescription($"Pushing tag to remote {remote.Name} ...");
|
||||
new Commands.Push(_repo.FullPath, remote.Name, _tagName, false).Exec();
|
||||
}
|
||||
}
|
||||
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
return true;
|
||||
return succ;
|
||||
});
|
||||
}
|
||||
|
||||
private readonly Repository _repo = null;
|
||||
private string _tagName = string.Empty;
|
||||
private bool _annotated = true;
|
||||
private readonly string _basedOn = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,14 +52,17 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
if (Target.IsLocal)
|
||||
{
|
||||
Commands.Branch.Delete(_repo.FullPath, Target.Name);
|
||||
Commands.Branch.DeleteLocal(_repo.FullPath, Target.Name);
|
||||
|
||||
if (_alsoDeleteTrackingRemote && TrackingRemoteBranch != null)
|
||||
new Commands.Push(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name).Exec();
|
||||
{
|
||||
SetProgressDescription("Deleting tracking remote branch...");
|
||||
Commands.Branch.DeleteRemote(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new Commands.Push(_repo.FullPath, Target.Remote, Target.Name).Exec();
|
||||
Commands.Branch.DeleteRemote(_repo.FullPath, Target.Remote, Target.Name);
|
||||
}
|
||||
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
|
|
53
src/ViewModels/DeleteMultipleBranches.cs
Normal file
53
src/ViewModels/DeleteMultipleBranches.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class DeleteMultipleBranches : Popup
|
||||
{
|
||||
public List<Models.Branch> Targets
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public DeleteMultipleBranches(Repository repo, List<Models.Branch> branches, bool isLocal)
|
||||
{
|
||||
_repo = repo;
|
||||
_isLocal = isLocal;
|
||||
Targets = branches;
|
||||
View = new Views.DeleteMultipleBranches() { DataContext = this };
|
||||
}
|
||||
|
||||
public override Task<bool> Sure()
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
ProgressDescription = "Deleting multiple branches...";
|
||||
|
||||
return Task.Run(() =>
|
||||
{
|
||||
if (_isLocal)
|
||||
{
|
||||
foreach (var target in Targets)
|
||||
{
|
||||
SetProgressDescription($"Deleting local branch : {target.Name}");
|
||||
Commands.Branch.DeleteLocal(_repo.FullPath, target.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var target in Targets)
|
||||
{
|
||||
SetProgressDescription($"Deleting remote branch : {target.Remote}/{target.Name}");
|
||||
Commands.Branch.DeleteRemote(_repo.FullPath, target.Remote, target.Name);
|
||||
}
|
||||
}
|
||||
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private Repository _repo = null;
|
||||
private bool _isLocal = false;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -63,6 +64,16 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _syncScrollOffset, value);
|
||||
}
|
||||
|
||||
public int Unified
|
||||
{
|
||||
get => _unified;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _unified, value))
|
||||
LoadDiffContent();
|
||||
}
|
||||
}
|
||||
|
||||
public DiffContext(string repo, Models.DiffOption option, DiffContext previous = null)
|
||||
{
|
||||
_repo = repo;
|
||||
|
@ -74,9 +85,40 @@ namespace SourceGit.ViewModels
|
|||
_content = previous._content;
|
||||
}
|
||||
|
||||
LoadDiffContent();
|
||||
}
|
||||
|
||||
public void IncrUnified()
|
||||
{
|
||||
Unified = _unified + 1;
|
||||
}
|
||||
|
||||
public void DecrUnified()
|
||||
{
|
||||
Unified = Math.Max(4, _unified - 1);
|
||||
}
|
||||
|
||||
public void OpenExternalMergeTool()
|
||||
{
|
||||
var type = Preference.Instance.ExternalMergeToolType;
|
||||
var exec = Preference.Instance.ExternalMergeToolPath;
|
||||
|
||||
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()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
var latest = new Commands.Diff(repo, option).Result();
|
||||
var latest = new Commands.Diff(_repo, _option, _unified).Result();
|
||||
var rs = null as object;
|
||||
|
||||
if (latest.TextDiff != null)
|
||||
|
@ -92,15 +134,15 @@ namespace SourceGit.ViewModels
|
|||
if (IMG_EXTS.Contains(ext))
|
||||
{
|
||||
var imgDiff = new Models.ImageDiff();
|
||||
if (option.Revisions.Count == 2)
|
||||
if (_option.Revisions.Count == 2)
|
||||
{
|
||||
imgDiff.Old = BitmapFromRevisionFile(repo, option.Revisions[0], oldPath);
|
||||
imgDiff.New = BitmapFromRevisionFile(repo, option.Revisions[1], oldPath);
|
||||
imgDiff.Old = BitmapFromRevisionFile(_repo, _option.Revisions[0], oldPath);
|
||||
imgDiff.New = BitmapFromRevisionFile(_repo, _option.Revisions[1], oldPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fullPath = Path.Combine(repo, _option.Path);
|
||||
imgDiff.Old = BitmapFromRevisionFile(repo, "HEAD", oldPath);
|
||||
var fullPath = Path.Combine(_repo, _option.Path);
|
||||
imgDiff.Old = BitmapFromRevisionFile(_repo, "HEAD", oldPath);
|
||||
imgDiff.New = File.Exists(fullPath) ? new Bitmap(fullPath) : null;
|
||||
}
|
||||
rs = imgDiff;
|
||||
|
@ -108,15 +150,15 @@ namespace SourceGit.ViewModels
|
|||
else
|
||||
{
|
||||
var binaryDiff = new Models.BinaryDiff();
|
||||
if (option.Revisions.Count == 2)
|
||||
if (_option.Revisions.Count == 2)
|
||||
{
|
||||
binaryDiff.OldSize = new Commands.QueryFileSize(repo, oldPath, option.Revisions[0]).Result();
|
||||
binaryDiff.NewSize = new Commands.QueryFileSize(repo, _option.Path, option.Revisions[1]).Result();
|
||||
binaryDiff.OldSize = new Commands.QueryFileSize(_repo, oldPath, _option.Revisions[0]).Result();
|
||||
binaryDiff.NewSize = new Commands.QueryFileSize(_repo, _option.Path, _option.Revisions[1]).Result();
|
||||
}
|
||||
else
|
||||
{
|
||||
var fullPath = Path.Combine(repo, _option.Path);
|
||||
binaryDiff.OldSize = new Commands.QueryFileSize(repo, oldPath, "HEAD").Result();
|
||||
var fullPath = Path.Combine(_repo, _option.Path);
|
||||
binaryDiff.OldSize = new Commands.QueryFileSize(_repo, oldPath, "HEAD").Result();
|
||||
binaryDiff.NewSize = File.Exists(fullPath) ? new FileInfo(fullPath).Length : 0;
|
||||
}
|
||||
rs = binaryDiff;
|
||||
|
@ -146,22 +188,6 @@ namespace SourceGit.ViewModels
|
|||
});
|
||||
}
|
||||
|
||||
public void OpenExternalMergeTool()
|
||||
{
|
||||
var type = Preference.Instance.ExternalMergeToolType;
|
||||
var exec = Preference.Instance.ExternalMergeToolPath;
|
||||
|
||||
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 Bitmap BitmapFromRevisionFile(string repo, string revision, string file)
|
||||
{
|
||||
var stream = Commands.QueryFileContent.Run(repo, revision, file);
|
||||
|
@ -181,5 +207,6 @@ namespace SourceGit.ViewModels
|
|||
private bool _isTextDiff = false;
|
||||
private object _content = null;
|
||||
private Vector _syncScrollOffset = Vector.Zero;
|
||||
private int _unified = 4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
|
@ -29,13 +30,18 @@ namespace SourceGit.ViewModels
|
|||
public bool UseSSH
|
||||
{
|
||||
get => _useSSH;
|
||||
set => SetProperty(ref _useSSH, value);
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _useSSH, value))
|
||||
ValidateProperty(_sshkey, nameof(SSHKey));
|
||||
}
|
||||
}
|
||||
|
||||
[CustomValidation(typeof(EditRemote), nameof(ValidateSSHKey))]
|
||||
public string SSHKey
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get => _sshkey;
|
||||
set => SetProperty(ref _sshkey, value, true);
|
||||
}
|
||||
|
||||
public EditRemote(Repository repo, Models.Remote remote)
|
||||
|
@ -85,6 +91,20 @@ namespace SourceGit.ViewModels
|
|||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
public static ValidationResult ValidateSSHKey(string sshkey, ValidationContext ctx)
|
||||
{
|
||||
if (ctx.ObjectInstance is EditRemote edit && edit.UseSSH)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sshkey))
|
||||
return new ValidationResult("SSH private key is required");
|
||||
|
||||
if (!File.Exists(sshkey))
|
||||
return new ValidationResult("Given SSH private key can NOT be found!");
|
||||
}
|
||||
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
public override Task<bool> Sure()
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
@ -106,11 +126,8 @@ namespace SourceGit.ViewModels
|
|||
_remote.URL = _url;
|
||||
}
|
||||
|
||||
if (_useSSH)
|
||||
{
|
||||
SetProgressDescription("Post processing ...");
|
||||
new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", SSHKey);
|
||||
}
|
||||
SetProgressDescription("Post processing ...");
|
||||
new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
|
||||
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
return true;
|
||||
|
@ -122,5 +139,6 @@ namespace SourceGit.ViewModels
|
|||
private string _name = string.Empty;
|
||||
private string _url = string.Empty;
|
||||
private bool _useSSH = false;
|
||||
private string _sshkey = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,6 +234,17 @@ namespace SourceGit.ViewModels
|
|||
e.Handled = true;
|
||||
};
|
||||
menu.Items.Add(reset);
|
||||
|
||||
var checkoutCommit = new MenuItem();
|
||||
checkoutCommit.Header = App.Text("CommitCM.Checkout");
|
||||
checkoutCommit.Icon = App.CreateMenuIcon("Icons.Check");
|
||||
checkoutCommit.Click += (o, e) =>
|
||||
{
|
||||
if (PopupHost.CanCreatePopup())
|
||||
PopupHost.ShowPopup(new CheckoutCommit(_repo, commit));
|
||||
e.Handled = true;
|
||||
};
|
||||
menu.Items.Add(checkoutCommit);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -11,9 +11,11 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _targetPath, value);
|
||||
}
|
||||
|
||||
public Init(string path)
|
||||
public Init(string path, RepositoryNode parent)
|
||||
{
|
||||
TargetPath = path;
|
||||
_targetPath = path;
|
||||
_parentNode = parent;
|
||||
|
||||
View = new Views.Init() { DataContext = this };
|
||||
}
|
||||
|
||||
|
@ -31,13 +33,14 @@ namespace SourceGit.ViewModels
|
|||
CallUIThread(() =>
|
||||
{
|
||||
var repo = Preference.AddRepository(_targetPath, gitDir);
|
||||
Preference.FindOrAddNodeByRepositoryPath(repo.FullPath, null);
|
||||
Preference.FindOrAddNodeByRepositoryPath(repo.FullPath, _parentNode, true);
|
||||
});
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private string _targetPath;
|
||||
private string _targetPath = string.Empty;
|
||||
private RepositoryNode _parentNode = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,27 @@ namespace SourceGit.ViewModels
|
|||
Pages = new AvaloniaList<LauncherPage>();
|
||||
AddNewTab();
|
||||
|
||||
if (Preference.Instance.RestoreTabs)
|
||||
var commandlines = Environment.GetCommandLineArgs();
|
||||
if (commandlines.Length == 2)
|
||||
{
|
||||
var path = commandlines[1];
|
||||
var root = new Commands.QueryRepositoryRootPath(path).Result();
|
||||
if (string.IsNullOrEmpty(root))
|
||||
{
|
||||
Pages[0].Notifications.Add(new Models.Notification
|
||||
{
|
||||
IsError = true,
|
||||
Message = $"Given path: '{path}' is NOT a valid repository!"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var gitDir = new Commands.QueryGitDir(root).Result();
|
||||
var repo = Preference.AddRepository(root, gitDir);
|
||||
var node = Preference.FindOrAddNodeByRepositoryPath(repo.FullPath, null, false);
|
||||
OpenRepositoryInTab(node, null);
|
||||
}
|
||||
else if (Preference.Instance.RestoreTabs)
|
||||
{
|
||||
foreach (var id in Preference.Instance.OpenedTabs)
|
||||
{
|
||||
|
|
|
@ -363,7 +363,7 @@ namespace SourceGit.ViewModels
|
|||
return FindNodeRecursive(id, _instance.RepositoryNodes);
|
||||
}
|
||||
|
||||
public static RepositoryNode FindOrAddNodeByRepositoryPath(string repo, RepositoryNode parent)
|
||||
public static RepositoryNode FindOrAddNodeByRepositoryPath(string repo, RepositoryNode parent, bool shouldMoveNode)
|
||||
{
|
||||
var node = FindNodeRecursive(repo, _instance.RepositoryNodes);
|
||||
if (node == null)
|
||||
|
@ -378,7 +378,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
AddNode(node, parent);
|
||||
}
|
||||
else
|
||||
else if (shouldMoveNode)
|
||||
{
|
||||
MoveNode(node, parent);
|
||||
}
|
||||
|
|
|
@ -82,6 +82,12 @@ namespace SourceGit.ViewModels
|
|||
set;
|
||||
}
|
||||
|
||||
public bool Tracking
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = true;
|
||||
|
||||
public bool ForcePush
|
||||
{
|
||||
get;
|
||||
|
@ -154,7 +160,7 @@ namespace SourceGit.ViewModels
|
|||
remoteBranchName,
|
||||
PushAllTags,
|
||||
ForcePush,
|
||||
string.IsNullOrEmpty(_selectedLocalBranch.Upstream),
|
||||
Tracking,
|
||||
SetProgressDescription).Exec();
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
return succ;
|
||||
|
|
|
@ -22,6 +22,12 @@ namespace SourceGit.ViewModels
|
|||
set;
|
||||
}
|
||||
|
||||
public bool PushAllRemotes
|
||||
{
|
||||
get => _pushAllRemotes;
|
||||
set => SetProperty(ref _pushAllRemotes, value);
|
||||
}
|
||||
|
||||
public PushTag(Repository repo, Models.Tag target)
|
||||
{
|
||||
_repo = repo;
|
||||
|
@ -33,16 +39,33 @@ namespace SourceGit.ViewModels
|
|||
public override Task<bool> Sure()
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
ProgressDescription = $"Pushing tag '{Target.Name}' to remote '{SelectedRemote.Name}' ...";
|
||||
ProgressDescription = $"Pushing tag ...";
|
||||
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var succ = new Commands.Push(_repo.FullPath, SelectedRemote.Name, Target.Name, false).Exec();
|
||||
bool succ = true;
|
||||
if (_pushAllRemotes)
|
||||
{
|
||||
foreach (var remote in _repo.Remotes)
|
||||
{
|
||||
SetProgressDescription($"Pushing tag to remote {remote.Name} ...");
|
||||
succ = new Commands.Push(_repo.FullPath, remote.Name, Target.Name, false).Exec();
|
||||
if (!succ)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetProgressDescription($"Pushing tag to remote {SelectedRemote.Name} ...");
|
||||
succ = new Commands.Push(_repo.FullPath, SelectedRemote.Name, Target.Name, false).Exec();
|
||||
}
|
||||
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
return succ;
|
||||
});
|
||||
}
|
||||
|
||||
private readonly Repository _repo = null;
|
||||
private bool _pushAllRemotes = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -721,6 +721,12 @@ namespace SourceGit.ViewModels
|
|||
else
|
||||
PopupHost.ShowAndStartPopup(new Checkout(this, branch));
|
||||
}
|
||||
|
||||
public void DeleteMultipleBranches(List<Models.Branch> branches, bool isLocal)
|
||||
{
|
||||
if (PopupHost.CanCreatePopup())
|
||||
PopupHost.ShowPopup(new DeleteMultipleBranches(this, branches, isLocal));
|
||||
}
|
||||
|
||||
public void CreateNewTag()
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public void InitRepository(string path)
|
||||
public void InitRepository(string path, RepositoryNode parent)
|
||||
{
|
||||
if (!Preference.Instance.IsGitConfigured)
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
if (PopupHost.CanCreatePopup())
|
||||
{
|
||||
PopupHost.ShowPopup(new Init(path));
|
||||
PopupHost.ShowPopup(new Init(path, parent));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<StackPanel Grid.Column="1" Orientation="Vertical" Margin="0,8,32,8">
|
||||
<StackPanel Height="48" Orientation="Horizontal">
|
||||
<TextBlock Classes="bold" Text="SourceGit" FontSize="32" />
|
||||
<Border Margin="12,0,0,0" Height="20" CornerRadius="10" Background="{DynamicResource Brush.Accent1}" Effect="drop-shadow(0 0 6 #40000000)">
|
||||
<Border Margin="12,0,0,0" Height="20" CornerRadius="10" Background="{DynamicResource Brush.Accent}" Effect="drop-shadow(0 0 6 #40000000)">
|
||||
<TextBlock Classes="monospace" Margin="8,0" Text="{Binding Version}" FontSize="12" Foreground="White"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
@ -82,19 +82,19 @@
|
|||
<StackPanel Orientation="Vertical" Margin="0,24,0,0">
|
||||
<StackPanel Orientation="Horizontal" Height="18">
|
||||
<TextBlock Text="{DynamicResource Text.About.BuildWith}" />
|
||||
<TextBlock Text="Avalonia UI" Cursor="Hand" Foreground="{DynamicResource Brush.Accent1}" TextDecorations="Underline" PointerPressed="OnVisitAvaloniaUI"/>
|
||||
<TextBlock Text="Avalonia UI" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitAvaloniaUI"/>
|
||||
<TextBlock Text=" & " />
|
||||
<TextBlock Text="AvaloniaEdit" Cursor="Hand" Foreground="{DynamicResource Brush.Accent1}" TextDecorations="Underline" PointerPressed="OnVisitAvaloniaEdit"/>
|
||||
<TextBlock Text="AvaloniaEdit" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitAvaloniaEdit"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Height="18" Margin="0,2,0,0">
|
||||
<TextBlock Text="{DynamicResource Text.About.Fonts}" />
|
||||
<TextBlock Text="JetBrains Mono" Cursor="Hand" Foreground="{DynamicResource Brush.Accent1}" TextDecorations="Underline" PointerPressed="OnVisitJetBrainsMonoFont"/>
|
||||
<TextBlock Text="JetBrains Mono" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitJetBrainsMonoFont"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Height="18" Margin="0,2,0,0">
|
||||
<TextBlock Text="{DynamicResource Text.About.SourceCode}" />
|
||||
<TextBlock Text="Github" Cursor="Hand" Foreground="{DynamicResource Brush.Accent1}" TextDecorations="Underline" PointerPressed="OnVisitSourceCode"/>
|
||||
<TextBlock Text="Github" Cursor="Hand" Foreground="{DynamicResource Brush.Accent}" TextDecorations="Underline" PointerPressed="OnVisitSourceCode"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
|
|
@ -299,7 +299,8 @@ namespace SourceGit.Views
|
|||
|
||||
var menu = new ContextMenu();
|
||||
menu.Items.Add(copy);
|
||||
menu.Open(TextArea.TextView);
|
||||
|
||||
TextArea.TextView.OpenContextMenu(menu);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
|
47
src/Views/CheckoutCommit.axaml
Normal file
47
src/Views/CheckoutCommit.axaml
Normal file
|
@ -0,0 +1,47 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:c="clr-namespace:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.CheckoutCommit"
|
||||
x:DataType="vm:CheckoutCommit">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0">
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.Checkout.Commit}" />
|
||||
|
||||
<TextBlock Margin="0,8,0,16"
|
||||
Text="{DynamicResource Text.Checkout.Commit.Warning}"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
FontStyle="Italic"/>
|
||||
|
||||
<Grid RowDefinitions="32,Auto" ColumnDefinitions="120,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Checkout.Commit.Target}" />
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
|
||||
<Path Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}" />
|
||||
<TextBlock Classes="monospace" Foreground="DarkOrange" VerticalAlignment="Center" Margin="8,0" Text="{Binding Commit.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" />
|
||||
<TextBlock Text="{Binding Commit.Subject}"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Checkout.LocalChanges}"
|
||||
IsVisible="{Binding HasLocalChanges}"/>
|
||||
<StackPanel Grid.Row="1" Grid.Column="1" Height="32" Orientation="Horizontal" IsVisible="{Binding HasLocalChanges}">
|
||||
<RadioButton Content="{DynamicResource Text.Checkout.LocalChanges.StashAndReply}"
|
||||
GroupName="LocalChanges"
|
||||
IsChecked="{Binding AutoStash, Mode=TwoWay}" />
|
||||
<RadioButton Content="{DynamicResource Text.Checkout.LocalChanges.Discard}"
|
||||
GroupName="LocalChanges"
|
||||
Margin="8,0,0,0" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
12
src/Views/CheckoutCommit.axaml.cs
Normal file
12
src/Views/CheckoutCommit.axaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CheckoutCommit : UserControl
|
||||
{
|
||||
public CheckoutCommit()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,9 +22,9 @@
|
|||
Height="26"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Background="Transparent"
|
||||
CornerRadius="4"
|
||||
Watermark="{DynamicResource Text.CommitDetail.Changes.Search}"
|
||||
Text="{Binding SearchChangeFilter, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True">
|
||||
Text="{Binding SearchChangeFilter, Mode=TwoWay}">
|
||||
<TextBox.InnerLeftContent>
|
||||
<Path Width="14" Height="14" Margin="4,0,0,0" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Search}"/>
|
||||
</TextBox.InnerLeftContent>
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
var detail = DataContext as ViewModels.CommitDetail;
|
||||
var menu = detail.CreateChangeContextMenu(datagrid.SelectedItem as Models.Change);
|
||||
menu.Open(datagrid);
|
||||
datagrid.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -39,7 +39,7 @@ namespace SourceGit.Views
|
|||
if (node != null && !node.IsFolder)
|
||||
{
|
||||
var menu = detail.CreateChangeContextMenu(node.Backend as Models.Change);
|
||||
menu.Open(view);
|
||||
view.OpenContextMenu(menu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
|
||||
var menu = detail.CreateChangeContextMenu(datagrid.SelectedItem as Models.Change);
|
||||
menu.Open(datagrid);
|
||||
datagrid.OpenContextMenu(menu);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
|
26
src/Views/ContextMenuExtension.cs
Normal file
26
src/Views/ContextMenuExtension.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public static class ContextMenuExtension
|
||||
{
|
||||
public static void OpenContextMenu(this Control control, ContextMenu menu)
|
||||
{
|
||||
if (menu == null) return;
|
||||
|
||||
menu.PlacementTarget = control;
|
||||
menu.Closing += OnContextMenuClosing; // Clear context menu because it is dynamic.
|
||||
|
||||
control.ContextMenu = menu;
|
||||
control.ContextMenu.Open();
|
||||
}
|
||||
|
||||
private static void OnContextMenuClosing(object sender, CancelEventArgs e)
|
||||
{
|
||||
if (sender is ContextMenu menu && menu.PlacementTarget != null)
|
||||
menu.PlacementTarget.ContextMenu = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
xmlns:ac="using:Avalonia.Controls.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.CreateBranch"
|
||||
x:DataType="vm:CreateBranch">
|
||||
|
@ -60,12 +61,21 @@
|
|||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.CreateBranch.LocalChanges}"/>
|
||||
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal">
|
||||
<StackPanel.Resources>
|
||||
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
|
||||
</StackPanel.Resources>
|
||||
|
||||
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}"
|
||||
GroupName="LocalChanges"
|
||||
IsChecked="{Binding AutoStash, Mode=TwoWay}"/>
|
||||
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static vm:BeforeCreateBranchAction.StashAndReaply}}"/>
|
||||
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}"
|
||||
GroupName="LocalChanges"
|
||||
Margin="8,0,0,0"/>
|
||||
Margin="8,0,0,0"
|
||||
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static vm:BeforeCreateBranchAction.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 vm:BeforeCreateBranchAction.DoNothing}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox Grid.Row="3" Grid.Column="1"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.CreateTag}"/>
|
||||
<Grid Margin="0,16,8,0" RowDefinitions="32,32,64" ColumnDefinitions="150,*">
|
||||
<Grid Margin="0,16,8,0" RowDefinitions="32,32,32,Auto,Auto,32" ColumnDefinitions="150,*">
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
|
@ -49,16 +49,41 @@
|
|||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.CreateTag.Type}"/>
|
||||
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal">
|
||||
<RadioButton Content="{DynamicResource Text.CreateTag.Type.Annotated}"
|
||||
GroupName="TagKind"
|
||||
IsChecked="{Binding Annotated, Mode=TwoWay}"/>
|
||||
<RadioButton Content="{DynamicResource Text.CreateTag.Type.Lightweight}"
|
||||
GroupName="TagKind"
|
||||
Margin="8,0,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
||||
Margin="0,6,8,0"
|
||||
Text="{DynamicResource Text.CreateTag.Message}"/>
|
||||
<TextBox Grid.Row="2" Grid.Column="1"
|
||||
Height="56"
|
||||
Text="{DynamicResource Text.CreateTag.Message}"
|
||||
IsVisible="{Binding Annotated}"/>
|
||||
<TextBox Grid.Row="3" Grid.Column="1"
|
||||
Height="64"
|
||||
AcceptsReturn="True" AcceptsTab="False"
|
||||
VerticalAlignment="Center" VerticalContentAlignment="Top"
|
||||
CornerRadius="2"
|
||||
Watermark="{DynamicResource Text.CreateTag.Message.Placeholder}"
|
||||
Text="{Binding Message, Mode=TwoWay}"/>
|
||||
Text="{Binding Message, Mode=TwoWay}"
|
||||
IsVisible="{Binding Annotated}"/>
|
||||
|
||||
<CheckBox Grid.Row="4" Grid.Column="1"
|
||||
Height="32" Margin="0,4,0,0"
|
||||
Content="{DynamicResource Text.CreateTag.GPGSign}"
|
||||
IsChecked="{Binding SignTag, Mode=TwoWay}"
|
||||
IsVisible="{Binding Annotated}"/>
|
||||
|
||||
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||
Content="{DynamicResource Text.CreateTag.PushToAllRemotes}"
|
||||
IsChecked="{Binding PushToAllRemotes, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
82
src/Views/DeleteMultipleBranches.axaml
Normal file
82
src/Views/DeleteMultipleBranches.axaml
Normal file
|
@ -0,0 +1,82 @@
|
|||
<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.DeleteMultipleBranches"
|
||||
x:DataType="vm:DeleteMultipleBranches">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0">
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.DeleteMultiBranch}" />
|
||||
|
||||
<Border Margin="4,16,0,0"
|
||||
Background="{DynamicResource Brush.Contents}"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource Brush.Border1}"
|
||||
CornerRadius="4"
|
||||
Padding="4">
|
||||
<DataGrid MaxHeight="200"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
ItemsSource="{Binding Targets}"
|
||||
SelectionMode="Single"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserResizeColumns="False"
|
||||
CanUserSortColumns="False"
|
||||
IsReadOnly="True"
|
||||
HeadersVisibility="None"
|
||||
Focusable="False"
|
||||
RowHeight="26"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<DataGrid.Styles>
|
||||
<Style Selector="DataGridRow">
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow /template/ Border#RowBorder">
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
|
||||
</Style>
|
||||
</DataGrid.Styles>
|
||||
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Header="ICON">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Path Width="10" Height="10" Margin="4,0,8,0" Data="{StaticResource Icons.Branch}" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTemplateColumn Width="*" Header="NAME">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={x:Static c:BranchConverters.ToName}}" ClipToBounds="True"
|
||||
Classes="monospace" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Border>
|
||||
|
||||
<TextBlock Margin="4,8,0,0"
|
||||
Text="{DynamicResource Text.DeleteMultiBranch.Tip}"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
FontStyle="Italic" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
13
src/Views/DeleteMultipleBranches.axaml.cs
Normal file
13
src/Views/DeleteMultipleBranches.axaml.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class DeleteMultipleBranches : UserControl
|
||||
{
|
||||
public DeleteMultipleBranches()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,14 @@
|
|||
|
||||
<!-- Toolbar Buttons -->
|
||||
<StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Button Classes="icon_button" Width="32" Command="{Binding IncrUnified}" IsVisible="{Binding IsTextDiff}" ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Incr}"/>
|
||||
</Button>
|
||||
|
||||
<Button Classes="icon_button" Width="32" Command="{Binding DecrUnified}" IsVisible="{Binding IsTextDiff}" ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}" IsEnabled="{Binding Unified, Converter={x:Static c:IntConverters.IsGreaterThanFour}}">
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/>
|
||||
</Button>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="32" Height="18"
|
||||
Background="Transparent"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<StackPanel Orientation="Vertical" Margin="8,0">
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.Remote.AddTitle}"/>
|
||||
Text="{DynamicResource Text.Remote.EditTitle}"/>
|
||||
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto" ColumnDefinitions="150,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
|
|
|
@ -300,7 +300,7 @@ namespace SourceGit.Views
|
|||
if (DataContext is ViewModels.Histories histories)
|
||||
{
|
||||
var menu = histories.MakeContextMenu();
|
||||
menu?.Open(sender as Control);
|
||||
(sender as Control)?.OpenContextMenu(menu);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
|
|
@ -321,7 +321,7 @@
|
|||
<ProgressBar Margin="0,8,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsIndeterminate="True"
|
||||
Background="{DynamicResource Brush.FG2}" Foreground="{DynamicResource Brush.Accent1}"
|
||||
Background="{DynamicResource Brush.FG2}" Foreground="{DynamicResource Brush.Accent}"
|
||||
Minimum="0" Maximum="100"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
|
|
@ -396,17 +396,10 @@
|
|||
|
||||
<Grid Margin="8" RowDefinitions="32,32,32" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preference.GPG.Enabled}"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,16,0"/>
|
||||
<CheckBox Grid.Row="0" Grid.Column="1"
|
||||
IsChecked="{Binding #me.EnableGPGSigning, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preference.GPG.Path}"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,16,0"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1"
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding #me.GPGExecutableFile, Mode=TwoWay}">
|
||||
|
@ -417,15 +410,19 @@
|
|||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preference.GPG.UserKey}"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,16,0"/>
|
||||
<TextBox Grid.Row="2" Grid.Column="1"
|
||||
<TextBox Grid.Row="1" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding #me.GPGUserKey, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.Preference.GPG.UserKey.Placeholder}"/>
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Preference.GPG.Enabled}"
|
||||
IsChecked="{Binding #me.EnableGPGSigning, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
|
|
|
@ -207,10 +207,17 @@ namespace SourceGit.Views
|
|||
|
||||
private async void SelectGPGExecutable(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var pattern = OperatingSystem.IsWindows() ? "gpg.exe" : "gpg";
|
||||
var patterns = new List<string>();
|
||||
if (OperatingSystem.IsWindows())
|
||||
patterns.Add("gpg.exe");
|
||||
else if (OperatingSystem.IsLinux())
|
||||
patterns.AddRange(new string[] { "gpg", "gpg2" });
|
||||
else
|
||||
patterns.Add("gpg");
|
||||
|
||||
var options = new FilePickerOpenOptions()
|
||||
{
|
||||
FileTypeFilter = [new FilePickerFileType("GPG Executable") { Patterns = [pattern] }],
|
||||
FileTypeFilter = [new FilePickerFileType("GPG Executable") { Patterns = patterns }],
|
||||
AllowMultiple = false,
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
Classes="bold"
|
||||
Text="{DynamicResource Text.Push.Title}"/>
|
||||
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32,32" ColumnDefinitions="150,*">
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32,32,32" ColumnDefinitions="150,*">
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
|
@ -73,10 +73,14 @@
|
|||
</ComboBox>
|
||||
|
||||
<CheckBox Grid.Row="3" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Push.Tracking}"
|
||||
IsChecked="{Binding Tracking, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="4" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Push.WithAllTags}"
|
||||
IsChecked="{Binding PushAllTags, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="4" Grid.Column="1"
|
||||
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Push.Force}"
|
||||
IsChecked="{Binding ForcePush, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.PushTag}"/>
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="150,*">
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32" ColumnDefinitions="150,*">
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
|
@ -31,7 +31,8 @@
|
|||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding Remotes}"
|
||||
SelectedItem="{Binding SelectedRemote, Mode=TwoWay}">
|
||||
SelectedItem="{Binding SelectedRemote, Mode=TwoWay}"
|
||||
IsEnabled="{Binding !PushAllRemotes}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="{x:Type m:Remote}">
|
||||
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
|
||||
|
@ -41,6 +42,10 @@
|
|||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="1"
|
||||
Content="{DynamicResource Text.PushTag.PushAllRemotes}"
|
||||
IsChecked="{Binding PushAllRemotes, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Left Normal Mode -->
|
||||
<Grid Grid.Column="0" RowDefinitions="28,Auto,5,28,28,Auto,28,*,28,Auto,28,Auto" Margin="0,0,0,4" IsVisible="{Binding !IsSearching}">
|
||||
<Grid Grid.Column="0" Classes="repository_leftpanel" RowDefinitions="28,Auto,5,28,28,Auto,28,*,28,Auto,28,Auto" Margin="0,0,0,4" IsVisible="{Binding !IsSearching}">
|
||||
<!-- WorkingCopy -->
|
||||
<TextBlock Grid.Row="0" Classes="group_header_label" Text="{DynamicResource Text.Repository.Workspace}"/>
|
||||
<ListBox Grid.Row="1" Classes="page_switcher" Background="Transparent" SelectedIndex="{Binding SelectedViewIndex, Mode=TwoWay}">
|
||||
|
@ -119,14 +119,14 @@
|
|||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
<ListBoxItem Height="28" Padding="0">
|
||||
<ListBoxItem Height="28">
|
||||
<Grid Margin="16,0,0,0" Height="28" ColumnDefinitions="20,*">
|
||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Data="{StaticResource Icons.Histories}"/>
|
||||
<TextBlock Grid.Column="1" Classes="monospace" Text="{DynamicResource Text.Histories}"/>
|
||||
</Grid>
|
||||
</ListBoxItem>
|
||||
|
||||
<ListBoxItem Height="28" Padding="0">
|
||||
<ListBoxItem Height="28">
|
||||
<Grid Margin="16,0,0,0" Height="28" ColumnDefinitions="20,*,Auto">
|
||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Data="{StaticResource Icons.Send}"/>
|
||||
<TextBlock Grid.Column="1" Classes="monospace" Text="{DynamicResource Text.WorkingCopy}"/>
|
||||
|
@ -142,7 +142,7 @@
|
|||
</Grid>
|
||||
</ListBoxItem>
|
||||
|
||||
<ListBoxItem Height="28" Padding="0">
|
||||
<ListBoxItem Height="28">
|
||||
<Grid Margin="16,0,0,0" Height="28" ColumnDefinitions="20,*,Auto">
|
||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Data="{StaticResource Icons.Stashes}"/>
|
||||
<TextBlock Grid.Column="1" Classes="monospace" Text="{DynamicResource Text.Stashes}"/>
|
||||
|
@ -198,19 +198,31 @@
|
|||
<TreeView Grid.Row="5"
|
||||
x:Name="localBranchTree"
|
||||
MaxHeight="400"
|
||||
Margin="4,0,2,0"
|
||||
SelectionMode="Multiple"
|
||||
ItemsSource="{Binding LocalBranchTrees}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
LostFocus="OnLocalBranchTreeLostFocus"
|
||||
ContextRequested="OnLocalBranchContextMenuRequested"
|
||||
SelectionChanged="OnLocalBranchTreeSelectionChanged">
|
||||
<TreeView.Styles>
|
||||
<Style Selector="TreeViewItem" x:DataType="vm:BranchTreeNode">
|
||||
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
|
||||
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
|
||||
<Setter Property="CornerRadius" Value="{Binding CornerRadius}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Grid.repository_leftpanel TreeViewItem:selected /template/ Border#PART_LayoutRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Grid.repository_leftpanel:focus-within TreeViewItem:selected /template/ Border#PART_LayoutRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
|
||||
</Style>
|
||||
</TreeView.Styles>
|
||||
<TreeView.ItemTemplate>
|
||||
<TreeDataTemplate ItemsSource="{Binding Children}" x:DataType="{x:Type vm:BranchTreeNode}">
|
||||
<Grid Height="24" ColumnDefinitions="20,*,Auto,Auto" Background="Transparent" ContextRequested="OnLocalBranchContextMenuRequested" DoubleTapped="OnDoubleTappedLocalBranchNode">
|
||||
<Grid Height="24" ColumnDefinitions="20,*,Auto,Auto" Background="Transparent" DoubleTapped="OnDoubleTappedLocalBranchNode">
|
||||
<Path Grid.Column="0" Classes="folder_icon" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,1,0,0" IsVisible="{Binding IsFolder}"/>
|
||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,2,0,0" Data="{StaticResource Icons.Check}" IsVisible="{Binding IsCurrent}" VerticalAlignment="Center"/>
|
||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Margin="2,0,0,0" Data="{StaticResource Icons.Branch}" VerticalAlignment="Center">
|
||||
|
@ -250,20 +262,32 @@
|
|||
</Grid>
|
||||
<TreeView Grid.Row="7"
|
||||
x:Name="remoteBranchTree"
|
||||
Margin="4,0,2,0"
|
||||
SelectionMode="Multiple"
|
||||
ItemsSource="{Binding RemoteBranchTrees}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
LostFocus="OnRemoteBranchTreeLostFocus"
|
||||
ContextRequested="OnRemoteBranchContextMenuRequested"
|
||||
SelectionChanged="OnRemoteBranchTreeSelectionChanged">
|
||||
<TreeView.Styles>
|
||||
<Style Selector="TreeViewItem" x:DataType="vm:BranchTreeNode">
|
||||
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
|
||||
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
|
||||
<Setter Property="CornerRadius" Value="{Binding CornerRadius}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Grid.repository_leftpanel TreeViewItem:selected /template/ Border#PART_LayoutRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Grid.repository_leftpanel:focus-within TreeViewItem:selected /template/ Border#PART_LayoutRoot">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
|
||||
</Style>
|
||||
</TreeView.Styles>
|
||||
|
||||
<TreeView.ItemTemplate>
|
||||
<TreeDataTemplate ItemsSource="{Binding Children}" x:DataType="{x:Type vm:BranchTreeNode}">
|
||||
<Grid Height="24" ColumnDefinitions="20,*,Auto" Background="Transparent" ContextRequested="OnRemoteBranchContextMenuRequested">
|
||||
<Grid Height="24" ColumnDefinitions="20,*,Auto" Background="Transparent">
|
||||
<Path Grid.Column="0" Classes="folder_icon" Width="10" Height="10" HorizontalAlignment="Left" Margin="0,2,0,0" IsVisible="{Binding IsFolder}" VerticalAlignment="Center"/>
|
||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,2,0,0" Data="{StaticResource Icons.Remote}" IsVisible="{Binding IsRemote}" VerticalAlignment="Center"/>
|
||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Margin="2,0,0,0" Data="{StaticResource Icons.Branch}" IsVisible="{Binding IsBranch}" VerticalAlignment="Center"/>
|
||||
|
@ -294,7 +318,9 @@
|
|||
</Grid>
|
||||
</ToggleButton>
|
||||
<DataGrid Grid.Row="9"
|
||||
x:Name="tagsList"
|
||||
MaxHeight="200"
|
||||
Margin="4,0,2,0"
|
||||
Background="Transparent"
|
||||
ItemsSource="{Binding Tags}"
|
||||
SelectionMode="Single"
|
||||
|
@ -307,10 +333,27 @@
|
|||
RowHeight="24"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
LostFocus="OnTagDataGridLostFocus"
|
||||
IsVisible="{Binding IsTagGroupExpanded, Mode=OneWay}"
|
||||
SelectionChanged="OnTagDataGridSelectionChanged"
|
||||
ContextRequested="OnTagContextRequested">
|
||||
<DataGrid.Styles>
|
||||
<Style Selector="DataGridRow">
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow /template/ Border#RowBorder">
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Grid.repository_leftpanel DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Grid.repository_leftpanel:focus-within DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
|
||||
</Style>
|
||||
</DataGrid.Styles>
|
||||
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Header="ICON">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
|
@ -364,6 +407,7 @@
|
|||
</ToggleButton>
|
||||
<DataGrid Grid.Row="11"
|
||||
MaxHeight="200"
|
||||
Margin="4,0,6,0"
|
||||
Background="Transparent"
|
||||
ItemsSource="{Binding Submodules}"
|
||||
SelectionMode="Single"
|
||||
|
@ -378,6 +422,24 @@
|
|||
VerticalScrollBarVisibility="Auto"
|
||||
ContextRequested="OnSubmoduleContextRequested"
|
||||
IsVisible="{Binding IsSubmoduleGroupExpanded, Mode=OneWay}">
|
||||
<DataGrid.Styles>
|
||||
<Style Selector="DataGridRow">
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow /template/ Border#RowBorder">
|
||||
<Setter Property="ClipToBounds" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
|
||||
</Style>
|
||||
</DataGrid.Styles>
|
||||
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Header="ICON">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
|
@ -390,7 +452,7 @@
|
|||
<DataGridTemplateColumn Width="*" Header="NAME">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding}" Classes="monospace"/>
|
||||
<TextBlock Text="{Binding}" ClipToBounds="True" Classes="monospace"/>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
@ -408,6 +470,7 @@
|
|||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Background="{DynamicResource Brush.Contents}"
|
||||
CornerRadius="4"
|
||||
Watermark="{DynamicResource Text.Repository.SearchTip}"
|
||||
Text="{Binding SearchCommitFilter, Mode=TwoWay}"
|
||||
VerticalContentAlignment="Center"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
|
@ -6,6 +7,7 @@ using Avalonia.Controls;
|
|||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
|
@ -66,56 +68,47 @@ namespace SourceGit.Views
|
|||
if (sender is Button button && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForExternalTools();
|
||||
if (menu != null)
|
||||
{
|
||||
menu.Open(button);
|
||||
e.Handled = true;
|
||||
}
|
||||
button.OpenContextMenu(menu);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLocalBranchTreeLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView tree)
|
||||
tree.UnselectAll();
|
||||
}
|
||||
|
||||
private void OnRemoteBranchTreeLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView tree)
|
||||
tree.UnselectAll();
|
||||
}
|
||||
|
||||
private void OnTagDataGridLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid)
|
||||
datagrid.SelectedItem = null;
|
||||
}
|
||||
|
||||
private void OnLocalBranchTreeSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView tree && tree.SelectedItem != null)
|
||||
if (sender is TreeView tree && tree.SelectedItem != null && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
remoteBranchTree.UnselectAll();
|
||||
tagsList.SelectedItem = null;
|
||||
|
||||
var node = tree.SelectedItem as ViewModels.BranchTreeNode;
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||
ViewModels.BranchTreeNode prev = null;
|
||||
foreach (var node in repo.LocalBranchTrees)
|
||||
node.UpdateCornerRadius(ref prev);
|
||||
|
||||
if (tree.SelectedItems.Count == 1)
|
||||
{
|
||||
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
||||
var node = tree.SelectedItem as ViewModels.BranchTreeNode;
|
||||
if (node.IsBranch)
|
||||
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRemoteBranchTreeSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView tree && tree.SelectedItem != null)
|
||||
if (sender is TreeView tree && tree.SelectedItem != null && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
localBranchTree.UnselectAll();
|
||||
tagsList.SelectedItem = null;
|
||||
|
||||
var node = tree.SelectedItem as ViewModels.BranchTreeNode;
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||
ViewModels.BranchTreeNode prev = null;
|
||||
foreach (var node in repo.RemoteBranchTrees)
|
||||
node.UpdateCornerRadius(ref prev);
|
||||
|
||||
if (tree.SelectedItems.Count == 1)
|
||||
{
|
||||
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
||||
var node = tree.SelectedItem as ViewModels.BranchTreeNode;
|
||||
if (node.IsBranch)
|
||||
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,11 +117,12 @@ namespace SourceGit.Views
|
|||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null)
|
||||
{
|
||||
localBranchTree.UnselectAll();
|
||||
remoteBranchTree.UnselectAll();
|
||||
|
||||
var tag = datagrid.SelectedItem as Models.Tag;
|
||||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
repo.NavigateToCommit(tag.SHA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,9 +130,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
var grid = sender as Grid;
|
||||
if (e.Property == IsVisibleProperty && grid.IsVisible)
|
||||
{
|
||||
txtSearchCommitsBox.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSearchKeyDown(object sender, KeyEventArgs e)
|
||||
|
@ -146,9 +138,8 @@ namespace SourceGit.Views
|
|||
if (e.Key == Key.Enter)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
repo.StartSearchCommits();
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
@ -174,9 +165,7 @@ namespace SourceGit.Views
|
|||
if (toggle.DataContext is ViewModels.BranchTreeNode node)
|
||||
{
|
||||
if (node.IsBranch)
|
||||
{
|
||||
filter = (node.Backend as Models.Branch).FullName;
|
||||
}
|
||||
}
|
||||
else if (toggle.DataContext is Models.Tag tag)
|
||||
{
|
||||
|
@ -195,16 +184,43 @@ namespace SourceGit.Views
|
|||
private void OnLocalBranchContextMenuRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
remoteBranchTree.UnselectAll();
|
||||
tagsList.SelectedItem = null;
|
||||
|
||||
if (sender is Grid grid && grid.DataContext is ViewModels.BranchTreeNode node)
|
||||
var repo = DataContext as ViewModels.Repository;
|
||||
var tree = sender as TreeView;
|
||||
if (tree.SelectedItems.Count == 0)
|
||||
{
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var branches = new List<Models.Branch>();
|
||||
foreach (var item in tree.SelectedItems)
|
||||
CollectBranchesFromNode(branches, item as ViewModels.BranchTreeNode);
|
||||
|
||||
if (branches.Count == 1)
|
||||
{
|
||||
var item = (e.Source as Control)?.FindAncestorOfType<TreeViewItem>(true);
|
||||
if (item != null)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForLocalBranch(node.Backend as Models.Branch);
|
||||
if (menu != null)
|
||||
menu.Open(grid);
|
||||
var menu = repo.CreateContextMenuForLocalBranch(branches[0]);
|
||||
item.OpenContextMenu(menu);
|
||||
}
|
||||
}
|
||||
else if (branches.Count > 1 && branches.Find(x => x.IsCurrent) == null)
|
||||
{
|
||||
var menu = new ContextMenu();
|
||||
var deleteMulti = new MenuItem();
|
||||
deleteMulti.Header = App.Text("BranchCM.DeleteMultiBranches", branches.Count);
|
||||
deleteMulti.Icon = App.CreateMenuIcon("Icons.Clear");
|
||||
deleteMulti.Click += (_, ev) =>
|
||||
{
|
||||
repo.DeleteMultipleBranches(branches, true);
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(deleteMulti);
|
||||
tree.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
@ -212,22 +228,60 @@ namespace SourceGit.Views
|
|||
private void OnRemoteBranchContextMenuRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
localBranchTree.UnselectAll();
|
||||
|
||||
if (sender is Grid grid && grid.DataContext is ViewModels.BranchTreeNode node && DataContext is ViewModels.Repository repo)
|
||||
tagsList.SelectedItem = null;
|
||||
|
||||
var repo = DataContext as ViewModels.Repository;
|
||||
var tree = sender as TreeView;
|
||||
if (tree.SelectedItems.Count == 0)
|
||||
{
|
||||
if (node.IsRemote)
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (tree.SelectedItems.Count == 1)
|
||||
{
|
||||
var node = tree.SelectedItem as ViewModels.BranchTreeNode;
|
||||
if (node != null && node.IsRemote)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForRemote(node.Backend as Models.Remote);
|
||||
if (menu != null)
|
||||
menu.Open(grid);
|
||||
var item = (e.Source as Control)?.FindAncestorOfType<TreeViewItem>(true);
|
||||
if (item != null && item.DataContext == node)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForRemote(node.Backend as Models.Remote);
|
||||
item.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
else if (node.IsBranch)
|
||||
}
|
||||
|
||||
var branches = new List<Models.Branch>();
|
||||
foreach (var item in tree.SelectedItems)
|
||||
CollectBranchesFromNode(branches, item as ViewModels.BranchTreeNode);
|
||||
|
||||
if (branches.Count == 1)
|
||||
{
|
||||
var item = (e.Source as Control)?.FindAncestorOfType<TreeViewItem>(true);
|
||||
if (item != null)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForRemoteBranch(node.Backend as Models.Branch);
|
||||
if (menu != null)
|
||||
menu.Open(grid);
|
||||
var menu = repo.CreateContextMenuForRemoteBranch(branches[0]);
|
||||
item.OpenContextMenu(menu);
|
||||
}
|
||||
}
|
||||
else if (branches.Count > 1)
|
||||
{
|
||||
var menu = new ContextMenu();
|
||||
var deleteMulti = new MenuItem();
|
||||
deleteMulti.Header = App.Text("BranchCM.DeleteMultiBranches", branches.Count);
|
||||
deleteMulti.Icon = App.CreateMenuIcon("Icons.Clear");
|
||||
deleteMulti.Click += (_, ev) =>
|
||||
{
|
||||
repo.DeleteMultipleBranches(branches, false);
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(deleteMulti);
|
||||
tree.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
@ -238,8 +292,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
var tag = datagrid.SelectedItem as Models.Tag;
|
||||
var menu = repo.CreateContextMenuForTag(tag);
|
||||
if (menu != null)
|
||||
menu.Open(datagrid);
|
||||
datagrid.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -251,8 +304,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
var submodule = datagrid.SelectedItem as string;
|
||||
var menu = repo.CreateContextMenuForSubmodule(submodule);
|
||||
if (menu != null)
|
||||
menu.Open(datagrid);
|
||||
datagrid.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -263,8 +315,7 @@ namespace SourceGit.Views
|
|||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForGitFlow();
|
||||
if (menu != null)
|
||||
menu.Open(sender as Button);
|
||||
(sender as Control)?.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -313,5 +364,23 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void CollectBranchesFromNode(List<Models.Branch> outs, ViewModels.BranchTreeNode node)
|
||||
{
|
||||
if (node == null || node.IsRemote)
|
||||
return;
|
||||
|
||||
if (node.IsFolder)
|
||||
{
|
||||
foreach (var child in node.Children)
|
||||
CollectBranchesFromNode(outs, child);
|
||||
}
|
||||
else
|
||||
{
|
||||
var b = node.Backend as Models.Branch;
|
||||
if (b != null && !outs.Contains(b))
|
||||
outs.Add(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,23 +47,18 @@
|
|||
Text="{Binding HttpProxy, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Preference.GPG.Enabled}"/>
|
||||
<CheckBox Grid.Row="3" Grid.Column="1"
|
||||
x:Name="chkGPGSigningEnabled"
|
||||
IsChecked="{Binding GPGSigningEnabled, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Preference.GPG.UserKey}"/>
|
||||
<TextBox Grid.Row="4" Grid.Column="1"
|
||||
<TextBox Grid.Row="3" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Watermark="{DynamicResource Text.Preference.GPG.UserKey.Placeholder}"
|
||||
Text="{Binding GPGUserSigningKey, Mode=TwoWay}"
|
||||
IsEnabled="{Binding #chkGPGSigningEnabled.IsChecked}"/>
|
||||
Text="{Binding GPGUserSigningKey, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="4" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Preference.GPG.Enabled}"
|
||||
IsChecked="{Binding GPGSigningEnabled, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
Height="26"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Background="Transparent"
|
||||
CornerRadius="4"
|
||||
Watermark="{DynamicResource Text.CommitDetail.Changes.Search}"
|
||||
Text="{Binding SearchFilter, Mode=TwoWay}">
|
||||
<TextBox.InnerLeftContent>
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
var compare = DataContext as ViewModels.RevisionCompare;
|
||||
var menu = compare.CreateChangeContextMenu(datagrid.SelectedItem as Models.Change);
|
||||
menu.Open(datagrid);
|
||||
datagrid.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -40,7 +40,7 @@ namespace SourceGit.Views
|
|||
if (node != null && !node.IsFolder)
|
||||
{
|
||||
var menu = compare.CreateChangeContextMenu(node.Backend as Models.Change);
|
||||
menu.Open(view);
|
||||
view.OpenContextMenu(menu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
Height="26"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Background="Transparent"
|
||||
Watermark="{DynamicResource Text.CommitDetail.Changes.Search}"
|
||||
Text="{Binding SearchFileFilter, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True">
|
||||
CornerRadius="4"
|
||||
Watermark="{DynamicResource Text.CommitDetail.Files.Search}"
|
||||
Text="{Binding SearchFileFilter, Mode=TwoWay}">
|
||||
<TextBox.InnerLeftContent>
|
||||
<Path Width="14" Height="14" Margin="4,0,0,0" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Search}"/>
|
||||
</TextBox.InnerLeftContent>
|
||||
|
|
|
@ -198,7 +198,8 @@ namespace SourceGit.Views
|
|||
|
||||
var menu = new ContextMenu();
|
||||
menu.Items.Add(copy);
|
||||
menu.Open(TextArea.TextView);
|
||||
|
||||
TextArea.TextView.OpenContextMenu(menu);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
@ -219,7 +220,7 @@ namespace SourceGit.Views
|
|||
if (!node.IsFolder)
|
||||
{
|
||||
var menu = detail.CreateRevisionFileContextMenu(node.Backend as Models.Object);
|
||||
menu.Open(sender as Control);
|
||||
(sender as Control)?.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,8">
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Info}" Fill="Green"/>
|
||||
<TextBlock Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.SelfUpdate.Available}"/>
|
||||
<Border Margin="4,0,0,0" Height="20" CornerRadius="10" Background="{DynamicResource Brush.Accent1}" Effect="drop-shadow(0 0 6 #40000000)">
|
||||
<Border Margin="4,0,0,0" Height="20" CornerRadius="10" Background="{DynamicResource Brush.Accent}" Effect="drop-shadow(0 0 6 #40000000)">
|
||||
<TextBlock Classes="monospace" Margin="8,0" Text="{Binding TagName}" FontSize="12" Foreground="White"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
<v:Chart Grid.Column="1"
|
||||
Margin="16,0,0,0"
|
||||
LineBrush="{DynamicResource Brush.Border1}"
|
||||
ShapeBrush="{DynamicResource Brush.Accent1}"
|
||||
ShapeBrush="{DynamicResource Brush.Accent}"
|
||||
Samples="{Binding Samples}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
|
|
@ -137,6 +137,9 @@ namespace SourceGit.Views
|
|||
var width = textView.Bounds.Width;
|
||||
foreach (var line in textView.VisualLines)
|
||||
{
|
||||
if (line.FirstDocumentLine == null)
|
||||
continue;
|
||||
|
||||
var index = line.FirstDocumentLine.LineNumber;
|
||||
if (index > _editor.DiffData.Lines.Count)
|
||||
break;
|
||||
|
@ -320,7 +323,8 @@ namespace SourceGit.Views
|
|||
};
|
||||
|
||||
menu.Items.Add(copy);
|
||||
menu.Open(TextArea.TextView);
|
||||
|
||||
TextArea.TextView.OpenContextMenu(menu);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
@ -516,6 +520,9 @@ namespace SourceGit.Views
|
|||
var infos = _editor.IsOld ? _editor.DiffData.Old : _editor.DiffData.New;
|
||||
foreach (var line in textView.VisualLines)
|
||||
{
|
||||
if (line.FirstDocumentLine == null)
|
||||
continue;
|
||||
|
||||
var index = line.FirstDocumentLine.LineNumber;
|
||||
if (index > infos.Count)
|
||||
break;
|
||||
|
@ -731,7 +738,8 @@ namespace SourceGit.Views
|
|||
};
|
||||
|
||||
menu.Items.Add(copy);
|
||||
menu.Open(TextArea.TextView);
|
||||
|
||||
TextArea.TextView.OpenContextMenu(menu);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace SourceGit.Views
|
|||
if (sender is Grid grid && DataContext is ViewModels.Welcome vm)
|
||||
{
|
||||
var menu = vm.CreateContextMenu(grid.DataContext as ViewModels.RepositoryNode);
|
||||
menu?.Open(grid);
|
||||
grid.OpenContextMenu(menu);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
(DataContext as ViewModels.Welcome).InitRepository(path);
|
||||
(DataContext as ViewModels.Welcome).InitRepository(path, parent);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ namespace SourceGit.Views
|
|||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
var repo = ViewModels.Preference.AddRepository(root, gitDir);
|
||||
var node = ViewModels.Preference.FindOrAddNodeByRepositoryPath(repo.FullPath, parent);
|
||||
var node = ViewModels.Preference.FindOrAddNodeByRepositoryPath(repo.FullPath, parent, true);
|
||||
launcher.OpenRepositoryInTab(node, page);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -205,8 +205,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
|
||||
var menu = vm.CreateContextMenuForUnstagedChanges(selected);
|
||||
if (menu != null)
|
||||
menu.Open(datagrid);
|
||||
datagrid.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -225,8 +224,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
|
||||
var menu = vm.CreateContextMenuForUnstagedChanges(selected);
|
||||
if (menu != null)
|
||||
menu.Open(tree);
|
||||
tree.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -245,8 +243,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
|
||||
var menu = vm.CreateContextMenuForStagedChanges(selected);
|
||||
if (menu != null)
|
||||
menu.Open(datagrid);
|
||||
datagrid.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -265,8 +262,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
|
||||
var menu = vm.CreateContextMenuForStagedChanges(selected);
|
||||
if (menu != null)
|
||||
menu.Open(tree);
|
||||
tree.OpenContextMenu(menu);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -331,7 +327,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
var menu = vm.CreateContextMenuForCommitMessages();
|
||||
menu.Placement = PlacementMode.TopEdgeAlignedLeft;
|
||||
menu.Open(button);
|
||||
button.OpenContextMenu(menu);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue