From 34930cb8e450e724b2173afe0b59b6614b56b7ac Mon Sep 17 00:00:00 2001 From: Filippo Ferrario <102259289+ferrariofilippo@users.noreply.github.com> Date: Tue, 12 Sep 2023 11:24:30 +0200 Subject: [PATCH] Feature: Switch between items using arrow keys in the conflicts dialog --- .../Dialogs/FilesystemOperationDialog.xaml | 1 + .../Dialogs/FilesystemOperationDialog.xaml.cs | 95 +++++++++++++------ 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml index a80e6fa95731..abae820b5fd1 100644 --- a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml +++ b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml @@ -99,6 +99,7 @@ x:Load="{x:Bind IsTextBoxVisible, Mode=OneWay}" Loaded="NameEdit_Loaded" LostFocus="NameEdit_LostFocus" + PreviewKeyDown="NameEdit_PreviewKeyDown" Text="{x:Bind CustomName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> diff --git a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs index ccbd9aad1a24..c340b0b952da 100644 --- a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs +++ b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs @@ -2,14 +2,9 @@ // Licensed under the MIT License. See the LICENSE. using CommunityToolkit.WinUI.UI; -using Files.App.Utils; -using Files.Core.ViewModels.Dialogs; -using Files.Core.ViewModels.Dialogs.FileSystemDialog; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; -using System; -using System.Threading.Tasks; namespace Files.App.Dialogs { @@ -72,7 +67,8 @@ protected override void OnApplyTemplate() private void PrimaryButton_GotFocus(object sender, RoutedEventArgs e) { - (sender as Button).GotFocus -= PrimaryButton_GotFocus; + if (sender is Button btn) + btn.GotFocus -= PrimaryButton_GotFocus; if (chkPermanentlyDelete is not null) chkPermanentlyDelete.IsEnabled = ViewModel.IsDeletePermanentlyEnabled; @@ -95,33 +91,14 @@ private void NameStackPanel_Tapped(object sender, Microsoft.UI.Xaml.Input.Tapped element.DataContext is FileSystemDialogConflictItemViewModel conflictItem && conflictItem.ConflictResolveOption == FileNameConflictResolveOptionType.GenerateNewName) { - conflictItem.IsTextBoxVisible = conflictItem.ConflictResolveOption == FileNameConflictResolveOptionType.GenerateNewName; - conflictItem.CustomName = conflictItem.DestinationDisplayName; + StartRename(conflictItem); } } private void NameEdit_LostFocus(object sender, RoutedEventArgs e) { if ((sender as FrameworkElement)?.DataContext is FileSystemDialogConflictItemViewModel conflictItem) - { - conflictItem.CustomName = FilesystemHelpers.FilterRestrictedCharacters(conflictItem.CustomName); - - if (ViewModel.IsNameAvailableForItem(conflictItem, conflictItem.CustomName!)) - { - conflictItem.IsTextBoxVisible = false; - } - else - { - ViewModel.PrimaryButtonEnabled = false; - } - - if (conflictItem.CustomName.Equals(conflictItem.DisplayName)) - { - var savedName = conflictItem.DestinationDisplayName; - conflictItem.CustomName = string.Empty; - conflictItem.DestinationDisplayName = savedName; - } - } + EndRename(conflictItem); } private void NameEdit_Loaded(object sender, RoutedEventArgs e) @@ -145,11 +122,71 @@ private void ConflictOptions_Loaded(object sender, RoutedEventArgs e) private void FilesystemOperationDialog_Opened(ContentDialog sender, ContentDialogOpenedEventArgs args) { if (ViewModel.FileSystemDialogMode.IsInDeleteMode) - { DescriptionText.Foreground = App.Current.Resources["TextControlForeground"] as SolidColorBrush; - } UpdateDialogLayout(); } + + private void NameEdit_PreviewKeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e) + { + if (sender is not FrameworkElement element || element.DataContext is not FileSystemDialogConflictItemViewModel currentItem) + return; + + if (e.Key is Windows.System.VirtualKey.Down) + { + var index = ViewModel.Items.IndexOf(currentItem); + if (index == -1 || index == ViewModel.Items.Count - 1) + return; + + var nextItem = ViewModel.Items.Skip(index + 1) + .FirstOrDefault(i => i is FileSystemDialogConflictItemViewModel { ConflictResolveOption: FileNameConflictResolveOptionType.GenerateNewName }); + + if (nextItem is null) + return; + + EndRename(currentItem); + StartRename((FileSystemDialogConflictItemViewModel)nextItem); + + e.Handled = true; + } + else if (e.Key is Windows.System.VirtualKey.Up) + { + var index = ViewModel.Items.IndexOf(currentItem); + if (index == -1 || index == 0) + return; + + var prevItem = ViewModel.Items.Take(index) + .LastOrDefault(i => i is FileSystemDialogConflictItemViewModel { ConflictResolveOption: FileNameConflictResolveOptionType.GenerateNewName }); + if (prevItem is null) + return; + + EndRename(currentItem); + StartRename((FileSystemDialogConflictItemViewModel)prevItem); + + e.Handled = true; + } + } + + private void StartRename(FileSystemDialogConflictItemViewModel conflictItem) + { + conflictItem.IsTextBoxVisible = conflictItem.ConflictResolveOption == FileNameConflictResolveOptionType.GenerateNewName; + conflictItem.CustomName = conflictItem.DestinationDisplayName; + } + + private void EndRename(FileSystemDialogConflictItemViewModel conflictItem) + { + conflictItem.CustomName = FilesystemHelpers.FilterRestrictedCharacters(conflictItem.CustomName); + + if (ViewModel.IsNameAvailableForItem(conflictItem, conflictItem.CustomName!)) + conflictItem.IsTextBoxVisible = false; + else + ViewModel.PrimaryButtonEnabled = false; + + if (conflictItem.CustomName.Equals(conflictItem.DisplayName)) + { + var savedName = conflictItem.DestinationDisplayName; + conflictItem.DestinationDisplayName = savedName; + } + } } }