diff --git a/src/modules/peek/Peek.FilePreviewer/Controls/BrowserControl.xaml.cs b/src/modules/peek/Peek.FilePreviewer/Controls/BrowserControl.xaml.cs
index 534cdb734c..c9ef112ea9 100644
--- a/src/modules/peek/Peek.FilePreviewer/Controls/BrowserControl.xaml.cs
+++ b/src/modules/peek/Peek.FilePreviewer/Controls/BrowserControl.xaml.cs
@@ -28,9 +28,6 @@ namespace Peek.FilePreviewer.Controls
public event DOMContentLoadedHandler? DOMContentLoaded;
- private string previewBrowserUserDataFolder = System.Environment.GetEnvironmentVariable("USERPROFILE") +
- "\\AppData\\LocalLow\\Microsoft\\PowerToys\\Peek-Temp";
-
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
nameof(Source),
typeof(Uri),
@@ -43,10 +40,40 @@ namespace Peek.FilePreviewer.Controls
set { SetValue(SourceProperty, value); }
}
+ public static readonly DependencyProperty IsDevFilePreviewProperty = DependencyProperty.Register(
+ nameof(IsDevFilePreview),
+ typeof(bool),
+ typeof(BrowserControl),
+ new PropertyMetadata(null, new PropertyChangedCallback((d, e) => ((BrowserControl)d).SourcePropertyChanged())));
+
+ public bool IsDevFilePreview
+ {
+ get
+ {
+ return (bool)GetValue(IsDevFilePreviewProperty);
+ }
+
+ set
+ {
+ SetValue(IsDevFilePreviewProperty, value);
+
+ if (PreviewBrowser.CoreWebView2 != null)
+ {
+ PreviewBrowser.CoreWebView2.Settings.IsScriptEnabled = value;
+ if (value)
+ {
+ PreviewBrowser.CoreWebView2.SetVirtualHostNameToFolderMapping(Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.VirtualHostName, Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.MonacoDirectory, CoreWebView2HostResourceAccessKind.Allow);
+ }
+ }
+ }
+ }
+
+ public string? TempDataFolder { get; set; }
+
public BrowserControl()
{
this.InitializeComponent();
- Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", previewBrowserUserDataFolder, EnvironmentVariableTarget.Process);
+ Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", TempDataFolder, EnvironmentVariableTarget.Process);
}
public void Dispose()
@@ -68,7 +95,7 @@ namespace Peek.FilePreviewer.Controls
_navigatedUri = null;
- if (Source != null)
+ if (Source != null && PreviewBrowser.CoreWebView2 != null)
{
/* CoreWebView2.Navigate() will always trigger a navigation even if the content/URI is the same.
* Use WebView2.Source to avoid re-navigating to the same content. */
@@ -93,15 +120,23 @@ namespace Peek.FilePreviewer.Controls
PreviewBrowser.CoreWebView2.Settings.AreHostObjectsAllowed = false;
PreviewBrowser.CoreWebView2.Settings.IsGeneralAutofillEnabled = false;
PreviewBrowser.CoreWebView2.Settings.IsPasswordAutosaveEnabled = false;
- PreviewBrowser.CoreWebView2.Settings.IsScriptEnabled = false;
+ PreviewBrowser.CoreWebView2.Settings.IsScriptEnabled = IsDevFilePreview;
PreviewBrowser.CoreWebView2.Settings.IsWebMessageEnabled = false;
+ if (IsDevFilePreview)
+ {
+ Logger.LogInfo("Set virtual host name to folder mapping: " + Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.MonacoDirectory);
+ PreviewBrowser.CoreWebView2.SetVirtualHostNameToFolderMapping(Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.VirtualHostName, Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.MonacoDirectory, CoreWebView2HostResourceAccessKind.Allow);
+ }
+
PreviewBrowser.CoreWebView2.DOMContentLoaded += CoreWebView2_DOMContentLoaded;
}
catch (Exception ex)
{
Logger.LogError("WebView2 loading failed. " + ex.Message);
}
+
+ Navigate();
}
private void CoreWebView2_DOMContentLoaded(CoreWebView2 sender, CoreWebView2DOMContentLoadedEventArgs args)
diff --git a/src/modules/peek/Peek.FilePreviewer/Controls/TextFilePreview.xaml b/src/modules/peek/Peek.FilePreviewer/Controls/TextFilePreview.xaml
deleted file mode 100644
index 701fd33648..0000000000
--- a/src/modules/peek/Peek.FilePreviewer/Controls/TextFilePreview.xaml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/modules/peek/Peek.FilePreviewer/Controls/TextFilePreview.xaml.cs b/src/modules/peek/Peek.FilePreviewer/Controls/TextFilePreview.xaml.cs
deleted file mode 100644
index 7d06ae0122..0000000000
--- a/src/modules/peek/Peek.FilePreviewer/Controls/TextFilePreview.xaml.cs
+++ /dev/null
@@ -1,164 +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 CommunityToolkit.Mvvm.ComponentModel;
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Controls;
-using Microsoft.Web.WebView2.Core;
-using Peek.Common.Helpers;
-using Windows.System;
-
-namespace Peek.FilePreviewer.Controls
-{
- [INotifyPropertyChanged]
- public sealed partial class TextFilePreview : UserControl, IDisposable
- {
- ///
- /// Helper private Uri where we cache the last navigated page
- /// so we can redirect internal PDF or Webpage links to external
- /// webbrowser, avoiding WebView internal navigation.
- ///
- private Uri? _navigatedUri;
-
- public delegate void NavigationCompletedHandler(WebView2? sender, CoreWebView2NavigationCompletedEventArgs? args);
-
- public delegate void DOMContentLoadedHandler(CoreWebView2? sender, CoreWebView2DOMContentLoadedEventArgs? args);
-
- public event NavigationCompletedHandler? NavigationCompleted;
-
- public event DOMContentLoadedHandler? DOMContentLoaded;
-
- public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
- nameof(Source),
- typeof(Uri),
- typeof(TextFilePreview),
- new PropertyMetadata(null, new PropertyChangedCallback((d, e) => ((TextFilePreview)d).SourcePropertyChanged())));
-
- public string? TempDataFolder { get; set; }
-
- public Uri? Source
- {
- get { return (Uri)GetValue(SourceProperty); }
- set { SetValue(SourceProperty, value); }
- }
-
- public TextFilePreview()
- {
- this.InitializeComponent();
- Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", TempDataFolder, EnvironmentVariableTarget.Process);
- }
-
- public void Dispose()
- {
- if (PreviewText.CoreWebView2 != null)
- {
- PreviewText.CoreWebView2.DOMContentLoaded -= CoreWebView2_DOMContentLoaded;
- }
- }
-
- ///
- /// Navigate to the to the set in .
- /// Calling will always trigger a navigation/refresh
- /// even if web target file is the same.
- ///
- public void Navigate()
- {
- var value = Environment.GetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS");
-
- _navigatedUri = null;
-
- if (Source != null && PreviewText.CoreWebView2 != null)
- {
- /* CoreWebView2.Navigate() will always trigger a navigation even if the content/URI is the same.
- * Use WebView2.Source to avoid re-navigating to the same content. */
- PreviewText.CoreWebView2.Navigate(Source.ToString());
- }
- }
-
- private void SourcePropertyChanged()
- {
- Navigate();
- }
-
- private async void PreviewText_Loading(FrameworkElement sender, object args)
- {
- if (PreviewText.CoreWebView2 == null)
- {
- try
- {
- await PreviewText.EnsureCoreWebView2Async();
- }
- catch (Exception ex)
- {
- Logger.LogError("CoreWebView2 initialization failed. " + ex.Message);
- }
- }
- }
-
- private void CoreWebView2_DOMContentLoaded(CoreWebView2 sender, CoreWebView2DOMContentLoadedEventArgs args)
- {
- DOMContentLoaded?.Invoke(sender, args);
- }
-
- private async void PreviewText_NavigationStarting(WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs args)
- {
- if (_navigatedUri == null)
- {
- return;
- }
-
- // In case user starts or tries to navigate from within the HTML file we launch default web browser for navigation.
- if (args.Uri != null && args.Uri != _navigatedUri?.ToString() && args.IsUserInitiated)
- {
- args.Cancel = true;
- await Launcher.LaunchUriAsync(new Uri(args.Uri));
- }
- }
-
- private void PreviewText_NavigationCompleted(WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs args)
- {
- if (args.IsSuccess)
- {
- _navigatedUri = Source;
- }
-
- // OperationCanceled status code is used when the app cancels a navigation via NavigationStarting event
- if (args.WebErrorStatus != CoreWebView2WebErrorStatus.OperationCanceled)
- {
- NavigationCompleted?.Invoke(sender, args);
- }
- }
-
- private void PreviewText_CoreWebView2Initialized(WebView2 sender, CoreWebView2InitializedEventArgs args)
- {
- try
- {
- sender.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
- sender.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
- sender.CoreWebView2.Settings.AreDevToolsEnabled = false;
- sender.CoreWebView2.Settings.AreHostObjectsAllowed = false;
- sender.CoreWebView2.Settings.IsGeneralAutofillEnabled = false;
- sender.CoreWebView2.Settings.IsPasswordAutosaveEnabled = false;
- sender.CoreWebView2.Settings.IsScriptEnabled = true; // TODO: enable only for dev files
- sender.CoreWebView2.Settings.IsWebMessageEnabled = false;
-
- sender.CoreWebView2.SetVirtualHostNameToFolderMapping(Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.VirtualHostName, Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.MonacoDirectory, CoreWebView2HostResourceAccessKind.Allow);
-
- sender.CoreWebView2.DOMContentLoaded += CoreWebView2_DOMContentLoaded;
-
- if (Source != null)
- {
- /* CoreWebView2.Navigate() will always trigger a navigation even if the content/URI is the same.
- * Use WebView2.Source to avoid re-navigating to the same content. */
- sender.CoreWebView2.Navigate(Source.ToString());
- }
- }
- catch (Exception ex)
- {
- Logger.LogError("WebView2 loading failed. " + ex.Message);
- }
- }
- }
-}
diff --git a/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml b/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml
index 1ce73960fe..73e36ac8ba 100644
--- a/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml
+++ b/src/modules/peek/Peek.FilePreviewer/FilePreview.xaml
@@ -32,17 +32,10 @@
DOMContentLoaded="BrowserPreview_DOMContentLoaded"
NavigationCompleted="PreviewBrowser_NavigationCompleted"
Source="{x:Bind BrowserPreviewer.Preview, Mode=OneWay}"
+ TempDataFolder="{x:Bind BrowserPreviewer.TempDataFolder, Mode=OneTime}"
+ IsDevFilePreview="{x:Bind BrowserPreviewer.IsDevFilePreview, Mode=OneWay}"
Visibility="{x:Bind IsPreviewVisible(BrowserPreviewer, Previewer.State), Mode=OneWay, FallbackValue=Collapsed}" />
-
-
Previewer as IBrowserPreviewer;
- public ITextFilePreviewer? TextFilePreviewer => Previewer as ITextFilePreviewer;
-
public IUnsupportedFilePreviewer? UnsupportedFilePreviewer => Previewer as IUnsupportedFilePreviewer;
public IFileSystemItem Item
@@ -126,7 +123,7 @@ namespace Peek.FilePreviewer
public bool IsWebPreview(IPreviewer? previewer, PreviewState? state)
{
- var isWebViewPreview = previewer != null && (previewer is ITextFilePreviewer || previewer is IBrowserPreviewer);
+ var isWebViewPreview = previewer != null && previewer is IBrowserPreviewer;
return isWebViewPreview && MatchPreviewState(state, PreviewState.Loaded);
}
@@ -223,25 +220,6 @@ namespace Peek.FilePreviewer
}
}
- private void TextPreview_DOMContentLoaded(CoreWebView2 sender, CoreWebView2DOMContentLoadedEventArgs args)
- {
- /*
- * There is an odd behavior where the WebView2 would not raise the NavigationCompleted event
- * for certain HTML files, even though it has already been loaded. Probably related to certain
- * extra module that require more time to load. One example is saving and opening google.com locally.
- *
- * So to address this, we will make the Browser visible and display it as "Loaded" as soon the HTML document
- * has been parsed and loaded with the DOMContentLoaded event.
- *
- * Similar issue: https://github.com/MicrosoftEdge/WebView2Feedback/issues/998
- */
-
- if (TextFilePreviewer != null)
- {
- TextFilePreviewer.State = PreviewState.Loaded;
- }
- }
-
private void PreviewBrowser_NavigationCompleted(WebView2 sender, CoreWebView2NavigationCompletedEventArgs args)
{
/*
@@ -261,25 +239,6 @@ namespace Peek.FilePreviewer
}
}
- private void TextPreview_NavigationCompleted(WebView2 sender, CoreWebView2NavigationCompletedEventArgs args)
- {
- /*
- * In theory most of navigation should work after DOM is loaded.
- * But in case something fails we check NavigationCompleted event
- * for failure and switch visibility accordingly.
- *
- * As an alternative, in the future, the preview control
- * could also display error content.
- */
- if (!args.IsSuccess)
- {
- if (TextFilePreviewer != null)
- {
- TextFilePreviewer.State = PreviewState.Error;
- }
- }
- }
-
private async void KeyboardAccelerator_CtrlC_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
if (Previewer != null)
diff --git a/src/modules/peek/Peek.FilePreviewer/Peek.FilePreviewer.csproj b/src/modules/peek/Peek.FilePreviewer/Peek.FilePreviewer.csproj
index 9fb3dd6301..ed348f9266 100644
--- a/src/modules/peek/Peek.FilePreviewer/Peek.FilePreviewer.csproj
+++ b/src/modules/peek/Peek.FilePreviewer/Peek.FilePreviewer.csproj
@@ -10,7 +10,6 @@
-
@@ -51,10 +50,4 @@
-
-
-
- MSBuild:Compile
-
-
diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IBrowserPreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IBrowserPreviewer.cs
index 8436b1e0cb..9ad5e8dc29 100644
--- a/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IBrowserPreviewer.cs
+++ b/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/IBrowserPreviewer.cs
@@ -9,5 +9,9 @@ namespace Peek.FilePreviewer.Previewers
public interface IBrowserPreviewer : IPreviewer
{
public Uri? Preview { get; }
+
+ public string TempDataFolder { get; }
+
+ public bool IsDevFilePreview { get; }
}
}
diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/ITextFilePreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/ITextFilePreviewer.cs
deleted file mode 100644
index c9d5c8d685..0000000000
--- a/src/modules/peek/Peek.FilePreviewer/Previewers/Interfaces/ITextFilePreviewer.cs
+++ /dev/null
@@ -1,15 +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;
-
-namespace Peek.FilePreviewer.Previewers
-{
- public interface ITextFilePreviewer : IPreviewer
- {
- public Uri? Preview { get; }
-
- public string TempDataFolder { get; }
- }
-}
diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/PreviewerFactory.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/PreviewerFactory.cs
index a4b275248f..8a8b0becdc 100644
--- a/src/modules/peek/Peek.FilePreviewer/Previewers/PreviewerFactory.cs
+++ b/src/modules/peek/Peek.FilePreviewer/Previewers/PreviewerFactory.cs
@@ -20,10 +20,6 @@ namespace Peek.FilePreviewer.Previewers
{
return new WebBrowserPreviewer(file);
}
- else if (TextFilePreviewer.IsFileTypeSupported(file.Extension))
- {
- return new TextFilePreviewer(file);
- }
// Other previewer types check their supported file types here
return CreateDefaultPreviewer(file);
diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/TextFilePreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/TextFilePreviewer.cs
deleted file mode 100644
index b3e1293af3..0000000000
--- a/src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/TextFilePreviewer.cs
+++ /dev/null
@@ -1,131 +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.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using CommunityToolkit.Mvvm.ComponentModel;
-using Microsoft.UI.Dispatching;
-using Peek.Common.Extensions;
-using Peek.Common.Helpers;
-using Peek.Common.Models;
-using Windows.Foundation;
-
-namespace Peek.FilePreviewer.Previewers
-{
- public partial class TextFilePreviewer : ObservableObject, ITextFilePreviewer, IDisposable
- {
- [ObservableProperty]
- private Uri? preview;
-
- [ObservableProperty]
- private PreviewState state;
-
- [ObservableProperty]
- private string tempDataFolder = Environment.GetEnvironmentVariable("USERPROFILE") +
- "\\AppData\\LocalLow\\Microsoft\\PowerToys\\Peek-Temp";
-
- public TextFilePreviewer(IFileSystemItem file)
- {
- Item = file;
- Dispatcher = DispatcherQueue.GetForCurrentThread();
- }
-
- public bool IsPreviewLoaded => preview != null;
-
- private IFileSystemItem Item { get; }
-
- private DispatcherQueue Dispatcher { get; }
-
- private Task? DisplayInfoTask { get; set; }
-
- public void Dispose()
- {
- Microsoft.PowerToys.FilePreviewCommon.Helper.CleanupTempDir(tempDataFolder);
- GC.SuppressFinalize(this);
- }
-
- public static bool IsFileTypeSupported(string fileExt)
- {
- return _supportedFileTypes.Contains(fileExt) || IsDevFile(fileExt);
- }
-
- public static bool IsDevFile(string fileExt)
- {
- return _supportedMonacoFileTypes.Contains(fileExt);
- }
-
- public Task GetPreviewSizeAsync(CancellationToken cancellationToken)
- {
- Size? size = new Size(1640, 1460);
- return Task.FromResult(size);
- }
-
- public async Task LoadPreviewAsync(CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- State = PreviewState.Loading;
- await LoadDisplayInfoAsync(cancellationToken);
-
- if (HasFailedLoadingPreview())
- {
- State = PreviewState.Error;
- }
- }
-
- public async Task CopyAsync()
- {
- await Dispatcher.RunOnUiThread(async () =>
- {
- var storageItem = await Item.GetStorageItemAsync();
- ClipboardHelper.SaveToClipboard(storageItem);
- });
- }
-
- public Task LoadDisplayInfoAsync(CancellationToken cancellationToken)
- {
- return TaskExtension.RunSafe(async () =>
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- await Dispatcher.RunOnUiThread(async () =>
- {
- var raw = await ReadHelper.Read(Item.Path.ToString());
- if (IsDevFile(Item.Extension))
- {
- Preview = new Uri(MonacoHelper.PreviewTempFile(raw, Item.Extension, tempDataFolder));
- }
- else
- {
- Preview = new Uri(WebViewHelper.PreviewTempFile(raw, Item.Path, tempDataFolder));
- }
- });
- });
- }
-
- partial void OnPreviewChanged(Uri? value)
- {
- if (Preview != null)
- {
- State = PreviewState.Loaded;
- }
- }
-
- private bool HasFailedLoadingPreview()
- {
- var hasFailedLoadingDisplayInfo = !(DisplayInfoTask?.Result ?? true);
-
- return hasFailedLoadingDisplayInfo;
- }
-
- private static readonly HashSet _supportedFileTypes = new HashSet
- {
- ".txt",
- ".md",
- };
-
- private static readonly HashSet _supportedMonacoFileTypes = MonacoHelper.GetExtensions();
- }
-}
diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/Helpers/WebViewHelper.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MarkdownHelper.cs
similarity index 96%
rename from src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/Helpers/WebViewHelper.cs
rename to src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MarkdownHelper.cs
index 13fb7880e5..0c22124162 100644
--- a/src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/Helpers/WebViewHelper.cs
+++ b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MarkdownHelper.cs
@@ -8,7 +8,7 @@ using Common.UI;
namespace Peek.FilePreviewer.Previewers
{
- public class WebViewHelper
+ public class MarkdownHelper
{
///
/// Prepares temp html for the previewing
diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/Helpers/MonacoHelper.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MonacoHelper.cs
similarity index 100%
rename from src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/Helpers/MonacoHelper.cs
rename to src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MonacoHelper.cs
diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/Helpers/ReadHelper.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/ReadHelper.cs
similarity index 100%
rename from src/modules/peek/Peek.FilePreviewer/Previewers/TextFilePreviewer/Helpers/ReadHelper.cs
rename to src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/ReadHelper.cs
diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/WebBrowserPreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/WebBrowserPreviewer.cs
index f4f2aa3386..fd0436c3ca 100644
--- a/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/WebBrowserPreviewer.cs
+++ b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/WebBrowserPreviewer.cs
@@ -15,7 +15,7 @@ using Windows.Foundation;
namespace Peek.FilePreviewer.Previewers
{
- public partial class WebBrowserPreviewer : ObservableObject, IBrowserPreviewer
+ public partial class WebBrowserPreviewer : ObservableObject, IBrowserPreviewer, IDisposable
{
private static readonly HashSet _supportedFileTypes = new HashSet
{
@@ -25,37 +25,89 @@ namespace Peek.FilePreviewer.Previewers
// Document
".pdf",
+
+ // Markdown
+ ".md",
};
+ private static readonly HashSet _supportedMonacoFileTypes = MonacoHelper.GetExtensions();
+
[ObservableProperty]
private Uri? preview;
[ObservableProperty]
private PreviewState state;
+ [ObservableProperty]
+ private string tempDataFolder = Environment.GetEnvironmentVariable("USERPROFILE") +
+ "\\AppData\\LocalLow\\Microsoft\\PowerToys\\Peek-Temp";
+
+ [ObservableProperty]
+ private bool isDevFilePreview;
+
public WebBrowserPreviewer(IFileSystemItem file)
{
File = file;
Dispatcher = DispatcherQueue.GetForCurrentThread();
}
+ public void Dispose()
+ {
+ Microsoft.PowerToys.FilePreviewCommon.Helper.CleanupTempDir(tempDataFolder);
+ GC.SuppressFinalize(this);
+ }
+
private IFileSystemItem File { get; }
+ public bool IsPreviewLoaded => preview != null;
+
private DispatcherQueue Dispatcher { get; }
+ private Task? DisplayInfoTask { get; set; }
+
public Task GetPreviewSizeAsync(CancellationToken cancellationToken)
{
Size? size = null;
return Task.FromResult(size);
}
- public Task LoadPreviewAsync(CancellationToken cancellationToken)
+ public async Task LoadPreviewAsync(CancellationToken cancellationToken)
{
+ cancellationToken.ThrowIfCancellationRequested();
State = PreviewState.Loading;
+ await LoadDisplayInfoAsync(cancellationToken);
- Preview = new Uri(File.Path);
+ if (HasFailedLoadingPreview())
+ {
+ State = PreviewState.Error;
+ }
+ }
- return Task.CompletedTask;
+ public Task LoadDisplayInfoAsync(CancellationToken cancellationToken)
+ {
+ return TaskExtension.RunSafe(async () =>
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ await Dispatcher.RunOnUiThread(async () =>
+ {
+ IsDevFilePreview = _supportedMonacoFileTypes.Contains(File.Extension);
+ if (IsDevFilePreview)
+ {
+ var raw = await ReadHelper.Read(File.Path.ToString());
+ Preview = new Uri(MonacoHelper.PreviewTempFile(raw, File.Extension, tempDataFolder));
+ }
+ else if (File.Extension == ".md")
+ {
+ var raw = await ReadHelper.Read(File.Path.ToString());
+ Preview = new Uri(MarkdownHelper.PreviewTempFile(raw, File.Path, tempDataFolder));
+ }
+ else
+ {
+ Preview = new Uri(File.Path);
+ }
+ });
+ });
}
public async Task CopyAsync()
@@ -69,7 +121,12 @@ namespace Peek.FilePreviewer.Previewers
public static bool IsFileTypeSupported(string fileExt)
{
- return _supportedFileTypes.Contains(fileExt);
+ return _supportedFileTypes.Contains(fileExt) || _supportedMonacoFileTypes.Contains(fileExt);
+ }
+
+ private bool HasFailedLoadingPreview()
+ {
+ return !(DisplayInfoTask?.Result ?? true);
}
}
}