using CefSharp;
using CefSharp.WinForms;
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using TradeIdeas.Logging;
namespace TradeIdeas.TIProGUI
{
public partial class ContactSupportForm : Form, ISaveLayout
{
private ChromiumWebBrowser _webBrowser;
private ContactSupportJsInterops _contactSupportJsInterops = new ContactSupportJsInterops();
public WindowIconCache WindowIconCache => new WindowIconCache("CONTACT_SUPPORT_FORM");
public bool Pinned { get; set; } = false;
public ContactSupportForm()
{
InitializeComponent();
// Initialize the browser.
InitializeChromium();
Controls.Add(_webBrowser);
LoadContactSupportTemplate();
}
///
/// Initialize the Chromium browser.
///
private void InitializeChromium()
{
try
{
Debug.WriteLine("InitializeChromium called Contact Support");
_webBrowser = BrowserManager.RequestChromiumWebBrowser("https://trade-ideas.com/");
_webBrowser.Dock = DockStyle.Fill;
_webBrowser.IsBrowserInitializedChanged += _webBrowser_IsBrowserInitializedChanged;
_webBrowser.JavascriptObjectRepository.Settings.LegacyBindingEnabled = true; // Set to allow Javascript bridging.
_webBrowser.JavascriptObjectRepository.Register("contactSupportObj", _contactSupportJsInterops, true, BindingOptions.DefaultBinder); // Javascript class.
/* Execute a script right after the html template load
* 1. Initializes the beacon
* 2. Add event listeners to these beacon's actions: close, ready
* Close for closing the Contact Support Window after the beacon's closure
* Ready for applying css customizations to the beacon for UI adjustments
* 3. Open the beacon automatically */
_webBrowser.ExecuteScriptAsyncWhenPageLoaded("!function(e,t,n){function a(){var e=t.getElementsByTagName(\"script\")[0],n=t.createElement(\"script\");n.type=\"text/javascript\",n.async=!0,n.src=\"https://beacon-v2.helpscout.net\",e.parentNode.insertBefore(n,e)}if(e.Beacon=n=function(t,n,a){e.Beacon.readyQueue.push({method:t,options:n,data:a})},n.readyQueue=[],\"complete\"===t.readyState)return a();e.attachEvent?e.attachEvent(\"onload\",a):e.addEventListener(\"load\",a,!1)}(window,document,window.Beacon||function(){});\r\n Beacon('init', '008b82bf-3f85-4ec6-ab4b-21b71ed257aa');Beacon('on', 'close', () => contactSupportObj.closeBeacon());Beacon('on', 'ready', () => {document.querySelector('.hsds-beacon .bQymmx.is-mobile').style.inset = '0px 0px 0px'; document.querySelector('.hsds-beacon .bQymmx.is-mobile').style.height = '100%';});Beacon('open');\r\n");
//Subscribe to the beacon's closing event in order to replicate that action over this parent window
_contactSupportJsInterops.OnBeaconClosed += OnBeaconClosed;
}
catch (Exception e)
{
string debugView = e.ToString();
TILogger.Error(e.Message, e);
}
}
///
/// Set the chromium browser to load the beacon in mobile mode.
/// This ensures a better responsive experience that fully adapts to the Contact Support
/// window host.
///
private void _webBrowser_IsBrowserInitializedChanged(object sender, EventArgs e)
{
if (_webBrowser.IsBrowserInitialized)
{
var client = _webBrowser.GetDevToolsClient();
client.Emulation.SetUserAgentOverrideAsync("Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36");
}
}
///
/// Load the html template for the Contact Support Beacon
///
private void LoadContactSupportTemplate()
{
if (null != _webBrowser && !_webBrowser.IsDisposed)
{
string curDir = new Uri(Directory.GetCurrentDirectory()).ToString();
_webBrowser.Load($"{curDir}/Resources/ContactSupportPage.html");
}
}
///
/// Dispose the resources used by the Chromium Webbrowser before
/// closing the Contact Support window.
///
private void ContactSupport_FormClosing(object sender, FormClosingEventArgs e)
{
if (null != _webBrowser && _webBrowser.IsBrowserInitialized && !_webBrowser.IsDisposed)
{
// Catch exception: Browser is not yet initialized.
try
{
Hide();
_webBrowser.Stop();
SuspendLayout();
_webBrowser.IsBrowserInitializedChanged -= _webBrowser_IsBrowserInitializedChanged;
_contactSupportJsInterops.OnBeaconClosed -= OnBeaconClosed;
if (Controls.Contains(_webBrowser))
Controls.Remove(_webBrowser);
ResumeLayout(false);
BrowserManager.RequestBrowserDisposal(_webBrowser);
}
catch (Exception ex)
{
string debugView = ex.ToString();
TILogger.Error(ex.Message, ex);
}
}
}
///
/// Close the Contact Support window when the beacon is closed
///
private void OnBeaconClosed()
{
this.BeginInvokeIfRequired(delegate
{
Close();
});
}
/* In order to declare this form as an unpinned window,
* the ISaveLayout has to be inherited and the presence
* of the SaveLayout method is mandatory */
public void SaveLayout(XmlNode parent)
{
throw new NotImplementedException();
}
public delegate void ChartJavaScriptBridgeOnBeaconClosedHandler();
public delegate void ChartJavaScriptBridgeOnBeaconReadyHandler();
///
/// This class handles the calls from the html template and the beacon
/// to the Contact Support windows form.
///
public class ContactSupportJsInterops
{
public event ChartJavaScriptBridgeOnBeaconClosedHandler OnBeaconClosed;
public void closeBeacon()
{
OnBeaconClosed?.Invoke();
}
}
}
}