common project localization: move out all updating strings

- finish localizing boostrapper/runner/action_runner
This commit is contained in:
yuyoyuppe
2020-10-22 19:02:59 +03:00
committed by Andrey Nekrasov
parent 5629e8068b
commit f33b3c771a
18 changed files with 427 additions and 181 deletions

View File

@@ -64,4 +64,94 @@
<data name="DOTNET_CORE_DOWNLOAD_FAILURE_TITLE" xml:space="preserve"> <data name="DOTNET_CORE_DOWNLOAD_FAILURE_TITLE" xml:space="preserve">
<value>PowerToys installation error</value> <value>PowerToys installation error</value>
</data> </data>
<data name="GITHUB_NEW_VERSION_AVAILABLE" xml:space="preserve">
<value>An update to PowerToys is available.</value>
</data>
<data name="GITHUB_NEW_VERSION_DOWNLOAD_STARTED" xml:space="preserve">
<value>PowerToys download started.</value>
</data>
<data name="GITHUB_NEW_VERSION_READY_TO_INSTALL" xml:space="preserve">
<value>An update to PowerToys is ready to install.</value>
</data>
<data name="GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR" xml:space="preserve">
<value>Error: couldn't download PowerToys installer. Visit our GitHub page to update.</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_NOW" xml:space="preserve">
<value>Update now</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART" xml:space="preserve">
<value>At next launch</value>
</data>
<data name="UNINSTALLATION_UNKNOWN_ERROR" xml:space="preserve">
<value>Error: please uninstall the previous version of PowerToys manually.</value>
</data>
<data name="GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT" xml:space="preserve">
<value>An update to PowerToys is available. Visit our GitHub page to update.</value>
</data>
<data name="GITHUB_NEW_VERSION_UNAVAILABLE" xml:space="preserve">
<value>PowerToys is up to date.</value>
</data>
<data name="GITHUB_NEW_VERSION_VISIT" xml:space="preserve">
<value>Visit</value>
</data>
<data name="GITHUB_NEW_VERSION_MORE_INFO" xml:space="preserve">
<value>More info...</value>
</data>
<data name="GITHUB_NEW_VERSION_ABORT" xml:space="preserve">
<value>Abort</value>
</data>
<data name="GITHUB_NEW_VERSION_SNOOZE_TITLE" xml:space="preserve">
<value>Click Snooze to be reminded in:</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D" xml:space="preserve">
<value>1 day</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D" xml:space="preserve">
<value>5 days</value>
</data>
<data name="DOWNLOAD_IN_PROGRESS" xml:space="preserve">
<value>Downloading...</value>
</data>
<data name="DOWNLOAD_COMPLETE" xml:space="preserve">
<value>Download complete</value>
</data>
<data name="TOAST_TITLE" xml:space="preserve">
<value>PowerToys Update</value>
</data>
<data name="OFFER_UNINSTALL_MSI" xml:space="preserve">
<value>We've detected a previous installation of PowerToys. Would you like to remove it?</value>
</data>
<data name="OFFER_UNINSTALL_MSI_TITLE" xml:space="preserve">
<value>PowerToys: uninstall previous version?</value>
</data>
<data name="INSTALLER_EXTRACT_ERROR" xml:space="preserve">
<value>Couldn't extract MSI installer!</value>
</data>
<data name="EXTRACTING_INSTALLER" xml:space="preserve">
<value>Extracting PowerToys MSI...</value>
</data>
<data name="UNINSTALLING_PREVIOUS_VERSION" xml:space="preserve">
<value>Uninstalling previous PowerToys version...</value>
</data>
<data name="UNINSTALL_PREVIOUS_VERSION_ERROR" xml:space="preserve">
<value>Couldn't uninstall previous PowerToys version!</value>
</data>
<data name="INSTALLING_DOTNET" xml:space="preserve">
<value>Installing dotnet...</value>
</data>
<data name="DOTNET_INSTALL_ERROR" xml:space="preserve">
<value>Couldn't install dotnet!</value>
</data>
<data name="INSTALLING_NEW_VERSION" xml:space="preserve">
<value>Installing new PowerToys version...</value>
</data>
<data name="NEW_VERSION_INSTALLATION_DONE" xml:space="preserve">
<value>PowerToys installation complete!</value>
</data>
<data name="NEW_VERSION_INSTALLATION_ERROR" xml:space="preserve">
<value>Couldn't install new PowerToys version.</value>
</data>
<data name="SNOOZE_BUTTON" xml:space="preserve">
<value>Snooze</value>
</data>
</root> </root>

View File

@@ -14,11 +14,14 @@
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
auto Strings = updating::notifications::strings::create();
#define STR_HELPER(x) #x #define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x) #define STR(x) STR_HELPER(x)
namespace namespace // Strings in this namespace should not be localized
{ {
const wchar_t APPLICATION_ID[] = L"PowerToysInstaller"; const wchar_t APPLICATION_ID[] = L"PowerToysInstaller";
const wchar_t INSTALLATION_TOAST_TITLE[] = L"PowerToys Installation";
const wchar_t TOAST_TAG[] = L"PowerToysInstallerProgress"; const wchar_t TOAST_TAG[] = L"PowerToysInstallerProgress";
const char LOG_FILENAME[] = "powertoys-bootstrapper-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; const char LOG_FILENAME[] = "powertoys-bootstrapper-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log";
const char MSI_LOG_FILENAME[] = "powertoys-bootstrapper-msi-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; const char MSI_LOG_FILENAME[] = "powertoys-bootstrapper-msi-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log";
@@ -27,20 +30,6 @@ namespace
#undef STR #undef STR
#undef STR_HELPER #undef STR_HELPER
namespace localized_strings
{
const wchar_t INSTALLER_EXTRACT_ERROR[] = L"Couldn't extract MSI installer!";
const wchar_t TOAST_TITLE[] = L"PowerToys Installation";
const wchar_t EXTRACTING_INSTALLER[] = L"Extracting PowerToys MSI...";
const wchar_t UNINSTALLING_PREVIOUS_VERSION[] = L"Uninstalling previous PowerToys version...";
const wchar_t UNINSTALL_PREVIOUS_VERSION_ERROR[] = L"Couldn't uninstall previous PowerToys version!";
const wchar_t INSTALLING_DOTNET[] = L"Installing dotnet...";
const wchar_t DOTNET_INSTALL_ERROR[] = L"Couldn't install dotnet!";
const wchar_t INSTALLING_NEW_VERSION[] = L"Installing new PowerToys version...";
const wchar_t NEW_VERSION_INSTALLATION_DONE[] = L"PowerToys installation complete!";
const wchar_t NEW_VERSION_INSTALLATION_ERROR[] = L"Couldn't install new PowerToys version.";
}
namespace fs = std::filesystem; namespace fs = std::filesystem;
std::optional<fs::path> extractEmbeddedInstaller() std::optional<fs::path> extractEmbeddedInstaller()
@@ -96,7 +85,6 @@ void setup_log(fs::path directory, const spdlog::level::level_enum severity)
int bootstrapper() int bootstrapper()
{ {
using namespace localized_strings;
winrt::init_apartment(); winrt::init_apartment();
cxxopts::Options options{ "PowerToysBootstrapper" }; cxxopts::Options options{ "PowerToysBootstrapper" };
// clang-format off // clang-format off
@@ -252,7 +240,7 @@ int bootstrapper()
iconPath = std::move(*extractedIcon); iconPath = std::move(*extractedIcon);
} }
spdlog::debug("Registering app id for toast notifications"); spdlog::debug("Registering app id for toast notifications");
notifications::register_application_id(TOAST_TITLE, iconPath.c_str()); notifications::register_application_id(INSTALLATION_TOAST_TITLE, iconPath.c_str());
auto removeShortcut = wil::scope_exit([&] { auto removeShortcut = wil::scope_exit([&] {
notifications::unregister_application_id(); notifications::unregister_application_id();
@@ -274,12 +262,12 @@ int bootstrapper()
std::mutex progressLock; std::mutex progressLock;
notifications::progress_bar_params progressParams; notifications::progress_bar_params progressParams;
progressParams.progress = 0.0f; progressParams.progress = 0.0f;
progressParams.progress_title = EXTRACTING_INSTALLER; progressParams.progress_title = GET_RESOURCE_STRING(IDS_EXTRACTING_INSTALLER);
notifications::toast_params params{ TOAST_TAG, false, std::move(progressParams) }; notifications::toast_params params{ TOAST_TAG, false, std::move(progressParams) };
if (!silent) if (!silent)
{ {
spdlog::debug("Launching progress toast notification"); spdlog::debug("Launching progress toast notification");
notifications::show_toast_with_activations({}, TOAST_TITLE, {}, {}, std::move(params)); notifications::show_toast_with_activations({}, INSTALLATION_TOAST_TITLE, {}, {}, std::move(params));
} }
auto processToasts = wil::scope_exit([&] { auto processToasts = wil::scope_exit([&] {
@@ -322,7 +310,7 @@ int bootstrapper()
{ {
if (!silent) if (!silent)
{ {
notifications::show_toast(INSTALLER_EXTRACT_ERROR, TOAST_TITLE); notifications::show_toast(GET_RESOURCE_STRING(IDS_INSTALLER_EXTRACT_ERROR), INSTALLATION_TOAST_TITLE);
} }
spdlog::error("Couldn't install the MSI installer ({})", GetLastError()); spdlog::error("Couldn't install the MSI installer ({})", GetLastError());
return 1; return 1;
@@ -332,7 +320,7 @@ int bootstrapper()
fs::remove(*installerPath, _); fs::remove(*installerPath, _);
}); });
updateProgressBar(.25f, UNINSTALLING_PREVIOUS_VERSION); updateProgressBar(.25f, GET_RESOURCE_STRING(IDS_UNINSTALLING_PREVIOUS_VERSION).c_str());
spdlog::debug("Acquiring existing MSI package path"); spdlog::debug("Acquiring existing MSI package path");
const auto package_path = updating::get_msi_package_path(); const auto package_path = updating::get_msi_package_path();
if (!package_path.empty()) if (!package_path.empty())
@@ -343,15 +331,15 @@ int bootstrapper()
{ {
spdlog::debug("Existing MSI package path not found"); spdlog::debug("Existing MSI package path not found");
} }
if (!package_path.empty() && !updating::uninstall_msi_version(package_path) && !silent) if (!package_path.empty() && !updating::uninstall_msi_version(package_path, Strings) && !silent)
{ {
spdlog::error("Couldn't install the existing MSI package ({})", GetLastError()); spdlog::error("Couldn't install the existing MSI package ({})", GetLastError());
notifications::show_toast(UNINSTALL_PREVIOUS_VERSION_ERROR, TOAST_TITLE); notifications::show_toast(GET_RESOURCE_STRING(IDS_UNINSTALL_PREVIOUS_VERSION_ERROR), INSTALLATION_TOAST_TITLE);
} }
const bool installDotnet = !skipDotnetInstall; const bool installDotnet = !skipDotnetInstall;
if (installDotnet) if (installDotnet)
{ {
updateProgressBar(.5f, INSTALLING_DOTNET); updateProgressBar(.5f, GET_RESOURCE_STRING(IDS_INSTALLING_DOTNET).c_str());
} }
try try
@@ -365,7 +353,7 @@ int bootstrapper()
!updating::install_dotnet(silent) && !updating::install_dotnet(silent) &&
!silent) !silent)
{ {
notifications::show_toast(DOTNET_INSTALL_ERROR, TOAST_TITLE); notifications::show_toast(GET_RESOURCE_STRING(IDS_DOTNET_INSTALL_ERROR), INSTALLATION_TOAST_TITLE);
} }
} }
} }
@@ -375,13 +363,14 @@ int bootstrapper()
MessageBoxW(nullptr, L".NET Core installation", L"Unknown exception encountered!", MB_OK | MB_ICONERROR); MessageBoxW(nullptr, L".NET Core installation", L"Unknown exception encountered!", MB_OK | MB_ICONERROR);
} }
updateProgressBar(.75f, INSTALLING_NEW_VERSION); updateProgressBar(.75f, GET_RESOURCE_STRING(IDS_INSTALLING_NEW_VERSION).c_str());
// Always skip dotnet install, because we should've installed it from here earlier // Always skip dotnet install, because we should've installed it from here earlier
std::wstring msiProps = L"SKIPDOTNETINSTALL=1 "; std::wstring msiProps = L"SKIPDOTNETINSTALL=1 ";
spdlog::debug("Launching MSI installation for new package {}", installerPath->string()); spdlog::debug("Launching MSI installation for new package {}", installerPath->string());
const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS; const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS;
updateProgressBar(1.f, installationDone ? NEW_VERSION_INSTALLATION_DONE : NEW_VERSION_INSTALLATION_ERROR); updateProgressBar(1.f,
installationDone ? GET_RESOURCE_STRING(IDS_NEW_VERSION_INSTALLATION_DONE).c_str() : GET_RESOURCE_STRING(IDS_NEW_VERSION_INSTALLATION_ERROR).c_str());
if (!installationDone) if (!installationDone)
{ {
spdlog::error("Couldn't install new MSI package ({})", GetLastError()); spdlog::error("Couldn't install new MSI package ({})", GetLastError());

View File

@@ -64,4 +64,67 @@
<data name="DOTNET_CORE_DOWNLOAD_FAILURE_TITLE" xml:space="preserve"> <data name="DOTNET_CORE_DOWNLOAD_FAILURE_TITLE" xml:space="preserve">
<value>PowerToys installation error</value> <value>PowerToys installation error</value>
</data> </data>
<data name="GITHUB_NEW_VERSION_AVAILABLE" xml:space="preserve">
<value>An update to PowerToys is available.</value>
</data>
<data name="GITHUB_NEW_VERSION_DOWNLOAD_STARTED" xml:space="preserve">
<value>PowerToys download started.</value>
</data>
<data name="GITHUB_NEW_VERSION_READY_TO_INSTALL" xml:space="preserve">
<value>An update to PowerToys is ready to install.</value>
</data>
<data name="GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR" xml:space="preserve">
<value>Error: couldn't download PowerToys installer. Visit our GitHub page to update.</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_NOW" xml:space="preserve">
<value>Update now</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART" xml:space="preserve">
<value>At next launch</value>
</data>
<data name="UNINSTALLATION_UNKNOWN_ERROR" xml:space="preserve">
<value>Error: please uninstall the previous version of PowerToys manually.</value>
</data>
<data name="GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT" xml:space="preserve">
<value>An update to PowerToys is available. Visit our GitHub page to update.</value>
</data>
<data name="GITHUB_NEW_VERSION_UNAVAILABLE" xml:space="preserve">
<value>PowerToys is up to date.</value>
</data>
<data name="GITHUB_NEW_VERSION_VISIT" xml:space="preserve">
<value>Visit</value>
</data>
<data name="GITHUB_NEW_VERSION_MORE_INFO" xml:space="preserve">
<value>More info...</value>
</data>
<data name="GITHUB_NEW_VERSION_ABORT" xml:space="preserve">
<value>Abort</value>
</data>
<data name="GITHUB_NEW_VERSION_SNOOZE_TITLE" xml:space="preserve">
<value>Click Snooze to be reminded in:</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D" xml:space="preserve">
<value>1 day</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D" xml:space="preserve">
<value>5 days</value>
</data>
<data name="DOWNLOAD_IN_PROGRESS" xml:space="preserve">
<value>Downloading...</value>
</data>
<data name="DOWNLOAD_COMPLETE" xml:space="preserve">
<value>Download complete</value>
</data>
<data name="TOAST_TITLE" xml:space="preserve">
<value>PowerToys Update</value>
</data>
<data name="OFFER_UNINSTALL_MSI" xml:space="preserve">
<value>We've detected a previous installation of PowerToys. Would you like to remove it?</value>
</data>
<data name="OFFER_UNINSTALL_MSI_TITLE" xml:space="preserve">
<value>PowerToys: uninstall previous version?</value>
</data>
<data name="SNOOZE_BUTTON" xml:space="preserve">
<value>Snooze</value>
</data>
</root> </root>

View File

@@ -1,4 +1,6 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include "Generated Files/resource.h"
#include <Windows.h> #include <Windows.h>
#include <shellapi.h> #include <shellapi.h>
@@ -16,10 +18,10 @@
#include "../runner/tray_icon.h" #include "../runner/tray_icon.h"
#include "../runner/action_runner_utils.h" #include "../runner/action_runner_utils.h"
#include "Generated Files/resource.h"
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
auto Strings = updating::notifications::strings::create();
int uninstall_msi_action() int uninstall_msi_action()
{ {
const auto package_path = updating::get_msi_package_path(); const auto package_path = updating::get_msi_package_path();
@@ -27,7 +29,7 @@ int uninstall_msi_action()
{ {
return 0; return 0;
} }
if (!updating::uninstall_msi_version(package_path)) if (!updating::uninstall_msi_version(package_path, Strings))
{ {
return -1; return -1;
} }

View File

@@ -85,22 +85,22 @@ std::optional<std::wstring> get_last_error_message(const DWORD dw)
return message; return message;
} }
void show_last_error_message(LPCWSTR lpszFunction, DWORD dw, LPCWSTR errorTitle) void show_last_error_message(LPCWSTR functionName, DWORD dw, LPCWSTR errorTitle)
{ {
const auto system_message = get_last_error_message(dw); const auto system_message = get_last_error_message(dw);
if (!system_message.has_value()) if (!system_message.has_value())
{ {
return; return;
} }
LPWSTR lpDisplayBuf = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(lpszFunction) + 40) * sizeof(WCHAR)); LPWSTR lpDisplayBuf = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(functionName) + 40) * sizeof(WCHAR));
if (lpDisplayBuf != NULL) if (lpDisplayBuf != NULL)
{ {
StringCchPrintfW(lpDisplayBuf, StringCchPrintfW(lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(WCHAR), LocalSize(lpDisplayBuf) / sizeof(WCHAR),
localized_strings::LAST_ERROR_FORMAT_STRING, L"%s: %s (%d)",
lpszFunction, functionName,
dw, system_message->c_str(),
system_message->c_str()); dw);
MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, errorTitle, MB_OK | MB_ICONERROR); MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, errorTitle, MB_OK | MB_ICONERROR);
LocalFree(lpDisplayBuf); LocalFree(lpDisplayBuf);
} }

View File

@@ -7,12 +7,6 @@
#include <vector> #include <vector>
namespace localized_strings
{
const wchar_t LAST_ERROR_FORMAT_STRING[] = L"%s failed with error %d: %s";
const wchar_t LAST_ERROR_TITLE_STRING[] = L"Error";
}
// Gets position of given window. // Gets position of given window.
std::optional<RECT> get_window_pos(HWND hwnd); std::optional<RECT> get_window_pos(HWND hwnd);
@@ -23,7 +17,7 @@ bool is_system_window(HWND hwnd, const char* class_name);
int run_message_loop(const bool until_idle = false, const std::optional<uint32_t> timeout_seconds = {}); int run_message_loop(const bool until_idle = false, const std::optional<uint32_t> timeout_seconds = {});
std::optional<std::wstring> get_last_error_message(const DWORD dw); std::optional<std::wstring> get_last_error_message(const DWORD dw);
void show_last_error_message(LPCWSTR lpszFunction, DWORD dw, LPCWSTR errorTitle = localized_strings::LAST_ERROR_TITLE_STRING); void show_last_error_message(LPCWSTR lpszFunction, DWORD dw, LPCWSTR errorTitle);
enum WindowState enum WindowState
{ {

View File

@@ -33,8 +33,7 @@ using winrt::Windows::UI::Notifications::ToastNotificationManager;
namespace fs = std::filesystem; namespace fs = std::filesystem;
// This namespace contains strings that SHOULD NOT be localized namespace // Strings in this namespace should not be localized
namespace
{ {
constexpr std::wstring_view TASK_NAME = L"PowerToysBackgroundNotificationsHandler"; constexpr std::wstring_view TASK_NAME = L"PowerToysBackgroundNotificationsHandler";
constexpr std::wstring_view TASK_ENTRYPOINT = L"PowerToysNotifications.BackgroundHandler"; constexpr std::wstring_view TASK_ENTRYPOINT = L"PowerToysNotifications.BackgroundHandler";
@@ -45,11 +44,6 @@ namespace
constexpr std::wstring_view DEFAULT_TOAST_GROUP = L"PowerToysToastTag"; constexpr std::wstring_view DEFAULT_TOAST_GROUP = L"PowerToysToastTag";
} }
namespace localized_strings
{
constexpr std::wstring_view SNOOZE_BUTTON = L"Snooze";
}
static DWORD loop_thread_id() static DWORD loop_thread_id()
{ {
static const DWORD thread_id = GetCurrentThreadId(); static const DWORD thread_id = GetCurrentThreadId();
@@ -365,7 +359,7 @@ void notifications::show_toast_with_activations(std::wstring message,
toast_xml += '"'; toast_xml += '"';
} }
toast_xml += LR"( content=")"; toast_xml += LR"( content=")";
toast_xml += localized_strings::SNOOZE_BUTTON; toast_xml += b.snooze_button_title;
toast_xml += LR"(" />)"; toast_xml += LR"(" />)";
} }, } },
actions[i]); actions[i]);

View File

@@ -28,6 +28,7 @@ namespace notifications
{ {
std::wstring snooze_title; std::wstring snooze_title;
std::vector<snooze_duration> durations; std::vector<snooze_duration> durations;
std::wstring snooze_button_title;
}; };
struct link_button struct link_button
@@ -45,7 +46,7 @@ namespace notifications
struct progress_bar_params struct progress_bar_params
{ {
std::wstring_view progress_title; std::wstring progress_title;
float progress = 0.f; float progress = 0.f;
}; };

View File

@@ -9,39 +9,10 @@
#include "VersionHelper.h" #include "VersionHelper.h"
#include "version.h" #include "version.h"
namespace
{
const wchar_t TOAST_TITLE[] = L"PowerToys Update";
}
namespace localized_strings
{
const wchar_t GITHUB_NEW_VERSION_AVAILABLE[] = L"An update to PowerToys is available.\n";
const wchar_t GITHUB_NEW_VERSION_DOWNLOAD_STARTED[] = L"PowerToys download started.\n";
const wchar_t GITHUB_NEW_VERSION_READY_TO_INSTALL[] = L"An update to PowerToys is ready to install.\n";
const wchar_t GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR[] = L"Error: couldn't download PowerToys installer. Visit our GitHub page to update.\n";
const wchar_t GITHUB_NEW_VERSION_UPDATE_NOW[] = L"Update now";
const wchar_t GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART[] = L"At next launch";
const wchar_t UNINSTALLATION_UNKNOWN_ERROR[] = L"Error: please uninstall the previous version of PowerToys manually.";
const wchar_t GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT[] = L"An update to PowerToys is available. Visit our GitHub page to update.\n";
const wchar_t GITHUB_NEW_VERSION_UNAVAILABLE[] = L"PowerToys is up to date.\n";
const wchar_t GITHUB_NEW_VERSION_VISIT[] = L"Visit";
const wchar_t GITHUB_NEW_VERSION_MORE_INFO[] = L"More info...";
const wchar_t GITHUB_NEW_VERSION_ABORT[] = L"Abort";
const wchar_t GITHUB_NEW_VERSION_SNOOZE_TITLE[] = L"Click Snooze to be reminded in:";
const wchar_t GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D[] = L"1 day";
const wchar_t GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D[] = L"5 days";
const wchar_t DOWNLOAD_IN_PROGRESS[] = L"Downloading...";
const wchar_t DOWNLOAD_COMPLETE[] = L"Download complete";
}
namespace updating namespace updating
{ {
namespace notifications namespace notifications
{ {
using namespace localized_strings;
using namespace ::notifications; using namespace ::notifications;
std::wstring current_version_to_next_version(const updating::new_version_download_info& info) std::wstring current_version_to_next_version(const updating::new_version_download_info& info)
{ {
@@ -51,108 +22,123 @@ namespace updating
return current_version_to_next_version; return current_version_to_next_version;
} }
void show_unavailable() void show_unavailable(const notifications::strings& strings)
{ {
remove_toasts(UPDATING_PROCESS_TOAST_TAG); remove_toasts(UPDATING_PROCESS_TOAST_TAG);
toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false };
std::wstring contents = GITHUB_NEW_VERSION_UNAVAILABLE; std::wstring contents = strings.GITHUB_NEW_VERSION_UNAVAILABLE;
show_toast(std::move(contents), TOAST_TITLE, std::move(toast_params)); show_toast(std::move(contents), strings.TOAST_TITLE, std::move(toast_params));
} }
void show_available(const updating::new_version_download_info& info) void show_available(const updating::new_version_download_info& info, const notifications::strings& strings)
{ {
remove_toasts(UPDATING_PROCESS_TOAST_TAG); remove_toasts(UPDATING_PROCESS_TOAST_TAG);
toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false };
std::wstring contents = GITHUB_NEW_VERSION_AVAILABLE; std::wstring contents = strings.GITHUB_NEW_VERSION_AVAILABLE;
contents += L'\n';
contents += current_version_to_next_version(info); contents += current_version_to_next_version(info);
show_toast_with_activations(std::move(contents), show_toast_with_activations(std::move(contents),
TOAST_TITLE, strings.TOAST_TITLE,
{}, {},
{ link_button{ GITHUB_NEW_VERSION_UPDATE_NOW, L"powertoys://download_and_install_update/" }, link_button{ GITHUB_NEW_VERSION_MORE_INFO, info.release_page_uri.ToString().c_str() } }, { link_button{ strings.GITHUB_NEW_VERSION_UPDATE_NOW,
L"powertoys://download_and_install_update/" },
link_button{ strings.GITHUB_NEW_VERSION_MORE_INFO,
info.release_page_uri.ToString().c_str() } },
std::move(toast_params)); std::move(toast_params));
} }
void show_download_start(const updating::new_version_download_info& info) void show_download_start(const updating::new_version_download_info& info, const notifications::strings& strings)
{ {
remove_toasts(UPDATING_PROCESS_TOAST_TAG); remove_toasts(UPDATING_PROCESS_TOAST_TAG);
progress_bar_params progress_bar_params; progress_bar_params progress_bar_params;
std::wstring progress_title{ info.version_string }; std::wstring progress_title{ info.version_string };
progress_title += L' '; progress_title += L' ';
progress_title += localized_strings::DOWNLOAD_IN_PROGRESS; progress_title += strings.DOWNLOAD_IN_PROGRESS;
progress_bar_params.progress_title = progress_title; progress_bar_params.progress_title = progress_title;
progress_bar_params.progress = .0f; progress_bar_params.progress = .0f;
toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false, std::move(progress_bar_params) }; toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false, std::move(progress_bar_params) };
show_toast_with_activations(localized_strings::GITHUB_NEW_VERSION_DOWNLOAD_STARTED, show_toast_with_activations(strings.GITHUB_NEW_VERSION_DOWNLOAD_STARTED,
TOAST_TITLE, strings.TOAST_TITLE,
{}, {},
{}, {},
std::move(toast_params)); std::move(toast_params));
} }
void show_visit_github(const updating::new_version_download_info& info) void show_visit_github(const updating::new_version_download_info& info, const notifications::strings& strings)
{ {
remove_toasts(UPDATING_PROCESS_TOAST_TAG); remove_toasts(UPDATING_PROCESS_TOAST_TAG);
toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false };
std::wstring contents = GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT; std::wstring contents = strings.GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT;
contents += L'\n';
contents += current_version_to_next_version(info); contents += current_version_to_next_version(info);
show_toast_with_activations(std::move(contents), show_toast_with_activations(std::move(contents),
TOAST_TITLE, strings.TOAST_TITLE,
{}, {},
{ link_button{ GITHUB_NEW_VERSION_VISIT, info.release_page_uri.ToString().c_str() } }, { link_button{ strings.GITHUB_NEW_VERSION_VISIT,
info.release_page_uri.ToString().c_str() } },
std::move(toast_params)); std::move(toast_params));
} }
void show_install_error(const updating::new_version_download_info& info) void show_install_error(const updating::new_version_download_info& info, const notifications::strings& strings)
{ {
remove_toasts(UPDATING_PROCESS_TOAST_TAG); remove_toasts(UPDATING_PROCESS_TOAST_TAG);
toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false };
std::wstring contents = GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR; std::wstring contents = strings.GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR;
contents += L'\n';
contents += current_version_to_next_version(info); contents += current_version_to_next_version(info);
show_toast_with_activations(std::move(contents), show_toast_with_activations(std::move(contents),
TOAST_TITLE, strings.TOAST_TITLE,
{}, {},
{ link_button{ GITHUB_NEW_VERSION_VISIT, info.release_page_uri.ToString().c_str() } }, { link_button{ strings.GITHUB_NEW_VERSION_VISIT, info.release_page_uri.ToString().c_str() } },
std::move(toast_params)); std::move(toast_params));
} }
void show_version_ready(const updating::new_version_download_info& info) void show_version_ready(const updating::new_version_download_info& info, const notifications::strings& strings)
{ {
remove_toasts(UPDATING_PROCESS_TOAST_TAG); remove_toasts(UPDATING_PROCESS_TOAST_TAG);
toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false };
std::wstring new_version_ready{ GITHUB_NEW_VERSION_READY_TO_INSTALL }; std::wstring new_version_ready{ strings.GITHUB_NEW_VERSION_READY_TO_INSTALL };
new_version_ready += L'\n';
new_version_ready += current_version_to_next_version(info); new_version_ready += current_version_to_next_version(info);
show_toast_with_activations(std::move(new_version_ready), show_toast_with_activations(std::move(new_version_ready),
TOAST_TITLE, strings.TOAST_TITLE,
{}, {},
{ link_button{ GITHUB_NEW_VERSION_UPDATE_NOW, L"powertoys://update_now/" + info.installer_filename }, { link_button{ strings.GITHUB_NEW_VERSION_UPDATE_NOW,
link_button{ GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART, L"powertoys://schedule_update/" + info.installer_filename }, L"powertoys://update_now/" + info.installer_filename },
snooze_button{ GITHUB_NEW_VERSION_SNOOZE_TITLE, { { GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D, 24 * 60 }, { GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D, 120 * 60 } } } }, link_button{ strings.GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART,
L"powertoys://schedule_update/" + info.installer_filename },
snooze_button{
strings.GITHUB_NEW_VERSION_SNOOZE_TITLE,
{ { strings.GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D, 24 * 60 },
{ strings.GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D, 120 * 60 } },
strings.SNOOZE_BUTTON
} },
std::move(toast_params)); std::move(toast_params));
} }
void show_uninstallation_error() void show_uninstallation_error(const notifications::strings& strings)
{ {
remove_toasts(UPDATING_PROCESS_TOAST_TAG); remove_toasts(UPDATING_PROCESS_TOAST_TAG);
show_toast(localized_strings::UNINSTALLATION_UNKNOWN_ERROR, TOAST_TITLE); show_toast(strings.UNINSTALLATION_UNKNOWN_ERROR, strings.TOAST_TITLE);
} }
void update_download_progress(const updating::new_version_download_info& info, float progress) void update_download_progress(const updating::new_version_download_info& info, float progress, const notifications::strings& strings)
{ {
progress_bar_params progress_bar_params; progress_bar_params progress_bar_params;
std::wstring progress_title{ info.version_string }; std::wstring progress_title{ info.version_string };
progress_title += L' '; progress_title += L' ';
progress_title += progress < 1 ? localized_strings::DOWNLOAD_IN_PROGRESS : localized_strings::DOWNLOAD_COMPLETE; progress_title += progress < 1 ? strings.DOWNLOAD_IN_PROGRESS : strings.DOWNLOAD_COMPLETE;
progress_bar_params.progress_title = progress_title; progress_bar_params.progress_title = progress_title;
progress_bar_params.progress = progress; progress_bar_params.progress = progress;
update_toast_progress_bar(UPDATING_PROCESS_TOAST_TAG, progress_bar_params); update_toast_progress_bar(UPDATING_PROCESS_TOAST_TAG, progress_bar_params);

View File

@@ -6,14 +6,66 @@ namespace updating
namespace notifications namespace notifications
{ {
void show_unavailable(); struct strings
void show_available(const updating::new_version_download_info& info); {
void show_download_start(const updating::new_version_download_info& info); std::wstring GITHUB_NEW_VERSION_AVAILABLE;
void show_visit_github(const updating::new_version_download_info& info); std::wstring GITHUB_NEW_VERSION_DOWNLOAD_STARTED;
void show_install_error(const updating::new_version_download_info& info); std::wstring GITHUB_NEW_VERSION_READY_TO_INSTALL;
void show_version_ready(const updating::new_version_download_info& info); std::wstring GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR;
void show_uninstallation_error(); std::wstring GITHUB_NEW_VERSION_UPDATE_NOW;
std::wstring GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART;
std::wstring UNINSTALLATION_UNKNOWN_ERROR;
std::wstring GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT;
std::wstring GITHUB_NEW_VERSION_UNAVAILABLE;
std::wstring GITHUB_NEW_VERSION_VISIT;
std::wstring GITHUB_NEW_VERSION_MORE_INFO;
std::wstring GITHUB_NEW_VERSION_ABORT;
std::wstring GITHUB_NEW_VERSION_SNOOZE_TITLE;
std::wstring SNOOZE_BUTTON;
std::wstring GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D;
std::wstring GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D;
std::wstring DOWNLOAD_IN_PROGRESS;
std::wstring DOWNLOAD_COMPLETE;
std::wstring TOAST_TITLE;
std::wstring OFFER_UNINSTALL_MSI;
std::wstring OFFER_UNINSTALL_MSI_TITLE;
template<typename = void>
static strings create()
{
return strings{
.GITHUB_NEW_VERSION_AVAILABLE = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_AVAILABLE),
.GITHUB_NEW_VERSION_DOWNLOAD_STARTED = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_DOWNLOAD_STARTED),
.GITHUB_NEW_VERSION_READY_TO_INSTALL = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_READY_TO_INSTALL),
.GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR),
.GITHUB_NEW_VERSION_UPDATE_NOW = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_UPDATE_NOW),
.GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART),
.UNINSTALLATION_UNKNOWN_ERROR = GET_RESOURCE_STRING(IDS_UNINSTALLATION_UNKNOWN_ERROR),
.GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT),
.GITHUB_NEW_VERSION_UNAVAILABLE = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_UNAVAILABLE),
.GITHUB_NEW_VERSION_VISIT = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_VISIT),
.GITHUB_NEW_VERSION_MORE_INFO = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_MORE_INFO),
.GITHUB_NEW_VERSION_ABORT = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_ABORT),
.GITHUB_NEW_VERSION_SNOOZE_TITLE = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_SNOOZE_TITLE),
.SNOOZE_BUTTON = GET_RESOURCE_STRING(IDS_SNOOZE_BUTTON),
.GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D),
.GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D),
.DOWNLOAD_IN_PROGRESS = GET_RESOURCE_STRING(IDS_DOWNLOAD_IN_PROGRESS),
.DOWNLOAD_COMPLETE = GET_RESOURCE_STRING(IDS_DOWNLOAD_COMPLETE),
.TOAST_TITLE = GET_RESOURCE_STRING(IDS_TOAST_TITLE),
.OFFER_UNINSTALL_MSI = GET_RESOURCE_STRING(IDS_OFFER_UNINSTALL_MSI),
.OFFER_UNINSTALL_MSI_TITLE = GET_RESOURCE_STRING(IDS_OFFER_UNINSTALL_MSI_TITLE)
};
}
};
void update_download_progress(const updating::new_version_download_info& info, float progress); void show_unavailable(const notifications::strings& strings);
void show_available(const updating::new_version_download_info& info, const strings&);
void show_download_start(const updating::new_version_download_info& info, const strings&);
void show_visit_github(const updating::new_version_download_info& info, const strings&);
void show_install_error(const updating::new_version_download_info& info, const strings&);
void show_version_ready(const updating::new_version_download_info& info, const strings&);
void show_uninstallation_error(const notifications::strings& strings);
void update_download_progress(const updating::new_version_download_info& info, float progress, const notifications::strings& strings);
} }
} }

View File

@@ -19,7 +19,7 @@
#include "VersionHelper.h" #include "VersionHelper.h"
#include <PathCch.h> #include <PathCch.h>
namespace namespace // Strings in this namespace should not be localized
{ {
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 POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}"; const wchar_t POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
@@ -32,12 +32,6 @@ namespace
const wchar_t TOAST_TITLE[] = L"PowerToys"; const wchar_t TOAST_TITLE[] = L"PowerToys";
} }
namespace localized_strings
{
const wchar_t OFFER_UNINSTALL_MSI[] = L"We've detected a previous installation of PowerToys. Would you like to remove it?";
const wchar_t OFFER_UNINSTALL_MSI_TITLE[] = L"PowerToys: uninstall previous version?";
}
namespace updating namespace updating
{ {
std::wstring get_msi_package_path() std::wstring get_msi_package_path()
@@ -73,13 +67,18 @@ namespace updating
return package_path; return package_path;
} }
bool offer_msi_uninstallation() bool offer_msi_uninstallation(const notifications::strings& strings)
{ {
const auto selection = SHMessageBoxCheckW(nullptr, localized_strings::OFFER_UNINSTALL_MSI, localized_strings::OFFER_UNINSTALL_MSI_TITLE, MB_ICONQUESTION | MB_YESNO, IDNO, DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH); const auto selection = SHMessageBoxCheckW(nullptr,
strings.OFFER_UNINSTALL_MSI.c_str(),
strings.OFFER_UNINSTALL_MSI_TITLE.c_str(),
MB_ICONQUESTION | MB_YESNO,
IDNO,
DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH);
return selection == IDYES; return selection == IDYES;
} }
bool uninstall_msi_version(const std::wstring& package_path) bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings& strings)
{ {
const auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL"); const auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL");
if (ERROR_SUCCESS == uninstall_result) if (ERROR_SUCCESS == uninstall_result)
@@ -94,7 +93,7 @@ namespace updating
} }
catch (...) catch (...)
{ {
updating::notifications::show_uninstallation_error(); updating::notifications::show_uninstallation_error(strings);
} }
} }
return false; return false;
@@ -202,7 +201,7 @@ namespace updating
return installer_download_dst; return installer_download_dst;
} }
std::future<void> try_autoupdate(const bool download_updates_automatically) std::future<void> try_autoupdate(const bool download_updates_automatically, const notifications::strings& strings)
{ {
const auto new_version = co_await get_new_github_version_info_async(); const auto new_version = co_await get_new_github_version_info_async();
if (!new_version) if (!new_version)
@@ -230,32 +229,32 @@ namespace updating
} }
if (!download_success) if (!download_success)
{ {
updating::notifications::show_install_error(new_version.value()); updating::notifications::show_install_error(new_version.value(), strings);
co_return; co_return;
} }
updating::notifications::show_version_ready(new_version.value()); updating::notifications::show_version_ready(new_version.value(), strings);
} }
else else
{ {
updating::notifications::show_visit_github(new_version.value()); updating::notifications::show_visit_github(new_version.value(), strings);
} }
} }
std::future<std::wstring> check_new_version_available() std::future<std::wstring> check_new_version_available(const notifications::strings& strings)
{ {
const auto new_version = co_await get_new_github_version_info_async(); const auto new_version = co_await get_new_github_version_info_async();
if (!new_version) if (!new_version)
{ {
updating::notifications::show_unavailable(); updating::notifications::show_unavailable(strings);
co_return VersionHelper{ VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION }.toWstring(); co_return VersionHelper{ VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION }.toWstring();
} }
updating::notifications::show_available(new_version.value()); updating::notifications::show_available(new_version.value(), strings);
co_return new_version->version_string; co_return new_version->version_string;
} }
std::future<std::wstring> download_update() std::future<std::wstring> download_update(const notifications::strings& strings)
{ {
const auto new_version = co_await get_new_github_version_info_async(); const auto new_version = co_await get_new_github_version_info_async();
if (!new_version) if (!new_version)
@@ -264,12 +263,12 @@ namespace updating
} }
auto installer_download_dst = create_download_path() / new_version->installer_filename; auto installer_download_dst = create_download_path() / new_version->installer_filename;
updating::notifications::show_download_start(new_version.value()); updating::notifications::show_download_start(new_version.value(), strings);
try try
{ {
auto progressUpdateHandle = [&](float progress) { auto progressUpdateHandle = [&](float progress) {
updating::notifications::update_download_progress(new_version.value(), progress); updating::notifications::update_download_progress(new_version.value(), progress, strings);
}; };
http::HttpClient client; http::HttpClient client;
@@ -277,7 +276,7 @@ namespace updating
} }
catch (...) catch (...)
{ {
updating::notifications::show_install_error(new_version.value()); updating::notifications::show_install_error(new_version.value(), strings);
co_return L""; co_return L"";
} }

View File

@@ -6,13 +6,14 @@
#include <filesystem> #include <filesystem>
#include <winrt/Windows.Foundation.h> #include <winrt/Windows.Foundation.h>
#include "notifications.h"
#include "../VersionHelper.h" #include "../VersionHelper.h"
namespace updating namespace updating
{ {
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, const notifications::strings&);
bool offer_msi_uninstallation(); bool offer_msi_uninstallation(const notifications::strings&);
std::optional<std::wstring> get_msi_package_installed_path(); std::optional<std::wstring> get_msi_package_installed_path();
std::optional<VersionHelper> get_installed_powertoys_version(); std::optional<VersionHelper> get_installed_powertoys_version();
@@ -27,11 +28,11 @@ namespace updating
}; };
std::future<std::optional<new_version_download_info>> get_new_github_version_info_async(); std::future<std::optional<new_version_download_info>> get_new_github_version_info_async();
std::future<void> try_autoupdate(const bool download_updates_automatically); std::future<void> try_autoupdate(const bool download_updates_automatically, const notifications::strings&);
std::filesystem::path get_pending_updates_path(); std::filesystem::path get_pending_updates_path();
std::future<std::wstring> check_new_version_available(); std::future<std::wstring> check_new_version_available(const notifications::strings&);
std::future<std::wstring> download_update(); std::future<std::wstring> download_update(const notifications::strings&);
// non-localized // non-localized
constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN = L"powertoyssetup"; constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN = L"powertoyssetup";

View File

@@ -4,9 +4,9 @@
"LanguageSet": "Azure_Languages", "LanguageSet": "Azure_Languages",
"LocItems": [ "LocItems": [
{ {
"SourceFile": "src\\action_runner\\Resources.resx", "SourceFile": "src\\runner\\Resources.resx",
"CopyOption": "LangIDOnName", "CopyOption": "LangIDOnName",
"OutputPath": "src\\action_runner" "OutputPath": "src\\runner"
} }
] ]
} }

View File

@@ -73,5 +73,85 @@
<data name="AUTOUPDATE_SUCCESS" xml:space="preserve"> <data name="AUTOUPDATE_SUCCESS" xml:space="preserve">
<value>PowerToys was successfully updated!</value> <value>PowerToys was successfully updated!</value>
</data> </data>
<data name="MSI_VERSION_IS_ALREADY_RUNNING" xml:space="preserve">
<value>An older version of PowerToys is already running.</value>
</data>
<data name="DOWNLOAD_UPDATE_ERROR" xml:space="preserve">
<value>Couldn't download PowerToys update! Please report the issue on Github.</value>
</data>
<data name="OLDER_MSIX_UNINSTALLED" xml:space="preserve">
<value>An older MSIX version of PowerToys was uninstalled.</value>
</data>
<data name="PT_UPDATE_MESSAGE_BOX_TEXT" xml:space="preserve">
<value>PowerToys was updated successfully!</value>
</data>
<data name="STARTUP_DISABLED_BY_POLICY" xml:space="preserve">
<value>This setting has been disabled by your administrator.</value>
</data>
<data name="STARTUP_DISABLED_BY_USER" xml:space="preserve">
<value>This setting has been disabled manually via &lt;a href=&quot;https://ms_settings_startupapps&quot; target=&quot;_blank&quot;&gt;Startup Settings&lt;/a&gt;.</value>
</data>
<data name="GITHUB_NEW_VERSION_AVAILABLE" xml:space="preserve">
<value>An update to PowerToys is available.</value>
</data>
<data name="GITHUB_NEW_VERSION_DOWNLOAD_STARTED" xml:space="preserve">
<value>PowerToys download started.</value>
</data>
<data name="GITHUB_NEW_VERSION_READY_TO_INSTALL" xml:space="preserve">
<value>An update to PowerToys is ready to install.</value>
</data>
<data name="GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_ERROR" xml:space="preserve">
<value>Error: couldn't download PowerToys installer. Visit our GitHub page to update.</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_NOW" xml:space="preserve">
<value>Update now</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART" xml:space="preserve">
<value>At next launch</value>
</data>
<data name="UNINSTALLATION_UNKNOWN_ERROR" xml:space="preserve">
<value>Error: please uninstall the previous version of PowerToys manually.</value>
</data>
<data name="GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT" xml:space="preserve">
<value>An update to PowerToys is available. Visit our GitHub page to update.</value>
</data>
<data name="GITHUB_NEW_VERSION_UNAVAILABLE" xml:space="preserve">
<value>PowerToys is up to date.</value>
</data>
<data name="GITHUB_NEW_VERSION_VISIT" xml:space="preserve">
<value>Visit</value>
</data>
<data name="GITHUB_NEW_VERSION_MORE_INFO" xml:space="preserve">
<value>More info...</value>
</data>
<data name="GITHUB_NEW_VERSION_ABORT" xml:space="preserve">
<value>Abort</value>
</data>
<data name="GITHUB_NEW_VERSION_SNOOZE_TITLE" xml:space="preserve">
<value>Click Snooze to be reminded in:</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_SNOOZE_1D" xml:space="preserve">
<value>1 day</value>
</data>
<data name="GITHUB_NEW_VERSION_UPDATE_SNOOZE_5D" xml:space="preserve">
<value>5 days</value>
</data>
<data name="DOWNLOAD_IN_PROGRESS" xml:space="preserve">
<value>Downloading...</value>
</data>
<data name="DOWNLOAD_COMPLETE" xml:space="preserve">
<value>Download complete</value>
</data>
<data name="TOAST_TITLE" xml:space="preserve">
<value>PowerToys Update</value>
</data>
<data name="OFFER_UNINSTALL_MSI" xml:space="preserve">
<value>We've detected a previous installation of PowerToys. Would you like to remove it?</value>
</data>
<data name="OFFER_UNINSTALL_MSI_TITLE" xml:space="preserve">
<value>PowerToys: uninstall previous version?</value>
</data>
<data name="SNOOZE_BUTTON" xml:space="preserve">
<value>Snooze</value>
</data>
</root> </root>

View File

@@ -1,6 +1,7 @@
#include "pch.h" #include "pch.h"
#include "general_settings.h" #include "general_settings.h"
#include "auto_start_helper.h" #include "auto_start_helper.h"
#include "Generated files/resource.h"
#include <common/common.h> #include <common/common.h>
#include <common/settings_helpers.h> #include <common/settings_helpers.h>
@@ -15,12 +16,7 @@ static std::wstring settings_theme = L"system";
static bool run_as_elevated = false; static bool run_as_elevated = false;
static bool download_updates_automatically = true; static bool download_updates_automatically = true;
// TODO: add resource.rc for settings project and localize extern "C" IMAGE_DOS_HEADER __ImageBase;
namespace localized_strings
{
const std::wstring_view STARTUP_DISABLED_BY_POLICY = L"This setting has been disabled by your administrator.";
const std::wstring_view STARTUP_DISABLED_BY_USER = LR"(This setting has been disabled manually via <a href="https://ms_settings_startupapps" target="_blank">Startup Settings</a>.)";
}
json::JsonObject GeneralSettings::to_json() json::JsonObject GeneralSettings::to_json()
{ {
@@ -81,7 +77,6 @@ GeneralSettings get_general_settings()
if (winstore::running_as_packaged()) if (winstore::running_as_packaged())
{ {
using namespace localized_strings;
const auto task_state = winstore::get_startup_task_status_async().get(); const auto task_state = winstore::get_startup_task_status_async().get();
switch (task_state) switch (task_state)
{ {
@@ -92,11 +87,11 @@ GeneralSettings get_general_settings()
settings.isStartupEnabled = true; settings.isStartupEnabled = true;
break; break;
case winstore::StartupTaskState::DisabledByPolicy: case winstore::StartupTaskState::DisabledByPolicy:
settings.startupDisabledReason = STARTUP_DISABLED_BY_POLICY; settings.startupDisabledReason = GET_RESOURCE_STRING(IDS_STARTUP_DISABLED_BY_POLICY);
settings.isStartupEnabled = false; settings.isStartupEnabled = false;
break; break;
case winstore::StartupTaskState::DisabledByUser: case winstore::StartupTaskState::DisabledByUser:
settings.startupDisabledReason = STARTUP_DISABLED_BY_USER; settings.startupDisabledReason = GET_RESOURCE_STRING(IDS_STARTUP_DISABLED_BY_USER);
settings.isStartupEnabled = false; settings.isStartupEnabled = false;
break; break;
} }

View File

@@ -35,20 +35,12 @@
#endif #endif
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
extern updating::notifications::strings Strings;
namespace localized_strings
{
const wchar_t MSI_VERSION_IS_ALREADY_RUNNING[] = L"An older version of PowerToys is already running.";
const wchar_t DOWNLOAD_UPDATE_ERROR[] = L"Couldn't download PowerToys update! Please report the issue on Github.";
const wchar_t OLDER_MSIX_UNINSTALLED[] = L"An older MSIX version of PowerToys was uninstalled.";
const wchar_t PT_UPDATE_MESSAGE_BOX_TEXT[] = L"PowerToys was updated successfully!";
const wchar_t POWER_TOYS[] = L"PowerToys";
const wchar_t POWER_TOYS_MODULE_LOAD_FAIL[] = L"Failed to load "; // Module name will be appended on this message and it is not localized.
}
namespace namespace
{ {
const wchar_t PT_URI_PROTOCOL_SCHEME[] = L"powertoys://"; const wchar_t PT_URI_PROTOCOL_SCHEME[] = L"powertoys://";
const wchar_t POWER_TOYS_MODULE_LOAD_FAIL[] = L"Failed to load "; // Module name will be appended on this message and it is not localized.
} }
void chdir_current_executable() void chdir_current_executable()
@@ -59,7 +51,7 @@ void chdir_current_executable()
PathRemoveFileSpec(executable_path); PathRemoveFileSpec(executable_path);
if (!SetCurrentDirectory(executable_path)) if (!SetCurrentDirectory(executable_path))
{ {
show_last_error_message(L"Change Directory to Executable Path", GetLastError()); show_last_error_message(L"Change Directory to Executable Path", GetLastError(), L"PowerToys - runner");
} }
} }
@@ -110,7 +102,7 @@ int runner(bool isProcessElevated)
std::thread{ [] { std::thread{ [] {
if (updating::uninstall_previous_msix_version_async().get()) if (updating::uninstall_previous_msix_version_async().get())
{ {
notifications::show_toast(localized_strings::OLDER_MSIX_UNINSTALLED, L"PowerToys"); notifications::show_toast(GET_RESOURCE_STRING(IDS_OLDER_MSIX_UNINSTALLED).c_str(), L"PowerToys");
} }
} }.detach(); } }.detach();
} }
@@ -140,11 +132,12 @@ int runner(bool isProcessElevated)
} }
catch (...) catch (...)
{ {
std::wstring errorMessage = std::wstring(localized_strings::POWER_TOYS_MODULE_LOAD_FAIL) + moduleSubdir.data(); std::wstring errorMessage = POWER_TOYS_MODULE_LOAD_FAIL;
MessageBox(NULL, errorMessage += moduleSubdir;
errorMessage.c_str(), MessageBoxW(NULL,
localized_strings::POWER_TOYS, errorMessage.c_str(),
MB_OK | MB_ICONERROR); L"PowerToys",
MB_OK | MB_ICONERROR);
} }
} }
// Start initial powertoys // Start initial powertoys
@@ -243,7 +236,7 @@ toast_notification_handler_result toast_notification_handler(const std::wstring_
{ {
try try
{ {
std::wstring installer_filename = updating::download_update().get(); std::wstring installer_filename = updating::download_update(Strings).get();
std::wstring args{ UPDATE_NOW_LAUNCH_STAGE1_CMDARG }; std::wstring args{ UPDATE_NOW_LAUNCH_STAGE1_CMDARG };
args += L' '; args += L' ';
@@ -255,7 +248,7 @@ toast_notification_handler_result toast_notification_handler(const std::wstring_
catch (...) catch (...)
{ {
MessageBoxW(nullptr, MessageBoxW(nullptr,
localized_strings::DOWNLOAD_UPDATE_ERROR, GET_RESOURCE_STRING(IDS_DOWNLOAD_UPDATE_ERROR).c_str(),
L"PowerToys", L"PowerToys",
MB_ICONWARNING | MB_OK); MB_ICONWARNING | MB_OK);
@@ -314,7 +307,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
case SpecialMode::ReportSuccessfulUpdate: case SpecialMode::ReportSuccessfulUpdate:
{ {
notifications::remove_toasts(notifications::UPDATING_PROCESS_TOAST_TAG); notifications::remove_toasts(notifications::UPDATING_PROCESS_TOAST_TAG);
notifications::show_toast(localized_strings::PT_UPDATE_MESSAGE_BOX_TEXT, notifications::show_toast(GET_RESOURCE_STRING(IDS_PT_UPDATE_MESSAGE_BOX_TEXT),
L"PowerToys", L"PowerToys",
notifications::toast_params{ notifications::UPDATING_PROCESS_TOAST_TAG }); notifications::toast_params{ notifications::UPDATING_PROCESS_TOAST_TAG });
break; break;

View File

@@ -390,7 +390,7 @@ void run_settings_window()
WaitForSingleObject(process_info.hProcess, INFINITE); WaitForSingleObject(process_info.hProcess, INFINITE);
if (WaitForSingleObject(process_info.hProcess, INFINITE) != WAIT_OBJECT_0) if (WaitForSingleObject(process_info.hProcess, INFINITE) != WAIT_OBJECT_0)
{ {
show_last_error_message(L"Couldn't wait on the Settings Window to close.", GetLastError()); show_last_error_message(L"Couldn't wait on the Settings Window to close.", GetLastError(), L"PowerToys - runner");
} }
LExit: LExit:

View File

@@ -1,5 +1,8 @@
#include "pch.h" #include "pch.h"
#include <common/common.h>
#include "Generated Files/resource.h"
#include "action_runner_utils.h" #include "action_runner_utils.h"
#include "update_state.h" #include "update_state.h"
#include "update_utils.h" #include "update_utils.h"
@@ -8,6 +11,10 @@
#include <common/updating/updating.h> #include <common/updating/updating.h>
#include <runner/general_settings.h> #include <runner/general_settings.h>
extern "C" IMAGE_DOS_HEADER __ImageBase;
auto Strings = updating::notifications::strings::create();
bool start_msi_uninstallation_sequence() bool start_msi_uninstallation_sequence()
{ {
const auto package_path = updating::get_msi_package_path(); const auto package_path = updating::get_msi_package_path();
@@ -18,7 +25,7 @@ bool start_msi_uninstallation_sequence()
return true; return true;
} }
if (!updating::offer_msi_uninstallation()) if (!updating::offer_msi_uninstallation(Strings))
{ {
// User declined to uninstall or opted for "Don't show again" // User declined to uninstall or opted for "Don't show again"
return false; return false;
@@ -54,7 +61,7 @@ void github_update_worker()
const bool download_updates_automatically = get_general_settings().downloadUpdatesAutomatically; const bool download_updates_automatically = get_general_settings().downloadUpdatesAutomatically;
try try
{ {
updating::try_autoupdate(download_updates_automatically).get(); updating::try_autoupdate(download_updates_automatically, Strings).get();
} }
catch (...) catch (...)
{ {
@@ -70,7 +77,7 @@ std::wstring check_for_updates()
{ {
try try
{ {
return updating::check_new_version_available().get(); return updating::check_new_version_available(Strings).get();
} }
catch (...) catch (...)
{ {