mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 19:57:07 +02:00
[EnvVar][Hosts][RegPrev]Decouple and refactor to make it "packable" as nuget package (#32604)
* WIP Hosts - remove deps * Add consumer app * Move App and MainWindow to Consumer app. Make Hosts dll * Try consume it * Fix errors * Make it work with custom build targets * Dependency injection Refactor Explicit page creation Wire missing dependencies * Fix installer * Remove unneeded stuff * Fix build again * Extract UI and logic from MainWindow to RegistryPreviewMainPage * Convert to lib Change namespace to RegistryPreviewUILib Remove PT deps * Add exe app and move App.xaml and MainWindow.xaml * Consume the lib * Update Hosts package creation * Fix RegistryPreview package creation * Rename RegistryPreviewUI back to RegistryPreview * Back to consuming lib * Ship icons and assets in nuget packages * Rename to EnvironmentVariablesUILib and convert to lib * Add app and consume * Telemetry * GPO * nuget * Rename HostsPackageConsumer to Hosts and Hosts lib to HostsUILib * Assets cleanup * nuget struct * v0 * assets * [Hosts] Re-add AppList to Lib Assets, [RegPrev] Copy lib assets to out dir * Sign UI dlls * Revert WinUIEx bump * Cleanup * Align deps * version exception dll * Fix RegistryPreview crashes * XAML format * XAML format 2 * Pack .pri files in lib/ dir --------- Co-authored-by: Darshak Bhatti <dabhatti@microsoft.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application
|
||||
x:Class="RegistryPreview.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:RegistryPreview">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Other app resources here -->
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,106 @@
|
||||
// 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.Web;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
namespace RegistryPreview
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="App"/> class.
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched.
|
||||
/// </summary>
|
||||
/// <param name="args">Details about the launch request and process.</param>
|
||||
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
|
||||
{
|
||||
// Keeping commented out but this is invaluable for protocol activation testing.
|
||||
// #if DEBUG
|
||||
// System.Diagnostics.Debugger.Launch();
|
||||
// #endif
|
||||
|
||||
// Open With... handler - gets activation arguments if they are available.
|
||||
AppActivationArguments activatedArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
|
||||
if (activatedArgs.Kind == ExtendedActivationKind.File)
|
||||
{
|
||||
// Covers the double click exe scenario and treated as no file loaded
|
||||
AppFilename = string.Empty;
|
||||
if (activatedArgs.Data != null)
|
||||
{
|
||||
IFileActivatedEventArgs eventArgs = (IFileActivatedEventArgs)activatedArgs.Data;
|
||||
if (eventArgs.Files.Count > 0)
|
||||
{
|
||||
AppFilename = eventArgs.Files[0].Path;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (activatedArgs.Kind == ExtendedActivationKind.Protocol)
|
||||
{
|
||||
// When the app is the default handler for REG files and the filename has non-ASCII characters, the app gets activated by Protocol
|
||||
AppFilename = string.Empty;
|
||||
if (activatedArgs.Data != null)
|
||||
{
|
||||
IProtocolActivatedEventArgs eventArgs = (IProtocolActivatedEventArgs)activatedArgs.Data;
|
||||
if (eventArgs.Uri.AbsoluteUri.Length > 0)
|
||||
{
|
||||
AppFilename = eventArgs.Uri.Query.Replace("?ContractId=Windows.File&Verb=open&File=", string.Empty);
|
||||
AppFilename = HttpUtility.UrlDecode(AppFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Right click on a REG file and selected Preview
|
||||
// Grab the command line parameters directly from the Environment since this is expected to be run
|
||||
// via Context Menu of a REG file.
|
||||
string[] cmdArgs = Environment.GetCommandLineArgs();
|
||||
if (cmdArgs == null)
|
||||
{
|
||||
// Covers the double click exe scenario and treated as no file loaded
|
||||
AppFilename = string.Empty;
|
||||
}
|
||||
else if (cmdArgs.Length == 2)
|
||||
{
|
||||
// GetCommandLineArgs() send in the called EXE as 0 and the selected filename as 1
|
||||
AppFilename = cmdArgs[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Anything else should be treated as no file loaded
|
||||
AppFilename = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the application
|
||||
appWindow = new MainWindow();
|
||||
appWindow.Activate();
|
||||
}
|
||||
|
||||
private Window appWindow;
|
||||
|
||||
#pragma warning disable SA1401 // Fields should be private
|
||||
#pragma warning disable CA2211 // Non-constant fields should not be visible. TODO: consider making it a property
|
||||
public static string AppFilename;
|
||||
#pragma warning restore CA2211 // Non-constant fields should not be visible
|
||||
#pragma warning restore SA1401 // Fields should be private
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<winuiex:WindowEx
|
||||
x:Class="RegistryPreview.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
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"
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
MinWidth="480"
|
||||
MinHeight="320"
|
||||
Closed="Window_Closed"
|
||||
mc:Ignorable="d">
|
||||
<Window.SystemBackdrop>
|
||||
<MicaBackdrop />
|
||||
</Window.SystemBackdrop>
|
||||
|
||||
<Grid x:Name="MainGrid" Loaded="Grid_Loaded">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid
|
||||
x:Name="titleBar"
|
||||
Grid.Row="0"
|
||||
Height="32"
|
||||
Margin="16,0"
|
||||
ColumnSpacing="16"
|
||||
IsHitTestVisible="True">
|
||||
<Grid.ColumnDefinitions>
|
||||
<!--<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>-->
|
||||
<ColumnDefinition x:Name="IconColumn" Width="Auto" />
|
||||
<ColumnDefinition x:Name="TitleColumn" Width="Auto" />
|
||||
<!--<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>-->
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
VerticalAlignment="Center"
|
||||
Source="../Assets/RegistryPreview/RegistryPreview.ico" />
|
||||
<TextBlock
|
||||
x:Name="titleBarText"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{Binding ApplicationTitle}" />
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</winuiex:WindowEx>
|
||||
@@ -0,0 +1,136 @@
|
||||
// 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 ManagedCommon;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using RegistryPreviewUILib;
|
||||
using Windows.Data.Json;
|
||||
using Windows.Graphics;
|
||||
using WinUIEx;
|
||||
|
||||
namespace RegistryPreview
|
||||
{
|
||||
public sealed partial class MainWindow : WindowEx
|
||||
{
|
||||
// Const values
|
||||
private const string APPNAME = "RegistryPreview";
|
||||
|
||||
// private members
|
||||
private Microsoft.UI.Windowing.AppWindow appWindow;
|
||||
private JsonObject jsonWindowPlacement;
|
||||
private string settingsFolder = string.Empty;
|
||||
private string windowPlacementFile = "app-placement.json";
|
||||
|
||||
private RegistryPreviewMainPage MainPage { get; }
|
||||
|
||||
internal MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
// Open settings file; this moved to after the window tweak because it gives the window time to start up
|
||||
settingsFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Microsoft\PowerToys\" + APPNAME;
|
||||
OpenWindowPlacementFile(settingsFolder, windowPlacementFile);
|
||||
|
||||
// Update the Win32 looking window with the correct icon (and grab the appWindow handle for later)
|
||||
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
||||
Microsoft.UI.WindowId windowId = Win32Interop.GetWindowIdFromWindow(windowHandle);
|
||||
appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
|
||||
appWindow.SetIcon("Assets\\RegistryPreview\\RegistryPreview.ico");
|
||||
|
||||
// TODO(stefan)
|
||||
appWindow.Closing += AppWindow_Closing;
|
||||
Activated += MainWindow_Activated;
|
||||
|
||||
// Extend the canvas to include the title bar so the app can support theming
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
SetTitleBar(titleBar);
|
||||
|
||||
// if have settings, update the location of the window
|
||||
if (jsonWindowPlacement != null)
|
||||
{
|
||||
// resize the window
|
||||
if (jsonWindowPlacement.ContainsKey("appWindow.Size.Width") && jsonWindowPlacement.ContainsKey("appWindow.Size.Height"))
|
||||
{
|
||||
SizeInt32 size;
|
||||
size.Width = (int)jsonWindowPlacement.GetNamedNumber("appWindow.Size.Width");
|
||||
size.Height = (int)jsonWindowPlacement.GetNamedNumber("appWindow.Size.Height");
|
||||
|
||||
// check to make sure the size values are reasonable before attempting to restore the last saved size
|
||||
if (size.Width >= 320 && size.Height >= 240)
|
||||
{
|
||||
appWindow.Resize(size);
|
||||
}
|
||||
}
|
||||
|
||||
// reposition the window
|
||||
if (jsonWindowPlacement.ContainsKey("appWindow.Position.X") && jsonWindowPlacement.ContainsKey("appWindow.Position.Y"))
|
||||
{
|
||||
PointInt32 point;
|
||||
point.X = (int)jsonWindowPlacement.GetNamedNumber("appWindow.Position.X");
|
||||
point.Y = (int)jsonWindowPlacement.GetNamedNumber("appWindow.Position.Y");
|
||||
|
||||
// check to make sure the move values are reasonable before attempting to restore the last saved location
|
||||
if (point.X >= 0 && point.Y >= 0)
|
||||
{
|
||||
appWindow.Move(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainPage = new RegistryPreviewMainPage(this, this.UpdateWindowTitle, App.AppFilename);
|
||||
|
||||
WindowHelpers.BringToForeground(windowHandle);
|
||||
}
|
||||
|
||||
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
|
||||
{
|
||||
if (args.WindowActivationState == WindowActivationState.Deactivated)
|
||||
{
|
||||
titleBarText.Foreground =
|
||||
(SolidColorBrush)Application.Current.Resources["WindowCaptionForegroundDisabled"];
|
||||
}
|
||||
else
|
||||
{
|
||||
titleBarText.Foreground =
|
||||
(SolidColorBrush)Application.Current.Resources["WindowCaptionForeground"];
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MainGrid.Children.Add(MainPage);
|
||||
Grid.SetRow(MainPage, 1);
|
||||
}
|
||||
|
||||
public void UpdateWindowTitle(string title)
|
||||
{
|
||||
string filename = title;
|
||||
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
{
|
||||
titleBarText.Text = APPNAME;
|
||||
appWindow.Title = APPNAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] file = filename.Split('\\');
|
||||
if (file.Length > 0)
|
||||
{
|
||||
titleBarText.Text = file[file.Length - 1] + " - " + APPNAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
titleBarText.Text = filename + " - " + APPNAME;
|
||||
}
|
||||
|
||||
// Continue to update the window's title, after updating the custom title bar
|
||||
appWindow.Title = titleBarText.Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user