UserSettings.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; 6 using System.ComponentModel.Composition; 7 using System.IO; 8 using System.IO.Abstractions; 9 using System.Threading; 10 11 using ManagedCommon; 12 using Microsoft.PowerToys.Settings.UI.Library; 13 using Microsoft.PowerToys.Settings.UI.Library.Utilities; 14 15 namespace PowerOCR.Settings 16 { 17 [Export(typeof(IUserSettings))] 18 public class UserSettings : IUserSettings 19 { 20 private readonly SettingsUtils _settingsUtils; 21 private const string PowerOcrModuleName = "TextExtractor"; 22 private const string DefaultActivationShortcut = "Win + Shift + O"; 23 private const int MaxNumberOfRetry = 5; 24 private const int SettingsReadOnChangeDelayInMs = 300; 25 26 private readonly IFileSystemWatcher _watcher; 27 private readonly Lock _loadingSettingsLock = new(); 28 29 [ImportingConstructor] 30 public UserSettings(Helpers.IThrottledActionInvoker throttledActionInvoker) 31 { 32 _settingsUtils = SettingsUtils.Default; 33 ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut); 34 PreferredLanguage = new SettingItem<string>(string.Empty); 35 36 LoadSettingsFromJson(); 37 38 // delay loading settings on change by some time to avoid file in use exception 39 _watcher = Helper.GetFileWatcher(PowerOcrModuleName, "settings.json", () => throttledActionInvoker.ScheduleAction(LoadSettingsFromJson, SettingsReadOnChangeDelayInMs)); 40 } 41 42 public SettingItem<string> ActivationShortcut { get; private set; } 43 44 public SettingItem<string> PreferredLanguage { get; private set; } 45 46 private void LoadSettingsFromJson() 47 { 48 // TODO this IO call should by Async, update GetFileWatcher helper to support async 49 lock (_loadingSettingsLock) 50 { 51 { 52 var retry = true; 53 var retryCount = 0; 54 55 while (retry) 56 { 57 try 58 { 59 retryCount++; 60 61 if (!_settingsUtils.SettingsExists(PowerOcrModuleName)) 62 { 63 Logger.LogInfo("TextExtractor settings.json was missing, creating a new one"); 64 var defaultPowerOcrSettings = new PowerOcrSettings(); 65 defaultPowerOcrSettings.Save(_settingsUtils); 66 } 67 68 var settings = _settingsUtils.GetSettingsOrDefault<PowerOcrSettings>(PowerOcrModuleName); 69 if (settings != null) 70 { 71 ActivationShortcut.Value = settings.Properties.ActivationShortcut.ToString(); 72 PreferredLanguage.Value = settings.Properties.PreferredLanguage.ToString(); 73 } 74 75 retry = false; 76 } 77 catch (IOException ex) 78 { 79 if (retryCount > MaxNumberOfRetry) 80 { 81 retry = false; 82 } 83 84 Logger.LogError("Failed to read changed settings", ex); 85 Thread.Sleep(500); 86 } 87 catch (Exception ex) 88 { 89 if (retryCount > MaxNumberOfRetry) 90 { 91 retry = false; 92 } 93 94 Logger.LogError("Failed to read changed settings", ex); 95 Thread.Sleep(500); 96 } 97 } 98 } 99 } 100 } 101 102 public void SendSettingsTelemetry() 103 { 104 Logger.LogInfo("Sending settings telemetry"); 105 var settings = _settingsUtils.GetSettingsOrDefault<PowerOcrSettings>(PowerOcrModuleName); 106 var properties = settings?.Properties; 107 if (properties == null) 108 { 109 Logger.LogError("Failed to send settings telemetry"); 110 return; 111 } 112 113 // TODO: Send Telemetry when settings change 114 // var telemetrySettings = new Telemetry.PowerOcrSettings(properties.VisibleColorFormats) 115 // { 116 // ActivationShortcut = properties.ActivationShortcut.ToString(), 117 // ActivationBehavior = properties.ActivationAction.ToString(), 118 // ColorFormatForClipboard = properties.CopiedColorRepresentation.ToString(), 119 // ShowColorName = properties.ShowColorName, 120 // }; 121 // 122 // PowerToysTelemetry.Log.WriteEvent(telemetrySettings); 123 } 124 } 125 }