diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 9e605257ca..2ddc4a8242 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1527,6 +1527,7 @@ PCWSTR pdb pdbonly pdf +pdfpreviewhandler pdo pdto pdtobj diff --git a/.pipelines/ci/templates/build-powertoys-steps.yml b/.pipelines/ci/templates/build-powertoys-steps.yml index 80fc0383d3..1da8d83229 100644 --- a/.pipelines/ci/templates/build-powertoys-steps.yml +++ b/.pipelines/ci/templates/build-powertoys-steps.yml @@ -122,6 +122,8 @@ steps: testAssemblyVer2: | **\UnitTests-SvgThumbnailProvider.dll **\Microsoft.PowerToys.Settings.UI.UnitTests.dll + **\UnitTests-MarkdownPreviewHandler.dll + **\UnitTests-PdfPreviewHandler.dll **\UnitTests-SvgPreviewHandler.dll **\UnitTests-PreviewHandlerCommon.dll **\PreviewPaneUnitTests.dll diff --git a/.pipelines/pipeline.user.windows.yml b/.pipelines/pipeline.user.windows.yml index fdaea129f6..9fe3f92fbc 100644 --- a/.pipelines/pipeline.user.windows.yml +++ b/.pipelines/pipeline.user.windows.yml @@ -108,6 +108,8 @@ build: - 'modules\FileExplorerPreview\ManagedTelemetry.dll' - 'modules\FileExplorerPreview\MarkdownPreviewHandler.dll' - 'modules\FileExplorerPreview\MarkdownPreviewHandler.comhost.dll' + - 'modules\FileExplorerPreview\PdfPreviewHandler.dll' + - 'modules\FileExplorerPreview\PdfPreviewHandler.comhost.dll' - 'modules\FileExplorerPreview\powerpreview.dll' - 'modules\FileExplorerPreview\PreviewHandlerCommon.dll' - 'modules\FileExplorerPreview\SvgPreviewHandler.dll' diff --git a/PowerToys.sln b/PowerToys.sln index 4d0c415207..d58e52fadd 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -166,7 +166,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PreviewHandlerCommon", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MarkdownPreviewHandler", "src\modules\previewpane\MarkdownPreviewHandler\MarkdownPreviewHandler.csproj", "{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-MarkdownPreviewHandler", "src\modules\previewpane\PreviewPaneUnitTests\UnitTests-MarkdownPreviewHandler.csproj", "{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-MarkdownPreviewHandler", "src\modules\previewpane\UnitTests-MarkdownPreviewHandler\UnitTests-MarkdownPreviewHandler.csproj", "{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgPreviewHandler", "src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csproj", "{DA425894-6E13-404F-8DCB-78584EC0557A}" EndProject @@ -305,6 +305,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Telemetry", "Telemetry", "{ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Common.UI", "src\common\Microsoft.PowerToys.Common.UI\Microsoft.PowerToys.Common.UI.csproj", "{C3A17DCA-217B-462C-BB0C-BE086AF80081}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfPreviewHandler", "src\modules\previewpane\PdfPreviewHandler\PdfPreviewHandler.csproj", "{69E1EE8D-143A-4060-9129-4658ACF14AAF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-PdfPreviewHandler", "src\modules\previewpane\UnitTests-PdfPreviewHandler\UnitTests-PdfPreviewHandler.csproj", "{ECC20689-002A-4354-95A6-B58DF089C6FF}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Registry", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\Microsoft.PowerToys.Run.Plugin.Registry.csproj", "{4BABF3FE-3451-42FD-873F-3C332E18DCEF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Registry.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry.UnitTest\Microsoft.PowerToys.Run.Plugin.Registry.UnitTests.csproj", "{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}" @@ -796,6 +800,18 @@ Global {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.ActiveCfg = Release|x64 {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.Build.0 = Release|x64 {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x86.ActiveCfg = Release|x64 + {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|x64.ActiveCfg = Debug|x64 + {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|x64.Build.0 = Debug|x64 + {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|x86.ActiveCfg = Debug|x64 + {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|x64.ActiveCfg = Release|x64 + {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|x64.Build.0 = Release|x64 + {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|x86.ActiveCfg = Release|x64 + {ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|x64.ActiveCfg = Debug|x64 + {ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|x64.Build.0 = Debug|x64 + {ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|x86.ActiveCfg = Debug|x64 + {ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|x64.ActiveCfg = Release|x64 + {ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|x64.Build.0 = Release|x64 + {ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|x86.ActiveCfg = Release|x64 {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.ActiveCfg = Debug|x64 {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.Build.0 = Debug|x64 {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x86.ActiveCfg = Debug|x64 @@ -1019,6 +1035,8 @@ Global {B39DC643-4663-475E-B329-03F0C9918D48} = {1AFB6476-670D-4E80-A464-657E01DFF482} {8F62026A-294B-41C6-8839-87463613F216} = {1AFB6476-670D-4E80-A464-657E01DFF482} {C3A17DCA-217B-462C-BB0C-BE086AF80081} = {1AFB6476-670D-4E80-A464-657E01DFF482} + {69E1EE8D-143A-4060-9129-4658ACF14AAF} = {2F305555-C296-497E-AC20-5FA1B237996A} + {ECC20689-002A-4354-95A6-B58DF089C6FF} = {2F305555-C296-497E-AC20-5FA1B237996A} {4BABF3FE-3451-42FD-873F-3C332E18DCEF} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {0648DF05-5DDA-4BE1-B5F2-584926EBDB65} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A} = {C3081D9A-1586-441A-B5F4-ED815B3719C1} diff --git a/installer/MSIX/appxmanifest.xml b/installer/MSIX/appxmanifest.xml index a57983a327..90c4d6b381 100644 --- a/installer/MSIX/appxmanifest.xml +++ b/installer/MSIX/appxmanifest.xml @@ -79,11 +79,20 @@ + + + + .pdf + + + + + diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 1810508c85..e52b052521 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -239,7 +239,6 @@ - @@ -499,6 +498,19 @@ + + + + + + + + + + + + + @@ -511,6 +523,10 @@ + + + + @@ -523,6 +539,10 @@ + + + + @@ -784,6 +804,11 @@ + + + + + @@ -1022,7 +1047,10 @@ - + + + + diff --git a/src/modules/previewpane/PdfPreviewHandler/LocProject.json b/src/modules/previewpane/PdfPreviewHandler/LocProject.json new file mode 100644 index 0000000000..b9ffe307fa --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/LocProject.json @@ -0,0 +1,14 @@ +{ + "Projects": [ + { + "LanguageSet": "Azure_Languages", + "LocItems": [ + { + "SourceFile": "src\\modules\\previewpane\\PdfPreviewHandler\\Properties\\Resources.resx", + "CopyOption": "LangIDOnName", + "OutputPath": "src\\modules\\previewpane\\PdfPreviewHandler\\Properties" + } + ] + } + ] +} diff --git a/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.cs b/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.cs new file mode 100644 index 0000000000..2f4d962287 --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.cs @@ -0,0 +1,73 @@ +// 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.Runtime.InteropServices; +using Common; +using Microsoft.PowerToys.Telemetry; + +namespace Microsoft.PowerToys.PreviewHandler.Pdf +{ + /// + /// Implementation of preview handler for pdf files. + /// + [Guid("07665729-6243-4746-95b7-79579308d1b2")] + [ClassInterface(ClassInterfaceType.None)] + [ComVisible(true)] + public class PdfPreviewHandler : StreamBasedPreviewHandler, IDisposable + { + private PdfPreviewHandlerControl _pdfPreviewHandlerControl; + private bool _disposedValue; + + /// + /// Initializes a new instance of the class. + /// + public PdfPreviewHandler() + { + Initialize(); + } + + /// + public override void DoPreview() + { + _pdfPreviewHandlerControl.DoPreview(Stream); + } + + /// + protected override IPreviewHandlerControl CreatePreviewHandlerControl() + { + PowerToysTelemetry.Log.WriteEvent(new Telemetry.Events.PdfFileHandlerLoaded()); + _pdfPreviewHandlerControl = new PdfPreviewHandlerControl(); + + return _pdfPreviewHandlerControl; + } + + /// + /// Disposes objects + /// + /// Is Disposing + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + _pdfPreviewHandlerControl.Dispose(); + } + + // TODO: free unmanaged resources (unmanaged objects) and override finalizer + // TODO: set large fields to null + _disposedValue = true; + } + } + + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} diff --git a/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj b/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj new file mode 100644 index 0000000000..a49bb3b7b3 --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj @@ -0,0 +1,72 @@ + + + x64 + true + PdfPreviewHandler + PowerToys PdfPreviewHandler + Microsoft Corp. + Copyright (C) 2020 Microsoft Corporation + PowerToys + PdfPreviewHandler + Microsoft Corp. + PowerToys + en-US + PowerToys PdfPreviewHandler + Copyright (C) 2020 Microsoft Corporation + true + $(SolutionDir)$(Platform)\$(Configuration)\modules\FileExplorerPreview\PdfPreviewPaneDocumentation.xml + $(SolutionDir)$(Platform)\$(Configuration)\modules\FileExplorerPreview\ + false + false + true + + + + {69E1EE8D-143A-4060-9129-4658ACF14AAF} + Microsoft.PowerToys.PreviewHandler.Pdf + netcoreapp3.1 + true + $(SolutionDir)$(Platform)\$(Configuration)\obj\$(AssemblyName)\ + + + + + + + + + True + True + Resources.resx + + + + + + all + + + all + + + + + + + + StyleCop.json + + + + + + + + + + + $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\10.0.17134.0\Windows.winmd + true + + + \ No newline at end of file diff --git a/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandlerControl.cs b/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandlerControl.cs new file mode 100644 index 0000000000..8e17d9811b --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandlerControl.cs @@ -0,0 +1,299 @@ +// 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.Drawing; +using System.IO; +using System.Runtime.InteropServices.ComTypes; +using System.Windows.Forms; + +using Common; +using Common.Utilities; +using Microsoft.PowerToys.PreviewHandler.Pdf.Properties; +using Microsoft.PowerToys.PreviewHandler.Pdf.Telemetry.Events; +using Microsoft.PowerToys.Telemetry; +using Windows.Data.Pdf; +using Windows.Storage.Streams; +using Windows.UI.ViewManagement; + +namespace Microsoft.PowerToys.PreviewHandler.Pdf +{ + /// + /// Win Form Implementation for Pdf Preview Handler. + /// + public class PdfPreviewHandlerControl : FormHandlerControl + { + /// + /// RichTextBox control to display error message. + /// + private RichTextBox _infoBar; + + /// + /// FlowLayoutPanel control to display the image of the pdf. + /// + private FlowLayoutPanel _flowLayoutPanel; + + /// + /// Use UISettings to get system colors and scroll bar size. + /// + private static UISettings _uISettings = new UISettings(); + + /// + /// Initializes a new instance of the class. + /// + public PdfPreviewHandlerControl() + { + SetBackgroundColor(GetBackgroundColor()); + } + + /// + /// Start the preview on the Control. + /// + /// Stream reference to access source file. + public override void DoPreview(T dataSource) + { + this.SuspendLayout(); + + try + { + using (var dataStream = new ReadonlyStream(dataSource as IStream)) + { + var memStream = new MemoryStream(); + dataStream.CopyTo(memStream); + memStream.Position = 0; + + try + { + // AsRandomAccessStream() extension method from System.Runtime.WindowsRuntime + var pdf = PdfDocument.LoadFromStreamAsync(memStream.AsRandomAccessStream()).GetAwaiter().GetResult(); + + if (pdf.PageCount > 0) + { + InvokeOnControlThread(() => + { + _flowLayoutPanel = new FlowLayoutPanel + { + AutoScroll = true, + AutoSize = true, + Dock = DockStyle.Fill, + FlowDirection = FlowDirection.TopDown, + WrapContents = false, + }; + _flowLayoutPanel.Resize += FlowLayoutPanel_Resize; + + // Only show first 10 pages. + for (uint i = 0; i < pdf.PageCount && i < 10; i++) + { + using (var page = pdf.GetPage(i)) + { + var image = PageToImage(page); + + var picturePanel = new Panel() + { + Name = "picturePanel", + Margin = new Padding(6, 6, 6, 0), + Size = CalculateSize(image), + BorderStyle = BorderStyle.FixedSingle, + }; + + var picture = new PictureBox + { + Dock = DockStyle.Fill, + Image = image, + SizeMode = PictureBoxSizeMode.Zoom, + }; + + picturePanel.Controls.Add(picture); + _flowLayoutPanel.Controls.Add(picturePanel); + } + } + + if (pdf.PageCount > 10) + { + var messageBox = new RichTextBox + { + Name = "messageBox", + Text = Resources.PdfMorePagesMessage, + BackColor = Color.LightYellow, + Dock = DockStyle.Fill, + Multiline = true, + ReadOnly = true, + ScrollBars = RichTextBoxScrollBars.None, + BorderStyle = BorderStyle.None, + }; + messageBox.ContentsResized += RTBContentsResized; + + _flowLayoutPanel.Controls.Add(messageBox); + } + + Controls.Add(_flowLayoutPanel); + }); + } + } +#pragma warning disable CA1031 // Password protected files throws an generic Exception + catch (Exception ex) +#pragma warning restore CA1031 + { + if (ex.Message.Contains("Unable to update the password. The value provided as the current password is incorrect.", StringComparison.Ordinal)) + { + InvokeOnControlThread(() => + { + Controls.Clear(); + _infoBar = GetTextBoxControl(Resources.PdfPasswordProtectedError); + Controls.Add(_infoBar); + }); + } + else + { + throw; + } + } + finally + { + memStream.Dispose(); + } + } + + PowerToysTelemetry.Log.WriteEvent(new PdfFilePreviewed()); + } +#pragma warning disable CA1031 // Do not catch general exception types + catch (Exception ex) +#pragma warning restore CA1031 // Do not catch general exception types + { + PowerToysTelemetry.Log.WriteEvent(new PdfFilePreviewError { Message = ex.Message }); + + InvokeOnControlThread(() => + { + Controls.Clear(); + _infoBar = GetTextBoxControl(Resources.PdfNotPreviewedError); + Controls.Add(_infoBar); + }); + } + finally + { + base.DoPreview(dataSource); + } + + this.ResumeLayout(false); + this.PerformLayout(); + } + + /// + /// Resize the Panels on FlowLayoutPanel resize based on the size of the image. + /// + /// sender (not used) + /// args (not used) + private void FlowLayoutPanel_Resize(object sender, EventArgs e) + { + this.SuspendLayout(); + _flowLayoutPanel.SuspendLayout(); + + foreach (Panel panel in _flowLayoutPanel.Controls.Find("picturePanel", false)) + { + var pictureBox = panel.Controls[0] as PictureBox; + var image = pictureBox.Image; + + panel.Size = CalculateSize(image); + } + + _flowLayoutPanel.ResumeLayout(false); + this.ResumeLayout(false); + } + + /// + /// Transform the PdfPage to an Image. + /// + /// The page to transform to an Image. + /// An object of type + private Image PageToImage(PdfPage page) + { + Image imageOfPage; + + using (var stream = new InMemoryRandomAccessStream()) + { + page.RenderToStreamAsync(stream, new PdfPageRenderOptions() + { + DestinationWidth = (uint)this.ClientSize.Width, + }).GetAwaiter().GetResult(); + + imageOfPage = Image.FromStream(stream.AsStream()); + } + + return imageOfPage; + } + + /// + /// Calculate the size of the control based on the size of the image/pdf page. + /// + /// Image of pdf page. + /// New size off the panel. + private Size CalculateSize(Image pdfImage) + { + var hasScrollBar = _flowLayoutPanel.VerticalScroll.Visible; + + // Add 12px margin to the image by making it 12px smaller. + int width = this.ClientSize.Width - 12; + + // If the vertical scroll bar is visible, make the image smaller. + var scrollBarSizeWidth = (int)_uISettings.ScrollBarSize.Width; + if (hasScrollBar && width > scrollBarSizeWidth) + { + width -= scrollBarSizeWidth; + } + + int originalWidth = pdfImage.Width; + int originalHeight = pdfImage.Height; + float percentWidth = (float)width / originalWidth; + + int newHeight = (int)(originalHeight * percentWidth); + + return new Size(width, newHeight); + } + + /// + /// Get the system background color, based on the selected theme. + /// + /// An object of type . + private static Color GetBackgroundColor() + { + var systemBackgroundColor = _uISettings.GetColorValue(UIColorType.Background); + + return Color.FromArgb(systemBackgroundColor.A, systemBackgroundColor.R, systemBackgroundColor.G, systemBackgroundColor.B); + } + + /// + /// Gets a textbox control. + /// + /// Message to be displayed in textbox. + /// An object of type . + private RichTextBox GetTextBoxControl(string message) + { + var textBox = new RichTextBox + { + Text = message, + BackColor = Color.LightYellow, + Multiline = true, + Dock = DockStyle.Top, + ReadOnly = true, + ScrollBars = RichTextBoxScrollBars.None, + BorderStyle = BorderStyle.None, + }; + textBox.ContentsResized += RTBContentsResized; + + return textBox; + } + + /// + /// Callback when RichTextBox is resized. + /// + /// Reference to resized control. + /// Provides data for the resize event. + private void RTBContentsResized(object sender, ContentsResizedEventArgs e) + { + var richTextBox = (RichTextBox)sender; + + // Add 5px extra height to the textbox. + richTextBox.Height = e.NewRectangle.Height + 5; + } + } +} diff --git a/src/modules/previewpane/PdfPreviewHandler/Properties/Resources.Designer.cs b/src/modules/previewpane/PdfPreviewHandler/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..f8531f334e --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/Properties/Resources.Designer.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.PowerToys.PreviewHandler.Pdf.Properties +{ + using System; + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if (object.ReferenceEquals(resourceMan, null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.PowerToys.PreviewHandler.Pdf.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to This pdf could not be preview due to an internal error.. + /// + internal static string PdfNotPreviewedError + { + get + { + return ResourceManager.GetString("PdfNotPreviewedError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Can't preview pdf. This pdf is password protected.. + /// + internal static string PdfPasswordProtectedError + { + get + { + return ResourceManager.GetString("PdfPasswordProtectedError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This PDF contains more pages, this preview only shows the first 10 pages. Open PDF to view all pages.. + /// + internal static string PdfMorePagesMessage + { + get + { + return ResourceManager.GetString("PdfMorePagesMessage", resourceCulture); + } + } + } +} diff --git a/src/modules/previewpane/PdfPreviewHandler/Properties/Resources.resx b/src/modules/previewpane/PdfPreviewHandler/Properties/Resources.resx new file mode 100644 index 0000000000..809efc52b8 --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/Properties/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + This PDF contains more than 10 pages. Open the document to view all pages. + This text is displayed if PDF has more than 10 pages. + + + This PDF could not be previewed due to an internal error. + This text is displayed if PDF fails to preview + + + Can't preview file. This PDF is password protected. + This text is displayed if PDF is password protected. + + diff --git a/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFileHandlerLoaded.cs b/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFileHandlerLoaded.cs new file mode 100644 index 0000000000..9cd16b0b78 --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFileHandlerLoaded.cs @@ -0,0 +1,20 @@ +// 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.Diagnostics.Tracing; +using Microsoft.PowerToys.Telemetry; +using Microsoft.PowerToys.Telemetry.Events; + +namespace Microsoft.PowerToys.PreviewHandler.Pdf.Telemetry.Events +{ + /// + /// A telemetry event that is triggered when a pdf file is viewed in the preview pane. + /// + [EventData] + public class PdfFileHandlerLoaded : EventBase, IEvent + { + /// + public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; + } +} diff --git a/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFilePreviewError.cs b/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFilePreviewError.cs new file mode 100644 index 0000000000..73dec91265 --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFilePreviewError.cs @@ -0,0 +1,23 @@ +// 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.Telemetry; +using Microsoft.PowerToys.Telemetry.Events; + +namespace Microsoft.PowerToys.PreviewHandler.Pdf.Telemetry.Events +{ + /// + /// A telemetry event that is triggered when an error occurs while attempting to view a markdown file in the preview pane. + /// + public class PdfFilePreviewError : EventBase, IEvent + { + /// + /// Gets or sets the error message. + /// + public string Message { get; set; } + + /// + public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance; + } +} diff --git a/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFilePreviewed.cs b/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFilePreviewed.cs new file mode 100644 index 0000000000..e9eee5d17e --- /dev/null +++ b/src/modules/previewpane/PdfPreviewHandler/Telemetry/Events/PdfFilePreviewed.cs @@ -0,0 +1,20 @@ +// 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.Diagnostics.Tracing; +using Microsoft.PowerToys.Telemetry; +using Microsoft.PowerToys.Telemetry.Events; + +namespace Microsoft.PowerToys.PreviewHandler.Pdf.Telemetry.Events +{ + /// + /// A telemetry event that is triggered when a markdown file is viewed in the preview pane. + /// + [EventData] + public class PdfFilePreviewed : EventBase, IEvent + { + /// + public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; + } +} diff --git a/src/modules/previewpane/PreviewPaneUnitTests/HTMLParsingExtensionTest.cs b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HTMLParsingExtensionTest.cs similarity index 100% rename from src/modules/previewpane/PreviewPaneUnitTests/HTMLParsingExtensionTest.cs rename to src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HTMLParsingExtensionTest.cs diff --git a/src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithExternalImage.txt b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithExternalImage.txt similarity index 98% rename from src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithExternalImage.txt rename to src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithExternalImage.txt index 1439071e7a..3cdaf321c1 100644 --- a/src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithExternalImage.txt +++ b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithExternalImage.txt @@ -1,2 +1,2 @@ -![Minion](https://octodex.github.com/images/minion.png) +![Minion](https://octodex.github.com/images/minion.png) \ No newline at end of file diff --git a/src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithHTMLImageTag.txt b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag.txt similarity index 97% rename from src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithHTMLImageTag.txt rename to src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag.txt index 5cd2ab8a77..98d78a5c1d 100644 --- a/src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithHTMLImageTag.txt +++ b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag.txt @@ -1,2 +1,2 @@ -## Something +## Something \ No newline at end of file diff --git a/src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithscript.txt b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithscript.txt similarity index 100% rename from src/modules/previewpane/PreviewPaneUnitTests/HelperFiles/MarkdownWithscript.txt rename to src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithscript.txt diff --git a/src/modules/previewpane/PreviewPaneUnitTests/MarkdownPreviewHandlerTest.cs b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/MarkdownPreviewHandlerTest.cs similarity index 99% rename from src/modules/previewpane/PreviewPaneUnitTests/MarkdownPreviewHandlerTest.cs rename to src/modules/previewpane/UnitTests-MarkdownPreviewHandler/MarkdownPreviewHandlerTest.cs index e1b525dc9d..eb43a18a0e 100644 --- a/src/modules/previewpane/PreviewPaneUnitTests/MarkdownPreviewHandlerTest.cs +++ b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/MarkdownPreviewHandlerTest.cs @@ -9,7 +9,7 @@ using Microsoft.PowerToys.STATestExtension; using Microsoft.VisualStudio.TestTools.UnitTesting; using PreviewHandlerCommon; -namespace PreviewPaneUnitTests +namespace MarkdownPreviewHandlerUnitTests { [STATestClass] public class MarkdownPreviewHandlerTest diff --git a/src/modules/previewpane/PreviewPaneUnitTests/UnitTests-MarkdownPreviewHandler.csproj b/src/modules/previewpane/UnitTests-MarkdownPreviewHandler/UnitTests-MarkdownPreviewHandler.csproj similarity index 100% rename from src/modules/previewpane/PreviewPaneUnitTests/UnitTests-MarkdownPreviewHandler.csproj rename to src/modules/previewpane/UnitTests-MarkdownPreviewHandler/UnitTests-MarkdownPreviewHandler.csproj diff --git a/src/modules/previewpane/UnitTests-PdfPreviewHandler/HelperFiles/sample.pdf b/src/modules/previewpane/UnitTests-PdfPreviewHandler/HelperFiles/sample.pdf new file mode 100644 index 0000000000..96304d9b21 Binary files /dev/null and b/src/modules/previewpane/UnitTests-PdfPreviewHandler/HelperFiles/sample.pdf differ diff --git a/src/modules/previewpane/UnitTests-PdfPreviewHandler/PdfPreviewHandlerTest.cs b/src/modules/previewpane/UnitTests-PdfPreviewHandler/PdfPreviewHandlerTest.cs new file mode 100644 index 0000000000..492ed80ba0 --- /dev/null +++ b/src/modules/previewpane/UnitTests-PdfPreviewHandler/PdfPreviewHandlerTest.cs @@ -0,0 +1,89 @@ +// 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.Drawing; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Windows.Forms; +using Microsoft.PowerToys.PreviewHandler.Pdf; +using Microsoft.PowerToys.STATestExtension; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; + +namespace PdfPreviewHandlerUnitTests +{ + [STATestClass] + public class PdfPreviewHandlerTest + { + [TestMethod] + public void PdfPreviewHandlerControlAddsControlsToFormWhenDoPreviewIsCalled() + { + // Arrange + using (var pdfPreviewHandlerControl = new PdfPreviewHandlerControl()) + { + // Act + var file = File.ReadAllBytes("HelperFiles/sample.pdf"); + + pdfPreviewHandlerControl.DoPreview(GetMockStream(file)); + + var flowLayoutPanel = pdfPreviewHandlerControl.Controls[0] as FlowLayoutPanel; + + // Assert + Assert.AreEqual(1, pdfPreviewHandlerControl.Controls.Count); + } + } + + [TestMethod] + public void PdfPreviewHandlerControlShouldAddValidInfoBarIfPdfPreviewThrows() + { + // Arrange + using (var pdfPreviewHandlerControl = new PdfPreviewHandlerControl()) + { + var mockStream = new Mock(); + mockStream + .Setup(x => x.Read(It.IsAny(), It.IsAny(), It.IsAny())) + .Throws(new Exception()); + + // Act + pdfPreviewHandlerControl.DoPreview(mockStream.Object); + var textBox = pdfPreviewHandlerControl.Controls[0] as RichTextBox; + + // Assert + Assert.IsFalse(string.IsNullOrWhiteSpace(textBox.Text)); + Assert.AreEqual(1, pdfPreviewHandlerControl.Controls.Count); + Assert.AreEqual(DockStyle.Top, textBox.Dock); + Assert.AreEqual(Color.LightYellow, textBox.BackColor); + Assert.IsTrue(textBox.Multiline); + Assert.IsTrue(textBox.ReadOnly); + Assert.AreEqual(RichTextBoxScrollBars.None, textBox.ScrollBars); + Assert.AreEqual(BorderStyle.None, textBox.BorderStyle); + } + } + + private static IStream GetMockStream(byte[] sourceArray) + { + var streamMock = new Mock(); + var firstCall = true; + streamMock + .Setup(x => x.Read(It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((buffer, countToRead, bytesReadPtr) => + { + if (firstCall) + { + Array.Copy(sourceArray, 0, buffer, 0, sourceArray.Length); + Marshal.WriteInt32(bytesReadPtr, sourceArray.Length); + firstCall = false; + } + else + { + Marshal.WriteInt32(bytesReadPtr, 0); + } + }); + + return streamMock.Object; + } + } +} diff --git a/src/modules/previewpane/UnitTests-PdfPreviewHandler/UnitTests-PdfPreviewHandler.csproj b/src/modules/previewpane/UnitTests-PdfPreviewHandler/UnitTests-PdfPreviewHandler.csproj new file mode 100644 index 0000000000..4fdfd32c98 --- /dev/null +++ b/src/modules/previewpane/UnitTests-PdfPreviewHandler/UnitTests-PdfPreviewHandler.csproj @@ -0,0 +1,67 @@ + + + x64 + UnitTests-PdfPreviewHandler + PowerToys UnitTests-PdfPreviewHandler + Microsoft Corp. + Copyright (C) 2020 Microsoft Corp. + PowerToys + UnitTests-PdfPreviewHandler + Microsoft Corp. + PowerToys + en-US + PowerToys UnitTests-PdfPreviewHandler + Copyright (C) 2020 Microsoft Corp. + + + + {ECC20689-002A-4354-95A6-B58DF089C6FF} + PreviewPaneUnitTests + PreviewPaneUnitTests + netcoreapp3.1 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + + + + + + + + + + + + + + + + all + + + + + + + + + + + + + Always + + + + + StyleCop.json + + + + + all + + + \ No newline at end of file diff --git a/src/modules/previewpane/powerpreview/CLSID.h b/src/modules/previewpane/powerpreview/CLSID.h index 64fc376a45..104e2d8ef8 100644 --- a/src/modules/previewpane/powerpreview/CLSID.h +++ b/src/modules/previewpane/powerpreview/CLSID.h @@ -16,6 +16,12 @@ const CLSID CLSID_SHIMActivateMdPreviewHandler = { 0xE0907A95, 0x6F9A, 0x4D1B, { // 45769bcc-e8fd-42d0-947e-02beef77a1f5 const CLSID CLSID_MdPreviewHandler = { 0x45769bcc, 0xe8fd, 0x42d0, { 0x94, 0x7e, 0x02, 0xbe, 0xef, 0x77, 0xa1, 0xf5 } }; +// 4F6D533B-4185-43A6-AD75-9B20034B14CA +const CLSID CLSID_SHIMActivatePdfPreviewHandler = { 0x4f6d533b, 0x4185, 0x43a6, { 0xad, 0x75, 0x9b, 0x20, 0x3, 0x4b, 0x14, 0xca } }; + +// 07665729-6243-4746-95b7-79579308d1b2 +const CLSID CLSID_PdfPreviewHandler = { 0x07665729, 0x6243, 0x4746, { 0x95, 0xb7, 0x79, 0x57, 0x93, 0x08, 0xd1, 0xb2 } }; + // 9C723B8C-4F5C-4147-9DE4-C2808F9AF66B const CLSID CLSID_SHIMActivateSvgThumbnailProvider = { 0x9C723B8C, 0x4F5C, 0x4147, { 0x9D, 0xE4, 0xC2, 0x80, 0x8F, 0x9A, 0xF6, 0x6B } }; @@ -23,8 +29,9 @@ const CLSID CLSID_SHIMActivateSvgThumbnailProvider = { 0x9C723B8C, 0x4F5C, 0x414 const CLSID CLSID_SvgThumbnailProvider = { 0x36B27788, 0xA8BB, 0x4698, { 0xA7, 0x56, 0xDF, 0x9F, 0x11, 0xF6, 0x4F, 0x84 } }; // Pairs of NativeClsid vs ManagedClsid used for preview handlers. -const std::vector> NativeToManagedClsid({ +const std::vector> NativeToManagedClsid({ { CLSID_SHIMActivateMdPreviewHandler, CLSID_MdPreviewHandler }, + { CLSID_SHIMActivatePdfPreviewHandler, CLSID_PdfPreviewHandler }, { CLSID_SHIMActivateSvgPreviewHandler, CLSID_SvgPreviewHandler }, { CLSID_SHIMActivateSvgThumbnailProvider, CLSID_SvgThumbnailProvider } }); \ No newline at end of file diff --git a/src/modules/previewpane/powerpreview/Resources.resx b/src/modules/previewpane/powerpreview/Resources.resx index 0b4cbf17bd..7af9b5effe 100644 --- a/src/modules/previewpane/powerpreview/Resources.resx +++ b/src/modules/previewpane/powerpreview/Resources.resx @@ -167,5 +167,11 @@ Don't show again - + + + PDF Previewer + + + PDF Previewer + \ No newline at end of file diff --git a/src/modules/previewpane/powerpreview/powerpreview.cpp b/src/modules/previewpane/powerpreview/powerpreview.cpp index 8856834445..27e6a482f6 100644 --- a/src/modules/previewpane/powerpreview/powerpreview.cpp +++ b/src/modules/previewpane/powerpreview/powerpreview.cpp @@ -33,6 +33,14 @@ PowerPreviewModule::PowerPreviewModule() : L"Markdown Preview Handler", std::make_unique())); + m_fileExplorerModules.emplace_back(std::make_unique( + true, + L"pdf-previewer-toggle-setting", + GET_RESOURCE_STRING(IDS_PREVPANE_PDF_SETTINGS_DESCRIPTION), + L"{07665729-6243-4746-95b7-79579308d1b2}", + L"PDF Preview Handler", + std::make_unique())); + m_fileExplorerModules.emplace_back(std::make_unique( true, L"svg-thumbnail-toggle-setting", diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerPreviewProperties.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerPreviewProperties.cs index 6e7e4b4297..8a5b5f7c83 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerPreviewProperties.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerPreviewProperties.cs @@ -63,6 +63,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library } } + private bool enablePdfPreview = true; + + [JsonPropertyName("pdf-previewer-toggle-setting")] + [JsonConverter(typeof(BoolPropertyJsonConverter))] + public bool EnablePdfPreview + { + get => enablePdfPreview; + set + { + if (value != enablePdfPreview) + { + LogTelemetryEvent(value); + enablePdfPreview = value; + } + } + } + public PowerPreviewProperties() { } diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs index 911620fee1..ea1f22ea2a 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs @@ -49,10 +49,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels _svgRenderIsEnabled = Settings.Properties.EnableSvgPreview; _svgThumbnailIsEnabled = Settings.Properties.EnableSvgThumbnail; _mdRenderIsEnabled = Settings.Properties.EnableMdPreview; + _pdfRenderIsEnabled = Settings.Properties.EnablePdfPreview; } private bool _svgRenderIsEnabled; private bool _mdRenderIsEnabled; + private bool _pdfRenderIsEnabled; private bool _svgThumbnailIsEnabled; public bool SVGRenderIsEnabled @@ -109,6 +111,24 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels } } + public bool PDFRenderIsEnabled + { + get + { + return _pdfRenderIsEnabled; + } + + set + { + if (value != _pdfRenderIsEnabled) + { + _pdfRenderIsEnabled = value; + Settings.Properties.EnablePdfPreview = value; + RaisePropertyChanged(); + } + } + } + public string GetSettingsSubPath() { return _settingsConfigFileFolder + "\\" + ModuleName; diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs index 07b03abb90..878069c8a9 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs @@ -57,6 +57,7 @@ namespace ViewModelTests // Verify that the old settings persisted Assert.AreEqual(originalGeneralSettings.IsElevated, viewModel.IsElevated); Assert.AreEqual(originalSettings.Properties.EnableMdPreview, viewModel.MDRenderIsEnabled); + Assert.AreEqual(originalSettings.Properties.EnablePdfPreview, viewModel.PDFRenderIsEnabled); Assert.AreEqual(originalSettings.Properties.EnableSvgPreview, viewModel.SVGRenderIsEnabled); Assert.AreEqual(originalSettings.Properties.EnableSvgThumbnail, viewModel.SVGThumbnailIsEnabled); @@ -118,5 +119,23 @@ namespace ViewModelTests // act viewModel.MDRenderIsEnabled = true; } + + [TestMethod] + public void PDFRenderIsEnabledShouldPrevHandlerWhenSuccessful() + { + // Assert + Func sendMockIPCConfigMSG = msg => + { + SndModuleSettings snd = JsonSerializer.Deserialize>(msg); + Assert.IsTrue(snd.PowertoysSetting.FileExplorerPreviewSettings.Properties.EnablePdfPreview); + return 0; + }; + + // arrange + PowerPreviewViewModel viewModel = new PowerPreviewViewModel(SettingsRepository.GetInstance(mockPowerPreviewSettingsUtils.Object), SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), sendMockIPCConfigMSG, PowerPreviewSettings.ModuleName); + + // act + viewModel.PDFRenderIsEnabled = true; + } } } diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Controls/Setting/Setting.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Controls/Setting/Setting.xaml index 382d4972bc..49c4122c0f 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Controls/Setting/Setting.xaml +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Controls/Setting/Setting.xaml @@ -58,7 +58,6 @@ Foreground="{ThemeResource CardPrimaryForegroundBrush}" VerticalAlignment="Center"/> - Enable SVG (.svg) preview Do you want this feature on / off + + Enable PDF (.pdf) preview + Do you want this feature on / off + Enable SVG (.svg) thumbnails Do you want this feature on / off diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml index 12d43ef077..5693f88554 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml @@ -18,7 +18,6 @@ ModuleImageSource="ms-appx:///Assets/Modules/PowerPreview.png"> - + + + + + + - - - + diff --git a/tools/BugReportTool/BugReportTool/RegistryUtils.cpp b/tools/BugReportTool/BugReportTool/RegistryUtils.cpp index d1a1fc5ffb..6acad09576 100644 --- a/tools/BugReportTool/BugReportTool/RegistryUtils.cpp +++ b/tools/BugReportTool/BugReportTool/RegistryUtils.cpp @@ -19,12 +19,14 @@ namespace { HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\AppUserModelId\\PowerToysRun" }, { HKEY_CLASSES_ROOT, L".svg\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" }, { HKEY_CLASSES_ROOT, L".svg\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" }, - { HKEY_CLASSES_ROOT, L".md\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" } + { HKEY_CLASSES_ROOT, L".md\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" }, + { HKEY_CLASSES_ROOT, L".pdf\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" } }; vector> registryValues = { { HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{ddee2b8a-6807-48a6-bb20-2338174ff779}" }, { HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{45769bcc-e8fd-42d0-947e-02beef77a1f5}" }, + { HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{07665729-6243-4746-95b7-79579308d1b2}" }, { HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", L"prevhost.exe" }, { HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", L"dllhost.exe" } };