diff --git a/src/ElectronNET.API/Bridge/BridgeConnector.cs b/src/ElectronNET.API/Bridge/BridgeConnector.cs new file mode 100644 index 0000000..3c06b43 --- /dev/null +++ b/src/ElectronNET.API/Bridge/BridgeConnector.cs @@ -0,0 +1,15 @@ +#pragma warning disable IDE0130 // Namespace does not match folder structure +// ReSharper disable once CheckNamespace +namespace ElectronNET.API +{ + internal static class BridgeConnector + { + public static SocketIoFacade Socket + { + get + { + return ElectronNetRuntime.GetSocket(); + } + } + } +} \ No newline at end of file diff --git a/src/ElectronNET.API/Bridge/Events.cs b/src/ElectronNET.API/Bridge/Events.cs new file mode 100644 index 0000000..732819a --- /dev/null +++ b/src/ElectronNET.API/Bridge/Events.cs @@ -0,0 +1,101 @@ +#pragma warning disable IDE0130 // Namespace does not match folder structure +// ReSharper disable once CheckNamespace +namespace ElectronNET.API +{ + using System; + using System.Globalization; + using System.Threading.Tasks; + + /// + /// Generic Event Consumers for Electron Modules + /// + internal class Events + { + private static Events _events; + private static readonly object SyncRoot = new(); + private readonly TextInfo _textInfo = new CultureInfo("en-US", false).TextInfo; + + private Events() + { } + + public static Events Instance + { + get + { + if (_events == null) + { + lock (SyncRoot) + { + if (_events == null) + { + _events = new Events(); + } + } + } + + return _events; + } + } + + /// + /// Subscribe to an unmapped electron event. + /// + /// The name of the module, e.g. app, dock, etc... + /// The name of the event + /// The event handler + public async Task On(string moduleName, string eventName, Action action) + { + var listener = $"{moduleName}{_textInfo.ToTitleCase(eventName)}Completed"; + var subscriber = $"register-{moduleName}-on-event"; + + BridgeConnector.Socket.On(listener, action); + await BridgeConnector.Socket.Emit(subscriber, eventName, listener).ConfigureAwait(false); + } + + + /// + /// Subscribe to an unmapped electron event. + /// + /// The name of the module, e.g. app, dock, etc... + /// The name of the event + /// The event handler + public async Task On(string moduleName, string eventName, Action action) + { + var listener = $"{moduleName}{_textInfo.ToTitleCase(eventName)}Completed"; + var subscriber = $"register-{moduleName}-on-event"; + + BridgeConnector.Socket.On(listener, action); + await BridgeConnector.Socket.Emit(subscriber, eventName, listener).ConfigureAwait(false); + } + + /// + /// Subscribe to an unmapped electron event. + /// + /// The name of the module, e.g. app, dock, etc... + /// The name of the event + /// The event handler + public async Task Once(string moduleName, string eventName, Action action) + { + var listener = $"{moduleName}{_textInfo.ToTitleCase(eventName)}Completed"; + var subscriber = $"register-{moduleName}-once-event"; + BridgeConnector.Socket.Once(listener, action); + await BridgeConnector.Socket.Emit(subscriber, eventName, listener).ConfigureAwait(false); + } + + + /// + /// Subscribe to an unmapped electron event. + /// + /// The name of the module, e.g. app, dock, etc... + /// The name of the event + /// The event handler + public async Task Once(string moduleName, string eventName, Action action) + { + var listener = $"{moduleName}{_textInfo.ToTitleCase(eventName)}Completed"; + var subscriber = $"register-{moduleName}-once-event"; + BridgeConnector.Socket.Once(listener, action); + await BridgeConnector.Socket.Emit(subscriber, eventName, listener).ConfigureAwait(false); + } + + } +} diff --git a/src/ElectronNET.API/Bridge/SocketIOFacade.cs b/src/ElectronNET.API/Bridge/SocketIOFacade.cs new file mode 100644 index 0000000..c3815d6 --- /dev/null +++ b/src/ElectronNET.API/Bridge/SocketIOFacade.cs @@ -0,0 +1,115 @@ +#pragma warning disable IDE0130 // Namespace does not match folder structure +// ReSharper disable once CheckNamespace +namespace ElectronNET.API; + +using System; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using SocketIO.Serializer.NewtonsoftJson; +using SocketIO = SocketIOClient.SocketIO; + +internal class SocketIoFacade +{ + private readonly SocketIO _socket; + + public SocketIoFacade(string uri) + { + _socket = new SocketIO(uri); + var jsonSerializer = new NewtonsoftJsonSerializer(new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + }); + + _socket.Serializer = jsonSerializer; + } + + public event EventHandler BridgeDisconnected; + + public event EventHandler BridgeConnected; + + public void Connect() + { + _socket.OnError += (sender, e) => + { + Console.WriteLine($"BridgeConnector Error: {sender} {e}"); + }; + + _socket.OnConnected += (_, _) => + { + Console.WriteLine("BridgeConnector connected!"); + this.BridgeConnected?.Invoke(this, EventArgs.Empty); + }; + + _socket.OnDisconnected += (_, _) => + { + Console.WriteLine("BridgeConnector disconnected!"); + this.BridgeDisconnected?.Invoke(this, EventArgs.Empty); + }; + + _socket.ConnectAsync().GetAwaiter().GetResult(); + } + + public void On(string eventName, Action action) + { + _socket.On(eventName, _ => + { + Task.Run(action); + }); + } + + public void On(string eventName, Action action) + { + _socket.On(eventName, response => + { + var value = response.GetValue(); + Task.Run(() => action(value)); + }); + } + + // TODO: Remove this method when SocketIoClient supports object deserialization + public void On(string eventName, Action action) + { + _socket.On(eventName, response => + { + var value = response.GetValue(); + ////Console.WriteLine($"Called Event {eventName} - data {value}"); + Task.Run(() => action(value)); + }); + } + + public void Once(string eventName, Action action) + { + _socket.On(eventName, _ => + { + _socket.Off(eventName); + Task.Run(action); + }); + } + + public void Once(string eventName, Action action) + { + _socket.On(eventName, (socketIoResponse) => + { + _socket.Off(eventName); + Task.Run(() => action(socketIoResponse.GetValue())); + }); + } + + public void Off(string eventName) + { + _socket.Off(eventName); + } + + public async Task Emit(string eventName, params object[] args) + { + await _socket.EmitAsync(eventName, args).ConfigureAwait(false); + } + + public void DisposeSocket() + { + _socket.Dispose(); + } +} \ No newline at end of file diff --git a/src/ElectronNET.API/Converter/ModifierTypeListConverter.cs b/src/ElectronNET.API/Converter/ModifierTypeListConverter.cs index e4b4446..5d1daed 100644 --- a/src/ElectronNET.API/Converter/ModifierTypeListConverter.cs +++ b/src/ElectronNET.API/Converter/ModifierTypeListConverter.cs @@ -1,12 +1,12 @@ -using System; +namespace ElectronNET.Converter; + +using System; using System.Collections.Generic; using System.Linq; using ElectronNET.API.Entities; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace ElectronNET.API.Converter; - /// /// ///