2020-05-03 17:22:33 +08:00
|
|
|
|
using System;
|
2020-08-26 11:13:36 +08:00
|
|
|
|
using System.Collections.Concurrent;
|
2019-12-16 18:48:03 +08:00
|
|
|
|
using System.Collections.Generic;
|
2020-08-26 11:13:36 +08:00
|
|
|
|
using System.Linq;
|
2020-04-22 19:37:06 +08:00
|
|
|
|
using System.Text.Json;
|
2021-04-27 14:03:39 +08:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using AntDesign.Core.Extensions;
|
|
|
|
|
using AntDesign.Core.JsInterop.ObservableApi;
|
|
|
|
|
using Microsoft.AspNetCore.Components;
|
2019-12-16 18:48:03 +08:00
|
|
|
|
using Microsoft.JSInterop;
|
|
|
|
|
|
2020-05-29 00:33:49 +08:00
|
|
|
|
namespace AntDesign.JsInterop
|
2019-12-16 18:48:03 +08:00
|
|
|
|
{
|
|
|
|
|
public class DomEventService
|
|
|
|
|
{
|
2020-08-26 11:13:36 +08:00
|
|
|
|
private ConcurrentDictionary<string, List<DomEventSubscription>> _domEventListeners = new ConcurrentDictionary<string, List<DomEventSubscription>>();
|
2019-12-16 18:48:03 +08:00
|
|
|
|
|
|
|
|
|
private readonly IJSRuntime _jsRuntime;
|
2021-04-27 14:03:39 +08:00
|
|
|
|
private bool? _isResizeObserverSupported = null;
|
2019-12-16 18:48:03 +08:00
|
|
|
|
|
|
|
|
|
public DomEventService(IJSRuntime jsRuntime)
|
|
|
|
|
{
|
|
|
|
|
_jsRuntime = jsRuntime;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-21 17:20:10 +08:00
|
|
|
|
private void AddEventListenerToFirstChildInternal<T>(object dom, string eventName, bool preventDefault, Action<T> callback)
|
2020-05-03 17:22:33 +08:00
|
|
|
|
{
|
2020-08-26 11:13:36 +08:00
|
|
|
|
if (!_domEventListeners.ContainsKey(FormatKey(dom, eventName)))
|
2020-05-03 17:22:33 +08:00
|
|
|
|
{
|
2021-01-21 17:20:10 +08:00
|
|
|
|
_jsRuntime.InvokeAsync<string>(JSInteropConstants.AddDomEventListenerToFirstChild, dom, eventName, preventDefault, DotNetObjectReference.Create(new Invoker<T>((p) =>
|
2020-05-03 17:22:33 +08:00
|
|
|
|
{
|
|
|
|
|
callback?.Invoke(p);
|
|
|
|
|
})));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-21 17:20:10 +08:00
|
|
|
|
public void AddEventListener(object dom, string eventName, Action<JsonElement> callback, bool exclusive = true, bool preventDefault = false)
|
2020-04-22 19:37:06 +08:00
|
|
|
|
{
|
2021-01-21 17:20:10 +08:00
|
|
|
|
AddEventListener<JsonElement>(dom, eventName, callback, exclusive, preventDefault);
|
2020-04-22 19:37:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-09 21:54:30 +08:00
|
|
|
|
public virtual void AddEventListener<T>(object dom, string eventName, Action<T> callback, bool exclusive = true, bool preventDefault = false)
|
2020-04-22 19:37:06 +08:00
|
|
|
|
{
|
2020-08-26 11:13:36 +08:00
|
|
|
|
if (exclusive)
|
2020-04-22 19:37:06 +08:00
|
|
|
|
{
|
2021-01-21 17:20:10 +08:00
|
|
|
|
_jsRuntime.InvokeAsync<string>(JSInteropConstants.AddDomEventListener, dom, eventName, preventDefault, DotNetObjectReference.Create(new Invoker<T>((p) =>
|
2020-08-26 11:13:36 +08:00
|
|
|
|
{
|
|
|
|
|
callback(p);
|
|
|
|
|
})));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string key = FormatKey(dom, eventName);
|
|
|
|
|
if (!_domEventListeners.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
_domEventListeners[key] = new List<DomEventSubscription>();
|
|
|
|
|
|
2021-01-21 17:20:10 +08:00
|
|
|
|
_jsRuntime.InvokeAsync<string>(JSInteropConstants.AddDomEventListener, dom, eventName, preventDefault, DotNetObjectReference.Create(new Invoker<string>((p) =>
|
2020-08-26 11:13:36 +08:00
|
|
|
|
{
|
2020-12-29 23:35:03 +08:00
|
|
|
|
for (var i = 0; i < _domEventListeners[key].Count; i++)
|
2020-08-26 11:13:36 +08:00
|
|
|
|
{
|
2020-12-29 23:35:03 +08:00
|
|
|
|
var subscription = _domEventListeners[key][i];
|
2020-09-28 16:44:11 +08:00
|
|
|
|
object tP = JsonSerializer.Deserialize(p, subscription.Type);
|
|
|
|
|
subscription.Delegate.DynamicInvoke(tP);
|
2020-08-26 11:13:36 +08:00
|
|
|
|
}
|
|
|
|
|
})));
|
|
|
|
|
}
|
2020-09-28 16:44:11 +08:00
|
|
|
|
_domEventListeners[key].Add(new DomEventSubscription(callback, typeof(T)));
|
2020-08-26 11:13:36 +08:00
|
|
|
|
}
|
2020-04-22 19:37:06 +08:00
|
|
|
|
}
|
2020-05-03 17:22:33 +08:00
|
|
|
|
|
2021-01-21 17:20:10 +08:00
|
|
|
|
public void AddEventListenerToFirstChild(object dom, string eventName, Action<JsonElement> callback, bool preventDefault = false)
|
2020-05-03 17:22:33 +08:00
|
|
|
|
{
|
2021-01-21 17:20:10 +08:00
|
|
|
|
AddEventListenerToFirstChildInternal<string>(dom, eventName, preventDefault, (e) =>
|
2020-05-03 17:22:33 +08:00
|
|
|
|
{
|
|
|
|
|
JsonElement jsonElement = JsonDocument.Parse(e).RootElement;
|
|
|
|
|
callback(jsonElement);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-21 17:20:10 +08:00
|
|
|
|
public void AddEventListenerToFirstChild<T>(object dom, string eventName, Action<T> callback, bool preventDefault = false)
|
2020-05-03 17:22:33 +08:00
|
|
|
|
{
|
2021-01-21 17:20:10 +08:00
|
|
|
|
AddEventListenerToFirstChildInternal<string>(dom, eventName, preventDefault, (e) =>
|
2020-05-03 17:22:33 +08:00
|
|
|
|
{
|
|
|
|
|
T obj = JsonSerializer.Deserialize<T>(e);
|
|
|
|
|
callback(obj);
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-08-26 11:13:36 +08:00
|
|
|
|
|
2021-04-27 14:03:39 +08:00
|
|
|
|
public async ValueTask AddResizeObserver(ElementReference dom, Action<List<ResizeObserverEntry>> callback)
|
|
|
|
|
{
|
|
|
|
|
string key = FormatKey(dom.Id, nameof(JSInteropConstants.ObserverConstants.Resize));
|
|
|
|
|
if (!(await IsResizeObserverSupported()))
|
|
|
|
|
{
|
|
|
|
|
Action<JsonElement> action = (je) => callback.Invoke(new List<ResizeObserverEntry> { new ResizeObserverEntry() });
|
|
|
|
|
AddEventListener("window", "resize", action, false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!_domEventListeners.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
_domEventListeners[key] = new List<DomEventSubscription>();
|
|
|
|
|
await _jsRuntime.InvokeVoidAsync(JSInteropConstants.ObserverConstants.Resize.Create, key, DotNetObjectReference.Create(new Invoker<string>((p) =>
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < _domEventListeners[key].Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var subscription = _domEventListeners[key][i];
|
|
|
|
|
object tP = JsonSerializer.Deserialize(p, subscription.Type);
|
|
|
|
|
subscription.Delegate.DynamicInvoke(tP);
|
|
|
|
|
}
|
|
|
|
|
})));
|
|
|
|
|
await _jsRuntime.InvokeVoidAsync(JSInteropConstants.ObserverConstants.Resize.Observe, key, dom);
|
|
|
|
|
}
|
|
|
|
|
_domEventListeners[key].Add(new DomEventSubscription(callback, typeof(List<ResizeObserverEntry>)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async ValueTask RemoveResizeObserver(ElementReference dom, Action<List<ResizeObserverEntry>> callback)
|
|
|
|
|
{
|
|
|
|
|
string key = FormatKey(dom.Id, nameof(JSInteropConstants.ObserverConstants.Resize));
|
|
|
|
|
if (_domEventListeners.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
var subscription = _domEventListeners[key].SingleOrDefault(s => s.Delegate == (Delegate)callback);
|
|
|
|
|
if (subscription != null)
|
|
|
|
|
{
|
|
|
|
|
_domEventListeners[key].Remove(subscription);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async ValueTask DisposeResizeObserver(ElementReference dom)
|
|
|
|
|
{
|
|
|
|
|
string key = FormatKey(dom.Id, nameof(JSInteropConstants.ObserverConstants.Resize));
|
|
|
|
|
if (await IsResizeObserverSupported())
|
|
|
|
|
{
|
|
|
|
|
await _jsRuntime.InvokeVoidAsync(JSInteropConstants.ObserverConstants.Resize.Dispose, key);
|
|
|
|
|
}
|
|
|
|
|
_domEventListeners.TryRemove(key, out _);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async ValueTask DisconnectResizeObserver(ElementReference dom)
|
|
|
|
|
{
|
|
|
|
|
string key = FormatKey(dom.Id, nameof(JSInteropConstants.ObserverConstants.Resize));
|
|
|
|
|
if (await IsResizeObserverSupported())
|
|
|
|
|
{
|
|
|
|
|
await _jsRuntime.InvokeVoidAsync(JSInteropConstants.ObserverConstants.Resize.Disconnect, key);
|
|
|
|
|
}
|
|
|
|
|
if (_domEventListeners.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
_domEventListeners[key].Clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-26 11:13:36 +08:00
|
|
|
|
private static string FormatKey(object dom, string eventName) => $"{dom}-{eventName}";
|
|
|
|
|
|
|
|
|
|
public void RemoveEventListerner<T>(object dom, string eventName, Action<T> callback)
|
|
|
|
|
{
|
|
|
|
|
string key = FormatKey(dom, eventName);
|
|
|
|
|
if (_domEventListeners.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
var subscription = _domEventListeners[key].SingleOrDefault(s => s.Delegate == (Delegate)callback);
|
|
|
|
|
if (subscription != null)
|
|
|
|
|
{
|
|
|
|
|
_domEventListeners[key].Remove(subscription);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-04-27 14:03:39 +08:00
|
|
|
|
|
|
|
|
|
private async ValueTask<bool> IsResizeObserverSupported() => _isResizeObserverSupported ??= await _jsRuntime.IsResizeObserverSupported();
|
2019-12-16 18:48:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-11 16:40:07 +08:00
|
|
|
|
public class Invoker<T>
|
2019-12-16 18:48:03 +08:00
|
|
|
|
{
|
2020-04-23 17:13:56 +08:00
|
|
|
|
private Action<T> _action;
|
2019-12-16 18:48:03 +08:00
|
|
|
|
|
2020-03-11 16:40:07 +08:00
|
|
|
|
public Invoker(Action<T> invoker)
|
2019-12-16 18:48:03 +08:00
|
|
|
|
{
|
2020-04-23 17:13:56 +08:00
|
|
|
|
this._action = invoker;
|
2019-12-16 18:48:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JSInvokable]
|
2020-03-11 16:40:07 +08:00
|
|
|
|
public void Invoke(T param)
|
2019-12-16 18:48:03 +08:00
|
|
|
|
{
|
2020-04-23 17:13:56 +08:00
|
|
|
|
_action.Invoke(param);
|
2019-12-16 18:48:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-23 17:13:56 +08:00
|
|
|
|
}
|