/ src / modules / Workspaces / WorkspacesLib / WorkspacesData.cpp
WorkspacesData.cpp
  1  #include "pch.h"
  2  #include "WorkspacesData.h"
  3  #include <common/SettingsAPI/settings_helpers.h>
  4  
  5  #include <workspaces-common/GuidUtils.h>
  6  
  7  namespace NonLocalizable
  8  {
  9      const inline wchar_t ModuleKey[] = L"Workspaces";
 10  }
 11  
 12  namespace WorkspacesData
 13  {
 14      std::wstring WorkspacesFile()
 15      {
 16          std::wstring settingsFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
 17          return settingsFolderPath + L"\\workspaces.json";
 18      }
 19  
 20      std::wstring TempWorkspacesFile()
 21      {
 22          std::wstring settingsFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
 23          return settingsFolderPath + L"\\temp-workspaces.json";
 24      }
 25  
 26      RECT WorkspacesProject::Application::Position::toRect() const noexcept
 27      {
 28          return RECT{ .left = x, .top = y, .right = x + width, .bottom = y + height };
 29      }
 30  
 31      namespace WorkspacesProjectJSON
 32      {
 33          namespace ApplicationJSON
 34          {
 35              namespace PositionJSON
 36              {
 37                  namespace NonLocalizable
 38                  {
 39                      const static wchar_t* XAxisID = L"X";
 40                      const static wchar_t* YAxisID = L"Y";
 41                      const static wchar_t* WidthID = L"width";
 42                      const static wchar_t* HeightID = L"height";
 43                  }
 44  
 45                  json::JsonObject ToJson(const WorkspacesProject::Application::Position& position)
 46                  {
 47                      json::JsonObject json{};
 48                      json.SetNamedValue(NonLocalizable::XAxisID, json::value(position.x));
 49                      json.SetNamedValue(NonLocalizable::YAxisID, json::value(position.y));
 50                      json.SetNamedValue(NonLocalizable::WidthID, json::value(position.width));
 51                      json.SetNamedValue(NonLocalizable::HeightID, json::value(position.height));
 52                      return json;
 53                  }
 54  
 55                  std::optional<WorkspacesProject::Application::Position> FromJson(const json::JsonObject& json)
 56                  {
 57                      WorkspacesProject::Application::Position result;
 58                      try
 59                      {
 60                          result.x = static_cast<int>(json.GetNamedNumber(NonLocalizable::XAxisID, 0));
 61                          result.y = static_cast<int>(json.GetNamedNumber(NonLocalizable::YAxisID, 0));
 62                          result.width = static_cast<int>(json.GetNamedNumber(NonLocalizable::WidthID, 0));
 63                          result.height = static_cast<int>(json.GetNamedNumber(NonLocalizable::HeightID, 0));
 64                      }
 65                      catch (const winrt::hresult_error&)
 66                      {
 67                          return std::nullopt;
 68                      }
 69  
 70                      return result;
 71                  }
 72              }
 73  
 74              namespace NonLocalizable
 75              {
 76                  const static wchar_t* AppIdID = L"id";
 77                  const static wchar_t* AppNameID = L"application";
 78                  const static wchar_t* AppPathID = L"application-path";
 79                  const static wchar_t* AppPackageFullNameID = L"package-full-name";
 80                  const static wchar_t* AppUserModelId = L"app-user-model-id";
 81                  const static wchar_t* PwaAppId = L"pwa-app-id";
 82                  const static wchar_t* AppTitleID = L"title";
 83                  const static wchar_t* CommandLineArgsID = L"command-line-arguments";
 84                  const static wchar_t* ElevatedID = L"is-elevated";
 85                  const static wchar_t* CanLaunchElevatedID = L"can-launch-elevated";
 86                  const static wchar_t* MinimizedID = L"minimized";
 87                  const static wchar_t* MaximizedID = L"maximized";
 88                  const static wchar_t* PositionID = L"position";
 89                  const static wchar_t* MonitorID = L"monitor";
 90                  const static wchar_t* VersionID = L"version";
 91              }
 92  
 93              json::JsonObject ToJson(const WorkspacesProject::Application& data)
 94              {
 95                  json::JsonObject json{};
 96                  json.SetNamedValue(NonLocalizable::AppIdID, json::value(data.id));
 97                  json.SetNamedValue(NonLocalizable::AppNameID, json::value(data.name));
 98                  json.SetNamedValue(NonLocalizable::AppPathID, json::value(data.path));
 99                  json.SetNamedValue(NonLocalizable::AppTitleID, json::value(data.title));
100                  json.SetNamedValue(NonLocalizable::AppPackageFullNameID, json::value(data.packageFullName));
101                  json.SetNamedValue(NonLocalizable::AppUserModelId, json::value(data.appUserModelId));
102                  json.SetNamedValue(NonLocalizable::PwaAppId, json::value(data.pwaAppId));
103                  json.SetNamedValue(NonLocalizable::CommandLineArgsID, json::value(data.commandLineArgs));
104                  json.SetNamedValue(NonLocalizable::ElevatedID, json::value(data.isElevated));
105                  json.SetNamedValue(NonLocalizable::CanLaunchElevatedID, json::value(data.canLaunchElevated));
106                  json.SetNamedValue(NonLocalizable::MinimizedID, json::value(data.isMinimized));
107                  json.SetNamedValue(NonLocalizable::MaximizedID, json::value(data.isMaximized));
108                  json.SetNamedValue(NonLocalizable::PositionID, PositionJSON::ToJson(data.position));
109                  json.SetNamedValue(NonLocalizable::MonitorID, json::value(data.monitor));
110                  json.SetNamedValue(NonLocalizable::VersionID, json::value(data.version));
111  
112                  return json;
113              }
114  
115              std::optional<WorkspacesProject::Application> FromJson(const json::JsonObject& json)
116              {
117                  WorkspacesProject::Application result;
118                  try
119                  {
120                      if (json.HasKey(NonLocalizable::AppIdID))
121                      {
122                          result.id = json.GetNamedString(NonLocalizable::AppIdID);
123                      }
124  
125                      if (json.HasKey(NonLocalizable::AppNameID))
126                      {
127                          result.name = json.GetNamedString(NonLocalizable::AppNameID);
128                      }
129  
130                      result.path = json.GetNamedString(NonLocalizable::AppPathID);
131                      result.title = json.GetNamedString(NonLocalizable::AppTitleID);
132                      if (json.HasKey(NonLocalizable::AppPackageFullNameID))
133                      {
134                          result.packageFullName = json.GetNamedString(NonLocalizable::AppPackageFullNameID);
135                      }
136  
137                      if (json.HasKey(NonLocalizable::AppUserModelId))
138                      {
139                          result.appUserModelId = json.GetNamedString(NonLocalizable::AppUserModelId);
140                      }
141  
142                      if (json.HasKey(NonLocalizable::PwaAppId))
143                      {
144                          result.pwaAppId = json.GetNamedString(NonLocalizable::PwaAppId);
145                      }
146  
147                      result.commandLineArgs = json.GetNamedString(NonLocalizable::CommandLineArgsID);
148  
149                      if (json.HasKey(NonLocalizable::ElevatedID))
150                      {
151                          result.isElevated = json.GetNamedBoolean(NonLocalizable::ElevatedID);
152                      }
153  
154                      if (json.HasKey(NonLocalizable::CanLaunchElevatedID))
155                      {
156                          result.canLaunchElevated = json.GetNamedBoolean(NonLocalizable::CanLaunchElevatedID);
157                      }
158  
159                      result.isMaximized = json.GetNamedBoolean(NonLocalizable::MaximizedID);
160                      result.isMinimized = json.GetNamedBoolean(NonLocalizable::MinimizedID);
161  
162                      result.monitor = static_cast<int>(json.GetNamedNumber(NonLocalizable::MonitorID));
163                      if (json.HasKey(NonLocalizable::PositionID))
164                      {
165                          auto position = PositionJSON::FromJson(json.GetNamedObject(NonLocalizable::PositionID));
166                          if (!position.has_value())
167                          {
168                              return std::nullopt;
169                          }
170  
171                          result.position = position.value();
172                      }
173  
174                      if (json.HasKey(NonLocalizable::VersionID))
175                      {
176                          result.version = json.GetNamedString(NonLocalizable::VersionID);
177                      }
178                  }
179                  catch (const winrt::hresult_error&)
180                  {
181                      return std::nullopt;
182                  }
183  
184                  return result;
185              }
186          }
187  
188          namespace MonitorJSON
189          {
190              namespace MonitorRectJSON
191              {
192                  namespace NonLocalizable
193                  {
194                      const static wchar_t* TopID = L"top";
195                      const static wchar_t* LeftID = L"left";
196                      const static wchar_t* WidthID = L"width";
197                      const static wchar_t* HeightID = L"height";
198                  }
199  
200                  json::JsonObject ToJson(const WorkspacesProject::Monitor::MonitorRect& data)
201                  {
202                      json::JsonObject json{};
203                      json.SetNamedValue(NonLocalizable::TopID, json::value(data.top));
204                      json.SetNamedValue(NonLocalizable::LeftID, json::value(data.left));
205                      json.SetNamedValue(NonLocalizable::WidthID, json::value(data.width));
206                      json.SetNamedValue(NonLocalizable::HeightID, json::value(data.height));
207  
208                      return json;
209                  }
210  
211                  std::optional<WorkspacesProject::Monitor::MonitorRect> FromJson(const json::JsonObject& json)
212                  {
213                      WorkspacesProject::Monitor::MonitorRect result;
214                      try
215                      {
216                          result.top = static_cast<int>(json.GetNamedNumber(NonLocalizable::TopID));
217                          result.left = static_cast<int>(json.GetNamedNumber(NonLocalizable::LeftID));
218                          result.width = static_cast<int>(json.GetNamedNumber(NonLocalizable::WidthID));
219                          result.height = static_cast<int>(json.GetNamedNumber(NonLocalizable::HeightID));
220                      }
221                      catch (const winrt::hresult_error&)
222                      {
223                          return std::nullopt;
224                      }
225  
226                      return result;
227                  }
228              }
229  
230              namespace NonLocalizable
231              {
232                  const static wchar_t* MonitorID = L"id";
233                  const static wchar_t* InstanceID = L"instance-id";
234                  const static wchar_t* NumberID = L"monitor-number";
235                  const static wchar_t* DpiID = L"dpi";
236                  const static wchar_t* MonitorRectDpiAwareID = L"monitor-rect-dpi-aware";
237                  const static wchar_t* MonitorRectDpiUnawareID = L"monitor-rect-dpi-unaware";
238              }
239  
240              json::JsonObject ToJson(const WorkspacesProject::Monitor& data)
241              {
242                  json::JsonObject json{};
243                  json.SetNamedValue(NonLocalizable::MonitorID, json::value(data.id));
244                  json.SetNamedValue(NonLocalizable::InstanceID, json::value(data.instanceId));
245                  json.SetNamedValue(NonLocalizable::NumberID, json::value(data.number));
246                  json.SetNamedValue(NonLocalizable::DpiID, json::value(data.dpi));
247                  json.SetNamedValue(NonLocalizable::MonitorRectDpiAwareID, MonitorRectJSON::ToJson(data.monitorRectDpiAware));
248                  json.SetNamedValue(NonLocalizable::MonitorRectDpiUnawareID, MonitorRectJSON::ToJson(data.monitorRectDpiUnaware));
249  
250                  return json;
251              }
252  
253              std::optional<WorkspacesProject::Monitor> FromJson(const json::JsonObject& json)
254              {
255                  WorkspacesProject::Monitor result;
256                  try
257                  {
258                      result.id = json.GetNamedString(NonLocalizable::MonitorID);
259                      result.instanceId = json.GetNamedString(NonLocalizable::InstanceID);
260                      result.number = static_cast<int>(json.GetNamedNumber(NonLocalizable::NumberID));
261                      result.dpi = static_cast<int>(json.GetNamedNumber(NonLocalizable::DpiID));
262                      auto rectDpiAware = MonitorRectJSON::FromJson(json.GetNamedObject(NonLocalizable::MonitorRectDpiAwareID));
263                      if (!rectDpiAware.has_value())
264                      {
265                          return std::nullopt;
266                      }
267  
268                      auto rectDpiUnaware = MonitorRectJSON::FromJson(json.GetNamedObject(NonLocalizable::MonitorRectDpiUnawareID));
269                      if (!rectDpiUnaware.has_value())
270                      {
271                          return std::nullopt;
272                      }
273  
274                      result.monitorRectDpiAware = rectDpiAware.value();
275                      result.monitorRectDpiUnaware = rectDpiUnaware.value();
276                  }
277                  catch (const winrt::hresult_error&)
278                  {
279                      return std::nullopt;
280                  }
281  
282                  return result;
283              }
284          }
285  
286          namespace NonLocalizable
287          {
288              const static wchar_t* IdID = L"id";
289              const static wchar_t* NameID = L"name";
290              const static wchar_t* CreationTimeID = L"creation-time";
291              const static wchar_t* LastLaunchedTimeID = L"last-launched-time";
292              const static wchar_t* IsShortcutNeededID = L"is-shortcut-needed";
293              const static wchar_t* MoveExistingWindowsID = L"move-existing-windows";
294              const static wchar_t* MonitorConfigurationID = L"monitor-configuration";
295              const static wchar_t* AppsID = L"applications";
296              const static wchar_t* Version = L"version";
297          }
298  
299          json::JsonObject ToJson(const WorkspacesProject& data)
300          {
301              json::JsonObject json{};
302  
303              json::JsonArray appsArray{};
304              for (const auto& app : data.apps)
305              {
306                  appsArray.Append(ApplicationJSON::ToJson(app));
307              }
308  
309              json::JsonArray monitorsArray{};
310              for (const auto& monitor : data.monitors)
311              {
312                  monitorsArray.Append(MonitorJSON::ToJson(monitor));
313              }
314  
315              json.SetNamedValue(NonLocalizable::IdID, json::value(data.id));
316              json.SetNamedValue(NonLocalizable::NameID, json::value(data.name));
317              json.SetNamedValue(NonLocalizable::CreationTimeID, json::value(static_cast<long>(data.creationTime)));
318              if (data.lastLaunchedTime.has_value())
319              {
320                  json.SetNamedValue(NonLocalizable::LastLaunchedTimeID, json::value(static_cast<long>(data.lastLaunchedTime.value())));
321              }
322              json.SetNamedValue(NonLocalizable::IsShortcutNeededID, json::value(data.isShortcutNeeded));
323              json.SetNamedValue(NonLocalizable::MoveExistingWindowsID, json::value(data.moveExistingWindows));
324              json.SetNamedValue(NonLocalizable::MonitorConfigurationID, monitorsArray);
325              json.SetNamedValue(NonLocalizable::AppsID, appsArray);
326              return json;
327          }
328  
329          std::optional<WorkspacesProject> FromJson(const json::JsonObject& json)
330          {
331              WorkspacesProject result{};
332  
333              try
334              {
335                  result.id = json.GetNamedString(NonLocalizable::IdID);
336                  result.name = json.GetNamedString(NonLocalizable::NameID);
337                  result.creationTime = static_cast<time_t>(json.GetNamedNumber(NonLocalizable::CreationTimeID));
338  
339                  if (json.HasKey(NonLocalizable::LastLaunchedTimeID))
340                  {
341                      result.lastLaunchedTime = static_cast<time_t>(json.GetNamedNumber(NonLocalizable::LastLaunchedTimeID));
342                  }
343  
344                  if (json.HasKey(NonLocalizable::IsShortcutNeededID))
345                  {
346                      result.isShortcutNeeded = json.GetNamedBoolean(NonLocalizable::IsShortcutNeededID);
347                  }
348  
349                  if (json.HasKey(NonLocalizable::MoveExistingWindowsID))
350                  {
351                      result.moveExistingWindows = json.GetNamedBoolean(NonLocalizable::MoveExistingWindowsID);
352                  }
353  
354                  auto appsArray = json.GetNamedArray(NonLocalizable::AppsID);
355                  for (uint32_t i = 0; i < appsArray.Size(); ++i)
356                  {
357                      auto obj = ApplicationJSON::FromJson(appsArray.GetObjectAt(i));
358                      if (!obj.has_value())
359                      {
360                          return std::nullopt;
361                      }
362  
363                      result.apps.push_back(obj.value());
364                  }
365  
366                  auto monitorsArray = json.GetNamedArray(NonLocalizable::MonitorConfigurationID);
367                  for (uint32_t i = 0; i < monitorsArray.Size(); ++i)
368                  {
369                      auto obj = MonitorJSON::FromJson(monitorsArray.GetObjectAt(i));
370                      if (!obj.has_value())
371                      {
372                          return std::nullopt;
373                      }
374  
375                      result.monitors.push_back(obj.value());
376                  }
377              }
378              catch (const winrt::hresult_error&)
379              {
380                  return std::nullopt;
381              }
382  
383              return result;
384          }
385      }
386  
387      namespace WorkspacesListJSON
388      {
389          namespace NonLocalizable
390          {
391              const static wchar_t* WorkspacesID = L"workspaces";
392          }
393  
394          json::JsonObject ToJson(const std::vector<WorkspacesProject>& data)
395          {
396              json::JsonObject json{};
397              json::JsonArray projectsArray{};
398  
399              for (const auto& project : data)
400              {
401                  projectsArray.Append(WorkspacesProjectJSON::ToJson(project));
402              }
403  
404              json.SetNamedValue(NonLocalizable::WorkspacesID, projectsArray);
405              return json;
406          }
407  
408          std::optional<std::vector<WorkspacesProject>> FromJson(const json::JsonObject& json)
409          {
410              std::vector<WorkspacesProject> result{};
411  
412              try
413              {
414                  auto array = json.GetNamedArray(NonLocalizable::WorkspacesID);
415                  for (uint32_t i = 0; i < array.Size(); ++i)
416                  {
417                      auto obj = WorkspacesProjectJSON::FromJson(array.GetObjectAt(i));
418                      if (obj.has_value())
419                      {
420                          result.push_back(obj.value());
421                      }
422                      else
423                      {
424                          return std::nullopt;
425                      }
426                  }
427              }
428              catch (const winrt::hresult_error&)
429              {
430                  return std::nullopt;
431              }
432  
433              return result;
434          }
435      }
436  
437      namespace AppLaunchInfoJSON
438      {
439          namespace NonLocalizable
440          {
441              const static wchar_t* ApplicationID = L"application";
442              const static wchar_t* StateID = L"state";
443          }
444  
445          json::JsonObject ToJson(const LaunchingAppState& data)
446          {
447              json::JsonObject json{};
448              json.SetNamedValue(NonLocalizable::ApplicationID, WorkspacesProjectJSON::ApplicationJSON::ToJson(data.application));
449              json.SetNamedValue(NonLocalizable::StateID, json::value(static_cast<int>(data.state)));
450              return json;
451          }
452  
453          std::optional<LaunchingAppState> FromJson(const json::JsonObject& json)
454          {
455              LaunchingAppState result{};
456  
457              try
458              {
459                  auto app = WorkspacesProjectJSON::ApplicationJSON::FromJson(json.GetNamedObject(NonLocalizable::ApplicationID));
460                  if (!app.has_value())
461                  {
462                      return std::nullopt;
463                  }
464  
465                  result.application = app.value();
466                  result.state = static_cast<LaunchingState>(json.GetNamedNumber(NonLocalizable::StateID));
467              }
468              catch (const winrt::hresult_error&)
469              {
470                  return std::nullopt;
471              }
472  
473              return result;
474          }
475      }
476  
477      namespace AppLaunchInfoListJSON
478      {
479          namespace NonLocalizable
480          {
481              const static wchar_t* AppLaunchInfoID = L"appLaunchInfos";
482          }
483  
484          json::JsonObject ToJson(const LaunchingAppStateMap& data)
485          {
486              json::JsonObject json{};
487              json::JsonArray appLaunchInfoArray{};
488              for (const auto& appLaunchInfo : data)
489              {
490                  appLaunchInfoArray.Append(AppLaunchInfoJSON::ToJson(appLaunchInfo.second));
491              }
492  
493              json.SetNamedValue(NonLocalizable::AppLaunchInfoID, appLaunchInfoArray);
494              return json;
495          }
496  
497          std::optional<LaunchingAppStateMap> FromJson(const json::JsonObject& json)
498          {
499              LaunchingAppStateMap result{};
500  
501              try
502              {
503                  auto array = json.GetNamedArray(NonLocalizable::AppLaunchInfoID);
504                  for (uint32_t i = 0; i < array.Size(); ++i)
505                  {
506                      auto obj = AppLaunchInfoJSON::FromJson(array.GetObjectAt(i));
507                      if (obj.has_value())
508                      {
509                          result.insert({ obj.value().application, obj.value() });
510                      }
511                      else
512                      {
513                          return std::nullopt;
514                      }
515                  }
516              }
517              catch (const winrt::hresult_error&)
518              {
519                  return std::nullopt;
520              }
521  
522              return result;
523          }
524      }
525  
526      namespace AppLaunchDataJSON
527      {
528          namespace NonLocalizable
529          {
530              const static wchar_t* AppsID = L"apps";
531              const static wchar_t* ProcessID = L"processId";
532          }
533  
534          json::JsonObject ToJson(const AppLaunchData& data)
535          {
536              json::JsonObject json{};
537              json.SetNamedValue(NonLocalizable::AppsID, AppLaunchInfoListJSON::ToJson(data.appsStateList));
538              json.SetNamedValue(NonLocalizable::ProcessID, json::value(data.launcherProcessID));
539              return json;
540          }
541      }
542  }