Files
PowerToys/src/modules/EnvironmentVariables/EnvironmentVariables/Models/ProfileVariablesSet.cs
Stefan Markovic 812b343776 🚧 [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>
2023-10-20 16:28:07 +02:00

165 lines
5.3 KiB
C#

// 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.Collections.ObjectModel;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using EnvironmentVariables.Helpers;
using ManagedCommon;
namespace EnvironmentVariables.Models
{
public partial class ProfileVariablesSet : VariablesSet
{
[ObservableProperty]
private bool _isEnabled;
public ProfileVariablesSet()
: base()
{
Type = VariablesSetType.Profile;
IconPath = ProfileIconPath;
}
public ProfileVariablesSet(Guid id, string name)
: base(id, name, VariablesSetType.Profile)
{
IconPath = ProfileIconPath;
}
public Task Apply()
{
return Task.Run(() =>
{
foreach (var variable in Variables)
{
var applyToSystem = variable.ApplyToSystem;
// 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.ParentType == VariablesSetType.User)
{
variableToOverride.Name = EnvironmentVariablesHelper.GetBackupVariableName(variableToOverride, this.Name);
// Backup the variable
if (!EnvironmentVariablesHelper.SetVariableWithoutNotify(variableToOverride))
{
Logger.LogError("Failed to set backup variable.");
}
}
if (!EnvironmentVariablesHelper.SetVariableWithoutNotify(variable))
{
Logger.LogError("Failed to set profile variable.");
}
}
EnvironmentVariablesHelper.NotifyEnvironmentChange();
});
}
public Task UnApply()
{
return Task.Run(() =>
{
foreach (var variable in Variables)
{
UnapplyVariable(variable);
}
EnvironmentVariablesHelper.NotifyEnvironmentChange();
});
}
public void UnapplyVariable(Variable variable)
{
// Unset the variable
if (!EnvironmentVariablesHelper.UnsetVariableWithoutNotify(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.UnsetVariableWithoutNotify(backupVariable))
{
Logger.LogError("Failed to unset backup variable.");
}
if (!EnvironmentVariablesHelper.SetVariableWithoutNotify(variableToRestore))
{
Logger.LogError("Failed to restore backup variable.");
}
}
}
public bool IsCorrectlyApplied()
{
if (!IsEnabled)
{
return false;
}
foreach (var variable in Variables)
{
var applied = EnvironmentVariablesHelper.GetExisting(variable.Name);
if (applied != null && applied.Values == variable.Values && applied.ParentType == VariablesSetType.User)
{
continue;
}
return false;
}
return true;
}
public bool IsApplicable()
{
foreach (var variable in Variables)
{
if (!variable.Validate())
{
return false;
}
// Get existing variable with the same name if it exist
var variableToOverride = EnvironmentVariablesHelper.GetExisting(variable.Name);
// It exists. Backup is needed.
if (variableToOverride != null && variableToOverride.ParentType == VariablesSetType.User)
{
variableToOverride.Name = EnvironmentVariablesHelper.GetBackupVariableName(variableToOverride, this.Name);
if (!variableToOverride.Validate())
{
return false;
}
}
}
return true;
}
public ProfileVariablesSet Clone()
{
var clone = new ProfileVariablesSet(this.Id, this.Name);
clone.Variables = new ObservableCollection<Variable>(this.Variables);
clone.IsEnabled = this.IsEnabled;
return clone;
}
}
}