mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-12-12 10:19:20 +08:00
[Peek] add WV2 improvements (behavior and UX) (#22685)
* [Peek] added logic to get max monitor size for opening WebView2 * Removed ununsed dependency property * Added workaround for cases where the web page would not finish navigating in a quick timing, for example google.com. * Remove window extensions from common and use nullable size argument instead Co-authored-by: Samuel Chapleau <sachaple@microsoft.com>
This commit is contained in:
parent
1253ed6607
commit
c22e78870b
@ -10,7 +10,7 @@ namespace Peek.FilePreviewer.Controls
|
|||||||
using Microsoft.Web.WebView2.Core;
|
using Microsoft.Web.WebView2.Core;
|
||||||
using Windows.System;
|
using Windows.System;
|
||||||
|
|
||||||
public sealed partial class BrowserControl : UserControl
|
public sealed partial class BrowserControl : UserControl, IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper private Uri where we cache the last navigated page
|
/// Helper private Uri where we cache the last navigated page
|
||||||
@ -21,37 +21,37 @@ namespace Peek.FilePreviewer.Controls
|
|||||||
|
|
||||||
public delegate void NavigationCompletedHandler(WebView2? sender, CoreWebView2NavigationCompletedEventArgs? args);
|
public delegate void NavigationCompletedHandler(WebView2? sender, CoreWebView2NavigationCompletedEventArgs? args);
|
||||||
|
|
||||||
|
public delegate void DOMContentLoadedHandler(CoreWebView2? sender, CoreWebView2DOMContentLoadedEventArgs? args);
|
||||||
|
|
||||||
public event NavigationCompletedHandler? NavigationCompleted;
|
public event NavigationCompletedHandler? NavigationCompleted;
|
||||||
|
|
||||||
|
public event DOMContentLoadedHandler? DOMContentLoaded;
|
||||||
|
|
||||||
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
|
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
|
||||||
nameof(Source),
|
nameof(Source),
|
||||||
typeof(Uri),
|
typeof(Uri),
|
||||||
typeof(BrowserControl),
|
typeof(BrowserControl),
|
||||||
new PropertyMetadata(null, new PropertyChangedCallback((d, e) => ((BrowserControl)d).SourcePropertyChanged())));
|
new PropertyMetadata(null, new PropertyChangedCallback((d, e) => ((BrowserControl)d).SourcePropertyChanged())));
|
||||||
|
|
||||||
public static readonly DependencyProperty IsNavigationCompletedProperty = DependencyProperty.Register(
|
|
||||||
nameof(IsNavigationCompleted),
|
|
||||||
typeof(bool),
|
|
||||||
typeof(BrowserControl),
|
|
||||||
new PropertyMetadata(false));
|
|
||||||
|
|
||||||
public Uri? Source
|
public Uri? Source
|
||||||
{
|
{
|
||||||
get { return (Uri)GetValue(SourceProperty); }
|
get { return (Uri)GetValue(SourceProperty); }
|
||||||
set { SetValue(SourceProperty, value); }
|
set { SetValue(SourceProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsNavigationCompleted
|
|
||||||
{
|
|
||||||
get { return (bool)GetValue(IsNavigationCompletedProperty); }
|
|
||||||
set { SetValue(IsNavigationCompletedProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public BrowserControl()
|
public BrowserControl()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (PreviewBrowser.CoreWebView2 != null)
|
||||||
|
{
|
||||||
|
PreviewBrowser.CoreWebView2.DOMContentLoaded -= CoreWebView2_DOMContentLoaded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Navigate to the to the <see cref="Uri"/> set in <see cref="Source"/>.
|
/// Navigate to the to the <see cref="Uri"/> set in <see cref="Source"/>.
|
||||||
/// Calling <see cref="Navigate"/> will always trigger a navigation/refresh
|
/// Calling <see cref="Navigate"/> will always trigger a navigation/refresh
|
||||||
@ -59,7 +59,8 @@ namespace Peek.FilePreviewer.Controls
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Navigate()
|
public void Navigate()
|
||||||
{
|
{
|
||||||
IsNavigationCompleted = false;
|
var value = Environment.GetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS");
|
||||||
|
|
||||||
_navigatedUri = null;
|
_navigatedUri = null;
|
||||||
|
|
||||||
if (Source != null)
|
if (Source != null)
|
||||||
@ -89,6 +90,8 @@ namespace Peek.FilePreviewer.Controls
|
|||||||
PreviewBrowser.CoreWebView2.Settings.IsPasswordAutosaveEnabled = false;
|
PreviewBrowser.CoreWebView2.Settings.IsPasswordAutosaveEnabled = false;
|
||||||
PreviewBrowser.CoreWebView2.Settings.IsScriptEnabled = false;
|
PreviewBrowser.CoreWebView2.Settings.IsScriptEnabled = false;
|
||||||
PreviewBrowser.CoreWebView2.Settings.IsWebMessageEnabled = false;
|
PreviewBrowser.CoreWebView2.Settings.IsWebMessageEnabled = false;
|
||||||
|
|
||||||
|
PreviewBrowser.CoreWebView2.DOMContentLoaded += CoreWebView2_DOMContentLoaded;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -96,6 +99,11 @@ namespace Peek.FilePreviewer.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CoreWebView2_DOMContentLoaded(CoreWebView2 sender, CoreWebView2DOMContentLoadedEventArgs args)
|
||||||
|
{
|
||||||
|
DOMContentLoaded?.Invoke(sender, args);
|
||||||
|
}
|
||||||
|
|
||||||
private async void PreviewBrowser_NavigationStarting(WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs args)
|
private async void PreviewBrowser_NavigationStarting(WebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs args)
|
||||||
{
|
{
|
||||||
if (_navigatedUri == null)
|
if (_navigatedUri == null)
|
||||||
@ -115,8 +123,6 @@ namespace Peek.FilePreviewer.Controls
|
|||||||
{
|
{
|
||||||
if (args.IsSuccess)
|
if (args.IsSuccess)
|
||||||
{
|
{
|
||||||
IsNavigationCompleted = true;
|
|
||||||
|
|
||||||
_navigatedUri = Source;
|
_navigatedUri = Source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
x:Name="BrowserPreview"
|
x:Name="BrowserPreview"
|
||||||
x:Load="True"
|
x:Load="True"
|
||||||
NavigationCompleted="PreviewBrowser_NavigationCompleted"
|
NavigationCompleted="PreviewBrowser_NavigationCompleted"
|
||||||
|
DOMContentLoaded="BrowserPreview_DOMContentLoaded"
|
||||||
Source="{x:Bind BrowserPreviewer.Preview, Mode=OneWay}"
|
Source="{x:Bind BrowserPreviewer.Preview, Mode=OneWay}"
|
||||||
Visibility="{x:Bind IsPreviewVisible(BrowserPreviewer, Previewer.State), Mode=OneWay, FallbackValue=Collapsed}" />
|
Visibility="{x:Bind IsPreviewVisible(BrowserPreviewer, Previewer.State), Mode=OneWay, FallbackValue=Collapsed}" />
|
||||||
|
|
||||||
|
@ -153,15 +153,43 @@ namespace Peek.FilePreviewer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PreviewBrowser_NavigationCompleted(WebView2 sender, CoreWebView2NavigationCompletedEventArgs args)
|
private void BrowserPreview_DOMContentLoaded(Microsoft.Web.WebView2.Core.CoreWebView2 sender, Microsoft.Web.WebView2.Core.CoreWebView2DOMContentLoadedEventArgs args)
|
||||||
{
|
{
|
||||||
// Once browser has completed navigation it is ready to be visible
|
/*
|
||||||
|
* 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 (BrowserPreviewer != null)
|
if (BrowserPreviewer != null)
|
||||||
{
|
{
|
||||||
BrowserPreviewer.State = PreviewState.Loaded;
|
BrowserPreviewer.State = PreviewState.Loaded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PreviewBrowser_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 Browser control
|
||||||
|
* could also display error content.
|
||||||
|
*/
|
||||||
|
if (!args.IsSuccess)
|
||||||
|
{
|
||||||
|
if (BrowserPreviewer != null)
|
||||||
|
{
|
||||||
|
BrowserPreviewer.State = PreviewState.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void KeyboardAccelerator_CtrlC_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
private async void KeyboardAccelerator_CtrlC_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
||||||
{
|
{
|
||||||
if (Previewer != null)
|
if (Previewer != null)
|
||||||
|
@ -14,13 +14,13 @@ namespace Peek.FilePreviewer.Models
|
|||||||
|
|
||||||
public class PreviewSizeChangedArgs
|
public class PreviewSizeChangedArgs
|
||||||
{
|
{
|
||||||
public PreviewSizeChangedArgs(Size windowSizeRequested, SizeFormat sizeFormat = SizeFormat.Pixels)
|
public PreviewSizeChangedArgs(Size? windowSizeRequested, SizeFormat sizeFormat = SizeFormat.Pixels)
|
||||||
{
|
{
|
||||||
WindowSizeRequested = windowSizeRequested;
|
WindowSizeRequested = windowSizeRequested;
|
||||||
WindowSizeFormat = sizeFormat;
|
WindowSizeFormat = sizeFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Size WindowSizeRequested { get; init; }
|
public Size? WindowSizeRequested { get; init; }
|
||||||
|
|
||||||
public SizeFormat WindowSizeFormat { get; init; }
|
public SizeFormat WindowSizeFormat { get; init; }
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace Peek.FilePreviewer.Previewers
|
|||||||
|
|
||||||
public static bool IsFileTypeSupported(string fileExt) => throw new NotImplementedException();
|
public static bool IsFileTypeSupported(string fileExt) => throw new NotImplementedException();
|
||||||
|
|
||||||
public Task<Size> GetPreviewSizeAsync(CancellationToken cancellationToken);
|
public Task<Size?> GetPreviewSizeAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
Task LoadPreviewAsync(CancellationToken cancellationToken);
|
Task LoadPreviewAsync(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ namespace Peek.FilePreviewer.Previewers
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Size> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
public async Task<Size?> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
var propertyImageSize = await PropertyHelper.GetImageSize(File.Path);
|
var propertyImageSize = await PropertyHelper.GetImageSize(File.Path);
|
||||||
|
@ -56,7 +56,7 @@ namespace Peek.FilePreviewer.Previewers
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Size> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
public async Task<Size?> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var propertyImageSize = await PropertyHelper.GetImageSize(File.Path);
|
var propertyImageSize = await PropertyHelper.GetImageSize(File.Path);
|
||||||
if (propertyImageSize != Size.Empty)
|
if (propertyImageSize != Size.Empty)
|
||||||
|
@ -80,11 +80,12 @@ namespace Peek.FilePreviewer.Previewers
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Size> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
public Task<Size?> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
return new Size(UnsupportedFileWidthPercent, UnsupportedFileHeightPercent);
|
Size? size = new Size(UnsupportedFileWidthPercent, UnsupportedFileHeightPercent);
|
||||||
|
return size;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,10 +45,9 @@ namespace Peek.FilePreviewer.Previewers
|
|||||||
|
|
||||||
private DispatcherQueue Dispatcher { get; }
|
private DispatcherQueue Dispatcher { get; }
|
||||||
|
|
||||||
public Task<Size> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
public Task<Size?> GetPreviewSizeAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// TODO: define how to proper window size on HTML content.
|
Size? size = null;
|
||||||
var size = new Size(1280, 720);
|
|
||||||
return Task.FromResult(size);
|
return Task.FromResult(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,10 +94,11 @@ namespace Peek.UI
|
|||||||
/// <param name="e">PreviewSizeChangedArgs</param>
|
/// <param name="e">PreviewSizeChangedArgs</param>
|
||||||
private void FilePreviewer_PreviewSizeChanged(object sender, PreviewSizeChangedArgs e)
|
private void FilePreviewer_PreviewSizeChanged(object sender, PreviewSizeChangedArgs e)
|
||||||
{
|
{
|
||||||
// TODO: Use design-defined rules for adjusted window size
|
|
||||||
var requestedSize = e.WindowSizeRequested;
|
|
||||||
var monitorSize = this.GetMonitorSize();
|
var monitorSize = this.GetMonitorSize();
|
||||||
|
|
||||||
|
// If no size is requested, try to fit to the monitor size.
|
||||||
|
Size requestedSize = e.WindowSizeRequested ?? monitorSize;
|
||||||
|
|
||||||
var titleBarHeight = TitleBarControl.ActualHeight;
|
var titleBarHeight = TitleBarControl.ActualHeight;
|
||||||
|
|
||||||
var maxContentSize = new Size(0, 0);
|
var maxContentSize = new Size(0, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user