mirror of
https://github.com/microsoft/PowerToys
synced 2025-08-30 22:15:11 +00:00
runner: periodically check if there's a new version available on github and offer a visit
This commit is contained in:
committed by
Andrey Nekrasov
parent
c543b7585a
commit
0016836022
@@ -107,6 +107,7 @@
|
|||||||
<ClInclude Include="dpi_aware.h" />
|
<ClInclude Include="dpi_aware.h" />
|
||||||
<ClInclude Include="com_object_factory.h" />
|
<ClInclude Include="com_object_factory.h" />
|
||||||
<ClInclude Include="notifications.h" />
|
<ClInclude Include="notifications.h" />
|
||||||
|
<ClInclude Include="timeutil.h" />
|
||||||
<ClInclude Include="window_helpers.h" />
|
<ClInclude Include="window_helpers.h" />
|
||||||
<ClInclude Include="icon_helpers.h" />
|
<ClInclude Include="icon_helpers.h" />
|
||||||
<ClInclude Include="json.h" />
|
<ClInclude Include="json.h" />
|
||||||
|
@@ -90,6 +90,9 @@
|
|||||||
<ClInclude Include="com_object_factory.h">
|
<ClInclude Include="com_object_factory.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="timeutil.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="d2d_svg.cpp">
|
<ClCompile Include="d2d_svg.cpp">
|
||||||
@@ -148,4 +151,4 @@
|
|||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -3,15 +3,21 @@
|
|||||||
|
|
||||||
#include <msi.h>
|
#include <msi.h>
|
||||||
#include <common/common.h>
|
#include <common/common.h>
|
||||||
|
#include <common/json.h>
|
||||||
|
|
||||||
#include <common/winstore.h>
|
#include <common/winstore.h>
|
||||||
#include <common/notifications.h>
|
#include <common/notifications.h>
|
||||||
#include <MsiQuery.h>
|
#include <MsiQuery.h>
|
||||||
|
|
||||||
|
#include <winrt/Windows.Web.Http.h>
|
||||||
|
#include <winrt/Windows.Web.Http.Headers.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const wchar_t* POWER_TOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
|
const wchar_t* POWER_TOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
|
||||||
const wchar_t* DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH = L"delete_previous_powertoys_confirm";
|
const wchar_t* DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH = L"delete_previous_powertoys_confirm";
|
||||||
|
const wchar_t* USER_AGENT = L"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)";
|
||||||
|
const wchar_t* LATEST_RELEASE_ENDPOINT = L"https://api.github.com/repos/microsoft/PowerToys/releases/latest";
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace localized_strings
|
namespace localized_strings
|
||||||
@@ -82,3 +88,32 @@ bool uninstall_msi_version(const std::wstring& package_path)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::future<std::optional<new_version_download_info>> check_for_new_github_release_async()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
winrt::Windows::Web::Http::HttpClient client;
|
||||||
|
auto headers = client.DefaultRequestHeaders();
|
||||||
|
headers.UserAgent().TryParseAdd(USER_AGENT);
|
||||||
|
|
||||||
|
auto response = co_await client.GetAsync(winrt::Windows::Foundation::Uri{ LATEST_RELEASE_ENDPOINT });
|
||||||
|
(void)response.EnsureSuccessStatusCode();
|
||||||
|
const auto body = co_await response.Content().ReadAsStringAsync();
|
||||||
|
auto json_body = json::JsonValue::Parse(body).GetObjectW();
|
||||||
|
auto new_version = json_body.GetNamedString(L"tag_name");
|
||||||
|
winrt::Windows::Foundation::Uri release_page_uri{ json_body.GetNamedString(L"html_url") };
|
||||||
|
|
||||||
|
const auto current_version = get_product_version();
|
||||||
|
if (new_version == current_version)
|
||||||
|
{
|
||||||
|
co_return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
co_return new_version_download_info{ std::move(release_page_uri), new_version.c_str() };
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
co_return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
@@ -2,7 +2,17 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
#include <winrt/Windows.Foundation.h>
|
||||||
|
|
||||||
std::wstring get_msi_package_path();
|
std::wstring get_msi_package_path();
|
||||||
bool uninstall_msi_version(const std::wstring& package_path);
|
bool uninstall_msi_version(const std::wstring& package_path);
|
||||||
bool offer_msi_uninstallation();
|
bool offer_msi_uninstallation();
|
||||||
|
|
||||||
|
struct new_version_download_info
|
||||||
|
{
|
||||||
|
winrt::Windows::Foundation::Uri release_page_uri;
|
||||||
|
std::wstring version_string;
|
||||||
|
};
|
||||||
|
std::future<std::optional<new_version_download_info>> check_for_new_github_release_async();
|
||||||
|
@@ -97,6 +97,7 @@
|
|||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<AdditionalOptions>/await %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
@@ -134,6 +135,7 @@
|
|||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<AdditionalOptions>/await %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
namespace PTSettingsHelper {
|
namespace PTSettingsHelper {
|
||||||
|
|
||||||
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name);
|
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name);
|
||||||
|
std::wstring get_root_save_folder_location();
|
||||||
|
|
||||||
void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings);
|
void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings);
|
||||||
json::JsonObject load_module_settings(std::wstring_view powertoy_name);
|
json::JsonObject load_module_settings(std::wstring_view powertoy_name);
|
||||||
|
57
src/common/timeutil.h
Normal file
57
src/common/timeutil.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include <winrt/base.h>
|
||||||
|
|
||||||
|
namespace timeutil
|
||||||
|
{
|
||||||
|
inline std::wstring to_string(const time_t time)
|
||||||
|
{
|
||||||
|
return std::to_wstring(static_cast<uint64_t>(time));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::optional<std::time_t> from_string(const std::wstring& s)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
uint64_t i = std::stoull(s);
|
||||||
|
return static_cast<std::time_t>(i);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::time_t now()
|
||||||
|
{
|
||||||
|
return winrt::clock::to_time_t(winrt::clock::now());
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace diff
|
||||||
|
{
|
||||||
|
inline int64_t in_seconds(const std::time_t to, const std::time_t from)
|
||||||
|
{
|
||||||
|
return static_cast<int64_t>(std::difftime(to, from));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int64_t in_minutes(const std::time_t to, const std::time_t from)
|
||||||
|
{
|
||||||
|
return static_cast<int64_t>(std::difftime(to, from) / 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int64_t in_hours(const std::time_t to, const std::time_t from)
|
||||||
|
{
|
||||||
|
return static_cast<int64_t>(std::difftime(to, from) / 3600);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int64_t in_days(const std::time_t to, const std::time_t from)
|
||||||
|
{
|
||||||
|
return static_cast<int64_t>(std::difftime(to, from) / (3600 * 24));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -16,6 +16,11 @@
|
|||||||
#include <common/msi_to_msix_upgrade_lib/msi_to_msix_upgrade.h>
|
#include <common/msi_to_msix_upgrade_lib/msi_to_msix_upgrade.h>
|
||||||
#include <common/winstore.h>
|
#include <common/winstore.h>
|
||||||
#include <common/notifications.h>
|
#include <common/notifications.h>
|
||||||
|
#include <common/timeutil.h>
|
||||||
|
|
||||||
|
#include "update_state.h"
|
||||||
|
|
||||||
|
#include <winrt/Windows.System.h>
|
||||||
|
|
||||||
#if _DEBUG && _WIN64
|
#if _DEBUG && _WIN64
|
||||||
#include "unhandled_exception_handler.h"
|
#include "unhandled_exception_handler.h"
|
||||||
@@ -26,6 +31,8 @@ extern "C" IMAGE_DOS_HEADER __ImageBase;
|
|||||||
namespace localized_strings
|
namespace localized_strings
|
||||||
{
|
{
|
||||||
const wchar_t MSI_VERSION_IS_ALREADY_RUNNING[] = L"An older version of PowerToys is already running.";
|
const wchar_t MSI_VERSION_IS_ALREADY_RUNNING[] = L"An older version of PowerToys is already running.";
|
||||||
|
const wchar_t GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT[] = L"An update to PowerToys is available. Visit our GitHub page to get ";
|
||||||
|
const wchar_t GITHUB_NEW_VERSION_AGREE[] = L"Visit";
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -97,6 +104,46 @@ bool start_msi_uninstallation_sequence()
|
|||||||
return exit_code == 0;
|
return exit_code == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::future<void> check_github_updates()
|
||||||
|
{
|
||||||
|
const auto new_version = co_await check_for_new_github_release_async();
|
||||||
|
if (!new_version)
|
||||||
|
{
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
using namespace localized_strings;
|
||||||
|
|
||||||
|
std::wstring contents = GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT;
|
||||||
|
contents += new_version->version_string;
|
||||||
|
contents += L'.';
|
||||||
|
notifications::show_toast_with_activations(contents, {}, { notifications::link_button{ GITHUB_NEW_VERSION_AGREE, new_version->release_page_uri.ToString() } });
|
||||||
|
}
|
||||||
|
|
||||||
|
void github_update_checking_worker()
|
||||||
|
{
|
||||||
|
const int64_t update_check_period_minutes = 60 * 24;
|
||||||
|
|
||||||
|
auto state = UpdateState::load();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int64_t sleep_minutes_till_next_update = 0;
|
||||||
|
if (state.github_update_last_checked_date.has_value())
|
||||||
|
{
|
||||||
|
int64_t last_checked_minutes_ago = timeutil::diff::in_minutes(timeutil::now(), *state.github_update_last_checked_date);
|
||||||
|
if (last_checked_minutes_ago < 0)
|
||||||
|
{
|
||||||
|
last_checked_minutes_ago = update_check_period_minutes;
|
||||||
|
}
|
||||||
|
sleep_minutes_till_next_update = max(0, update_check_period_minutes - last_checked_minutes_ago);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::minutes(sleep_minutes_till_next_update));
|
||||||
|
|
||||||
|
check_github_updates().get();
|
||||||
|
state.github_update_last_checked_date.emplace(timeutil::now());
|
||||||
|
state.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
void alert_already_running()
|
void alert_already_running()
|
||||||
{
|
{
|
||||||
MessageBoxW(nullptr,
|
MessageBoxW(nullptr,
|
||||||
@@ -271,12 +318,17 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
|
std::thread{ [] {
|
||||||
|
github_update_checking_worker();
|
||||||
|
} }.detach();
|
||||||
|
|
||||||
if (winstore::running_as_packaged())
|
if (winstore::running_as_packaged())
|
||||||
{
|
{
|
||||||
std::thread{ [] {
|
std::thread{ [] {
|
||||||
start_msi_uninstallation_sequence();
|
start_msi_uninstallation_sequence();
|
||||||
} }.detach();
|
} }.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Singletons initialization order needs to be preserved, first events and
|
// Singletons initialization order needs to be preserved, first events and
|
||||||
// then modules to guarantee the reverse destruction order.
|
// then modules to guarantee the reverse destruction order.
|
||||||
SystemMenuHelperInstace();
|
SystemMenuHelperInstace();
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
<ImportGroup Label="Shared">
|
<ImportGroup Label="Shared">
|
||||||
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
@@ -64,6 +64,7 @@
|
|||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<AdditionalIncludeDirectories>..\common\inc;..\common\Telemetry;..;..\modules;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\common\inc;..\common\Telemetry;..;..\modules;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalOptions>/await %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
|
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
|
||||||
@@ -88,6 +89,7 @@
|
|||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<AdditionalIncludeDirectories>..\common\inc;..\common\Telemetry;..;..\modules;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\common\inc;..\common\Telemetry;..;..\modules;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalOptions>/await %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
@@ -117,6 +119,7 @@
|
|||||||
<ClCompile Include="trace.cpp" />
|
<ClCompile Include="trace.cpp" />
|
||||||
<ClCompile Include="tray_icon.cpp" />
|
<ClCompile Include="tray_icon.cpp" />
|
||||||
<ClCompile Include="unhandled_exception_handler.cpp" />
|
<ClCompile Include="unhandled_exception_handler.cpp" />
|
||||||
|
<ClCompile Include="update_state.cpp" />
|
||||||
<ClCompile Include="win_hook_event.cpp" />
|
<ClCompile Include="win_hook_event.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -124,6 +127,7 @@
|
|||||||
<ClInclude Include="general_settings.h" />
|
<ClInclude Include="general_settings.h" />
|
||||||
<ClInclude Include="lowlevel_keyboard_event.h" />
|
<ClInclude Include="lowlevel_keyboard_event.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="update_state.h" />
|
||||||
<ClInclude Include="powertoys_events.h" />
|
<ClInclude Include="powertoys_events.h" />
|
||||||
<ClInclude Include="powertoy_module.h" />
|
<ClInclude Include="powertoy_module.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
|
@@ -39,6 +39,9 @@
|
|||||||
<ClCompile Include="restart_elevated.cpp">
|
<ClCompile Include="restart_elevated.cpp">
|
||||||
<Filter>Utils</Filter>
|
<Filter>Utils</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="update_state.cpp">
|
||||||
|
<Filter>Utils</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
@@ -79,6 +82,9 @@
|
|||||||
<ClInclude Include="restart_elevated.h">
|
<ClInclude Include="restart_elevated.h">
|
||||||
<Filter>Utils</Filter>
|
<Filter>Utils</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="update_state.h">
|
||||||
|
<Filter>Utils</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Utils">
|
<Filter Include="Utils">
|
||||||
|
38
src/runner/update_state.cpp
Normal file
38
src/runner/update_state.cpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "update_state.h"
|
||||||
|
|
||||||
|
#include <common/json.h>
|
||||||
|
#include <common/timeutil.h>
|
||||||
|
#include <common/settings_helpers.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const wchar_t PERSISTENT_STATE_FILENAME[] = L"\\update_state.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateState UpdateState::load()
|
||||||
|
{
|
||||||
|
const auto file_name = PTSettingsHelper::get_root_save_folder_location() + PERSISTENT_STATE_FILENAME;
|
||||||
|
auto json = json::from_file(file_name);
|
||||||
|
UpdateState state;
|
||||||
|
|
||||||
|
if (!json)
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.github_update_last_checked_date = timeutil::from_string(json->GetNamedString(L"github_update_last_checked_date", L"invalid").c_str());
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateState::save()
|
||||||
|
{
|
||||||
|
json::JsonObject json;
|
||||||
|
if (github_update_last_checked_date.has_value())
|
||||||
|
{
|
||||||
|
json.SetNamedValue(L"github_update_last_checked_date", json::value(timeutil::to_string(*github_update_last_checked_date)));
|
||||||
|
}
|
||||||
|
const auto file_name = PTSettingsHelper::get_root_save_folder_location() + PERSISTENT_STATE_FILENAME;
|
||||||
|
json::to_file(file_name, json);
|
||||||
|
}
|
12
src/runner/update_state.h
Normal file
12
src/runner/update_state.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
struct UpdateState
|
||||||
|
{
|
||||||
|
std::optional<std::time_t> github_update_last_checked_date;
|
||||||
|
|
||||||
|
static UpdateState load();
|
||||||
|
void save();
|
||||||
|
};
|
Reference in New Issue
Block a user