mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-06-26 21:04:59 +00:00
feature: support to use input control in custom action
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
parent
a8803ca188
commit
676785f8b1
26 changed files with 659 additions and 56 deletions
|
@ -1,4 +1,5 @@
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Avalonia.Collections;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
|
@ -9,6 +10,52 @@ namespace SourceGit.Models
|
|||
Branch,
|
||||
}
|
||||
|
||||
public enum CustomActionControlType
|
||||
{
|
||||
TextBox = 0,
|
||||
PathSelector,
|
||||
CheckBox,
|
||||
}
|
||||
|
||||
public class CustomActionControl : ObservableObject
|
||||
{
|
||||
public CustomActionControlType Type
|
||||
{
|
||||
get => _type;
|
||||
set => SetProperty(ref _type, value);
|
||||
}
|
||||
|
||||
public string Label
|
||||
{
|
||||
get => _label;
|
||||
set => SetProperty(ref _label, value);
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get => _description;
|
||||
set => SetProperty(ref _description, value);
|
||||
}
|
||||
|
||||
public string StringValue
|
||||
{
|
||||
get => _stringValue;
|
||||
set => SetProperty(ref _stringValue, value);
|
||||
}
|
||||
|
||||
public bool BoolValue
|
||||
{
|
||||
get => _boolValue;
|
||||
set => SetProperty(ref _boolValue, value);
|
||||
}
|
||||
|
||||
private CustomActionControlType _type = CustomActionControlType.TextBox;
|
||||
private string _label = string.Empty;
|
||||
private string _description = string.Empty;
|
||||
private string _stringValue = string.Empty;
|
||||
private bool _boolValue = false;
|
||||
}
|
||||
|
||||
public class CustomAction : ObservableObject
|
||||
{
|
||||
public string Name
|
||||
|
@ -35,6 +82,12 @@ namespace SourceGit.Models
|
|||
set => SetProperty(ref _arguments, value);
|
||||
}
|
||||
|
||||
public AvaloniaList<CustomActionControl> Controls
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = [];
|
||||
|
||||
public bool WaitForExit
|
||||
{
|
||||
get => _waitForExit;
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
<StreamGeometry x:Key="Icons.OpenWith">M683 409v204L1024 308 683 0v191c-413 0-427 526-427 526c117-229 203-307 427-307zm85 492H102V327h153s38-63 114-122H51c-28 0-51 27-51 61v697c0 34 23 61 51 61h768c28 0 51-27 51-61V614l-102 100v187z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.OrderByName">M841 627A43 43 0 00811 555h-299v85h196l-183 183A43 43 0 00555 896h299v-85h-196l183-183zM299 170H213v512H85l171 171 171-171H299zM725 128h-85c-18 0-34 11-40 28l-117 313h91L606 384h154l32 85h91l-117-313A43 43 0 00725 128zm-88 171 32-85h26l32 85h-90z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.OrderByTime">M512 0a512 512 0 01512 512 57 57 0 01-114 0 398 398 0 10-398 398 57 57 0 010 114A512 512 0 01512 0zm367 600 121 120a57 57 0 01-80 81l-40-40V967a57 57 0 01-50 57l-7 0a57 57 0 01-57-57v-205l-40 40a57 57 0 01-75 5l-5-5a57 57 0 01-0-80l120-121a80 80 0 01113-0zM512 272a57 57 0 0157 57V499h114a57 57 0 0156 50L740 556a57 57 0 01-57 57H512a57 57 0 01-57-57v-228a57 57 0 0150-57L512 272z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Parameter">M834 0H190C85 0 0 85 0 189v646c0 104 85 189 189 189h645c104 0 189-85 189-189V189C1024 85 939 0 834 0zM658 748c-25 29-62 47-111 54v54h-66v-56c-38-4-72-19-101-44-29-26-43-71-43-135v-28h144v35c0 39 1 63 4 72 3 9 10 14 22 14 10 0 17-3 22-10 5-7 7-16 7-29 0-32-2-55-7-69-5-14-20-29-46-45-44-28-74-48-90-61-16-13-29-31-41-55-12-24-17-50-17-80 0-43 12-77 37-101 24-24 61-40 110-45v-46h66v46c44 6 78 21 100 45 22 24 33 57 33 100 0 6-0 15-1 27H535v-24c0-25-2-42-5-50-3-8-10-12-21-12-9 0-15 3-20 10-4 7-7 17-7 30 0 23 5 38 14 47 9 9 35 27 78 53 37 22 62 39 75 51 13 12 25 28 34 50 9 22 14 48 14 80 0 51-12 92-37 121z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Password">M640 96c-158 0-288 130-288 288 0 17 3 31 5 46L105 681 96 691V928h224v-96h96v-96h96v-95c38 18 82 31 128 31 158 0 288-130 288-288s-130-288-288-288zm0 64c123 0 224 101 224 224s-101 224-224 224a235 235 0 01-109-28l-8-4H448v96h-96v96H256v96H160v-146l253-254 12-11-3-17C419 417 416 400 416 384c0-123 101-224 224-224zm64 96a64 64 0 100 128 64 64 0 100-128z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Paste">M544 85c49 0 90 37 95 85h75a96 96 0 0196 89L811 267a32 32 0 01-28 32L779 299a32 32 0 01-32-28L747 267a32 32 0 00-28-32L715 235h-91a96 96 0 01-80 42H395c-33 0-62-17-80-42L224 235a32 32 0 00-32 28L192 267v576c0 16 12 30 28 32l4 0h128a32 32 0 0132 28l0 4a32 32 0 01-32 32h-128a96 96 0 01-96-89L128 843V267a96 96 0 0189-96L224 171h75a96 96 0 0195-85h150zm256 256a96 96 0 0196 89l0 7v405a96 96 0 01-89 96L800 939h-277a96 96 0 01-96-89L427 843v-405a96 96 0 0189-96L523 341h277zm-256-192H395a32 32 0 000 64h150a32 32 0 100-64z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Pattern">M470 722q-23 3-43 3T384 722v-150l-106 106q-34-26-60-59L324 512H174q-3-23-3-43t3-42h150L218 320q16-20 28-32t32-27L384 367V217q23-4 43-4t43 4v150l106-106q34 26 60 59l-106 107h150q3 22 3 42T680 512h-150l106 107q-16 20-28 32t-32 27l-106-106v150zM0 811q0-36 25-61t61-25 61 25 25 61-25 61-61 25-61-25T0 811z</StreamGeometry>
|
||||
|
|
|
@ -304,8 +304,6 @@
|
|||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Ziel:</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Ausgewählte Gruppe bearbeiten</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Ausgewähltes Repository bearbeiten</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Führe benutzerdefinierte Aktion aus</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Name der Aktion:</x:String>
|
||||
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Alle Remotes fetchen</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Aktiviere '--force' Option</x:String>
|
||||
|
|
|
@ -162,6 +162,9 @@
|
|||
<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; ${BRANCH} - Selected branch; ${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.InputControls" xml:space="preserve">Input Controls:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls.Edit" xml:space="preserve">Edit</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls.Tip" xml:space="preserve">You can use $1, $2 ... in arguments for input control values</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.Branch" xml:space="preserve">Branch</x:String>
|
||||
|
@ -195,6 +198,14 @@
|
|||
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP proxy used by this repository</x:String>
|
||||
<x:String x:Key="Text.Configure.User" xml:space="preserve">User Name</x:String>
|
||||
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">User name for this repository</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls" xml:space="preserve">Edit Custom Action Controls</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.CheckedValue" xml:space="preserve">Checked Value:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Description" xml:space="preserve">Description:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Description.Placeholder" xml:space="preserve">Used as placeholder in TextBox/PathSelector or tooltip in CheckBox</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.DefaultValue" xml:space="preserve">Default:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.IsFolder" xml:space="preserve">Is Folder:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Label" xml:space="preserve">Label:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Type" xml:space="preserve">Type:</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">Workspaces</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">Color</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">Name</x:String>
|
||||
|
@ -300,8 +311,7 @@
|
|||
<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.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.ExecuteCustomAction.SimpleWait" xml:space="preserve">Action is running, please wait...</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.Force" xml:space="preserve">Force override local refs</x:String>
|
||||
|
|
|
@ -300,8 +300,6 @@
|
|||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Destino:</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Editar Grupo Seleccionado</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Editar Repositorio Seleccionado</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Ejecutar Acción Personalizada</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nombre de la Acción:</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 todos los remotos</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Utilizar opción '--force'</x:String>
|
||||
|
|
|
@ -273,8 +273,6 @@
|
|||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Cible :</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Éditer le groupe sélectionné</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Éditer le dépôt sélectionné</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Lancer action personnalisée</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nom de l'action :</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 toutes les branches distantes</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Outrepasser les vérifications de refs</x:String>
|
||||
|
|
|
@ -290,8 +290,6 @@
|
|||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Destinazione:</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Modifica Gruppo Selezionato</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Modifica Repository Selezionato</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Esegui Azione Personalizzata</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nome Azione:</x:String>
|
||||
<x:String x:Key="Text.Fetch" xml:space="preserve">Recupera</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Recupera da tutti i remoti</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Forza la sovrascrittura dei riferimenti locali</x:String>
|
||||
|
|
|
@ -272,8 +272,6 @@
|
|||
<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.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.Fetch" xml:space="preserve">フェッチ</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">すべてのリモートをフェッチ</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">ローカル参照を強制的に上書き</x:String>
|
||||
|
|
|
@ -247,8 +247,6 @@
|
|||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Alvo:</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Editar Grupo Selecionado</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Editar Repositório Selecionado</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Executar ação customizada</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nome da ação:</x:String>
|
||||
<x:String x:Key="Text.Fetch" xml:space="preserve">Buscar</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Buscar todos os remotos</x:String>
|
||||
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">Buscar sem tags</x:String>
|
||||
|
|
|
@ -301,8 +301,6 @@
|
|||
<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.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.Fetch" xml:space="preserve">Извлечь</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Извлечь все внешние репозитории</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Разрешить опцию (--force)</x:String>
|
||||
|
|
|
@ -272,8 +272,6 @@
|
|||
<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.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.Fetch" xml:space="preserve">பெறு</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">எல்லா தொலைகளையும் பெறு</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">உள்ளக குறிப்புகளை கட்டாயமாக மீறு</x:String>
|
||||
|
|
|
@ -277,8 +277,6 @@
|
|||
<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.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.Fetch" xml:space="preserve">Витягти</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Витягти всі віддалені сховища</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Примусово перезаписати локальні refs</x:String>
|
||||
|
|
|
@ -166,6 +166,9 @@
|
|||
<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}代替仓库路径,${BRANCH}代替选中的分支,${SHA}代替提交哈希</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">可执行文件路径 :</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls" xml:space="preserve">输入控件 :</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls.Edit" xml:space="preserve">编辑</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls.Tip" xml:space="preserve">请在命令行参数中使用 $1, $2 等占位符表示输入控件的值</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.Branch" xml:space="preserve">选中的分支</x:String>
|
||||
|
@ -199,6 +202,14 @@
|
|||
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP网络代理</x:String>
|
||||
<x:String x:Key="Text.Configure.User" xml:space="preserve">用户名</x:String>
|
||||
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">应用于本仓库的用户名</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls" xml:space="preserve">编辑自定义操作输入控件</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.CheckedValue" xml:space="preserve">启用时命令行参数 :</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Description" xml:space="preserve">描述 :</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Description.Placeholder" xml:space="preserve">TextBox及Path Selector中用作Placeholder,CheckBox中用作ToolTip</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.DefaultValue" xml:space="preserve">默认值 :</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.IsFolder" xml:space="preserve">目标是否是目录 :</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Label" xml:space="preserve">名称 :</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Type" xml:space="preserve">类型 :</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">工作区</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">颜色</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">名称</x:String>
|
||||
|
@ -304,8 +315,7 @@
|
|||
<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.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.ExecuteCustomAction.SimpleWait" xml:space="preserve">操作正在进行中,请耐心等待...</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.Force" xml:space="preserve">强制覆盖本地REFs</x:String>
|
||||
|
|
|
@ -166,6 +166,9 @@
|
|||
<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} 表示存放庫路徑、${BRANCH} 表示所選的分支、${SHA} 表示所選的提交編號</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">可執行檔案路徑:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls" xml:space="preserve">輸入控件:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls.Edit" xml:space="preserve">編輯</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls.Tip" xml:space="preserve">請使用占位符如 $1, $2 來代表輸入控制項的值</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.Branch" xml:space="preserve">選取的分支</x:String>
|
||||
|
@ -199,6 +202,14 @@
|
|||
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP 網路代理</x:String>
|
||||
<x:String x:Key="Text.Configure.User" xml:space="preserve">使用者名稱</x:String>
|
||||
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">用於本存放庫的使用者名稱</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls" xml:space="preserve">編輯自訂動作輸入控件</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.CheckedValue" xml:space="preserve">啟用時的指令行參數:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Description" xml:space="preserve">描述:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Description.Placeholder" xml:space="preserve">在 TextBox/PathSelector 中用作占位符,或在 CheckBox 中用作工具提示</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.DefaultValue" xml:space="preserve">預設值:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.IsFolder" xml:space="preserve">目標路徑是否為資料夾:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Label" xml:space="preserve">名稱:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Type" xml:space="preserve">類型:</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">工作區</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">顏色</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">名稱</x:String>
|
||||
|
@ -304,8 +315,7 @@
|
|||
<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.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.ExecuteCustomAction.SimpleWait" xml:space="preserve">動作正在執行中,請稍候...</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.Force" xml:space="preserve">強制覆寫本機 REFs</x:String>
|
||||
|
|
62
src/ViewModels/ConfigureCustomActionControls.cs
Normal file
62
src/ViewModels/ConfigureCustomActionControls.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
using Avalonia.Collections;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class ConfigureCustomActionControls : ObservableObject
|
||||
{
|
||||
public AvaloniaList<Models.CustomActionControl> Controls
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public Models.CustomActionControl Edit
|
||||
{
|
||||
get => _edit;
|
||||
set => SetProperty(ref _edit, value);
|
||||
}
|
||||
|
||||
public ConfigureCustomActionControls(AvaloniaList<Models.CustomActionControl> controls)
|
||||
{
|
||||
Controls = controls;
|
||||
}
|
||||
|
||||
public void Add()
|
||||
{
|
||||
var added = new Models.CustomActionControl() { Type = Models.CustomActionControlType.TextBox };
|
||||
Controls.Add(added);
|
||||
Edit = added;
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
if (_edit == null)
|
||||
return;
|
||||
|
||||
Controls.Remove(_edit);
|
||||
Edit = null;
|
||||
}
|
||||
|
||||
public void MoveUp()
|
||||
{
|
||||
if (_edit == null)
|
||||
return;
|
||||
|
||||
var idx = Controls.IndexOf(_edit);
|
||||
if (idx > 0)
|
||||
Controls.Move(idx - 1, idx);
|
||||
}
|
||||
|
||||
public void MoveDown()
|
||||
{
|
||||
if (_edit == null)
|
||||
return;
|
||||
|
||||
var idx = Controls.IndexOf(_edit);
|
||||
if (idx < Controls.Count - 1)
|
||||
Controls.Move(idx + 1, idx);
|
||||
}
|
||||
|
||||
private Models.CustomActionControl _edit;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,75 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public interface ICustomActionControlParameter
|
||||
{
|
||||
string GetValue();
|
||||
}
|
||||
|
||||
public class CustomActionControlTextBox : ICustomActionControlParameter
|
||||
{
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public string Placeholder { get; set; } = string.Empty;
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
public CustomActionControlTextBox(string label, string placeholder, string defaultValue)
|
||||
{
|
||||
Label = label;
|
||||
Placeholder = placeholder;
|
||||
Text = defaultValue;
|
||||
}
|
||||
|
||||
public string GetValue() => Text;
|
||||
}
|
||||
|
||||
public class CustomActionControlPathSelector : ObservableObject, ICustomActionControlParameter
|
||||
{
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public string Placeholder { get; set; } = string.Empty;
|
||||
public bool IsFolder { get; set; } = false;
|
||||
|
||||
public string Path
|
||||
{
|
||||
get => _path;
|
||||
set => SetProperty(ref _path, value);
|
||||
}
|
||||
|
||||
public CustomActionControlPathSelector(string label, string placeholder, bool isFolder, string defaultValue)
|
||||
{
|
||||
Label = label;
|
||||
Placeholder = placeholder;
|
||||
IsFolder = isFolder;
|
||||
_path = defaultValue;
|
||||
}
|
||||
|
||||
public string GetValue() => _path;
|
||||
|
||||
private string _path = string.Empty;
|
||||
}
|
||||
|
||||
public class CustomActionControlCheckBox : ICustomActionControlParameter
|
||||
{
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public string ToolTip { get; set; } = string.Empty;
|
||||
public string CheckedValue { get; set; } = string.Empty;
|
||||
public bool IsChecked { get; set; }
|
||||
|
||||
public CustomActionControlCheckBox(string label, string tooltip, string checkedValue, bool isChecked)
|
||||
{
|
||||
Label = label;
|
||||
ToolTip = string.IsNullOrEmpty(tooltip) ? null : tooltip;
|
||||
CheckedValue = checkedValue;
|
||||
IsChecked = isChecked;
|
||||
}
|
||||
|
||||
public string GetValue() => IsChecked ? CheckedValue : string.Empty;
|
||||
}
|
||||
|
||||
public class ExecuteCustomAction : Popup
|
||||
{
|
||||
public Models.CustomAction CustomAction
|
||||
|
@ -10,25 +77,38 @@ namespace SourceGit.ViewModels
|
|||
get;
|
||||
}
|
||||
|
||||
public List<ICustomActionControlParameter> ControlParameters
|
||||
{
|
||||
get;
|
||||
} = [];
|
||||
|
||||
public bool IsSimpleMode
|
||||
{
|
||||
get => ControlParameters.Count == 0;
|
||||
}
|
||||
|
||||
public ExecuteCustomAction(Repository repo, Models.CustomAction action)
|
||||
{
|
||||
_repo = repo;
|
||||
_args = action.Arguments.Replace("${REPO}", GetWorkdir());
|
||||
_commandline = action.Arguments.Replace("${REPO}", GetWorkdir());
|
||||
CustomAction = action;
|
||||
PrepareControlParameters();
|
||||
}
|
||||
|
||||
public ExecuteCustomAction(Repository repo, Models.CustomAction action, Models.Branch branch)
|
||||
{
|
||||
_repo = repo;
|
||||
_args = action.Arguments.Replace("${REPO}", GetWorkdir()).Replace("${BRANCH}", branch.FriendlyName);
|
||||
_commandline = action.Arguments.Replace("${REPO}", GetWorkdir()).Replace("${BRANCH}", branch.FriendlyName);
|
||||
CustomAction = action;
|
||||
PrepareControlParameters();
|
||||
}
|
||||
|
||||
public ExecuteCustomAction(Repository repo, Models.CustomAction action, Models.Commit commit)
|
||||
{
|
||||
_repo = repo;
|
||||
_args = action.Arguments.Replace("${REPO}", GetWorkdir()).Replace("${SHA}", commit.SHA);
|
||||
_commandline = action.Arguments.Replace("${REPO}", GetWorkdir()).Replace("${SHA}", commit.SHA);
|
||||
CustomAction = action;
|
||||
PrepareControlParameters();
|
||||
}
|
||||
|
||||
public override Task<bool> Sure()
|
||||
|
@ -36,15 +116,22 @@ namespace SourceGit.ViewModels
|
|||
_repo.SetWatcherEnabled(false);
|
||||
ProgressDescription = "Run custom action ...";
|
||||
|
||||
var cmdline = _commandline;
|
||||
for (var i = 0; i < ControlParameters.Count; i++)
|
||||
{
|
||||
var param = ControlParameters[i];
|
||||
cmdline = cmdline.Replace($"${i}", param.GetValue());
|
||||
}
|
||||
|
||||
var log = _repo.CreateLog(CustomAction.Name);
|
||||
Use(log);
|
||||
|
||||
return Task.Run(() =>
|
||||
{
|
||||
if (CustomAction.WaitForExit)
|
||||
Commands.ExecuteCustomAction.RunAndWait(_repo.FullPath, CustomAction.Executable, _args, log);
|
||||
Commands.ExecuteCustomAction.RunAndWait(_repo.FullPath, CustomAction.Executable, cmdline, log);
|
||||
else
|
||||
Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, _args);
|
||||
Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, cmdline);
|
||||
|
||||
log.Complete();
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
|
@ -52,12 +139,31 @@ namespace SourceGit.ViewModels
|
|||
});
|
||||
}
|
||||
|
||||
private void PrepareControlParameters()
|
||||
{
|
||||
foreach (var ctl in CustomAction.Controls)
|
||||
{
|
||||
switch (ctl.Type)
|
||||
{
|
||||
case Models.CustomActionControlType.TextBox:
|
||||
ControlParameters.Add(new CustomActionControlTextBox(ctl.Label, ctl.Description, ctl.StringValue));
|
||||
break;
|
||||
case Models.CustomActionControlType.CheckBox:
|
||||
ControlParameters.Add(new CustomActionControlCheckBox(ctl.Label, ctl.Description, ctl.StringValue, ctl.BoolValue));
|
||||
break;
|
||||
case Models.CustomActionControlType.PathSelector:
|
||||
ControlParameters.Add(new CustomActionControlPathSelector(ctl.Label, ctl.Description, ctl.BoolValue, ctl.StringValue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetWorkdir()
|
||||
{
|
||||
return OperatingSystem.IsWindows() ? _repo.FullPath.Replace("/", "\\") : _repo.FullPath;
|
||||
}
|
||||
|
||||
private readonly Repository _repo = null;
|
||||
private readonly string _args;
|
||||
private readonly string _commandline = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -806,9 +806,7 @@ namespace SourceGit.ViewModels
|
|||
item.Header = dup.Name;
|
||||
item.Click += (_, e) =>
|
||||
{
|
||||
if (_repo.CanCreatePopup())
|
||||
_repo.ShowAndStartPopup(new ExecuteCustomAction(_repo, dup, commit));
|
||||
|
||||
_repo.ExecCustomAction(dup, commit);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -819,17 +819,34 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
|
||||
public void ApplyPatch()
|
||||
{
|
||||
if (CanCreatePopup())
|
||||
ShowPopup(new Apply(this));
|
||||
}
|
||||
|
||||
public void ExecCustomAction(Models.CustomAction action, object scope)
|
||||
{
|
||||
if (!CanCreatePopup())
|
||||
return;
|
||||
ShowPopup(new Apply(this));
|
||||
|
||||
var popup = null as ExecuteCustomAction;
|
||||
if (scope is Models.Branch b)
|
||||
popup = new ExecuteCustomAction(this, action, b);
|
||||
else if (scope is Models.Commit c)
|
||||
popup = new ExecuteCustomAction(this, action, c);
|
||||
else
|
||||
popup = new ExecuteCustomAction(this, action);
|
||||
|
||||
if (action.Controls.Count == 0)
|
||||
ShowAndStartPopup(popup);
|
||||
else
|
||||
ShowPopup(popup);
|
||||
}
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
if (!CanCreatePopup())
|
||||
return;
|
||||
ShowAndStartPopup(new Cleanup(this));
|
||||
if (CanCreatePopup())
|
||||
ShowAndStartPopup(new Cleanup(this));
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
|
@ -1706,9 +1723,7 @@ namespace SourceGit.ViewModels
|
|||
item.Header = dup.Name;
|
||||
item.Click += (_, e) =>
|
||||
{
|
||||
if (CanCreatePopup())
|
||||
ShowAndStartPopup(new ExecuteCustomAction(this, dup));
|
||||
|
||||
ExecCustomAction(dup, null);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
@ -2805,9 +2820,7 @@ namespace SourceGit.ViewModels
|
|||
item.Header = dup.Name;
|
||||
item.Click += (_, e) =>
|
||||
{
|
||||
if (CanCreatePopup())
|
||||
ShowAndStartPopup(new ExecuteCustomAction(this, dup, branch));
|
||||
|
||||
ExecCustomAction(dup, branch);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
|
180
src/Views/ConfigureCustomActionControls.axaml
Normal file
180
src/Views/ConfigureCustomActionControls.axaml
Normal file
|
@ -0,0 +1,180 @@
|
|||
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="520" d:DesignHeight="230"
|
||||
x:Class="SourceGit.Views.ConfigureCustomActionControls"
|
||||
x:DataType="vm:ConfigureCustomActionControls"
|
||||
x:Name="ThisControl"
|
||||
Icon="/App.ico"
|
||||
Title="{DynamicResource Text.ConfigureCustomActionControls}"
|
||||
Width="560" SizeToContent="Height"
|
||||
CanResize="False"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Grid RowDefinitions="Auto,Auto">
|
||||
<!-- TitleBar -->
|
||||
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
|
||||
<Border Background="{DynamicResource Brush.TitleBar}"
|
||||
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
|
||||
PointerPressed="BeginMoveWindow"/>
|
||||
|
||||
<Path Width="14" Height="14"
|
||||
Margin="10,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Data="{StaticResource Icons.Settings}"
|
||||
IsVisible="{OnPlatform True, macOS=False}"/>
|
||||
|
||||
<TextBlock Classes="bold"
|
||||
Text="{DynamicResource Text.ConfigureCustomActionControls}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
IsHitTestVisible="False"/>
|
||||
|
||||
<v:CaptionButtons HorizontalAlignment="Right"
|
||||
IsCloseButtonOnly="True"
|
||||
IsVisible="{OnPlatform True, macOS=False}"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Body -->
|
||||
<Grid Grid.Row="1" ColumnDefinitions="200,*" Height="340" Margin="8,8,8,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 Controls}"
|
||||
SelectedItem="{Binding Edit, 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:CustomActionControl">
|
||||
<Grid Margin="4,0" ColumnDefinitions="Auto,*">
|
||||
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Parameter}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Label, Mode=OneWay}" 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"/>
|
||||
|
||||
<Grid Grid.Row="2" ColumnDefinitions="Auto,Auto,*,Auto,Auto" Background="{DynamicResource Brush.ToolBar}">
|
||||
<Button Grid.Column="0"
|
||||
Classes="icon_button"
|
||||
Width="28" Height="28"
|
||||
Command="{Binding Add}">
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
|
||||
</Button>
|
||||
<Button Grid.Column="1"
|
||||
Classes="icon_button"
|
||||
Width="28" Height="28"
|
||||
Command="{Binding Remove}">
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Minus}"/>
|
||||
</Button>
|
||||
<Button Grid.Column="3"
|
||||
Classes="icon_button"
|
||||
Width="28" Height="28"
|
||||
Command="{Binding MoveUp}"
|
||||
IsVisible="{Binding Edit, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
|
||||
</Button>
|
||||
<Button Grid.Column="4"
|
||||
Classes="icon_button"
|
||||
Width="28" Height="28"
|
||||
Command="{Binding MoveDown}"
|
||||
IsVisible="{Binding Edit, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<ContentControl Grid.Column="1" Margin="16,0,0,0">
|
||||
<ContentControl.Content>
|
||||
<Binding Path="Edit">
|
||||
<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:CustomActionControl">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<!-- Label -->
|
||||
<TextBlock Text="{DynamicResource Text.ConfigureCustomActionControls.Label}"/>
|
||||
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Label, Mode=TwoWay}"/>
|
||||
|
||||
<!-- Type -->
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.ConfigureCustomActionControls.Type}"/>
|
||||
<ComboBox Margin="0,4,0,0" Height="28" HorizontalAlignment="Stretch" SelectedIndex="{Binding Type, Mode=TwoWay}">
|
||||
<ComboBoxItem Content="TextBox"/>
|
||||
<ComboBoxItem Content="Path Selector"/>
|
||||
<ComboBoxItem Content="CheckBox"/>
|
||||
</ComboBox>
|
||||
|
||||
<!-- Description -->
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.ConfigureCustomActionControls.Description}"/>
|
||||
<TextBox Margin="0,4,0,0"
|
||||
CornerRadius="3"
|
||||
Height="28"
|
||||
Text="{Binding Description, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.ConfigureCustomActionControls.Description.Placeholder}"/>
|
||||
|
||||
<!-- Default value -->
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.ConfigureCustomActionControls.DefaultValue}"/>
|
||||
<TextBox Margin="0,4,0,0"
|
||||
CornerRadius="3"
|
||||
Height="28"
|
||||
Text="{Binding StringValue, Mode=TwoWay}"
|
||||
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.NotEqual}, ConverterParameter={x:Static m:CustomActionControlType.CheckBox}}"/>
|
||||
<CheckBox Height="28"
|
||||
Margin="0,4,0,0"
|
||||
IsChecked="{Binding BoolValue, Mode=TwoWay}"
|
||||
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:CustomActionControlType.CheckBox}}"/>
|
||||
|
||||
<!-- PathSelector needs a bool to determine whether we want a folder or a file -->
|
||||
<TextBlock Margin="0,12,0,0"
|
||||
Text="{DynamicResource Text.ConfigureCustomActionControls.IsFolder}"
|
||||
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:CustomActionControlType.PathSelector}}"/>
|
||||
<CheckBox Height="28"
|
||||
Margin="0,4,0,0"
|
||||
IsChecked="{Binding BoolValue, Mode=TwoWay}"
|
||||
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:CustomActionControlType.PathSelector}}"/>
|
||||
|
||||
<!-- CheckBox needs a checked value for commandline -->
|
||||
<TextBlock Margin="0,12,0,0"
|
||||
Text="{DynamicResource Text.ConfigureCustomActionControls.CheckedValue}"
|
||||
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:CustomActionControlType.CheckBox}}"/>
|
||||
<TextBox Margin="0,4,0,0"
|
||||
CornerRadius="3"
|
||||
Height="28"
|
||||
Text="{Binding StringValue, Mode=TwoWay}"
|
||||
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:CustomActionControlType.CheckBox}}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</v:ChromelessWindow>
|
10
src/Views/ConfigureCustomActionControls.axaml.cs
Normal file
10
src/Views/ConfigureCustomActionControls.axaml.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class ConfigureCustomActionControls : ChromelessWindow
|
||||
{
|
||||
public ConfigureCustomActionControls()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,11 +9,81 @@
|
|||
<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>
|
||||
Text="{Binding CustomAction.Name}"/>
|
||||
|
||||
<Grid Margin="0,16,0,0" IsVisible="{Binding IsSimpleMode}">
|
||||
<TextBlock Text="{DynamicResource Text.ExecuteCustomAction.SimpleWait}"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Grid>
|
||||
|
||||
<ListBox Margin="0,16,0,0"
|
||||
IsVisible="{Binding !IsSimpleMode}"
|
||||
ItemsSource="{Binding ControlParameters, Mode=OneWay}">
|
||||
<ListBox.Styles>
|
||||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
</Style>
|
||||
<Style Selector="ListBoxItem:pointerover /template/ ContentPresenter#PART_ContentPresenter, ListBoxItem:selected /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
<ListBox.DataTemplates>
|
||||
<DataTemplate DataType="vm:CustomActionControlTextBox">
|
||||
<Grid ColumnDefinitions="120,*">
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding Label}"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"/>
|
||||
|
||||
<TextBox Grid.Column="1"
|
||||
Height="28"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="3"
|
||||
Watermark="{Binding Placeholder, Mode=OneWay}"
|
||||
Text="{Binding Text, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="vm:CustomActionControlCheckBox">
|
||||
<Grid ColumnDefinitions="120,*">
|
||||
<CheckBox Grid.Column="1"
|
||||
Content="{Binding Label}"
|
||||
ToolTip.Tip="{Binding ToolTip, Mode=OneWay}"
|
||||
IsChecked="{Binding IsChecked, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="vm:CustomActionControlPathSelector">
|
||||
<Grid ColumnDefinitions="120,*">
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding Label}"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"/>
|
||||
|
||||
<TextBox Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Watermark="{Binding Placeholder, Mode=OneWay}"
|
||||
Text="{Binding Path, Mode=TwoWay}">
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button" Width="30" Height="30" Click="SelectPath">
|
||||
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.DataTemplates>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
using System;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
|
@ -8,5 +12,53 @@ namespace SourceGit.Views
|
|||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void SelectPath(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null)
|
||||
return;
|
||||
|
||||
var control = sender as Control;
|
||||
if (control == null)
|
||||
return;
|
||||
|
||||
var selector = control.DataContext as ViewModels.CustomActionControlPathSelector;
|
||||
if (selector == null)
|
||||
return;
|
||||
|
||||
if (selector.IsFolder)
|
||||
{
|
||||
try
|
||||
{
|
||||
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
|
||||
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
var folder = selected[0];
|
||||
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
|
||||
selector.Path = folderPath;
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
App.RaiseException(string.Empty, $"Failed to select parent folder: {exception.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var options = new FilePickerOpenOptions()
|
||||
{
|
||||
AllowMultiple = false,
|
||||
FileTypeFilter = [new FilePickerFileType("File") { Patterns = ["*.*"] }]
|
||||
};
|
||||
|
||||
var selected = await topLevel.StorageProvider.OpenFilePickerAsync(options);
|
||||
if (selected.Count == 1)
|
||||
selector.Path = selected[0].Path.LocalPath;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -548,7 +548,7 @@
|
|||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.CustomAction}"/>
|
||||
</TabItem.Header>
|
||||
|
||||
<Grid MinHeight="340" Margin="0,8,0,16">
|
||||
<Grid MinHeight="380" Margin="0,8,0,16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200"/>
|
||||
<ColumnDefinition Width="*" MaxWidth="400"/>
|
||||
|
@ -659,6 +659,15 @@
|
|||
<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}"/>
|
||||
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CustomAction.InputControls}"/>
|
||||
<Button Margin="0,4,0,0" Classes="flat" Height="28" Click="EditCustomActionControls">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Edit}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
<TextBlock Margin="4,0,0,0" Text="{DynamicResource Text.Configure.CustomAction.InputControls.Edit}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<TextBlock Margin="0,2,0,0" TextWrapping="Wrap" Text="{DynamicResource Text.Configure.CustomAction.InputControls.Tip}" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<CheckBox Margin="0,8,0,0" Content="{DynamicResource Text.Configure.CustomAction.WaitForExit}" IsChecked="{Binding WaitForExit, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
|
|
@ -439,6 +439,20 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void EditCustomActionControls(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not Button { DataContext: Models.CustomAction act })
|
||||
return;
|
||||
|
||||
var dialog = new ConfigureCustomActionControls()
|
||||
{
|
||||
DataContext = new ViewModels.ConfigureCustomActionControls(act.Controls)
|
||||
};
|
||||
|
||||
await dialog.ShowDialog(this);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void UpdateGitVersion()
|
||||
{
|
||||
GitVersion = Native.OS.GitVersionString;
|
||||
|
|
|
@ -381,7 +381,7 @@
|
|||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.CustomAction}"/>
|
||||
</TabItem.Header>
|
||||
|
||||
<Grid ColumnDefinitions="200,*" Height="340" Margin="0,8,0,16">
|
||||
<Grid ColumnDefinitions="200,*" Height="380" Margin="0,8,0,16">
|
||||
<Border Grid.Column="0"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Background="{DynamicResource Brush.Contents}">
|
||||
|
@ -487,6 +487,15 @@
|
|||
<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}"/>
|
||||
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CustomAction.InputControls}"/>
|
||||
<Button Margin="0,4,0,0" Classes="flat" Height="28" Click="EditCustomActionControls">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Edit}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
<TextBlock Margin="4,0,0,0" Text="{DynamicResource Text.Configure.CustomAction.InputControls.Edit}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<TextBlock Margin="0,2,0,0" TextWrapping="Wrap" Text="{DynamicResource Text.Configure.CustomAction.InputControls.Tip}" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<CheckBox Margin="0,8,0,0" Content="{DynamicResource Text.Configure.CustomAction.WaitForExit}" IsChecked="{Binding WaitForExit, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
|
|
@ -12,6 +12,14 @@ namespace SourceGit.Views
|
|||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
|
||||
if (!e.Handled && e.Key == Key.Escape)
|
||||
Close();
|
||||
}
|
||||
|
||||
protected override void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
base.OnClosing(e);
|
||||
|
@ -35,12 +43,18 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
private async void EditCustomActionControls(object sender, RoutedEventArgs e)
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
if (sender is not Button { DataContext: Models.CustomAction act })
|
||||
return;
|
||||
|
||||
if (!e.Handled && e.Key == Key.Escape)
|
||||
Close();
|
||||
var dialog = new ConfigureCustomActionControls()
|
||||
{
|
||||
DataContext = new ViewModels.ConfigureCustomActionControls(act.Controls)
|
||||
};
|
||||
|
||||
await dialog.ShowDialog(this);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue