using System.Linq; using Serilog; using TINK.Model.Device; using Xamarin.Forms; namespace TINK.View { public static class WebViewHelper { /// Rountes request to browser if internal URI was detected or displays link in app otherwise. /// Sender of the event. /// Event arguments public static void SelectDisplayTarget(object sender, WebNavigatingEventArgs eventArgs) { if (!eventArgs.Url.ToUpper().StartsWith("HTTP")) { // An internal link was detected. // Stay inside WebView eventArgs.Cancel = false; return; } // Do not navigate outside the document on web view. eventArgs.Cancel = true; // Open external link in browser. DependencyService.Get().OpenUrl(eventArgs.Url); } /// Routes request to broswer to download pdf- documents or displays link in app otherwise. /// Sender of the event. /// Event arguments public static void SetBusyAndDisplayOrDownload(object sender, WebNavigatingEventArgs eventArgs) { if (!eventArgs.Url.ToUpper().EndsWith(".PDF")) { // Stay inside web view except for downloading pdf- files. SetBusy(sender); eventArgs.Cancel = false; return; } // Do not navigate outside the document on web view. eventArgs.Cancel = true; // Open external link in browser. DependencyService.Get().OpenUrl(eventArgs.Url); } /// /// Disables WebView and shows ActivityIndicator. /// /// /// Prerequisites: Both WebView and ActivityInicator must be located on the same Grid object. /// /// private static void SetBusy(object sender) { if (!(sender is WebView webView)) { // Nothing to do if sender is not a web view. Log.Error($"Unexpected call of {nameof(SetBusy)} detected. Argument must not be of type {sender.GetType()}."); return; } if (!(webView.Parent is Grid grid)) { // Nothing to do if web view is not located on grid. Log.Error($"Unexpected call of {nameof(SetBusy)} detected. Parent of argument must not be of type {webView.Parent.GetType()}."); return; } grid.IsEnabled = false; var indicator = grid.Children.OfType().FirstOrDefault(); if (indicator == null) { // Nothing to do if there is not activity indicator. Log.Error($"Unexpected call of {nameof(SetBusy)} detected. No activity indicator found."); return; } indicator.IsVisible = true; indicator.IsRunning = true; } /// /// Enables WebView and hides ActivityIndicator and sets error text to WebView in case an error occurred. /// /// /// Prerequisites: Both WebView and ActivityInicator must be located on the same Grid object. /// /// HTML showing an error message. public static void SetIdleAndHandleError( object sender, WebNavigatedEventArgs eventArgs, string htmlErrorMessage) { if (!(sender is WebView webView)) { // Nothing to do if sender is not a web view. Log.Error($"Unexpected call of {nameof(SetIdleAndHandleError)} detected. Argument must not be of type {sender.GetType()}."); return; } if (!(webView.Parent is Grid grid)) { // Nothing to do if web view is not located on grid. Log.Error($"Unexpected call of {nameof(SetIdleAndHandleError)} detected. Parent of argument must not be of type {webView.Parent.GetType()}."); return; } var indicator = grid.Children.OfType().FirstOrDefault(); if (indicator == null) { // Nothing to do if there is not activity indicator. Log.Error($"Unexpected call of {nameof(SetIdleAndHandleError)} detected. No activity indicator found."); } if (eventArgs.Result == WebNavigationResult.Success) { // Uri could be loaded successfully. grid.IsEnabled = true; if (indicator != null) { indicator.IsVisible = false; indicator.IsRunning = false; } return; } // Navigation failed. Log.Error("Navigation did not succeed.{@Event}{@Sender}", eventArgs, sender); webView.Source = new HtmlWebViewSource { Html = !string.IsNullOrEmpty(htmlErrorMessage) ? htmlErrorMessage : $"Navigation to {eventArgs.Url} failed." }; grid.IsEnabled = true; if (indicator != null) { indicator.IsVisible = false; indicator.IsRunning = false; } } /// /// Sets error text to WebView in case an error occurred. /// /// HTML showing an error message. public static void HandleError( object sender, WebNavigatedEventArgs eventArgs, string htmlErrorMessage) { if (eventArgs.Result == WebNavigationResult.Success) { // Uri could be loaded successfully. return; } if (!(sender is WebView webView)) { // Nothing to do if sender is not a web view. Log.Error($"Unexpected call of {nameof(HandleError)} detected. Argument must not be of type {sender.GetType()}."); return; } // Navigation failed. Log.Error("Navigation did not succeed.{@Event}{@Sender}", eventArgs, sender); webView.Source = new HtmlWebViewSource { Html = !string.IsNullOrEmpty(htmlErrorMessage) ? htmlErrorMessage : $"Navigation to {eventArgs.Url} failed." }; } } }