Skip to content
Snippets Groups Projects
WebViewController.cs 5.46 KiB
Newer Older
  • Learn to ignore specific revisions
  • using bessw.Unity.WebView;
    using bessw.Unity.WebView.ChromeDevTools;
    using bessw.Unity.WebView.ChromeDevTools.Protocol.DOM;
    using MoreLinq;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    using UnityEngine.Events;
    
    public class WebViewController : MonoBehaviour
    {
    
    
        // TODO: onFactAssignment event shoud hav a dropzone id and a fact id as parameters
        public UnityEvent<DomNodeWrapper, string> onFactAssignment;
        // TODO: implement onHintRequested event
        public UnityEvent<DomNodeWrapper, string> onHintRequested;
        // TODO: click events (option for custom buttons for a scroll)
        public UnityEvent<DomNodeWrapper, string> onClick;
        private WebViewComponent webViewComponent;
        private DomNodeWrapper[] dropzones;
    
        private void Awake()
        {
            webViewComponent = GetComponent<WebViewComponent>();
            WebViewComponent.serializerSettings.Converters.Add(new FactObjectUIConverter());
    
            // TODO: handle webViewComponent.onDomDocumentUpdated
    
            // TODO: remove this debug code
            onFactAssignment.AddListener((DomNodeWrapper node, string factId) => {
                Debug.LogWarning($"onFactAssignment: '{string.Join(", ", GetFactAssignments())}'");
            });
        }
    
        /// <summary>
        /// sets or updates the content of the scroll container dom element
        /// </summary>
        /// <param name="scrollHTML"></param>
        public async void SetScrollContent(string scrollHTML)
        {
            // update scroll container content
            DomNodeWrapper scrollContainer = await DomNodeWrapper.requestNodeAsync(webViewComponent.tab, "scrollContainer");
            await scrollContainer.setNodeValueAsync(scrollHTML);
    
            // get the dropzones from the scroll and add the event handler to track when something is dropped
            dropzones = await scrollContainer.querySelectorAllAsync("[dropzone='copy']");
            dropzones.ForEach(dropzone => dropzone.OnAttributeModified += DropzoneAttributeModifiedHandler);
        }
    
        private void DropzoneAttributeModifiedHandler(attributeModifiedEvent attributeModifiedEvent)
        {
            Debug.LogWarning($"dropzoneAtrributeModifiedHandler: '{attributeModifiedEvent.name}'");
    
            // call the onFactAssignment event if the data-fact-id attribute was modified
            if (attributeModifiedEvent.name == "data-fact-id")
            {
                var node = webViewComponent.tab.domNodes.GetValueOrDefault(attributeModifiedEvent.nodeId);
                onFactAssignment.Invoke(node, attributeModifiedEvent.value);
            }
        }
    
        public string[] GetFactAssignments()
        {
            return dropzones.Select(dropzone => dropzone.Node.attributes.GetValueOrDefault("data-fact-id", null)).ToArray();
        }
    
        private async void GetDropzoneStateAsync()
        {
            // alternative way to get the dropzone state
            DomNodeWrapper document = await DomNodeWrapper.getDocumentAsync(webViewComponent.tab);
            Debug.LogWarning($"dropzone 1: '{document}'");
            var dropzones = await document.querySelectorAllAsync("[dropzone='copy']");
    
            Debug.LogWarning($"dropzone 2: '{dropzones.Index().Aggregate("", (currentString, dropzone) => $"{currentString}, {dropzone.Key}: {dropzone.Value.Node.attributes.GetValueOrDefault("data-fact-id")}")}'");
    
            string[] factIDs = new string[dropzones.Length];
    
            // get attributes for each dropzone
            //for (int i = 0; i < dropzones.Length; i++)
            //{
            //    factIDs[i] = ( await dropzones[i].getAttributesAsync() ).GetValueOrDefault("data-fact-id", null);
            //}
            //Debug.LogWarning($"dropzone 3: '{string.Join(", ", factIDs)}'");
        }
    
    
        /// <summary>
        /// First try to get the dropzone state using coroutines.
        /// Doesn't work because coroutines can't access method local temporary variables.
        /// </summary>
        /// <returns></returns>
        [Obsolete("Use getDropzoneStateAsync instead")]
        private IEnumerator GetDropzoneState()
        {
            Debug.LogWarning($"dropzone pre");
    
            DomNodeWrapper doc = null;
            yield return DomNodeWrapper.getDocument(webViewComponent.tab, (document) => {
                Debug.LogWarning($"dropzone 1: '{document}'");
                doc = document;
    
                StartCoroutine(document.querySelectorAll("[dropzone='copy']", (dropzones) => {
                    foreach (var dropzone in dropzones)
                    {
                        Debug.LogWarning($"dropzone 2: Node is Null?: '{dropzone.Node == null}'");
                        StartCoroutine(dropzone.getAttributes((attributes) =>
                        {
                            Debug.LogWarning($"dropzone 3 getAttributes: '{string.Join(", ", attributes.Values)}'");
                        }));
                    }
                }));
            });
            Debug.LogWarning($"dropzone post: '{doc}'");
        }
    }
    
    public class FactObjectUIConverter : JsonConverter<FactObjectUI>
    {
        public override void WriteJson(JsonWriter writer, FactObjectUI value, JsonSerializer serializer)
        {
            //serializer.Serialize(writer, value.Fact);
            JObject o = JObject.FromObject(value.Fact, WebViewComponent.serializer);
            o.AddFirst(new JProperty("id", value.Fact.Id));
    
            o.WriteTo(writer);
        }
        public override FactObjectUI ReadJson(JsonReader reader, Type objectType, FactObjectUI existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            var factObject = new FactObjectUI();
            factObject.Fact = serializer.Deserialize<Fact>(reader);
            return factObject;
        }
    }