diff --git a/src/Files.App/Data/Commands/Manager/CommandManager.cs b/src/Files.App/Data/Commands/Manager/CommandManager.cs index 39924064c860..0fcf0c7c0966 100644 --- a/src/Files.App/Data/Commands/Manager/CommandManager.cs +++ b/src/Files.App/Data/Commands/Manager/CommandManager.cs @@ -4,6 +4,7 @@ using System.Collections.Frozen; using System.Collections.Immutable; using Files.App.Actions; +using Microsoft.Extensions.Logging; namespace Files.App.Data.Commands { @@ -391,25 +392,26 @@ public IEnumerator GetEnumerator() => /// private void OverwriteKeyBindings() { + var allCommands = commands.Values.OfType(); + if (ActionsSettingsService.ActionsV2 is null) { - foreach (var command in commands.Values.OfType()) - { - command.RestoreKeyBindings(); - } + allCommands.ForEach(x => x.RestoreKeyBindings()); } else { - foreach (var command in commands.Values.OfType()) + foreach (var command in allCommands) { var customizedKeyBindings = ActionsSettingsService.ActionsV2.FindAll(x => x.CommandCode == command.Code.ToString()); if (customizedKeyBindings.IsEmpty()) { + // Could not find customized key bindings for the command command.RestoreKeyBindings(); } else if (customizedKeyBindings.Count == 1 && customizedKeyBindings[0].KeyBinding == string.Empty) { + // Do not assign any key binding even though there're default keys pre-defined command.OverwriteKeyBindings(HotKeyCollection.Empty); } else @@ -420,9 +422,62 @@ private void OverwriteKeyBindings() } } - _allKeyBindings = commands.Values - .SelectMany(command => command.HotKeys, (command, hotKey) => (Command: command, HotKey: hotKey)) - .ToImmutableDictionary(item => item.HotKey, item => item.Command); + try + { + // Set collection of a set of command code and key bindings to dictionary + _allKeyBindings = commands.Values + .SelectMany(command => command.HotKeys, (command, hotKey) => (Command: command, HotKey: hotKey)) + .ToImmutableDictionary(item => item.HotKey, item => item.Command); + } + catch (ArgumentException ex) + { + // The keys are not necessarily all different because they can be set manually in text editor + // ISSUE: https://github.com/files-community/Files/issues/15331 + + var flat = commands.Values.SelectMany(x => x.HotKeys).Select(x => x.LocalizedLabel); + var duplicates = flat.GroupBy(x => x).Where(x => x.Count() > 1).Select(group => group.Key); + + foreach (var item in duplicates) + { + if (!string.IsNullOrEmpty(item)) + { + var occurrences = allCommands.Where(x => x.HotKeys.Select(x => x.LocalizedLabel).Contains(item)); + + // Restore the defaults for all occurrences in our cache + occurrences.ForEach(x => x.RestoreKeyBindings()); + + // Get all customized key bindings from user settings json + var actions = + ActionsSettingsService.ActionsV2 is not null + ? new List(ActionsSettingsService.ActionsV2) + : []; + + // Remove the duplicated key binding from user settings JSON file + actions.RemoveAll(x => x.KeyBinding.Contains(item)); + + // Reset + ActionsSettingsService.ActionsV2 = actions; + } + } + + // Set collection of a set of command code and key bindings to dictionary + _allKeyBindings = commands.Values + .SelectMany(command => command.HotKeys, (command, hotKey) => (Command: command, HotKey: hotKey)) + .ToImmutableDictionary(item => item.HotKey, item => item.Command); + + App.Logger.LogWarning(ex, "The app found some keys in different commands are duplicated and are using default key bindings for those commands."); + } + catch (Exception ex) + { + allCommands.ForEach(x => x.RestoreKeyBindings()); + + // Set collection of a set of command code and key bindings to dictionary + _allKeyBindings = commands.Values + .SelectMany(command => command.HotKeys, (command, hotKey) => (Command: command, HotKey: hotKey)) + .ToImmutableDictionary(item => item.HotKey, item => item.Command); + + App.Logger.LogWarning(ex, "The app is temporarily using default key bindings for all because of a serious error of assigning custom keys."); + } } public static HotKeyCollection GetDefaultKeyBindings(IAction action)