🚧 [new module] Environment variables editor (#28722)

* Init EnvironmentVariables UI project

* Models
TitleBar
MainPage init
Icon

* User and system variables

* Profiles init

* XAML cleanup

* Missing ItemTemplate

* EditDialog

* ModuleInterface

* Signing and processes lists

* Installer

* spellcheck

* Fix ARM64 build and consolidate packages

* spellcheck2

* Fix installer

* Single instance. C# telemetry. Wait on PT pid

* ElevationHelper

* Add profile wip

* Init EnvironmentVariables UI project

* Models
TitleBar
MainPage init
Icon

* User and system variables

* Profiles init

* XAML cleanup

* Missing ItemTemplate

* EditDialog

* ModuleInterface

* Signing and processes lists

* Installer

* spellcheck

* Fix ARM64 build and consolidate packages

* spellcheck2

* Fix installer

* Single instance. C# telemetry. Wait on PT pid

* ElevationHelper

* Add profile wip

* show run as administrator in title (#28516)

* Environment Variables added to Run plugin (#28466)

* UI tweaks

* Remove style

* Add profile - init working

* Applied variables

* Read/Write profiles

* Fixes

* Add separator and fix loading profiles

* Only allow to edit System vars if running elevated

* Add tmp progress ring to show applying changes progress
Ignore not needed json fields

* Remove variable and profile logic

* Do not read data async
Update System and User variables on change

* Add isCorrectlyApplied()

* Sort variables in Applied variables

* WIP WndProc

* spellcheck

* Revert "WIP WndProc"

This reverts commit 0c0b6c67de.

* WHY CRASH???

* UI tweaks

* WIP modified state warning

* Add cancel button in dialogs

* Add buttons validations

* Set variables - fire and forget notify

* Revert "Revert "WIP WndProc""

This reverts commit 1b2306eeb7.

* Listen to WM_SETTINGSCHANGED
Add Infobar reload button

* spellcheck

* spellcheck again

* Fix build

* InfoBar runAsAdmin visibility

* Fix comment

* Confirm dialog when deleting variable
Fix add variable button when creating profile

* Edit profile

* Sort variables on Load

* Select existing variables on edit

* Add default variable

* Fix adding existing vars to profile

* update notice.md

* Handle PATH properly

* Add tooltips and fix dialogs text wrapping

* Fix applied values for duplicates
Fix add/eddit variable txt box validation

* Add horizontal scroll bar for applied values

* Fix duplicate variables handling
Fix user variable handling and preview

* spellcheck

* Try fix spellcheck

* Revert "spellcheck"

This reverts commit ee76231974.

* Revert "Try fix spellcheck"

This reverts commit dc8f04afb9.

* Fix path and duplicates conflict

* Fix PATH handling
Fix unapply on delete active variable
Fix ordering in applied variables

* Show variables as lists and add drag-to-reorder feature

* Only show specific variables as list
Update list in edit dialog on editing the value

* spellcheck

* Update GPO policy

* Add Edit and Remove variable buttons
Remove context menu

* Remove drag&drop when editing list variable and add buttons to move up/down

* Fix Edit profile dialog title

* Fix backup and restore variables when editing variable from applied profile

* Apply var to system WIP

* Tweaks

* Simplify edit variable logic

* Minor fixes

* Spellcheck

* Update src/modules/EnvironmentVariables/EnvironmentVariables/app.manifest

Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>

* spellcheck 2

* Remove unneeded string

* Add more telemetry

* Do not allow adding existing variables with the same name into the profile

* Adding icon

* Fix the crash when opening existing variables dialog

* Update Settings and OOBE screenshots

* Fix crash when malformed profiles.json and jsonignore not needed properties

* Fix selecting duplicates in existing variables dialog

* Add user variable name limit (<255 chars)
Check if profile is applicable on apply
Show message if profile is not applicable

* XamlStyling

* Better Flyout positioning
Add Cancel button to the flyout

* Fix UI glitches by using ItemsControl (no virtualization)

* Fix spellcheck

* Fix XAML style

* Add horizontal scrollbar to applied variables

* Revert to ItemsRepeater

* Fix UI glitches by adding a decent minimum cache

* Fixing UI bugs

* Fix spellcheck

* Fix crash while trying to edit a User variable when there's no Parent
profile

* Fix issue overwriting backup var when you edit var on applied profile

* Fix nuking of variables when adding to applied profile

* Fix profile not being saved when deleting a variable

* Fix ValuesList empty crash, issues and no serialization

* fix spellcheck

* Allow in-line edit of list variables

* Fix xaml style

* Fix add profile variable cancel button logic

* Fix add profile variable cancel button logic - clean the list

* Bump VerticalCacheLength to 10

as in some cases UI glitch on expanding System variables was still present

* Fix profile Add variable button enable/disable logic

* Remove unneeded using

* Add to Dashboard

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it>
Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
This commit is contained in:
Stefan Markovic
2023-10-20 16:28:07 +02:00
committed by GitHub
parent 1f936df3eb
commit 812b343776
109 changed files with 4978 additions and 37 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

View File

@@ -11,6 +11,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
Awake,
ColorPicker,
CropAndLock,
EnvironmentVariables,
FancyZones,
FileLocksmith,
FileExplorer,

View File

@@ -134,4 +134,4 @@
</Page>
</ItemGroup>
</Project>
</Project>

View File

@@ -404,6 +404,7 @@ namespace Microsoft.PowerToys.Settings.UI
case "PastePlain": return typeof(PastePlainPage);
case "Peek": return typeof(PeekPage);
case "CropAndLock": return typeof(CropAndLockPage);
case "EnvironmentVariables": return typeof(EnvironmentVariablesPage);
default:
// Fallback to Dashboard
Debug.Assert(false, "Unexpected SettingsWindow argument value");

View File

@@ -42,6 +42,21 @@ namespace Microsoft.PowerToys.Settings.UI.Flyout
}
break;
case "EnvironmentVariables": // Launch Environment Variables
{
bool launchAdmin = SettingsRepository<EnvironmentVariablesSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator;
string eventName = !App.IsElevated && launchAdmin
? Constants.ShowEnvironmentVariablesAdminSharedEvent()
: Constants.ShowEnvironmentVariablesSharedEvent();
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
{
eventHandle.Set();
}
}
break;
case "FancyZones": // Launch FancyZones Editor
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.FZEToggleEvent()))
{

View File

@@ -100,6 +100,9 @@ namespace Microsoft.PowerToys.Settings.UI
case "CropAndLock":
needToUpdate = generalSettingsConfig.Enabled.CropAndLock != isEnabled;
generalSettingsConfig.Enabled.CropAndLock = isEnabled; break;
case "EnvironmentVariables":
needToUpdate = generalSettingsConfig.Enabled.EnvironmentVariables != isEnabled;
generalSettingsConfig.Enabled.EnvironmentVariables = isEnabled; break;
case "FancyZones":
needToUpdate = generalSettingsConfig.Enabled.FancyZones != isEnabled;
generalSettingsConfig.Enabled.FancyZones = isEnabled; break;

View File

@@ -0,0 +1,31 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeEnvironmentVariables"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_EnvironmentVariables" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/EnvironmentVariables.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="Launch_EnvironmentVariables"
Click="Launch_EnvironmentVariables_Click"
Style="{StaticResource AccentButtonStyle}" />
<Button x:Uid="OOBE_Settings" Click="Launch_Settings_Click" />
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_EnvironmentVariables" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_EnvironmentVariables" TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,60 @@
// 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.Threading;
using interop;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeEnvironmentVariables : Page
{
public OobePowerToysModule ViewModel { get; }
public OobeEnvironmentVariables()
{
InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.EnvironmentVariables]);
DataContext = ViewModel;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
private void Launch_EnvironmentVariables_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
bool launchAdmin = SettingsRepository<EnvironmentVariablesSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator;
string eventName = !App.IsElevated && launchAdmin
? Constants.ShowEnvironmentVariablesAdminSharedEvent()
: Constants.ShowEnvironmentVariablesSharedEvent();
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
{
eventHandle.Set();
}
}
private void Launch_Settings_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(EnvironmentVariablesPage));
}
ViewModel.LogOpeningSettingsEvent();
}
}
}

View File

@@ -1,4 +1,4 @@
<UserControl
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeShellPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -14,24 +14,6 @@
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LayoutVisualStates">
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="SmallLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600" />
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="navigationView.PaneDisplayMode" Value="LeftMinimal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Button
x:Name="PaneToggleBtn"
Width="48"
@@ -64,11 +46,11 @@
</StackPanel>
</Grid>
<NavigationView
Grid.Row="1"
x:Name="navigationView"
Grid.Row="1"
DisplayModeChanged="NavigationView_DisplayModeChanged"
IsBackButtonVisible="Collapsed"
IsPaneOpen="True"
DisplayModeChanged="NavigationView_DisplayModeChanged"
IsPaneToggleButtonVisible="False"
IsSettingsVisible="False"
OpenPaneLength="296"
@@ -95,6 +77,10 @@
x:Uid="Shell_CropAndLock"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsCropAndLock.png}"
Tag="CropAndLock" />
<NavigationViewItem
x:Uid="Shell_EnvironmentVariables"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsEnvironmentVariables.png}"
Tag="EnvironmentVariables" />
<NavigationViewItem
x:Uid="Shell_FancyZones"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsFancyZones.png}"
@@ -171,13 +157,30 @@
<NavigationView.FooterMenuItems>
<NavigationViewItem
x:Uid="Shell_WhatsNew"
Icon="{ui:FontIcon
Glyph=&#xF133;}"
Icon="{ui:FontIcon Glyph=&#xF133;}"
Tag="WhatsNew" />
</NavigationView.FooterMenuItems>
<NavigationView.Content>
<Frame x:Name="NavigationFrame" />
</NavigationView.Content>
</NavigationView>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LayoutVisualStates">
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="SmallLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600" />
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="navigationView.PaneDisplayMode" Value="LeftMinimal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</UserControl>

View File

@@ -89,6 +89,11 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
ModuleName = "CropAndLock",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.EnvironmentVariables, new OobePowerToysModule()
{
ModuleName = "EnvironmentVariables",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.FancyZones, new OobePowerToysModule()
{
ModuleName = "FancyZones",
@@ -247,6 +252,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
case "Awake": NavigationFrame.Navigate(typeof(OobeAwake)); break;
case "ColorPicker": NavigationFrame.Navigate(typeof(OobeColorPicker)); break;
case "CropAndLock": NavigationFrame.Navigate(typeof(OobeCropAndLock)); break;
case "EnvironmentVariables": NavigationFrame.Navigate(typeof(OobeEnvironmentVariables)); break;
case "FancyZones": NavigationFrame.Navigate(typeof(OobeFancyZones)); break;
case "FileLocksmith": NavigationFrame.Navigate(typeof(OobeFileLocksmith)); break;
case "Run": NavigationFrame.Navigate(typeof(OobeRun)); break;

View File

@@ -0,0 +1,52 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.EnvironmentVariablesPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:controls1="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI.UI"
mc:Ignorable="d">
<controls:SettingsPageControl x:Uid="EnvironmentVariables" ModuleImageSource="ms-appx:///Assets/Settings/Modules/EnvironmentVariables.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
<controls1:SettingsCard
x:Uid="EnvironmentVariables_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsEnvironmentVariables.png}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</controls1:SettingsCard>
<InfoBar
x:Uid="GPO_IsSettingForced"
IsClosable="False"
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
Severity="Informational" />
<controls:SettingsGroup x:Uid="EnvironmentVariables_Activation_GroupSettings" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls1:SettingsCard
x:Uid="EnvironmentVariables_LaunchButtonControl"
ActionIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
FontSize=14,
Glyph=&#xE8A7;}"
Command="{x:Bind ViewModel.LaunchEventHandler}"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xEA37;}"
IsClickEnabled="True" />
<controls1:SettingsCard
x:Uid="EnvironmentVariables_Toggle_LaunchAdministrator"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xE7EF;}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.LaunchAdministratorEnabled}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.LaunchAdministrator}" />
</controls1:SettingsCard>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_EnvironmentVariables" Link="https://aka.ms/PowerToysOverview_EnvironmentVariables" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Page>

View File

@@ -0,0 +1,28 @@
// 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 Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class EnvironmentVariablesPage : Page, IRefreshablePage
{
private EnvironmentVariablesViewModel ViewModel { get; }
public EnvironmentVariablesPage()
{
InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new EnvironmentVariablesViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<EnvironmentVariablesSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated);
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@@ -116,6 +116,11 @@
helpers:NavHelper.NavigateTo="views:CropAndLockPage"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsCropAndLock.png}" />
<NavigationViewItem
x:Uid="Shell_EnvironmentVariables"
helpers:NavHelper.NavigateTo="views:EnvironmentVariablesPage"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsEnvironmentVariables.png}" />
<NavigationViewItem
x:Uid="Shell_FancyZones"
helpers:NavHelper.NavigateTo="views:FancyZonesPage"

View File

@@ -3461,6 +3461,48 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="Hosts_Toggle_LaunchAdministrator.Header" xml:space="preserve">
<value>Launch as administrator</value>
</data>
<data name="EnvironmentVariables.ModuleDescription" xml:space="preserve">
<value>A quick utility for managing environment variables.</value>
</data>
<data name="EnvironmentVariables.ModuleTitle" xml:space="preserve">
<value>Environment Variables</value>
</data>
<data name="Shell_EnvironmentVariables.Content" xml:space="preserve">
<value>Environment Variables</value>
</data>
<data name="EnvironmentVariables_EnableToggleControl_HeaderText.Header" xml:space="preserve">
<value>Enable Environment Variables</value>
</data>
<data name="EnvironmentVariables_Activation_GroupSettings.Header" xml:space="preserve">
<value>Activation</value>
</data>
<data name="EnvironmentVariables_LaunchButtonControl.Description" xml:space="preserve">
<value>Manage your environment variables</value>
</data>
<data name="EnvironmentVariables_LaunchButtonControl.Header" xml:space="preserve">
<value>Launch Environment Variables</value>
</data>
<data name="EnvironmentVariables_LaunchButton_Accessible.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Launch Environment Variables</value>
</data>
<data name="Launch_EnvironmentVariables.Content" xml:space="preserve">
<value>Launch Environment Variables</value>
</data>
<data name="LearnMore_EnvironmentVariables.Text" xml:space="preserve">
<value>Learn more about Environment Variables</value>
</data>
<data name="Oobe_EnvironmentVariables.Description" xml:space="preserve">
<value>Environment Variables is a quick utility for managing environment variables.</value>
</data>
<data name="Oobe_EnvironmentVariables.Title" xml:space="preserve">
<value>Environment Variables</value>
</data>
<data name="EnvironmentVariables_Toggle_LaunchAdministrator.Description" xml:space="preserve">
<value>Needs to be launched as administrator in order to make changes to the system environment variables</value>
</data>
<data name="EnvironmentVariables_Toggle_LaunchAdministrator.Header" xml:space="preserve">
<value>Launch as administrator</value>
</data>
<data name="ShortcutGuide_PressTimeForTaskbarIconShortcuts.Header" xml:space="preserve">
<value>Press duration before showing taskbar icon shortcuts (ms)</value>
<comment>ms = milliseconds</comment>

View File

@@ -106,6 +106,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
DashboardModuleItems = GetModuleItemsCropAndLock(),
});
gpo = GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue();
_allModules.Add(new DashboardListItem()
{
Tag = "EnvironmentVariables",
Label = resourceLoader.GetString("EnvironmentVariables/ModuleTitle"),
IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.EnvironmentVariables),
IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsEnvironmentVariables.png",
EnabledChangedCallback = EnabledChangedOnUI,
AccentColor = Color.FromArgb(255, 16, 132, 208), // #1084d0
DashboardModuleItems = GetModuleItemsEnvironmentVariables(),
});
gpo = GPOWrapper.GetConfiguredFancyZonesEnabledValue();
_allModules.Add(new DashboardListItem()
{
@@ -538,6 +551,15 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
return new ObservableCollection<DashboardModuleItem>(list);
}
private ObservableCollection<DashboardModuleItem> GetModuleItemsEnvironmentVariables()
{
var list = new List<DashboardModuleItem>
{
new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("EnvironmentVariables_LaunchButtonControl/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("EnvironmentVariables_LaunchButtonControl/Description"), ButtonGlyph = "\uEA37", ButtonClickHandler = EnvironmentVariablesLaunchClicked },
};
return new ObservableCollection<DashboardModuleItem>(list);
}
private ObservableCollection<DashboardModuleItem> GetModuleItemsFancyZones()
{
ISettingsRepository<FancyZonesSettings> moduleSettingsRepository = SettingsRepository<FancyZonesSettings>.GetInstance(new SettingsUtils());
@@ -767,6 +789,13 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
NavigationService.Navigate(typeof(GeneralPage));
}
private void EnvironmentVariablesLaunchClicked(object sender, RoutedEventArgs e)
{
var settingsUtils = new SettingsUtils();
var environmentVariablesViewModel = new EnvironmentVariablesViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<EnvironmentVariablesSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated);
environmentVariablesViewModel.Launch();
}
private void HostLaunchClicked(object sender, RoutedEventArgs e)
{
var settingsUtils = new SettingsUtils();

View File

@@ -0,0 +1,130 @@
// 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.Runtime.CompilerServices;
using System.Threading;
using global::PowerToys.GPOWrapper;
using interop;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
using Settings.UI.Library.Enumerations;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class EnvironmentVariablesViewModel : Observable
{
private bool _isElevated;
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
private ISettingsUtils SettingsUtils { get; set; }
private GeneralSettings GeneralSettingsConfig { get; set; }
private EnvironmentVariablesSettings Settings { get; set; }
private Func<string, int> SendConfigMSG { get; }
public ButtonClickCommand LaunchEventHandler => new ButtonClickCommand(Launch);
public bool IsEnabled
{
get => _isEnabled;
set
{
if (_enabledStateIsGPOConfigured)
{
// If it's GPO configured, shouldn't be able to change this state.
return;
}
if (value != _isEnabled)
{
_isEnabled = value;
// Set the status in the general settings configuration
GeneralSettingsConfig.Enabled.EnvironmentVariables = value;
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(snd.ToString());
OnPropertyChanged(nameof(IsEnabled));
}
}
}
public bool IsEnabledGpoConfigured
{
get => _enabledStateIsGPOConfigured;
}
public bool LaunchAdministratorEnabled => IsEnabled && !_isElevated;
public bool LaunchAdministrator
{
get => Settings.Properties.LaunchAdministrator;
set
{
if (value != Settings.Properties.LaunchAdministrator)
{
Settings.Properties.LaunchAdministrator = value;
NotifyPropertyChanged();
}
}
}
public EnvironmentVariablesViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<EnvironmentVariablesSettings> moduleSettingsRepository, Func<string, int> ipcMSGCallBackFunc, bool isElevated)
{
SettingsUtils = settingsUtils;
GeneralSettingsConfig = settingsRepository.SettingsConfig;
Settings = moduleSettingsRepository.SettingsConfig;
SendConfigMSG = ipcMSGCallBackFunc;
_isElevated = isElevated;
InitializeEnabledValue();
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.EnvironmentVariables;
}
}
public void Launch()
{
string eventName = !_isElevated && LaunchAdministrator
? Constants.ShowEnvironmentVariablesAdminSharedEvent()
: Constants.ShowEnvironmentVariablesSharedEvent();
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
{
eventHandle.Set();
}
}
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(propertyName);
SettingsUtils.SaveSettings(Settings.ToJsonString(), EnvironmentVariablesSettings.ModuleName);
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
}
}

View File

@@ -52,6 +52,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("CropAndLock/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.CropAndLock, Tag = "CropAndLock", Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsCropAndLock.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("EnvironmentVariables/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.EnvironmentVariables, Tag = "EnvironmentVariables", Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsEnvironmentVariables.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredFancyZonesEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("FancyZones/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.FancyZones, Tag = "FancyZones", Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsFancyZones.png", EnabledChangedCallback = EnabledChangedOnUI });
@@ -171,6 +176,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
case "Awake": item.IsEnabled = generalSettingsConfig.Enabled.Awake; break;
case "ColorPicker": item.IsEnabled = generalSettingsConfig.Enabled.ColorPicker; break;
case "CropAndLock": item.IsEnabled = generalSettingsConfig.Enabled.CropAndLock; break;
case "EnvironmentVariables": item.IsEnabled = generalSettingsConfig.Enabled.EnvironmentVariables; break;
case "FancyZones": item.IsEnabled = generalSettingsConfig.Enabled.FancyZones; break;
case "FileLocksmith": item.IsEnabled = generalSettingsConfig.Enabled.FileLocksmith; break;
case "FindMyMouse": item.IsEnabled = generalSettingsConfig.Enabled.FindMyMouse; break;

View File

@@ -46,6 +46,17 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
});
}
if (GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()
{
Label = resourceLoader.GetString("EnvironmentVariables/ModuleTitle"),
Tag = "EnvironmentVariables",
Visible = generalSettingsConfig.Enabled.EnvironmentVariables,
Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsEnvironmentVariables.png",
});
}
if (GPOWrapper.GetConfiguredFancyZonesEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()