diff --git a/src/Models/CustomAction.cs b/src/Models/CustomAction.cs index a614961a..4e9107a1 100644 --- a/src/Models/CustomAction.cs +++ b/src/Models/CustomAction.cs @@ -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 Controls + { + get; + set; + } = []; + public bool WaitForExit { get => _waitForExit; diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index d54859ba..b1528c5a 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -93,6 +93,7 @@ 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 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 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 + 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 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 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 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 diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 824e3f38..5dd0c899 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -304,8 +304,6 @@ Ziel: Ausgewählte Gruppe bearbeiten Ausgewähltes Repository bearbeiten - Führe benutzerdefinierte Aktion aus - Name der Aktion: Fetch Alle Remotes fetchen Aktiviere '--force' Option diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 0817ed45..b3c41d33 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -162,6 +162,9 @@ Arguments: ${REPO} - Repository's path; ${BRANCH} - Selected branch; ${SHA} - Selected commit's SHA Executable File: + Input Controls: + Edit + You can use $1, $2 ... in arguments for input control values Name: Scope: Branch @@ -195,6 +198,14 @@ HTTP proxy used by this repository User Name User name for this repository + Edit Custom Action Controls + Checked Value: + Description: + Used as placeholder in TextBox/PathSelector or tooltip in CheckBox + Default: + Is Folder: + Label: + Type: Workspaces Color Name @@ -300,8 +311,7 @@ Target: Edit Selected Group Edit Selected Repository - Run Custom Action - Action Name: + Action is running, please wait... Fetch Fetch all remotes Force override local refs diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index d66e515a..7c75d81b 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -300,8 +300,6 @@ Destino: Editar Grupo Seleccionado Editar Repositorio Seleccionado - Ejecutar Acción Personalizada - Nombre de la Acción: Fetch Fetch todos los remotos Utilizar opción '--force' diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 8e1fd7bd..2a2441b4 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -273,8 +273,6 @@ Cible : Éditer le groupe sélectionné Éditer le dépôt sélectionné - Lancer action personnalisée - Nom de l'action : Fetch Fetch toutes les branches distantes Outrepasser les vérifications de refs diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index 62f15e38..26c9c097 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -290,8 +290,6 @@ Destinazione: Modifica Gruppo Selezionato Modifica Repository Selezionato - Esegui Azione Personalizzata - Nome Azione: Recupera Recupera da tutti i remoti Forza la sovrascrittura dei riferimenti locali diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml index bf9fe586..bf0e35f0 100644 --- a/src/Resources/Locales/ja_JP.axaml +++ b/src/Resources/Locales/ja_JP.axaml @@ -272,8 +272,6 @@ 対象: 選択中のグループを編集 選択中のリポジトリを編集 - カスタムアクションを実行 - アクション名: フェッチ すべてのリモートをフェッチ ローカル参照を強制的に上書き diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index fecd9540..bbda6065 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -247,8 +247,6 @@ Alvo: Editar Grupo Selecionado Editar Repositório Selecionado - Executar ação customizada - Nome da ação: Buscar Buscar todos os remotos Buscar sem tags diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 708ff7cc..a93cb0be 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -301,8 +301,6 @@ Цель: Редактировать выбранную группу Редактировать выбранный репозиторий - Выполнить пользовательское действие - Имя действия: Извлечь Извлечь все внешние репозитории Разрешить опцию (--force) diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml index 248d5f42..de764253 100644 --- a/src/Resources/Locales/ta_IN.axaml +++ b/src/Resources/Locales/ta_IN.axaml @@ -272,8 +272,6 @@ இலக்கு: தேர்ந்தெடுக்கப்பட்ட குழுவைத் திருத்து தேர்ந்தெடுக்கப்பட்ட களஞ்சியத்தைத் திருத்து - தனிப்பயன் செயலை இயக்கு - செயல் பெயர்: பெறு எல்லா தொலைகளையும் பெறு உள்ளக குறிப்புகளை கட்டாயமாக மீறு diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml index 5d120117..0f791a3f 100644 --- a/src/Resources/Locales/uk_UA.axaml +++ b/src/Resources/Locales/uk_UA.axaml @@ -277,8 +277,6 @@ Ціль: Редагувати вибрану групу Редагувати вибраний репозиторій - Виконати спеціальну дію - Ім'я дії: Витягти Витягти всі віддалені сховища Примусово перезаписати локальні refs diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index d33ff993..3cc822a2 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -166,6 +166,9 @@ 命令行参数 : 请使用${REPO}代替仓库路径,${BRANCH}代替选中的分支,${SHA}代替提交哈希 可执行文件路径 : + 输入控件 : + 编辑 + 请在命令行参数中使用 $1, $2 等占位符表示输入控件的值 名称 : 作用目标 : 选中的分支 @@ -199,6 +202,14 @@ HTTP网络代理 用户名 应用于本仓库的用户名 + 编辑自定义操作输入控件 + 启用时命令行参数 : + 描述 : + TextBox及Path Selector中用作Placeholder,CheckBox中用作ToolTip + 默认值 : + 目标是否是目录 : + 名称 : + 类型 : 工作区 颜色 名称 @@ -304,8 +315,7 @@ 目标 : 编辑分组 编辑仓库 - 执行自定义操作 - 自定义操作 : + 操作正在进行中,请耐心等待... 拉取(fetch) 拉取所有的远程仓库 强制覆盖本地REFs diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index dec6eddd..dc4a227b 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -166,6 +166,9 @@ 指令參數: 使用 ${REPO} 表示存放庫路徑、${BRANCH} 表示所選的分支、${SHA} 表示所選的提交編號 可執行檔案路徑: + 輸入控件: + 編輯 + 請使用占位符如 $1, $2 來代表輸入控制項的值 名稱: 執行範圍: 選取的分支 @@ -199,6 +202,14 @@ HTTP 網路代理 使用者名稱 用於本存放庫的使用者名稱 + 編輯自訂動作輸入控件 + 啟用時的指令行參數: + 描述: + 在 TextBox/PathSelector 中用作占位符,或在 CheckBox 中用作工具提示 + 預設值: + 目標路徑是否為資料夾: + 名稱: + 類型: 工作區 顏色 名稱 @@ -304,8 +315,7 @@ 目標: 編輯群組 編輯存放庫 - 執行自訂動作 - 自訂動作: + 動作正在執行中,請稍候... 提取 (fetch) 提取所有的遠端存放庫 強制覆寫本機 REFs diff --git a/src/ViewModels/ConfigureCustomActionControls.cs b/src/ViewModels/ConfigureCustomActionControls.cs new file mode 100644 index 00000000..f0588af7 --- /dev/null +++ b/src/ViewModels/ConfigureCustomActionControls.cs @@ -0,0 +1,62 @@ +using Avalonia.Collections; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace SourceGit.ViewModels +{ + public class ConfigureCustomActionControls : ObservableObject + { + public AvaloniaList Controls + { + get; + } + + public Models.CustomActionControl Edit + { + get => _edit; + set => SetProperty(ref _edit, value); + } + + public ConfigureCustomActionControls(AvaloniaList 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; + } +} diff --git a/src/ViewModels/ExecuteCustomAction.cs b/src/ViewModels/ExecuteCustomAction.cs index 72570bf0..5effd3a1 100644 --- a/src/ViewModels/ExecuteCustomAction.cs +++ b/src/ViewModels/ExecuteCustomAction.cs @@ -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 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 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; } } diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 9e24e9b3..75c5861d 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -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; }; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 52f2f43a..7c8476a3 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -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; }; diff --git a/src/Views/ConfigureCustomActionControls.axaml b/src/Views/ConfigureCustomActionControls.axaml new file mode 100644 index 00000000..71c196cf --- /dev/null +++ b/src/Views/ConfigureCustomActionControls.axaml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/ConfigureCustomActionControls.axaml.cs b/src/Views/ConfigureCustomActionControls.axaml.cs new file mode 100644 index 00000000..9e2104cf --- /dev/null +++ b/src/Views/ConfigureCustomActionControls.axaml.cs @@ -0,0 +1,10 @@ +namespace SourceGit.Views +{ + public partial class ConfigureCustomActionControls : ChromelessWindow + { + public ConfigureCustomActionControls() + { + InitializeComponent(); + } + } +} diff --git a/src/Views/ExecuteCustomAction.axaml b/src/Views/ExecuteCustomAction.axaml index 9ee2b55d..a965be69 100644 --- a/src/Views/ExecuteCustomAction.axaml +++ b/src/Views/ExecuteCustomAction.axaml @@ -9,11 +9,81 @@ - - - - - + Text="{Binding CustomAction.Name}"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/ExecuteCustomAction.axaml.cs b/src/Views/ExecuteCustomAction.axaml.cs index e4f9cecf..94d1f7c8 100644 --- a/src/Views/ExecuteCustomAction.axaml.cs +++ b/src/Views/ExecuteCustomAction.axaml.cs @@ -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; + } } } diff --git a/src/Views/Preferences.axaml b/src/Views/Preferences.axaml index b90c028e..b392068b 100644 --- a/src/Views/Preferences.axaml +++ b/src/Views/Preferences.axaml @@ -548,7 +548,7 @@ - + @@ -659,6 +659,15 @@ + + + + diff --git a/src/Views/Preferences.axaml.cs b/src/Views/Preferences.axaml.cs index 6856fbce..f0f4617a 100644 --- a/src/Views/Preferences.axaml.cs +++ b/src/Views/Preferences.axaml.cs @@ -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; diff --git a/src/Views/RepositoryConfigure.axaml b/src/Views/RepositoryConfigure.axaml index bb8d2fe6..ecf10aba 100644 --- a/src/Views/RepositoryConfigure.axaml +++ b/src/Views/RepositoryConfigure.axaml @@ -381,7 +381,7 @@ - + @@ -487,6 +487,15 @@ + + + + diff --git a/src/Views/RepositoryConfigure.axaml.cs b/src/Views/RepositoryConfigure.axaml.cs index 2c80dd45..47895ba1 100644 --- a/src/Views/RepositoryConfigure.axaml.cs +++ b/src/Views/RepositoryConfigure.axaml.cs @@ -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; } } }