diff --git a/.gitignore b/.gitignore index 1318abc22c..b8a09a865e 100644 --- a/.gitignore +++ b/.gitignore @@ -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 \ No newline at end of file +installer/*/*.wxs.bk diff --git a/src/modules/awake/Awake.ModuleServices/Awake.ModuleServices.csproj b/src/modules/awake/Awake.ModuleServices/Awake.ModuleServices.csproj index a4c7c6c997..52588938e4 100644 --- a/src/modules/awake/Awake.ModuleServices/Awake.ModuleServices.csproj +++ b/src/modules/awake/Awake.ModuleServices/Awake.ModuleServices.csproj @@ -15,5 +15,6 @@ + diff --git a/src/modules/awake/Awake.ModuleServices/AwakeService.cs b/src/modules/awake/Awake.ModuleServices/AwakeService.cs index c71066f285..c1b5bcbd55 100644 --- a/src/modules/awake/Awake.ModuleServices/AwakeService.cs +++ b/src/modules/awake/Awake.ModuleServices/AwakeService.cs @@ -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 SetIndefiniteAsync(CancellationToken cancellationToken = default) { - return InvokeCliAsync("-m indefinite"); + return UpdateSettingsAsync( + settings => + { + settings.Properties.Mode = AwakeMode.INDEFINITE; + settings.Properties.KeepDisplayOn = true; + }, + cancellationToken); } public Task 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 SetOffAsync(CancellationToken cancellationToken = default) { - return InvokeCliAsync("-m passive"); + return UpdateSettingsAsync( + settings => + { + settings.Properties.Mode = AwakeMode.PASSIVE; + }, + cancellationToken); } - private static Task InvokeCliAsync(string arguments) + private static Task UpdateSettingsAsync(Action 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.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}")); } } } diff --git a/src/modules/awake/Awake.ModuleServices/AwakeServiceJsonContext.cs b/src/modules/awake/Awake.ModuleServices/AwakeServiceJsonContext.cs new file mode 100644 index 0000000000..cfaeff5bed --- /dev/null +++ b/src/modules/awake/Awake.ModuleServices/AwakeServiceJsonContext.cs @@ -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 +{ +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Modules/AwakeModuleCommandProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Modules/AwakeModuleCommandProvider.cs index 52026d0bdb..ba4e72fb4d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Modules/AwakeModuleCommandProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Modules/AwakeModuleCommandProvider.cs @@ -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 BuildCommands() { - var title = SettingsDeepLink.SettingsWindow.Awake.ModuleDisplayName(); - var icon = SettingsDeepLink.SettingsWindow.Awake.ModuleIcon(); + var items = new List(); + var icon = IconHelpers.FromRelativePath("Assets\\Awake.png"); - var more = new List + // 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; } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Pages/PowerToysExtensionPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Pages/PowerToysExtensionPage.cs index 12f9d92cde..4dad6534bf 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Pages/PowerToysExtensionPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Pages/PowerToysExtensionPage.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 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", - }, ]; } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Properties/launchSettings.json b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Properties/launchSettings.json new file mode 100644 index 0000000000..c0037538b9 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "Microsoft.CmdPal.Ext.PowerToys (Package)": { + "commandName": "MsixPackage", + "doNotLaunchApp": true, + "nativeDebugging": false + }, + "Microsoft.CmdPal.Ext.PowerToys (Unpackaged)": { + "commandName": "Project" + } + } +}