diff --git a/Directory.Packages.props b/Directory.Packages.props index e02ed27170..0c08952d71 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,6 +5,7 @@ + diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj index da28393647..60b375a79f 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj @@ -58,6 +58,11 @@ + + + https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-Labs/nuget/v3/index.json + + @@ -70,13 +75,14 @@ - - + + + diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs index e84d41e934..c9b4db11c7 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/MainWindow.xaml.cs @@ -23,20 +23,6 @@ namespace EnvironmentVariables AppWindow.SetIcon("Assets/EnvironmentVariables/EnvironmentVariables.ico"); Title = ResourceLoaderInstance.ResourceLoader.GetString("WindowTitle"); - - Activated += MainWindow_Activated; - } - - private void MainWindow_Activated(object sender, WindowActivatedEventArgs args) - { - if (args.WindowActivationState == WindowActivationState.Deactivated) - { - AppTitleTextBlock.Foreground = (SolidColorBrush)App.Current.Resources["WindowCaptionForegroundDisabled"]; - } - else - { - AppTitleTextBlock.Foreground = (SolidColorBrush)App.Current.Resources["WindowCaptionForeground"]; - } } } } diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/Views/MainPage.xaml b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/Views/MainPage.xaml index 218c2158a4..2918937be7 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/Views/MainPage.xaml +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/Views/MainPage.xaml @@ -43,10 +43,10 @@ - + + + diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/Views/MainPage.xaml.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/Views/MainPage.xaml.cs index 0bdedb3ee6..68f952fa34 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/Views/MainPage.xaml.cs +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariablesXAML/Views/MainPage.xaml.cs @@ -9,7 +9,9 @@ using CommunityToolkit.Labs.WinUI; using CommunityToolkit.Mvvm.Input; using EnvironmentVariables.Models; using EnvironmentVariables.ViewModels; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using static EnvironmentVariables.Models.Common; namespace EnvironmentVariables.Views { @@ -19,6 +21,10 @@ namespace EnvironmentVariables.Views public ICommand EditCommand => new RelayCommand(EditVariable); + public ICommand NewProfileCommand => new AsyncRelayCommand(AddProfileAsync); + + public ICommand AddProfileCommand => new RelayCommand(AddProfile); + public MainPage() { this.InitializeComponent(); @@ -30,15 +36,15 @@ namespace EnvironmentVariables.Views { var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader; - EditDialog.Title = resourceLoader.GetString("EditVariableDialog_Title"); - EditDialog.PrimaryButtonText = resourceLoader.GetString("SaveBtn"); - EditDialog.PrimaryButtonCommand = EditCommand; - EditDialog.PrimaryButtonCommandParameter = variable; + EditVariableDialog.Title = resourceLoader.GetString("EditVariableDialog_Title"); + EditVariableDialog.PrimaryButtonText = resourceLoader.GetString("SaveBtn"); + EditVariableDialog.PrimaryButtonCommand = EditCommand; + EditVariableDialog.PrimaryButtonCommandParameter = variable; var clone = variable.Clone(); - EditDialog.DataContext = clone; + EditVariableDialog.DataContext = clone; - await EditDialog.ShowAsync(); + await EditVariableDialog.ShowAsync(); } private async void EditVariable_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) @@ -52,8 +58,50 @@ namespace EnvironmentVariables.Views private void EditVariable(Variable original) { - var edited = EditDialog.DataContext as Variable; + var edited = EditVariableDialog.DataContext as Variable; ViewModel.EditVariable(original, edited); } + + private async Task AddProfileAsync() + { + SwitchViewsSegmentedView.SelectedIndex = 0; + ViewModel.CurrentAddVariablePage = AddVariablePageKind.AddNewVariable; + ViewModel.ShowAddNewVariablePage = Visibility.Visible; + + var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader; + AddProfileDialog.Title = resourceLoader.GetString("AddNewProfileDialog_Title"); + AddProfileDialog.PrimaryButtonText = resourceLoader.GetString("AddBtn"); + AddProfileDialog.PrimaryButtonCommand = AddProfileCommand; + AddProfileDialog.DataContext = new ProfileVariablesSet(Guid.NewGuid(), string.Empty); + await AddProfileDialog.ShowAsync(); + } + + private void AddProfile() + { + var profile = AddProfileDialog.DataContext as ProfileVariablesSet; + ViewModel.AddProfile(profile); + } + + private void Segmented_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (ViewModel.CurrentAddVariablePage == AddVariablePageKind.AddNewVariable) + { + ChangeToExistingVariablePage(); + } + else + { + ChangeToNewVariablePage(); + } + } + + private void ChangeToNewVariablePage() + { + ViewModel.ChangeToNewVariablePage(); + } + + private void ChangeToExistingVariablePage() + { + ViewModel.ChangeToExistingVariablePage(); + } } } diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/Helpers/EnvironmentVariablesHelper.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/Helpers/EnvironmentVariablesHelper.cs index ded7cc6703..0a499a2a95 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/Helpers/EnvironmentVariablesHelper.cs +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/Helpers/EnvironmentVariablesHelper.cs @@ -11,6 +11,30 @@ namespace EnvironmentVariables.Helpers { internal sealed class EnvironmentVariablesHelper { + internal static string GetBackupVariableName(Variable variable, string profileName) + { + return variable.Name + "_PowerToys_" + profileName; + } + + internal static Variable GetExisting(string variableName) + { + var userVariables = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); + + if (userVariables.Contains(variableName)) + { + return new Variable(variableName, userVariables[variableName] as string, VariablesSetType.User); + } + + var systemVariables = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); + + if (systemVariables.Contains(variableName)) + { + return new Variable(variableName, userVariables[variableName] as string, VariablesSetType.System); + } + + return null; + } + internal static void GetVariables(EnvironmentVariableTarget target, VariablesSet set) { var variables = Environment.GetEnvironmentVariables(target); diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/Models/Common.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/Models/Common.cs new file mode 100644 index 0000000000..10ff85b5b7 --- /dev/null +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/Models/Common.cs @@ -0,0 +1,16 @@ +// 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 EnvironmentVariables.Models +{ + internal sealed class Common + { + internal enum AddVariablePageKind + { + AddNewVariable, + + AddExistingVariable, + } + } +} diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/Models/ProfileVariablesSet.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/Models/ProfileVariablesSet.cs index cd1e2ba931..5e128491d1 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/Models/ProfileVariablesSet.cs +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/Models/ProfileVariablesSet.cs @@ -3,16 +3,91 @@ // See the LICENSE file in the project root for more information. using System; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.ComponentModel; +using EnvironmentVariables.Helpers; +using ManagedCommon; namespace EnvironmentVariables.Models { - public class ProfileVariablesSet : VariablesSet + public partial class ProfileVariablesSet : VariablesSet { - public bool IsEnabled { get; set; } + [ObservableProperty] + private bool _isEnabled; + + public ProfileVariablesSet() + : base() + { + } public ProfileVariablesSet(Guid id, string name) : base(id, name, VariablesSetType.Profile) { } + + public void Apply() + { + Task.Run(() => + { + foreach (var variable in Variables) + { + // Get existing variable with the same name if it exist + var variableToOverride = EnvironmentVariablesHelper.GetExisting(variable.Name); + + // It exists. Rename it to preserve it. + if (variableToOverride != null) + { + variableToOverride.Name = EnvironmentVariablesHelper.GetBackupVariableName(variableToOverride, this.Name); + + // Backup the variable + if (!EnvironmentVariablesHelper.SetVariable(variableToOverride)) + { + Logger.LogError("Failed to set backup variable."); + } + } + + if (!EnvironmentVariablesHelper.SetVariable(variable)) + { + Logger.LogError("Failed to set profile variable."); + } + } + }); + } + + public void UnApply() + { + Task.Run(() => + { + foreach (var variable in Variables) + { + // Unset the variable + if (!EnvironmentVariablesHelper.UnsetVariable(variable)) + { + Logger.LogError("Failed to unset variable."); + } + + var originalName = variable.Name; + var backupName = EnvironmentVariablesHelper.GetBackupVariableName(variable, this.Name); + + // Get backup variable if it exist + var backupVariable = EnvironmentVariablesHelper.GetExisting(backupName); + + if (backupVariable != null) + { + var variableToRestore = new Variable(originalName, backupVariable.Values, backupVariable.ParentType); + + if (!EnvironmentVariablesHelper.UnsetVariable(backupVariable)) + { + Logger.LogError("Failed to unset backup variable."); + } + + if (!EnvironmentVariablesHelper.SetVariable(variableToRestore)) + { + Logger.LogError("Failed to restore backup variable."); + } + } + } + }); + } } } diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/Models/Variable.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/Models/Variable.cs index 9a782cf21b..771ed15335 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/Models/Variable.cs +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/Models/Variable.cs @@ -31,15 +31,10 @@ namespace EnvironmentVariables.Models Values = values; ParentType = parentType; - ValuesList = new List(); - var splitValues = Values.Split(';'); if (splitValues.Length > 0) { - foreach (var splitValue in splitValues) - { - ValuesList.Add(splitValue); - } + ValuesList = new List(splitValues); } } diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/Models/VariablesSet.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/Models/VariablesSet.cs index 79b4a9bd07..e99af31d8c 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/Models/VariablesSet.cs +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/Models/VariablesSet.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; namespace EnvironmentVariables.Models { - public class VariablesSet + public partial class VariablesSet : ObservableObject { public static readonly Guid UserGuid = new Guid("92F7AA9A-AE31-49CD-83C8-80A71E432AA5"); public static readonly Guid SystemGuid = new Guid("F679C74D-DB00-4795-92E1-B1F6A4833279"); @@ -19,7 +19,8 @@ namespace EnvironmentVariables.Models public Guid Id { get; } - public string Name { get; } + [ObservableProperty] + private string _name; public VariablesSetType Type { get; } @@ -27,6 +28,10 @@ namespace EnvironmentVariables.Models public List Variables { get; } + public VariablesSet() + { + } + public VariablesSet(Guid id, string name, VariablesSetType type) { Id = id; diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/Strings/en-us/Resources.resw b/src/modules/EnvironmentVariables/EnvironmentVariables/Strings/en-us/Resources.resw index a6b7784eb1..0d71f64286 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/Strings/en-us/Resources.resw +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/Strings/en-us/Resources.resw @@ -156,4 +156,28 @@ Value + + Add + + + Add new profile + + + Enabled + + + Add variable + + + Variable name + + + Variable value + + + Existing + + + New + \ No newline at end of file diff --git a/src/modules/EnvironmentVariables/EnvironmentVariables/ViewModels/MainViewModel.cs b/src/modules/EnvironmentVariables/EnvironmentVariables/ViewModels/MainViewModel.cs index 6c94c62827..10754fd1b9 100644 --- a/src/modules/EnvironmentVariables/EnvironmentVariables/ViewModels/MainViewModel.cs +++ b/src/modules/EnvironmentVariables/EnvironmentVariables/ViewModels/MainViewModel.cs @@ -3,15 +3,18 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using EnvironmentVariables.Helpers; using EnvironmentVariables.Models; +using Microsoft.UI.Xaml; +using static EnvironmentVariables.Models.Common; namespace EnvironmentVariables.ViewModels { - public partial class MainViewModel + public partial class MainViewModel : ObservableObject { public DefaultVariablesSet UserDefaultSet { get; private set; } = new DefaultVariablesSet(VariablesSet.UserGuid, ResourceLoaderInstance.ResourceLoader.GetString("User"), VariablesSetType.User); @@ -19,6 +22,16 @@ namespace EnvironmentVariables.ViewModels public ObservableCollection Profiles { get; private set; } = new ObservableCollection(); + public ProfileVariablesSet AppliedProfile { get; set; } + + internal AddVariablePageKind CurrentAddVariablePage { get; set; } + + [ObservableProperty] + private Visibility _showAddNewVariablePage; + + [ObservableProperty] + private Visibility _showAddExistingVariablePage; + public MainViewModel() { } @@ -30,11 +43,14 @@ namespace EnvironmentVariables.ViewModels EnvironmentVariablesHelper.GetVariables(EnvironmentVariableTarget.User, UserDefaultSet); var profile1 = new ProfileVariablesSet(Guid.NewGuid(), "profile1"); - profile1.Variables.Add(new Variable("profile11", "pvalue1", VariablesSetType.Profile)); - profile1.Variables.Add(new Variable("profile12", "pvalue2", VariablesSetType.Profile)); + profile1.Variables.Add(new Variable("testvar1", "pvalue1", VariablesSetType.Profile)); + profile1.Variables.Add(new Variable("p11", "pvalue2", VariablesSetType.Profile)); + profile1.PropertyChanged += Profile_PropertyChanged; + var profile2 = new ProfileVariablesSet(Guid.NewGuid(), "profile2"); - profile2.Variables.Add(new Variable("profile21", "pvalue11", VariablesSetType.Profile)); - profile2.Variables.Add(new Variable("profile22", "pvalue22", VariablesSetType.Profile)); + profile2.Variables.Add(new Variable("ppp22", "pvalue11", VariablesSetType.Profile)); + profile2.Variables.Add(new Variable("pp22", "pvalue22", VariablesSetType.Profile)); + profile2.PropertyChanged += Profile_PropertyChanged; Profiles.Add(profile1); Profiles.Add(profile2); @@ -44,5 +60,71 @@ namespace EnvironmentVariables.ViewModels { original.Update(edited); } + + internal void AddProfile(ProfileVariablesSet profile) + { + profile.PropertyChanged += Profile_PropertyChanged; + if (profile.IsEnabled) + { + UnsetAppliedProfile(); + SetAppliedProfile(profile); + } + + Profiles.Add(profile); + } + + private void Profile_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + var profile = sender as ProfileVariablesSet; + + if (profile != null) + { + if (e.PropertyName == nameof(ProfileVariablesSet.IsEnabled)) + { + if (profile.IsEnabled) + { + UnsetAppliedProfile(); + SetAppliedProfile(profile); + } + else + { + UnsetAppliedProfile(); + } + } + } + } + + private void SetAppliedProfile(ProfileVariablesSet profile) + { + profile.Apply(); + AppliedProfile = profile; + } + + private void UnsetAppliedProfile() + { + if (AppliedProfile != null) + { + var appliedProfile = AppliedProfile; + appliedProfile.PropertyChanged -= Profile_PropertyChanged; + AppliedProfile.UnApply(); + AppliedProfile.IsEnabled = false; + AppliedProfile = null; + appliedProfile.PropertyChanged += Profile_PropertyChanged; + } + } + + internal void ChangeToNewVariablePage() + { + ShowAddExistingVariablePage = Visibility.Collapsed; + ShowAddNewVariablePage = Visibility.Visible; + CurrentAddVariablePage = AddVariablePageKind.AddNewVariable; + } + + internal void ChangeToExistingVariablePage() + { + ShowAddNewVariablePage = Visibility.Collapsed; + ShowAddExistingVariablePage = Visibility.Visible; + CurrentAddVariablePage = AddVariablePageKind.AddExistingVariable; + } } }