diff --git a/README.md b/README.md
index 322e5ffc7f..b1eaedead4 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ For a video overview of PowerToys, including install steps and a walkthrough of
### Color Picker
-[
](https://aka.ms/PowerToysOverview_ColorPicker) [ColorPicker](https://aka.ms/PowerToysOverview_ColorPicker) is a simple and quick system-wide color picker with Win+Shift+C. Color Picker allows to pick colors from any currently running application and automatically copies the HEX or RGB values to your clipboard. This code is based on [Martin Chrzan's Color Picker](https://github.com/martinchrzan/ColorPicker).
+[
](https://aka.ms/PowerToysOverview_ColorPicker) [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) is a simple and quick system-wide color picker with Win+Shift+C. Color Picker allows to pick colors from any currently running application and automatically copies the HEX or RGB values to your clipboard. This code is based on [Martin Chrzan's Color Picker](https://github.com/martinchrzan/ColorPicker).
@@ -105,7 +105,7 @@ Download PowerToys from [WinGet](https://github.com/microsoft/winget-cli/release
WinGet install powertoys
```
-### Experiential PowerToys utility with Video conference muting
+### Experimental PowerToys utility with Video conference muting
Install the [pre-release experimental version of PowerToys][github-prerelease-link] to try out this version. It includes all improvements from 0.23 in addition to the Video conference utility. Click on `Assets` to show the files available in the release and then download the .exe installer.
diff --git a/installer/PowerToysBootstrapper/bootstrapper/Resources.resx b/installer/PowerToysBootstrapper/bootstrapper/Resources.resx
index d1ca376f1a..e80ed5a84a 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/Resources.resx
+++ b/installer/PowerToysBootstrapper/bootstrapper/Resources.resx
@@ -64,4 +64,94 @@
PowerToys installation error
+
+ An update to PowerToys is available.
+
+
+ PowerToys download started.
+
+
+ An update to PowerToys is ready to install.
+
+
+ Error: couldn't download PowerToys installer. Visit our GitHub page to update.
+
+
+ Update now
+
+
+ At next launch
+
+
+ Error: please uninstall the previous version of PowerToys manually.
+
+
+ An update to PowerToys is available. Visit our GitHub page to update.
+
+
+ PowerToys is up to date.
+
+
+ Visit
+
+
+ More info...
+
+
+ Abort
+
+
+ Click Snooze to be reminded in:
+
+
+ 1 day
+
+
+ 5 days
+
+
+ Downloading...
+
+
+ Download complete
+
+
+ PowerToys Update
+
+
+ We've detected a previous installation of PowerToys. Would you like to remove it?
+
+
+ PowerToys: uninstall previous version?
+
+
+ Couldn't extract MSI installer!
+
+
+ Extracting PowerToys MSI...
+
+
+ Uninstalling previous PowerToys version...
+
+
+ Couldn't uninstall previous PowerToys version!
+
+
+ Installing dotnet...
+
+
+ Couldn't install dotnet!
+
+
+ Installing new PowerToys version...
+
+
+ PowerToys installation complete!
+
+
+ Couldn't install new PowerToys version.
+
+
+ Snooze
+
\ No newline at end of file
diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp
index 2ab0c29cd5..85774cc741 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp
+++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp
@@ -14,11 +14,14 @@
extern "C" IMAGE_DOS_HEADER __ImageBase;
+auto Strings = updating::notifications::strings::create();
+
#define STR_HELPER(x) #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 INSTALLATION_TOAST_TITLE[] = L"PowerToys Installation";
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 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_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;
std::optional extractEmbeddedInstaller()
@@ -96,7 +85,6 @@ void setup_log(fs::path directory, const spdlog::level::level_enum severity)
int bootstrapper()
{
- using namespace localized_strings;
winrt::init_apartment();
cxxopts::Options options{ "PowerToysBootstrapper" };
// clang-format off
@@ -252,7 +240,7 @@ int bootstrapper()
iconPath = std::move(*extractedIcon);
}
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([&] {
notifications::unregister_application_id();
@@ -274,12 +262,12 @@ int bootstrapper()
std::mutex progressLock;
notifications::progress_bar_params progressParams;
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) };
if (!silent)
{
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([&] {
@@ -322,7 +310,7 @@ int bootstrapper()
{
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());
return 1;
@@ -332,7 +320,7 @@ int bootstrapper()
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");
const auto package_path = updating::get_msi_package_path();
if (!package_path.empty())
@@ -343,15 +331,15 @@ int bootstrapper()
{
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());
- 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;
if (installDotnet)
{
- updateProgressBar(.5f, INSTALLING_DOTNET);
+ updateProgressBar(.5f, GET_RESOURCE_STRING(IDS_INSTALLING_DOTNET).c_str());
}
try
@@ -365,7 +353,7 @@ int bootstrapper()
!updating::install_dotnet(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);
}
- 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
std::wstring msiProps = L"SKIPDOTNETINSTALL=1 ";
spdlog::debug("Launching MSI installation for new package {}", installerPath->string());
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)
{
spdlog::error("Couldn't install new MSI package ({})", GetLastError());
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/cs/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/cs/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index 806af68f3a..6bcc4709de 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/cs/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/cs/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/de/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/de/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index 125d416730..0ceb815e69 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/de/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/de/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/es/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/es/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index 74588a0bf4..5f8875c61d 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/es/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/es/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/fr/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/fr/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index fb70b6e461..68c63c6898 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/fr/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/fr/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/hu/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/hu/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index 47eb8d05a1..170a038827 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/hu/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/hu/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/ja/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/ja/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index e72715f337..0ea663700a 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/ja/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/ja/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/nl/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/nl/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index 5a2c84c762..732cf16cab 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/nl/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/nl/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/pt-BR/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/pt-BR/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index 1ca19d3324..e34f883dce 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/pt-BR/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/pt-BR/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/ru/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/ru/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index 03c917be3f..841505881b 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/ru/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/ru/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/sv/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/sv/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index a66e6cb92e..506e8580a1 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/sv/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/sv/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/tr/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/tr/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index c10bb57c10..c80fbc0db4 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/tr/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/tr/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysBootstrapper/bootstrapper/loc/zh-Hans/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl b/installer/PowerToysBootstrapper/bootstrapper/loc/zh-Hans/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
index ee330663f3..a1d18ae8d6 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/loc/zh-Hans/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
+++ b/installer/PowerToysBootstrapper/bootstrapper/loc/zh-Hans/installer/PowerToysBootstrapper/bootstrapper/Resources.resx.lcl
@@ -13,12 +13,18 @@
-
+
+
+
-
+
+
+
diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs
index fa36e6b81a..74307b7181 100644
--- a/installer/PowerToysSetup/Product.wxs
+++ b/installer/PowerToysSetup/Product.wxs
@@ -883,7 +883,7 @@
-
+
diff --git a/src/action_runner/Resources.resx b/src/action_runner/Resources.resx
index d1ca376f1a..1b90cd3d36 100644
--- a/src/action_runner/Resources.resx
+++ b/src/action_runner/Resources.resx
@@ -64,4 +64,67 @@
PowerToys installation error
+
+ An update to PowerToys is available.
+
+
+ PowerToys download started.
+
+
+ An update to PowerToys is ready to install.
+
+
+ Error: couldn't download PowerToys installer. Visit our GitHub page to update.
+
+
+ Update now
+
+
+ At next launch
+
+
+ Error: please uninstall the previous version of PowerToys manually.
+
+
+ An update to PowerToys is available. Visit our GitHub page to update.
+
+
+ PowerToys is up to date.
+
+
+ Visit
+
+
+ More info...
+
+
+ Abort
+
+
+ Click Snooze to be reminded in:
+
+
+ 1 day
+
+
+ 5 days
+
+
+ Downloading...
+
+
+ Download complete
+
+
+ PowerToys Update
+
+
+ We've detected a previous installation of PowerToys. Would you like to remove it?
+
+
+ PowerToys: uninstall previous version?
+
+
+ Snooze
+
\ No newline at end of file
diff --git a/src/action_runner/action_runner.cpp b/src/action_runner/action_runner.cpp
index acabf8d767..321be922b2 100644
--- a/src/action_runner/action_runner.cpp
+++ b/src/action_runner/action_runner.cpp
@@ -1,4 +1,6 @@
#define WIN32_LEAN_AND_MEAN
+#include "Generated Files/resource.h"
+
#include
#include
@@ -16,10 +18,10 @@
#include "../runner/tray_icon.h"
#include "../runner/action_runner_utils.h"
-#include "Generated Files/resource.h"
-
extern "C" IMAGE_DOS_HEADER __ImageBase;
+auto Strings = updating::notifications::strings::create();
+
int uninstall_msi_action()
{
const auto package_path = updating::get_msi_package_path();
@@ -27,7 +29,7 @@ int uninstall_msi_action()
{
return 0;
}
- if (!updating::uninstall_msi_version(package_path))
+ if (!updating::uninstall_msi_version(package_path, Strings))
{
return -1;
}
diff --git a/src/action_runner/loc/cs/src/runner/Resources.resx.lcl b/src/action_runner/loc/cs/src/runner/Resources.resx.lcl
index 4dec18f832..f6d43d2ad5 100644
--- a/src/action_runner/loc/cs/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/cs/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/de/src/runner/Resources.resx.lcl b/src/action_runner/loc/de/src/runner/Resources.resx.lcl
index 5b8e0e52b3..7424804ed1 100644
--- a/src/action_runner/loc/de/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/de/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/es/src/runner/Resources.resx.lcl b/src/action_runner/loc/es/src/runner/Resources.resx.lcl
index 8150491f92..3ced2ecaff 100644
--- a/src/action_runner/loc/es/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/es/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/fr/src/runner/Resources.resx.lcl b/src/action_runner/loc/fr/src/runner/Resources.resx.lcl
index 6a6ad56295..2674cc5036 100644
--- a/src/action_runner/loc/fr/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/fr/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/hu/src/runner/Resources.resx.lcl b/src/action_runner/loc/hu/src/runner/Resources.resx.lcl
index 2d1197d4a7..18f1420373 100644
--- a/src/action_runner/loc/hu/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/hu/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/ja/src/runner/Resources.resx.lcl b/src/action_runner/loc/ja/src/runner/Resources.resx.lcl
index 95e71485cd..f8c5716a14 100644
--- a/src/action_runner/loc/ja/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/ja/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/nl/src/runner/Resources.resx.lcl b/src/action_runner/loc/nl/src/runner/Resources.resx.lcl
index 062cf9bdaa..80862face2 100644
--- a/src/action_runner/loc/nl/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/nl/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/pt-BR/src/runner/Resources.resx.lcl b/src/action_runner/loc/pt-BR/src/runner/Resources.resx.lcl
index 32f7bcdbee..ec55d333e5 100644
--- a/src/action_runner/loc/pt-BR/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/pt-BR/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/ru/src/runner/Resources.resx.lcl b/src/action_runner/loc/ru/src/runner/Resources.resx.lcl
index 45350da9a6..9c5febc6f5 100644
--- a/src/action_runner/loc/ru/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/ru/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/tr/src/runner/Resources.resx.lcl b/src/action_runner/loc/tr/src/runner/Resources.resx.lcl
index dcb2988a86..4dc1589b9d 100644
--- a/src/action_runner/loc/tr/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/tr/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/action_runner/loc/zh-Hans/src/runner/Resources.resx.lcl b/src/action_runner/loc/zh-Hans/src/runner/Resources.resx.lcl
index a905f2d967..6443430967 100644
--- a/src/action_runner/loc/zh-Hans/src/runner/Resources.resx.lcl
+++ b/src/action_runner/loc/zh-Hans/src/runner/Resources.resx.lcl
@@ -13,30 +13,45 @@
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
diff --git a/src/common/common.cpp b/src/common/common.cpp
index 8d9d251e72..2c7d3e919d 100644
--- a/src/common/common.cpp
+++ b/src/common/common.cpp
@@ -85,22 +85,22 @@ std::optional get_last_error_message(const DWORD dw)
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);
if (!system_message.has_value())
{
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)
{
StringCchPrintfW(lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(WCHAR),
- localized_strings::LAST_ERROR_FORMAT_STRING,
- lpszFunction,
- dw,
- system_message->c_str());
+ L"%s: %s (%d)",
+ functionName,
+ system_message->c_str(),
+ dw);
MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, errorTitle, MB_OK | MB_ICONERROR);
LocalFree(lpDisplayBuf);
}
diff --git a/src/common/common.h b/src/common/common.h
index e826702a7b..ed3db9e0a4 100644
--- a/src/common/common.h
+++ b/src/common/common.h
@@ -7,12 +7,6 @@
#include
-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.
std::optional 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 timeout_seconds = {});
std::optional 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
{
diff --git a/src/common/notifications.cpp b/src/common/notifications.cpp
index f87064b4cd..bb48d76feb 100644
--- a/src/common/notifications.cpp
+++ b/src/common/notifications.cpp
@@ -33,8 +33,7 @@ using winrt::Windows::UI::Notifications::ToastNotificationManager;
namespace fs = std::filesystem;
-// This namespace contains strings that SHOULD NOT be localized
-namespace
+namespace // Strings in this namespace should not be localized
{
constexpr std::wstring_view TASK_NAME = L"PowerToysBackgroundNotificationsHandler";
constexpr std::wstring_view TASK_ENTRYPOINT = L"PowerToysNotifications.BackgroundHandler";
@@ -45,11 +44,6 @@ namespace
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 const DWORD thread_id = GetCurrentThreadId();
@@ -365,7 +359,7 @@ void notifications::show_toast_with_activations(std::wstring message,
toast_xml += '"';
}
toast_xml += LR"( content=")";
- toast_xml += localized_strings::SNOOZE_BUTTON;
+ toast_xml += b.snooze_button_title;
toast_xml += LR"(" />)";
} },
actions[i]);
diff --git a/src/common/notifications.h b/src/common/notifications.h
index ac52539b4f..01a0a986e0 100644
--- a/src/common/notifications.h
+++ b/src/common/notifications.h
@@ -28,6 +28,7 @@ namespace notifications
{
std::wstring snooze_title;
std::vector durations;
+ std::wstring snooze_button_title;
};
struct link_button
@@ -45,7 +46,7 @@ namespace notifications
struct progress_bar_params
{
- std::wstring_view progress_title;
+ std::wstring progress_title;
float progress = 0.f;
};
diff --git a/src/common/updating/notifications.cpp b/src/common/updating/notifications.cpp
index 8984df265f..01e523e657 100644
--- a/src/common/updating/notifications.cpp
+++ b/src/common/updating/notifications.cpp
@@ -9,39 +9,10 @@
#include "VersionHelper.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 notifications
{
- using namespace localized_strings;
using namespace ::notifications;
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;
}
- void show_unavailable()
+ void show_unavailable(const notifications::strings& strings)
{
remove_toasts(UPDATING_PROCESS_TOAST_TAG);
toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false };
- std::wstring contents = GITHUB_NEW_VERSION_UNAVAILABLE;
- show_toast(std::move(contents), TOAST_TITLE, std::move(toast_params));
+ std::wstring contents = strings.GITHUB_NEW_VERSION_UNAVAILABLE;
+ 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);
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);
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));
}
- 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);
progress_bar_params progress_bar_params;
std::wstring progress_title{ info.version_string };
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 = .0f;
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,
- TOAST_TITLE,
+ show_toast_with_activations(strings.GITHUB_NEW_VERSION_DOWNLOAD_STARTED,
+ strings.TOAST_TITLE,
{},
{},
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);
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);
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));
}
- 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);
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);
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));
}
- 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);
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);
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{ GITHUB_NEW_VERSION_UPDATE_AFTER_RESTART, L"powertoys://schedule_update/" + 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_NOW,
+ L"powertoys://update_now/" + info.installer_filename },
+ 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));
}
- void show_uninstallation_error()
+ void show_uninstallation_error(const notifications::strings& strings)
{
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;
std::wstring progress_title{ info.version_string };
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 = progress;
update_toast_progress_bar(UPDATING_PROCESS_TOAST_TAG, progress_bar_params);
diff --git a/src/common/updating/notifications.h b/src/common/updating/notifications.h
index 30f33f0470..0bd791620f 100644
--- a/src/common/updating/notifications.h
+++ b/src/common/updating/notifications.h
@@ -6,14 +6,66 @@ namespace updating
namespace notifications
{
- void show_unavailable();
- void show_available(const updating::new_version_download_info& info);
- void show_download_start(const updating::new_version_download_info& info);
- void show_visit_github(const updating::new_version_download_info& info);
- void show_install_error(const updating::new_version_download_info& info);
- void show_version_ready(const updating::new_version_download_info& info);
- void show_uninstallation_error();
+ struct strings
+ {
+ std::wstring GITHUB_NEW_VERSION_AVAILABLE;
+ std::wstring GITHUB_NEW_VERSION_DOWNLOAD_STARTED;
+ std::wstring GITHUB_NEW_VERSION_READY_TO_INSTALL;
+ std::wstring GITHUB_NEW_VERSION_DOWNLOAD_INSTALL_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
+ 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);
}
}
\ No newline at end of file
diff --git a/src/common/updating/updating.cpp b/src/common/updating/updating.cpp
index c2f0e6e536..0160d4b0fc 100644
--- a/src/common/updating/updating.cpp
+++ b/src/common/updating/updating.cpp
@@ -19,7 +19,7 @@
#include "VersionHelper.h"
#include
-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 POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
@@ -32,12 +32,6 @@ namespace
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
{
std::wstring get_msi_package_path()
@@ -73,13 +67,18 @@ namespace updating
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;
}
- 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");
if (ERROR_SUCCESS == uninstall_result)
@@ -94,7 +93,7 @@ namespace updating
}
catch (...)
{
- updating::notifications::show_uninstallation_error();
+ updating::notifications::show_uninstallation_error(strings);
}
}
return false;
@@ -202,7 +201,7 @@ namespace updating
return installer_download_dst;
}
- std::future try_autoupdate(const bool download_updates_automatically)
+ std::future try_autoupdate(const bool download_updates_automatically, const notifications::strings& strings)
{
const auto new_version = co_await get_new_github_version_info_async();
if (!new_version)
@@ -230,32 +229,32 @@ namespace updating
}
if (!download_success)
{
- updating::notifications::show_install_error(new_version.value());
+ updating::notifications::show_install_error(new_version.value(), strings);
co_return;
}
- updating::notifications::show_version_ready(new_version.value());
+ updating::notifications::show_version_ready(new_version.value(), strings);
}
else
{
- updating::notifications::show_visit_github(new_version.value());
+ updating::notifications::show_visit_github(new_version.value(), strings);
}
}
- std::future check_new_version_available()
+ std::future check_new_version_available(const notifications::strings& strings)
{
const auto new_version = co_await get_new_github_version_info_async();
if (!new_version)
{
- updating::notifications::show_unavailable();
+ updating::notifications::show_unavailable(strings);
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;
}
- std::future download_update()
+ std::future download_update(const notifications::strings& strings)
{
const auto new_version = co_await get_new_github_version_info_async();
if (!new_version)
@@ -264,12 +263,12 @@ namespace updating
}
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
{
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;
@@ -277,7 +276,7 @@ namespace updating
}
catch (...)
{
- updating::notifications::show_install_error(new_version.value());
+ updating::notifications::show_install_error(new_version.value(), strings);
co_return L"";
}
diff --git a/src/common/updating/updating.h b/src/common/updating/updating.h
index 597a866b16..ea993f6d60 100644
--- a/src/common/updating/updating.h
+++ b/src/common/updating/updating.h
@@ -6,13 +6,14 @@
#include
#include
+#include "notifications.h"
#include "../VersionHelper.h"
namespace updating
{
std::wstring get_msi_package_path();
- bool uninstall_msi_version(const std::wstring& package_path);
- bool offer_msi_uninstallation();
+ bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings&);
+ bool offer_msi_uninstallation(const notifications::strings&);
std::optional get_msi_package_installed_path();
std::optional get_installed_powertoys_version();
@@ -27,11 +28,11 @@ namespace updating
};
std::future> get_new_github_version_info_async();
- std::future try_autoupdate(const bool download_updates_automatically);
+ std::future try_autoupdate(const bool download_updates_automatically, const notifications::strings&);
std::filesystem::path get_pending_updates_path();
- std::future check_new_version_available();
- std::future download_update();
+ std::future check_new_version_available(const notifications::strings&);
+ std::future download_update(const notifications::strings&);
// non-localized
constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN = L"powertoyssetup";
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/ISettingsPath.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/ISettingsPath.cs
new file mode 100644
index 0000000000..072058e4bc
--- /dev/null
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/ISettingsPath.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.PowerToys.Settings.UI.Library
+{
+ public interface ISettingsPath
+ {
+ bool SettingsFolderExists(string powertoy);
+
+ void CreateSettingsFolder(string powertoy);
+
+ void DeleteSettings(string powertoy = "");
+
+ string GetSettingsPath(string powertoy, string fileName);
+ }
+}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/Microsoft.PowerToys.Settings.UI.Library.csproj b/src/core/Microsoft.PowerToys.Settings.UI.Library/Microsoft.PowerToys.Settings.UI.Library.csproj
index 4c94051072..dc4cf10d0b 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Library/Microsoft.PowerToys.Settings.UI.Library.csproj
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/Microsoft.PowerToys.Settings.UI.Library.csproj
@@ -41,6 +41,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+
3.3.0
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/SettingPath.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/SettingPath.cs
new file mode 100644
index 0000000000..65a1ea1244
--- /dev/null
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/SettingPath.cs
@@ -0,0 +1,62 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.IO.Abstractions;
+
+namespace Microsoft.PowerToys.Settings.UI.Library
+{
+ public class SettingPath : ISettingsPath
+ {
+ private const string DefaultFileName = "settings.json";
+
+ private readonly IDirectory _directory;
+
+ private readonly IPath _path;
+
+ public SettingPath(IDirectory directory, IPath path)
+ {
+ _directory = directory ?? throw new ArgumentNullException(nameof(directory));
+ _path = path ?? throw new ArgumentNullException(nameof(path));
+ }
+
+ public bool SettingsFolderExists(string powertoy)
+ {
+ return _directory.Exists(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
+ }
+
+ public void CreateSettingsFolder(string powertoy)
+ {
+ _directory.CreateDirectory(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
+ }
+
+ public void DeleteSettings(string powertoy = "")
+ {
+ _directory.Delete(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
+ }
+
+ private static string LocalApplicationDataFolder()
+ {
+ return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ }
+
+ ///
+ /// Get path to the json settings file.
+ ///
+ /// string path.
+ public string GetSettingsPath(string powertoy, string fileName = DefaultFileName)
+ {
+ if (string.IsNullOrWhiteSpace(powertoy))
+ {
+ return _path.Combine(
+ LocalApplicationDataFolder(),
+ $"Microsoft\\PowerToys\\{fileName}");
+ }
+
+ return _path.Combine(
+ LocalApplicationDataFolder(),
+ $"Microsoft\\PowerToys\\{powertoy}\\{fileName}");
+ }
+ }
+}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/SettingsUtils.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/SettingsUtils.cs
index 13a9b9ba69..e7fc1dec69 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Library/SettingsUtils.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/SettingsUtils.cs
@@ -5,6 +5,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using System.IO.Abstractions;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
@@ -15,49 +16,34 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
private const string DefaultFileName = "settings.json";
private const string DefaultModuleName = "";
- private IIOProvider _ioProvider;
+ private readonly IFile _file;
+ private readonly ISettingsPath _settingsPath;
- public SettingsUtils(IIOProvider ioProvider)
+ public SettingsUtils()
+ : this(new FileSystem())
{
- _ioProvider = ioProvider ?? throw new ArgumentNullException(nameof(ioProvider));
}
- private bool SettingsFolderExists(string powertoy)
+ public SettingsUtils(IFileSystem fileSystem)
+ : this(fileSystem?.File, new SettingPath(fileSystem?.Directory, fileSystem?.Path))
{
- return _ioProvider.DirectoryExists(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
}
- private void CreateSettingsFolder(string powertoy)
+ public SettingsUtils(IFile file, ISettingsPath settingPath)
{
- _ioProvider.CreateDirectory(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
- }
-
- public void DeleteSettings(string powertoy = "")
- {
- _ioProvider.DeleteDirectory(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
- }
-
- ///
- /// Get path to the json settings file.
- ///
- /// string path.
- public static string GetSettingsPath(string powertoy, string fileName = DefaultFileName)
- {
- if (string.IsNullOrWhiteSpace(powertoy))
- {
- return System.IO.Path.Combine(
- LocalApplicationDataFolder(),
- $"Microsoft\\PowerToys\\{fileName}");
- }
-
- return System.IO.Path.Combine(
- LocalApplicationDataFolder(),
- $"Microsoft\\PowerToys\\{powertoy}\\{fileName}");
+ _file = file ?? throw new ArgumentNullException(nameof(file));
+ _settingsPath = settingPath;
}
public bool SettingsExists(string powertoy = DefaultModuleName, string fileName = DefaultFileName)
{
- return _ioProvider.FileExists(GetSettingsPath(powertoy, fileName));
+ var settingsPath = _settingsPath.GetSettingsPath(powertoy, fileName);
+ return _file.Exists(settingsPath);
+ }
+
+ public void DeleteSettings(string powertoy = "")
+ {
+ _settingsPath.DeleteSettings(powertoy);
}
///
@@ -106,7 +92,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
// Look at issue https://github.com/microsoft/PowerToys/issues/6413 you'll see the file has a large sum of \0 to fill up a 4096 byte buffer for writing to disk
// This, while not totally ideal, does work around the problem by trimming the end.
// The file itself did write the content correctly but something is off with the actual end of the file, hence the 0x00 bug
- var jsonSettingsString = _ioProvider.ReadAllText(GetSettingsPath(powertoyFolderName, fileName)).Trim('\0');
+ var jsonSettingsString = _file.ReadAllText(_settingsPath.GetSettingsPath(powertoyFolderName, fileName)).Trim('\0');
return JsonSerializer.Deserialize(jsonSettingsString);
}
@@ -118,12 +104,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
if (jsonSettings != null)
{
- if (!SettingsFolderExists(powertoy))
+ if (!_settingsPath.SettingsFolderExists(powertoy))
{
- CreateSettingsFolder(powertoy);
+ _settingsPath.CreateSettingsFolder(powertoy);
}
- _ioProvider.WriteAllText(GetSettingsPath(powertoy, fileName), jsonSettings);
+ _file.WriteAllText(_settingsPath.GetSettingsPath(powertoy, fileName), jsonSettings);
}
}
catch (Exception e)
@@ -137,10 +123,5 @@ namespace Microsoft.PowerToys.Settings.UI.Library
#endif
}
}
-
- private static string LocalApplicationDataFolder()
- {
- return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
- }
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/Helper.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/Helper.cs
index 8cce1f2a68..22b2964592 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/Helper.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/Helper.cs
@@ -5,6 +5,7 @@
using System;
using System.Diagnostics;
using System.IO;
+using System.IO.Abstractions;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.PowerToys.Settings.UI.Library.CustomAction;
@@ -13,6 +14,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{
public static class Helper
{
+ public static readonly IFileSystem FileSystem = new FileSystem();
+
public static bool AllowRunnerToForeground()
{
var result = false;
@@ -47,22 +50,20 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
return sendCustomAction.ToJsonString();
}
- public static FileSystemWatcher GetFileWatcher(string moduleName, string fileName, Action onChangedCallback)
+ public static IFileSystemWatcher GetFileWatcher(string moduleName, string fileName, Action onChangedCallback)
{
- var path = Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{moduleName}");
+ var path = FileSystem.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{moduleName}");
- if (!Directory.Exists(path))
+ if (!FileSystem.Directory.Exists(path))
{
- Directory.CreateDirectory(path);
+ FileSystem.Directory.CreateDirectory(path);
}
- var watcher = new FileSystemWatcher
- {
- Path = path,
- Filter = fileName,
- NotifyFilter = NotifyFilters.LastWrite,
- EnableRaisingEvents = true,
- };
+ var watcher = FileSystem.FileSystemWatcher.CreateNew();
+ watcher.Path = path;
+ watcher.Filter = fileName;
+ watcher.NotifyFilter = NotifyFilters.LastWrite;
+ watcher.EnableRaisingEvents = true;
watcher.Changed += (o, e) => onChangedCallback();
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/Logger.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/Logger.cs
index 7d98018af7..fbac2c88fb 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/Logger.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/Logger.cs
@@ -5,12 +5,16 @@
using System;
using System.Diagnostics;
using System.Globalization;
-using System.IO;
+using System.IO.Abstractions;
namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{
public static class Logger
{
+ private static readonly IFileSystem FileSystem = new FileSystem();
+ private static readonly IPath Path = FileSystem.Path;
+ private static readonly IDirectory Directory = FileSystem.Directory;
+
private static readonly string ApplicationLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys\\Settings Logs");
static Logger()
@@ -20,6 +24,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
Directory.CreateDirectory(ApplicationLogPath);
}
+ // Using InvariantCulture since this is used for a log file name
var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/SystemIOProvider.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/SystemIOProvider.cs
index 8519f90319..f2895ffd4e 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/SystemIOProvider.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/Utilities/SystemIOProvider.cs
@@ -2,41 +2,61 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.IO;
+using System;
+using System.IO.Abstractions;
namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{
public class SystemIOProvider : IIOProvider
{
+ private readonly IDirectory _directory;
+ private readonly IFile _file;
+
+ public SystemIOProvider()
+ : this(new FileSystem())
+ {
+ }
+
+ public SystemIOProvider(IFileSystem fileSystem)
+ : this(fileSystem?.Directory, fileSystem?.File)
+ {
+ }
+
+ private SystemIOProvider(IDirectory directory, IFile file)
+ {
+ _directory = directory ?? throw new ArgumentNullException(nameof(directory));
+ _file = file ?? throw new ArgumentNullException(nameof(file));
+ }
+
public bool CreateDirectory(string path)
{
- var directoryInfo = Directory.CreateDirectory(path);
+ var directoryInfo = _directory.CreateDirectory(path);
return directoryInfo != null;
}
public void DeleteDirectory(string path)
{
- Directory.Delete(path, recursive: true);
+ _directory.Delete(path, recursive: true);
}
public bool DirectoryExists(string path)
{
- return Directory.Exists(path);
+ return _directory.Exists(path);
}
public bool FileExists(string path)
{
- return File.Exists(path);
+ return _file.Exists(path);
}
public string ReadAllText(string path)
{
- return File.ReadAllText(path);
+ return _file.ReadAllText(path);
}
public void WriteAllText(string path, string content)
{
- File.WriteAllText(path, content);
+ _file.WriteAllText(path, content);
}
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/BackwardsCompatibility/BackCompatTestProperties.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/BackwardsCompatibility/BackCompatTestProperties.cs
index 28ed4f04bc..36ec7b6ffa 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/BackwardsCompatibility/BackCompatTestProperties.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/BackwardsCompatibility/BackCompatTestProperties.cs
@@ -1,13 +1,11 @@
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
-using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Moq;
using System;
-using System.Collections.Generic;
using System.Globalization;
+using System.IO.Abstractions;
using System.Linq.Expressions;
-using System.Text;
namespace Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility
{
@@ -15,6 +13,9 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility
{
public const string RootPathStubFiles = "..\\..\\..\\..\\src\\core\\Microsoft.PowerToys.Settings.UI.UnitTests\\BackwardsCompatibility\\TestFiles\\{0}\\Microsoft\\PowerToys\\{1}\\{2}";
+ // Using Ordinal since this is used internally for a path
+ private static readonly Expression> SettingsFilterExpression = s => s == null || s.Contains("Microsoft\\PowerToys\\settings.json", StringComparison.Ordinal);
+
internal class MockSettingsRepository : ISettingsRepository where T : ISettingsConfig, new()
{
T _settingsConfig;
@@ -43,44 +44,56 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility
}
- public static MockGetModuleIOProvider(string version, string module, string fileName)
+ public static MockGetModuleIOProvider(string version, string module, string fileName)
{
- var stubSettingsPath = string.Format(CultureInfo.InvariantCulture, BackCompatTestProperties.RootPathStubFiles, version, module, fileName);
- Expression> filterExpression = (string s) => s.Contains(module, StringComparison.Ordinal);
- var mockIOProvider = IIOProviderMocks.GetMockIOReadWithStubFile(stubSettingsPath, filterExpression);
- return mockIOProvider;
+ var stubSettingsPath = StubSettingsPath(version, module, fileName);
+ Expression> filterExpression = ModuleFilterExpression(module);
+ return IIOProviderMocks.GetMockIOReadWithStubFile(stubSettingsPath, filterExpression);
}
- public static void VerifyModuleIOProviderWasRead(Mock provider, string module, int expectedCallCount)
+ public static string StubGeneralSettingsPath(string version)
+ {
+ return StubSettingsPath(version, string.Empty, "settings.json");
+ }
+
+ public static string StubSettingsPath(string version, string module, string fileName)
+ {
+ return string.Format(CultureInfo.InvariantCulture, BackCompatTestProperties.RootPathStubFiles, version, module, fileName);
+ }
+
+ public static void VerifyModuleIOProviderWasRead(Mock provider, string module, int expectedCallCount)
{
if(provider == null)
{
throw new ArgumentNullException(nameof(provider));
}
- Expression> filterExpression = (string s) => s.Contains(module, StringComparison.Ordinal);
+ Expression> filterExpression = ModuleFilterExpression(module);
IIOProviderMocks.VerifyIOReadWithStubFile(provider, filterExpression, expectedCallCount);
}
- public static Mock GetGeneralSettingsIOProvider(string version)
+ private static Expression> ModuleFilterExpression(string module)
{
- var stubGeneralSettingsPath = string.Format(CultureInfo.InvariantCulture, BackCompatTestProperties.RootPathStubFiles, version, string.Empty, "settings.json");
- Expression> filterExpression = (string s) => s.Contains("Microsoft\\PowerToys\\settings.json", StringComparison.Ordinal);
- var mockGeneralIOProvider = IIOProviderMocks.GetMockIOReadWithStubFile(stubGeneralSettingsPath, filterExpression);
- return mockGeneralIOProvider;
+ // Using Ordinal since this is used internally for a path
+ return s => s == null || s.Contains(module, StringComparison.Ordinal);
}
- public static void VerifyGeneralSettingsIOProviderWasRead(Mock provider, int expectedCallCount)
+ public static Mock GetGeneralSettingsIOProvider(string version)
+ {
+ var stubGeneralSettingsPath = StubGeneralSettingsPath(version);
+ return IIOProviderMocks.GetMockIOReadWithStubFile(stubGeneralSettingsPath, SettingsFilterExpression);
+ }
+
+ public static void VerifyGeneralSettingsIOProviderWasRead(Mock provider, int expectedCallCount)
{
if (provider == null)
{
throw new ArgumentNullException(nameof(provider));
}
- Expression> filterExpression = (string s) => s.Contains("Microsoft\\PowerToys\\settings.json", StringComparison.Ordinal);
- IIOProviderMocks.VerifyIOReadWithStubFile(provider, filterExpression, expectedCallCount);
+ IIOProviderMocks.VerifyIOReadWithStubFile(provider, SettingsFilterExpression, expectedCallCount);
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/CorruptJson/Microsoft/PowerToys/settings.json b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/CorruptJson/Microsoft/PowerToys/settings.json
new file mode 100644
index 0000000000..7e9dae7531
Binary files /dev/null and b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/CorruptJson/Microsoft/PowerToys/settings.json differ
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Microsoft.PowerToys.Settings.UI.UnitTests.csproj b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Microsoft.PowerToys.Settings.UI.UnitTests.csproj
index 77c03e0bce..92d996e1aa 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Microsoft.PowerToys.Settings.UI.UnitTests.csproj
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Microsoft.PowerToys.Settings.UI.UnitTests.csproj
@@ -29,6 +29,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/IIOProviderMocks.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/IIOProviderMocks.cs
index 9a0b7433ec..226e243b08 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/IIOProviderMocks.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/IIOProviderMocks.cs
@@ -1,10 +1,9 @@
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Moq;
using System;
-using System.Collections.Generic;
-using System.IO;
+using System.IO.Abstractions;
+using System.IO.Abstractions.TestingHelpers;
using System.Linq.Expressions;
-using System.Text;
namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
{
@@ -26,11 +25,13 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
savePath = path;
saveContent = content;
});
+ // Using Ordinal since this is used internally for a path
mockIOProvider.Setup(x => x.ReadAllText(It.Is(x => x.Equals(savePath, StringComparison.Ordinal))))
.Returns(() => saveContent);
-
+ // Using Ordinal since this is used internally for a path
mockIOProvider.Setup(x => x.FileExists(It.Is(x => x.Equals(savePath, StringComparison.Ordinal))))
.Returns(true);
+ // Using Ordinal since this is used internally for a path
mockIOProvider.Setup(x => x.FileExists(It.Is(x => !x.Equals(savePath, StringComparison.Ordinal))))
.Returns(false);
@@ -39,6 +40,8 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
+ private static readonly IFileSystem FileSystem = new FileSystem();
+ private static readonly IFile File = FileSystem.File;
///
/// This method mocks an IO provider so that it will always return data at the savePath location.
/// This mock is specific to a given module, and is verifiable that the stub file was read.
@@ -46,25 +49,25 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
/// The path to the stub settings file
/// The substring in the path that identifies the module eg. Microsoft\\PowerToys\\ColorPicker
///
- internal static Mock GetMockIOReadWithStubFile(string savePath, Expression> filterExpression)
+ internal static Mock GetMockIOReadWithStubFile(string savePath, Expression> filterExpression)
{
string saveContent = File.ReadAllText(savePath);
- var mockIOProvider = new Mock();
+ var fileMock = new Mock();
- mockIOProvider.Setup(x => x.ReadAllText(It.Is(filterExpression)))
+ fileMock.Setup(x => x.ReadAllText(It.Is(filterExpression)))
.Returns(() => saveContent).Verifiable();
- mockIOProvider.Setup(x => x.FileExists(It.Is(filterExpression)))
+ fileMock.Setup(x => x.Exists(It.Is(filterExpression)))
.Returns(true);
- return mockIOProvider;
+ return fileMock;
}
- internal static void VerifyIOReadWithStubFile(Mock mockIOProvider, Expression> filterExpression, int expectedCallCount)
+ internal static void VerifyIOReadWithStubFile(Mock fileMock, Expression> filterExpression, int expectedCallCount)
{
- mockIOProvider.Verify(x => x.ReadAllText(It.Is(filterExpression)), Times.Exactly(expectedCallCount));
+ fileMock.Verify(x => x.ReadAllText(It.Is(filterExpression)), Times.Exactly(expectedCallCount));
}
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsTest.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsTest.cs
index 99555c4649..67daf9a363 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsTest.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsTest.cs
@@ -6,9 +6,9 @@ using System;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
+using System.IO.Abstractions.TestingHelpers;
using Microsoft.PowerToys.Settings.UnitTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
@@ -25,11 +25,8 @@ namespace CommonLibTest
public void ToJsonStringShouldReturnValidJSONOfModelWhenSuccessful()
{
//Mock Disk access
- string saveContent = string.Empty;
- string savePath = string.Empty;
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
-
- var settingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var mockFileSystem = new MockFileSystem();
+ var settingsUtils = new SettingsUtils(mockFileSystem);
// Arrange
string file_name = "test\\BasePTModuleSettingsTest";
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsRepositoryTest.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsRepositoryTest.cs
index 99501ff2e6..ced10464d9 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsRepositoryTest.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsRepositoryTest.cs
@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Collections.Generic;
-using System.IO;
using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.VisualStudio.TestTools.UnitTesting;
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs
index 1289f7015d..9c60f9b8b3 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs
@@ -3,11 +3,14 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.IO;
+using System.IO.Abstractions;
+using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
+using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Microsoft.PowerToys.Settings.UnitTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -19,14 +22,13 @@ namespace CommonLibTest
public class SettingsUtilsTests
{
-
[TestMethod]
public void SaveSettingsSaveSettingsToFileWhenFilePathExists()
{
// Arrange
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
- var settingsUtils = new SettingsUtils(mockIOProvider.Object);
-
+ var mockFileSystem = new MockFileSystem();
+ var settingsUtils = new SettingsUtils(mockFileSystem);
+
string file_name = "\\test";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -44,8 +46,8 @@ namespace CommonLibTest
public void SaveSettingsShouldCreateFileWhenFilePathIsNotFound()
{
// Arrange
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
- var settingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var mockFileSystem = new MockFileSystem();
+ var settingsUtils = new SettingsUtils(mockFileSystem);
string file_name = "test\\Test Folder";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -62,8 +64,8 @@ namespace CommonLibTest
public void SettingsFolderExistsShouldReturnFalseWhenFilePathIsNotFound()
{
// Arrange
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
- var settingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var mockFileSystem = new MockFileSystem();
+ var settingsUtils = new SettingsUtils(mockFileSystem);
string file_name_random = "test\\" + RandomString();
string file_name_exists = "test\\exists";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -79,6 +81,21 @@ namespace CommonLibTest
Assert.IsTrue(pathFound);
}
+ [TestMethod]
+ public void SettingsUtilsMustReturnDefaultItemWhenFileIsCorrupt()
+ {
+ // Arrange
+ var mockFileSystem = new MockFileSystem();
+ var mockSettingsUtils = new SettingsUtils(mockFileSystem);
+
+ // Act
+ TestClass settings = mockSettingsUtils.GetSettings(string.Empty);
+
+ // Assert
+ Assert.AreEqual(settings.TestInt, 100);
+ Assert.AreEqual(settings.TestString, "test");
+ }
+
public static string RandomString()
{
Random random = new Random();
@@ -88,5 +105,26 @@ namespace CommonLibTest
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
+
+ partial class TestClass : ISettingsConfig
+ {
+ public int TestInt { get; set; } = 100;
+ public string TestString { get; set; } = "test";
+
+ public string GetModuleName()
+ {
+ throw new NotImplementedException();
+ }
+
+ public string ToJsonString()
+ {
+ return JsonSerializer.Serialize(this);
+ }
+
+ public bool UpgradeSettingsConfiguration()
+ {
+ throw new NotImplementedException();
+ }
+ }
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs
index 1ddc93c17f..01efdd2370 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs
@@ -2,14 +2,13 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Globalization;
-using System.IO;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
namespace ViewModelTests
{
@@ -27,11 +26,14 @@ namespace ViewModelTests
{
//Arrange
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, ColorPickerSettings.ModuleName, fileName);
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var settingPathMock = new Mock();
+
+ var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object, settingPathMock.Object);
ColorPickerSettings originalSettings = mockSettingsUtils.GetSettings(ColorPickerSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
- var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
+
+ var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockGeneralSettingsUtils);
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/FancyZones.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/FancyZones.cs
index ead763064c..d40f1d9e94 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/FancyZones.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/FancyZones.cs
@@ -3,9 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Drawing;
-using System.Globalization;
-using System.IO;
using System.Text.Json;
using CommonLibTest;
using Microsoft.PowerToys.Settings.UI.Library;
@@ -33,13 +30,16 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName)
{
- var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, FancyZonesSettings.ModuleName, fileName);
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var settingPathMock = new Mock();
+
+ var fileMock = BackCompatTestProperties.GetModuleIOProvider(version, FancyZonesSettings.ModuleName, fileName);
+ var mockSettingsUtils = new SettingsUtils(fileMock.Object, settingPathMock.Object);
FancyZonesSettings originalSettings = mockSettingsUtils.GetSettings(FancyZonesSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
- var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
+ var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings();
+
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockGeneralSettingsUtils);
var fancyZonesRepository = new BackCompatTestProperties.MockSettingsRepository(mockSettingsUtils);
@@ -71,7 +71,7 @@ namespace ViewModelTests
//Verify that the stub file was used
var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings)
- BackCompatTestProperties.VerifyModuleIOProviderWasRead(mockIOProvider, FancyZonesSettings.ModuleName, expectedCallCount);
+ BackCompatTestProperties.VerifyModuleIOProviderWasRead(fileMock, FancyZonesSettings.ModuleName, expectedCallCount);
BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount);
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs
index 167037fc38..98a5a19bd4 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs
@@ -4,7 +4,6 @@
using System;
using System.Globalization;
-using System.IO;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -12,7 +11,7 @@ using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
-using NuGet.Frameworks;
+using JsonSerializer = System.Text.Json.JsonSerializer;
namespace ViewModelTests
{
@@ -40,16 +39,20 @@ namespace ViewModelTests
[DataRow("v0.22.0")]
public void OriginalFilesModificationTest(string version)
{
- var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
- var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
+ var settingPathMock = new Mock();
+ var fileMock = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
+
+ var mockGeneralSettingsUtils = new SettingsUtils(fileMock.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings();
+
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockGeneralSettingsUtils);
+
// Initialise View Model with test Config files
// Arrange
- Func SendMockIPCConfigMSG = msg => { return 0; };
- Func SendRestartAdminIPCMessage = msg => { return 0; };
- Func SendCheckForUpdatesIPCMessage = msg => { return 0; };
+ Func SendMockIPCConfigMSG = msg => 0;
+ Func SendRestartAdminIPCMessage = msg => 0;
+ Func SendCheckForUpdatesIPCMessage = msg => 0;
var viewModel = new GeneralViewModel(
settingsRepository: generalSettingsRepository,
runAsAdminText: "GeneralSettings_RunningAsAdminText",
@@ -71,7 +74,7 @@ namespace ViewModelTests
//Verify that the stub file was used
var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings)
- BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount);
+ BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(fileMock, expectedCallCount);
}
[TestMethod]
@@ -82,7 +85,7 @@ namespace ViewModelTests
Func SendRestartAdminIPCMessage = msg => { return 0; };
Func SendCheckForUpdatesIPCMessage = msg => { return 0; };
GeneralViewModel viewModel = new GeneralViewModel(
- SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
+ settingsRepository: SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText",
false,
@@ -119,7 +122,7 @@ namespace ViewModelTests
Func SendRestartAdminIPCMessage = msg => { return 0; };
Func SendCheckForUpdatesIPCMessage = msg => { return 0; };
GeneralViewModel viewModel = new GeneralViewModel(
- SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
+ settingsRepository: SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText",
false,
@@ -151,7 +154,7 @@ namespace ViewModelTests
// Arrange
GeneralViewModel viewModel = new GeneralViewModel(
- SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
+ settingsRepository: SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText",
false,
@@ -184,7 +187,7 @@ namespace ViewModelTests
Func SendRestartAdminIPCMessage = msg => { return 0; };
Func SendCheckForUpdatesIPCMessage = msg => { return 0; };
viewModel = new GeneralViewModel(
- SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
+ settingsRepository: SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText",
false,
@@ -215,7 +218,7 @@ namespace ViewModelTests
Func SendRestartAdminIPCMessage = msg => { return 0; };
Func SendCheckForUpdatesIPCMessage = msg => { return 0; };
GeneralViewModel viewModel = new GeneralViewModel(
- SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
+ settingsRepository: SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText",
false,
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ImageResizer.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ImageResizer.cs
index 2ea3590483..452b54a8d9 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ImageResizer.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ImageResizer.cs
@@ -3,8 +3,8 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Globalization;
-using System.IO;
+using System.IO.Abstractions;
+using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
@@ -20,16 +20,15 @@ namespace ViewModelTests
[TestClass]
public class ImageResizer
{
+ private Mock _mockGeneralSettingsUtils;
- private Mock mockGeneralSettingsUtils;
-
- private Mock mockImgResizerSettingsUtils;
+ private Mock _mockImgResizerSettingsUtils;
[TestInitialize]
public void SetUpStubSettingUtils()
{
- mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils();
- mockImgResizerSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils();
+ _mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils();
+ _mockImgResizerSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils();
}
@@ -44,13 +43,17 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName)
{
- var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, ImageResizerSettings.ModuleName, fileName);
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var settingPathMock = new Mock();
+
+ var fileMock = BackCompatTestProperties.GetModuleIOProvider(version, ImageResizerSettings.ModuleName, fileName);
+ var mockSettingsUtils = new SettingsUtils(fileMock.Object, settingPathMock.Object);
+
ImageResizerSettings originalSettings = mockSettingsUtils.GetSettings(ImageResizerSettings.ModuleName);
- var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
- var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
+ var mockGeneralFileMock = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
+ var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralFileMock.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings();
+
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockGeneralSettingsUtils);
// Initialise View Model with test Config files
@@ -69,8 +72,8 @@ namespace ViewModelTests
//Verify that the stub file was used
var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings)
- BackCompatTestProperties.VerifyModuleIOProviderWasRead(mockIOProvider, ImageResizerSettings.ModuleName, expectedCallCount);
- BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount);
+ BackCompatTestProperties.VerifyModuleIOProviderWasRead(fileMock, ImageResizerSettings.ModuleName, expectedCallCount);
+ BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralFileMock, expectedCallCount);
}
[TestMethod]
@@ -85,7 +88,7 @@ namespace ViewModelTests
};
// arrange
- ImageResizerViewModel viewModel = new ImageResizerViewModel(mockImgResizerSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(_mockImgResizerSettingsUtils.Object, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act
viewModel.IsEnabled = true;
@@ -95,16 +98,16 @@ namespace ViewModelTests
public void JPEGQualityLevelShouldSetValueToTenWhenSuccessful()
{
// arrange
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var fileSystemMock = new MockFileSystem();
+ var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func SendMockIPCConfigMSG = msg => { return 0; };
- ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act
viewModel.JPEGQualityLevel = 10;
// Assert
- viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual(10, viewModel.JPEGQualityLevel);
}
@@ -112,16 +115,16 @@ namespace ViewModelTests
public void PngInterlaceOptionShouldSetValueToTenWhenSuccessful()
{
// arrange
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var fileSystemMock = new MockFileSystem();
+ var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func SendMockIPCConfigMSG = msg => { return 0; };
- ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act
viewModel.PngInterlaceOption = 10;
// Assert
- viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual(10, viewModel.PngInterlaceOption);
}
@@ -129,16 +132,16 @@ namespace ViewModelTests
public void TiffCompressOptionShouldSetValueToTenWhenSuccessful()
{
// arrange
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var fileSystemMock = new MockFileSystem();
+ var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func SendMockIPCConfigMSG = msg => { return 0; };
- ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act
viewModel.TiffCompressOption = 10;
// Assert
- viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual(10, viewModel.TiffCompressOption);
}
@@ -146,17 +149,17 @@ namespace ViewModelTests
public void FileNameShouldUpdateValueWhenSuccessful()
{
// arrange
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var fileSystemMock = new MockFileSystem();
+ var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func SendMockIPCConfigMSG = msg => { return 0; };
- ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
string expectedValue = "%1 (%3)";
// act
viewModel.FileName = expectedValue;
// Assert
- viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual(expectedValue, viewModel.FileName);
}
@@ -167,6 +170,7 @@ namespace ViewModelTests
var settingUtils = ISettingsUtilsMocks.GetStubSettingsUtils();
var expectedSettingsString = new ImageResizerSettings() { Properties = new ImageResizerProperties() { ImageresizerKeepDateModified = new BoolProperty() { Value = true } } }.ToJsonString();
+ // Using Ordinal since this is used internally
settingUtils.Setup(x => x.SaveSettings(
It.Is(content => content.Equals(expectedSettingsString, StringComparison.Ordinal)),
It.Is(module => module.Equals(ImageResizerSettings.ModuleName, StringComparison.Ordinal)),
@@ -174,7 +178,7 @@ namespace ViewModelTests
.Verifiable();
Func SendMockIPCConfigMSG = msg => { return 0; };
- ImageResizerViewModel viewModel = new ImageResizerViewModel(settingUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(settingUtils.Object, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act
viewModel.KeepDateModified = true;
@@ -187,16 +191,16 @@ namespace ViewModelTests
public void EncoderShouldUpdateValueWhenSuccessful()
{
// arrange
- var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var fileSystemMock = new MockFileSystem();
+ var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func SendMockIPCConfigMSG = msg => { return 0; };
- ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act
viewModel.Encoder = 3;
// Assert
- viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual("163bcc30-e2e9-4f0b-961d-a3e9fdb788a3", viewModel.EncoderGuid);
Assert.AreEqual(3, viewModel.Encoder);
}
@@ -207,7 +211,7 @@ namespace ViewModelTests
// arrange
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils();
Func SendMockIPCConfigMSG = msg => { return 0; };
- ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
int sizeOfOriginalArray = viewModel.Sizes.Count;
// act
@@ -223,7 +227,7 @@ namespace ViewModelTests
// arrange
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils();
Func SendMockIPCConfigMSG = msg => { return 0; };
- ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
+ ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
int sizeOfOriginalArray = viewModel.Sizes.Count;
ImageSize deleteCandidate = viewModel.Sizes.Where(x => x.Id == 0).First();
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerLauncherViewModelTest.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerLauncherViewModelTest.cs
index 9024e55650..3662d18094 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerLauncherViewModelTest.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerLauncherViewModelTest.cs
@@ -10,6 +10,7 @@ using Moq;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility;
using System.Globalization;
+using System.IO.Abstractions;
namespace ViewModelTests
{
@@ -52,13 +53,16 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName)
{
+ var settingPathMock = new Mock();
+
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, PowerLauncherSettings.ModuleName, fileName);
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object, settingPathMock.Object);
PowerLauncherSettings originalSettings = mockSettingsUtils.GetSettings(PowerLauncherSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
- var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
+ var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings();
+
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockGeneralSettingsUtils);
// Initialise View Model with test Config files
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs
index a4b48e63db..c68c973eae 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.IO;
+using System.IO.Abstractions;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -40,13 +40,15 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName)
{
- var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, PowerPreviewSettings.ModuleName, fileName);
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var settingPathMock = new Mock();
+ var fileMock = BackCompatTestProperties.GetModuleIOProvider(version, PowerPreviewSettings.ModuleName, fileName);
+
+ var mockSettingsUtils = new SettingsUtils(fileMock.Object, settingPathMock.Object);
PowerPreviewSettings originalSettings = mockSettingsUtils.GetSettings(PowerPreviewSettings.ModuleName);
var repository = new BackCompatTestProperties.MockSettingsRepository(mockSettingsUtils);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
- var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
+ var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockGeneralSettingsUtils);
@@ -62,7 +64,7 @@ namespace ViewModelTests
//Verify that the stub file was used
var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings)
- BackCompatTestProperties.VerifyModuleIOProviderWasRead(mockIOProvider, PowerPreviewSettings.ModuleName, expectedCallCount);
+ BackCompatTestProperties.VerifyModuleIOProviderWasRead(fileMock, PowerPreviewSettings.ModuleName, expectedCallCount);
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerRename.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerRename.cs
index 937a163aa4..571d061734 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerRename.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerRename.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.IO;
+using System.IO.Abstractions;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -40,12 +40,16 @@ namespace ViewModelTests
[DataRow("v0.22.0", "power-rename-settings.json")]
public void OriginalFilesModificationTest(string version, string fileName)
{
+ var settingPathMock = new Mock();
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, PowerRenameSettings.ModuleName, fileName);
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+
+ var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object, settingPathMock.Object);
PowerRenameLocalProperties originalSettings = mockSettingsUtils.GetSettings(PowerRenameSettings.ModuleName);
+
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
- var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
+
+ var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockGeneralSettingsUtils);
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs
index a6a41fc9d7..53f7a11f06 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.IO;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -30,12 +29,13 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName)
{
+ var settingPathMock = new Mock();
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, ShortcutGuideSettings.ModuleName, fileName);
- var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
+ var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object, settingPathMock.Object);
ShortcutGuideSettings originalSettings = mockSettingsUtils.GetSettings(ShortcutGuideSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
- var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
+ var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockGeneralSettingsUtils);
var shortcutSettingsRepository = new BackCompatTestProperties.MockSettingsRepository(mockSettingsUtils);
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Converters/ModuleEnabledToForegroundConverter.cs b/src/core/Microsoft.PowerToys.Settings.UI/Converters/ModuleEnabledToForegroundConverter.cs
index 8737b6b4ae..e35908e095 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Converters/ModuleEnabledToForegroundConverter.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Converters/ModuleEnabledToForegroundConverter.cs
@@ -5,7 +5,6 @@
using System;
using System.Globalization;
using Microsoft.PowerToys.Settings.UI.Library;
-using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
@@ -14,7 +13,7 @@ namespace Microsoft.PowerToys.Settings.UI.Converters
{
public sealed class ModuleEnabledToForegroundConverter : IValueConverter
{
- private readonly ISettingsUtils settingsUtils = new SettingsUtils(new SystemIOProvider());
+ private readonly ISettingsUtils settingsUtils = new SettingsUtils();
private string selectedTheme = string.Empty;
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
index 3440beb373..83c908a3ee 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
@@ -163,7 +163,10 @@
Enable Keyboard Manager
- Keyboard Manager enable toggle header
+
+ Keyboard Manager enable toggle header
+ do not loc the Product name. Do you want this feature on / off
+
Select the profile to display the active key remap and shortcuts
@@ -214,6 +217,7 @@
Enable Color Picker
+ do not loc the Product name. Do you want this feature on / off
Change cursor when picking a color
@@ -229,6 +233,7 @@
Enable PowerToys Run
+ do not loc the Product name. Do you want this feature on / off
Search & results
@@ -311,6 +316,7 @@
Enable FancyZones
+ do not loc the Product name. Do you want this feature on / off
Excluded apps
@@ -373,10 +379,12 @@
Give feedback
- Module overview
+ Learn more
+ This label is there to point people to additional overview for how to use the product
Attribution
+ giving credit to the projects this utility was based on
About PowerToys
@@ -392,12 +400,15 @@
Report a bug
+ Report an issue inside powertoys
Request a feature
+ Tell our team what we should build
Restart as administrator
+ running PowerToys as a higher level user, account is typically referred to as an admin / administrator
Run at startup
@@ -407,9 +418,11 @@
Shell integration
+ This refers to directly integrating in with Windows
Enable PowerRename
+ do not loc the Product name. Do you want this feature on / off
Settings theme
@@ -428,12 +441,15 @@
Enable Markdown (.md) preview
+ Do not loc "Markdown". Do you want this feature on / off
Enable SVG (.svg) preview
+ Do you want this feature on / off
Enable SVG (.svg) thumbnails
+ Do you want this feature on / off
These settings allow you to manage your Windows File Explorer custom preview handlers.
@@ -464,6 +480,7 @@
Enable Shortcut Guide
+ do not loc the Product name. Do you want this feature on / off
Opacity of background
@@ -476,6 +493,7 @@
Enable Image Resizer
+ do not loc the Product name. Do you want this feature on / off
Image Size
@@ -768,4 +786,4 @@
Windows color settings
Windows refers to the Operating system
-
\ No newline at end of file
+
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs
index e27aeb3aaa..6d994eedc2 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs
@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.IO.Abstractions;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -15,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public ColorPickerPage()
{
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new ColorPickerViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml.cs
index bf96e0880d..f8687cfd1c 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml.cs
@@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public FancyZonesPage()
{
InitializeComponent();
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs
index 4f36d529a9..9ee9591d36 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs
@@ -36,7 +36,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
// Load string resources
ResourceLoader loader = ResourceLoader.GetForViewIndependentUse();
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new GeneralViewModel(
SettingsRepository.GetInstance(settingsUtils),
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ImageResizerPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/ImageResizerPage.xaml.cs
index bf85ea0b50..c76eeede5c 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ImageResizerPage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ImageResizerPage.xaml.cs
@@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public ImageResizerPage()
{
InitializeComponent();
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new ImageResizerViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/KeyboardManagerPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/KeyboardManagerPage.xaml.cs
index dde3ecc739..15a01e9d4f 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/KeyboardManagerPage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/KeyboardManagerPage.xaml.cs
@@ -5,7 +5,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
-using System.IO;
+using System.IO.Abstractions;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -24,7 +24,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private const string PowerToyName = "Keyboard Manager";
private readonly CoreDispatcher dispatcher;
- private readonly FileSystemWatcher watcher;
+ private readonly IFileSystemWatcher watcher;
public KeyboardManagerViewModel ViewModel { get; }
@@ -32,7 +32,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
dispatcher = Window.Current.Dispatcher;
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new KeyboardManagerViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, FilterRemapKeysList);
watcher = Helper.GetFileWatcher(
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml.cs
index 59a61ac699..2efd6c7629 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml.cs
@@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public PowerLauncherPage()
{
InitializeComponent();
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new PowerLauncherViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, (int)Windows.System.VirtualKey.Space);
DataContext = ViewModel;
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml.cs
index 0e23644bdb..ee760a37e1 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml.cs
@@ -19,7 +19,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public PowerPreviewPage()
{
InitializeComponent();
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new PowerPreviewViewModel(SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml.cs
index dd8bec2564..c0f9a1b514 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml.cs
@@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public PowerRenamePage()
{
InitializeComponent();
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new PowerRenameViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml.cs
index 503b31d8d7..b1ec61624b 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml.cs
@@ -17,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
InitializeComponent();
- var settingsUtils = new SettingsUtils(new SystemIOProvider());
+ var settingsUtils = new SettingsUtils();
ViewModel = new ShortcutGuideViewModel(SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/loc/ja/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl b/src/core/Microsoft.PowerToys.Settings.UI/loc/ja/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
index 09179c1389..03966f7659 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/loc/ja/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
+++ b/src/core/Microsoft.PowerToys.Settings.UI/loc/ja/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
@@ -148,6 +148,9 @@
-
+
+
+
@@ -1483,33 +1486,6 @@
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
@@ -1600,15 +1576,6 @@
- -
-
-
-
-
-
-
-
-
-
@@ -1783,7 +1750,7 @@
-
-
+
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/loc/sv/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl b/src/core/Microsoft.PowerToys.Settings.UI/loc/sv/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
index 4dc5864958..9eeb7fc5db 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/loc/sv/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
+++ b/src/core/Microsoft.PowerToys.Settings.UI/loc/sv/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
@@ -148,6 +148,9 @@
-
+
+
+
@@ -1483,33 +1486,6 @@
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
@@ -1600,12 +1576,6 @@
- -
-
-
-
-
-
-
@@ -1736,7 +1706,7 @@
-
+
@@ -1780,8 +1750,8 @@
-
-
-
+
+
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/loc/tr/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl b/src/core/Microsoft.PowerToys.Settings.UI/loc/tr/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
index 11942a2183..c8ff36ebf0 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/loc/tr/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
+++ b/src/core/Microsoft.PowerToys.Settings.UI/loc/tr/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw.lcl
@@ -148,6 +148,9 @@
-
+
+
+
@@ -1483,33 +1486,6 @@
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
@@ -1600,12 +1576,6 @@
- -
-
-
-
-
-
-
@@ -1780,8 +1750,8 @@
-
-
-
+
+
diff --git a/src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj b/src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj
index 3eef221bc0..9126afe98a 100644
--- a/src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj
+++ b/src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj
@@ -225,6 +225,9 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
+ 12.2.5
+
2.0.20525
diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs
index 230d8913c2..1b2294d915 100644
--- a/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs
+++ b/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs
@@ -66,6 +66,7 @@ namespace ColorPicker.Helpers
saturation = Math.Round(saturation * 100);
lightness = Math.Round(lightness * 100);
+ // Using InvariantCulture since this is used for color representation
return $"hsl({hue.ToString(CultureInfo.InvariantCulture)}"
+ $", {saturation.ToString(CultureInfo.InvariantCulture)}%"
+ $", {lightness.ToString(CultureInfo.InvariantCulture)}%)";
@@ -84,6 +85,7 @@ namespace ColorPicker.Helpers
saturation = Math.Round(saturation * 100);
value = Math.Round(value * 100);
+ // Using InvariantCulture since this is used for color representation
return $"hsv({hue.ToString(CultureInfo.InvariantCulture)}"
+ $", {saturation.ToString(CultureInfo.InvariantCulture)}%"
+ $", {value.ToString(CultureInfo.InvariantCulture)}%)";
@@ -103,6 +105,7 @@ namespace ColorPicker.Helpers
yellow = Math.Round(yellow * 100);
blackKey = Math.Round(blackKey * 100);
+ // Using InvariantCulture since this is used for color representation
return $"cmyk({cyan.ToString(CultureInfo.InvariantCulture)}%"
+ $", {magenta.ToString(CultureInfo.InvariantCulture)}%"
+ $", {yellow.ToString(CultureInfo.InvariantCulture)}%"
diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/Logger.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/Logger.cs
index 7058a8ff51..56a149eb7d 100644
--- a/src/modules/colorPicker/ColorPickerUI/Helpers/Logger.cs
+++ b/src/modules/colorPicker/ColorPickerUI/Helpers/Logger.cs
@@ -5,22 +5,24 @@
using System;
using System.Diagnostics;
using System.Globalization;
-using System.IO;
+using System.IO.Abstractions;
namespace ColorPicker.Helpers
{
public static class Logger
{
- private static readonly string ApplicationLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ColorPicker");
+ private static readonly IFileSystem _fileSystem = new FileSystem();
+ private static readonly string ApplicationLogPath = _fileSystem.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ColorPicker");
static Logger()
{
- if (!Directory.Exists(ApplicationLogPath))
+ if (!_fileSystem.Directory.Exists(ApplicationLogPath))
{
- Directory.CreateDirectory(ApplicationLogPath);
+ _fileSystem.Directory.CreateDirectory(ApplicationLogPath);
}
- var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.CurrentCulture) + ".txt");
+ // Using InvariantCulture since this is used for a log file name
+ var logFilePath = _fileSystem.Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
diff --git a/src/modules/colorPicker/ColorPickerUI/Mouse/CursorManager.cs b/src/modules/colorPicker/ColorPickerUI/Mouse/CursorManager.cs
index a523f575a0..7166f881d9 100644
--- a/src/modules/colorPicker/ColorPickerUI/Mouse/CursorManager.cs
+++ b/src/modules/colorPicker/ColorPickerUI/Mouse/CursorManager.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.IO;
+using System.IO.Abstractions;
using ColorPicker.Helpers;
using Microsoft.Win32;
@@ -28,11 +28,13 @@ namespace ColorPicker.Mouse
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
private const int SPIF_SENDCHANGE = 0x02;
+ private static readonly IFileSystem _fileSystem = new FileSystem();
+
public static void SetColorPickerCursor()
{
BackupOriginalCursors();
- var colorPickerCursorPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ColorPickerCursorName);
+ var colorPickerCursorPath = _fileSystem.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ColorPickerCursorName);
ChangeCursor(colorPickerCursorPath, ArrowRegistryName);
ChangeCursor(colorPickerCursorPath, IBeamRegistryName);
}
diff --git a/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs b/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs
index a1e50f5ec7..3ccea1f1e4 100644
--- a/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs
+++ b/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs
@@ -5,6 +5,7 @@
using System;
using System.ComponentModel.Composition;
using System.IO;
+using System.IO.Abstractions;
using System.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
@@ -20,14 +21,14 @@ namespace ColorPicker.Settings
private const int MaxNumberOfRetry = 5;
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Actually, call back is LoadSettingsFromJson")]
- private readonly FileSystemWatcher _watcher;
+ private readonly IFileSystemWatcher _watcher;
private readonly object _loadingSettingsLock = new object();
[ImportingConstructor]
public UserSettings()
{
- _settingsUtils = new SettingsUtils(new SystemIOProvider());
+ _settingsUtils = new SettingsUtils();
ChangeCursor = new SettingItem(true);
ActivationShortcut = new SettingItem(DefaultActivationShortcut);
CopiedColorRepresentation = new SettingItem(ColorRepresentationType.HEX);
diff --git a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs
index 5f9c867b93..aae56ac7c2 100644
--- a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs
+++ b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs
@@ -167,7 +167,7 @@ namespace UnitTest_ColorPickerUI.Helpers
{
var color = Color.FromArgb(red, green, blue);
- Exception? exception = null;
+ Exception exception = null;
try
{
diff --git a/src/modules/colorPicker/UnitTest-ColorPickerUI/UnitTest-ColorPickerUI.csproj b/src/modules/colorPicker/UnitTest-ColorPickerUI/UnitTest-ColorPickerUI.csproj
index c3c3256613..48f90e048e 100644
--- a/src/modules/colorPicker/UnitTest-ColorPickerUI/UnitTest-ColorPickerUI.csproj
+++ b/src/modules/colorPicker/UnitTest-ColorPickerUI/UnitTest-ColorPickerUI.csproj
@@ -2,20 +2,16 @@
netcoreapp3.1
- UnitTest_ColorPickerUI
false
- enable
- 8.0
- Library
+ x64
+ true
- x64
..\..\..\..\x64\Debug\modules\ColorPicker\UnitTest-ColorPickerUI\
- x64
..\..\..\..\x64\Release\modules\ColorPicker\UnitTest-ColorPickerUI\
diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs
index 7b6d389c4c..751fc6c40a 100644
--- a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs
+++ b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
+using System.IO.Abstractions;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
@@ -41,6 +42,8 @@ namespace FancyZonesEditor
private const string CrashReportDynamicAssemblyTag = "dynamic assembly doesn't have location";
private const string CrashReportLocationNullTag = "location is null or empty";
+ private readonly IFileSystem _fileSystem = new FileSystem();
+
public Settings ZoneSettings { get; }
public App()
@@ -157,6 +160,8 @@ namespace FancyZonesEditor
sb.AppendLine("## " + CrashReportEnvironmentTag);
sb.AppendLine(CrashReportCommandLineTag + Environment.CommandLine);
+
+ // Using InvariantCulture since this is used for a timestamp internally
sb.AppendLine(CrashReportTimestampTag + DateTime.Now.ToString(CultureInfo.InvariantCulture));
sb.AppendLine(CrashReportOSVersionTag + Environment.OSVersion.VersionString);
sb.AppendLine(CrashReportIntPtrLengthTag + IntPtr.Size);
diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj b/src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj
index 9494995aa5..9f83b03b19 100644
--- a/src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj
+++ b/src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj
@@ -250,6 +250,9 @@
2.3.0
+
+ 12.2.5
+
4.7.2
diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/GridEditorWindow.xaml b/src/modules/fancyzones/editor/FancyZonesEditor/GridEditorWindow.xaml
index 9e7e74ac27..7c7ad39c71 100644
--- a/src/modules/fancyzones/editor/FancyZonesEditor/GridEditorWindow.xaml
+++ b/src/modules/fancyzones/editor/FancyZonesEditor/GridEditorWindow.xaml
@@ -166,8 +166,8 @@
-
-
+
+
+ {{ThemeName}}
+ PowerToysRun
+ {{ThemeDisplayName}}
+ {{BaseColorScheme}}
+ {{ColorScheme}}
+ {{PrimaryAccentColor}}
+ {{IsHighContrast}}
+
+ {{SystemBaseMediumLowColor}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ScrollBarThumbPointerOver}}
+ {{ScrollBarThumbPointerPressed}}
+
+ {{ScrollBarBackgroundPointerOver}}
+
+
+ {{ScrollBarLineButtonForegroundPointerOver}}
+ {{ScrollBarLineButtonForegroundPointerPressed}}
+
+
+ {{ScrollBarLineButtonBackgroundPointerOver}}
+ {{ScrollBarLineButtonBackgroundPointerPressed}}
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/launcher/Wox.Plugin/Logger/Log.cs b/src/modules/launcher/Wox.Plugin/Logger/Log.cs
index 00bebead1f..76fedeac68 100644
--- a/src/modules/launcher/Wox.Plugin/Logger/Log.cs
+++ b/src/modules/launcher/Wox.Plugin/Logger/Log.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.IO;
+using System.IO.Abstractions;
using System.Runtime.CompilerServices;
using NLog;
using NLog.Config;
@@ -13,6 +13,10 @@ namespace Wox.Plugin.Logger
{
public static class Log
{
+ private static readonly IFileSystem FileSystem = new FileSystem();
+ private static readonly IPath Path = FileSystem.Path;
+ private static readonly IDirectory Directory = FileSystem.Directory;
+
public const string DirectoryName = "Logs";
public static string CurrentLogDirectory { get; }
diff --git a/src/modules/launcher/Wox.Plugin/PluginMetadata.cs b/src/modules/launcher/Wox.Plugin/PluginMetadata.cs
index 657dfe26ba..e4cf311dde 100644
--- a/src/modules/launcher/Wox.Plugin/PluginMetadata.cs
+++ b/src/modules/launcher/Wox.Plugin/PluginMetadata.cs
@@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
-using System.IO;
+using System.IO.Abstractions;
using Newtonsoft.Json;
namespace Wox.Plugin
@@ -12,6 +12,9 @@ namespace Wox.Plugin
[JsonObject(MemberSerialization.OptOut)]
public class PluginMetadata : BaseModel
{
+ private static readonly IFileSystem FileSystem = new FileSystem();
+ private static readonly IPath Path = FileSystem.Path;
+
private string _pluginDirectory;
private List _actionKeywords;
diff --git a/src/modules/launcher/Wox.Plugin/Result.cs b/src/modules/launcher/Wox.Plugin/Result.cs
index 2bcae0d53d..422331840f 100644
--- a/src/modules/launcher/Wox.Plugin/Result.cs
+++ b/src/modules/launcher/Wox.Plugin/Result.cs
@@ -5,7 +5,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
-using System.IO;
+using System.IO.Abstractions;
using System.Windows;
using System.Windows.Media;
@@ -13,6 +13,9 @@ namespace Wox.Plugin
{
public class Result
{
+ private static readonly IFileSystem FileSystem = new FileSystem();
+ private static readonly IPath Path = FileSystem.Path;
+
private string _title;
private ToolTipData _toolTipData;
private string _pluginDirectory;
diff --git a/src/modules/launcher/Wox.Plugin/SharedCommands/FilesFolders.cs b/src/modules/launcher/Wox.Plugin/SharedCommands/FilesFolders.cs
deleted file mode 100644
index f68c39c655..0000000000
--- a/src/modules/launcher/Wox.Plugin/SharedCommands/FilesFolders.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// The Microsoft Corporation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Globalization;
-using System.IO;
-using System.Reflection;
-using Wox.Plugin.Logger;
-using Wox.Plugin.Properties;
-
-namespace Wox.Plugin.SharedCommands
-{
- public static class FilesFolders
- {
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Suppressing this to enable FxCop. We are logging the exception, and going forward general exceptions should not be caught")]
- public static void Copy(this string sourcePath, string targetPath)
- {
- // Get the subdirectories for the specified directory.
- DirectoryInfo dir = new DirectoryInfo(sourcePath);
-
- if (!dir.Exists)
- {
- throw new DirectoryNotFoundException(
- "Source directory does not exist or could not be found: "
- + sourcePath);
- }
-
- try
- {
- DirectoryInfo[] dirs = dir.GetDirectories();
-
- // If the destination directory doesn't exist, create it.
- if (!Directory.Exists(targetPath))
- {
- Directory.CreateDirectory(targetPath);
- }
-
- // Get the files in the directory and copy them to the new location.
- FileInfo[] files = dir.GetFiles();
- foreach (FileInfo file in files)
- {
- string temppath = Path.Combine(targetPath, file.Name);
- file.CopyTo(temppath, false);
- }
-
- // Recursively copy subdirectories by calling itself on each subdirectory until there are no more to copy
- foreach (DirectoryInfo subdir in dirs)
- {
- string temppath = Path.Combine(targetPath, subdir.Name);
- Copy(subdir.FullName, temppath);
- }
- }
-#pragma warning disable CS0168 // Variable is declared but never used. Due to #if debug vs release statement
- catch (Exception e)
-#pragma warning restore CS0168 // Variable is declared but never used
- {
- string error = $"Copying path {targetPath} has failed";
- Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
-#if DEBUG
- throw;
-#else
- // Using CurrentCulture since this is user facing
- System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_copy_failed, targetPath));
- RemoveFolder(targetPath);
-#endif
- }
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Suppressing this to enable FxCop. We are logging the exception, and going forward general exceptions should not be caught")]
- public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPath)
- {
- try
- {
- var fromDir = new DirectoryInfo(fromPath);
- var toDir = new DirectoryInfo(toPath);
-
- if (fromDir.GetFiles("*", SearchOption.AllDirectories).Length != toDir.GetFiles("*", SearchOption.AllDirectories).Length)
- {
- return false;
- }
-
- if (fromDir.GetDirectories("*", SearchOption.AllDirectories).Length != toDir.GetDirectories("*", SearchOption.AllDirectories).Length)
- {
- return false;
- }
-
- return true;
- }
-#pragma warning disable CS0168 // Variable is declared but never used. Due to #if debug vs release statement
- catch (Exception e)
-#pragma warning restore CS0168 // Variable is declared but never used
- {
- string error = $"Unable to verify folders and files between {fromPath} and {toPath}";
- Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
-#if DEBUG
- throw;
-#else
- // Using CurrentCulture since this is user facing
- System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_verifybothfolderfilesequal_failed, fromPath, toPath));
- return false;
-#endif
- }
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Suppressing this to enable FxCop. We are logging the exception, and going forward general exceptions should not be caught")]
- public static void RemoveFolder(this string path)
- {
- try
- {
- if (Directory.Exists(path))
- {
- Directory.Delete(path, true);
- }
- }
-#pragma warning disable CS0168 // Variable is declared but never used. Due to #if debug vs release statement
- catch (Exception e)
-#pragma warning restore CS0168 // Variable is declared but never used
- {
- string error = $"Not able to delete folder {path}";
- Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
-#if DEBUG
- throw;
-#else
- // Using CurrentCulture since this is user facing
- System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_removefolder_failed, path));
-#endif
- }
- }
- }
-}
diff --git a/src/modules/launcher/Wox.Plugin/SharedCommands/SearchWeb.cs b/src/modules/launcher/Wox.Plugin/SharedCommands/SearchWeb.cs
deleted file mode 100644
index 224c7a830d..0000000000
--- a/src/modules/launcher/Wox.Plugin/SharedCommands/SearchWeb.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) Microsoft Corporation
-// The Microsoft Corporation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-
-namespace Wox.Plugin.SharedCommands
-{
- public static class SearchWeb
- {
- ///
- /// Opens search in a new browser. If no browser path is passed in then Chrome is used.
- /// Leave browser path blank to use Chrome.
- ///
- public static void NewBrowserWindow(this Uri url, string browserPath)
- {
- if (url == null)
- {
- throw new ArgumentNullException(nameof(url));
- }
-
- var browserExecutableName = browserPath?
- .Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None)
- .Last();
-
- var browser = string.IsNullOrEmpty(browserExecutableName) ? "chrome" : browserPath;
-
- // Internet Explorer will open url in new browser window, and does not take the --new-window parameter
- var browserArguments = browserExecutableName == "iexplore.exe" ? url.AbsoluteUri : "--new-window " + url.AbsoluteUri;
-
- try
- {
- Process.Start(browser, browserArguments);
- }
- catch (System.ComponentModel.Win32Exception)
- {
- var psi = new ProcessStartInfo
- {
- FileName = url.AbsoluteUri,
- UseShellExecute = true,
- };
- Process.Start(psi);
- }
- }
-
- ///
- /// Opens search as a tab in the default browser chosen in Windows settings.
- ///
- public static void NewTabInBrowser(this Uri url, string browserPath)
- {
- if (url == null)
- {
- throw new ArgumentNullException(nameof(url));
- }
-
- try
- {
- if (!string.IsNullOrEmpty(browserPath))
- {
- Process.Start(browserPath, url.AbsoluteUri);
- }
- else
- {
- Process.Start(url.AbsoluteUri);
- }
- }
-
- // This error may be thrown for Process.Start(browserPath, url)
- catch (System.ComponentModel.Win32Exception)
- {
- Process.Start(url.AbsoluteUri);
- }
- }
- }
-}
diff --git a/src/modules/launcher/Wox.Plugin/ThemeManager.cs b/src/modules/launcher/Wox.Plugin/ThemeManager.cs
index 55b3cdcc06..a8c19bba7c 100644
--- a/src/modules/launcher/Wox.Plugin/ThemeManager.cs
+++ b/src/modules/launcher/Wox.Plugin/ThemeManager.cs
@@ -1,11 +1,10 @@
-// Copyright (c) Microsoft Corporation
+// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Linq;
using System.Windows;
-using MahApps.Metro.Theming;
using ManagedCommon;
using Microsoft.Win32;
@@ -40,31 +39,35 @@ namespace Wox.Plugin
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new ControlzEx.Theming.LibraryTheme(
highContrastOneThemeUri,
- MahAppsLibraryThemeProvider.DefaultInstance));
+ CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new ControlzEx.Theming.LibraryTheme(
highContrastTwoThemeUri,
- MahAppsLibraryThemeProvider.DefaultInstance));
+ CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new ControlzEx.Theming.LibraryTheme(
highContrastBlackThemeUri,
- MahAppsLibraryThemeProvider.DefaultInstance));
+ CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new ControlzEx.Theming.LibraryTheme(
highContrastWhiteThemeUri,
- MahAppsLibraryThemeProvider.DefaultInstance));
+ CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new ControlzEx.Theming.LibraryTheme(
lightThemeUri,
- MahAppsLibraryThemeProvider.DefaultInstance));
+ CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new ControlzEx.Theming.LibraryTheme(
darkThemeUri,
- MahAppsLibraryThemeProvider.DefaultInstance));
+ CustomLibraryThemeProvider.DefaultInstance));
- ResetTheme();
- ControlzEx.Theming.ThemeManager.Current.ThemeSyncMode = ControlzEx.Theming.ThemeSyncMode.SyncAll;
ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged;
+
+ // Currently there is an issue in ControlzEx, so we must use SyncAll to sync also HighContrast themes.
+ // We can change this after using next release.
+ ControlzEx.Theming.ThemeManager.Current.ThemeSyncMode = ControlzEx.Theming.ThemeSyncMode.SyncAll;
+
+ ControlzEx.Theming.ThemeManager.Current.SyncTheme();
}
public Theme GetCurrentTheme()
@@ -119,22 +122,22 @@ namespace Wox.Plugin
else if (theme == Theme.HighContrastOne)
{
currentTheme = Theme.HighContrastOne;
- ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastOneTheme);
+ ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastOneTheme, true);
}
else if (theme == Theme.HighContrastTwo)
{
currentTheme = Theme.HighContrastTwo;
- ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastTwoTheme);
+ ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastTwoTheme, true);
}
else if (theme == Theme.HighContrastWhite)
{
currentTheme = Theme.HighContrastWhite;
- ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastWhiteTheme);
+ ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastWhiteTheme, true);
}
else if (theme == Theme.HighContrastBlack)
{
currentTheme = Theme.HighContrastBlack;
- ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastBlackTheme);
+ ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastBlackTheme, true);
}
else if (theme == Theme.Light)
{
@@ -157,7 +160,15 @@ namespace Wox.Plugin
private void Current_ThemeChanged(object sender, ControlzEx.Theming.ThemeChangedEventArgs e)
{
- ResetTheme();
+ ControlzEx.Theming.ThemeManager.Current.ThemeChanged -= Current_ThemeChanged;
+ try
+ {
+ ResetTheme();
+ }
+ finally
+ {
+ ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged;
+ }
}
protected virtual void Dispose(bool disposing)
diff --git a/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj b/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj
index 8d9c037483..b92c794657 100644
--- a/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj
+++ b/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj
@@ -49,6 +49,15 @@
true
+
+ $(DefaultItemExcludes);**/*.Template.xaml
+
+
+
+
+
+
+
@@ -67,7 +76,6 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
all
diff --git a/src/modules/launcher/Wox.Plugin/loc/cs/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/cs/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index 20aa817c87..894b58408f 100644
--- a/src/modules/launcher/Wox.Plugin/loc/cs/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/cs/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/de/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/de/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index f2c7a84fc1..e8433ea738 100644
--- a/src/modules/launcher/Wox.Plugin/loc/de/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/de/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/es/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/es/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index 9e743b6bd6..d52642fde1 100644
--- a/src/modules/launcher/Wox.Plugin/loc/es/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/es/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/fr/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/fr/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index e67764b6e2..6f087f90e3 100644
--- a/src/modules/launcher/Wox.Plugin/loc/fr/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/fr/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/hu/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/hu/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index ca61fd5acc..338d7a142d 100644
--- a/src/modules/launcher/Wox.Plugin/loc/hu/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/hu/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/ja/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/ja/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index 9c053516cc..b458bb4d8f 100644
--- a/src/modules/launcher/Wox.Plugin/loc/ja/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/ja/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/nl/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/nl/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index acad4295fc..e8644aaba3 100644
--- a/src/modules/launcher/Wox.Plugin/loc/nl/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/nl/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/pt-BR/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/pt-BR/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index e455f4b6fb..6508d57795 100644
--- a/src/modules/launcher/Wox.Plugin/loc/pt-BR/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/pt-BR/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/ru/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/ru/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index 492d44b6b1..1a6c046d1b 100644
--- a/src/modules/launcher/Wox.Plugin/loc/ru/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/ru/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/tr/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/tr/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index 6c57456e62..2ccdcfdb1c 100644
--- a/src/modules/launcher/Wox.Plugin/loc/tr/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/tr/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Plugin/loc/zh-Hans/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl b/src/modules/launcher/Wox.Plugin/loc/zh-Hans/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
index 5d0e91b07e..49c1ef83da 100644
--- a/src/modules/launcher/Wox.Plugin/loc/zh-Hans/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
+++ b/src/modules/launcher/Wox.Plugin/loc/zh-Hans/src/modules/launcher/Wox.Plugin/Properties/Resources.resx.lcl
@@ -13,29 +13,29 @@
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
diff --git a/src/modules/launcher/Wox.Test/Plugins/WindowsIndexerTest.cs b/src/modules/launcher/Wox.Test/Plugins/WindowsIndexerTest.cs
index 8d9a2b5155..b9ca054e78 100644
--- a/src/modules/launcher/Wox.Test/Plugins/WindowsIndexerTest.cs
+++ b/src/modules/launcher/Wox.Test/Plugins/WindowsIndexerTest.cs
@@ -380,6 +380,8 @@ namespace Wox.Test.Plugins
// Assert
string expectedSqlQuery = "SELECT TOP 30 \"System.ItemUrl\", \"System.FileName\", \"System.FileAttributes\" FROM \"SystemIndex\" WHERE (CONTAINS(System.FileName,'\"abcd.*\"',1033)) AND scope='file:' ORDER BY System.DateModified DESC";
+
+ // Using InvariantCultureIgnoreCase since this relates to sql code in string form
Assert.IsFalse(simplifiedSqlQuery.Equals(sqlQuery, StringComparison.InvariantCultureIgnoreCase));
Assert.IsTrue(simplifiedSqlQuery.Equals(expectedSqlQuery, StringComparison.InvariantCultureIgnoreCase));
}
@@ -394,6 +396,7 @@ namespace Wox.Test.Plugins
var simplifiedSqlQuery = WindowsSearchAPI.SimplifyQuery(sqlQuery);
// Assert
+ // Using InvariantCultureIgnoreCase since this relates to sql code in string form
Assert.IsTrue(simplifiedSqlQuery.Equals(sqlQuery, StringComparison.InvariantCultureIgnoreCase));
}
@@ -408,6 +411,8 @@ namespace Wox.Test.Plugins
// Assert
string expectedSqlQuery = "SELECT TOP 30 \"System.ItemUrl\", \"System.FileName\", \"System.FileAttributes\", \"System.FileExtension\" FROM \"SystemIndex\" WHERE (CONTAINS(System.FileName,'\"ab.*\"',1033)) AND (CONTAINS(System.FileName,'\".cd*\"',1033)) AND scope='file:' ORDER BY System.DateModified DESC";
+
+ // Using InvariantCultureIgnoreCase since this relates to sql code in string form
Assert.IsFalse(simplifiedSqlQuery.Equals(sqlQuery, StringComparison.InvariantCultureIgnoreCase));
Assert.IsTrue(simplifiedSqlQuery.Equals(expectedSqlQuery, StringComparison.InvariantCultureIgnoreCase));
}
@@ -423,6 +428,8 @@ namespace Wox.Test.Plugins
// Assert
string expectedSqlQuery = "SELECT TOP 30 \"System.ItemUrl\", \"System.FileName\", \"System.FileAttributes\" FROM \"SystemIndex\" WHERE (CONTAINS(System.FileName,'\"'ab.cd'*\"',1033)) AND scope='file:' ORDER BY System.DateModified DESC";
+
+ // Using InvariantCultureIgnoreCase since this relates to sql code in string form
Assert.IsFalse(simplifiedSqlQuery.Equals(sqlQuery, StringComparison.InvariantCultureIgnoreCase));
Assert.IsTrue(simplifiedSqlQuery.Equals(expectedSqlQuery, StringComparison.InvariantCultureIgnoreCase));
}
diff --git a/src/modules/powerrename/ui/PowerRenameUI.base.rc b/src/modules/powerrename/ui/PowerRenameUI.base.rc
index 1338197c5c..0369a50812 100644
Binary files a/src/modules/powerrename/ui/PowerRenameUI.base.rc and b/src/modules/powerrename/ui/PowerRenameUI.base.rc differ
diff --git a/src/modules/powerrename/ui/PowerRenameUI.cpp b/src/modules/powerrename/ui/PowerRenameUI.cpp
index 2edf08544d..83abdd4850 100644
--- a/src/modules/powerrename/ui/PowerRenameUI.cpp
+++ b/src/modules/powerrename/ui/PowerRenameUI.cpp
@@ -63,7 +63,8 @@ RepositionMap g_repositionMap[] = {
{ IDC_EDIT_SEARCHFOR, Reposition_Width },
{ IDC_EDIT_REPLACEWITH, Reposition_Width },
{ IDC_LIST_PREVIEW, Reposition_Width | Reposition_Height },
- { IDC_STATUS_MESSAGE, Reposition_Y },
+ { IDC_STATUS_MESSAGE_SELECTED, Reposition_Y },
+ { IDC_STATUS_MESSAGE_RENAMING, Reposition_Y },
{ ID_RENAME, Reposition_X | Reposition_Y },
{ ID_ABOUT, Reposition_X | Reposition_Y },
{ IDCANCEL, Reposition_X | Reposition_Y }
@@ -679,7 +680,8 @@ void CPowerRenameUI::_InitDlgText()
UpdateDlgControl(m_hwnd, IDCANCEL, IDS_CANCEL_BUTTON);
UpdateDlgControl(m_hwnd, IDC_SEARCH_FOR, IDS_SEARCH_FOR);
UpdateDlgControl(m_hwnd, IDC_REPLACE_WITH, IDS_REPLACE_WITH);
- UpdateDlgControl(m_hwnd, IDC_STATUS_MESSAGE, IDS_ITEMS_SELECTED);
+ UpdateDlgControl(m_hwnd, IDC_STATUS_MESSAGE_SELECTED, IDS_ITEMS_SELECTED);
+ UpdateDlgControl(m_hwnd, IDC_STATUS_MESSAGE_RENAMING, IDS_ITEMS_RENAMING);
UpdateDlgControl(m_hwnd, IDC_OPTIONSGROUP, IDS_OPTIONS);
UpdateDlgControl(m_hwnd, IDC_PREVIEWGROUP, IDS_PREVIEW);
UpdateDlgControl(m_hwnd, IDC_SEARCHREPLACEGROUP, IDS_RENAME_CRITERIA);
@@ -868,8 +870,11 @@ void CPowerRenameUI::_MoveControl(_In_ DWORD id, _In_ DWORD repositionFlags)
width = mainWindowWidth - static_cast(m_itemsPositioning.listPreviewWidthDiff * scale);
height = mainWindowHeight - static_cast(m_itemsPositioning.listPreviewHeightDiff * scale);
break;
- case IDC_STATUS_MESSAGE:
- y = mainWindowHeight - static_cast(m_itemsPositioning.statusMessageYDiff * scale);
+ case IDC_STATUS_MESSAGE_SELECTED:
+ y = mainWindowHeight - static_cast(m_itemsPositioning.statusMessageSelectedYDiff * scale);
+ break;
+ case IDC_STATUS_MESSAGE_RENAMING:
+ y = mainWindowHeight - static_cast(m_itemsPositioning.statusMessageRenamingYDiff * scale);
break;
case ID_RENAME:
x = mainWindowWidth - static_cast(m_itemsPositioning.renameButtonXDiff * scale);
@@ -1000,12 +1005,17 @@ void CPowerRenameUI::_UpdateCounts()
m_renamingCount = renamingCount;
// Update selected and rename count label
- wchar_t countsLabelFormat[100] = { 0 };
- LoadString(g_hInst, IDS_COUNTSLABELFMT, countsLabelFormat, ARRAYSIZE(countsLabelFormat));
+ wchar_t countsLabelFormatSelected[100] = { 0 };
+ wchar_t countsLabelFormatRenaming[100] = { 0 };
+ LoadString(g_hInst, IDS_COUNTSLABELSELECTEDFMT, countsLabelFormatSelected, ARRAYSIZE(countsLabelFormatSelected));
+ LoadString(g_hInst, IDS_COUNTSLABELRENAMINGFMT, countsLabelFormatRenaming, ARRAYSIZE(countsLabelFormatRenaming));
- wchar_t countsLabel[100] = { 0 };
- StringCchPrintf(countsLabel, ARRAYSIZE(countsLabel), countsLabelFormat, selectedCount, renamingCount);
- SetDlgItemText(m_hwnd, IDC_STATUS_MESSAGE, countsLabel);
+ wchar_t countsLabelSelected[100] = { 0 };
+ wchar_t countsLabelRenaming[100] = { 0 };
+ StringCchPrintf(countsLabelSelected, ARRAYSIZE(countsLabelSelected), countsLabelFormatSelected, selectedCount);
+ StringCchPrintf(countsLabelRenaming, ARRAYSIZE(countsLabelRenaming), countsLabelFormatRenaming, renamingCount);
+ SetDlgItemText(m_hwnd, IDC_STATUS_MESSAGE_SELECTED, countsLabelSelected);
+ SetDlgItemText(m_hwnd, IDC_STATUS_MESSAGE_RENAMING, countsLabelRenaming);
// Update Rename button state
EnableWindow(GetDlgItem(m_hwnd, ID_RENAME), (renamingCount > 0));
@@ -1039,8 +1049,11 @@ void CPowerRenameUI::_CollectItemPosition(_In_ DWORD id)
m_itemsPositioning.listPreviewWidthDiff = m_initialWidth - itemWidth;
m_itemsPositioning.listPreviewHeightDiff = m_initialHeight - itemHeight;
break;
- case IDC_STATUS_MESSAGE:
- m_itemsPositioning.statusMessageYDiff = m_initialHeight - rcWindow.top;
+ case IDC_STATUS_MESSAGE_SELECTED:
+ m_itemsPositioning.statusMessageSelectedYDiff = m_initialHeight - rcWindow.top;
+ break;
+ case IDC_STATUS_MESSAGE_RENAMING:
+ m_itemsPositioning.statusMessageRenamingYDiff = m_initialHeight - rcWindow.top;
break;
case ID_RENAME:
m_itemsPositioning.renameButtonXDiff = m_initialWidth - rcWindow.left;
diff --git a/src/modules/powerrename/ui/PowerRenameUI.h b/src/modules/powerrename/ui/PowerRenameUI.h
index 35b79e0923..c0ef499156 100644
--- a/src/modules/powerrename/ui/PowerRenameUI.h
+++ b/src/modules/powerrename/ui/PowerRenameUI.h
@@ -83,7 +83,8 @@ private:
int searchReplaceWidthDiff;
int listPreviewWidthDiff;
int listPreviewHeightDiff;
- int statusMessageYDiff;
+ int statusMessageSelectedYDiff;
+ int statusMessageRenamingYDiff;
int renameButtonXDiff;
int renameButtonYDiff;
int helpButtonXDiff;
diff --git a/src/modules/powerrename/ui/Resources.resx b/src/modules/powerrename/ui/Resources.resx
index c278b9c056..4da3576bbd 100644
--- a/src/modules/powerrename/ui/Resources.resx
+++ b/src/modules/powerrename/ui/Resources.resx
@@ -133,8 +133,11 @@ Please select from the options above to show items.
Item Name and Extension
-
- Items Selected: %u | Renaming: %u
+
+ Items Selected: %u
+
+
+ Items Renaming: %u
Use Regular Expressions
@@ -188,7 +191,10 @@ Please select from the options above to show items.
Replace with:
- Items Selected: 0 | Renaming: 0
+ Items Selected: 0
+
+
+ Items Renaming: 0
Options
diff --git a/src/modules/powerrename/ui/resource.base.h b/src/modules/powerrename/ui/resource.base.h
index 34b94ea1d9..a79a44208c 100644
--- a/src/modules/powerrename/ui/resource.base.h
+++ b/src/modules/powerrename/ui/resource.base.h
@@ -10,24 +10,25 @@
#define IDC_EDIT_REPLACEWITH 3003
#define IDC_LIST_PREVIEW 3004
#define IDC_CHECK_USEREGEX 3005
-#define IDC_STATUS_MESSAGE 3006
-#define IDC_CHECK_EXCLUDESUBFOLDERS 3007
-#define IDC_CHECK_ENUMITEMS 3008
-#define IDC_CHECK_EXCLUDEFILES 3009
-#define IDC_CHECK_CASESENSITIVE 3010
-#define IDC_CHECK_MATCHALLOCCURENCES 3011
-#define IDC_CHECK_EXCLUDEFOLDERS 3012
-#define IDC_CHECK_NAMEONLY 3013
-#define IDC_CHECK_EXTENSIONONLY 3014
-#define IDC_PREVIEWGROUP 3015
-#define IDC_OPTIONSGROUP 3016
-#define IDC_SEARCHREPLACEGROUP 3017
-#define IDC_TRANSFORM_UPPERCASE 3018
-#define IDC_TRANSFORM_LOWERCASE 3019
-#define IDC_TRANSFORM_TITLECASE 3020
-#define IDC_SEARCH_FOR 3021
-#define IDC_REPLACE_WITH 3022
+#define IDC_STATUS_MESSAGE_SELECTED 3006
+#define IDC_STATUS_MESSAGE_RENAMING 3007
+#define IDC_CHECK_EXCLUDESUBFOLDERS 3008
+#define IDC_CHECK_ENUMITEMS 3009
+#define IDC_CHECK_EXCLUDEFILES 3010
+#define IDC_CHECK_CASESENSITIVE 3011
+#define IDC_CHECK_MATCHALLOCCURENCES 3012
+#define IDC_CHECK_EXCLUDEFOLDERS 3013
+#define IDC_CHECK_NAMEONLY 3014
+#define IDC_CHECK_EXTENSIONONLY 3015
+#define IDC_PREVIEWGROUP 3016
+#define IDC_OPTIONSGROUP 3017
+#define IDC_SEARCHREPLACEGROUP 3018
+#define IDC_TRANSFORM_UPPERCASE 3019
+#define IDC_TRANSFORM_LOWERCASE 3020
+#define IDC_TRANSFORM_TITLECASE 3021
+#define IDC_SEARCH_FOR 3022
+#define IDC_REPLACE_WITH 3023
#define IDC_STATIC -1
-#define IDR_MAINFRAME 3023
-#define IDD_MAIN 3024
+#define IDR_MAINFRAME 3024
+#define IDD_MAIN 3025
#define IDI_RENAME 2001
diff --git a/src/modules/previewpane/MarkdownPreviewHandler/HTMLParsingExtension.cs b/src/modules/previewpane/MarkdownPreviewHandler/HTMLParsingExtension.cs
index e703e586ba..b36467d4a1 100644
--- a/src/modules/previewpane/MarkdownPreviewHandler/HTMLParsingExtension.cs
+++ b/src/modules/previewpane/MarkdownPreviewHandler/HTMLParsingExtension.cs
@@ -2,8 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.IO;
using Markdig;
using Markdig.Extensions.Figures;
using Markdig.Extensions.Tables;
diff --git a/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj b/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj
index d120d518d0..9e2d5c4698 100644
--- a/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj
+++ b/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj
@@ -137,6 +137,9 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
+ 12.2.5
+
diff --git a/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandlerControl.cs b/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandlerControl.cs
index 5957756f4b..fe6b6f3310 100644
--- a/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandlerControl.cs
+++ b/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandlerControl.cs
@@ -4,7 +4,7 @@
using System;
using System.Drawing;
-using System.IO;
+using System.IO.Abstractions;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Common;
@@ -21,6 +21,10 @@ namespace Microsoft.PowerToys.PreviewHandler.Markdown
///
public class MarkdownPreviewHandlerControl : FormHandlerControl
{
+ private static readonly IFileSystem FileSystem = new FileSystem();
+ private static readonly IPath Path = FileSystem.Path;
+ private static readonly IFile File = FileSystem.File;
+
///
/// Extension to modify markdown AST.
///
diff --git a/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs b/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs
index 4ac672ebb7..c5af5df681 100644
--- a/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs
+++ b/src/modules/previewpane/SvgPreviewHandler/Utilities/SvgPreviewHandlerHelper.cs
@@ -47,7 +47,10 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg.Utilities
var elements = doc.Descendants().ToList();
foreach (XElement element in elements)
{
- var elementName = element?.Name?.LocalName?.ToLower(CultureInfo.CurrentCulture);
+ // Using Invariant since we are doing an exact match for HTML tags and we want it to behave the same in every culture
+#pragma warning disable CA1308 // Normalize strings to uppercase
+ var elementName = element?.Name?.LocalName?.ToLowerInvariant();
+#pragma warning restore CA1308 // Normalize strings to uppercase
if (elementName != null && blockedElementsName.ContainsKey(elementName))
{
foundBlockedElement = true;
diff --git a/src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.cs b/src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.cs
index 7f7c29f197..af09d1369d 100644
--- a/src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.cs
+++ b/src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.cs
@@ -166,7 +166,9 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Svg
{0}