Skip to content

Commit

Permalink
Custom events
Browse files Browse the repository at this point in the history
  • Loading branch information
artemiusgreat committed Feb 11, 2024
1 parent 9901116 commit d9dfa5a
Show file tree
Hide file tree
Showing 35 changed files with 95 additions and 1,420 deletions.
7 changes: 7 additions & 0 deletions Libs/MessageEnum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ScriptContainer
{
public enum MessageEnum : byte
{
Size = 0
}
}
2 changes: 1 addition & 1 deletion Libs/ScriptContainer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<PropertyGroup>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>1.2.0</Version>
<Version>1.2.1</Version>
<Authors>artemiusgreat</Authors>
<Copyright>indemos.com</Copyright>
<PackageProjectUrl>http://indemos.com</PackageProjectUrl>
Expand Down
77 changes: 35 additions & 42 deletions Libs/ScriptControl.razor.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
function ScriptModule(instance, options) {

this.events = [];
this.sizeObservers = [];
const sizeObserverName = "Size";

this.eventMap = {};
this.observerMap = {};
this.serviceInstance = instance;

/// <summary>
Expand All @@ -25,80 +27,71 @@ function ScriptModule(instance, options) {
/// Subscribe to custom event
/// </summary>
/// <param name="element"></param>
/// <param name="event"></param>
/// <param name="action"></param>
this.subscribe = (element, event, action) => {
/// <param name="eventName"></param>
/// <param name="actionName"></param>
this.subscribe = (element, eventName, actionName) => {
let scheduler = null;
let index = this.sizeObservers.length;
let change = e => {
let done = e => {
clearTimeout(scheduler);
scheduler = setTimeout(() => {
this.serviceInstance && this
.serviceInstance
.invokeMethodAsync(action, e, index, event)
.catch(o => this.unsubscribe());
.invokeMethodAsync("OnChange", e, actionName)
.catch(o => this.unsubscribe(actionName));
}, options.interval || 100);
};
element.addEventListener(event, change, false);
this.events.push({ element, event, change });
return this.events.length - 1;
element.addEventListener(eventName, done, false);
this.eventMap[actionName] = { element, eventName, done };
return actionName;
};

/// <summary>
/// Unsubscribe from custom event
/// </summary>
/// <param name="index"></param>
this.unsubscribe = index => {
this.events.forEach((o, i) => {
if (this.events[index] || i === index) {
o.element.removeEventListener(o.event, o.change);
this.events[i] = null;
}
});
this.events = this.events.filter(o => o);
/// <param name="actionName"></param>
this.unsubscribe = actionName => {
const o = this.eventMap[actionName];
o && o.element.removeEventListener(o.event, o.done);
this.eventMap[actionName] = null;
};

/// <summary>
/// Subscribe to element resize
/// </summary>
/// <param name="element"></param>
/// <param name="action"></param>
this.subscribeToSize = (element, action) => {
/// <param name="actionName"></param>
this.subscribeToSize = (element, actionName) => {
let scheduler = null;
let index = this.sizeObservers.length;
let change = e => {
let done = e => {
clearTimeout(scheduler);
scheduler = setTimeout(() => {
this.serviceInstance && this
.serviceInstance
.invokeMethodAsync(action, e, index, "resize")
.catch(o => this.unsubscribeFromSize());
.invokeMethodAsync("OnChange", e, actionName)
.catch(o => this.unsubscribeFromSize(actionName));
}, options.interval || 100);
};
this.sizeObservers.push(new ResizeObserver(change).observe(element));
return this.sizeObservers.length - 1;
this.observerMap[actionName] = new ResizeObserver(done);
this.observerMap[actionName].observe(element);
return actionName;
};

/// <summary>
/// Unsubscribe from size observer
/// </summary>
/// <param name="index"></param>
this.unsubscribeFromSize = index => {
this.sizeObservers.forEach((o, i) => {
if (this.sizeObservers[index] || i === index) {
this.sizeObservers[i].disconnect();
this.sizeObservers[i] = null;
}
});
this.sizeObservers = this.sizeObservers.filter(o => o);
/// <param name="actionName"></param>
this.unsubscribeFromSize = actionName => {
const o = this.observerMap[actionName];
o && o.disconnect();
this.observerMap[actionName] = null;
};

try {
this.unsubscribeFromSize();
this.subscribeToSize(document.body, "OnChangeAction");
this.unsubscribeFromSize(sizeObserverName);
this.subscribeToSize(document.body, sizeObserverName);
} catch (e) {
this.unsubscribe();
this.subscribe(window, "resize", "OnChangeAction");
this.unsubscribe(sizeObserverName);
this.subscribe(window, "resize", sizeObserverName);
}
};

Expand Down
63 changes: 47 additions & 16 deletions Libs/ScriptService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using static System.Collections.Specialized.BitVector32;

namespace ScriptContainer
{
Expand Down Expand Up @@ -34,15 +32,15 @@ public class ScriptService : IAsyncDisposable
private DotNetObjectReference<ScriptService> _serviceInstance;

/// <summary>
/// Constructor
/// On size event
/// </summary>
/// <param name="runtime"></param>
public ScriptService(IJSRuntime runtime) => _runtime = runtime;
public Dictionary<string, Action<dynamic>> Actions { get; set; } = new();

/// <summary>
/// On size event
/// Constructor
/// </summary>
public Action<dynamic, int, string> OnChange { get; set; } = (o, i, action) => { };
/// <param name="runtime"></param>
public ScriptService(IJSRuntime runtime) => _runtime = runtime;

/// <summary>
/// Get document bounds
Expand Down Expand Up @@ -73,19 +71,50 @@ public class ScriptService : IAsyncDisposable
return null;
}

/// <summary>
/// Subscribe to custom events
/// </summary>
/// <param name="element"></param>
/// <param name="eventName"></param>
/// <param name="actionName"></param>
/// <returns></returns>
public async Task<string> Subscribe(ElementReference element, string eventName, string actionName)
{
if (_scriptInstance is not null)
{
return await _scriptInstance.InvokeAsync<string>("subscribe", element, eventName, actionName);
}

return null;
}

/// <summary>
/// Subscribe to size changes
/// </summary>
/// <param name="element"></param>
/// <param name="actionName"></param>
/// <returns></returns>
public async Task<string> SubscribeToSize(ElementReference element, string actionName)
{
if (_scriptInstance is not null)
{
return await _scriptInstance.InvokeAsync<string>("subscribeToSize", element, actionName);
}

return null;
}

/// <summary>
/// Setup script proxy under specified namespace
/// </summary>
/// <returns></returns>
public async Task<ScriptService> CreateModule(IDictionary<string, object> options = null)
public async Task<ScriptService> CreateModule(IDictionary<string, dynamic> options = null)
{
await DisposeAsync();

options ??= new Dictionary<string, object>();

_serviceInstance = DotNetObjectReference.Create(this);
_scriptModule = await _runtime.InvokeAsync<IJSObjectReference>("import", "./_content/ScriptContainer/ScriptControl.razor.js");
_scriptInstance = await _scriptModule.InvokeAsync<IJSObjectReference>("getScriptModule", _serviceInstance, options);
_scriptInstance = await _scriptModule.InvokeAsync<IJSObjectReference>("getScriptModule", _serviceInstance, options ?? new Dictionary<string, object>());

return this;
}
Expand All @@ -94,20 +123,22 @@ public async Task<ScriptService> CreateModule(IDictionary<string, object> option
/// Script proxy
/// </summary>
/// <param name="message"></param>
/// <param name="index"></param>
/// <param name="action"></param>
/// <param name="actionName"></param>
/// <returns></returns>
[JSInvokable]
public void OnChangeAction(dynamic message, int index, string action) => OnChange(message, index, action);
public void OnChange(dynamic message, string actionName)
{
if (Actions.TryGetValue(actionName, out var action)) {
action(message);
}
}

/// <summary>
/// Dispose
/// </summary>
/// <returns></returns>
public async ValueTask DisposeAsync()
{
OnChange = (o, i, action) => { };

if (_scriptInstance is not null)
{
await _scriptInstance.DisposeAsync();
Expand Down
12 changes: 0 additions & 12 deletions Samples/SampleClient/App.razor

This file was deleted.

18 changes: 0 additions & 18 deletions Samples/SampleClient/Pages/Counter.razor

This file was deleted.

57 changes: 0 additions & 57 deletions Samples/SampleClient/Pages/FetchData.razor

This file was deleted.

Loading

0 comments on commit d9dfa5a

Please sign in to comment.