awake tweak

This commit is contained in:
vanzue
2025-12-12 16:40:04 +08:00
parent e0ccac7550
commit a4b950210f
6 changed files with 134 additions and 17 deletions

View File

@@ -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<string> _applySubtitle;
internal RefreshAwakeStatusCommand(Action<string> 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(),
});
}
}
}

View File

@@ -32,14 +32,25 @@ internal sealed partial class StartAwakeCommand : InvokableCommand
var result = _action().GetAwaiter().GetResult(); var result = _action().GetAwaiter().GetResult();
if (!result.Success) 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) 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(),
});
}
} }

View File

@@ -22,14 +22,23 @@ internal sealed partial class StopAwakeCommand : InvokableCommand
var result = AwakeService.Instance.SetOffAsync().GetAwaiter().GetResult(); var result = AwakeService.Instance.SetOffAsync().GetAwaiter().GetResult();
if (result.Success) 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) 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(),
});
}
} }

View File

@@ -71,14 +71,34 @@ internal static class AwakeCommandsFactory
{ {
var results = new List<IListItem>(); var results = new List<IListItem>();
var statusSubtitle = AwakeStatusService.BuildSubtitle(); var statusSubtitle = AwakeStatusService.GetStatusSubtitle();
if (Matches("Current status", statusSubtitle, searchText)) 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, Subtitle = statusSubtitle,
Icon = AwakeIcon, Icon = AwakeIcon,
MoreCommands =
[
new CommandContextItem(refreshCommand)
{
Title = "Refresh status",
Subtitle = "Re-read current Awake state",
},
],
}; };
results.Add(statusItem); results.Add(statusItem);

View File

@@ -9,6 +9,7 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
using Common.UI;
namespace PowerToysExtension.Helpers; namespace PowerToysExtension.Helpers;
@@ -47,7 +48,7 @@ internal static class AwakeStatusService
return new AwakeStatusSnapshot(isRunning, mode, settings.Properties.KeepDisplayOn, duration, expiration); return new AwakeStatusSnapshot(isRunning, mode, settings.Properties.KeepDisplayOn, duration, expiration);
} }
internal static string BuildSubtitle() internal static string GetStatusSubtitle()
{ {
var snapshot = GetSnapshot(); var snapshot = GetSnapshot();
if (!snapshot.IsRunning) if (!snapshot.IsRunning)
@@ -55,16 +56,25 @@ internal static class AwakeStatusService
return "Awake is idle"; 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 return snapshot.Mode switch
{ {
AwakeMode.Passive => "Awake is idle", AwakeMode.Indefinite => snapshot.KeepDisplayOn ? "Active - indefinite (display on)" : "Active - indefinite",
AwakeMode.Indefinite => snapshot.KeepDisplayOn ? "Active <20> indefinite (display on)" : "Active <20> indefinite",
AwakeMode.Timed => snapshot.Duration is { } span AwakeMode.Timed => snapshot.Duration is { } span
? $"Active <EFBFBD> timer {FormatDuration(span)}" ? $"Active - timer {FormatDuration(span)}"
: "Active <EFBFBD> timer", : "Active - timer",
AwakeMode.Expirable => snapshot.Expiration is { } expiry AwakeMode.Expirable => snapshot.Expiration is { } expiry
? $"Active <EFBFBD> until {expiry.ToLocalTime():t}" ? $"Active - until {expiry.ToLocalTime():t}"
: "Active <EFBFBD> scheduled", : "Active - scheduled",
_ => "Awake is running", _ => "Awake is running",
}; };
} }

View File

@@ -35,6 +35,34 @@ internal sealed class AwakeModuleCommandProvider : ModuleCommandProvider
} }
// Direct commands surfaced in the PowerToys list page. // 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")) items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake indefinitely", () => AwakeService.Instance.SetIndefiniteAsync(), "Awake set to indefinite"))
{ {
Title = "Awake: Keep awake indefinitely", Title = "Awake: Keep awake indefinitely",