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 }