mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-25 21:07:20 -08:00
feature: supports custom actions (#638)
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
parent
7c5de7e48c
commit
a36058ec51
17 changed files with 478 additions and 2 deletions
63
src/Commands/ExecuteCustomAction.cs
Normal file
63
src/Commands/ExecuteCustomAction.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Avalonia.Threading;
|
||||||
|
|
||||||
|
namespace SourceGit.Commands
|
||||||
|
{
|
||||||
|
public static class ExecuteCustomAction
|
||||||
|
{
|
||||||
|
public static void Run(string repo, string file, string args, Action<string> outputHandler)
|
||||||
|
{
|
||||||
|
var start = new ProcessStartInfo();
|
||||||
|
start.FileName = file;
|
||||||
|
start.Arguments = args;
|
||||||
|
start.UseShellExecute = false;
|
||||||
|
start.CreateNoWindow = true;
|
||||||
|
start.RedirectStandardOutput = true;
|
||||||
|
start.RedirectStandardError = true;
|
||||||
|
start.StandardOutputEncoding = Encoding.UTF8;
|
||||||
|
start.StandardErrorEncoding = Encoding.UTF8;
|
||||||
|
start.WorkingDirectory = repo;
|
||||||
|
|
||||||
|
// Force using en_US.UTF-8 locale to avoid GCM crash
|
||||||
|
if (OperatingSystem.IsLinux())
|
||||||
|
start.Environment.Add("LANG", "en_US.UTF-8");
|
||||||
|
|
||||||
|
// Fix macOS `PATH` env
|
||||||
|
if (OperatingSystem.IsMacOS() && !string.IsNullOrEmpty(Native.OS.CustomPathEnv))
|
||||||
|
start.Environment.Add("PATH", Native.OS.CustomPathEnv);
|
||||||
|
|
||||||
|
var proc = new Process() { StartInfo = start };
|
||||||
|
proc.OutputDataReceived += (_, e) =>
|
||||||
|
{
|
||||||
|
if (e.Data != null)
|
||||||
|
outputHandler?.Invoke(e.Data);
|
||||||
|
};
|
||||||
|
|
||||||
|
proc.ErrorDataReceived += (_, e) =>
|
||||||
|
{
|
||||||
|
if (e.Data != null)
|
||||||
|
outputHandler?.Invoke(e.Data);
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
proc.Start();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Invoke(() =>
|
||||||
|
{
|
||||||
|
App.RaiseException(repo, e.Message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
proc.BeginOutputReadLine();
|
||||||
|
proc.BeginErrorReadLine();
|
||||||
|
proc.WaitForExit();
|
||||||
|
proc.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
src/Models/CustomAction.cs
Normal file
42
src/Models/CustomAction.cs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace SourceGit.Models
|
||||||
|
{
|
||||||
|
public enum CustomActionScope
|
||||||
|
{
|
||||||
|
Repository,
|
||||||
|
Commit,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CustomAction : ObservableObject
|
||||||
|
{
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => _name;
|
||||||
|
set => SetProperty(ref _name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomActionScope Scope
|
||||||
|
{
|
||||||
|
get => _scope;
|
||||||
|
set => SetProperty(ref _scope, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Executable
|
||||||
|
{
|
||||||
|
get => _executable;
|
||||||
|
set => SetProperty(ref _executable, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Arguments
|
||||||
|
{
|
||||||
|
get => _arguments;
|
||||||
|
set => SetProperty(ref _arguments, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _name = string.Empty;
|
||||||
|
private CustomActionScope _scope = CustomActionScope.Repository;
|
||||||
|
private string _executable = string.Empty;
|
||||||
|
private string _arguments = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -100,6 +100,12 @@ namespace SourceGit.Models
|
||||||
set;
|
set;
|
||||||
} = new AvaloniaList<IssueTrackerRule>();
|
} = new AvaloniaList<IssueTrackerRule>();
|
||||||
|
|
||||||
|
public AvaloniaList<CustomAction> CustomActions
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
} = new AvaloniaList<CustomAction>();
|
||||||
|
|
||||||
public bool EnableAutoFetch
|
public bool EnableAutoFetch
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
|
@ -230,5 +236,22 @@ namespace SourceGit.Models
|
||||||
if (rule != null)
|
if (rule != null)
|
||||||
IssueTrackerRules.Remove(rule);
|
IssueTrackerRules.Remove(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CustomAction AddNewCustomAction()
|
||||||
|
{
|
||||||
|
var act = new CustomAction()
|
||||||
|
{
|
||||||
|
Name = "Unnamed Custom Action",
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomActions.Add(act);
|
||||||
|
return act;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveCustomAction(CustomAction act)
|
||||||
|
{
|
||||||
|
if (act != null)
|
||||||
|
CustomActions.Remove(act);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<StreamGeometry x:Key="Icons.Action">M41 512c0-128 46-241 138-333C271 87 384 41 512 41s241 46 333 138c92 92 138 205 138 333s-46 241-138 333c-92 92-205 138-333 138s-241-46-333-138C87 753 41 640 41 512zm87 0c0 108 36 195 113 271s164 113 271 113c108 0 195-36 271-113s113-164 113-271-36-195-113-271c-77-77-164-113-271-113-108 0-195 36-271 113C164 317 128 404 128 512zm256 148V292l195 113L768 512l-195 113-195 113v-77zm148-113-61 36V440l61 36 61 36-61 36z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.AIAssist">M951 419a255 255 0 00-22-209 258 258 0 00-278-124A259 259 0 00213 178a255 255 0 00-171 124 258 258 0 0032 303 255 255 0 0022 210 258 258 0 00278 124A255 255 0 00566 1024a258 258 0 00246-179 256 256 0 00171-124 258 258 0 00-32-302zM566 957a191 191 0 01-123-44l6-3 204-118a34 34 0 0017-29v-287l86 50a3 3 0 012 2v238a192 192 0 01-192 192zM154 781a191 191 0 01-23-129l6 4 204 118a33 33 0 0033 0l249-144v99a3 3 0 01-1 3L416 851a192 192 0 01-262-70zM100 337a191 191 0 01101-84V495a33 33 0 0017 29l248 143-86 50a3 3 0 01-3 0l-206-119A192 192 0 01100 336zm708 164-249-145L645 307a3 3 0 013 0l206 119a192 192 0 01-29 346v-242a34 34 0 00-17-28zm86-129-6-4-204-119a33 33 0 00-33 0L401 394V294a3 3 0 011-3l206-119a192 192 0 01285 199zm-539 176-86-50a3 3 0 01-2-2V259a192 192 0 01315-147l-6 3-204 118a34 34 0 00-17 29zm47-101 111-64 111 64v128l-111 64-111-64z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.AIAssist">M951 419a255 255 0 00-22-209 258 258 0 00-278-124A259 259 0 00213 178a255 255 0 00-171 124 258 258 0 0032 303 255 255 0 0022 210 258 258 0 00278 124A255 255 0 00566 1024a258 258 0 00246-179 256 256 0 00171-124 258 258 0 00-32-302zM566 957a191 191 0 01-123-44l6-3 204-118a34 34 0 0017-29v-287l86 50a3 3 0 012 2v238a192 192 0 01-192 192zM154 781a191 191 0 01-23-129l6 4 204 118a33 33 0 0033 0l249-144v99a3 3 0 01-1 3L416 851a192 192 0 01-262-70zM100 337a191 191 0 01101-84V495a33 33 0 0017 29l248 143-86 50a3 3 0 01-3 0l-206-119A192 192 0 01100 336zm708 164-249-145L645 307a3 3 0 013 0l206 119a192 192 0 01-29 346v-242a34 34 0 00-17-28zm86-129-6-4-204-119a33 33 0 00-33 0L401 394V294a3 3 0 011-3l206-119a192 192 0 01285 199zm-539 176-86-50a3 3 0 01-2-2V259a192 192 0 01315-147l-6 3-204 118a34 34 0 00-17 29zm47-101 111-64 111 64v128l-111 64-111-64z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Archive">M296 392h64v64h-64zM296 582v160h128V582h-64v-62h-64v62zm80 48v64h-32v-64h32zM360 328h64v64h-64zM296 264h64v64h-64zM360 456h64v64h-64zM360 200h64v64h-64zM855 289 639 73c-6-6-14-9-23-9H192c-18 0-32 14-32 32v832c0 18 14 32 32 32h640c18 0 32-14 32-32V311c0-9-3-17-9-23zM790 326H602V138L790 326zm2 562H232V136h64v64h64v-64h174v216c0 23 19 42 42 42h216v494z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Archive">M296 392h64v64h-64zM296 582v160h128V582h-64v-62h-64v62zm80 48v64h-32v-64h32zM360 328h64v64h-64zM296 264h64v64h-64zM360 456h64v64h-64zM360 200h64v64h-64zM855 289 639 73c-6-6-14-9-23-9H192c-18 0-32 14-32 32v832c0 18 14 32 32 32h640c18 0 32-14 32-32V311c0-9-3-17-9-23zM790 326H602V138L790 326zm2 562H232V136h64v64h64v-64h174v216c0 23 19 42 42 42h216v494z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Binary">M71 1024V0h661L953 219V1024H71zm808-731-220-219H145V951h735V293zM439 512h-220V219h220V512zm-74-219H292v146h74v-146zm0 512h74v73h-220v-73H292v-146H218V585h147v219zm294-366h74V512H512v-73h74v-146H512V219h147v219zm74 439H512V585h220v293zm-74-219h-74v146h74v-146z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Binary">M71 1024V0h661L953 219V1024H71zm808-731-220-219H145V951h735V293zM439 512h-220V219h220V512zm-74-219H292v146h74v-146zm0 512h74v73h-220v-73H292v-146H218V585h147v219zm294-366h74V512H512v-73h74v-146H512V219h147v219zm74 439H512V585h220v293zm-74-219h-74v146h74v-146z</StreamGeometry>
|
||||||
|
|
|
@ -108,6 +108,7 @@
|
||||||
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
|
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copy Info</x:String>
|
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copy Info</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copy SHA</x:String>
|
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copy SHA</x:String>
|
||||||
|
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Custom Action</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactive Rebase ${0}$ to Here</x:String>
|
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactive Rebase ${0}$ to Here</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ to Here</x:String>
|
<x:String x:Key="Text.CommitCM.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.Reset" xml:space="preserve">Reset ${0}$ to Here</x:String>
|
||||||
|
@ -139,6 +140,14 @@
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">COMMIT TEMPLATE</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">COMMIT TEMPLATE</x:String>
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Template Name:</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Template Name:</x:String>
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Template Content:</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Template Content:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">CUSTOM ACTION</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">Arguments:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">${REPO} - Repository's path; ${SHA} - Selected commit's SHA</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Executable File:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Name:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Scope:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String>
|
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String>
|
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String>
|
||||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
||||||
|
@ -252,6 +261,8 @@
|
||||||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Target:</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Target:</x:String>
|
||||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Edit Selected Group</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Edit Selected Group</x:String>
|
||||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Edit Selected Repository</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Edit Selected Repository</x:String>
|
||||||
|
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Run Custom Action</x:String>
|
||||||
|
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Action Name:</x:String>
|
||||||
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String>
|
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String>
|
||||||
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
|
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
|
||||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch all remotes</x:String>
|
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch all remotes</x:String>
|
||||||
|
@ -516,6 +527,8 @@
|
||||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
|
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
|
||||||
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String>
|
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String>
|
||||||
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String>
|
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Custom Actions</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">No Custom Actions</x:String>
|
||||||
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Enable '--reflog' Option</x:String>
|
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Enable '--reflog' Option</x:String>
|
||||||
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open In File Browser</x:String>
|
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open In File Browser</x:String>
|
||||||
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Search Branches/Tags/Submodules</x:String>
|
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Search Branches/Tags/Submodules</x:String>
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
|
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">复制简要信息</x:String>
|
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">复制简要信息</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">复制提交指纹</x:String>
|
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">复制提交指纹</x:String>
|
||||||
|
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">自定义操作</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">交互式变基(rebase -i) ${0}$ 到此处</x:String>
|
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">交互式变基(rebase -i) ${0}$ 到此处</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 到此处</x:String>
|
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 到此处</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此处</x:String>
|
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此处</x:String>
|
||||||
|
@ -142,6 +143,14 @@
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交信息模板</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交信息模板</x:String>
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">模板名 :</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">模板名 :</x:String>
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">模板内容 :</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">模板内容 :</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">自定义操作</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">命令行参数 :</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">请使用${REPO}代替仓库路径,${SHA}代替提交哈希</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">可执行文件路径 :</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">名称 :</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">作用目标 :</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">选中的提交</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">仓库</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String>
|
<x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String>
|
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String>
|
||||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT配置</x:String>
|
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT配置</x:String>
|
||||||
|
@ -255,6 +264,8 @@
|
||||||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目标 :</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目标 :</x:String>
|
||||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">编辑分组</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">编辑分组</x:String>
|
||||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">编辑仓库</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">编辑仓库</x:String>
|
||||||
|
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">执行自定义操作</x:String>
|
||||||
|
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">自定义操作 :</x:String>
|
||||||
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快进(fast-forward,无需checkout)</x:String>
|
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快进(fast-forward,无需checkout)</x:String>
|
||||||
<x:String x:Key="Text.Fetch" xml:space="preserve">拉取(fetch)</x:String>
|
<x:String x:Key="Text.Fetch" xml:space="preserve">拉取(fetch)</x:String>
|
||||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">拉取所有的远程仓库</x:String>
|
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">拉取所有的远程仓库</x:String>
|
||||||
|
@ -519,6 +530,8 @@
|
||||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String>
|
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String>
|
||||||
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String>
|
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String>
|
||||||
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
|
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">自定义操作</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">自定义操作未设置</x:String>
|
||||||
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">启用 --reflog 选项</x:String>
|
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">启用 --reflog 选项</x:String>
|
||||||
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String>
|
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String>
|
||||||
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速查找分支/标签/子模块</x:String>
|
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速查找分支/标签/子模块</x:String>
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">與本機工作區比較</x:String>
|
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">與本機工作區比較</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">複製摘要資訊</x:String>
|
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">複製摘要資訊</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">複製提交編號</x:String>
|
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">複製提交編號</x:String>
|
||||||
|
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">自訂動作</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">互動式重定基底 (rebase -i) ${0}$ 到此處</x:String>
|
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">互動式重定基底 (rebase -i) ${0}$ 到此處</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 到此處</x:String>
|
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 到此處</x:String>
|
||||||
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重設 (reset) ${0}$ 到此處</x:String>
|
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重設 (reset) ${0}$ 到此處</x:String>
|
||||||
|
@ -142,6 +143,14 @@
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交訊息範本</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交訊息範本</x:String>
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">範本名稱:</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">範本名稱:</x:String>
|
||||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">範本內容:</x:String>
|
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">範本內容:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">自訂動作</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">指令行參數:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">使用${REPO}代表儲存庫的路徑,${SHA}代表所選的提交編號</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">可執行檔案路徑:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">名稱 :</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">執行範圍:</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">選取的提交</x:String>
|
||||||
|
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">存放庫</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵件</x:String>
|
<x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵件</x:String>
|
||||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">電子郵件地址</x:String>
|
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">電子郵件地址</x:String>
|
||||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">Git 設定</x:String>
|
<x:String x:Key="Text.Configure.Git" xml:space="preserve">Git 設定</x:String>
|
||||||
|
@ -255,6 +264,8 @@
|
||||||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目標:</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目標:</x:String>
|
||||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">編輯群組</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">編輯群組</x:String>
|
||||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">編輯存放庫</x:String>
|
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">編輯存放庫</x:String>
|
||||||
|
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">執行自訂動作</x:String>
|
||||||
|
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">自訂動作:</x:String>
|
||||||
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快進 (fast-forward,無需 checkout)</x:String>
|
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快進 (fast-forward,無需 checkout)</x:String>
|
||||||
<x:String x:Key="Text.Fetch" xml:space="preserve">提取 (fetch)</x:String>
|
<x:String x:Key="Text.Fetch" xml:space="preserve">提取 (fetch)</x:String>
|
||||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">提取所有的遠端存放庫</x:String>
|
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">提取所有的遠端存放庫</x:String>
|
||||||
|
@ -519,6 +530,8 @@
|
||||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String>
|
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String>
|
||||||
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">設定本存放庫</x:String>
|
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">設定本存放庫</x:String>
|
||||||
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
|
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">自訂動作</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">沒有自訂的動作</x:String>
|
||||||
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">啟用 [--reflog] 選項</x:String>
|
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">啟用 [--reflog] 選項</x:String>
|
||||||
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在檔案瀏覽器中開啟</x:String>
|
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在檔案瀏覽器中開啟</x:String>
|
||||||
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速搜尋分支/標籤/子模組</x:String>
|
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速搜尋分支/標籤/子模組</x:String>
|
||||||
|
|
40
src/ViewModels/ExecuteCustomAction.cs
Normal file
40
src/ViewModels/ExecuteCustomAction.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SourceGit.ViewModels
|
||||||
|
{
|
||||||
|
public class ExecuteCustomAction : Popup
|
||||||
|
{
|
||||||
|
public Models.CustomAction CustomAction
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExecuteCustomAction(Repository repo, Models.CustomAction action, string sha)
|
||||||
|
{
|
||||||
|
_repo = repo;
|
||||||
|
_args = action.Arguments.Replace("${REPO}", _repo.FullPath);
|
||||||
|
if (!string.IsNullOrEmpty(sha))
|
||||||
|
_args = _args.Replace("${SHA}", sha);
|
||||||
|
|
||||||
|
CustomAction = action;
|
||||||
|
View = new Views.ExecuteCustomAction() { DataContext = this };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<bool> Sure()
|
||||||
|
{
|
||||||
|
_repo.SetWatcherEnabled(false);
|
||||||
|
ProgressDescription = "Run custom action ...";
|
||||||
|
|
||||||
|
return Task.Run(() =>
|
||||||
|
{
|
||||||
|
Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, _args, SetProgressDescription);
|
||||||
|
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Repository _repo = null;
|
||||||
|
private string _args = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -605,6 +605,39 @@ namespace SourceGit.ViewModels
|
||||||
menu.Items.Add(archive);
|
menu.Items.Add(archive);
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
|
var actions = new List<Models.CustomAction>();
|
||||||
|
foreach (var action in _repo.Settings.CustomActions)
|
||||||
|
{
|
||||||
|
if (action.Scope == Models.CustomActionScope.Commit)
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
if (actions.Count > 0)
|
||||||
|
{
|
||||||
|
var custom = new MenuItem();
|
||||||
|
custom.Header = App.Text("CommitCM.CustomAction");
|
||||||
|
custom.Icon = App.CreateMenuIcon("Icons.Action");
|
||||||
|
|
||||||
|
foreach (var action in actions)
|
||||||
|
{
|
||||||
|
var dup = action;
|
||||||
|
var item = new MenuItem();
|
||||||
|
item.Icon = App.CreateMenuIcon("Icons.Action");
|
||||||
|
item.Header = dup.Name;
|
||||||
|
item.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
if (PopupHost.CanCreatePopup())
|
||||||
|
PopupHost.ShowAndStartPopup(new ExecuteCustomAction(_repo, action, commit.SHA));
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
custom.Items.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.Items.Add(custom);
|
||||||
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
}
|
||||||
|
|
||||||
var copySHA = new MenuItem();
|
var copySHA = new MenuItem();
|
||||||
copySHA.Header = App.Text("CommitCM.CopySHA");
|
copySHA.Header = App.Text("CommitCM.CopySHA");
|
||||||
copySHA.Icon = App.CreateMenuIcon("Icons.Copy");
|
copySHA.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||||
|
|
|
@ -1287,6 +1287,45 @@ namespace SourceGit.ViewModels
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ContextMenu CreateContextMenuForCustomAction()
|
||||||
|
{
|
||||||
|
var actions = new List<Models.CustomAction>();
|
||||||
|
foreach (var action in _settings.CustomActions)
|
||||||
|
{
|
||||||
|
if (action.Scope == Models.CustomActionScope.Repository)
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
var menu = new ContextMenu();
|
||||||
|
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
||||||
|
|
||||||
|
if (actions.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var action in actions)
|
||||||
|
{
|
||||||
|
var dup = action;
|
||||||
|
var item = new MenuItem();
|
||||||
|
item.Icon = App.CreateMenuIcon("Icons.Action");
|
||||||
|
item.Header = dup.Name;
|
||||||
|
item.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
if (PopupHost.CanCreatePopup())
|
||||||
|
PopupHost.ShowAndStartPopup(new ExecuteCustomAction(this, action, null));
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
menu.Items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
menu.Items.Add(new MenuItem() { Header = App.Text("Repository.CustomActions.Empty") });
|
||||||
|
}
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
|
public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
|
||||||
{
|
{
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
|
|
|
@ -127,6 +127,17 @@ namespace SourceGit.ViewModels
|
||||||
set => _repo.Settings.PreferedOpenAIService = value;
|
set => _repo.Settings.PreferedOpenAIService = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AvaloniaList<Models.CustomAction> CustomActions
|
||||||
|
{
|
||||||
|
get => _repo.Settings.CustomActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Models.CustomAction SelectedCustomAction
|
||||||
|
{
|
||||||
|
get => _selectedCustomAction;
|
||||||
|
set => SetProperty(ref _selectedCustomAction, value);
|
||||||
|
}
|
||||||
|
|
||||||
public RepositoryConfigure(Repository repo)
|
public RepositoryConfigure(Repository repo)
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
|
@ -233,11 +244,21 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public void RemoveSelectedIssueTracker()
|
public void RemoveSelectedIssueTracker()
|
||||||
{
|
{
|
||||||
if (_selectedIssueTrackerRule != null)
|
_repo.Settings.RemoveIssueTracker(_selectedIssueTrackerRule);
|
||||||
_repo.Settings.RemoveIssueTracker(_selectedIssueTrackerRule);
|
|
||||||
SelectedIssueTrackerRule = null;
|
SelectedIssueTrackerRule = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddNewCustomAction()
|
||||||
|
{
|
||||||
|
SelectedCustomAction = _repo.Settings.AddNewCustomAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveSelectedCustomAction()
|
||||||
|
{
|
||||||
|
_repo.Settings.RemoveCustomAction(_selectedCustomAction);
|
||||||
|
SelectedCustomAction = null;
|
||||||
|
}
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
SetIfChanged("user.name", UserName, "");
|
SetIfChanged("user.name", UserName, "");
|
||||||
|
@ -271,5 +292,6 @@ namespace SourceGit.ViewModels
|
||||||
private string _httpProxy;
|
private string _httpProxy;
|
||||||
private Models.CommitTemplate _selectedCommitTemplate = null;
|
private Models.CommitTemplate _selectedCommitTemplate = null;
|
||||||
private Models.IssueTrackerRule _selectedIssueTrackerRule = null;
|
private Models.IssueTrackerRule _selectedIssueTrackerRule = null;
|
||||||
|
private Models.CustomAction _selectedCustomAction = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
src/Views/ExecuteCustomAction.axaml
Normal file
19
src/Views/ExecuteCustomAction.axaml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<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"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||||
|
x:Class="SourceGit.Views.ExecuteCustomAction"
|
||||||
|
x:DataType="vm:ExecuteCustomAction">
|
||||||
|
<StackPanel Orientation="Vertical" Margin="8,0">
|
||||||
|
<TextBlock FontSize="18"
|
||||||
|
Classes="bold"
|
||||||
|
Text="{DynamicResource Text.ExecuteCustomAction}"/>
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0">
|
||||||
|
<TextBlock Text="{DynamicResource Text.ExecuteCustomAction.Name}"/>
|
||||||
|
<Path Width="14" Height="14" Margin="8,0,0,0" Data="{StaticResource Icons.Action}"/>
|
||||||
|
<TextBlock Text="{Binding CustomAction.Name}" Margin="8,0,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
12
src/Views/ExecuteCustomAction.axaml.cs
Normal file
12
src/Views/ExecuteCustomAction.axaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace SourceGit.Views
|
||||||
|
{
|
||||||
|
public partial class ExecuteCustomAction : UserControl
|
||||||
|
{
|
||||||
|
public ExecuteCustomAction()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
xmlns:m="using:SourceGit.Models"
|
xmlns:m="using:SourceGit.Models"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
|
xmlns:ac="using:Avalonia.Controls.Converters"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.RepositoryConfigure"
|
x:Class="SourceGit.Views.RepositoryConfigure"
|
||||||
x:DataType="vm:RepositoryConfigure"
|
x:DataType="vm:RepositoryConfigure"
|
||||||
|
@ -338,6 +339,116 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem>
|
||||||
|
<TabItem.Header>
|
||||||
|
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.CustomAction}"/>
|
||||||
|
</TabItem.Header>
|
||||||
|
|
||||||
|
<Grid ColumnDefinitions="200,*" Height="250" Margin="0,8,0,16">
|
||||||
|
<Border Grid.Column="0"
|
||||||
|
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
|
Background="{DynamicResource Brush.Contents}">
|
||||||
|
<Grid RowDefinitions="*,1,Auto">
|
||||||
|
<ListBox Grid.Row="0"
|
||||||
|
Background="Transparent"
|
||||||
|
ItemsSource="{Binding CustomActions}"
|
||||||
|
SelectedItem="{Binding SelectedCustomAction, Mode=TwoWay}"
|
||||||
|
SelectionMode="Single">
|
||||||
|
<ListBox.Styles>
|
||||||
|
<Style Selector="ListBoxItem">
|
||||||
|
<Setter Property="MinHeight" Value="0"/>
|
||||||
|
<Setter Property="Height" Value="26"/>
|
||||||
|
<Setter Property="Padding" Value="4,2"/>
|
||||||
|
</Style>
|
||||||
|
</ListBox.Styles>
|
||||||
|
|
||||||
|
<ListBox.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Vertical"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ListBox.ItemsPanel>
|
||||||
|
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate DataType="m:CustomAction">
|
||||||
|
<Grid Margin="4,0" ColumnDefinitions="Auto,*">
|
||||||
|
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Action}" Fill="{DynamicResource Brush.FG1}"/>
|
||||||
|
<TextBlock Grid.Column="1" Text="{Binding Name}" Margin="6,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
|
||||||
|
<Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="{DynamicResource Brush.ToolBar}">
|
||||||
|
<Button Classes="icon_button" Command="{Binding AddNewCustomAction}">
|
||||||
|
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
|
||||||
|
|
||||||
|
<Button Classes="icon_button" Command="{Binding RemoveSelectedCustomAction}">
|
||||||
|
<Path Width="14" Height="14" Data="{StaticResource Icons.Window.Minimize}"/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<ContentControl Grid.Column="1" Margin="16,0,0,0">
|
||||||
|
<ContentControl.Content>
|
||||||
|
<Binding Path="SelectedCustomAction">
|
||||||
|
<Binding.TargetNullValue>
|
||||||
|
<Path Width="64" Height="64"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Fill="{DynamicResource Brush.FG2}"
|
||||||
|
Data="{StaticResource Icons.Empty}"/>
|
||||||
|
</Binding.TargetNullValue>
|
||||||
|
</Binding>
|
||||||
|
</ContentControl.Content>
|
||||||
|
|
||||||
|
<ContentControl.DataTemplates>
|
||||||
|
<DataTemplate DataType="m:CustomAction">
|
||||||
|
<StackPanel Orientation="Vertical">
|
||||||
|
<TextBlock Text="{DynamicResource Text.Configure.CustomAction.Name}"/>
|
||||||
|
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Name, Mode=TwoWay}"/>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,12,0,0">
|
||||||
|
<StackPanel.Resources>
|
||||||
|
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
|
||||||
|
</StackPanel.Resources>
|
||||||
|
|
||||||
|
<TextBlock Text="{DynamicResource Text.Configure.CustomAction.Scope}"/>
|
||||||
|
<RadioButton Content="{DynamicResource Text.Configure.CustomAction.Scope.Repository}"
|
||||||
|
GroupName="CustomActionScope"
|
||||||
|
Margin="8,0"
|
||||||
|
IsChecked="{Binding Scope, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:CustomActionScope.Repository}}"/>
|
||||||
|
<RadioButton Content="{DynamicResource Text.Configure.CustomAction.Scope.Commit}"
|
||||||
|
GroupName="CustomActionScope"
|
||||||
|
IsChecked="{Binding Scope, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:CustomActionScope.Commit}}"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CustomAction.Executable}"/>
|
||||||
|
<TextBox Margin="0,4,0,0" Height="28" CornerRadius="3" Text="{Binding Executable, Mode=TwoWay}">
|
||||||
|
<TextBox.InnerRightContent>
|
||||||
|
<Button Classes="icon_button" Width="30" Height="30" Click="SelectExecutableForCustomAction">
|
||||||
|
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||||
|
</Button>
|
||||||
|
</TextBox.InnerRightContent>
|
||||||
|
</TextBox>
|
||||||
|
|
||||||
|
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CustomAction.Arguments}"/>
|
||||||
|
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Arguments, Mode=TwoWay}"/>
|
||||||
|
<TextBlock Margin="0,2,0,0" TextWrapping="Wrap" Text="{DynamicResource Text.Configure.CustomAction.Arguments.Tip}" Foreground="{DynamicResource Brush.FG2}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ContentControl.DataTemplates>
|
||||||
|
</ContentControl>
|
||||||
|
</Grid>
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
<TabItem>
|
<TabItem>
|
||||||
<TabItem.Header>
|
<TabItem.Header>
|
||||||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.OpenAI}"/>
|
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.OpenAI}"/>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
|
@ -14,5 +16,20 @@ namespace SourceGit.Views
|
||||||
(DataContext as ViewModels.RepositoryConfigure)?.Save();
|
(DataContext as ViewModels.RepositoryConfigure)?.Save();
|
||||||
base.OnClosing(e);
|
base.OnClosing(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void SelectExecutableForCustomAction(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var options = new FilePickerOpenOptions()
|
||||||
|
{
|
||||||
|
FileTypeFilter = [new FilePickerFileType("Executable file(script)") { Patterns = ["*.*"] }],
|
||||||
|
AllowMultiple = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var selected = await StorageProvider.OpenFilePickerAsync(options);
|
||||||
|
if (selected.Count == 1 && sender is Button { DataContext: Models.CustomAction action })
|
||||||
|
action.Executable = selected[0].Path.LocalPath;
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,10 @@
|
||||||
<Path Width="14" Height="14" Data="{StaticResource Icons.LFS}"/>
|
<Path Width="14" Height="14" Data="{StaticResource Icons.LFS}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenCustomActionMenu" ToolTip.Tip="{DynamicResource Text.Repository.CustomActions}">
|
||||||
|
<Path Width="14" Height="14" Data="{StaticResource Icons.Action}"/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Command="{Binding Cleanup}" ToolTip.Tip="{DynamicResource Text.Repository.Clean}">
|
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Command="{Binding Cleanup}" ToolTip.Tip="{DynamicResource Text.Repository.Clean}">
|
||||||
<Path Width="14" Height="14" Margin="0,1,0,0" Data="{StaticResource Icons.Clean}"/>
|
<Path Width="14" Height="14" Margin="0,1,0,0" Data="{StaticResource Icons.Clean}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -91,6 +91,17 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OpenCustomActionMenu(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataContext is ViewModels.Repository repo)
|
||||||
|
{
|
||||||
|
var menu = repo.CreateContextMenuForCustomAction();
|
||||||
|
(sender as Control)?.OpenContextMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue