66using Files . App . Helpers . ContextFlyouts ;
77using Files . App . UserControls . Menus ;
88using Files . App . ViewModels . Layouts ;
9+ using Microsoft . UI . Input ;
910using Microsoft . UI . Xaml ;
1011using Microsoft . UI . Xaml . Controls ;
1112using Microsoft . UI . Xaml . Controls . Primitives ;
2324using Windows . Foundation . Collections ;
2425using Windows . Storage ;
2526using Windows . System ;
27+ using Windows . UI . Core ;
2628using static Files . App . Helpers . PathNormalization ;
2729using DispatcherQueueTimer = Microsoft . UI . Dispatching . DispatcherQueueTimer ;
2830using SortDirection = Files . App . Data . Enums . SortDirection ;
@@ -40,6 +42,8 @@ public abstract class BaseLayoutPage : Page, IBaseLayoutPage, INotifyPropertyCha
4042 protected IFileTagsSettingsService FileTagsSettingsService { get ; } = Ioc . Default . GetService < IFileTagsSettingsService > ( ) ! ;
4143 protected IUserSettingsService UserSettingsService { get ; } = Ioc . Default . GetService < IUserSettingsService > ( ) ! ;
4244 protected ILayoutSettingsService LayoutSettingsService { get ; } = Ioc . Default . GetService < ILayoutSettingsService > ( ) ! ;
45+ protected IGeneralSettingsService GeneralSettingsService { get ; } = Ioc . Default . GetService < IGeneralSettingsService > ( ) ! ;
46+ protected IFoldersSettingsService FoldersSettingsService { get ; } = Ioc . Default . GetService < IFoldersSettingsService > ( ) ! ;
4347 protected ICommandManager Commands { get ; } = Ioc . Default . GetRequiredService < ICommandManager > ( ) ;
4448 public InfoPaneViewModel InfoPaneViewModel { get ; } = Ioc . Default . GetRequiredService < InfoPaneViewModel > ( ) ;
4549 protected readonly IWindowContext WindowContext = Ioc . Default . GetRequiredService < IWindowContext > ( ) ;
@@ -401,7 +405,7 @@ protected override async void OnNavigatedTo(NavigationEventArgs e)
401405 base . OnNavigatedTo ( e ) ;
402406
403407 // Add item jumping handler
404- CharacterReceived += Page_CharacterReceived ;
408+ PreviewKeyDown += Page_PreviewKeyDown ; ;
405409
406410 navigationArguments = ( NavigationArguments ) e . Parameter ;
407411 ParentShellPageInstance = navigationArguments . AssociatedTabInstance ;
@@ -565,7 +569,7 @@ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
565569 base . OnNavigatingFrom ( e ) ;
566570
567571 // Remove item jumping handler
568- CharacterReceived -= Page_CharacterReceived ;
572+ PreviewKeyDown -= Page_PreviewKeyDown ;
569573 FolderSettings ! . LayoutModeChangeRequested -= BaseFolderSettings_LayoutModeChangeRequested ;
570574 FolderSettings . GroupOptionPreferenceUpdated -= FolderSettings_GroupOptionPreferenceUpdated ;
571575 FolderSettings . GroupDirectionPreferenceUpdated -= FolderSettings_GroupDirectionPreferenceUpdated ;
@@ -996,12 +1000,66 @@ private void RemoveOverflow(CommandBarFlyout contextMenuFlyout)
9961000 overflowSeparator . Visibility = Visibility . Collapsed ;
9971001 }
9981002
999- protected virtual void Page_CharacterReceived ( UIElement sender , CharacterReceivedRoutedEventArgs args )
1003+ protected virtual void Page_PreviewKeyDown ( object sender , KeyRoutedEventArgs e )
10001004 {
1001- if ( ParentShellPageInstance ! . IsCurrentInstance )
1005+ if ( ParentShellPageInstance ? . IsCurrentInstance != true )
1006+ return ;
1007+
1008+ var key = e . Key ;
1009+ var filter = ParentShellPageInstance . ShellViewModel . FilesAndFoldersFilter ;
1010+ bool isShiftDown = InputKeyboardSource . GetKeyStateForCurrentThread ( VirtualKey . Shift ) . HasFlag ( CoreVirtualKeyStates . Down ) ;
1011+ bool isFilteringEnabled = FoldersSettingsService . KeyboardTypingBehavior == KeyboardTypingBehavior . FilterItems ;
1012+
1013+ // OEM codes
1014+ bool isOemMinus = ( int ) key == ( int ) Keys . OemMinus ;
1015+ bool isOemPeriod = ( int ) key == ( int ) Keys . OemPeriod ;
1016+
1017+ char ? keyChar = key switch
1018+ {
1019+ >= VirtualKey . A and <= VirtualKey . Z => ( char ) ( 'A' + ( key - VirtualKey . A ) ) ,
1020+ >= VirtualKey . Number0 and <= VirtualKey . Number9 => ( char ) ( '0' + ( key - VirtualKey . Number0 ) ) ,
1021+ _ => isOemMinus ? ( isShiftDown ? '_' : '-' ) :
1022+ isOemPeriod ? '.' : null
1023+ } ;
1024+
1025+ if ( keyChar is char ch &&
1026+ ! Path . GetInvalidFileNameChars ( ) . Contains ( char . ToLowerInvariant ( ch ) ) )
1027+ {
1028+ string typedChar = char . ToLowerInvariant ( ch ) . ToString ( ) ;
1029+
1030+ if ( isFilteringEnabled )
1031+ {
1032+ if ( ! GeneralSettingsService . ShowFilterHeader )
1033+ GeneralSettingsService . ShowFilterHeader = true ;
1034+
1035+ ParentShellPageInstance . ShellViewModel . FilesAndFoldersFilter += typedChar ;
1036+ }
1037+ else
1038+ {
1039+ JumpString += typedChar ;
1040+ return ;
1041+ }
1042+ }
1043+ else if ( isFilteringEnabled && ! string . IsNullOrEmpty ( filter ) )
1044+ {
1045+ if ( key == VirtualKey . Space )
1046+ ParentShellPageInstance . ShellViewModel . FilesAndFoldersFilter += " " ;
1047+ else if ( key == VirtualKey . Back && filter . Length > 1 )
1048+ ParentShellPageInstance . ShellViewModel . FilesAndFoldersFilter = filter [ ..^ 1 ] ;
1049+ else if ( key == VirtualKey . Back && filter . Length == 1 )
1050+ {
1051+ ParentShellPageInstance . ShellViewModel . FilesAndFoldersFilter = string . Empty ;
1052+ GeneralSettingsService . ShowFilterHeader = false ;
1053+ }
1054+ }
1055+
1056+ if ( isFilteringEnabled )
10021057 {
1003- char letter = args . Character ;
1004- JumpString += letter . ToString ( ) . ToLowerInvariant ( ) ;
1058+ var jumpedToItem = ParentShellPageInstance ! . ShellViewModel . FilesAndFolders
1059+ . FirstOrDefault ( f => f . Name ? . Contains ( ParentShellPageInstance . ShellViewModel . FilesAndFoldersFilter , StringComparison . OrdinalIgnoreCase ) == true ) ;
1060+ ItemManipulationModel . SetSelectedItem ( jumpedToItem ) ;
1061+ ItemManipulationModel . ScrollIntoView ( jumpedToItem ) ;
1062+ ItemManipulationModel . FocusSelectedItems ( ) ;
10051063 }
10061064 }
10071065
0 commit comments