From a4b950210fbd962dbaa50d14b950e4c3dfacdcda Mon Sep 17 00:00:00 2001 From: vanzue Date: Fri, 12 Dec 2025 16:40:04 +0800 Subject: [PATCH] awake tweak --- .../Awake/RefreshAwakeStatusCommand.cs | 39 +++++++++++++++++++ .../Commands/Awake/StartAwakeCommand.cs | 17 ++++++-- .../Commands/Awake/StopAwakeCommand.cs | 15 +++++-- .../Helpers/AwakeCommandsFactory.cs | 28 +++++++++++-- .../Helpers/AwakeStatusService.cs | 24 ++++++++---- .../Modules/AwakeModuleCommandProvider.cs | 28 +++++++++++++ 6 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/RefreshAwakeStatusCommand.cs diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/RefreshAwakeStatusCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/RefreshAwakeStatusCommand.cs new file mode 100644 index 0000000000..43e942cfed --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/RefreshAwakeStatusCommand.cs @@ -0,0 +1,39 @@ +// 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 Microsoft.CommandPalette.Extensions.Toolkit; +using PowerToysExtension.Helpers; + +namespace PowerToysExtension.Commands; + +internal sealed partial class RefreshAwakeStatusCommand : InvokableCommand +{ + private readonly Action _applySubtitle; + + internal RefreshAwakeStatusCommand(Action applySubtitle) + { + ArgumentNullException.ThrowIfNull(applySubtitle); + _applySubtitle = applySubtitle; + Name = "Refresh Awake status"; + } + + public override CommandResult Invoke() + { + try + { + var subtitle = AwakeStatusService.GetStatusSubtitle(); + _applySubtitle(subtitle); + return CommandResult.KeepOpen(); + } + catch (Exception ex) + { + return CommandResult.ShowToast(new ToastArgs() + { + Message = $"Failed to refresh Awake status: {ex.Message}", + Result = CommandResult.KeepOpen(), + }); + } + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/StartAwakeCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/StartAwakeCommand.cs index b46b0301e7..fa1f82bf47 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/StartAwakeCommand.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/StartAwakeCommand.cs @@ -32,14 +32,25 @@ internal sealed partial class StartAwakeCommand : InvokableCommand var result = _action().GetAwaiter().GetResult(); if (!result.Success) { - return CommandResult.ShowToast(result.Error ?? "Failed to start Awake."); + return ShowToastKeepOpen(result.Error ?? "Failed to start Awake."); } - return string.IsNullOrWhiteSpace(_successToast) ? CommandResult.Hide() : CommandResult.ShowToast(_successToast); + return string.IsNullOrWhiteSpace(_successToast) + ? CommandResult.KeepOpen() + : ShowToastKeepOpen(_successToast); } catch (Exception ex) { - return CommandResult.ShowToast($"Launching Awake failed: {ex.Message}"); + return ShowToastKeepOpen($"Launching Awake failed: {ex.Message}"); } } + + private static CommandResult ShowToastKeepOpen(string message) + { + return CommandResult.ShowToast(new ToastArgs() + { + Message = message, + Result = CommandResult.KeepOpen(), + }); + } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/StopAwakeCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/StopAwakeCommand.cs index 4d201f6084..b4e5d75111 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/StopAwakeCommand.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Commands/Awake/StopAwakeCommand.cs @@ -22,14 +22,23 @@ internal sealed partial class StopAwakeCommand : InvokableCommand var result = AwakeService.Instance.SetOffAsync().GetAwaiter().GetResult(); if (result.Success) { - return CommandResult.ShowToast("Awake switched to Off."); + return ShowToastKeepOpen("Awake switched to Off."); } - return CommandResult.ShowToast(result.Error ?? "Awake does not appear to be running."); + return ShowToastKeepOpen(result.Error ?? "Awake does not appear to be running."); } catch (Exception ex) { - return CommandResult.ShowToast($"Failed to switch Awake off: {ex.Message}"); + return ShowToastKeepOpen($"Failed to switch Awake off: {ex.Message}"); } } + + private static CommandResult ShowToastKeepOpen(string message) + { + return CommandResult.ShowToast(new ToastArgs() + { + Message = message, + Result = CommandResult.KeepOpen(), + }); + } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/AwakeCommandsFactory.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/AwakeCommandsFactory.cs index 2f6a04300e..e6cec1174e 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/AwakeCommandsFactory.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/AwakeCommandsFactory.cs @@ -71,14 +71,34 @@ internal static class AwakeCommandsFactory { var results = new List(); - var statusSubtitle = AwakeStatusService.BuildSubtitle(); - if (Matches("Current status", statusSubtitle, searchText)) + var statusSubtitle = AwakeStatusService.GetStatusSubtitle(); + if (Matches("Awake: Current status", statusSubtitle, searchText)) { - var statusItem = new ListItem(new CommandItem(new Commands.NoOpCommand("Awake status"))) + ListItem? statusItem = null; + var refreshCommand = new RefreshAwakeStatusCommand(subtitle => { - Title = "Current status", + if (statusItem is not null) + { + statusItem.Subtitle = subtitle; + } + }); + + var statusNoOp = new NoOpCommand(); + statusNoOp.Name = "Awake status"; + + statusItem = new ListItem(new CommandItem(statusNoOp)) + { + Title = "Awake: Current status", Subtitle = statusSubtitle, Icon = AwakeIcon, + MoreCommands = + [ + new CommandContextItem(refreshCommand) + { + Title = "Refresh status", + Subtitle = "Re-read current Awake state", + }, + ], }; results.Add(statusItem); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/AwakeStatusService.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/AwakeStatusService.cs index edd2de0423..5669f6e171 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/AwakeStatusService.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/AwakeStatusService.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text.Json; +using Common.UI; namespace PowerToysExtension.Helpers; @@ -47,7 +48,7 @@ internal static class AwakeStatusService return new AwakeStatusSnapshot(isRunning, mode, settings.Properties.KeepDisplayOn, duration, expiration); } - internal static string BuildSubtitle() + internal static string GetStatusSubtitle() { var snapshot = GetSnapshot(); if (!snapshot.IsRunning) @@ -55,16 +56,25 @@ internal static class AwakeStatusService return "Awake is idle"; } + if (snapshot.Mode == AwakeMode.Passive) + { + // When the PowerToys Awake module is enabled, the Awake process stays resident + // even in passive mode. In that case "idle" is correct. If the module is disabled, + // a running process implies a standalone/session keep-awake, so report as active. + return ModuleEnablementService.IsModuleEnabled(SettingsDeepLink.SettingsWindow.Awake) + ? "Awake is idle" + : "Active - session running"; + } + return snapshot.Mode switch { - AwakeMode.Passive => "Awake is idle", - AwakeMode.Indefinite => snapshot.KeepDisplayOn ? "Active � indefinite (display on)" : "Active � indefinite", + AwakeMode.Indefinite => snapshot.KeepDisplayOn ? "Active - indefinite (display on)" : "Active - indefinite", AwakeMode.Timed => snapshot.Duration is { } span - ? $"Active � timer {FormatDuration(span)}" - : "Active � timer", + ? $"Active - timer {FormatDuration(span)}" + : "Active - timer", AwakeMode.Expirable => snapshot.Expiration is { } expiry - ? $"Active � until {expiry.ToLocalTime():t}" - : "Active � scheduled", + ? $"Active - until {expiry.ToLocalTime():t}" + : "Active - scheduled", _ => "Awake is running", }; } 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 744e01b9e3..a050274b63 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 @@ -35,6 +35,34 @@ internal sealed class AwakeModuleCommandProvider : ModuleCommandProvider } // Direct commands surfaced in the PowerToys list page. + ListItem? statusItem = null; + var refreshCommand = new RefreshAwakeStatusCommand(subtitle => + { + if (statusItem is not null) + { + statusItem.Subtitle = subtitle; + } + }); + + var statusNoOp = new NoOpCommand(); + statusNoOp.Name = "Awake status"; + + statusItem = new ListItem(new CommandItem(statusNoOp)) + { + Title = "Awake: Current status", + Subtitle = AwakeStatusService.GetStatusSubtitle(), + Icon = icon, + MoreCommands = + [ + new CommandContextItem(refreshCommand) + { + Title = "Refresh status", + Subtitle = "Re-read current Awake state", + }, + ], + }; + items.Add(statusItem); + items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake indefinitely", () => AwakeService.Instance.SetIndefiniteAsync(), "Awake set to indefinite")) { Title = "Awake: Keep awake indefinitely",