Compare commits

..

2 Commits

Author SHA1 Message Date
Gordon Lam (SH)
3bd9698073 Add Parallel project build 2025-10-11 10:03:54 +08:00
Mike Griese
cd5b76c988 CmdPal: make the context menu search look more like a cmdpal (#42081)
Replaces our styling with the same styleing we use for the search bar

But we can't _just_ do that, because the stupid "text cursors don't show
up on top of transparent backgrounds" thing.

So I just added the smoke backdrop to the search box. Seemed reasonable.

Screenshots below.

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
2025-10-10 06:26:04 -05:00
27 changed files with 410 additions and 763 deletions

View File

@@ -58,7 +58,6 @@ body:
- Image Resizer
- Installer
- Keyboard Manager
- Light Switch
- Mouse Utilities
- Mouse Without Borders
- New+

View File

@@ -38,7 +38,6 @@ body:
- Image Resizer
- Installer
- Keyboard Manager
- Light Switch
- Mouse Utilities
- Mouse Without Borders
- New+

View File

@@ -258,6 +258,7 @@ jobs:
-restore -graph
/p:RestorePackagesConfig=true
/p:CIBuild=true
/p:BuildInParallel=true
/bl:$(LogOutputDirectory)\build-0-main.binlog
${{ parameters.additionalBuildOptions }}
$(MSBuildCacheParameters)
@@ -274,10 +275,10 @@ jobs:
# Build PowerToys.DSC.exe for ARM64 (x64 uses existing binary from previous build)
- task: VSBuild@1
displayName: Build PowerToys.DSC.exe (x64 for generating manifests)
condition: and(succeeded(), ne(variables['BuildPlatform'], 'x64'))
condition: ne(variables['BuildPlatform'], 'x64')
inputs:
solution: src/dsc/v3/PowerToys.DSC/PowerToys.DSC.csproj
msbuildArgs: /t:Build /m /restore
msbuildArgs: /t:Build /m /restore /p:BuildInParallel=true
platform: x64
configuration: $(BuildConfiguration)
msbuildArchitecture: x64
@@ -323,6 +324,7 @@ jobs:
-restore -graph
/p:RestorePackagesConfig=true
/p:CIBuild=true
/p:BuildInParallel=true
/bl:$(LogOutputDirectory)\build-bug-report.binlog
${{ parameters.additionalBuildOptions }}
$(MSBuildCacheParameters)
@@ -344,6 +346,7 @@ jobs:
-restore -graph
/p:RestorePackagesConfig=true
/p:CIBuild=true
/p:BuildInParallel=true
/bl:$(LogOutputDirectory)\build-styles-report.binlog
${{ parameters.additionalBuildOptions }}
$(MSBuildCacheParameters)
@@ -365,7 +368,7 @@ jobs:
msbuildArgs: >-
/target:Publish
/graph
/p:Configuration=$(BuildConfiguration);Platform=$(BuildPlatform);AppxBundle=Never
/p:Configuration=$(BuildConfiguration);Platform=$(BuildPlatform);AppxBundle=Never;BuildInParallel=true
/p:VCRTForwarders-IncludeDebugCRT=false
/p:PowerToysRoot=$(Build.SourcesDirectory)
/p:PublishProfile=InstallationPublishProfile.pubxml
@@ -564,16 +567,15 @@ jobs:
flattenFolders: True
targetFolder: $(JobOutputDirectory)
- pwsh: |-
$Symbols = Get-ChildItem "$(BuildPlatform)" -Recurse -Filter *.pdb -Exclude "vc143.pdb","*test*.pdb" |
Group-Object Name | ForEach-Object { $_.Group[0] }
$OutDir = "$(JobOutputDirectory)/symbols-$(BuildPlatform)"
New-Item -Type Directory $OutDir -EA:Ignore
Write-Host "Linking $($Symbols.Length) symbols into place at $OutDir"
ForEach($s in $Symbols) {
New-Item -Type HardLink -Target $s.FullName (Join-Path $OutDir $s.Name)
}
displayName: Stage Unique Symbols (as hard links)
- task: CopyFiles@2
displayName: Stage Symbols
inputs:
contents: |-
**\*.pdb
!**\vc143.pdb
!**\*test*.pdb
flattenFolders: True
targetFolder: $(JobOutputDirectory)/symbols-$(BuildPlatform)/
- pwsh: |-
$p = "$(JobOutputDirectory)\"
@@ -622,30 +624,21 @@ jobs:
# Publishing the GPO files
- pwsh: |-
$GpoArchive = "$(JobOutputDirectory)\GroupPolicyObjectFiles-${{ parameters.versionNumber }}.zip"
tar -c -v --format=zip -C .\src\gpo\assets -f $GpoArchive *
New-Item "$(JobOutputDirectory)/gpo" -Type Directory
Copy-Item src\gpo\assets\* "$(JobOutputDirectory)/gpo" -Recurse
displayName: Stage GPO files
# Running the tests may result in future jobs consuming artifacts out of this build
- ${{ if or(eq(parameters.runTests, true), eq(parameters.buildTests, true)) }}:
# Running the tests may result in future jobs consuming artifacts out of this build
# Instead of running an expensive file copy step, move everything over since the build is totally done.
- pwsh: |-
# It seems weird, but this is for compatibility. Our artifacts historically contained the folder x64/Release/x64/Release (for example).
$FinalOutputRoot = "$(JobOutputDirectory)\$(BuildPlatform)\$(BuildConfiguration)\$(BuildPlatform)"
$ProjectBuildRoot = "$(Build.SourcesDirectory)\$(BuildPlatform)"
$ProjectBuildDirectory = "$ProjectBuildRoot\$(BuildConfiguration)"
New-Item -Type Directory $FinalOutputRoot -EA:Ignore
Move-Item $ProjectBuildDirectory $FinalOutputRoot
displayName: Move entire output directory into artifacts
- task: CopyFiles@2
displayName: Stage entire build output
inputs:
sourceFolder: '$(Build.SourcesDirectory)'
contents: '$(BuildPlatform)/$(BuildConfiguration)/**/*'
targetFolder: '$(JobOutputDirectory)\$(BuildPlatform)\$(BuildConfiguration)'
- ${{ if eq(parameters.publishArtifacts, true) }}:
- publish: $(JobOutputDirectory)
artifact: $(JobOutputArtifactName)
displayName: Publish all outputs
condition: succeeded()
- publish: $(JobOutputDirectory)
artifact: $(JobOutputArtifactName)-failure-$(System.JobAttempt)
displayName: Publish failure logs
condition: or(failed(), canceled())
condition: always()

View File

@@ -90,6 +90,7 @@ jobs:
/p:RestorePackagesConfig=true
/p:BuildProjectReferences=true
/p:CIBuild=true
/p:BuildInParallel=true
/bl:$(LogOutputDirectory)\build-all-uitests.binlog
$(NUGET_RESTORE_MSBUILD_ARGS)
platform: $(BuildPlatform)
@@ -111,6 +112,7 @@ jobs:
/p:RestorePackagesConfig=true
/p:BuildProjectReferences=true
/p:CIBuild=true
/p:BuildInParallel=true
/bl:$(LogOutputDirectory)\build-${{ module }}.binlog
$(NUGET_RESTORE_MSBUILD_ARGS)
platform: $(BuildPlatform)

View File

@@ -63,14 +63,14 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<UseDebugLibraries>true</UseDebugLibraries>
<LinkIncremental>true</LinkIncremental>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LinkIncremental>false</LinkIncremental>

View File

@@ -3,26 +3,6 @@
#include "ThemeHelper.h"
// Controls changing the themes.
static void ResetColorPrevalence()
{
HKEY hKey;
if (RegOpenKeyEx(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
0,
KEY_SET_VALUE,
&hKey) == ERROR_SUCCESS)
{
DWORD value = 0; // back to default value
RegSetValueEx(hKey, L"ColorPrevalence", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
RegCloseKey(hKey);
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
SendMessageTimeout(HWND_BROADCAST, WM_DWMCOLORIZATIONCOLORCHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
}
}
void SetAppsTheme(bool mode)
{
@@ -56,11 +36,6 @@ void SetSystemTheme(bool mode)
RegSetValueEx(hKey, L"SystemUsesLightTheme", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
RegCloseKey(hKey);
if (mode) // if are changing to light mode
{
ResetColorPrevalence();
}
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);

View File

@@ -47,7 +47,6 @@ const static wchar_t* MODULE_DESC = L"This is a module that allows you to contro
enum class ScheduleMode
{
Off,
FixedHours,
SunsetToSunrise,
// add more later
@@ -60,9 +59,8 @@ inline std::wstring ToString(ScheduleMode mode)
case ScheduleMode::SunsetToSunrise:
return L"SunsetToSunrise";
case ScheduleMode::FixedHours:
return L"FixedHours";
default:
return L"Off";
return L"FixedHours";
}
}
@@ -70,9 +68,7 @@ inline ScheduleMode FromString(const std::wstring& str)
{
if (str == L"SunsetToSunrise")
return ScheduleMode::SunsetToSunrise;
if (str == L"FixedHours")
return ScheduleMode::FixedHours;
return ScheduleMode::Off;
return ScheduleMode::FixedHours;
}
// These are the properties shown in the Settings page.
@@ -80,7 +76,7 @@ struct ModuleSettings
{
bool m_changeSystem = true;
bool m_changeApps = true;
ScheduleMode m_scheduleMode = ScheduleMode::Off;
ScheduleMode m_scheduleMode = ScheduleMode::FixedHours;
int m_lightTime = 480;
int m_darkTime = 1200;
int m_sunrise_offset = 0;
@@ -165,8 +161,7 @@ public:
L"scheduleMode",
L"Theme schedule mode",
ToString(g_settings.m_scheduleMode),
{ { L"Off", L"Disable the schedule" },
{ L"FixedHours", L"Set hours manually" },
{ { L"FixedHours", L"Set hours manually" },
{ L"SunsetToSunrise", L"Use sunrise/sunset times" } });
// Integer spinners
@@ -289,20 +284,9 @@ public:
g_settings.m_changeApps = *v;
}
auto previousMode = g_settings.m_scheduleMode;
if (auto v = values.get_string_value(L"scheduleMode"))
{
auto newMode = FromString(*v);
if (newMode != g_settings.m_scheduleMode)
{
Logger::info(L"[LightSwitchInterface] Schedule mode changed from {} to {}",
ToString(g_settings.m_scheduleMode),
ToString(newMode));
g_settings.m_scheduleMode = newMode;
start_service_if_needed();
}
g_settings.m_scheduleMode = FromString(*v);
}
if (auto v = values.get_int_value(L"lightTime"))
@@ -320,7 +304,7 @@ public:
g_settings.m_sunrise_offset = *v;
}
if (auto v = values.get_int_value(L"sunset_offset"))
if (auto v = values.get_int_value(L"m_sunset_offset"))
{
g_settings.m_sunset_offset = *v;
}
@@ -342,47 +326,6 @@ public:
}
}
virtual void start_service_if_needed()
{
if (!m_process || WaitForSingleObject(m_process, 0) != WAIT_TIMEOUT)
{
Logger::info(L"[LightSwitchInterface] Starting LightSwitchService due to active schedule mode.");
enable();
}
else
{
Logger::debug(L"[LightSwitchInterface] Service already running, skipping start.");
}
}
/*virtual void stop_worker_only()
{
if (m_process)
{
Logger::info(L"[LightSwitchInterface] Stopping LightSwitchService (worker only).");
constexpr DWORD timeout_ms = 1500;
DWORD result = WaitForSingleObject(m_process, timeout_ms);
if (result == WAIT_TIMEOUT)
{
Logger::warn("Light Switch: Process didn't exit in time. Forcing termination.");
TerminateProcess(m_process, 0);
}
CloseHandle(m_process);
m_process = nullptr;
}
}*/
/*virtual void stop_service_if_running()
{
if (m_process)
{
Logger::info(L"[LightSwitchInterface] Stopping LightSwitchService due to schedule OFF.");
stop_worker_only();
}
}*/
virtual void enable()
{
m_enabled = true;
@@ -470,12 +413,6 @@ public:
return m_enabled;
}
// Returns whether the PowerToys should be enabled by default
virtual bool is_enabled_by_default() const override
{
return false;
}
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
{
auto settingsObject = settings.get_raw_json();
@@ -534,15 +471,6 @@ public:
SetAppsTheme(!GetCurrentAppsTheme());
}
if (!m_manual_override_event_handle)
{
m_manual_override_event_handle = OpenEventW(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
if (!m_manual_override_event_handle)
{
m_manual_override_event_handle = CreateEventW(nullptr, TRUE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
}
}
if (m_manual_override_event_handle)
{
SetEvent(m_manual_override_event_handle);

View File

@@ -186,138 +186,61 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
if (settings.changeSystem && !isSystemCurrentlyLight)
SetSystemTheme(true);
Logger::info(L"[LightSwitchService] Changing system theme to light mode.");
if (settings.changeApps && !isAppsCurrentlyLight)
SetAppsTheme(true);
Logger::info(L"[LightSwitchService] Changing apps theme to light mode.");
}
else
{
if (settings.changeSystem && isSystemCurrentlyLight)
SetSystemTheme(false);
Logger::info(L"[LightSwitchService] Changing system theme to dark mode.");
if (settings.changeApps && isAppsCurrentlyLight)
SetAppsTheme(false);
Logger::info(L"[LightSwitchService] Changing apps theme to light mode.");
}
};
// --- Initial settings load ---
LightSwitchSettings::instance().LoadSettings();
auto& settings = LightSwitchSettings::instance().settings();
// --- Initial theme application (if schedule enabled) ---
if (settings.scheduleMode != ScheduleMode::Off)
// --- At service start: immediately honor the schedule ---
{
SYSTEMTIME st;
GetLocalTime(&st);
int nowMinutes = st.wHour * 60 + st.wMinute;
LightSwitchSettings::instance().LoadSettings();
const auto& settings = LightSwitchSettings::instance().settings();
applyTheme(nowMinutes, settings.lightTime + settings.sunrise_offset, settings.darkTime + settings.sunset_offset, settings);
}
else
{
Logger::info(L"[LightSwitchService] Schedule mode is OFF - ticker suspended, waiting for manual action or mode change.");
}
// --- Main loop ---
// --- Main loop: wakes once per minute or stop/parent death ---
for (;;)
{
HANDLE waits[2] = { g_ServiceStopEvent, hParent };
DWORD count = hParent ? 2 : 1;
LightSwitchSettings::instance().LoadSettings();
const auto& settings = LightSwitchSettings::instance().settings();
// If schedule is off, idle but keep watching settings and manual override
if (settings.scheduleMode == ScheduleMode::Off)
{
Logger::info(L"[LightSwitchService] Schedule mode OFF - suspending scheduler but keeping service alive.");
if (!hManualOverride)
{
hManualOverride = OpenEventW(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
}
HANDLE waits[4];
DWORD count = 0;
waits[count++] = g_ServiceStopEvent;
if (hParent)
waits[count++] = hParent;
if (hManualOverride)
waits[count++] = hManualOverride;
waits[count++] = LightSwitchSettings::instance().GetSettingsChangedEvent();
for (;;)
{
DWORD wait = WaitForMultipleObjects(count, waits, FALSE, INFINITE);
// --- Handle exit signals ---
if (wait == WAIT_OBJECT_0) // stop event
{
Logger::info(L"[LightSwitchService] Stop event triggered - exiting worker loop.");
break;
}
if (hParent && wait == WAIT_OBJECT_0 + 1)
{
Logger::info(L"[LightSwitchService] Parent exited - stopping service.");
break;
}
// --- Manual override triggered ---
if (wait == WAIT_OBJECT_0 + (hParent ? 2 : 1))
{
Logger::info(L"[LightSwitchService] Manual override received while schedule OFF.");
ResetEvent(hManualOverride);
continue;
}
// --- Settings file changed ---
if (wait == WAIT_OBJECT_0 + (hParent ? 3 : 2))
{
Logger::trace(L"[LightSwitchService] Settings change event triggered, reloading settings...");
ResetEvent(LightSwitchSettings::instance().GetSettingsChangedEvent());
LightSwitchSettings::instance().LoadSettings();
const auto& newSettings = LightSwitchSettings::instance().settings();
if (newSettings.scheduleMode != ScheduleMode::Off)
{
Logger::info(L"[LightSwitchService] Schedule re-enabled, resuming normal loop.");
break;
}
}
}
}
// --- When schedule is active, run once per minute ---
SYSTEMTIME st;
GetLocalTime(&st);
int nowMinutes = st.wHour * 60 + st.wMinute;
LightSwitchSettings::instance().LoadSettings();
const auto& settings = LightSwitchSettings::instance().settings();
// Refresh suntimes at day boundary
if ((g_lastUpdatedDay != st.wDay) && (settings.scheduleMode == ScheduleMode::SunsetToSunrise))
if (g_lastUpdatedDay != st.wDay)
{
update_sun_times(settings);
g_lastUpdatedDay = st.wDay;
Logger::info(L"[LightSwitchService] Recalculated sun times at new day boundary.");
}
// Have to do this again in case settings got updated in the refresh suntimes chunk
LightSwitchSettings::instance().LoadSettings();
const auto& currentSettings = LightSwitchSettings::instance().settings();
wchar_t msg[160];
swprintf_s(msg,
L"[LightSwitchService] now=%02d:%02d | light=%02d:%02d | dark=%02d:%02d | mode=%d",
L"[LightSwitchService] now=%02d:%02d | light=%02d:%02d | dark=%02d:%02d",
st.wHour,
st.wMinute,
currentSettings.lightTime / 60,
currentSettings.lightTime % 60,
currentSettings.darkTime / 60,
currentSettings.darkTime % 60,
static_cast<int>(currentSettings.scheduleMode));
settings.lightTime / 60,
settings.lightTime % 60,
settings.darkTime / 60,
settings.darkTime % 60);
Logger::info(msg);
// --- Manual override check ---
@@ -329,20 +252,22 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
if (manualOverrideActive)
{
if (nowMinutes == (currentSettings.lightTime + currentSettings.sunrise_offset) % 1440 ||
nowMinutes == (currentSettings.darkTime + currentSettings.sunset_offset) % 1440)
// Did we hit a scheduled boundary? (reset override at boundary)
if (nowMinutes == (settings.lightTime + settings.sunrise_offset) % 1440 ||
nowMinutes == (settings.darkTime + settings.sunset_offset) % 1440)
{
ResetEvent(hManualOverride);
Logger::info(L"[LightSwitchService] Manual override cleared at boundary");
Logger::info(L"[LightSwitchService] Manual override cleared at boundary\n");
}
else
{
Logger::info(L"[LightSwitchService] Skipping schedule due to manual override");
Logger::info(L"[LightSwitchService] Skipping schedule due to manual override\n");
goto sleep_until_next_minute;
}
}
applyTheme(nowMinutes, currentSettings.lightTime + currentSettings.sunrise_offset, currentSettings.darkTime + currentSettings.sunset_offset, currentSettings);
// Apply theme logic (only runs if no manual override or override just cleared)
applyTheme(nowMinutes, settings.lightTime + settings.sunrise_offset, settings.darkTime + settings.sunset_offset, settings);
sleep_until_next_minute:
GetLocalTime(&st);
@@ -353,14 +278,15 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
DWORD wait = WaitForMultipleObjects(count, waits, FALSE, msToNextMinute);
if (wait == WAIT_OBJECT_0)
{
Logger::info(L"[LightSwitchService] Stop event triggered - exiting worker loop.");
Logger::info(L"[LightSwitchService] Stop event triggered <EFBFBD> exiting worker loop.");
break;
}
if (hParent && wait == WAIT_OBJECT_0 + 1)
if (hParent && wait == WAIT_OBJECT_0 + 1) // parent process exited
{
Logger::info(L"[LightSwitchService] Parent process exited - stopping service.");
Logger::info(L"[LightSwitchService] Parent process exited <EFBFBD> stopping service.");
break;
}
}
if (hManualOverride)
@@ -371,7 +297,6 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
return 0;
}
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
if (powertoys_gpo::getConfiguredLightSwitchEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled)

View File

@@ -6,7 +6,6 @@
#include <filesystem>
#include <fstream>
#include <WinHookEventIDs.h>
#include <logger.h>
using namespace std;
@@ -28,20 +27,10 @@ std::wstring LightSwitchSettings::GetSettingsFileName()
void LightSwitchSettings::InitFileWatcher()
{
if (!m_settingsChangedEvent)
{
m_settingsChangedEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
}
if (!m_settingsFileWatcher)
{
m_settingsFileWatcher = std::make_unique<FileWatcher>(
GetSettingsFileName(),
[this]() {
Logger::info(L"[LightSwitchSettings] Settings file changed, signaling event.");
SetEvent(m_settingsChangedEvent);
});
}
const std::wstring& settingsFileName = GetSettingsFileName();
m_settingsFileWatcher = std::make_unique<FileWatcher>(settingsFileName, [&]() {
PostMessageW(HWND_BROADCAST, WM_PRIV_SETTINGS_CHANGED, NULL, NULL);
});
}
void LightSwitchSettings::AddObserver(SettingsObserver& observer)

View File

@@ -14,7 +14,6 @@ class SettingsObserver;
enum class ScheduleMode
{
Off,
FixedHours,
SunsetToSunrise
// Add more in the future
@@ -29,7 +28,7 @@ inline std::wstring ToString(ScheduleMode mode)
case ScheduleMode::SunsetToSunrise:
return L"SunsetToSunrise";
default:
return L"Off";
return L"FixedHours";
}
}
@@ -37,10 +36,8 @@ inline ScheduleMode FromString(const std::wstring& str)
{
if (str == L"SunsetToSunrise")
return ScheduleMode::SunsetToSunrise;
if (str == L"FixedHours")
return ScheduleMode::FixedHours;
else
return ScheduleMode::Off;
return ScheduleMode::FixedHours;
}
struct LightSwitchConfig
@@ -79,8 +76,6 @@ public:
void LoadSettings();
HANDLE GetSettingsChangedEvent() const { return m_settingsChangedEvent; }
private:
LightSwitchSettings();
~LightSwitchSettings() = default;
@@ -90,6 +85,4 @@ private:
std::unordered_set<SettingsObserver*> m_observers;
void NotifyObservers(SettingId id) const;
HANDLE m_settingsChangedEvent = nullptr;
};

View File

@@ -1,32 +1,8 @@
#include <windows.h>
#include <logger/logger_settings.h>
#include <logger/logger.h>
#include <utils/logger_helper.h>
#include "ThemeHelper.h"
// Controls changing the themes.
static void ResetColorPrevalence()
{
HKEY hKey;
if (RegOpenKeyEx(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
0,
KEY_SET_VALUE,
&hKey) == ERROR_SUCCESS)
{
DWORD value = 0; // back to default value
RegSetValueEx(hKey, L"ColorPrevalence", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
RegCloseKey(hKey);
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
SendMessageTimeout(HWND_BROADCAST, WM_DWMCOLORIZATIONCOLORCHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
}
}
void SetAppsTheme(bool mode)
{
HKEY hKey;
@@ -59,12 +35,6 @@ void SetSystemTheme(bool mode)
RegSetValueEx(hKey, L"SystemUsesLightTheme", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
RegCloseKey(hKey);
if (mode) // if are changing to light mode
{
ResetColorPrevalence();
Logger::info(L"[LightSwitchService] Reset ColorPrevalence to default when switching to light mode.");
}
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);

View File

@@ -2,10 +2,8 @@
// 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.Collections.Generic;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -15,8 +13,6 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
public string CurrentFilterId { get; private set; } = string.Empty;
public IFilterItemViewModel? CurrentFilter { get; private set; }
public IFilterItemViewModel[] Filters { get; private set; } = [];
public bool ShouldShowFilters => Filters.Length > 0;
@@ -34,13 +30,11 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
if (_filtersModel.Unsafe is not null)
{
var filters = _filtersModel.Unsafe.GetFilters();
var currentFilterId = _filtersModel.Unsafe.CurrentFilterId ?? string.Empty;
Filters = BuildFilters(filters ?? []);
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters));
var result = BuildFilters(filters ?? [], currentFilterId);
Filters = result.Items;
CurrentFilterId = currentFilterId;
CurrentFilter = result.Selected;
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters), nameof(CurrentFilterId), nameof(CurrentFilter));
CurrentFilterId = _filtersModel.Unsafe.CurrentFilterId ?? string.Empty;
UpdateProperty(nameof(CurrentFilterId));
return;
}
@@ -51,48 +45,27 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
}
Filters = [];
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters));
CurrentFilterId = string.Empty;
CurrentFilter = null;
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters), nameof(CurrentFilterId), nameof(CurrentFilter));
UpdateProperty(nameof(CurrentFilterId));
}
private (IFilterItemViewModel[] Items, IFilterItemViewModel? Selected) BuildFilters(IFilterItem[] filters, string currentFilterId)
private IFilterItemViewModel[] BuildFilters(IFilterItem[] filters)
{
if (filters is null || filters.Length == 0)
{
return ([], null);
}
var items = new List<IFilterItemViewModel>(filters.Length);
FilterItemViewModel? firstFilterItem = null;
FilterItemViewModel? selectedFilterItem = null;
foreach (var filter in filters)
return [..filters.Select<IFilterItem, IFilterItemViewModel>(filter =>
{
if (filter is IFilter filterItem)
{
var filterItemViewModel = new FilterItemViewModel(filterItem, PageContext);
var filterItemViewModel = new FilterItemViewModel(filterItem!, PageContext);
filterItemViewModel.InitializeProperties();
if (firstFilterItem is null)
{
firstFilterItem = filterItemViewModel;
}
if (selectedFilterItem is null && filterItemViewModel.Id == currentFilterId)
{
selectedFilterItem = filterItemViewModel;
}
items.Add(filterItemViewModel);
return filterItemViewModel;
}
else
{
items.Add(new SeparatorViewModel());
return new SeparatorViewModel();
}
}
return (items.ToArray(), selectedFilterItem ?? firstFilterItem);
})];
}
public override void SafeCleanup()

View File

@@ -244,36 +244,7 @@ public partial class MainListPage : DynamicListPage,
var commands = _tlcManager.TopLevelCommands;
lock (commands)
{
if (token.IsCancellationRequested)
{
return;
}
// prefilter fallbacks
var specialFallbacks = new List<TopLevelViewModel>(_specialFallbacks.Length);
var commonFallbacks = new List<TopLevelViewModel>();
foreach (var s in commands)
{
if (!s.IsFallback)
{
continue;
}
if (_specialFallbacks.Contains(s.CommandProviderId))
{
specialFallbacks.Add(s);
}
else
{
commonFallbacks.Add(s);
}
}
// start update of fallbacks; update special fallbacks separately,
// so they can finish faster
UpdateFallbacks(SearchText, specialFallbacks, token);
UpdateFallbacks(SearchText, commonFallbacks, token);
UpdateFallbacks(SearchText, commands.ToImmutableArray(), token);
if (token.IsCancellationRequested)
{
@@ -345,12 +316,15 @@ public partial class MainListPage : DynamicListPage,
// with a list of all our commands & apps.
if (!newFilteredItems.Any() && !newApps.Any())
{
// We're going to start over with our fallbacks
newFallbacks = Enumerable.Empty<IListItem>();
newFilteredItems = commands.Where(s => !s.IsFallback);
// Fallbacks are always included in the list, even if they
// don't match the search text. But we don't want to
// consider them when filtering the list.
newFallbacks = commonFallbacks;
newFallbacks = commands.Where(s => s.IsFallback && !_specialFallbacks.Contains(s.CommandProviderId));
if (token.IsCancellationRequested)
{

View File

@@ -74,7 +74,8 @@
ItemsSource="{x:Bind ViewModel.Filters, Mode=OneWay}"
PlaceholderText="Filters"
PreviewKeyDown="FiltersComboBox_PreviewKeyDown"
SelectedValue="{x:Bind ViewModel.CurrentFilter, Mode=OneWay}"
SelectedValue="{x:Bind ViewModel.CurrentFilterId, Mode=OneWay}"
SelectedValuePath="Id"
SelectionChanged="FiltersComboBox_SelectionChanged"
Style="{StaticResource ComboBoxStyle}"
Visibility="{x:Bind ViewModel.ShouldShowFilters, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">

View File

@@ -51,12 +51,7 @@ internal static class WindowExtensions
currentStyle &= ~(int)style;
}
var wasSet = PInvoke.SetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, currentStyle) != 0;
// SWP_FRAMECHANGED - invalidate cached window style
PInvoke.SetWindowPos(hWnd, new HWND(IntPtr.Zero), 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_FRAMECHANGED | SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_NOZORDER | SET_WINDOW_POS_FLAGS.SWP_NOOWNERZORDER);
return wasSet;
return PInvoke.SetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, currentStyle) != 0;
}
/// <summary>

View File

@@ -11,7 +11,6 @@
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
@@ -215,8 +214,7 @@
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
@@ -237,8 +235,6 @@
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets'))" />

View File

@@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
public const int DefaultSunsetOffset = 0;
public const string DefaultLatitude = "0.0";
public const string DefaultLongitude = "0.0";
public const string DefaultScheduleMode = "Off";
public const string DefaultScheduleMode = "FixedHours";
public static readonly HotkeySettings DefaultToggleThemeHotkey = new HotkeySettings(true, true, false, true, 0x44); // Ctrl+Win+Shift+D
public LightSwitchProperties()

View File

@@ -3,17 +3,14 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Settings.UI.Library
{
public class LightSwitchSettings : BasePTModuleSettings, ISettingsConfig, ICloneable, IHotkeyConfig
public class LightSwitchSettings : BasePTModuleSettings, ISettingsConfig, ICloneable
{
public const string ModuleName = "LightSwitch";
@@ -27,21 +24,6 @@ namespace Settings.UI.Library
[JsonPropertyName("properties")]
public LightSwitchProperties Properties { get; set; }
public HotkeyAccessor[] GetAllHotkeyAccessors()
{
var hotkeyAccessors = new List<HotkeyAccessor>
{
new HotkeyAccessor(
() => Properties.ToggleThemeHotkey.Value,
value => Properties.ToggleThemeHotkey.Value = value ?? LightSwitchProperties.DefaultToggleThemeHotkey,
"LightSwitch_ThemeToggle_Shortcut"),
};
return hotkeyAccessors.ToArray();
}
public ModuleType GetModuleType() => ModuleType.LightSwitch;
public object Clone()
{
return new LightSwitchSettings()
@@ -59,7 +41,6 @@ namespace Settings.UI.Library
SunsetOffset = new IntProperty((int)Properties.SunsetOffset.Value),
Latitude = new StringProperty(Properties.Latitude.Value),
Longitude = new StringProperty(Properties.Longitude.Value),
ToggleThemeHotkey = new KeyboardKeysProperty(Properties.ToggleThemeHotkey.Value),
},
};
}

View File

@@ -0,0 +1,37 @@
// 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.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.Converters
{
public partial class EnumToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null || parameter == null)
{
return Visibility.Collapsed;
}
string enumString = value.ToString();
string targetString = parameter.ToString();
return enumString.Equals(targetString, StringComparison.OrdinalIgnoreCase)
? Visibility.Visible
: Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}

View File

@@ -17,175 +17,143 @@
AutomationProperties.LandmarkType="Main"
mc:Ignorable="d">
<Page.Resources>
<converters:EnumToVisibilityConverter x:Key="EnumToVisibilityConverter" />
<converters:TimeSpanToFriendlyTimeConverter x:Key="TimeSpanToFriendlyTimeConverter" />
</Page.Resources>
<Grid>
<controls:SettingsPageControl
x:Uid="LightSwitch"
IsTabStop="False"
ModuleImageSource="ms-appx:///Assets/Settings/Modules/LightSwitch.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
x:Uid="LightSwitch_EnableSettingsCard"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/LightSwitch.png}"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch AutomationProperties.AutomationId="Toggle_LightSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>
<controls:SettingsPageControl
x:Uid="LightSwitch"
IsTabStop="False"
ModuleImageSource="ms-appx:///Assets/Settings/Modules/LightSwitch.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
x:Uid="LightSwitch_EnableSettingsCard"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/LightSwitch.png}"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch AutomationProperties.AutomationId="Toggle_LightSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>
<controls:SettingsGroup x:Uid="LightSwitch_ShortcutsSettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="LightSwitch_ThemeToggle_Shortcut" HeaderIcon="{ui:FontIcon Glyph=&#xE708;}">
<controls:ShortcutControl
MinWidth="{StaticResource SettingActionControlMinWidth}"
AllowDisable="True"
AutomationProperties.AutomationId="Shortcut_LightSwitch"
HotkeySettings="{x:Bind Path=ViewModel.ToggleThemeActivationShortcut, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="LightSwitch_ShortcutsSettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="LightSwitch_ThemeToggle_Shortcut" HeaderIcon="{ui:FontIcon Glyph=&#xE708;}">
<controls:ShortcutControl
MinWidth="{StaticResource SettingActionControlMinWidth}"
AllowDisable="True"
AutomationProperties.AutomationId="Shortcut_LightSwitch"
HotkeySettings="{x:Bind Path=ViewModel.ToggleThemeActivationShortcut, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="LightSwitch_ScheduleSettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
x:Uid="LightSwitch_ModeSettingsExpander"
HeaderIcon="{ui:FontIcon Glyph=&#xE823;}"
IsExpanded="True">
<ComboBox
x:Name="ModeSelector"
AutomationProperties.AutomationId="ModeSelection_LightSwitch"
SelectedValue="{x:Bind ViewModel.ScheduleMode, Mode=TwoWay}"
SelectedValuePath="Tag"
SelectionChanged="ModeSelector_SelectionChanged">
<ComboBoxItem
x:Uid="LightSwitch_ModeOff"
AutomationProperties.AutomationId="OffCBItem_LightSwitch"
Tag="Off" />
<ComboBoxItem
x:Uid="LightSwitch_ModeManual"
AutomationProperties.AutomationId="ManualCBItem_LightSwitch"
Tag="FixedHours" />
<ComboBoxItem
x:Uid="LightSwitch_ModeSunsetToSunrise"
AutomationProperties.AutomationId="SunCBItem_LightSwitch"
Tag="SunsetToSunrise" />
</ComboBox>
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard
x:Name="Fixed_TurnOnCard"
x:Uid="LightSwitch_TurnOnDarkMode"
Visibility="Collapsed">
<TimePicker AutomationProperties.AutomationId="DarkTimePicker" Time="{x:Bind ViewModel.DarkTimePickerValue, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Name="Fixed_TurnOffCard"
x:Uid="LightSwitch_TurnOffDarkMode"
Visibility="Collapsed">
<TimePicker AutomationProperties.AutomationId="LightTimePicker" Time="{x:Bind ViewModel.LightTimePickerValue, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<controls:SettingsGroup x:Uid="LightSwitch_ScheduleSettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
x:Uid="LightSwitch_ModeSettingsExpander"
HeaderIcon="{ui:FontIcon Glyph=&#xE823;}"
IsExpanded="True">
<ComboBox
x:Name="ModeSelector"
AutomationProperties.AutomationId="ModeSelection_LightSwitch"
SelectedValue="{x:Bind ViewModel.ScheduleMode, Mode=TwoWay}"
SelectedValuePath="Tag"
SelectionChanged="ModeSelector_SelectionChanged">
<ComboBoxItem
x:Uid="LightSwitch_ModeManual"
AutomationProperties.AutomationId="ManualCBItem_LightSwitch"
Tag="FixedHours" />
<ComboBoxItem
x:Uid="LightSwitch_ModeSunsetToSunrise"
AutomationProperties.AutomationId="SunCBItem_LightSwitch"
Tag="SunsetToSunrise" />
</ComboBox>
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard x:Uid="LightSwitch_TurnOnDarkMode" Visibility="{x:Bind ViewModel.ScheduleMode, Mode=OneWay, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=FixedHours}">
<TimePicker AutomationProperties.AutomationId="DarkTimePicker" Time="{x:Bind ViewModel.DarkTimePickerValue, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="LightSwitch_TurnOffDarkMode" Visibility="{x:Bind ViewModel.ScheduleMode, Mode=OneWay, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=FixedHours}">
<TimePicker AutomationProperties.AutomationId="LightTimePicker" Time="{x:Bind ViewModel.LightTimePickerValue, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Name="SunLocation_Card"
x:Uid="LightSwitch_LocationSettingsCard"
Visibility="Collapsed">
<tkcontrols:SettingsCard x:Uid="LightSwitch_LocationSettingsCard" Visibility="{x:Bind ViewModel.ScheduleMode, Mode=OneWay, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=SunsetToSunrise}">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.SyncButtonInformation, Mode=OneWay}" />
<Button
Padding="8"
AutomationProperties.AutomationId="SetLocationButton_LightSwitch"
Click="SyncLocationButton_Click"
Content="{ui:FontIcon Glyph=&#xECAF;,
FontSize=16}" />
</StackPanel>
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="LightSwitch_OffsetSettingsCard" Visibility="{x:Bind ViewModel.ScheduleMode, Mode=OneWay, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=SunsetToSunrise}">
<StackPanel Orientation="Horizontal" Spacing="20">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.SyncButtonInformation, Mode=OneWay}" />
<Button
Padding="8"
AutomationProperties.AutomationId="SetLocationButton_LightSwitch"
Click="SyncLocationButton_Click"
Content="{ui:FontIcon Glyph=&#xECAF;,
FontSize=16}" />
<!--<FontIcon Glyph="&#xED39;" FontSize="16" />-->
<controls:IsEnabledTextBlock x:Uid="LightSwitch_SunriseText" VerticalAlignment="Center" />
<NumberBox
AutomationProperties.AutomationId="SunriseOffset_LightSwitch"
Maximum="60"
Minimum="-60"
SpinButtonPlacementMode="Compact"
Value="{x:Bind ViewModel.SunriseOffset, Mode=TwoWay}" />
</StackPanel>
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Name="SunOffset_Card"
x:Uid="LightSwitch_OffsetSettingsCard"
Visibility="Collapsed">
<StackPanel Orientation="Horizontal" Spacing="20">
<StackPanel Orientation="Horizontal" Spacing="8">
<!--<FontIcon Glyph="&#xED39;" FontSize="16" />-->
<controls:IsEnabledTextBlock x:Uid="LightSwitch_SunriseText" VerticalAlignment="Center" />
<NumberBox
AutomationProperties.AutomationId="SunriseOffset_LightSwitch"
Maximum="60"
Minimum="-60"
SpinButtonPlacementMode="Compact"
Value="{x:Bind ViewModel.SunriseOffset, Mode=TwoWay}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<controls:IsEnabledTextBlock x:Uid="LightSwitch_SunsetText" VerticalAlignment="Center" />
<NumberBox
AutomationProperties.AutomationId="SunsetOffset_LightSwitch"
Maximum="60"
Minimum="-60"
SpinButtonPlacementMode="Compact"
Value="{x:Bind ViewModel.SunsetOffset, Mode=TwoWay}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<controls:IsEnabledTextBlock x:Uid="LightSwitch_SunsetText" VerticalAlignment="Center" />
<NumberBox
AutomationProperties.AutomationId="SunsetOffset_LightSwitch"
Maximum="60"
Minimum="-60"
SpinButtonPlacementMode="Compact"
Value="{x:Bind ViewModel.SunsetOffset, Mode=TwoWay}" />
</StackPanel>
</StackPanel>
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Name="TimelineCard"
HorizontalContentAlignment="Stretch"
ContentAlignment="Vertical">
<controls:Timeline
Margin="0,24,0,24"
AutomationProperties.AutomationId="Timeline_LightSwitch"
EndTime="{x:Bind ViewModel.DarkTimeTimeSpan, Mode=OneWay}"
StartTime="{x:Bind ViewModel.LightTimeTimeSpan, Mode=OneWay}"
Sunrise="{x:Bind ViewModel.SunriseTimeSpan, Mode=OneWay}"
Sunset="{x:Bind ViewModel.SunsetTimeSpan, Mode=OneWay}" />
</tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
<InfoBar
x:Name="LocationWarningBar"
x:Uid="LightSwitch_LocationWarningBar"
IsOpen="True"
Severity="Informational"
Visibility="Collapsed" />
<controls:SettingsGroup x:Uid="LightSwitch_BehaviorSettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
x:Uid="LightSwitch_ApplyDarkModeExpander"
HeaderIcon="{ui:FontIcon Glyph=&#xE790;}"
IsExpanded="True">
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard HorizontalContentAlignment="Stretch" ContentAlignment="Left">
<controls:CheckBoxWithDescriptionControl
x:Uid="LightSwitch_SystemCheckbox"
AutomationProperties.AutomationId="ChangeSystemCheckbox_LightSwitch"
IsChecked="{x:Bind ViewModel.ChangeSystem, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Name="TimelineCard"
HorizontalContentAlignment="Stretch"
ContentAlignment="Vertical"
Visibility="Collapsed">
<controls:Timeline
Margin="0,24,0,24"
AutomationProperties.AutomationId="Timeline_LightSwitch"
EndTime="{x:Bind ViewModel.DarkTimeTimeSpan, Mode=OneWay}"
StartTime="{x:Bind ViewModel.LightTimeTimeSpan, Mode=OneWay}"
Sunrise="{x:Bind ViewModel.SunriseTimeSpan, Mode=OneWay}"
Sunset="{x:Bind ViewModel.SunsetTimeSpan, Mode=OneWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Name="NoScheduleCard"
Padding="0"
HorizontalContentAlignment="Stretch"
Background="{ThemeResource InfoBarInformationalSeverityBackgroundBrush}"
ContentAlignment="Vertical"
Visibility="Visible">
<InfoBar
x:Uid="LightSwitch_ScheduleOffMessage"
Background="Transparent"
BorderThickness="0"
IsClosable="False"
IsOpen="True"
Severity="Informational" />
<tkcontrols:SettingsCard HorizontalContentAlignment="Stretch" ContentAlignment="Left">
<controls:CheckBoxWithDescriptionControl
x:Uid="LightSwitch_AppsCheckbox"
AutomationProperties.AutomationId="ChangeAppsCheckbox_LightSwitch"
IsChecked="{x:Bind ViewModel.ChangeApps, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
<InfoBar
x:Name="LocationWarningBar"
x:Uid="LightSwitch_LocationWarningBar"
IsOpen="True"
Severity="Informational"
Visibility="Collapsed" />
<controls:SettingsGroup x:Uid="LightSwitch_BehaviorSettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
x:Uid="LightSwitch_ApplyDarkModeExpander"
HeaderIcon="{ui:FontIcon Glyph=&#xE790;}"
IsExpanded="True">
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard HorizontalContentAlignment="Stretch" ContentAlignment="Left">
<controls:CheckBoxWithDescriptionControl
x:Uid="LightSwitch_SystemCheckbox"
AutomationProperties.AutomationId="ChangeSystemCheckbox_LightSwitch"
IsChecked="{x:Bind ViewModel.ChangeSystem, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard HorizontalContentAlignment="Stretch" ContentAlignment="Left">
<controls:CheckBoxWithDescriptionControl
x:Uid="LightSwitch_AppsCheckbox"
AutomationProperties.AutomationId="ChangeAppsCheckbox_LightSwitch"
IsChecked="{x:Bind ViewModel.ChangeApps, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
</controls:SettingsGroup>
<!-- Force mode buttons -->
<!--<tkcontrols:SettingsCard
</controls:SettingsGroup>
<!-- Force mode buttons -->
<!--<tkcontrols:SettingsCard
Header="Force mode now"
HeaderIcon="{ui:FontIcon Glyph=&#xE706;}"
Description="Apply light or dark mode immediately">
@@ -199,21 +167,21 @@
</StackPanel>
</tkcontrols:SettingsCard>-->
<ContentDialog
x:Name="LocationDialog"
x:Uid="LightSwitch_LocationDialog"
IsPrimaryButtonEnabled="True"
IsSecondaryButtonEnabled="True"
Opened="LocationDialog_Opened"
PrimaryButtonClick="LocationDialog_PrimaryButtonClick"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}">
<Grid RowSpacing="48">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock x:Uid="LightSwitch_LocationDialog_Description" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<!--<AutoSuggestBox
<ContentDialog
x:Name="LocationDialog"
x:Uid="LightSwitch_LocationDialog"
IsPrimaryButtonEnabled="True"
IsSecondaryButtonEnabled="True"
Opened="LocationDialog_Opened"
PrimaryButtonClick="LocationDialog_PrimaryButtonClick"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}">
<Grid RowSpacing="48">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock x:Uid="LightSwitch_LocationDialog_Description" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<!--<AutoSuggestBox
x:Name="CityAutoSuggestBox"
Grid.Row="1"
Margin="0,16,0,8"
@@ -240,122 +208,113 @@
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>-->
<StackPanel
Grid.Row="2"
Margin="0,24,0,0"
HorizontalAlignment="Center"
Orientation="Vertical"
Spacing="32">
<Button
x:Name="SyncButton"
HorizontalAlignment="Stretch"
AutomationProperties.AutomationId="SyncLocationButton_LightSwitch"
Style="{StaticResource AccentButtonStyle}"
Visibility="Collapsed">
<StackPanel Orientation="Horizontal" Spacing="8">
<FontIcon FontSize="14" Glyph="&#xECAF;" />
<TextBlock x:Uid="LightSwitch_GetCurrentLocation" />
</StackPanel>
</Button>
</StackPanel>
<ProgressRing
x:Name="SyncLoader"
Grid.Row="1"
Width="40"
Height="40"
VerticalAlignment="Center"
IsActive="False"
Visibility="Collapsed" />
<Grid
x:Name="LocationResultPanel"
Grid.Row="1"
VerticalAlignment="Bottom"
ColumnSpacing="16"
RowSpacing="12"
<StackPanel
Grid.Row="2"
Margin="0,24,0,0"
HorizontalAlignment="Center"
Orientation="Vertical"
Spacing="32">
<Button
x:Name="SyncButton"
HorizontalAlignment="Stretch"
AutomationProperties.AutomationId="SyncLocationButton_LightSwitch"
Style="{StaticResource AccentButtonStyle}"
Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<FontIcon FontSize="16" Glyph="&#xECAF;">
<ToolTipService.ToolTip>
<TextBlock x:Uid="LightSwitch_LocationTooltip" />
</ToolTipService.ToolTip>
</FontIcon>
<TextBlock
Grid.Row="1"
AutomationProperties.AutomationId="LocationResultText_LightSwitch"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextAlignment="Center">
<Run Text="{x:Bind ViewModel.Latitude, Mode=OneWay}" /><Run Text="°, " />
<Run Text="{x:Bind ViewModel.Longitude, Mode=OneWay}" /><Run Text="°" />
</TextBlock>
<FontIcon
Grid.Column="1"
FontSize="20"
Glyph="&#xED39;">
<ToolTipService.ToolTip>
<TextBlock x:Uid="LightSwitch_SunriseTooltip" />
</ToolTipService.ToolTip>
</FontIcon>
<TextBlock
Grid.Row="1"
Grid.Column="1"
AutomationProperties.AutomationId="SunriseText_LightSwitch"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.LightTimeTimeSpan, Converter={StaticResource TimeSpanToFriendlyTimeConverter}, Mode=OneWay}"
TextAlignment="Center" />
<FontIcon
Grid.Column="2"
FontSize="20"
Glyph="&#xED3A;">
<ToolTipService.ToolTip>
<TextBlock x:Uid="LightSwitch_SunsetTooltip" />
</ToolTipService.ToolTip>
</FontIcon>
<TextBlock
Grid.Row="2"
Grid.Column="2"
AutomationProperties.AutomationId="SunsetText_LightSwitch"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.DarkTimeTimeSpan, Converter={StaticResource TimeSpanToFriendlyTimeConverter}, Mode=OneWay}"
TextAlignment="Center" />
</Grid>
</Grid>
</ContentDialog>
</controls:SettingsGroup>
<StackPanel Orientation="Horizontal" Spacing="8">
<FontIcon FontSize="14" Glyph="&#xECAF;" />
<TextBlock x:Uid="LightSwitch_GetCurrentLocation" />
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_LightSwitch" Link="https://aka.ms/PowerToysOverview_LightSwitch" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScheduleModeStates">
<VisualState x:Name="OffState" />
<VisualState x:Name="SunsetToSunriseState">
<VisualState.Setters>
<Setter Target="SunLocation_Card.Visibility" Value="Visible" />
<Setter Target="SunOffset_Card.Visibility" Value="Visible" />
<Setter Target="NoScheduleCard.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="ManualState">
<VisualState.Setters>
<Setter Target="Fixed_TurnOnCard.Visibility" Value="Visible" />
<Setter Target="Fixed_TurnOffCard.Visibility" Value="Visible" />
<Setter Target="NoScheduleCard.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
<ProgressRing
x:Name="SyncLoader"
Grid.Row="1"
Width="40"
Height="40"
VerticalAlignment="Center"
IsActive="False"
Visibility="Collapsed" />
<Grid
x:Name="LocationResultPanel"
Grid.Row="1"
VerticalAlignment="Bottom"
ColumnSpacing="16"
RowSpacing="12"
Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<FontIcon FontSize="16" Glyph="&#xECAF;">
<ToolTipService.ToolTip>
<TextBlock x:Uid="LightSwitch_LocationTooltip" />
</ToolTipService.ToolTip>
</FontIcon>
<TextBlock
Grid.Row="1"
AutomationProperties.AutomationId="LocationResultText_LightSwitch"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextAlignment="Center">
<Run Text="{x:Bind ViewModel.Latitude, Mode=OneWay}" /><Run Text="°, " />
<Run Text="{x:Bind ViewModel.Longitude, Mode=OneWay}" /><Run Text="°" />
</TextBlock>
<FontIcon
Grid.Column="1"
FontSize="20"
Glyph="&#xED39;">
<ToolTipService.ToolTip>
<TextBlock x:Uid="LightSwitch_SunriseTooltip" />
</ToolTipService.ToolTip>
</FontIcon>
<TextBlock
Grid.Row="1"
Grid.Column="1"
AutomationProperties.AutomationId="SunriseText_LightSwitch"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.LightTimeTimeSpan, Converter={StaticResource TimeSpanToFriendlyTimeConverter}, Mode=OneWay}"
TextAlignment="Center" />
<FontIcon
Grid.Column="2"
FontSize="20"
Glyph="&#xED3A;">
<ToolTipService.ToolTip>
<TextBlock x:Uid="LightSwitch_SunsetTooltip" />
</ToolTipService.ToolTip>
</FontIcon>
<TextBlock
Grid.Row="2"
Grid.Column="2"
AutomationProperties.AutomationId="SunsetText_LightSwitch"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.DarkTimeTimeSpan, Converter={StaticResource TimeSpanToFriendlyTimeConverter}, Mode=OneWay}"
TextAlignment="Center" />
</Grid>
</Grid>
</ContentDialog>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_LightSwitch" Link="https://aka.ms/PowerToysOverview_LightSwitch" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LocationEnabledStates">
<VisualState x:Name="LocationSet" />
<VisualState x:Name="LocationNotSet">
<VisualState.Setters>
<Setter Target="TimelineCard.Visibility" Value="Collapsed" />
<Setter Target="LocationWarningBar.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Page>

View File

@@ -73,7 +73,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
this.InitializeComponent();
this.Loaded += LightSwitchPage_Loaded;
this.Loaded += (s, e) => ViewModel.OnPageLoaded();
}
private void LightSwitchPage_Loaded(object sender, RoutedEventArgs e)
@@ -300,20 +299,20 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private void ModeSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
switch (ViewModel.ScheduleMode)
SunriseModeChartState();
}
private void SunriseModeChartState()
{
if (ViewModel.Latitude == "0.0" && ViewModel.Longitude == "0.0" && ViewModel.ScheduleMode == "SunsetToSunrise")
{
case "FixedHours":
VisualStateManager.GoToState(this, "ManualState", true);
TimelineCard.Visibility = Visibility.Visible;
break;
case "SunsetToSunrise":
VisualStateManager.GoToState(this, "SunsetToSunriseState", true);
SunriseModeChartState();
break;
default:
VisualStateManager.GoToState(this, "OffState", true);
TimelineCard.Visibility = Visibility.Collapsed;
break;
TimelineCard.Visibility = Visibility.Collapsed;
LocationWarningBar.Visibility = Visibility.Visible;
}
else
{
TimelineCard.Visibility = Visibility.Visible;
LocationWarningBar.Visibility = Visibility.Collapsed;
}
}
@@ -321,19 +320,5 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
await GetGeoLocation();
}
private void SunriseModeChartState()
{
if (ViewModel.Latitude != "0.0" && ViewModel.Longitude != "0.0")
{
TimelineCard.Visibility = Visibility.Visible;
LocationWarningBar.Visibility = Visibility.Collapsed;
}
else
{
TimelineCard.Visibility = Visibility.Collapsed;
LocationWarningBar.Visibility = Visibility.Visible;
}
}
}
}

View File

@@ -177,9 +177,6 @@
AutomationProperties.AutomationId="SystemToolsNavItem"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/SystemTools.png}"
SelectsOnInvoked="False">
<NavigationViewItem.InfoBadge>
<InfoBadge Style="{StaticResource NewInfoBadge}" />
</NavigationViewItem.InfoBadge>
<NavigationViewItem.MenuItems>
<NavigationViewItem
x:Name="AdvancedPasteNavigationItem"
@@ -210,11 +207,7 @@
x:Uid="Shell_LightSwitch"
helpers:NavHelper.NavigateTo="views:LightSwitchPage"
AutomationProperties.AutomationId="LightSwitchNavItem"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/LightSwitch.png}">
<NavigationViewItem.InfoBadge>
<InfoBadge Style="{StaticResource NewInfoBadge}" />
</NavigationViewItem.InfoBadge>
</NavigationViewItem>
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/LightSwitch.png}" />
<NavigationViewItem
x:Name="PowerLauncherNavigationItem"
x:Uid="Shell_PowerLauncher"

View File

@@ -5269,18 +5269,12 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
<data name="LightSwitch_ModeSettingsExpander.Description" xml:space="preserve">
<value>Determine when dark mode should be turned on</value>
</data>
<data name="LightSwitch_ModeOff.Content" xml:space="preserve">
<value>Off</value>
</data>
<data name="LightSwitch_ModeManual.Content" xml:space="preserve">
<value>Fixed hours</value>
<value>Manual</value>
</data>
<data name="LightSwitch_ModeSunsetToSunrise.Content" xml:space="preserve">
<value>Sunset to sunrise</value>
</data>
<data name="LightSwitch_ScheduleOffMessage.Title" xml:space="preserve">
<value>Scheduling is turned off.</value>
</data>
<data name="LightSwitch_TurnOnDarkMode.Header" xml:space="preserve">
<value>Turn on dark mode</value>
</data>

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
@@ -21,10 +20,8 @@ using Settings.UI.Library.Helpers;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public partial class LightSwitchViewModel : PageViewModelBase
public partial class LightSwitchViewModel : Observable
{
protected override string ModuleName => LightSwitchSettings.ModuleName;
private Func<string, int> SendConfigMSG { get; }
public ObservableCollection<SearchLocation> SearchLocations { get; } = new();
@@ -38,25 +35,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
ForceDarkCommand = new RelayCommand(ForceDarkNow);
AvailableScheduleModes = new ObservableCollection<string>
{
"Off",
"FixedHours",
"SunsetToSunrise",
};
{
"FixedHours",
"SunsetToSunrise",
};
_toggleThemeHotkey = _moduleSettings.Properties.ToggleThemeHotkey.Value;
}
public override Dictionary<string, HotkeySettings[]> GetAllHotkeySettings()
{
var hotkeysDict = new Dictionary<string, HotkeySettings[]>
{
[ModuleName] = [ToggleThemeActivationShortcut],
};
return hotkeysDict;
}
private void ForceLightNow()
{
Logger.LogInfo("Sending custom action: forceLight");
@@ -409,21 +395,22 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
public HotkeySettings ToggleThemeActivationShortcut
{
get => ModuleSettings.Properties.ToggleThemeHotkey.Value;
get => _toggleThemeHotkey;
set
{
if (value != ModuleSettings.Properties.ToggleThemeHotkey.Value)
if (value != _toggleThemeHotkey)
{
if (value == null)
{
ModuleSettings.Properties.ToggleThemeHotkey.Value = LightSwitchProperties.DefaultToggleThemeHotkey;
_toggleThemeHotkey = LightSwitchProperties.DefaultToggleThemeHotkey;
}
else
{
ModuleSettings.Properties.ToggleThemeHotkey.Value = value;
_toggleThemeHotkey = value;
}
_moduleSettings.Properties.ToggleThemeHotkey.Value = _toggleThemeHotkey;
NotifyPropertyChanged();
SendConfigMSG(
@@ -431,7 +418,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
CultureInfo.InvariantCulture,
"{{ \"powertoys\": {{ \"{0}\": {1} }} }}",
LightSwitchSettings.ModuleName,
JsonSerializer.Serialize(_moduleSettings, SourceGenerationContextContext.Default.LightSwitchSettings)));
JsonSerializer.Serialize(_moduleSettings, (System.Text.Json.Serialization.Metadata.JsonTypeInfo<LightSwitchSettings>)SourceGenerationContextContext.Default.LightSwitchSettings)));
}
}
}

View File

@@ -19,13 +19,13 @@ void XmlDocumentEx::Print(winrt::Windows::Data::Xml::Dom::IXmlNode node, int ind
PrintTagWithAttributes(node);
if (!node.HasChildNodes())
{
stream << L"</" << node.NodeName().c_str() << ">" << std::endl;
stream << L"<\\" << node.NodeName().c_str() << ">" << std::endl;
return;
}
if (node.ChildNodes().Size() == 1 && !node.FirstChild().HasChildNodes())
{
stream << node.InnerText().c_str() << L"</" << node.NodeName().c_str() << ">" << std::endl;
stream << node.InnerText().c_str() << L"<\\" << node.NodeName().c_str() << ">" << std::endl;
return;
}
@@ -40,7 +40,7 @@ void XmlDocumentEx::Print(winrt::Windows::Data::Xml::Dom::IXmlNode node, int ind
{
stream << " ";
}
stream << L"</" << node.NodeName().c_str() << ">" << std::endl;
stream << L"<\\" << node.NodeName().c_str() << ">" << std::endl;
}
void XmlDocumentEx::PrintTagWithAttributes(winrt::Windows::Data::Xml::Dom::IXmlNode node)

View File

@@ -52,8 +52,10 @@ function RunMSBuild {
$base = @(
$Solution
"/m"
"/p:Platform=$Platform"
"/p:Configuration=$Configuration"
"/p:BuildInParallel=true"
"/verbosity:normal"
'/clp:Summary;PerformanceSummary;ErrorsOnly;WarningsOnly'
"/fileLoggerParameters:LogFile=$allLog;Verbosity=detailed"
@@ -92,9 +94,7 @@ function RestoreThenBuild {
RunMSBuild $Solution $restoreArgs $Platform $Configuration
if (-not $RestoreOnly) {
$buildArgs = '/m'
if ($ExtraArgs) { $buildArgs = "$buildArgs $ExtraArgs" }
RunMSBuild $Solution $buildArgs $Platform $Configuration
RunMSBuild $Solution $ExtraArgs $Platform $Configuration
}
}
@@ -133,9 +133,7 @@ function BuildProjectsInDirectory {
if ($f.Extension -eq '.sln') {
RestoreThenBuild $f.FullName $ExtraArgs $Platform $Configuration $RestoreOnly
} else {
$buildArgs = '/m'
if ($ExtraArgs) { $buildArgs = "$buildArgs $ExtraArgs" }
RunMSBuild $f.FullName $buildArgs $Platform $Configuration
RunMSBuild $f.FullName $ExtraArgs $Platform $Configuration
}
}

View File

@@ -63,6 +63,7 @@ if ($ForceRebuildExecutable -or -not (Test-Path $exePath)) {
'/m',
"/p:Configuration=$BuildConfiguration",
"/p:Platform=x64",
"/p:BuildInParallel=true",
'/restore'
)