Settings.cpp
  1  #include "pch.h"
  2  #include "Settings.h"
  3  #include "ImageResizerConstants.h"
  4  
  5  #include <common/utils/json.h>
  6  #include <common/SettingsAPI/settings_helpers.h>
  7  #include <filesystem>
  8  #include <commctrl.h>
  9  
 10  namespace
 11  {
 12      const wchar_t c_imageResizerDataFilePath[] = L"\\image-resizer-settings.json";
 13      const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\ImageResizer";
 14      const wchar_t c_enabled[] = L"enabled";
 15      const wchar_t c_ImageResizer[] = L"Image Resizer";
 16  
 17      unsigned int RegReadInteger(const std::wstring& valueName, unsigned int defaultValue)
 18      {
 19          DWORD type = REG_DWORD;
 20          DWORD data = 0;
 21          DWORD size = sizeof(DWORD);
 22          if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), &type, &data, &size) == ERROR_SUCCESS)
 23          {
 24              return data;
 25          }
 26          return defaultValue;
 27      }
 28  
 29      bool RegReadBoolean(const std::wstring& valueName, bool defaultValue)
 30      {
 31          DWORD value = RegReadInteger(valueName.c_str(), defaultValue ? 1 : 0);
 32          return (value == 0) ? false : true;
 33      }
 34  
 35      bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime)
 36      {
 37          WIN32_FILE_ATTRIBUTE_DATA attr{};
 38          if (GetFileAttributesExW(filePath.c_str(), GetFileExInfoStandard, &attr))
 39          {
 40              *lpFileTime = attr.ftLastWriteTime;
 41              return true;
 42          }
 43          return false;
 44      }
 45  }
 46  
 47  CSettings::CSettings()
 48  {
 49      generalJsonFilePath = PTSettingsHelper::get_powertoys_general_save_file_location();
 50      std::wstring oldSavePath = PTSettingsHelper::get_module_save_folder_location(ImageResizerConstants::ModuleOldSaveFolderKey);
 51      std::wstring savePath = PTSettingsHelper::get_module_save_folder_location(ImageResizerConstants::ModuleSaveFolderKey);
 52      std::error_code ec;
 53      if (std::filesystem::exists(oldSavePath, ec))
 54      {
 55          std::filesystem::copy(oldSavePath, savePath, std::filesystem::copy_options::recursive, ec);
 56          std::filesystem::remove_all(oldSavePath, ec);
 57      }
 58  
 59      jsonFilePath = savePath + std::wstring(c_imageResizerDataFilePath);
 60      Load();
 61  }
 62  
 63  void CSettings::Save()
 64  {
 65      json::JsonObject jsonData;
 66  
 67      json::to_file(jsonFilePath, jsonData);
 68      GetSystemTimeAsFileTime(&lastLoadedTime);
 69  }
 70  
 71  void CSettings::Load()
 72  {
 73      if (!std::filesystem::exists(jsonFilePath))
 74      {
 75          MigrateFromRegistry();
 76  
 77          Save();
 78      }
 79      else
 80      {
 81          ParseJson();
 82      }
 83  }
 84  
 85  void CSettings::RefreshEnabledState()
 86  {
 87      // Load json settings from data file if it is modified in the meantime.
 88      FILETIME lastModifiedTime{};
 89      if (!(LastModifiedTime(generalJsonFilePath, &lastModifiedTime) &&
 90            CompareFileTime(&lastModifiedTime, &lastLoadedGeneralSettingsTime) == 1))
 91          return;
 92  
 93      lastLoadedGeneralSettingsTime = lastModifiedTime;
 94  
 95      auto json = json::from_file(generalJsonFilePath);
 96      if (!json)
 97          return;
 98  
 99      const json::JsonObject& jsonSettings = json.value();
100      try
101      {
102          json::JsonObject modulesEnabledState;
103          json::get(jsonSettings, c_enabled, modulesEnabledState, json::JsonObject{});
104          json::get(modulesEnabledState, c_ImageResizer, settings.enabled, true);
105      }
106      catch (const winrt::hresult_error&)
107      {
108      }
109  }
110  
111  void CSettings::Reload()
112  {
113      // Load json settings from data file if it is modified in the meantime.
114      FILETIME lastModifiedTime{};
115      if (LastModifiedTime(jsonFilePath, &lastModifiedTime) &&
116          CompareFileTime(&lastModifiedTime, &lastLoadedTime) == 1)
117      {
118          Load();
119      }
120  }
121  
122  void CSettings::MigrateFromRegistry()
123  {
124      settings.enabled = RegReadBoolean(c_enabled, true);
125  }
126  
127  void CSettings::ParseJson()
128  {
129      auto json = json::from_file(jsonFilePath);
130      if (json)
131      {
132          const json::JsonObject& jsonSettings = json.value();
133          try
134          {
135              // NB: add any new settings here
136          }
137          catch (const winrt::hresult_error&)
138          {
139          }
140      }
141      GetSystemTimeAsFileTime(&lastLoadedTime);
142  }
143  
144  CSettings& CSettingsInstance()
145  {
146      static CSettings instance;
147      return instance;
148  }