/ src / modules / cmdpal / Microsoft.CmdPal.UI.ViewModels / SettingsViewModel.cs
SettingsViewModel.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  using System.Collections.ObjectModel;
  6  using System.ComponentModel;
  7  using Microsoft.CmdPal.UI.ViewModels.Services;
  8  using Microsoft.CmdPal.UI.ViewModels.Settings;
  9  using Microsoft.CommandPalette.Extensions.Toolkit;
 10  
 11  namespace Microsoft.CmdPal.UI.ViewModels;
 12  
 13  public partial class SettingsViewModel : INotifyPropertyChanged
 14  {
 15      private static readonly List<TimeSpan> AutoGoHomeIntervals =
 16      [
 17          Timeout.InfiniteTimeSpan,
 18          TimeSpan.Zero,
 19          TimeSpan.FromSeconds(10),
 20          TimeSpan.FromSeconds(20),
 21          TimeSpan.FromSeconds(30),
 22          TimeSpan.FromSeconds(60),
 23          TimeSpan.FromSeconds(90),
 24          TimeSpan.FromSeconds(120),
 25          TimeSpan.FromSeconds(180),
 26      ];
 27  
 28      private readonly SettingsModel _settings;
 29      private readonly TopLevelCommandManager _topLevelCommandManager;
 30  
 31      public event PropertyChangedEventHandler? PropertyChanged;
 32  
 33      public AppearanceSettingsViewModel Appearance { get; }
 34  
 35      public HotkeySettings? Hotkey
 36      {
 37          get => _settings.Hotkey;
 38          set
 39          {
 40              _settings.Hotkey = value ?? SettingsModel.DefaultActivationShortcut;
 41              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Hotkey)));
 42              Save();
 43          }
 44      }
 45  
 46      public bool UseLowLevelGlobalHotkey
 47      {
 48          get => _settings.UseLowLevelGlobalHotkey;
 49          set
 50          {
 51              _settings.UseLowLevelGlobalHotkey = value;
 52              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Hotkey)));
 53              Save();
 54          }
 55      }
 56  
 57      public bool AllowExternalReload
 58      {
 59          get => _settings.AllowExternalReload;
 60          set
 61          {
 62              _settings.AllowExternalReload = value;
 63              Save();
 64          }
 65      }
 66  
 67      public bool ShowAppDetails
 68      {
 69          get => _settings.ShowAppDetails;
 70          set
 71          {
 72              _settings.ShowAppDetails = value;
 73              Save();
 74          }
 75      }
 76  
 77      public bool BackspaceGoesBack
 78      {
 79          get => _settings.BackspaceGoesBack;
 80          set
 81          {
 82              _settings.BackspaceGoesBack = value;
 83              Save();
 84          }
 85      }
 86  
 87      public bool SingleClickActivates
 88      {
 89          get => _settings.SingleClickActivates;
 90          set
 91          {
 92              _settings.SingleClickActivates = value;
 93              Save();
 94          }
 95      }
 96  
 97      public bool HighlightSearchOnActivate
 98      {
 99          get => _settings.HighlightSearchOnActivate;
100          set
101          {
102              _settings.HighlightSearchOnActivate = value;
103              Save();
104          }
105      }
106  
107      public int MonitorPositionIndex
108      {
109          get => (int)_settings.SummonOn;
110          set
111          {
112              _settings.SummonOn = (MonitorBehavior)value;
113              Save();
114          }
115      }
116  
117      public bool ShowSystemTrayIcon
118      {
119          get => _settings.ShowSystemTrayIcon;
120          set
121          {
122              _settings.ShowSystemTrayIcon = value;
123              Save();
124          }
125      }
126  
127      public bool IgnoreShortcutWhenFullscreen
128      {
129          get => _settings.IgnoreShortcutWhenFullscreen;
130          set
131          {
132              _settings.IgnoreShortcutWhenFullscreen = value;
133              Save();
134          }
135      }
136  
137      public bool DisableAnimations
138      {
139          get => _settings.DisableAnimations;
140          set
141          {
142              _settings.DisableAnimations = value;
143              Save();
144          }
145      }
146  
147      public int AutoGoBackIntervalIndex
148      {
149          get
150          {
151              var index = AutoGoHomeIntervals.IndexOf(_settings.AutoGoHomeInterval);
152              return index >= 0 ? index : 0;
153          }
154  
155          set
156          {
157              if (value >= 0 && value < AutoGoHomeIntervals.Count)
158              {
159                  _settings.AutoGoHomeInterval = AutoGoHomeIntervals[value];
160              }
161  
162              Save();
163          }
164      }
165  
166      public int EscapeKeyBehaviorIndex
167      {
168          get => (int)_settings.EscapeKeyBehaviorSetting;
169          set
170          {
171              _settings.EscapeKeyBehaviorSetting = (EscapeKeyBehavior)value;
172              Save();
173          }
174      }
175  
176      public ObservableCollection<ProviderSettingsViewModel> CommandProviders { get; } = new();
177  
178      public ObservableCollection<FallbackSettingsViewModel> FallbackRankings { get; set; } = new();
179  
180      public SettingsExtensionsViewModel Extensions { get; }
181  
182      public SettingsViewModel(SettingsModel settings, TopLevelCommandManager topLevelCommandManager, TaskScheduler scheduler, IThemeService themeService)
183      {
184          _settings = settings;
185          _topLevelCommandManager = topLevelCommandManager;
186  
187          Appearance = new AppearanceSettingsViewModel(themeService, _settings);
188  
189          var activeProviders = GetCommandProviders();
190          var allProviderSettings = _settings.ProviderSettings;
191  
192          var fallbacks = new List<FallbackSettingsViewModel>();
193          var currentRankings = _settings.FallbackRanks;
194          var needsSave = false;
195  
196          foreach (var item in activeProviders)
197          {
198              var providerSettings = settings.GetProviderSettings(item);
199  
200              var settingsModel = new ProviderSettingsViewModel(item, providerSettings, _settings);
201              CommandProviders.Add(settingsModel);
202  
203              fallbacks.AddRange(settingsModel.FallbackCommands);
204          }
205  
206          var fallbackRankings = new List<Scored<FallbackSettingsViewModel>>(fallbacks.Count);
207          foreach (var fallback in fallbacks)
208          {
209              var index = currentRankings.IndexOf(fallback.Id);
210              var score = fallbacks.Count;
211  
212              if (index >= 0)
213              {
214                  score = index;
215              }
216  
217              fallbackRankings.Add(new Scored<FallbackSettingsViewModel>() { Item = fallback, Score = score });
218  
219              if (index == -1)
220              {
221                  needsSave = true;
222              }
223          }
224  
225          FallbackRankings = new ObservableCollection<FallbackSettingsViewModel>(fallbackRankings.OrderBy(o => o.Score).Select(fr => fr.Item));
226          Extensions = new SettingsExtensionsViewModel(CommandProviders, scheduler);
227  
228          if (needsSave)
229          {
230              ApplyFallbackSort();
231          }
232      }
233  
234      private IEnumerable<CommandProviderWrapper> GetCommandProviders()
235      {
236          var allProviders = _topLevelCommandManager.CommandProviders;
237          return allProviders;
238      }
239  
240      public void ApplyFallbackSort()
241      {
242          _settings.FallbackRanks = FallbackRankings.Select(s => s.Id).ToArray();
243          Save();
244          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FallbackRankings)));
245      }
246  
247      private void Save() => SettingsModel.SaveSettings(_settings);
248  }