From 3fc497d6d6a79a55c9fbf12d4504d1f6e34fce30 Mon Sep 17 00:00:00 2001 From: weiningwei Date: Sat, 8 Aug 2026 21:39:49 +0800 Subject: [PATCH] fix: copy folder path when a folder is selected Pressing Ctrl+C on a folder row in the unstaged/staged change tree copied the first file path under the folder (or silently did nothing when the folder contained multiple files). Now the Ctrl+C handler checks the real selection in the tree container first and copies the folder path, and multi-selection copies every path line by line. Ctrl+Shift+C keeps copying absolute paths. --- src/Views/WorkingCopy.axaml.cs | 61 ++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/src/Views/WorkingCopy.axaml.cs b/src/Views/WorkingCopy.axaml.cs index 6b9ad8e75..47b9ae75f 100644 --- a/src/Views/WorkingCopy.axaml.cs +++ b/src/Views/WorkingCopy.axaml.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using Avalonia.Controls; using Avalonia.Input; @@ -117,15 +118,31 @@ private async void OnUnstagedKeyDown(object _, KeyEventArgs e) Native.OS.OpenWithDefaultEditor(fullpath); e.Handled = true; } - else if (e.Key is Key.C && e.KeyModifiers.HasFlag(cmdKey) && vm.SelectedUnstaged is { Count: 1 }) + else if (e.Key is Key.C && e.KeyModifiers.HasFlag(cmdKey)) { - var change = vm.SelectedUnstaged[0]; - if (e.KeyModifiers.HasFlag(KeyModifiers.Shift)) - await this.CopyTextAsync(Native.OS.GetAbsPath(vm.Repository.FullPath, change.Path)); - else - await this.CopyTextAsync(change.Path); + var builder = new StringBuilder(); + var copyAbsPath = e.KeyModifiers.HasFlag(KeyModifiers.Shift); + var container = UnstagedChangesView.FindDescendantOfType(); + if (container is { SelectedItems.Count: 1, SelectedItem: ViewModels.ChangeTreeNode { IsFolder: true } node }) + { + builder.Append(copyAbsPath ? Native.OS.GetAbsPath(vm.Repository.FullPath, node.FullPath) : node.FullPath); + } + else if (vm.SelectedUnstaged is { Count: 1 }) + { + var change = vm.SelectedUnstaged[0]; + builder.Append(copyAbsPath ? Native.OS.GetAbsPath(vm.Repository.FullPath, change.Path) : change.Path); + } + else if (vm.SelectedUnstaged is { Count: > 0 }) + { + foreach (var c in vm.SelectedUnstaged) + builder.AppendLine(copyAbsPath ? Native.OS.GetAbsPath(vm.Repository.FullPath, c.Path) : c.Path); + } - e.Handled = true; + if (builder.Length > 0) + { + await this.CopyTextAsync(builder.ToString()); + e.Handled = true; + } } else if (e.Key is Key.F && e.KeyModifiers == cmdKey) { @@ -156,15 +173,31 @@ private async void OnStagedKeyDown(object _, KeyEventArgs e) Native.OS.OpenWithDefaultEditor(fullpath); e.Handled = true; } - else if (e.Key is Key.C && e.KeyModifiers.HasFlag(cmdKey) && vm.SelectedStaged is { Count: 1 }) + else if (e.Key is Key.C && e.KeyModifiers.HasFlag(cmdKey)) { - var change = vm.SelectedStaged[0]; - if (e.KeyModifiers.HasFlag(KeyModifiers.Shift)) - await this.CopyTextAsync(Native.OS.GetAbsPath(vm.Repository.FullPath, change.Path)); - else - await this.CopyTextAsync(change.Path); + var builder = new StringBuilder(); + var copyAbsPath = e.KeyModifiers.HasFlag(KeyModifiers.Shift); + var container = StagedChangesView.FindDescendantOfType(); + if (container is { SelectedItems.Count: 1, SelectedItem: ViewModels.ChangeTreeNode { IsFolder: true } node }) + { + builder.Append(copyAbsPath ? Native.OS.GetAbsPath(vm.Repository.FullPath, node.FullPath) : node.FullPath); + } + else if (vm.SelectedStaged is { Count: 1 }) + { + var change = vm.SelectedStaged[0]; + builder.Append(copyAbsPath ? Native.OS.GetAbsPath(vm.Repository.FullPath, change.Path) : change.Path); + } + else if (vm.SelectedStaged is { Count: > 0 }) + { + foreach (var c in vm.SelectedStaged) + builder.AppendLine(copyAbsPath ? Native.OS.GetAbsPath(vm.Repository.FullPath, c.Path) : c.Path); + } - e.Handled = true; + if (builder.Length > 0) + { + await this.CopyTextAsync(builder.ToString()); + e.Handled = true; + } } else if (e.Key is Key.F && e.KeyModifiers == cmdKey) {