From 7cc4a16aa7727c64b61fdea1a66c8082e3cb4ed5 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 20:25:03 -0500 Subject: [PATCH] Add setting to select network speed units in Command Palette (#46320) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Adds a unit selection setting to the Performance Monitor extension in Command Palette that allows users to choose how network transmission speed is displayed. The setting offers three options: bits per second (Kbps/Mbps/Gbps, the default), bytes per second (KB/s/MB/s/GB/s), and binary bytes per second using IEC prefixes (KiB/s/MiB/s/GiB/s). ## PR Checklist - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments The following files were changed: - **`NetworkSpeedUnit.cs`** (new): Enum defining the three supported unit modes — `BitsPerSecond`, `BytesPerSecond`, and `BinaryBytesPerSecond`. - **`SettingsManager.cs`** (new): A `JsonSettingsManager` subclass for the Performance Monitor extension. Defines a `ChoiceSetSetting` for `NetworkSpeedUnit` (default: `BitsPerSecond`), stored under the `performanceMonitor` namespace in the shared CmdPal `settings.json`. - **`PerformanceWidgetsPage.cs`**: - `PerformanceWidgetsPage` constructor now accepts `SettingsManager` and passes it to `SystemNetworkUsageWidgetPage`. - `SystemNetworkUsageWidgetPage` stores the settings manager and calls `SpeedToString()`, which dispatches via a switch expression to `FormatAsBitsPerSecString()` (e.g. `12.5 Mbps`), `FormatAsBytesPerSecString()` (e.g. `1.6 MB/s`), or `FormatAsBinaryBytesPerSecString()` (e.g. `1.5 MiB/s`) based on the selected unit. - **`PerformanceMonitorCommandsProvider.cs`**: Holds the `SettingsManager`, passes it to both the list page and dock band via `SetEnabledState()`, exposes `Settings` on the provider, and adds the settings page to the command's `MoreCommands`. The crash-recovery hardening from main (`ProviderCrashSentinel`, `TryReactivateImmediately`, `SetDisabledState`, thread-safe locking) is fully preserved and integrated with the settings manager. - **`Resources.resw`**: Updated `Network_Speed_Unit_Setting_Title` and `Network_Speed_Unit_Setting_Description` to neutral language; added three choice label strings (`Network_Speed_Unit_BitsPerSec`, `Network_Speed_Unit_BytesPerSec`, `Network_Speed_Unit_BinaryBytesPerSec`). Also includes the disabled-state strings merged from main. ## Validation Steps Performed - Manually verified that the setting appears in the Performance Monitor extension's settings page (accessible via the ⋯ context menu on the Performance Monitor command item). - Verified that network speed values display in Kbps/Mbps/Gbps by default, switch to KB/s/MB/s/GB/s when the bytes option is selected, and switch to KiB/s/MiB/s/GiB/s when the binary bytes option is selected. - Setting persists across Command Palette restarts via the shared CmdPal settings file. - Verified that the crash-recovery re-enable flow correctly restores pages with the settings manager wired up.
Original prompt > > ---- > > *This section details on the original issue you should resolve* > > [Command Palette] Allows network transmission speed units to be switched between bits per second and bytes per second > ### Description of the new feature / enhancement > > Add a setting that allows network monitoring in the Command Palette Dock to be displayed in bytes per second. > > ### Scenario when this would be used? > > In everyday usage, byte units are more commonly used. > > ### Supporting information > > _No response_ > > ## Comments on the Issue (you are @copilot in this section) > > > @niels9001 > @copilot Can you add a setting for this? > >
- Fixes microsoft/PowerToys#46271 --- ✨ Let Copilot coding agent [set things up for you](https://github.com/microsoft/PowerToys/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com> --- .../NetworkSpeedUnit.cs | 20 ++++ .../PerformanceMonitorCommandsProvider.cs | 13 ++- .../PerformanceWidgetsPage.cs | 97 +++++++++++++++++-- .../SettingsManager.cs | 50 ++++++++++ .../Strings/en-US/Resources.resw | 15 +++ 5 files changed, 186 insertions(+), 9 deletions(-) create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/NetworkSpeedUnit.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/SettingsManager.cs diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/NetworkSpeedUnit.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/NetworkSpeedUnit.cs new file mode 100644 index 0000000000..0578bb1d88 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/NetworkSpeedUnit.cs @@ -0,0 +1,20 @@ +// 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. + +namespace Microsoft.CmdPal.Ext.PerformanceMonitor; + +/// +/// Controls the unit used to display network transmission speed. +/// +internal enum NetworkSpeedUnit +{ + /// Bits per second (Kbps, Mbps, Gbps) — SI decimal prefixes. + BitsPerSecond, + + /// Bytes per second (KB/s, MB/s, GB/s) — SI decimal prefixes. + BytesPerSecond, + + /// Bytes per second (KiB/s, MiB/s, GiB/s) — IEC binary prefixes. + BinaryBytesPerSecond, +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceMonitorCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceMonitorCommandsProvider.cs index 3f00a99395..f80d84ae70 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceMonitorCommandsProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceMonitorCommandsProvider.cs @@ -21,6 +21,7 @@ public partial class PerformanceMonitorCommandsProvider : CommandProvider internal static ProviderCrashSentinel CrashSentinel { get; } = new(ProviderIdValue); private readonly Lock _stateLock = new(); + private readonly SettingsManager _settingsManager = new(); private ICommandItem[] _commands = []; private ICommandItem _band = new CommandItem(); private PerformanceWidgetsPage? _mainPage; @@ -33,6 +34,8 @@ public partial class PerformanceMonitorCommandsProvider : CommandProvider Id = ProviderIdValue; Icon = Icons.PerformanceMonitorIcon; + Settings = _settingsManager.Settings; + if (softDisabled) { SetDisabledState(); @@ -121,12 +124,16 @@ public partial class PerformanceMonitorCommandsProvider : CommandProvider { DisposeActivePages(); - _mainPage = new PerformanceWidgetsPage(false); - _bandPage = new PerformanceWidgetsPage(true); + _mainPage = new PerformanceWidgetsPage(_settingsManager, false); + _bandPage = new PerformanceWidgetsPage(_settingsManager, true); _band = new CommandItem(_bandPage) { Title = DisplayName }; _commands = [ - new CommandItem(_mainPage) { Title = DisplayName }, + new CommandItem(_mainPage) + { + Title = DisplayName, + MoreCommands = [new CommandContextItem(_settingsManager.Settings.SettingsPage)], + }, ]; _softDisabled = false; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceWidgetsPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceWidgetsPage.cs index f82e45bc57..f898079ca2 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceWidgetsPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/PerformanceWidgetsPage.cs @@ -43,7 +43,7 @@ internal sealed partial class PerformanceWidgetsPage : OnLoadStaticListPage, IDi private readonly SystemMemoryUsageWidgetPage _memoryPage = new(); private readonly ListItem _memoryItem; - private readonly SystemNetworkUsageWidgetPage _networkPage = new(); + private readonly SystemNetworkUsageWidgetPage _networkPage; private readonly ListItem _networkItem; private readonly SystemGPUUsageWidgetPage _gpuPage = new(); @@ -55,9 +55,10 @@ internal sealed partial class PerformanceWidgetsPage : OnLoadStaticListPage, IDi private string _networkUpSpeed = string.Empty; private string _networkDownSpeed = string.Empty; - public PerformanceWidgetsPage(bool isBandPage = false) + public PerformanceWidgetsPage(SettingsManager settingsManager, bool isBandPage = false) { _isBandPage = isBandPage; + _networkPage = new SystemNetworkUsageWidgetPage(settingsManager); _cpuItem = new ListItem(_cpuPage) { Title = _cpuPage.GetItemTitle(isBandPage), @@ -532,10 +533,12 @@ internal sealed partial class SystemNetworkUsageWidgetPage : WidgetPage, IDispos public override IconInfo Icon => Icons.NetworkIcon; private readonly DataManager _dataManager; + private readonly SettingsManager _settingsManager; private int _networkIndex; - public SystemNetworkUsageWidgetPage() + public SystemNetworkUsageWidgetPage(SettingsManager settingsManager) { + _settingsManager = settingsManager; _dataManager = new(DataType.Network, () => UpdateWidget()); Commands = [ new CommandContextItem(new PrevNetworkCommand(this) { Name = Resources.GetResource("Previous_Network_Title") }), @@ -561,8 +564,8 @@ internal sealed partial class SystemNetworkUsageWidgetPage : WidgetPage, IDispos var networkStats = currentData.GetNetworkUsage(_networkIndex); ContentData["networkUsage"] = FloatToPercentString(networkStats.Usage); - ContentData["netSent"] = BytesToBitsPerSecString(networkStats.Sent); - ContentData["netReceived"] = BytesToBitsPerSecString(networkStats.Received); + ContentData["netSent"] = SpeedToString(networkStats.Sent); + ContentData["netReceived"] = SpeedToString(networkStats.Received); ContentData["networkName"] = netName; ContentData["netGraphUrl"] = currentData.CreateNetImageUrl(_networkIndex); ContentData["chartHeight"] = ChartHelper.ChartHeight + "px"; @@ -627,7 +630,17 @@ internal sealed partial class SystemNetworkUsageWidgetPage : WidgetPage, IDispos } } - private string BytesToBitsPerSecString(float value) + private string SpeedToString(float bytesPerSec) + { + return _settingsManager.NetworkSpeedUnit switch + { + NetworkSpeedUnit.BytesPerSecond => FormatAsBytesPerSecString(bytesPerSec), + NetworkSpeedUnit.BinaryBytesPerSecond => FormatAsBinaryBytesPerSecString(bytesPerSec), + _ => FormatAsBitsPerSecString(bytesPerSec), + }; + } + + private static string FormatAsBitsPerSecString(float value) { // Bytes to bits value *= 8; @@ -666,6 +679,78 @@ internal sealed partial class SystemNetworkUsageWidgetPage : WidgetPage, IDispos return string.Format(CultureInfo.InvariantCulture, "{0:0} Gbps", value); } + private static string FormatAsBytesPerSecString(float value) + { + // Bytes to KB + value /= 1024; + if (value < 1024) + { + if (value < 100) + { + return string.Format(CultureInfo.InvariantCulture, "{0:0.0} KB/s", value); + } + + return string.Format(CultureInfo.InvariantCulture, "{0:0} KB/s", value); + } + + // KB to MB + value /= 1024; + if (value < 1024) + { + if (value < 100) + { + return string.Format(CultureInfo.InvariantCulture, "{0:0.0} MB/s", value); + } + + return string.Format(CultureInfo.InvariantCulture, "{0:0} MB/s", value); + } + + // MB to GB + value /= 1024; + if (value < 100) + { + return string.Format(CultureInfo.InvariantCulture, "{0:0.0} GB/s", value); + } + + return string.Format(CultureInfo.InvariantCulture, "{0:0} GB/s", value); + } + + private static string FormatAsBinaryBytesPerSecString(float value) + { + // Bytes to KiB + value /= 1024; + if (value < 1024) + { + if (value < 100) + { + return string.Format(CultureInfo.InvariantCulture, "{0:0.0} KiB/s", value); + } + + return string.Format(CultureInfo.InvariantCulture, "{0:0} KiB/s", value); + } + + // KiB to MiB + value /= 1024; + if (value < 1024) + { + if (value < 100) + { + return string.Format(CultureInfo.InvariantCulture, "{0:0.0} MiB/s", value); + } + + return string.Format(CultureInfo.InvariantCulture, "{0:0} MiB/s", value); + } + + // MiB to GiB + value /= 1024; + if (value < 100) + { + return string.Format(CultureInfo.InvariantCulture, "{0:0.0} GiB/s", value); + } + + return string.Format(CultureInfo.InvariantCulture, "{0:0} GiB/s", value); + } + internal override void PushActivate() { base.PushActivate(); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/SettingsManager.cs new file mode 100644 index 0000000000..2c32ddb9f4 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/SettingsManager.cs @@ -0,0 +1,50 @@ +// 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.IO; +using CoreWidgetProvider.Helpers; +using Microsoft.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.Ext.PerformanceMonitor; + +internal sealed class SettingsManager : JsonSettingsManager +{ + private const string Namespace = "performanceMonitor"; + + private static string Namespaced(string propertyName) => $"{Namespace}.{propertyName}"; + + private readonly ChoiceSetSetting _networkSpeedUnit = new( + Namespaced(nameof(NetworkSpeedUnit)), + Resources.GetResource("Network_Speed_Unit_Setting_Title"), + Resources.GetResource("Network_Speed_Unit_Setting_Description"), + [ + new ChoiceSetSetting.Choice(Resources.GetResource("Network_Speed_Unit_BitsPerSec"), NetworkSpeedUnit.BitsPerSecond.ToString("G")), + new ChoiceSetSetting.Choice(Resources.GetResource("Network_Speed_Unit_BytesPerSec"), NetworkSpeedUnit.BytesPerSecond.ToString("G")), + new ChoiceSetSetting.Choice(Resources.GetResource("Network_Speed_Unit_BinaryBytesPerSec"), NetworkSpeedUnit.BinaryBytesPerSecond.ToString("G")), + ]); + + public NetworkSpeedUnit NetworkSpeedUnit => + Enum.TryParse(_networkSpeedUnit.Value, out var unit) + ? unit + : NetworkSpeedUnit.BitsPerSecond; + + private static string SettingsJsonPath() + { + var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal"); + Directory.CreateDirectory(directory); + return Path.Combine(directory, "settings.json"); + } + + public SettingsManager() + { + FilePath = SettingsJsonPath(); + + Settings.Add(_networkSpeedUnit); + + LoadSettings(); + + Settings.SettingsChanged += (_, _) => SaveSettings(); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Strings/en-US/Resources.resw b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Strings/en-US/Resources.resw index 1d49265baf..92d5c7be1d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Strings/en-US/Resources.resw +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Strings/en-US/Resources.resw @@ -276,4 +276,19 @@ Receive ↓ + + Network speed unit + + + Choose the unit used to display network transmission speed + + + Bits per second (Kbps, Mbps, Gbps) + + + Bytes per second (KB/s, MB/s, GB/s) + + + Binary bytes per second (KiB/s, MiB/s, GiB/s) +