This commit is contained in:
vanzue
2025-11-29 19:49:22 +08:00
parent d32b8c2a50
commit 51a858d6b0
7 changed files with 122 additions and 60 deletions

3
.gitignore vendored
View File

@@ -56,6 +56,7 @@ project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
!src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
@@ -358,4 +359,4 @@ src/common/Telemetry/*.etl
/src/settings-ui/Settings.UI/Assets/Settings/search.index.json
# PowerToysInstaller Build Temp Files
installer/*/*.wxs.bk
installer/*/*.wxs.bk

View File

@@ -15,5 +15,6 @@
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
<ProjectReference Include="..\..\..\common\PowerToys.ModuleContracts\PowerToys.ModuleContracts.csproj" />
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
</ItemGroup>
</Project>

View File

@@ -2,9 +2,9 @@
// 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.Diagnostics;
using System.Text.Json;
using Common.UI;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using PowerToys.ModuleContracts;
namespace Awake.ModuleServices;
@@ -28,7 +28,13 @@ public sealed class AwakeService : ModuleServiceBase, IAwakeService
public Task<OperationResult> SetIndefiniteAsync(CancellationToken cancellationToken = default)
{
return InvokeCliAsync("-m indefinite");
return UpdateSettingsAsync(
settings =>
{
settings.Properties.Mode = AwakeMode.INDEFINITE;
settings.Properties.KeepDisplayOn = true;
},
cancellationToken);
}
public Task<OperationResult> SetTimedAsync(int minutes, CancellationToken cancellationToken = default)
@@ -38,42 +44,49 @@ public sealed class AwakeService : ModuleServiceBase, IAwakeService
return Task.FromResult(OperationResult.Fail("Minutes must be greater than zero."));
}
return InvokeCliAsync($"-m timed -t {minutes}");
return UpdateSettingsAsync(
settings =>
{
var totalMinutes = Math.Min(minutes, int.MaxValue);
settings.Properties.Mode = AwakeMode.TIMED;
settings.Properties.KeepDisplayOn = true;
settings.Properties.IntervalHours = (uint)(totalMinutes / 60);
settings.Properties.IntervalMinutes = (uint)(totalMinutes % 60);
},
cancellationToken);
}
public Task<OperationResult> SetOffAsync(CancellationToken cancellationToken = default)
{
return InvokeCliAsync("-m passive");
return UpdateSettingsAsync(
settings =>
{
settings.Properties.Mode = AwakeMode.PASSIVE;
},
cancellationToken);
}
private static Task<OperationResult> InvokeCliAsync(string arguments)
private static Task<OperationResult> UpdateSettingsAsync(Action<AwakeSettings> mutateSettings, CancellationToken cancellationToken)
{
try
{
var basePath = PowerToysPathResolver.GetPowerToysInstallPath();
if (string.IsNullOrWhiteSpace(basePath))
{
return Task.FromResult(OperationResult.Fail("PowerToys install path not found."));
}
cancellationToken.ThrowIfCancellationRequested();
var exePath = Path.Combine(basePath, "PowerToys.Awake.exe");
if (!File.Exists(exePath))
{
return Task.FromResult(OperationResult.Fail("Unable to locate PowerToys.Awake.exe."));
}
var settingsUtils = new SettingsUtils();
var settings = settingsUtils.GetSettingsOrDefault<AwakeSettings>(AwakeSettings.ModuleName);
var startInfo = new ProcessStartInfo(exePath, arguments)
{
UseShellExecute = false,
CreateNoWindow = true,
};
mutateSettings(settings);
Process.Start(startInfo);
settingsUtils.SaveSettings(JsonSerializer.Serialize(settings, AwakeServiceJsonContext.Default.AwakeSettings), AwakeSettings.ModuleName);
return Task.FromResult(OperationResult.Ok());
}
catch (OperationCanceledException)
{
return Task.FromResult(OperationResult.Fail("Awake update was cancelled."));
}
catch (Exception ex)
{
return Task.FromResult(OperationResult.Fail($"Failed to invoke Awake: {ex.Message}"));
return Task.FromResult(OperationResult.Fail($"Failed to update Awake settings: {ex.Message}"));
}
}
}

View File

@@ -0,0 +1,13 @@
// 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.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library;
namespace Awake.ModuleServices;
[JsonSerializable(typeof(AwakeSettings))]
internal sealed partial class AwakeServiceJsonContext : JsonSerializerContext
{
}

View File

@@ -8,6 +8,7 @@ using Common.UI;
using Microsoft.CommandPalette.Extensions.Toolkit;
using PowerToysExtension.Commands;
using PowerToysExtension.Helpers;
using PowerToysExtension.Pages;
namespace PowerToysExtension.Modules;
@@ -15,25 +16,65 @@ internal sealed class AwakeModuleCommandProvider : ModuleCommandProvider
{
public override IEnumerable<ListItem> BuildCommands()
{
var title = SettingsDeepLink.SettingsWindow.Awake.ModuleDisplayName();
var icon = SettingsDeepLink.SettingsWindow.Awake.ModuleIcon();
var items = new List<ListItem>();
var icon = IconHelpers.FromRelativePath("Assets\\Awake.png");
var more = new List<CommandContextItem>
// Settings entry with quick actions in MoreCommands.
var settingsTitle = SettingsDeepLink.SettingsWindow.Awake.ModuleDisplayName();
items.Add(new ListItem(new OpenInSettingsCommand(SettingsDeepLink.SettingsWindow.Awake, settingsTitle))
{
new CommandContextItem(new StartAwakeCommand("Awake: Keep awake indefinitely", () => AwakeService.Instance.SetIndefiniteAsync(), "Awake set to indefinite")),
new CommandContextItem(new StartAwakeCommand("Awake: Keep awake for 30 minutes", () => AwakeService.Instance.SetTimedAsync(30), "Awake set for 30 minutes")),
new CommandContextItem(new StartAwakeCommand("Awake: Keep awake for 2 hours", () => AwakeService.Instance.SetTimedAsync(120), "Awake set for 2 hours")),
new CommandContextItem(new StopAwakeCommand()),
};
var item = new ListItem(new OpenInSettingsCommand(SettingsDeepLink.SettingsWindow.Awake, title))
{
Title = title,
Title = settingsTitle,
Subtitle = "Open Awake settings",
Icon = icon,
MoreCommands = more.ToArray(),
};
Icon = SettingsDeepLink.SettingsWindow.Awake.ModuleIcon(),
MoreCommands =
[
new CommandContextItem(new StartAwakeCommand("Awake: Keep awake indefinitely", () => AwakeService.Instance.SetIndefiniteAsync(), "Awake set to indefinite")),
new CommandContextItem(new StartAwakeCommand("Awake: Keep awake for 30 minutes", () => AwakeService.Instance.SetTimedAsync(30), "Awake set for 30 minutes")),
new CommandContextItem(new StartAwakeCommand("Awake: Keep awake for 1 hour", () => AwakeService.Instance.SetTimedAsync(60), "Awake set for 1 hour")),
new CommandContextItem(new StartAwakeCommand("Awake: Keep awake for 2 hours", () => AwakeService.Instance.SetTimedAsync(120), "Awake set for 2 hours")),
new CommandContextItem(new StopAwakeCommand()),
new CommandContextItem(new AwakeProcessListPage()),
],
});
return [item];
// Direct commands surfaced in the PowerToys list page.
items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake indefinitely", () => AwakeService.Instance.SetIndefiniteAsync(), "Awake set to indefinite"))
{
Title = "Awake: Keep awake indefinitely",
Subtitle = "Run Awake in indefinite mode",
Icon = icon,
});
items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake for 30 minutes", () => AwakeService.Instance.SetTimedAsync(30), "Awake set for 30 minutes"))
{
Title = "Awake: Keep awake for 30 minutes",
Subtitle = "Run Awake timed for 30 minutes",
Icon = icon,
});
items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake for 1 hour", () => AwakeService.Instance.SetTimedAsync(60), "Awake set for 1 hour"))
{
Title = "Awake: Keep awake for 1 hour",
Subtitle = "Run Awake timed for 1 hour",
Icon = icon,
});
items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake for 2 hours", () => AwakeService.Instance.SetTimedAsync(120), "Awake set for 2 hours"))
{
Title = "Awake: Keep awake for 2 hours",
Subtitle = "Run Awake timed for 2 hours",
Icon = icon,
});
items.Add(new ListItem(new StopAwakeCommand())
{
Title = "Awake: Turn off",
Subtitle = "Switch Awake back to Off",
Icon = icon,
});
items.Add(new ListItem(new CommandItem(new AwakeProcessListPage()))
{
Title = "Bind Awake to another process",
Subtitle = "Stop automatically when the target process exits",
Icon = icon,
});
return items;
}
}

View File

@@ -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 Awake.ModuleServices;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using PowerToysExtension.Commands;
@@ -40,26 +41,6 @@ internal sealed partial class PowerToysExtensionPage : ListPage
Title = "Open Workspaces editor",
Subtitle = "Launch the Workspaces editor",
},
new ListItem(new StartAwakeCommand("Awake: Keep awake indefinitely", () => "-m indefinite", "Awake set to indefinite"))
{
Title = "Awake: Keep awake indefinitely",
Subtitle = "Run Awake in indefinite mode",
},
new ListItem(new StartAwakeCommand("Awake: Keep awake for 30 minutes", () => "-m timed -t 30", "Awake set for 30 minutes"))
{
Title = "Awake: Keep awake for 30 minutes",
Subtitle = "Run Awake timed for 30 minutes",
},
new ListItem(new StartAwakeCommand("Awake: Keep awake for 2 hours", () => "-m timed -t 120", "Awake set for 2 hours"))
{
Title = "Awake: Keep awake for 2 hours",
Subtitle = "Run Awake timed for 2 hours",
},
new ListItem(new StopAwakeCommand())
{
Title = "Awake: Turn off",
Subtitle = "Switch Awake back to Off",
},
];
}
}

View File

@@ -0,0 +1,12 @@
{
"profiles": {
"Microsoft.CmdPal.Ext.PowerToys (Package)": {
"commandName": "MsixPackage",
"doNotLaunchApp": true,
"nativeDebugging": false
},
"Microsoft.CmdPal.Ext.PowerToys (Unpackaged)": {
"commandName": "Project"
}
}
}