Merge pull request #2156 from xamarin/fix-github1630 fixes #1630

[MacOS] Implement the navigation events on MacOS
This commit is contained in:
Rui Marinho 2018-03-21 19:26:37 +00:00 коммит произвёл GitHub
Родитель 2055c2aea7 eda1edef61
Коммит 2533912019
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1 изменённых файлов: 77 добавлений и 24 удалений

Просмотреть файл

@ -4,12 +4,15 @@ using AppKit;
using Foundation;
using Xamarin.Forms.Internals;
using WebKit;
namespace Xamarin.Forms.Platform.MacOS
{
public class WebViewRenderer : ViewRenderer<WebView, WebKit.WebView>, IWebViewDelegate
public class WebViewRenderer : ViewRenderer<WebView, WebKit.WebView>, IWebViewDelegate, WebKit.IWebPolicyDelegate
{
bool _disposed;
bool _ignoreSourceChanges;
bool _sentNavigating;
WebNavigationEvent _lastBackForwardEvent;
WebNavigationEvent _lastEvent;
@ -25,6 +28,46 @@ namespace Xamarin.Forms.Platform.MacOS
Control.MainFrame.LoadRequest(new NSUrlRequest(new NSUrl(url)));
}
[Export("webView:decidePolicyForNavigationAction:request:frame:decisionListener:")]
public void DecidePolicyForNavigation(WebKit.WebView webView, NSDictionary actionInformation, NSUrlRequest request, WebKit.WebFrame frame, WebKit.IWebPolicyDecisionListener decisionToken)
{
var navEvent = WebNavigationEvent.NewPage;
if(actionInformation.ContainsKey(WebPolicyDelegate.WebActionNavigationTypeKey))
{
var navigationType = ((WebNavigationType)((NSNumber)actionInformation[WebPolicyDelegate.WebActionNavigationTypeKey]).Int32Value);
switch (navigationType)
{
case WebNavigationType.BackForward:
navEvent = _lastBackForwardEvent;
break;
case WebNavigationType.Reload:
navEvent = WebNavigationEvent.Refresh;
break;
case WebNavigationType.FormResubmitted:
case WebNavigationType.FormSubmitted:
case WebNavigationType.LinkClicked:
case WebNavigationType.Other:
navEvent = WebNavigationEvent.NewPage;
break;
}
}
if (!_sentNavigating)
{
_lastEvent = navEvent;
_sentNavigating = true;
var lastUrl = request.Url.ToString();
var args = new WebNavigatingEventArgs(navEvent, new UrlWebViewSource { Url = lastUrl }, lastUrl);
Element.SendNavigating(args);
UpdateCanGoBackForward();
if (!args.Cancel)
{
decisionToken.Use();
}
}
}
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
@ -38,13 +81,13 @@ namespace Xamarin.Forms.Platform.MacOS
AutoresizingMask = NSViewResizingMask.WidthSizable,
AutoresizesSubviews = true
});
Control.OnFinishedLoading += OnNSWebViewFinishedLoad;
Control.OnFailedLoading += OnNSWebViewFailedLoadWithError;
Element.EvalRequested += OnEvalRequested;
Element.GoBackRequested += OnGoBackRequested;
Element.GoForwardRequested += OnGoForwardRequested;
Control.FrameLoadDelegate = new FormsWebFrameDelegate(this);
Control.PolicyDelegate = this;
Layer.BackgroundColor = NSColor.Clear.CGColor;
}
}
@ -65,8 +108,6 @@ namespace Xamarin.Forms.Platform.MacOS
if (disposing && !_disposed)
{
_disposed = true;
Control.OnFinishedLoading -= OnNSWebViewFinishedLoad;
Control.OnFailedLoading -= OnNSWebViewFailedLoadWithError;
Element.EvalRequested -= OnEvalRequested;
Element.GoBackRequested -= OnGoBackRequested;
Element.GoForwardRequested -= OnGoForwardRequested;
@ -119,29 +160,41 @@ namespace Xamarin.Forms.Platform.MacOS
UpdateCanGoBackForward();
}
void OnNSWebViewFailedLoadWithError(object sender, WebKit.WebResourceErrorEventArgs e)
internal class FormsWebFrameDelegate : WebKit.WebFrameLoadDelegate
{
_lastEvent = _lastBackForwardEvent;
Element?.SendNavigated(new WebNavigatedEventArgs(_lastEvent, new UrlWebViewSource { Url = Control.MainFrameUrl },
Control.MainFrameUrl, WebNavigationResult.Failure));
WebViewRenderer _renderer;
internal FormsWebFrameDelegate(WebViewRenderer renderer)
{
_renderer = renderer;
}
UpdateCanGoBackForward();
}
public override void FinishedLoad(WebKit.WebView sender, WebFrame forFrame)
{
_renderer._sentNavigating = false;
void OnNSWebViewFinishedLoad(object sender, WebKit.WebResourceCompletedEventArgs e)
{
if (Control.IsLoading)
return;
if (_renderer.Control.IsLoading)
return;
_ignoreSourceChanges = true;
Element?.SetValueFromRenderer(WebView.SourceProperty, new UrlWebViewSource { Url = Control.MainFrameUrl });
_ignoreSourceChanges = false;
_renderer._ignoreSourceChanges = true;
_renderer.Element?.SetValueFromRenderer(WebView.SourceProperty, new UrlWebViewSource { Url = _renderer.Control.MainFrameUrl });
_renderer._ignoreSourceChanges = false;
_lastEvent = _lastBackForwardEvent;
Element?.SendNavigated(new WebNavigatedEventArgs(_lastEvent, Element?.Source, Control.MainFrameUrl,
WebNavigationResult.Success));
_renderer._lastEvent = _renderer._lastBackForwardEvent;
_renderer.Element?.SendNavigated(new WebNavigatedEventArgs(_renderer._lastEvent, _renderer.Element?.Source, _renderer.Control.MainFrameUrl, WebNavigationResult.Success));
UpdateCanGoBackForward();
_renderer.UpdateCanGoBackForward();
}
public override void FailedLoadWithError(WebKit.WebView sender, NSError error, WebFrame forFrame)
{
_renderer._sentNavigating = false;
_renderer._lastEvent = _renderer._lastBackForwardEvent;
_renderer.Element?.SendNavigated(new WebNavigatedEventArgs(_renderer._lastEvent, new UrlWebViewSource { Url = _renderer.Control.MainFrameUrl }, _renderer.Control.MainFrameUrl, WebNavigationResult.Failure));
_renderer.UpdateCanGoBackForward();
}
}
}
}