-
Notifications
You must be signed in to change notification settings - Fork 9.8k
/
WebViewRenderer.cs
84 lines (68 loc) · 2.94 KB
/
WebViewRenderer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Web.Infrastructure;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Components.WebView.Services;
internal class WebViewRenderer : WebRenderer
{
private readonly Queue<UnacknowledgedRenderBatch> _unacknowledgedRenderBatches = new();
private readonly Dispatcher _dispatcher;
private readonly IpcSender _ipcSender;
private long nextRenderBatchId = 1;
public WebViewRenderer(
IServiceProvider serviceProvider,
Dispatcher dispatcher,
IpcSender ipcSender,
ILoggerFactory loggerFactory,
WebViewJSRuntime jsRuntime,
JSComponentInterop jsComponentInterop) :
base(serviceProvider, loggerFactory, jsRuntime.ReadJsonSerializerOptions(), jsComponentInterop)
{
_dispatcher = dispatcher;
_ipcSender = ipcSender;
ElementReferenceContext = jsRuntime.ElementReferenceContext;
}
public override Dispatcher Dispatcher => _dispatcher;
protected override void HandleException(Exception exception)
{
// Notify the JS code so it can show the in-app UI
_ipcSender.NotifyUnhandledException(exception);
}
protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
{
var batchId = nextRenderBatchId++;
var tcs = new TaskCompletionSource();
_unacknowledgedRenderBatches.Enqueue(new UnacknowledgedRenderBatch
{
BatchId = batchId,
CompletionSource = tcs,
});
_ipcSender.ApplyRenderBatch(batchId, renderBatch);
return tcs.Task;
}
protected override void AttachRootComponentToBrowser(int componentId, string domElementSelector)
{
_ipcSender.AttachToDocument(componentId, domElementSelector);
}
public new int AddRootComponent(Type componentType, string domElementSelector)
=> base.AddRootComponent(componentType, domElementSelector);
public new Task RenderRootComponentAsync(int componentId, ParameterView parameters)
=> base.RenderRootComponentAsync(componentId, parameters);
public new void RemoveRootComponent(int componentId)
=> base.RemoveRootComponent(componentId);
public void NotifyRenderCompleted(long batchId)
{
var nextUnacknowledgedBatch = _unacknowledgedRenderBatches.Dequeue();
if (nextUnacknowledgedBatch.BatchId != batchId)
{
throw new InvalidOperationException($"Received unexpected acknowledgement for render batch {batchId} (next batch should be {nextUnacknowledgedBatch.BatchId})");
}
nextUnacknowledgedBatch.CompletionSource.SetResult();
}
record UnacknowledgedRenderBatch
{
public long BatchId { get; init; }
public TaskCompletionSource CompletionSource { get; init; }
}
}