Skip to content

Commit

Permalink
Fix for #2407 - MapHandler Throws InvalidSystemOperationExcetption (#…
Browse files Browse the repository at this point in the history
…2409)

* Call EnsureCoreWebView2Async() before trying to execute script
Fixes #2407

* Rename to `TryCallJSMethod`

* Update MapHandler.Windows.cs

---------

Co-authored-by: Brandon Minnick <[email protected]>
  • Loading branch information
mikelor and TheCodeTraveler authored Jan 2, 2025
1 parent 1f67ed4 commit 33bda60
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<ApplicationVersion>1</ApplicationVersion>

<!--
Uncomment the line below if you need to debug the SG code
Uncomment the lines below if you need to debug the SG code
If you see any LongPath issue on Windows, check this doc
https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later
-->
Expand Down
56 changes: 34 additions & 22 deletions src/CommunityToolkit.Maui.Maps/Handler/Map/MapHandler.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ protected override FrameworkElement CreatePlatformView()
webView.NavigationCompleted += HandleWebViewNavigationCompleted;
webView.WebMessageReceived += WebViewWebMessageReceived;
webView.LoadHtml(mapPage, null);

return webView;
}

Expand All @@ -88,31 +89,31 @@ protected override void DisconnectHandler(FrameworkElement platformView)
/// </summary>
public static new Task MapMapType(IMapHandler handler, IMap map)
{
return CallJSMethod(handler.PlatformView, $"setMapType('{map.MapType}');");
return TryCallJSMethod(handler.PlatformView, $"setMapType('{map.MapType}');");
}

/// <summary>
/// Maps IsZoomEnabled
/// </summary>
public static new Task MapIsZoomEnabled(IMapHandler handler, IMap map)
{
return CallJSMethod(handler.PlatformView, $"disableMapZoom({(!map.IsZoomEnabled).ToString().ToLower()});");
return TryCallJSMethod(handler.PlatformView, $"disableMapZoom({(!map.IsZoomEnabled).ToString().ToLower()});");
}

/// <summary>
/// Maps IsScrollEnabled
/// </summary>
public static new Task MapIsScrollEnabled(IMapHandler handler, IMap map)
{
return CallJSMethod(handler.PlatformView, $"disablePanning({(!map.IsScrollEnabled).ToString().ToLower()});");
return TryCallJSMethod(handler.PlatformView, $"disablePanning({(!map.IsScrollEnabled).ToString().ToLower()});");
}

/// <summary>
/// Maps IsTrafficEnabled
/// </summary>
public static new Task MapIsTrafficEnabled(IMapHandler handler, IMap map)
{
return CallJSMethod(handler.PlatformView, $"disableTraffic({(!map.IsTrafficEnabled).ToString().ToLower()});");
return TryCallJSMethod(handler.PlatformView, $"disableTraffic({(!map.IsTrafficEnabled).ToString().ToLower()});");
}

/// <summary>
Expand All @@ -123,14 +124,14 @@ protected override void DisconnectHandler(FrameworkElement platformView)
if (map.IsShowingUser)
{
var location = await GetCurrentLocation();
if (location != null)
if (location is not null)
{
await CallJSMethod(handler.PlatformView, $"addLocationPin({location.Latitude.ToString(CultureInfo.InvariantCulture)},{location.Longitude.ToString(CultureInfo.InvariantCulture)});");
await TryCallJSMethod(handler.PlatformView, $"addLocationPin({location.Latitude.ToString(CultureInfo.InvariantCulture)},{location.Longitude.ToString(CultureInfo.InvariantCulture)});");
}
}
else
{
await CallJSMethod(handler.PlatformView, "removeLocationPin();");
await TryCallJSMethod(handler.PlatformView, "removeLocationPin();");
}
}

Expand All @@ -139,13 +140,13 @@ protected override void DisconnectHandler(FrameworkElement platformView)
/// </summary>
public static new async Task MapPins(IMapHandler handler, IMap map)
{
await CallJSMethod(handler.PlatformView, "removeAllPins();");
await TryCallJSMethod(handler.PlatformView, "removeAllPins();");

var addPinTaskList = new List<Task>();

foreach (var pin in map.Pins)
{
addPinTaskList.Add(CallJSMethod(handler.PlatformView, $"addPin({pin.Location.Latitude.ToString(CultureInfo.InvariantCulture)}," +
addPinTaskList.Add(TryCallJSMethod(handler.PlatformView, $"addPin({pin.Location.Latitude.ToString(CultureInfo.InvariantCulture)}," +
$"{pin.Location.Longitude.ToString(CultureInfo.InvariantCulture)},'{pin.Label}', '{pin.Address}', '{(pin as Pin)?.Id}');"));
}

Expand All @@ -172,22 +173,33 @@ protected override void DisconnectHandler(FrameworkElement platformView)
mapHandler.regionToGo = newRegion;
}

await CallJSMethod(handler.PlatformView, $"setRegion({newRegion.Center.Latitude.ToString(CultureInfo.InvariantCulture)},{newRegion.Center.Longitude.ToString(CultureInfo.InvariantCulture)},{newRegion.LatitudeDegrees.ToString(CultureInfo.InvariantCulture)},{newRegion.LongitudeDegrees.ToString(CultureInfo.InvariantCulture)});");
await TryCallJSMethod(handler.PlatformView, $"setRegion({newRegion.Center.Latitude.ToString(CultureInfo.InvariantCulture)},{newRegion.Center.Longitude.ToString(CultureInfo.InvariantCulture)},{newRegion.LatitudeDegrees.ToString(CultureInfo.InvariantCulture)},{newRegion.LongitudeDegrees.ToString(CultureInfo.InvariantCulture)});");
}

static async Task CallJSMethod(FrameworkElement platformWebView, string script)
static async Task<bool> TryCallJSMethod(FrameworkElement platformWebView, string script)
{
if (platformWebView is WebView2 webView2)
if (platformWebView is not WebView2 webView2)
{
var tcs = new TaskCompletionSource();
webView2.DispatcherQueue.TryEnqueue(async () =>
{
await webView2.ExecuteScriptAsync(script);
tcs.SetResult();
});
return false;
}

await tcs.Task;
await webView2.EnsureCoreWebView2Async();

var tcs = new TaskCompletionSource();
var isEnqueueSuccessful = webView2.DispatcherQueue.TryEnqueue(async () =>
{
await webView2.ExecuteScriptAsync(script);
tcs.SetResult();
});

if (!isEnqueueSuccessful)
{
return false;
}

await tcs.Task;

return true;
}

static string GetMapHtmlPage(string key)
Expand Down Expand Up @@ -413,7 +425,7 @@ async void HandleWebViewNavigationCompleted(WebView2 sender, CoreWebView2Navigat
// Update initial properties when our page is loaded
Mapper.UpdateProperties(this, VirtualView);

if (regionToGo != null)
if (regionToGo is not null)
{
await MapMoveToRegion(this, VirtualView, regionToGo);
}
Expand Down Expand Up @@ -476,7 +488,7 @@ async void WebViewWebMessageReceived(WebView2 sender, CoreWebView2WebMessageRece
var hideInfoWindow = clickedPin?.SendInfoWindowClick();
if (hideInfoWindow is not false)
{
await CallJSMethod(PlatformView, "hideInfoWindow();");
await TryCallJSMethod(PlatformView, "hideInfoWindow();");
}
}
break;
Expand All @@ -492,7 +504,7 @@ async void WebViewWebMessageReceived(WebView2 sender, CoreWebView2WebMessageRece
var hideInfoWindow = clickedPin?.SendMarkerClick();
if (hideInfoWindow is not false)
{
await CallJSMethod(PlatformView, "hideInfoWindow();");
await TryCallJSMethod(PlatformView, "hideInfoWindow();");
}
}
break;
Expand Down
9 changes: 7 additions & 2 deletions src/CommunityToolkit.Maui/CommunityToolkit.Maui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsAotCompatible>true</IsAotCompatible>

<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
<!--
Uncomment the lines below if you need to debug the SG code
If you see any LongPath issue on Windows, check this doc
https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later
-->
<!--<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath> -->

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

Expand Down

0 comments on commit 33bda60

Please sign in to comment.