44using System . Collections . Frozen ;
55using System . Collections . Immutable ;
66using Files . App . Actions ;
7+ using Microsoft . Extensions . Logging ;
78
89namespace Files . App . Data . Commands
910{
@@ -391,25 +392,26 @@ public IEnumerator<IRichCommand> GetEnumerator() =>
391392 /// </summary>
392393 private void OverwriteKeyBindings ( )
393394 {
395+ var allCommands = commands . Values . OfType < ActionCommand > ( ) ;
396+
394397 if ( ActionsSettingsService . ActionsV2 is null )
395398 {
396- foreach ( var command in commands . Values . OfType < ActionCommand > ( ) )
397- {
398- command . RestoreKeyBindings ( ) ;
399- }
399+ allCommands . ForEach ( x => x . RestoreKeyBindings ( ) ) ;
400400 }
401401 else
402402 {
403- foreach ( var command in commands . Values . OfType < ActionCommand > ( ) )
403+ foreach ( var command in allCommands )
404404 {
405405 var customizedKeyBindings = ActionsSettingsService . ActionsV2 . FindAll ( x => x . CommandCode == command . Code . ToString ( ) ) ;
406406
407407 if ( customizedKeyBindings . IsEmpty ( ) )
408408 {
409+ // Could not find customized key bindings for the command
409410 command . RestoreKeyBindings ( ) ;
410411 }
411412 else if ( customizedKeyBindings . Count == 1 && customizedKeyBindings [ 0 ] . KeyBinding == string . Empty )
412413 {
414+ // Do not assign any key binding even though there're default keys pre-defined
413415 command . OverwriteKeyBindings ( HotKeyCollection . Empty ) ;
414416 }
415417 else
@@ -420,9 +422,62 @@ private void OverwriteKeyBindings()
420422 }
421423 }
422424
423- _allKeyBindings = commands . Values
424- . SelectMany ( command => command . HotKeys , ( command , hotKey ) => ( Command : command , HotKey : hotKey ) )
425- . ToImmutableDictionary ( item => item . HotKey , item => item . Command ) ;
425+ try
426+ {
427+ // Set collection of a set of command code and key bindings to dictionary
428+ _allKeyBindings = commands . Values
429+ . SelectMany ( command => command . HotKeys , ( command , hotKey ) => ( Command : command , HotKey : hotKey ) )
430+ . ToImmutableDictionary ( item => item . HotKey , item => item . Command ) ;
431+ }
432+ catch ( ArgumentException ex )
433+ {
434+ // The keys are not necessarily all different because they can be set manually in text editor
435+ // ISSUE: https://github.com/files-community/Files/issues/15331
436+
437+ var flat = commands . Values . SelectMany ( x => x . HotKeys ) . Select ( x => x . LocalizedLabel ) ;
438+ var duplicates = flat . GroupBy ( x => x ) . Where ( x => x . Count ( ) > 1 ) . Select ( group => group . Key ) ;
439+
440+ foreach ( var item in duplicates )
441+ {
442+ if ( ! string . IsNullOrEmpty ( item ) )
443+ {
444+ var occurrences = allCommands . Where ( x => x . HotKeys . Select ( x => x . LocalizedLabel ) . Contains ( item ) ) ;
445+
446+ // Restore the defaults for all occurrences in our cache
447+ occurrences . ForEach ( x => x . RestoreKeyBindings ( ) ) ;
448+
449+ // Get all customized key bindings from user settings json
450+ var actions =
451+ ActionsSettingsService . ActionsV2 is not null
452+ ? new List < ActionWithParameterItem > ( ActionsSettingsService . ActionsV2 )
453+ : [ ] ;
454+
455+ // Remove the duplicated key binding from user settings JSON file
456+ actions . RemoveAll ( x => x . KeyBinding . Contains ( item ) ) ;
457+
458+ // Reset
459+ ActionsSettingsService . ActionsV2 = actions ;
460+ }
461+ }
462+
463+ // Set collection of a set of command code and key bindings to dictionary
464+ _allKeyBindings = commands . Values
465+ . SelectMany ( command => command . HotKeys , ( command , hotKey ) => ( Command : command , HotKey : hotKey ) )
466+ . ToImmutableDictionary ( item => item . HotKey , item => item . Command ) ;
467+
468+ App . Logger . LogWarning ( ex , "The app found some keys in different commands are duplicated and are using default key bindings for those commands." ) ;
469+ }
470+ catch ( Exception ex )
471+ {
472+ allCommands . ForEach ( x => x . RestoreKeyBindings ( ) ) ;
473+
474+ // Set collection of a set of command code and key bindings to dictionary
475+ _allKeyBindings = commands . Values
476+ . SelectMany ( command => command . HotKeys , ( command , hotKey ) => ( Command : command , HotKey : hotKey ) )
477+ . ToImmutableDictionary ( item => item . HotKey , item => item . Command ) ;
478+
479+ App . Logger . LogWarning ( ex , "The app is temporarily using default key bindings for all because of a serious error of assigning custom keys." ) ;
480+ }
426481 }
427482
428483 public static HotKeyCollection GetDefaultKeyBindings ( IAction action )
0 commit comments