mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
New Utility: New+ (#33136)
Co-authored-by: Jaime Bernardo <jaime@janeasystems.com> Co-authored-by: Stefan Markovic <stefan@janeasystems.com>
This commit is contained in:
committed by
GitHub
parent
d7a07dc7c8
commit
3f44ad186d
@@ -462,6 +462,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
}
|
||||
}
|
||||
|
||||
private bool newPlus;
|
||||
|
||||
[JsonPropertyName("NewPlus")] // This key must match newplus::constants::non_localizable
|
||||
public bool NewPlus
|
||||
{
|
||||
get => newPlus;
|
||||
set
|
||||
{
|
||||
if (newPlus != value)
|
||||
{
|
||||
LogTelemetryEvent(value);
|
||||
newPlus = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool workspaces = true;
|
||||
|
||||
[JsonPropertyName("Workspaces")]
|
||||
|
||||
48
src/settings-ui/Settings.UI.Library/NewPlusSettings.cs
Normal file
48
src/settings-ui/Settings.UI.Library/NewPlusSettings.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
using Settings.UI.Library.Resources;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
public class NewPlusSettings : ISettingsConfig
|
||||
{
|
||||
public const string ModuleName = "NewPlus";
|
||||
|
||||
public void InitializeWithDefaultSettings()
|
||||
{
|
||||
// This code path should never happen
|
||||
}
|
||||
|
||||
public string ToJsonString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
|
||||
[JsonPropertyName("HideFileExtension")]
|
||||
public bool HideFileExtension { get; set; }
|
||||
|
||||
[JsonPropertyName("HideStartingDigits")]
|
||||
public bool HideStartingDigits { get; set; }
|
||||
|
||||
[JsonPropertyName("TemplateLocation")]
|
||||
public string TemplateLocation { get; set; }
|
||||
|
||||
public string GetModuleName()
|
||||
{
|
||||
return ModuleName;
|
||||
}
|
||||
|
||||
public bool UpgradeSettingsConfiguration()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,6 +96,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
|
||||
return Directory.GetParent(settingsPath).FullName;
|
||||
}
|
||||
|
||||
public static string GetPowerToysInstallationWinUI3AppsAssetsFolder()
|
||||
{
|
||||
// return .\PowerToys\WinUI3Apps\Assets
|
||||
return Path.Combine(GetPowerToysInstallationFolder(), "WinUI3Apps", "Assets");
|
||||
}
|
||||
|
||||
private static readonly global::PowerToys.Interop.LayoutMapManaged LayoutMap = new global::PowerToys.Interop.LayoutMapManaged();
|
||||
|
||||
public static string GetKeyName(uint key)
|
||||
@@ -148,6 +154,30 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
|
||||
}
|
||||
}
|
||||
|
||||
public static void CopyDirectory(string source_directory, string destination_directory, bool copy_recursively)
|
||||
{
|
||||
var current_directory_info = new DirectoryInfo(source_directory);
|
||||
|
||||
DirectoryInfo[] source_subdirectories = current_directory_info.GetDirectories();
|
||||
|
||||
Directory.CreateDirectory(destination_directory);
|
||||
|
||||
foreach (FileInfo file in current_directory_info.GetFiles())
|
||||
{
|
||||
string destination_file_path = Path.Combine(destination_directory, file.Name);
|
||||
file.CopyTo(destination_file_path, true);
|
||||
}
|
||||
|
||||
if (copy_recursively)
|
||||
{
|
||||
foreach (DirectoryInfo subdirectory in source_subdirectories)
|
||||
{
|
||||
string newDestinationDir = Path.Combine(destination_directory, subdirectory.Name);
|
||||
CopyDirectory(subdirectory.FullName, newDestinationDir, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly uint VirtualKeyWindows = global::PowerToys.Interop.Constants.VK_WIN_BOTH;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/settings-ui/Settings.UI/Assets/Settings/Icons/NewPlus.png
Normal file
BIN
src/settings-ui/Settings.UI/Assets/Settings/Icons/NewPlus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
BIN
src/settings-ui/Settings.UI/Assets/Settings/Modules/NewPlus.png
Normal file
BIN
src/settings-ui/Settings.UI/Assets/Settings/Modules/NewPlus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 322 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 879 KiB |
@@ -62,6 +62,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
case ModuleType.MouseJump: return generalSettingsConfig.Enabled.MouseJump;
|
||||
case ModuleType.MousePointerCrosshairs: return generalSettingsConfig.Enabled.MousePointerCrosshairs;
|
||||
case ModuleType.MouseWithoutBorders: return generalSettingsConfig.Enabled.MouseWithoutBorders;
|
||||
case ModuleType.NewPlus: return generalSettingsConfig.Enabled.NewPlus;
|
||||
case ModuleType.Peek: return generalSettingsConfig.Enabled.Peek;
|
||||
case ModuleType.PowerRename: return generalSettingsConfig.Enabled.PowerRename;
|
||||
case ModuleType.PowerLauncher: return generalSettingsConfig.Enabled.PowerLauncher;
|
||||
@@ -95,6 +96,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
case ModuleType.MouseJump: generalSettingsConfig.Enabled.MouseJump = isEnabled; break;
|
||||
case ModuleType.MousePointerCrosshairs: generalSettingsConfig.Enabled.MousePointerCrosshairs = isEnabled; break;
|
||||
case ModuleType.MouseWithoutBorders: generalSettingsConfig.Enabled.MouseWithoutBorders = isEnabled; break;
|
||||
case ModuleType.NewPlus: generalSettingsConfig.Enabled.NewPlus = isEnabled; break;
|
||||
case ModuleType.Peek: generalSettingsConfig.Enabled.Peek = isEnabled; break;
|
||||
case ModuleType.PowerRename: generalSettingsConfig.Enabled.PowerRename = isEnabled; break;
|
||||
case ModuleType.PowerLauncher: generalSettingsConfig.Enabled.PowerLauncher = isEnabled; break;
|
||||
@@ -127,6 +129,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
case ModuleType.MouseJump: return GPOWrapper.GetConfiguredMouseJumpEnabledValue();
|
||||
case ModuleType.MousePointerCrosshairs: return GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
|
||||
case ModuleType.MouseWithoutBorders: return GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue();
|
||||
case ModuleType.NewPlus: return GPOWrapper.GetConfiguredNewPlusEnabledValue();
|
||||
case ModuleType.Peek: return GPOWrapper.GetConfiguredPeekEnabledValue();
|
||||
case ModuleType.PowerRename: return GPOWrapper.GetConfiguredPowerRenameEnabledValue();
|
||||
case ModuleType.PowerLauncher: return GPOWrapper.GetConfiguredPowerLauncherEnabledValue();
|
||||
@@ -160,6 +163,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
ModuleType.MouseJump => typeof(MouseUtilsPage),
|
||||
ModuleType.MousePointerCrosshairs => typeof(MouseUtilsPage),
|
||||
ModuleType.MouseWithoutBorders => typeof(MouseWithoutBordersPage),
|
||||
ModuleType.NewPlus => typeof(NewPlusPage),
|
||||
ModuleType.Peek => typeof(PeekPage),
|
||||
ModuleType.PowerRename => typeof(PowerRenamePage),
|
||||
ModuleType.PowerLauncher => typeof(PowerLauncherPage),
|
||||
|
||||
@@ -26,6 +26,11 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
}
|
||||
|
||||
public static string GetFolderDialog(IntPtr hwndOwner)
|
||||
{
|
||||
return GetFolderDialogWithFlags(hwndOwner, 0);
|
||||
}
|
||||
|
||||
public static string GetFolderDialogWithFlags(IntPtr hwndOwner, uint ulFlags)
|
||||
{
|
||||
// windows MAX_PATH with long path enable can be approximated 32k char long
|
||||
// allocating more than double (unicode) to hold the path
|
||||
@@ -37,7 +42,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
browseInfo.PidlRoot = IntPtr.Zero;
|
||||
browseInfo.PszDisplayName = null;
|
||||
browseInfo.LpszTitle = null;
|
||||
browseInfo.UlFlags = 0;
|
||||
browseInfo.UlFlags = ulFlags;
|
||||
browseInfo.Lpfn = null;
|
||||
browseInfo.LParam = IntPtr.Zero;
|
||||
browseInfo.IImage = 0;
|
||||
@@ -61,5 +66,10 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public struct FolderDialogFlags
|
||||
{
|
||||
public const uint _BIF_NEWDIALOGSTYLE = 0x00000040;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,6 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
|
||||
Workspaces,
|
||||
WhatsNew,
|
||||
RegistryPreview,
|
||||
NewPlus,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<None Remove="Assets\Settings\Modules\APDialog.dark.png" />
|
||||
<None Remove="Assets\Settings\Modules\APDialog.light.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Remove="SettingsXAML\App.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -424,6 +424,7 @@ namespace Microsoft.PowerToys.Settings.UI
|
||||
case "Peek": return typeof(PeekPage);
|
||||
case "CropAndLock": return typeof(CropAndLockPage);
|
||||
case "EnvironmentVariables": return typeof(EnvironmentVariablesPage);
|
||||
case "NewPlus": return typeof(NewPlusPage);
|
||||
case "Workspaces": return typeof(WorkspacesPage);
|
||||
default:
|
||||
// Fallback to Dashboard
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeNewPlus"
|
||||
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:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<!-- TODO: Create New+ overview .gif and update ref here -->
|
||||
<controls:OOBEPageControl x:Uid="Oobe_NewPlus" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/NewPlus.png">
|
||||
<controls:OOBEPageControl.PageContent>
|
||||
<StackPanel Orientation="Vertical" Spacing="12">
|
||||
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
|
||||
<tk7controls:MarkdownTextBlock x:Uid="Oobe_NewPlus_HowToUse" Background="Transparent" />
|
||||
|
||||
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
|
||||
<tk7controls:MarkdownTextBlock x:Uid="Oobe_NewPlus_TipsAndTricks" Background="Transparent" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />
|
||||
|
||||
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_NewPlus" Style="{StaticResource TextButtonStyle}">
|
||||
<TextBlock x:Uid="NewPlus_Learn_More" TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</controls:OOBEPageControl.PageContent>
|
||||
</controls:OOBEPageControl>
|
||||
</Page>
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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.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
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class OobeNewPlus : Page
|
||||
{
|
||||
public OobePowerToysModule ViewModel { get; set; }
|
||||
|
||||
public OobeNewPlus()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.NewPlus]);
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
if (OobeShellPage.OpenMainWindowCallback != null)
|
||||
{
|
||||
OobeShellPage.OpenMainWindowCallback(typeof(NewPlusPage));
|
||||
}
|
||||
|
||||
ViewModel.LogOpeningSettingsEvent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
ViewModel.LogOpeningModuleEvent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||
{
|
||||
ViewModel.LogClosingModuleEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,10 @@
|
||||
x:Uid="Shell_MouseWithoutBorders"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseWithoutBorders.png}"
|
||||
Tag="MouseWithoutBorders" />
|
||||
<NavigationViewItem
|
||||
x:Uid="NewPlus_Product_Name"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/NewPlus.png}"
|
||||
Tag="NewPlus" />
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_Peek"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/Peek.png}"
|
||||
|
||||
@@ -207,6 +207,12 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
ModuleName = "RegistryPreview",
|
||||
IsNew = true,
|
||||
});
|
||||
|
||||
Modules.Insert((int)PowerToysModules.NewPlus, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "NewPlus",
|
||||
IsNew = true,
|
||||
});
|
||||
}
|
||||
|
||||
public void OnClosing()
|
||||
@@ -285,6 +291,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
case "Hosts": NavigationFrame.Navigate(typeof(OobeHosts)); break;
|
||||
case "RegistryPreview": NavigationFrame.Navigate(typeof(OobeRegistryPreview)); break;
|
||||
case "Peek": NavigationFrame.Navigate(typeof(OobePeek)); break;
|
||||
case "NewPlus": NavigationFrame.Navigate(typeof(OobeNewPlus)); break;
|
||||
case "Workspaces": NavigationFrame.Navigate(typeof(OobeWorkspaces)); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Views.NewPlusPage"
|
||||
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="NewPlus" ModuleImageSource="ms-appx:///Assets/Settings/Modules/NewPlus.png">
|
||||
<controls:SettingsPageControl.ModuleContent>
|
||||
<StackPanel
|
||||
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
|
||||
Orientation="Vertical"
|
||||
Spacing="2">
|
||||
<tkcontrols:SettingsCard
|
||||
x:Uid="NewPlus_Enable_Toggle"
|
||||
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/NewPlus.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="NewPlus_NoWindows10SupportWarning"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind ViewModel.IsWin10OrLower, Mode=OneWay}"
|
||||
IsTabStop="{x:Bind ViewModel.IsWin10OrLower, Mode=OneWay}"
|
||||
Severity="Warning" />
|
||||
|
||||
<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="NewPlus_Templates" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
|
||||
<tkcontrols:SettingsCard
|
||||
x:Uid="NewPlus_Templates_Location"
|
||||
ActionIcon="{ui:FontIcon Glyph=}"
|
||||
Command="{x:Bind ViewModel.OpenCurrentNewTemplateFolder}"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsClickEnabled="True">
|
||||
<Button
|
||||
x:Uid="NewPlus_Templates_Location_Change"
|
||||
Command="{x:Bind ViewModel.PickAnotherNewTemplateFolder}"
|
||||
Style="{ThemeResource AccentButtonStyle}" />
|
||||
|
||||
<tkcontrols:SettingsCard.Description>
|
||||
<StackPanel>
|
||||
<TextBlock Text="{x:Bind ViewModel.TemplateLocation, Mode=OneWay}" />
|
||||
<HyperlinkButton x:Uid="NewPlus_Templates_Location_Learn_More" NavigateUri="https://aka.ms/PowerToysOverview_NewPlus_TemplatesLocation" />
|
||||
</StackPanel>
|
||||
</tkcontrols:SettingsCard.Description>
|
||||
|
||||
</tkcontrols:SettingsCard>
|
||||
|
||||
<InfoBar
|
||||
x:Uid="NewPlus_TemplatesNotBackupAndRestoreWarning"
|
||||
IsClosable="True"
|
||||
IsOpen="True"
|
||||
IsTabStop="True"
|
||||
Severity="Informational" />
|
||||
|
||||
</controls:SettingsGroup>
|
||||
|
||||
<controls:SettingsGroup x:Uid="NewPlus_Display_Options" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
|
||||
<tkcontrols:SettingsCard x:Uid="NewPlus_Hide_File_Extension_Toggle" IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||
<ToggleSwitch x:Uid="HideFileExtensionToggle" IsOn="{x:Bind ViewModel.HideFileExtension, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard x:Uid="NewPlus_Hide_Starting_Digits_Toggle" IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||
<ToggleSwitch x:Uid="HideStartingDigitsToggle" IsOn="{x:Bind ViewModel.HideStartingDigits, Mode=TwoWay}" />
|
||||
<tkcontrols:SettingsCard.Description>
|
||||
<TextBlock x:Uid="NewPlus_Hide_Starting_Digits_Description" />
|
||||
</tkcontrols:SettingsCard.Description>
|
||||
</tkcontrols:SettingsCard>
|
||||
</controls:SettingsGroup>
|
||||
</StackPanel>
|
||||
</controls:SettingsPageControl.ModuleContent>
|
||||
|
||||
<controls:SettingsPageControl.PrimaryLinks>
|
||||
<controls:PageLink x:Uid="NewPlus_Learn_More" Link="https://aka.ms/PowerToysOverview_NewPlus" />
|
||||
</controls:SettingsPageControl.PrimaryLinks>
|
||||
<controls:SettingsPageControl.SecondaryLinks>
|
||||
<controls:PageLink Link="https://www.linkedin.com/in/christian-gaardmark/" Text="Christian Gaardmark" />
|
||||
</controls:SettingsPageControl.SecondaryLinks>
|
||||
</controls:SettingsPageControl>
|
||||
|
||||
</Page>
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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.Tasks;
|
||||
using System.Windows;
|
||||
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 NewPlusPage : Page, IRefreshablePage
|
||||
{
|
||||
private NewPlusViewModel ViewModel { get; set; }
|
||||
|
||||
public NewPlusPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
var settings_utils = new SettingsUtils();
|
||||
ViewModel = new NewPlusViewModel(settings_utils, SettingsRepository<GeneralSettings>.GetInstance(settings_utils), ShellPage.SendDefaultIPCMessage);
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
public void RefreshEnabledState()
|
||||
{
|
||||
ViewModel.RefreshEnabledState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,6 +180,11 @@
|
||||
helpers:NavHelper.NavigateTo="views:MouseWithoutBordersPage"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseWithoutBorders.png}" />
|
||||
|
||||
<NavigationViewItem
|
||||
x:Uid="NewPlus_Product_Name"
|
||||
helpers:NavHelper.NavigateTo="views:NewPlusPage"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/NewPlus.png}" />
|
||||
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_Peek"
|
||||
helpers:NavHelper.NavigateTo="views:PeekPage"
|
||||
|
||||
@@ -4276,6 +4276,88 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>Automatically close the AdvancedPaste window after it loses focus</value>
|
||||
<comment>AdvancedPaste is a product name, do not loc</comment>
|
||||
</data>
|
||||
<data name="NewPlus.ModuleTitle" xml:space="preserve">
|
||||
<value>New+</value>
|
||||
<comment>New+ is the name of the utility. Localize product name in accordance with Windows New</comment>
|
||||
</data>
|
||||
<data name="NewPlus.ModuleDescription" xml:space="preserve">
|
||||
<value>Create files and folders from a personalized set of templates</value>
|
||||
</data>
|
||||
<data name="NewPlus_Product_Name.Content" xml:space="preserve">
|
||||
<value>New+</value>
|
||||
<comment>New+ is the name of the utility. Localize product name in accordance with Windows New</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Product_Description.Description" xml:space="preserve">
|
||||
<value>Create files and folders from a personalized set of templates</value>
|
||||
<comment>New+ product description</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Learn_More.Text" xml:space="preserve">
|
||||
<value>Learn more about New+</value>
|
||||
<comment>New+ learn more link. Localize product name in accordance with Windows New</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Enable_Toggle.Header" xml:space="preserve">
|
||||
<value>Enable New+</value>
|
||||
<comment>Localize product name in accordance with Windows New</comment>
|
||||
</data>
|
||||
<data name="NewPlus_NoWindows10SupportWarning.Title" xml:space="preserve">
|
||||
<value>New+ is not supported in Windows 10 and is not expected to work.</value>
|
||||
</data>
|
||||
<data name="NewPlus_TemplatesNotBackupAndRestoreWarning.Title" xml:space="preserve">
|
||||
<value>PowerToys "Backup and Restore" feature doesn't take templates into account at this moment. If you use that feature, templates will have to be copied manually.</value>
|
||||
</data>
|
||||
<data name="NewPlus_Templates.Header" xml:space="preserve">
|
||||
<value>Templates</value>
|
||||
<comment>Templates label</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Templates_Location.Header" xml:space="preserve">
|
||||
<value>Location</value>
|
||||
<comment>Templates Location label</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Templates_Location_Path.Text" xml:space="preserve">
|
||||
<value>...</value>
|
||||
<comment>Do not localize</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Templates_Location_Learn_More.Content" xml:space="preserve">
|
||||
<value>Learn more about template location</value>
|
||||
<comment>Read more about templates location</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Templates_Location_Change.Content" xml:space="preserve">
|
||||
<value>Change</value>
|
||||
<comment>Button where user can Change the location of New templates</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Display_Options.Header" xml:space="preserve">
|
||||
<value>Display options</value>
|
||||
<comment>Display options label</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Hide_File_Extension_Toggle.Header" xml:space="preserve">
|
||||
<value>Hide template filename extension</value>
|
||||
<comment>Template file name extension settings toggle</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Hide_Starting_Digits_Toggle.Header" xml:space="preserve">
|
||||
<value>Hide template filename starting digits, spaces, and dots</value>
|
||||
<comment>Template filename starting digits settings toggle</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Hide_Starting_Digits_Description.Text" xml:space="preserve">
|
||||
<value>This option is useful when using digits, spaces and dots at the beginning of filenames to control the display order of templates</value>
|
||||
<comment>Template filename starting digits settings toggle</comment>
|
||||
</data>
|
||||
<data name="NewPlus.SecondaryLinksHeader" xml:space="preserve">
|
||||
<value>Attribution</value>
|
||||
<comment>giving credit</comment>
|
||||
</data>
|
||||
<data name="Oobe_NewPlus.Title" xml:space="preserve">
|
||||
<value>New+</value>
|
||||
<comment>New+ is the name of the utility. Localize product name in accordance with Windows New</comment>
|
||||
</data>
|
||||
<data name="Oobe_NewPlus.Description" xml:space="preserve">
|
||||
<value>Create files and folders from a personalized set of templates.</value>
|
||||
</data>
|
||||
<data name="Oobe_NewPlus_HowToUse.Text" xml:space="preserve">
|
||||
<value>In File Explorer, right-click the desktop or a folder and via the New+ from the context menu select your template. You can add new templates by opening the template folder via "Open templates" and add new files and folders there.</value>
|
||||
</data>
|
||||
<data name="Oobe_NewPlus_TipsAndTricks.Text" xml:space="preserve">
|
||||
<value>You can have multiple templates of the same file type, and you can even template folders!</value>
|
||||
</data>
|
||||
<data name="Workspaces.ModuleDescription" xml:space="preserve">
|
||||
<value>Workspaces is a quick and easy way to launch a set of applications to custom positions and configurations with one-click.</value>
|
||||
</data>
|
||||
|
||||
@@ -125,6 +125,13 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
private void EnabledChangedOnUI(DashboardListItem dashboardListItem)
|
||||
{
|
||||
Views.ShellPage.UpdateGeneralSettingsCallback(dashboardListItem.Tag, dashboardListItem.IsEnabled);
|
||||
|
||||
if (dashboardListItem.Tag == ModuleType.NewPlus && dashboardListItem.IsEnabled == true)
|
||||
{
|
||||
var settingsUtils = new SettingsUtils();
|
||||
var settings = NewPlusViewModel.LoadSettings(settingsUtils);
|
||||
NewPlusViewModel.CopyTemplateExamples(settings.TemplateLocation);
|
||||
}
|
||||
}
|
||||
|
||||
public void ModuleEnabledChangedOnSettingsPage()
|
||||
@@ -178,6 +185,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
ModuleType.MeasureTool => GetModuleItemsMeasureTool(),
|
||||
ModuleType.ShortcutGuide => GetModuleItemsShortcutGuide(),
|
||||
ModuleType.PowerOCR => GetModuleItemsPowerOCR(),
|
||||
ModuleType.NewPlus => GetModuleItemsNewPlus(),
|
||||
_ => new ObservableCollection<DashboardModuleItem>(), // never called, all values listed above
|
||||
};
|
||||
}
|
||||
@@ -495,6 +503,15 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
return new ObservableCollection<DashboardModuleItem>(list);
|
||||
}
|
||||
|
||||
private ObservableCollection<DashboardModuleItem> GetModuleItemsNewPlus()
|
||||
{
|
||||
var list = new List<DashboardModuleItem>
|
||||
{
|
||||
new DashboardModuleTextItem() { Label = resourceLoader.GetString("NewPlus_Product_Description/Description") },
|
||||
};
|
||||
return new ObservableCollection<DashboardModuleItem>(list);
|
||||
}
|
||||
|
||||
internal void SWVersionButtonClicked()
|
||||
{
|
||||
NavigationService.Navigate(typeof(GeneralPage));
|
||||
|
||||
256
src/settings-ui/Settings.UI/ViewModels/NewPlusViewModel.cs
Normal file
256
src/settings-ui/Settings.UI/ViewModels/NewPlusViewModel.cs
Normal file
@@ -0,0 +1,256 @@
|
||||
// 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.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Common.UI;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
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;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
|
||||
using Windows.ApplicationModel.VoiceCommands;
|
||||
using Windows.System;
|
||||
using static Microsoft.PowerToys.Settings.UI.Helpers.ShellGetFolder;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class NewPlusViewModel : Observable
|
||||
{
|
||||
private GeneralSettings GeneralSettingsConfig { get; set; }
|
||||
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
|
||||
private NewPlusSettings Settings { get; set; }
|
||||
|
||||
private const string ModuleName = NewPlusSettings.ModuleName;
|
||||
|
||||
public NewPlusViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc)
|
||||
{
|
||||
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
|
||||
|
||||
// To obtain the general settings configurations of PowerToys Settings.
|
||||
ArgumentNullException.ThrowIfNull(settingsRepository);
|
||||
|
||||
GeneralSettingsConfig = settingsRepository.SettingsConfig;
|
||||
|
||||
Settings = LoadSettings(settingsUtils);
|
||||
|
||||
// Initialize properties
|
||||
_hideFileExtension = Settings.HideFileExtension;
|
||||
_hideStartingDigits = Settings.HideStartingDigits;
|
||||
_templateLocation = Settings.TemplateLocation;
|
||||
InitializeEnabledValue();
|
||||
|
||||
// set the callback functions value to handle outgoing IPC message.
|
||||
SendConfigMSG = ipcMSGCallBackFunc;
|
||||
}
|
||||
|
||||
private void InitializeEnabledValue()
|
||||
{
|
||||
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredNewPlusEnabledValue();
|
||||
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
// Get the enabled state from GPO.
|
||||
_enabledStateIsGPOConfigured = true;
|
||||
_isNewPlusEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isNewPlusEnabled = GeneralSettingsConfig.Enabled.NewPlus;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isNewPlusEnabled;
|
||||
set
|
||||
{
|
||||
if (_isNewPlusEnabled != value)
|
||||
{
|
||||
_isNewPlusEnabled = value;
|
||||
|
||||
GeneralSettingsConfig.Enabled.NewPlus = value;
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
|
||||
OutGoingGeneralSettings outgoingMessage = new OutGoingGeneralSettings(GeneralSettingsConfig);
|
||||
SendConfigMSG(outgoingMessage.ToString());
|
||||
|
||||
NotifySettingsChanged();
|
||||
|
||||
if (_isNewPlusEnabled == true)
|
||||
{
|
||||
CopyTemplateExamples(_templateLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsWin10OrLower
|
||||
{
|
||||
get => !OSVersionHelper.IsWindows11();
|
||||
}
|
||||
|
||||
public string TemplateLocation
|
||||
{
|
||||
get => _templateLocation;
|
||||
set
|
||||
{
|
||||
if (_templateLocation != value)
|
||||
{
|
||||
_templateLocation = value;
|
||||
Settings.TemplateLocation = value;
|
||||
OnPropertyChanged(nameof(TemplateLocation));
|
||||
|
||||
NotifySettingsChanged();
|
||||
|
||||
SaveSettingsToJson();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HideFileExtension
|
||||
{
|
||||
get => _hideFileExtension;
|
||||
set
|
||||
{
|
||||
if (_hideFileExtension != value)
|
||||
{
|
||||
_hideFileExtension = value;
|
||||
Settings.HideFileExtension = value;
|
||||
OnPropertyChanged(nameof(HideFileExtension));
|
||||
|
||||
NotifySettingsChanged();
|
||||
|
||||
SaveSettingsToJson();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HideStartingDigits
|
||||
{
|
||||
get => _hideStartingDigits;
|
||||
set
|
||||
{
|
||||
if (_hideStartingDigits != value)
|
||||
{
|
||||
_hideStartingDigits = value;
|
||||
Settings.HideStartingDigits = value;
|
||||
OnPropertyChanged(nameof(HideStartingDigits));
|
||||
|
||||
NotifySettingsChanged();
|
||||
|
||||
SaveSettingsToJson();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabledGpoConfigured
|
||||
{
|
||||
get => _enabledStateIsGPOConfigured;
|
||||
}
|
||||
|
||||
public ButtonClickCommand OpenCurrentNewTemplateFolder => new ButtonClickCommand(OpenNewTemplateFolder);
|
||||
|
||||
public ButtonClickCommand PickAnotherNewTemplateFolder => new ButtonClickCommand(PickNewTemplateFolder);
|
||||
|
||||
private void NotifySettingsChanged()
|
||||
{
|
||||
// Using InvariantCulture as this is an IPC message
|
||||
SendConfigMSG(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{{ \"powertoys\": {{ \"{0}\": {1} }} }}",
|
||||
ModuleName,
|
||||
JsonSerializer.Serialize(Settings)));
|
||||
}
|
||||
|
||||
private Func<string, int> SendConfigMSG { get; }
|
||||
|
||||
public static NewPlusSettings LoadSettings(ISettingsUtils settingsUtils)
|
||||
{
|
||||
NewPlusSettings settings = null;
|
||||
|
||||
try
|
||||
{
|
||||
settings = settingsUtils.GetSettings<NewPlusSettings>(NewPlusSettings.ModuleName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception encountered while reading {NewPlusSettings.ModuleName} settings.", e);
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static void CopyTemplateExamples(string templateLocation)
|
||||
{
|
||||
if (!Directory.Exists(templateLocation))
|
||||
{
|
||||
Directory.CreateDirectory(templateLocation);
|
||||
}
|
||||
|
||||
if (Directory.GetFiles(templateLocation).Length == 0 && Directory.GetDirectories(templateLocation).Length == 0)
|
||||
{
|
||||
// No files in templateLocation directory
|
||||
// Copy over examples files from <Program Files>\PowerToys\WinUI3Apps\Assets\NewPlus\Templates
|
||||
var example_templates = Path.Combine(Helper.GetPowerToysInstallationWinUI3AppsAssetsFolder(), "NewPlus", "Templates");
|
||||
Helper.CopyDirectory(example_templates, templateLocation, true);
|
||||
}
|
||||
}
|
||||
|
||||
private GpoRuleConfigured _enabledGpoRuleConfiguration;
|
||||
private bool _enabledStateIsGPOConfigured;
|
||||
private bool _isNewPlusEnabled;
|
||||
private string _templateLocation;
|
||||
private bool _hideFileExtension;
|
||||
private bool _hideStartingDigits;
|
||||
|
||||
public void RefreshEnabledState()
|
||||
{
|
||||
InitializeEnabledValue();
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
|
||||
private void OpenNewTemplateFolder()
|
||||
{
|
||||
var process = new ProcessStartInfo()
|
||||
{
|
||||
FileName = _templateLocation,
|
||||
UseShellExecute = true,
|
||||
};
|
||||
Process.Start(process);
|
||||
}
|
||||
|
||||
private async void PickNewTemplateFolder()
|
||||
{
|
||||
var newPath = await PickFolderDialog();
|
||||
if (newPath.Length > 1)
|
||||
{
|
||||
TemplateLocation = newPath;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> PickFolderDialog()
|
||||
{
|
||||
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.GetSettingsWindow());
|
||||
string pathFolder = await Task.FromResult<string>(ShellGetFolder.GetFolderDialogWithFlags(hwnd, ShellGetFolder.FolderDialogFlags._BIF_NEWDIALOGSTYLE));
|
||||
return pathFolder;
|
||||
}
|
||||
|
||||
private void SaveSettingsToJson()
|
||||
{
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user