3028e9e29d
* First pass adding async * Updated Idle manager to work with async Tasks * CA1506 * missing async * Fixed tests * Really fixed tests * CA2201 * Really fixed the tests * remaining awaits * Async everywhere! * Fixed merge errors * fix: Missing imports * IProgress sync used * rename progress * format * Remove empty files * update sdk * convert progress * use FireAndForget and readonly struct * revert revit to use RevitTask * don't use sync to UI thread for progress * Fixes autocad loop to update UI with Task.Delay instead of Task.Yield * format * merge fixes * update nugets * fix imports for exceptions * fix import --------- Co-authored-by: Alan Rynne <alan@speckle.systems> Co-authored-by: Adam Hathcock <adam@hathcock.uk>
111 lines
3.3 KiB
C#
111 lines
3.3 KiB
C#
using System.Windows.Controls;
|
|
using System.Windows.Threading;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Web.WebView2.Core;
|
|
using Speckle.Connectors.DUI.Bindings;
|
|
using Speckle.Connectors.DUI.Bridge;
|
|
|
|
namespace Speckle.Connectors.DUI.WebView;
|
|
|
|
public sealed partial class DUI3ControlWebView : UserControl, IBrowserScriptExecutor, IDisposable
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
|
|
public DUI3ControlWebView(IServiceProvider serviceProvider)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
InitializeComponent();
|
|
|
|
Browser.CoreWebView2InitializationCompleted += (sender, args) =>
|
|
_serviceProvider
|
|
.GetRequiredService<ITopLevelExceptionHandler>()
|
|
.CatchUnhandled(() => OnInitialized(sender, args));
|
|
}
|
|
|
|
public bool IsBrowserInitialized => Browser.IsInitialized;
|
|
|
|
public object BrowserElement => Browser;
|
|
|
|
// {
|
|
// if (!Browser.IsInitialized)
|
|
// {
|
|
// throw new InvalidOperationException("Failed to execute script, Webview2 is not initialized yet.");
|
|
// }
|
|
//
|
|
// var t = Browser.Dispatcher.Invoke(
|
|
// async () =>
|
|
// {
|
|
// var res = await Browser.ExecuteScriptAsync(script).ConfigureAwait(true);
|
|
// await Task.Delay(100).ConfigureAwait(true);
|
|
// return res;
|
|
// },
|
|
// DispatcherPriority.Background
|
|
// );
|
|
//
|
|
// _ = t.IsCompleted;
|
|
|
|
// bool isAlreadyMainThread = Browser.Dispatcher.CheckAccess();
|
|
// if (isAlreadyMainThread)
|
|
// {
|
|
// Browser.ExecuteScriptAsync(script);
|
|
// }
|
|
// else
|
|
// {
|
|
// Browser.Dispatcher.Invoke(
|
|
// () =>
|
|
// {
|
|
// return Browser.ExecuteScriptAsync(script);
|
|
// },
|
|
// DispatcherPriority.Background
|
|
// );
|
|
// }
|
|
// }
|
|
|
|
public async Task ExecuteScriptAsyncMethod(string script, CancellationToken cancellationToken)
|
|
{
|
|
if (!Browser.IsInitialized)
|
|
{
|
|
throw new InvalidOperationException("Failed to execute script, Webview2 is not initialized yet.");
|
|
}
|
|
|
|
var callbackTask = await Browser
|
|
.Dispatcher.InvokeAsync(
|
|
async () => await Browser.ExecuteScriptAsync(script).ConfigureAwait(false),
|
|
DispatcherPriority.Background,
|
|
cancellationToken
|
|
)
|
|
.Task.ConfigureAwait(false);
|
|
|
|
_ = await callbackTask.ConfigureAwait(false);
|
|
}
|
|
|
|
private void OnInitialized(object? sender, CoreWebView2InitializationCompletedEventArgs e)
|
|
{
|
|
if (!e.IsSuccess)
|
|
{
|
|
throw new InvalidOperationException("Webview Failed to initialize", e.InitializationException);
|
|
}
|
|
|
|
// We use Lazy here to delay creating the binding until after the Browser is fully initialized.
|
|
// Otherwise the Browser cannot respond to any requests to ExecuteScriptAsyncMethod
|
|
foreach (var binding in _serviceProvider.GetRequiredService<IEnumerable<IBinding>>())
|
|
{
|
|
SetupBinding(binding);
|
|
}
|
|
}
|
|
|
|
/// <remark>
|
|
/// This must be called on the Main thread
|
|
/// </remark>
|
|
private void SetupBinding(IBinding binding)
|
|
{
|
|
binding.Parent.AssociateWithBinding(binding);
|
|
Browser.CoreWebView2.AddHostObjectToScript(binding.Name, binding.Parent);
|
|
}
|
|
|
|
public void ShowDevTools() => Browser.CoreWebView2.OpenDevToolsWindow();
|
|
|
|
//https://github.com/MicrosoftEdge/WebView2Feedback/issues/2161
|
|
public void Dispose() => Browser.Dispatcher.Invoke(() => Browser.Dispose(), DispatcherPriority.Send);
|
|
}
|