diff --git a/InvisibleMan-XRay/Assets/NotifyIcons/IconDisabled.ico b/InvisibleMan-XRay/Assets/NotifyIcons/IconDisabled.ico new file mode 100644 index 0000000..5889966 Binary files /dev/null and b/InvisibleMan-XRay/Assets/NotifyIcons/IconDisabled.ico differ diff --git a/InvisibleMan-XRay/Assets/NotifyIcons/IconEnabled.ico b/InvisibleMan-XRay/Assets/NotifyIcons/IconEnabled.ico new file mode 100644 index 0000000..39026d8 Binary files /dev/null and b/InvisibleMan-XRay/Assets/NotifyIcons/IconEnabled.ico differ diff --git a/InvisibleMan-XRay/Core/InvisibleManXRayCore.cs b/InvisibleMan-XRay/Core/InvisibleManXRayCore.cs index 9976c02..ec9519b 100644 --- a/InvisibleMan-XRay/Core/InvisibleManXRayCore.cs +++ b/InvisibleMan-XRay/Core/InvisibleManXRayCore.cs @@ -1,4 +1,5 @@ using System; +using InvisibleManXRay.Handlers; namespace InvisibleManXRay.Core { @@ -27,6 +28,7 @@ public class InvisibleManXRayCore private Func getProxy; private Func getTunnel; private Action onFailLoadingConfig; + private CoreEnabledOrDisabledModeObserver coreEnabledOrDisabledModeObserver; private LocalizationService LocalizationService => ServiceLocator.Get(); private AnalyticsService AnalyticsService => ServiceLocator.Get(); @@ -46,7 +48,8 @@ public void Setup( Func getDns, Func getProxy, Func getTunnel, - Action onFailLoadingConfig) + Action onFailLoadingConfig, + CoreEnabledOrDisabledModeObserver coreEnabledOrDisabledModeObserver) { this.getConfig = getConfig; this.getMode = getMode; @@ -63,6 +66,7 @@ public void Setup( this.getProxy = getProxy; this.getTunnel = getTunnel; this.onFailLoadingConfig = onFailLoadingConfig; + this.coreEnabledOrDisabledModeObserver = coreEnabledOrDisabledModeObserver; } public Status LoadConfig() @@ -95,17 +99,26 @@ public Status LoadConfig(string path) public Status EnableMode() { Mode mode = getMode.Invoke(); - + + Status status; if (mode == Mode.PROXY) - return EnableProxy(); + status = EnableProxy(); else - return EnableTunnel(); + status = EnableTunnel(); + + if (status.Code == Code.SUCCESS) + { + coreEnabledOrDisabledModeObserver.Notify(ProxyEnabledOrDisabledState.ENABLED); + } + + return status; } public void DisableMode() { DisableProxy(); DisableTunnel(); + coreEnabledOrDisabledModeObserver.Notify(ProxyEnabledOrDisabledState.DISABLED); } public void Run(string config) @@ -139,6 +152,7 @@ public void Cancel() { CancelProxy(); CancelTunnel(); + coreEnabledOrDisabledModeObserver.Notify(ProxyEnabledOrDisabledState.DISABLED); } public int Test(string config) diff --git a/InvisibleMan-XRay/Handlers/CoreEnabledOrDisabledModeObserver.cs b/InvisibleMan-XRay/Handlers/CoreEnabledOrDisabledModeObserver.cs new file mode 100644 index 0000000..74418dd --- /dev/null +++ b/InvisibleMan-XRay/Handlers/CoreEnabledOrDisabledModeObserver.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace InvisibleManXRay.Handlers; + +public enum ProxyEnabledOrDisabledState +{ + ENABLED, + DISABLED +} + +public class CoreEnabledOrDisabledModeObserver : Handler +{ + private readonly List> listeners = new(); + + public void Subscribe(Action listener) + { + listeners.Add(listener); + } + + public void Unsubscribe(Action listener) + { + listeners.Remove(listener); + } + + public void Notify(ProxyEnabledOrDisabledState state) + { + foreach (var listener in listeners) + { + listener(state); + } + } +} \ No newline at end of file diff --git a/InvisibleMan-XRay/Handlers/NotifyHandler.cs b/InvisibleMan-XRay/Handlers/NotifyHandler.cs index 1455587..1e2ea1e 100644 --- a/InvisibleMan-XRay/Handlers/NotifyHandler.cs +++ b/InvisibleMan-XRay/Handlers/NotifyHandler.cs @@ -3,6 +3,7 @@ using System.Drawing; using System.Windows.Forms; using System.Collections.Generic; +using System.Reflection; namespace InvisibleManXRay.Handlers { @@ -13,7 +14,7 @@ namespace InvisibleManXRay.Handlers public class NotifyHandler : Handler { - private NotifyIcon notifyIcon; + private NotifyIcon? notifyIcon; private Func getMode; private Action onOpenClick; @@ -35,7 +36,8 @@ public void Setup( Action onAboutClick, Action onCloseClick, Action onProxyModeClick, - Action onTunnelModeClick + Action onTunnelModeClick, + CoreEnabledOrDisabledModeObserver coreEnabledOrDisabledModeObserver ) { this.getMode = getMode; @@ -45,6 +47,7 @@ Action onTunnelModeClick this.onCloseClick = onCloseClick; this.onProxyModeClick = onProxyModeClick; this.onTunnelModeClick = onTunnelModeClick; + coreEnabledOrDisabledModeObserver.Subscribe(HandleProxyEnabledOrDisabled); } public void CheckModeItem(Mode mode) @@ -60,20 +63,35 @@ public void InitializeNotifyIcon() notifyIcon.Dispose(); notifyIcon = new NotifyIcon(); - notifyIcon.Icon = GetNotifyIcon(); + notifyIcon.Icon = GetNotifyIconFromResources(forEnabled: false); notifyIcon.Visible = true; HandleNotifyIconClick(); AddMenuStrip(); bool IsNotifyIconAlreadyExists() => notifyIcon != null; + } - Icon GetNotifyIcon() - { - return Icon.ExtractAssociatedIcon( - System.Environment.GetCommandLineArgs().First() - ); - } + public void HandleProxyEnabledOrDisabled(ProxyEnabledOrDisabledState state) + { + if (notifyIcon is null) + return; + + var icon = GetNotifyIconFromResources(forEnabled: state == ProxyEnabledOrDisabledState.ENABLED); + notifyIcon.Icon = icon; + } + + private Icon GetNotifyIconFromResources(bool forEnabled) + { + const string rootNamespace = "InvisibleManXRay"; + const string basePath = $"Assets.NotifyIcons"; + var fileName = forEnabled ? "IconEnabled.ico" : "IconDisabled.ico"; + var resourceName = $"{rootNamespace}.{basePath}.{fileName}"; + + var assembly = Assembly.GetExecutingAssembly(); + using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new InvalidOperationException("Something went wrong with resources or with assembly or with root namespace"); + var icon = new Icon(stream); + return icon; } private void HandleNotifyIconClick() diff --git a/InvisibleMan-XRay/InvisibleMan-XRay.csproj b/InvisibleMan-XRay/InvisibleMan-XRay.csproj index b6a1fbf..6c26b59 100644 --- a/InvisibleMan-XRay/InvisibleMan-XRay.csproj +++ b/InvisibleMan-XRay/InvisibleMan-XRay.csproj @@ -41,4 +41,10 @@ + + + + + + diff --git a/InvisibleMan-XRay/Managers/Initializers/CoreInitializer.cs b/InvisibleMan-XRay/Managers/Initializers/CoreInitializer.cs index 2a4be85..76d86de 100644 --- a/InvisibleMan-XRay/Managers/Initializers/CoreInitializer.cs +++ b/InvisibleMan-XRay/Managers/Initializers/CoreInitializer.cs @@ -34,7 +34,8 @@ public void Setup(HandlersManager handlersManager) getDns: settingsHandler.UserSettings.GetDns, getProxy: proxyHandler.GetProxy, getTunnel: tunnelHandler.GetTunnel, - onFailLoadingConfig: configHandler.RemoveConfigFromList + onFailLoadingConfig: configHandler.RemoveConfigFromList, + coreEnabledOrDisabledModeObserver: handlersManager.GetHandler() ); } } diff --git a/InvisibleMan-XRay/Managers/Initializers/HandlersInitializer.cs b/InvisibleMan-XRay/Managers/Initializers/HandlersInitializer.cs index e1ba684..2407ae0 100644 --- a/InvisibleMan-XRay/Managers/Initializers/HandlersInitializer.cs +++ b/InvisibleMan-XRay/Managers/Initializers/HandlersInitializer.cs @@ -29,6 +29,7 @@ public void Register() HandlersManager.AddHandler(new DeepLinkHandler()); HandlersManager.AddHandler(new LinkHandler()); HandlersManager.AddHandler(new LocalizationHandler()); + HandlersManager.AddHandler(new CoreEnabledOrDisabledModeObserver()); } public void Setup( @@ -96,7 +97,8 @@ void SetupNotifyHandler() onAboutClick: OpenAboutWindow, onCloseClick: CloseApplication, onProxyModeClick: () => { OnModeClick(Mode.PROXY); }, - onTunnelModeClick: () => { OnModeClick(Mode.TUN); } + onTunnelModeClick: () => { OnModeClick(Mode.TUN); }, + coreEnabledOrDisabledModeObserver: HandlersManager.GetHandler() ); void CloseApplication()