mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-24 04:00:02 +01:00
leave single webview control
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
|
||||
<!-- Licensed under the MIT License. -->
|
||||
|
||||
<UserControl
|
||||
x:Class="Peek.FilePreviewer.Controls.TextFilePreview"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid
|
||||
Margin="48"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition x:Name="FileInfo" Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:WebView2 Name ="PreviewText"
|
||||
Loading="PreviewText_Loading"
|
||||
CoreWebView2Initialized="PreviewText_CoreWebView2Initialized"
|
||||
NavigationStarting="PreviewText_NavigationStarting"
|
||||
NavigationCompleted="PreviewText_NavigationCompleted" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Navigate to the to the <see cref="Uri"/> set in <see cref="Source"/>.
|
||||
/// Calling <see cref="Navigate"/> will always trigger a navigation/refresh
|
||||
/// even if web target file is the same.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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}" />
|
||||
|
||||
<controls:TextFilePreview
|
||||
x:Name="TextPreview"
|
||||
x:Load="{x:Bind IsWebPreview(TextFilePreviewer, Previewer.State), Mode=OneWay}"
|
||||
Source="{x:Bind TextFilePreviewer.Preview, Mode=OneWay}"
|
||||
TempDataFolder="{x:Bind TextFilePreviewer.TempDataFolder, Mode=OneTime}"
|
||||
DOMContentLoaded="TextPreview_DOMContentLoaded"
|
||||
NavigationCompleted="TextPreview_NavigationCompleted"
|
||||
Visibility="{x:Bind IsPreviewVisible(TextFilePreviewer, Previewer.State), Mode=OneWay}" />
|
||||
|
||||
<controls:UnsupportedFilePreview
|
||||
x:Name="UnsupportedFilePreview"
|
||||
DateModified="{x:Bind UnsupportedFilePreviewer.DateModified, Mode=OneWay}"
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace Peek.FilePreviewer
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ImagePreviewer))]
|
||||
[NotifyPropertyChangedFor(nameof(BrowserPreviewer))]
|
||||
[NotifyPropertyChangedFor(nameof(TextFilePreviewer))]
|
||||
[NotifyPropertyChangedFor(nameof(UnsupportedFilePreviewer))]
|
||||
|
||||
private IPreviewer? previewer;
|
||||
@@ -89,8 +88,6 @@ namespace Peek.FilePreviewer
|
||||
|
||||
public IBrowserPreviewer? BrowserPreviewer => 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)
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Controls\BrowserControl.xaml" />
|
||||
<None Remove="Controls\TextFilePreview.xaml" />
|
||||
<None Remove="FilePreview.xaml" />
|
||||
<None Remove="UnsupportedFilePreview.xaml" />
|
||||
</ItemGroup>
|
||||
@@ -51,10 +50,4 @@
|
||||
<ItemGroup>
|
||||
<Folder Include="Previewers\DrivePreviewer\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\TextFilePreview.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -9,5 +9,9 @@ namespace Peek.FilePreviewer.Previewers
|
||||
public interface IBrowserPreviewer : IPreviewer
|
||||
{
|
||||
public Uri? Preview { get; }
|
||||
|
||||
public string TempDataFolder { get; }
|
||||
|
||||
public bool IsDevFilePreview { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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<bool>? 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<Size?> 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<bool> 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<string> _supportedFileTypes = new HashSet<string>
|
||||
{
|
||||
".txt",
|
||||
".md",
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> _supportedMonacoFileTypes = MonacoHelper.GetExtensions();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ using Common.UI;
|
||||
|
||||
namespace Peek.FilePreviewer.Previewers
|
||||
{
|
||||
public class WebViewHelper
|
||||
public class MarkdownHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Prepares temp html for the previewing
|
||||
@@ -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<string> _supportedFileTypes = new HashSet<string>
|
||||
{
|
||||
@@ -25,37 +25,89 @@ namespace Peek.FilePreviewer.Previewers
|
||||
|
||||
// Document
|
||||
".pdf",
|
||||
|
||||
// Markdown
|
||||
".md",
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> _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<bool>? DisplayInfoTask { get; set; }
|
||||
|
||||
public Task<Size?> 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<bool> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user