First steps toward integration of the projects utility to PT

This commit is contained in:
donlaci
2024-06-11 13:32:40 +02:00
parent 1cf5d88507
commit 927ac511c8
17 changed files with 1172 additions and 1 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,7 @@ namespace ManagedCommon
PowerRename,
PowerLauncher,
PowerAccent,
Projects,
RegistryPreview,
MeasureTool,
ShortcutGuide,

View File

@@ -23,7 +23,7 @@
</PropertyGroup>
<PropertyGroup>
<ProjectGuid>{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}</ProjectGuid>
<ProjectGuid>{367D7543-7DBA-4381-99F1-BF6142A996C4}</ProjectGuid>
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>

View File

@@ -462,6 +462,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
private bool projects = true;
[JsonPropertyName("Projects")]
public bool Projects
{
get => projects;
set
{
if (projects != value)
{
LogTelemetryEvent(value);
projects = value;
NotifyChange();
}
}
}
private void NotifyChange()
{
notifyEnabledChangedAction?.Invoke();

View File

@@ -0,0 +1,27 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ProjectsProperties
{
public static readonly HotkeySettings DefaultHotkeyValue = new HotkeySettings(true, false, false, true, 0x50);
public ProjectsProperties()
{
Hotkey = new KeyboardKeysProperty(DefaultHotkeyValue);
}
[JsonPropertyName("hotkey")]
public KeyboardKeysProperty Hotkey { get; set; }
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

View File

@@ -0,0 +1,35 @@
// 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.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ProjectsSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "Projects";
public const string ModuleVersion = "0.0.1";
public ProjectsSettings()
{
Name = ModuleName;
Version = ModuleVersion;
Properties = new ProjectsProperties();
}
[JsonPropertyName("properties")]
public ProjectsProperties Properties { get; set; }
public string GetModuleName()
{
return Name;
}
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -64,6 +64,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
case ModuleType.PowerRename: return generalSettingsConfig.Enabled.PowerRename;
case ModuleType.PowerLauncher: return generalSettingsConfig.Enabled.PowerLauncher;
case ModuleType.PowerAccent: return generalSettingsConfig.Enabled.PowerAccent;
case ModuleType.Projects: return generalSettingsConfig.Enabled.Projects;
case ModuleType.RegistryPreview: return generalSettingsConfig.Enabled.RegistryPreview;
case ModuleType.MeasureTool: return generalSettingsConfig.Enabled.MeasureTool;
case ModuleType.ShortcutGuide: return generalSettingsConfig.Enabled.ShortcutGuide;
@@ -96,6 +97,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
case ModuleType.PowerRename: generalSettingsConfig.Enabled.PowerRename = isEnabled; break;
case ModuleType.PowerLauncher: generalSettingsConfig.Enabled.PowerLauncher = isEnabled; break;
case ModuleType.PowerAccent: generalSettingsConfig.Enabled.PowerAccent = isEnabled; break;
case ModuleType.Projects: generalSettingsConfig.Enabled.Projects = isEnabled; break;
case ModuleType.RegistryPreview: generalSettingsConfig.Enabled.RegistryPreview = isEnabled; break;
case ModuleType.MeasureTool: generalSettingsConfig.Enabled.MeasureTool = isEnabled; break;
case ModuleType.ShortcutGuide: generalSettingsConfig.Enabled.ShortcutGuide = isEnabled; break;
@@ -159,6 +161,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
ModuleType.PowerRename => typeof(PowerRenamePage),
ModuleType.PowerLauncher => typeof(PowerLauncherPage),
ModuleType.PowerAccent => typeof(PowerAccentPage),
ModuleType.Projects => typeof(ProjectsPage),
ModuleType.RegistryPreview => typeof(RegistryPreviewPage),
ModuleType.MeasureTool => typeof(MeasureToolPage),
ModuleType.ShortcutGuide => typeof(ShortcutGuidePage),

View File

@@ -25,6 +25,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
PowerRename,
Run,
QuickAccent,
Projects,
ShortcutGuide,
TextExtractor,
VideoConference,

View File

@@ -24,6 +24,7 @@
<ItemGroup>
<None Remove="Assets\Settings\Modules\APDialog.dark.png" />
<None Remove="Assets\Settings\Modules\APDialog.light.png" />
<None Remove="SettingsXAML\Views\ProjectsPage.xaml" />
</ItemGroup>
<ItemGroup>
@@ -142,4 +143,10 @@
</None>
</ItemGroup>
<ItemGroup>
<Page Update="SettingsXAML\Views\ProjectsPage.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
</ItemGroup>
</Project>

View File

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

View File

@@ -0,0 +1,46 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.ProjectsPage"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
AutomationProperties.LandmarkType="Main"
mc:Ignorable="d">
<controls:SettingsPageControl
x:Uid="Projects"
IsTabStop="False"
ModuleImageSource="ms-appx:///Assets/Settings/Modules/Projects.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
<tkcontrols:SettingsCard
x:Uid="Projects_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/Projects.png}"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
<controls:SettingsGroup x:Uid="Projects_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
x:Uid="Projects_ActivationShortcut"
HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}"
IsExpanded="True">
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind Path=ViewModel.Hotkey, Mode=TwoWay}" />
</tkcontrols:SettingsExpander>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_Projects" Link="https://aka.ms/PowerToysOverview_Projects" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Page>

View File

@@ -0,0 +1,29 @@
// 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 ProjectsPage : Page, IRefreshablePage
{
private ProjectsViewModel ViewModel { get; set; }
public ProjectsPage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new ProjectsViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<ProjectsSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@@ -199,6 +199,11 @@
helpers:NavHelper.NavigateTo="views:PowerAccentPage"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/QuickAccent.png}" />
<NavigationViewItem
x:Uid="Shell_Projects"
helpers:NavHelper.NavigateTo="views:ProjectsPage"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/Projects.png}" />
<NavigationViewItem
x:Uid="Shell_RegistryPreview"
helpers:NavHelper.NavigateTo="views:RegistryPreviewPage"

View File

@@ -3110,6 +3110,26 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
<data name="Shell_QuickAccent.Content" xml:space="preserve">
<value>Quick Accent</value>
</data>
<data name="Shell_Projects.Content" xml:space="preserve">
<value>Projects</value>
</data>
<data name="Projects_EnableToggleControl_HeaderText.Header" xml:space="preserve">
<value>Enable Projects</value>
<comment>"Projects" is the name of the utility</comment>
</data>
<data name="Projects_Activation_GroupSettings.Header" xml:space="preserve">
<value>Activation</value>
</data>
<data name="Projects_ActivationShortcut.Description" xml:space="preserve">
<value>Customize the shortcut to launch the Projects Editor</value>
</data>
<data name="Projects_ActivationShortcut.Header" xml:space="preserve">
<value>Activation shortcut</value>
</data>
<data name="LearnMore_Projects.Text" xml:space="preserve">
<value>Learn more about the Projects utility</value>
<comment> Projects is the name of the module. </comment>
</data>
<data name="QuickAccent.ModuleDescription" xml:space="preserve">
<value>Quick Accent is an alternative way to type accented characters, useful for when a keyboard doesn't support that specific accent.
@@ -4178,4 +4198,14 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="AdvancedPaste_EnableAIDialog_NoteAICreditsErrorText.Text" xml:space="preserve">
<value>If you do not have credits you will see an 'API key quota exceeded' error</value>
</data>
<data name="Projects.ModuleDescription" xml:space="preserve">
<value>Projects is a quick and easy way to launch multiple applications.</value>
<comment>{Locked="Always On Top"}</comment>
</data>
<data name="Projects.ModuleTitle" xml:space="preserve">
<value>Projects</value>
</data>
<data name="Projects_ShortDescription" xml:space="preserve">
<value>Create and launch workspaces</value>
</data>
</root>

View File

@@ -166,6 +166,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
ModuleType.PowerRename => GetModuleItemsPowerRename(),
ModuleType.PowerLauncher => GetModuleItemsPowerLauncher(),
ModuleType.PowerAccent => GetModuleItemsPowerAccent(),
ModuleType.Projects => GetModuleItemsProjects(),
ModuleType.RegistryPreview => GetModuleItemsRegistryPreview(),
ModuleType.MeasureTool => GetModuleItemsMeasureTool(),
ModuleType.ShortcutGuide => GetModuleItemsShortcutGuide(),
@@ -430,6 +431,15 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
return new ObservableCollection<DashboardModuleItem>(list);
}
private ObservableCollection<DashboardModuleItem> GetModuleItemsProjects()
{
var list = new List<DashboardModuleItem>
{
new DashboardModuleTextItem() { Label = resourceLoader.GetString("Projects_ShortDescription") },
};
return new ObservableCollection<DashboardModuleItem>(list);
}
private ObservableCollection<DashboardModuleItem> GetModuleItemsRegistryPreview()
{
var list = new List<DashboardModuleItem>

View File

@@ -0,0 +1,147 @@
// 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.Globalization;
using System.Runtime.CompilerServices;
using System.Text.Json;
using Common.UI;
using global::PowerToys.GPOWrapper;
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.Utilities;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class ProjectsViewModel : Observable
{
private ISettingsUtils SettingsUtils { get; set; }
private GeneralSettings GeneralSettingsConfig { get; set; }
private ProjectsSettings Settings { get; set; }
private Func<string, int> SendConfigMSG { get; }
public ProjectsViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<ProjectsSettings> moduleSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
{
ArgumentNullException.ThrowIfNull(settingsUtils);
SettingsUtils = settingsUtils;
// To obtain the general settings configurations of PowerToys Settings.
ArgumentNullException.ThrowIfNull(settingsRepository);
GeneralSettingsConfig = settingsRepository.SettingsConfig;
InitializeEnabledValue();
// To obtain the settings configurations of Projects.
ArgumentNullException.ThrowIfNull(moduleSettingsRepository);
Settings = moduleSettingsRepository.SettingsConfig;
_hotkey = Settings.Properties.Hotkey.Value;
// set the callback functions value to handle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
}
private void InitializeEnabledValue()
{
////_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredProjectsEnabledValue();
_enabledGpoRuleConfiguration = GpoRuleConfigured.NotConfigured;
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.Projects;
}
}
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.Projects = value;
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(snd.ToString());
OnPropertyChanged(nameof(IsEnabled));
}
}
}
public bool IsEnabledGpoConfigured
{
get => _enabledStateIsGPOConfigured;
}
public HotkeySettings Hotkey
{
get => _hotkey;
set
{
if (value != _hotkey)
{
if (value == null || value.IsEmpty())
{
_hotkey = ProjectsProperties.DefaultHotkeyValue;
}
else
{
_hotkey = value;
}
Settings.Properties.Hotkey.Value = _hotkey;
NotifyPropertyChanged();
// Using InvariantCulture as this is an IPC message
SendConfigMSG(
string.Format(
CultureInfo.InvariantCulture,
"{{ \"powertoys\": {{ \"{0}\": {1} }} }}",
ProjectsSettings.ModuleName,
JsonSerializer.Serialize(Settings)));
}
}
}
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(propertyName);
SettingsUtils.SaveSettings(Settings.ToJsonString(), ProjectsSettings.ModuleName);
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
private HotkeySettings _hotkey;
}
}