Skip to content

Commit

Permalink
Initial HybridWebView control to send messages between C# and .NET
Browse files Browse the repository at this point in the history
Fixes #22302
  • Loading branch information
Eilon committed Jul 11, 2024
1 parent facb5ef commit c4d65c5
Show file tree
Hide file tree
Showing 45 changed files with 2,069 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<views:BasePage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Pages.HybridWebViewPage"
xmlns:views="clr-namespace:Maui.Controls.Sample.Pages.Base"
Title="HybridWebView">
<views:BasePage.Content>

<Grid ColumnDefinitions="2*,1*" RowDefinitions="Auto,1*">

<Label
Grid.Row="0"
Grid.Column="0"
Text="HybridWebView here"
x:Name="statusLabel" />

<Button
Grid.Row="0"
Grid.Column="1"
Text="Send message to JS"
Clicked="SendMessageButton_Clicked" />

<HybridWebView
x:Name="hwv"
Grid.Row="1"
Grid.ColumnSpan="2"
HybridRoot="HybridSamplePage"
RawMessageReceived="hwv_RawMessageReceived"/>

</Grid>
</views:BasePage.Content>
</views:BasePage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using Microsoft.Maui.Controls;

namespace Maui.Controls.Sample.Pages
{
public partial class HybridWebViewPage
{
public HybridWebViewPage()
{
InitializeComponent();
}

private void SendMessageButton_Clicked(object sender, EventArgs e)
{
hwv.SendRawMessage("Hello from C#!");
}

private void hwv_RawMessageReceived(object sender, HybridWebViewRawMessageReceivedEventArgs e)
{
Dispatcher.Dispatch(() => statusLabel.Text += e.Message);
}
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="styles/app.css">
<script src="scripts/HybridWebView.js"></script>
<script>
window.addEventListener(
"HybridWebViewMessageReceived",
function (e) {
var messageFromCSharp = document.getElementById("messageFromCSharp");
messageFromCSharp.value += '\r\n' + e.detail.message;
});
</script>
</head>
<body>
<div>
Hybrid sample!
</div>
<div>
<button onclick="window.HybridWebView.SendRawMessage('Message from JS!')">Send message to C#</button>
</div>
<div>
Message from C#: <textarea readonly id="messageFromCSharp" style="width: 80%; height: 10em;"></textarea>
</div>
<div>
Consider checking out this PDF: <a href="docs/sample.pdf">sample.pdf</a>
</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
function HybridWebViewInit() {

function DispatchHybridWebViewMessage(message) {
const event = new CustomEvent("HybridWebViewMessageReceived", { detail: { message: message } });
window.dispatchEvent(event);
}

if (window.chrome && window.chrome.webview) {
// Windows WebView2
window.chrome.webview.addEventListener('message', arg => {
DispatchHybridWebViewMessage(arg.data);
});
}
else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
// iOS and MacCatalyst WKWebView
window.external = {
"receiveMessage": message => {
DispatchHybridWebViewMessage(message);
}
};
}
else {
// Android WebView
window.addEventListener('message', arg => {
DispatchHybridWebViewMessage(arg.data);
});
}
}

window.HybridWebView = {
"SendRawMessage": function (message) {

if (window.chrome && window.chrome.webview) {
// Windows WebView2
window.chrome.webview.postMessage(message);
}
else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
// iOS and MacCatalyst WKWebView
window.webkit.messageHandlers.webwindowinterop.postMessage(message);
}
else {
// Android WebView
hybridWebViewHost.sendRawMessage(message);
}
}
}

HybridWebViewInit();
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
button
{
background-color: dodgerblue;
border-radius: 5px;
border-width: 1px;
color: white;
cursor: pointer;
margin: 6px;
text-align: center;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ protected override IEnumerable<SectionModel> CreateItems() => new[]
new SectionModel(typeof(EntryPage), "Entry",
"The Entry control is used for single-line text input."),

new SectionModel(typeof(HybridWebViewPage), "HybridWebView",
"The HybridWebView control embeds web content locally and natively in an app."),

new SectionModel(typeof(ImagePage), "Image",
"Displays an image."),

Expand Down
54 changes: 54 additions & 0 deletions src/Controls/src/Core/HybridWebView/HybridWebView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;

namespace Microsoft.Maui.Controls
{
/// <summary>
/// A <see cref="View"/> that presents local HTML content in a web view and allows JavaScript and C# code to interop using messages.
/// </summary>
public class HybridWebView : View, IHybridWebView
{
/// <summary>Bindable property for <see cref="DefaultFile"/>.</summary>
public static readonly BindableProperty DefaultFileProperty =
BindableProperty.Create(nameof(DefaultFile), typeof(string), typeof(HybridWebView), defaultValue: "index.html");
/// <summary>Bindable property for <see cref="HybridRoot"/>.</summary>
public static readonly BindableProperty HybridRootProperty =
BindableProperty.Create(nameof(HybridRoot), typeof(string), typeof(HybridWebView), defaultValue: "HybridRoot");


/// <summary>
/// Specifies the file within the <see cref="HybridRoot"/> that should be served as the default file. The
/// default value is <c>index.html</c>.
/// </summary>
public string? DefaultFile
{
get { return (string)GetValue(DefaultFileProperty); }
set { SetValue(DefaultFileProperty, value); }
}

/// <summary>
/// The path within the app's "Raw" asset resources that contain the web app's contents. For example, if the
/// files are located in <c>[ProjectFolder]/Resources/Raw/hybrid_root</c>, then set this property to "hybrid_root".
/// The default value is <c>HybridRoot</c>, which maps to <c>[ProjectFolder]/Resources/Raw/HybridRoot</c>.
/// </summary>
public string? HybridRoot
{
get { return (string)GetValue(HybridRootProperty); }
set { SetValue(HybridRootProperty, value); }
}

void IHybridWebView.RawMessageReceived(string rawMessage)
{
RawMessageReceived?.Invoke(this, new HybridWebViewRawMessageReceivedEventArgs(rawMessage));
}

/// <summary>
/// Raised when a raw message is received from the web view. Raw messages are strings that have no additional processing.
/// </summary>
public event EventHandler<HybridWebViewRawMessageReceivedEventArgs>? RawMessageReceived;

public void SendRawMessage(string rawMessage)
{
Handler?.Invoke(nameof(IHybridWebView.SendRawMessage), rawMessage);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace Microsoft.Maui.Controls
{
public class HybridWebViewRawMessageReceivedEventArgs : EventArgs
{
public HybridWebViewRawMessageReceivedEventArgs(string? message)
{
Message = message;
}

public string? Message { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
#nullable enable
Microsoft.Maui.Controls.HybridWebView
Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string?
Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string?
Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void
Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler<Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs!>?
Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string?
Microsoft.Maui.Controls.PlatformDragStartingEventArgs
Microsoft.Maui.Controls.PlatformDragStartingEventArgs.Sender.get -> Android.Views.View!
Microsoft.Maui.Controls.PlatformDragStartingEventArgs.MotionEvent.get -> Android.Views.MotionEvent!
Expand Down Expand Up @@ -73,6 +84,8 @@ Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan
Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan
Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void
Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler<Microsoft.Maui.Controls.TimeChangedEventArgs>
static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.KeyProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.ModifiersProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.DragGestureRecognizer.CanDragProperty -> Microsoft.Maui.Controls.BindableProperty!
Expand Down
13 changes: 13 additions & 0 deletions src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
#nullable enable
Microsoft.Maui.Controls.HybridWebView
Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string?
Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string?
Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void
Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler<Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs!>?
Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string?
override Microsoft.Maui.Controls.Handlers.Compatibility.CellRenderer.Invoke(string! command, object? args) -> void
override Microsoft.Maui.Controls.Handlers.Compatibility.CellRenderer.UpdateValue(string! property) -> void
override Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer.PreferredStatusBarUpdateAnimation.get -> UIKit.UIStatusBarAnimation
Expand Down Expand Up @@ -89,6 +100,8 @@ override Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.Pref
override Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.PrefersHomeIndicatorAutoHidden.get -> bool
override Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.PrefersStatusBarHidden() -> bool
override Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer.ViewDidAppear(bool animated) -> void
static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.KeyProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.ModifiersProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.DragGestureRecognizer.CanDragProperty -> Microsoft.Maui.Controls.BindableProperty!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
#nullable enable
Microsoft.Maui.Controls.HybridWebView
Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string?
Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string?
Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void
Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler<Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs!>?
Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string?
override Microsoft.Maui.Controls.Handlers.Compatibility.CellRenderer.Invoke(string! command, object? args) -> void
override Microsoft.Maui.Controls.Handlers.Compatibility.CellRenderer.UpdateValue(string! property) -> void
override Microsoft.Maui.Controls.GradientBrush.IsEmpty.get -> bool
Expand Down Expand Up @@ -83,6 +94,8 @@ Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan
Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void
Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler<Microsoft.Maui.Controls.TimeChangedEventArgs>
override Microsoft.Maui.Controls.Handlers.Items.ItemsViewController<TItemsView>.LoadView() -> void
static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.KeyProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.ModifiersProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.DragGestureRecognizer.CanDragProperty -> Microsoft.Maui.Controls.BindableProperty!
Expand Down
13 changes: 13 additions & 0 deletions src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
#nullable enable
Microsoft.Maui.Controls.HybridWebView
Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string?
Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string?
Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void
Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler<Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs!>?
Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string?
Microsoft.Maui.Controls.PlatformDragStartingEventArgs
Microsoft.Maui.Controls.PlatformDropCompletedEventArgs
Microsoft.Maui.Controls.PlatformDragEventArgs
Expand Down Expand Up @@ -55,6 +66,8 @@ Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan
Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void
Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler<Microsoft.Maui.Controls.TimeChangedEventArgs>
override Microsoft.Maui.Controls.GradientBrush.IsEmpty.get -> bool
static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.KeyProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.ModifiersProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.DragGestureRecognizer.CanDragProperty -> Microsoft.Maui.Controls.BindableProperty!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
#nullable enable
Microsoft.Maui.Controls.Handlers.Items.CarouselViewHandler.~CarouselViewHandler() -> void
Microsoft.Maui.Controls.HybridWebView
Microsoft.Maui.Controls.HybridWebView.DefaultFile.get -> string?
Microsoft.Maui.Controls.HybridWebView.DefaultFile.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridRoot.get -> string?
Microsoft.Maui.Controls.HybridWebView.HybridRoot.set -> void
Microsoft.Maui.Controls.HybridWebView.HybridWebView() -> void
Microsoft.Maui.Controls.HybridWebView.RawMessageReceived -> System.EventHandler<Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs!>?
Microsoft.Maui.Controls.HybridWebView.SendRawMessage(string! rawMessage) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.HybridWebViewRawMessageReceivedEventArgs(string? message) -> void
Microsoft.Maui.Controls.HybridWebViewRawMessageReceivedEventArgs.Message.get -> string?
Microsoft.Maui.Controls.PlatformDragStartingEventArgs
Microsoft.Maui.Controls.PlatformDragStartingEventArgs.Sender.get -> Microsoft.UI.Xaml.UIElement!
Microsoft.Maui.Controls.PlatformDragStartingEventArgs.DragStartingEventArgs.get -> Microsoft.UI.Xaml.DragStartingEventArgs!
Expand Down Expand Up @@ -80,6 +91,8 @@ Microsoft.Maui.Controls.TimeChangedEventArgs.NewTime.get -> System.TimeSpan
Microsoft.Maui.Controls.TimeChangedEventArgs.OldTime.get -> System.TimeSpan
Microsoft.Maui.Controls.TimeChangedEventArgs.TimeChangedEventArgs(System.TimeSpan oldTime, System.TimeSpan newTime) -> void
Microsoft.Maui.Controls.TimePicker.TimeSelected -> System.EventHandler<Microsoft.Maui.Controls.TimeChangedEventArgs>
static readonly Microsoft.Maui.Controls.HybridWebView.DefaultFileProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.HybridWebView.HybridRootProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.KeyProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.ModifiersProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.DragGestureRecognizer.CanDragProperty -> Microsoft.Maui.Controls.BindableProperty!
Expand Down
Loading

0 comments on commit c4d65c5

Please sign in to comment.