Compare commits

..

1 Commits

Author SHA1 Message Date
Gordon Lam (SH)
d868a85b87 Add Version 2025-06-13 18:53:02 +08:00
38 changed files with 132 additions and 570 deletions

View File

@@ -1663,7 +1663,6 @@ TDefault
TDevice
telephon
templatenamespace
TESTONLY
testprocess
TEXCOORD
TEXTBOXNEWLINE
@@ -1716,7 +1715,6 @@ trx
tsa
TSender
TServer
tskill
tstoi
TStr
tweakme

View File

@@ -394,7 +394,10 @@ jobs:
testAssemblyVer2: |
**\KeyboardManagerEngineTest.dll
**\KeyboardManagerEditorTest.dll
**\*UnitTest*.dll
**\UnitTests-CommonLib.dll
**\PowerRenameUnitTests.dll
**\UnitTests-FancyZones.dll
**\\WorkspacesLibUnitTests.dll
!**\obj\**
- pwsh: |-

View File

@@ -28,8 +28,6 @@ $versionExceptions = @(
"ObjectModelCsProjection.dll",
"RendererCsProjection.dll") -join '|';
$nullVersionExceptions = @(
"SkiaSharp.Views.WinUI.Native.dll",
"libSkiaSharp.dll",
"codicon.ttf",
"e_sqlite3.dll",
"getfilesiginforedist.dll",

View File

@@ -181,6 +181,7 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
## PowerToys core team
- [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon - Lead
- [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager
- [@craigloewen-msft](https://github.com/craigloewen-msft) - Craig Loewen - Product Manager
- [@niels9001](https://github.com/niels9001/) - Niels Laute - Product Manager
- [@dhowett](https://github.com/dhowett) - Dustin Howett - Dev lead
@@ -212,7 +213,6 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
- [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang - Product Manager
- [@plante-msft](https://github.com/plante-msft) - Connor Plante - Product Manager
- [@joadoumie](https://github.com/joadoumie) - Jordi Adoumie - Product Manager
- [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager
- [@enricogior](https://github.com/enricogior) - Enrico Giordani - Dev Lead
- [@bzoz](https://github.com/bzoz) - Bartosz Sosnowski - Dev
- [@ivan100sic](https://github.com/ivan100sic) - Ivan Stošić - Dev

View File

@@ -1,36 +0,0 @@
#include <windows.h>
#include "resource.h"
#include "../version/version.h"
1 VERSIONINFO
FILEVERSION FILE_VERSION
PRODUCTVERSION PRODUCT_VERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
BEGIN
VALUE "CompanyName", COMPANY_NAME
VALUE "FileDescription", FILE_DESCRIPTION
VALUE "FileVersion", FILE_VERSION_STRING
VALUE "InternalName", INTERNAL_NAME
VALUE "LegalCopyright", COPYRIGHT_NOTE
VALUE "OriginalFilename", ORIGINAL_FILENAME
VALUE "ProductName", PRODUCT_NAME
VALUE "ProductVersion", PRODUCT_VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
END
END

View File

@@ -98,11 +98,6 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\version\version.vcxproj">
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ExprtkEvaluator.h" />
<ClInclude Include="pch.h" />
@@ -110,7 +105,6 @@
<ClInclude Include="Calculator.h">
<DependentUpon>Calculator.idl</DependentUpon>
</ClInclude>
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ExprtkEvaluator.cpp">
@@ -134,14 +128,16 @@
<ItemGroup>
<None Include="PropertySheet.props" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="CalculatorEngineCommon.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<ItemGroup>
<ProjectReference Include="..\version\version.vcxproj">
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
</ProjectReference>
</ItemGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>

View File

@@ -1,13 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by CalculatorEngineCommon.rc
//////////////////////////////
// Non-localizable
#define FILE_DESCRIPTION "CalculatorEngineCommon"
#define INTERNAL_NAME "CalculatorEngineCommon"
#define ORIGINAL_FILENAME "CalculatorEngineCommon.dll"
// Non-localizable
//////////////////////////////

View File

@@ -154,9 +154,6 @@
<ProjectReference Include="..\..\..\common\Telemetry\EtwTrace\EtwTrace.vcxproj">
<Project>{8f021b46-362b-485c-bfba-ccf83e820cbd}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />

View File

@@ -17,9 +17,6 @@
#include <common/Telemetry/EtwTrace/EtwTrace.h>
#include <common/Themes/theme_helpers.h>
#include <common/Themes/theme_listener.h>
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
namespace winrt
@@ -38,23 +35,6 @@ namespace util
const std::wstring instanceMutexName = L"Local\\PowerToys_CropAndLock_InstanceMutex";
bool m_running = true;
// Theming
ThemeListener theme_listener{};
// Keep a list of our cropped windows
std::vector<std::shared_ptr<CropAndLockWindow>> croppedWindows;
void handleTheme()
{
auto theme = theme_listener.AppTheme;
auto isDark = theme == Theme::Dark;
Logger::info(L"Theme is now {}", isDark ? L"Dark" : L"Light");
for (auto&& croppedWindow : croppedWindows)
{
ThemeHelpers::SetImmersiveDarkMode(croppedWindow->Handle(), isDark);
}
}
int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _In_ int)
{
// Initialize COM
@@ -62,8 +42,6 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
Trace::CropAndLock::RegisterProvider();
theme_listener.AddChangedHandler(handleTheme);
Shared::Trace::ETWTrace trace;
trace.UpdateState(true);
@@ -129,6 +107,8 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
// Create our overlay window
std::unique_ptr<OverlayWindow> overlayWindow;
// Keep a list of our cropped windows
std::vector<std::shared_ptr<CropAndLockWindow>> croppedWindows;
// Handles and thread for the events sent from runner
HANDLE m_reparent_event_handle;
@@ -187,7 +167,6 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
croppedWindow->CropAndLock(targetWindow, cropRect);
croppedWindow->OnClosed(removeWindowCallback);
croppedWindows.push_back(croppedWindow);
handleTheme();
};
overlayWindow.reset();

View File

@@ -6,7 +6,6 @@
<PropertyGroup>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<DefineConstants>TESTONLY</DefineConstants>
</PropertyGroup>
<PropertyGroup>

View File

@@ -611,7 +611,6 @@
<ContentDialog
x:Name="EntryDialog"
x:Uid="EntryDialog"
x:DataType="models:Entry"
IsPrimaryButtonEnabled="{Binding Valid, Mode=OneWay}"
Loaded="ContentDialog_Loaded_ApplyMargin"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}">

View File

@@ -139,23 +139,10 @@ namespace HostsUILib.Views
dialog.XamlRoot = XamlRoot;
dialog.Style = Application.Current.Resources["DefaultContentDialogStyle"] as Style;
dialog.Title = resourceLoader.GetString("WarningDialog_Title");
dialog.Content = new StackPanel
dialog.Content = new TextBlock
{
Children =
{
new TextBlock
{
Text = resourceLoader.GetString("WarningDialog_Text"),
TextWrapping = TextWrapping.Wrap,
},
new HyperlinkButton
{
Content = resourceLoader.GetString("WarningDialog_LearnMore"),
NavigateUri = new Uri("https://aka.ms/PowerToysOverview_HostsFileEditor"),
Padding = new Thickness(0),
Margin = new Thickness(0, 5, 0, 5),
},
},
Text = resourceLoader.GetString("WarningDialog_Text"),
TextWrapping = TextWrapping.Wrap,
};
dialog.PrimaryButtonText = resourceLoader.GetString("WarningDialog_AcceptBtn");
dialog.PrimaryButtonStyle = Application.Current.Resources["AccentButtonStyle"] as Style;

View File

@@ -11,9 +11,6 @@ using HostsUILib.Helpers;
namespace HostsUILib.Models
{
#if !TESTONLY
[Microsoft.UI.Xaml.Data.Bindable]
#endif
public partial class Entry : ObservableObject
{
private static readonly char[] _spaceCharacters = new char[] { ' ', '\t' };

View File

@@ -331,9 +331,6 @@
<data name="WarningDialog_Title" xml:space="preserve">
<value>Warning</value>
</data>
<data name="WarningDialog_LearnMore" xml:space="preserve">
<value>Learn more</value>
</data>
<data name="WindowAdminTitle" xml:space="preserve">
<value>Administrator: Hosts File Editor</value>
<comment>Title of the window when running as administrator. "Hosts File Editor" is the name of the utility. "Hosts" refers to the system hosts file, do not loc</comment>

View File

@@ -117,18 +117,16 @@ private:
for (DWORD pid : processIds)
{
HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, pid);
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (hProcess != NULL)
{
SetEvent(m_hTerminateEvent);
// Wait for 1.5 seconds for the process to end correctly, allowing time for ETW tracer and extensions to stop
if (WaitForSingleObject(hProcess, 1500) == WAIT_TIMEOUT)
{
TerminateProcess(hProcess, 0);
}
// Wait for 1.5 seconds for the process to end correctly and stop etw tracer
WaitForSingleObject(hProcess, 1500);
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
}
}

View File

@@ -102,8 +102,6 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
}
HandleChangeAlias();
OnPropertyChanged(nameof(AliasText));
OnPropertyChanged(nameof(IsDirectAlias));
}
}
@@ -118,7 +116,6 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
}
HandleChangeAlias();
OnPropertyChanged(nameof(IsDirectAlias));
}
}

View File

@@ -67,7 +67,6 @@ public partial class App : Application
"Local\\PowerToysCmdPal-ExitEvent-eb73f6be-3f22-4b36-aee3-62924ba40bfd", () =>
{
EtwTrace?.Dispose();
AppWindow?.Close();
Environment.Exit(0);
});
}

View File

@@ -105,10 +105,6 @@
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<RdXmlFile Include="rd.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj" />

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="Microsoft.CmdPal.UI.Settings.ExtensionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
@@ -92,11 +92,12 @@
<controls:SettingsCard x:Uid="Settings_ExtensionPage_Alias_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=&#xE8AC;}">
<StackPanel Orientation="Vertical">
<TextBox Text="{x:Bind AliasText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{x:Bind AliasText, Mode=TwoWay}" />
<ToggleSwitch
x:Uid="Settings_ExtensionPage_Alias_ToggleSwitch"
IsEnabled="{x:Bind AliasText, Converter={StaticResource StringEmptyToBoolConverter}, Mode=OneWay}"
IsOn="{x:Bind IsDirectAlias, Mode=TwoWay}" />
IsOn="{x:Bind IsDirectAlias, Mode=TwoWay}"
OffContent="Indirect"
OnContent="Direct" />
</StackPanel>
</controls:SettingsCard>

View File

@@ -418,10 +418,4 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
<data name="TrayMenu_Exit" xml:space="preserve">
<value>Exit</value>
</data>
<data name="Settings_ExtensionPage_Alias_ToggleSwitch.OnContent" xml:space="preserve">
<value>Direct</value>
</data>
<data name="Settings_ExtensionPage_Alias_ToggleSwitch.OffContent" xml:space="preserve">
<value>Indirect</value>
</data>
</root>

View File

@@ -1,7 +0,0 @@
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="Microsoft.WinUI">
<Type Name="Microsoft.UI.Xaml.Controls.FontIconSource" Dynamic="Required All" />
</Assembly>
</Application>
</Directives>

View File

@@ -1,49 +0,0 @@
// 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;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Apps.Commands;
internal sealed partial class CopyPathCommand : InvokableCommand
{
private static readonly IconInfo TheIcon = new("\ue8c8");
private readonly string _target;
public CopyPathCommand(string target)
{
Name = Resources.copy_path;
Icon = TheIcon;
_target = target;
}
private static readonly CompositeFormat CopyFailedFormat = CompositeFormat.Parse(Resources.copy_failed);
public override CommandResult Invoke()
{
try
{
ClipboardHelper.SetText(_target);
}
catch (Exception ex)
{
Logger.LogError("Copy failed: " + ex.Message);
return CommandResult.ShowToast(
new ToastArgs
{
Message = string.Format(CultureInfo.CurrentCulture, CopyFailedFormat, ex.Message),
Result = CommandResult.KeepOpen(),
});
}
return CommandResult.ShowToast(Resources.copied_to_clipboard);
}
}

View File

@@ -85,10 +85,6 @@ public class UWPApplication : IProgram
// We don't add context menu to 'run as different user', because UWP applications normally installed per user and not for all users.
}
commands.Add(
new CommandContextItem(
new CopyPathCommand(Location)));
commands.Add(
new CommandContextItem(
new OpenPathCommand(Location)

View File

@@ -198,9 +198,6 @@ public class Win32Program : IProgram
new RunAsUserCommand(!string.IsNullOrEmpty(LnkFilePath) ? LnkFilePath : FullPath, ParentDirectory)));
}
commands.Add(new CommandContextItem(
new CopyPathCommand(FullPath)));
commands.Add(new CommandContextItem(
new OpenPathCommand(ParentDirectory)));

View File

@@ -78,33 +78,6 @@ namespace Microsoft.CmdPal.Ext.Apps.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Copied to clipboard!.
/// </summary>
internal static string copied_to_clipboard {
get {
return ResourceManager.GetString("copied_to_clipboard", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Copy failed ({0}). Please try again..
/// </summary>
internal static string copy_failed {
get {
return ResourceManager.GetString("copy_failed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Copy path.
/// </summary>
internal static string copy_path {
get {
return ResourceManager.GetString("copy_path", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Include apps found on the desktop.
/// </summary>

View File

@@ -163,22 +163,12 @@
<data name="open_location" xml:space="preserve">
<value>Open location</value>
</data>
<data name="copy_path" xml:space="preserve">
<value>Copy path</value>
</data>
<data name="run_as_administrator" xml:space="preserve">
<value>Run as administrator</value>
</data>
<data name="run_as_different_user" xml:space="preserve">
<value>Run as different user</value>
</data>
<data name="copy_failed" xml:space="preserve">
<value>Copy failed ({0}). Please try again.</value>
<comment>{0} is the error message</comment>
</data>
<data name="copied_to_clipboard" xml:space="preserve">
<value>Copied to clipboard!</value>
</data>
<data name="enable_start_menu_source" xml:space="preserve">
<value>Include apps found in the Start Menu</value>
</data>

View File

@@ -110,13 +110,6 @@ internal static class Commands
});
}
results.Add(new ListItem(new ExecuteCommandConfirmation(Resources.Microsoft_plugin_sys_RestartShell_name!, confirmCommands, Resources.Microsoft_plugin_sys_RestartShell_confirmation!, static () => OpenInShellHelper.OpenInShell("cmd", "/C tskill explorer && start explorer", runWithHiddenWindow: true)))
{
Title = Resources.Microsoft_plugin_sys_RestartShell!,
Subtitle = Resources.Microsoft_plugin_sys_RestartShell_description!,
Icon = Icons.RestartShellIcon,
});
// UEFI command/result. It is only available on systems booted in UEFI mode.
if (isUefi)
{

View File

@@ -20,8 +20,6 @@ public static partial class Icons
public static IconInfo RestartIcon { get; } = new IconInfo("\uE777");
public static IconInfo RestartShellIcon { get; } = new IconInfo("\uEC50");
public static IconInfo ShutdownIcon { get; } = new IconInfo("\uE7E8");
public static IconInfo SleepIcon { get; } = new IconInfo("\uE708");

View File

@@ -645,42 +645,6 @@ namespace Microsoft.CmdPal.Ext.System {
}
}
/// <summary>
/// Looks up a localized string similar to Restart Windows Explorer.
/// </summary>
public static string Microsoft_plugin_sys_RestartShell {
get {
return ResourceManager.GetString("Microsoft_plugin_sys_RestartShell", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You are about to restart Windows Explorer, are you sure?.
/// </summary>
public static string Microsoft_plugin_sys_RestartShell_confirmation {
get {
return ResourceManager.GetString("Microsoft_plugin_sys_RestartShell_confirmation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to End and restart the Windows Explorer shell process.
/// </summary>
public static string Microsoft_plugin_sys_RestartShell_description {
get {
return ResourceManager.GetString("Microsoft_plugin_sys_RestartShell_description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Restart.
/// </summary>
public static string Microsoft_plugin_sys_RestartShell_name {
get {
return ResourceManager.GetString("Microsoft_plugin_sys_RestartShell_name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ip; mac; address.
/// </summary>

View File

@@ -417,16 +417,4 @@
<data name="Microsoft_plugin_ext_fallback_display_title" xml:space="preserve">
<value>Open System Command</value>
</data>
<data name="Microsoft_plugin_sys_RestartShell" xml:space="preserve">
<value>Restart Windows Explorer</value>
</data>
<data name="Microsoft_plugin_sys_RestartShell_description" xml:space="preserve">
<value>End and restart the Windows Explorer shell process</value>
</data>
<data name="Microsoft_plugin_sys_RestartShell_name" xml:space="preserve">
<value>Restart</value>
</data>
<data name="Microsoft_plugin_sys_RestartShell_confirmation" xml:space="preserve">
<value>You are about to restart Windows Explorer, are you sure?</value>
</data>
</root>

View File

@@ -68,7 +68,6 @@ internal sealed partial class FallbackTimeDateItem : FallbackCommandItem
Title = result.Title;
Subtitle = result.Subtitle;
Icon = result.Icon;
Command = result.Command;
}
else
{

View File

@@ -18,6 +18,8 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
private IList<ListItem> _results = new List<ListItem>();
private bool initialized;
private SettingsManager _settingsManager;
public TimeDateExtensionPage(SettingsManager settingsManager)
@@ -33,9 +35,12 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
public override IListItem[] GetItems()
{
DoExecuteSearch(string.Empty);
if (!initialized)
{
DoExecuteSearch(string.Empty);
}
lock (_resultsLock)
lock (_resultsLock)
{
ListItem[] results = _results.ToArray();
return results;
@@ -44,6 +49,11 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
public override void UpdateSearchText(string oldSearch, string newSearch)
{
if (newSearch == oldSearch)
{
return;
}
DoExecuteSearch(newSearch);
}
@@ -74,6 +84,7 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
{
lock (_resultsLock)
{
initialized = true;
this._results = result;
}

View File

@@ -65,7 +65,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{StaticResource TextFillColorSecondaryBrush}"
Visibility="{x:Bind IsWarningMessageVisible(VideoPreviewer, Previewer.State), Mode=OneWay}">
Visibility="{x:Bind IsWarningMessageVisible(VideoPreviewer.MissingCodecName), Mode=OneWay}">
<Paragraph>
<Run Text="{x:Bind GetWarningMessage(VideoPreviewer.MissingCodecName), Mode=OneWay}" />
<Hyperlink Click="CodecSearchHyperlink_Click">

View File

@@ -150,9 +150,9 @@ namespace Peek.FilePreviewer
return isValidPreview ? Visibility.Visible : Visibility.Collapsed;
}
public Visibility IsWarningMessageVisible(IPreviewer? previewer, PreviewState? state)
public Visibility IsWarningMessageVisible(string? missingCodecName)
{
var shouldShow = previewer is IVideoPreviewer videoPreviewer && MatchPreviewState(state, PreviewState.Loaded) && !string.IsNullOrEmpty(videoPreviewer.MissingCodecName);
var shouldShow = !string.IsNullOrEmpty(missingCodecName);
return shouldShow ? Visibility.Visible : Visibility.Collapsed;
}

View File

@@ -228,8 +228,6 @@ namespace Microsoft.PowerToys.PreviewHandler.Pdf
DestinationWidth = (uint)this.ClientSize.Width,
}).GetAwaiter().GetResult();
stream.Seek(0); // Reset the stream position to the beginning before reading.
imageOfPage = Image.FromStream(stream.AsStream());
}

View File

@@ -22,10 +22,6 @@ namespace RegistryPreviewUILib
{
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
// Indicator if we loaded/reloaded/saved a file and need to skip TextChanged event one time.
// (Solves the problem that enabling the event handler fires it one time.)
private static bool editorContentChangedScripted;
/// <summary>
/// Event that is will prevent the app from closing if the "save file" flag is active
/// </summary>
@@ -80,67 +76,6 @@ namespace RegistryPreviewUILib
MonacoEditor.Focus(FocusState.Programmatic);
}
/// <summary>
/// New button action: Ask to save last changes and reset editor content to reg header only
/// </summary>
private async void NewButton_Click(object sender, RoutedEventArgs e)
{
// Check to see if the current file has been saved
if (saveButton.IsEnabled)
{
ContentDialog contentDialog = new ContentDialog()
{
Title = resourceLoader.GetString("YesNoCancelDialogTitle"),
Content = resourceLoader.GetString("YesNoCancelDialogContent"),
PrimaryButtonText = resourceLoader.GetString("YesNoCancelDialogPrimaryButtonText"),
SecondaryButtonText = resourceLoader.GetString("YesNoCancelDialogSecondaryButtonText"),
CloseButtonText = resourceLoader.GetString("YesNoCancelDialogCloseButtonText"),
DefaultButton = ContentDialogButton.Primary,
};
// Use this code to associate the dialog to the appropriate AppWindow by setting
// the dialog's XamlRoot to the same XamlRoot as an element that is already present in the AppWindow.
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
contentDialog.XamlRoot = this.Content.XamlRoot;
}
ContentDialogResult contentDialogResult = await contentDialog.ShowAsync();
switch (contentDialogResult)
{
case ContentDialogResult.Primary:
// Save, then continue the new action
if (!AskFileName(string.Empty) ||
!SaveFile())
{
return;
}
break;
case ContentDialogResult.Secondary:
// Don't save and continue the new action!
break;
default:
// Don't open the new action!
return;
}
}
// mute the TextChanged handler to make for clean UI
MonacoEditor.TextChanged -= MonacoEditor_TextChanged;
// reset editor, file info and ui.
_appFileName = string.Empty;
ResetEditorAndFile();
// disable buttons that do not make sense
UpdateUnsavedFileState(false);
refreshButton.IsEnabled = false;
// restore the TextChanged handler
ButtonAction_RestoreTextChangedEvent();
}
/// <summary>
/// Uses a picker to select a new file to open
/// </summary>
@@ -171,15 +106,11 @@ namespace RegistryPreviewUILib
{
case ContentDialogResult.Primary:
// Save, then continue the file open
if (!AskFileName(string.Empty) ||
!SaveFile())
{
return;
}
SaveFile();
break;
case ContentDialogResult.Secondary:
// Don't save and continue the file open!
saveButton.IsEnabled = false;
break;
default:
// Don't open the new file!
@@ -206,16 +137,14 @@ namespace RegistryPreviewUILib
{
// mute the TextChanged handler to make for clean UI
MonacoEditor.TextChanged -= MonacoEditor_TextChanged;
// update file name
_appFileName = storageFile.Path;
UpdateToolBarAndUI(await OpenRegistryFile(_appFileName));
// disable the Save button as it's a new file
UpdateUnsavedFileState(false);
saveButton.IsEnabled = false;
// Restore the event handler as we're loaded
ButtonAction_RestoreTextChangedEvent();
MonacoEditor.TextChanged += MonacoEditor_TextChanged;
}
}
@@ -224,14 +153,7 @@ namespace RegistryPreviewUILib
/// </summary>
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
if (!AskFileName(string.Empty))
{
return;
}
// save and update window title
// error handling and ui update happens in SaveFile() method
_ = SaveFile();
SaveFile();
}
/// <summary>
@@ -239,24 +161,47 @@ namespace RegistryPreviewUILib
/// </summary>
private async void SaveAsButton_Click(object sender, RoutedEventArgs e)
{
// mute the TextChanged handler to make for clean UI
MonacoEditor.TextChanged -= MonacoEditor_TextChanged;
// Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's
// called while running as admin
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow);
string filename = SaveFilePicker.ShowDialog(
windowHandle,
resourceLoader.GetString("SuggestFileName"),
resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0',
resourceLoader.GetString("SaveDialogTitle"));
if (!AskFileName(_appFileName) || !SaveFile())
if (filename == string.Empty)
{
return;
}
_appFileName = filename;
SaveFile();
UpdateToolBarAndUI(await OpenRegistryFile(_appFileName));
// restore the TextChanged handler
ButtonAction_RestoreTextChangedEvent();
}
/// <summary>
/// Reloads the current REG file from storage
/// </summary>
private async void RefreshButton_Click(object sender, RoutedEventArgs e)
{
// mute the TextChanged handler to make for clean UI
MonacoEditor.TextChanged -= MonacoEditor_TextChanged;
// reload the current Registry file and update the toolbar accordingly.
UpdateToolBarAndUI(await OpenRegistryFile(_appFileName), true, true);
// disable the Save button as it's a new file
saveButton.IsEnabled = false;
// restore the TextChanged handler
MonacoEditor.TextChanged += MonacoEditor_TextChanged;
}
/// <summary>
/// Resets the editor content
/// </summary>
private async void NewButton_Click(object sender, RoutedEventArgs e)
{
// Check to see if the current file has been saved
if (saveButton.IsEnabled)
@@ -264,9 +209,10 @@ namespace RegistryPreviewUILib
ContentDialog contentDialog = new ContentDialog()
{
Title = resourceLoader.GetString("YesNoCancelDialogTitle"),
Content = resourceLoader.GetString("ReloadDialogContent"),
PrimaryButtonText = resourceLoader.GetString("ReloadDialogPrimaryButtonText"),
CloseButtonText = resourceLoader.GetString("ReloadDialogCloseButtonText"),
Content = resourceLoader.GetString("YesNoCancelDialogContent"),
PrimaryButtonText = resourceLoader.GetString("YesNoCancelDialogPrimaryButtonText"),
SecondaryButtonText = resourceLoader.GetString("YesNoCancelDialogSecondaryButtonText"),
CloseButtonText = resourceLoader.GetString("YesNoCancelDialogCloseButtonText"),
DefaultButton = ContentDialogButton.Primary,
};
@@ -281,10 +227,15 @@ namespace RegistryPreviewUILib
switch (contentDialogResult)
{
case ContentDialogResult.Primary:
// Don't save and continue the reload action!
// Save, then continue the file open
SaveFile();
break;
case ContentDialogResult.Secondary:
// Don't save and continue the file open!
saveButton.IsEnabled = false;
break;
default:
// Don't continue the reload action!
// Don't open the new file!
return;
}
}
@@ -292,14 +243,16 @@ namespace RegistryPreviewUILib
// mute the TextChanged handler to make for clean UI
MonacoEditor.TextChanged -= MonacoEditor_TextChanged;
// reload the current Registry file and update the toolbar accordingly.
UpdateToolBarAndUI(await OpenRegistryFile(_appFileName), true, true);
// disable the Save button as it's a new file
UpdateUnsavedFileState(false);
// reset editor, file info and ui.
_appFileName = string.Empty;
ResetEditorAndFile();
// restore the TextChanged handler
ButtonAction_RestoreTextChangedEvent();
MonacoEditor.TextChanged += MonacoEditor_TextChanged;
// disable buttons that do not make sense
saveButton.IsEnabled = false;
refreshButton.IsEnabled = false;
}
/// <summary>
@@ -360,20 +313,15 @@ namespace RegistryPreviewUILib
switch (contentDialogResult)
{
case ContentDialogResult.Primary:
// Save, then continue the merge action
if (!AskFileName(string.Empty) ||
!SaveFile())
{
return;
}
// Save, then continue the file open
SaveFile();
break;
case ContentDialogResult.Secondary:
// Don't save and continue the merge action!
UpdateUnsavedFileState(false);
// Don't save and continue the file open!
saveButton.IsEnabled = false;
break;
default:
// Don't merge the file!
// Don't open the new file!
return;
}
}
@@ -463,29 +411,10 @@ namespace RegistryPreviewUILib
_dispatcherQueue.TryEnqueue(() =>
{
RefreshRegistryFile();
if (!editorContentChangedScripted)
{
UpdateUnsavedFileState(true);
}
editorContentChangedScripted = false;
saveButton.IsEnabled = true;
});
}
/// <summary>
/// Sets indicator for programatic text change and adds text changed handler
/// </summary>
/// <remarks>
/// Use this always, if button actions temporary disable the text changed event
/// </remarks>
private void ButtonAction_RestoreTextChangedEvent()
{
// Solves the problem that enabling the event handler fires it one time.
// These one time fired event would causes wrong unsaved changes state.
editorContentChangedScripted = true;
MonacoEditor.TextChanged += MonacoEditor_TextChanged;
}
// Commands to show data preview
public void ButtonExtendedPreview_Click(object sender, RoutedEventArgs e)
{

View File

@@ -11,7 +11,6 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.UI.Input;
@@ -25,10 +24,7 @@ namespace RegistryPreviewUILib
{
private const string NEWFILEHEADER = "Windows Registry Editor Version 5.00\r\n\r\n";
private static readonly string _unsavedFileIndicator = "* ";
private static readonly char[] _unsavedFileIndicatorChars = [' ', '*'];
private static SemaphoreSlim _dialogSemaphore = new(1);
private string lastKeyPath;
public delegate void UpdateWindowTitleFunction(string title);
@@ -836,66 +832,42 @@ namespace RegistryPreviewUILib
/// </summary>
private async void HandleDirtyClosing(string title, string content, string primaryButtonText, string secondaryButtonText, string closeButtonText)
{
if (_dialogSemaphore.CurrentCount == 0)
ContentDialog contentDialog = new ContentDialog()
{
return;
Title = title,
Content = content,
PrimaryButtonText = primaryButtonText,
SecondaryButtonText = secondaryButtonText,
CloseButtonText = closeButtonText,
DefaultButton = ContentDialogButton.Primary,
};
// Use this code to associate the dialog to the appropriate AppWindow by setting
// the dialog's XamlRoot to the same XamlRoot as an element that is already present in the AppWindow.
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
contentDialog.XamlRoot = this.Content.XamlRoot;
}
try
ContentDialogResult contentDialogResult = await contentDialog.ShowAsync();
switch (contentDialogResult)
{
await _dialogSemaphore.WaitAsync();
ContentDialog contentDialog = new ContentDialog()
{
Title = title,
Content = content,
PrimaryButtonText = primaryButtonText,
SecondaryButtonText = secondaryButtonText,
CloseButtonText = closeButtonText,
DefaultButton = ContentDialogButton.Primary,
};
// Use this code to associate the dialog to the appropriate AppWindow by setting
// the dialog's XamlRoot to the same XamlRoot as an element that is already present in the AppWindow.
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
contentDialog.XamlRoot = this.Content.XamlRoot;
}
ContentDialogResult contentDialogResult = await contentDialog.ShowAsync();
switch (contentDialogResult)
{
case ContentDialogResult.Primary:
// Save, then close
if (!AskFileName(string.Empty) ||
!SaveFile())
{
return;
}
break;
case ContentDialogResult.Secondary:
// Don't save, and then close!
UpdateUnsavedFileState(false);
break;
default:
// Cancel closing!
return;
}
// if we got here, we should try to close again
Application.Current.Exit();
}
catch
{
// Normally nothing to catch here.
// But for safety the try-catch ensures that we always release the content dialog lock and exit correctly.
}
finally
{
_dialogSemaphore.Release();
case ContentDialogResult.Primary:
// Save, then close
SaveFile();
break;
case ContentDialogResult.Secondary:
// Don't save, and then close!
saveButton.IsEnabled = false;
break;
default:
// Cancel closing!
return;
}
// if we got here, we should try to close again
Application.Current.Exit();
}
/// <summary>
@@ -955,71 +927,11 @@ namespace RegistryPreviewUILib
type.InvokeMember("ProtectedCursor", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, uiElement, new object[] { cursor }, CultureInfo.InvariantCulture);
}
public void UpdateUnsavedFileState(bool unsavedChanges)
{
// get, cut and analyze the current title
string currentTitle = Regex.Replace(_mainWindow.Title, APPNAME + @"$|\s-\s" + APPNAME + @"$", string.Empty);
bool titleContainsIndicator = currentTitle.StartsWith(_unsavedFileIndicator, StringComparison.CurrentCultureIgnoreCase);
// update window title and save button state
if (unsavedChanges)
{
saveButton.IsEnabled = true;
if (!titleContainsIndicator)
{
_updateWindowTitleFunction(_unsavedFileIndicator + currentTitle);
}
}
else
{
saveButton.IsEnabled = false;
if (titleContainsIndicator)
{
_updateWindowTitleFunction(currentTitle.TrimStart(_unsavedFileIndicatorChars));
}
}
}
/// <summary>
/// Ask the user for the file path if it is unknown because of an unsaved file
/// </summary>
/// <param name="fileName">If not empty always ask for a file path and use the value as name.</param>
/// <returns>Returns true if user selected a path, otherwise false</returns>
public bool AskFileName(string fileName)
{
if (string.IsNullOrEmpty(_appFileName) || !string.IsNullOrEmpty(fileName) )
{
string fName = string.IsNullOrEmpty(fileName) ? resourceLoader.GetString("SuggestFileName") : fileName;
// Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's
// called while running as admin
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow);
string filename = SaveFilePicker.ShowDialog(
windowHandle,
fName,
resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0',
resourceLoader.GetString("SaveDialogTitle"));
if (filename == string.Empty)
{
return false;
}
_appFileName = filename;
}
return true;
}
/// <summary>
/// Wrapper method that saves the current file in place, using the current text in editor.
/// </summary>
private bool SaveFile()
private void SaveFile()
{
bool saveSuccess = true;
ChangeCursor(gridPreview, true);
// set up the FileStream for all writing
@@ -1043,13 +955,10 @@ namespace RegistryPreviewUILib
streamWriter.Close();
// only change when the save is successful
UpdateUnsavedFileState(false);
_updateWindowTitleFunction(_appFileName);
saveButton.IsEnabled = false;
}
catch (UnauthorizedAccessException ex)
{
saveSuccess = false;
// this exception is thrown if the file is there but marked as read only
ShowMessageBox(
resourceLoader.GetString("ErrorDialogTitle"),
@@ -1058,8 +967,6 @@ namespace RegistryPreviewUILib
}
catch
{
saveSuccess = false;
// this catch handles all other exceptions thrown when trying to write the file out
ShowMessageBox(
resourceLoader.GetString("ErrorDialogTitle"),
@@ -1077,8 +984,6 @@ namespace RegistryPreviewUILib
// restore the cursor
ChangeCursor(gridPreview, false);
return saveSuccess;
}
/// <summary>

View File

@@ -258,18 +258,12 @@
<data name="YesNoCancelDialogCloseButtonText" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ReloadDialogCloseButtonText" xml:space="preserve">
<value>No</value>
</data>
<data name="YesNoCancelDialogContent" xml:space="preserve">
<value>Save changes?</value>
</data>
<data name="YesNoCancelDialogPrimaryButtonText" xml:space="preserve">
<value>Save</value>
</data>
<data name="ReloadDialogPrimaryButtonText" xml:space="preserve">
<value>Yes</value>
</data>
<data name="YesNoCancelDialogSecondaryButtonText" xml:space="preserve">
<value>Don't save</value>
</data>
@@ -369,7 +363,4 @@
<data name="NewButton.Label" xml:space="preserve">
<value>New</value>
</data>
<data name="ReloadDialogContent" xml:space="preserve">
<value>You lose any unsaved changes. Reload anyway?</value>
</data>
</root>