Decompiled source of Notiffy v0.1.2

plugins\Notiffy\Notiffy.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Notiffy.API;
using Notiffy.Server;
using Notiffy.UI;
using Notiffy.Utils;
using PluginConfig.API;
using PluginConfig.API.Decorators;
using PluginConfig.API.Fields;
using PluginConfig.API.Functionals;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Notiffy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e0f1dd749ee9c692d8d02ea3f983c327d473dccb")]
[assembly: AssemblyProduct("Notiffy")]
[assembly: AssemblyTitle("Notiffy")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Notiffy
{
	public enum PauseMenuButtonTypeEnum
	{
		MenuConfiggyAligned,
		MenuRight,
		Corner,
		None
	}
	public class ConfigManager
	{
		public static PluginConfigurator? config;

		public static readonly FloatField DefaultTimeout;

		public static readonly IntField MaxHistory;

		public static readonly BoolField UseModifierKey;

		public static readonly KeyCodeField ModifierKey;

		public static readonly KeyCodeField NotificationPanelKey;

		public static readonly EnumField<PauseMenuButtonTypeEnum> PauseMenuButtonType;

		public static readonly BoolField ShowDebugOptions;

		public static readonly BoolField FirstRun;

		public static readonly ButtonField SendTestNotificationButton;

		public static readonly ButtonField SendUrgentNotificationButton;

		public static readonly BoolField Silent;

		private static readonly List<uint> ActiveNotifIds;

		public static void Initialize()
		{
		}

		private static void UpdateDebugOptionsVisibility()
		{
			bool value = ShowDebugOptions.value;
			((ConfigField)SendTestNotificationButton).hidden = !value;
			((ConfigField)SendUrgentNotificationButton).hidden = !value;
			((ConfigField)FirstRun).hidden = !value;
		}

		public static string GetFormattedPanelKeybind()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			string text = "";
			KeyCode value;
			if (UseModifierKey.value)
			{
				string text2 = text;
				value = ModifierKey.value;
				text = text2 + "<color=#ff8000>" + ((object)(KeyCode)(ref value)).ToString() + "</color>+";
			}
			string text3 = text;
			value = NotificationPanelKey.value;
			return text3 + "<color=#ff8000>" + ((object)(KeyCode)(ref value)).ToString() + "</color>";
		}

		static ConfigManager()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Expected O, but got Unknown
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Expected O, but got Unknown
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Expected O, but got Unknown
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Expected O, but got Unknown
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Expected O, but got Unknown
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Expected O, but got Unknown
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Expected O, but got Unknown
			ActiveNotifIds = new List<uint>();
			config = PluginConfigurator.Create("Notiffy", "com.github.end-4.notiffy");
			string iconPath = Path.Combine(NotiffyPlugin.workingDir, "icon.png");
			if (File.Exists(iconPath))
			{
				config.SetIconWithURL(iconPath);
			}
			new ConfigHeader(config.rootPanel, "", 10);
			new ConfigHeader(config.rootPanel, "-- NOTIFICATION SYSTEM --", 24);
			UseModifierKey = new BoolField(config.rootPanel, "Use modifier key", "modifierKey", true);
			UseModifierKey.postValueChangeEvent += (PostBoolValueChangeEvent)delegate(bool newValue)
			{
				if (ModifierKey != null)
				{
					((ConfigField)ModifierKey).interactable = newValue;
				}
			};
			ModifierKey = new KeyCodeField(config.rootPanel, "Modifier key", "notificationPanelModkey", (KeyCode)308);
			ModifierKey.postValueChangeEvent += (PostKeyCodeValueChangeEvent)delegate
			{
				NotificationController.UpdateKeybindText();
			};
			((ConfigField)ModifierKey).interactable = UseModifierKey.value;
			NotificationPanelKey = new KeyCodeField(config.rootPanel, "Toggle panel keybind", "notificationPanelKey", (KeyCode)110);
			NotificationPanelKey.postValueChangeEvent += (PostKeyCodeValueChangeEvent)delegate
			{
				NotificationController.UpdateKeybindText();
			};
			DefaultTimeout = new FloatField(config.rootPanel, "Default timeout (secs)", "defaultTimeout", 6f);
			MaxHistory = new IntField(config.rootPanel, "Max history length", "maxHistory", 50);
			PauseMenuButtonType = new EnumField<PauseMenuButtonTypeEnum>(config.rootPanel, "Pause menu button type", "pauseMenuButtonType", PauseMenuButtonTypeEnum.Corner);
			PauseMenuButtonType.postValueChangeEvent += delegate
			{
				NotificationController.UpdatePopupTail();
				MenuPatcher.UpdateAppearance();
			};
			new ConfigHeader(config.rootPanel, "", 10);
			new ConfigHeader(config.rootPanel, "-- DEBUG --", 24);
			ShowDebugOptions = new BoolField(config.rootPanel, "Show debug options", "showDebugOptions", false);
			ShowDebugOptions.postValueChangeEvent += (PostBoolValueChangeEvent)delegate
			{
				UpdateDebugOptionsVisibility();
			};
			SendTestNotificationButton = new ButtonField(config.rootPanel, "Send test notification", "testNotification");
			SendTestNotificationButton.onClick += (OnClick)delegate
			{
				uint item = NotificationSystem.NotifySend("Test notification", "The quick blue V1 jumps over the red V2. Sisyphus sells sea shells by the sea shore.", null, iconPath, Urgency.Normal, "NotifySend", 0u, new Dictionary<string, string>
				{
					{ "hellYeah", "Hell yeah!" },
					{ "noThanks", "I'll pass this time..." }
				});
				ActiveNotifIds.Add(item);
			};
			SendUrgentNotificationButton = new ButtonField(config.rootPanel, "Send urgent test notification", "testNotificationUrgent");
			SendUrgentNotificationButton.onClick += (OnClick)delegate
			{
				NotificationSystem.NotifySend("Urgent notification", "This message should not disappear on its own.", null, "", Urgency.Critical);
			};
			FirstRun = new BoolField(config.rootPanel, "First run", "firstRun", true);
			UpdateDebugOptionsVisibility();
			Silent = new BoolField(config.rootPanel, "Silent", "silent", false);
			((ConfigField)Silent).hidden = true;
			NotificationSystem.ActionInvoked += OnActionInvoked;
			NotificationSystem.NotificationClosed += OnNotificationClosed;
			NotificationSystem.NotificationDeleted += OnNotificationDeleted;
		}

		private static void PrintActiveNotifIds()
		{
			NotiffyPlugin.Log.LogInfo((object)"ACTIVE NOTIFS");
			foreach (uint activeNotifId in ActiveNotifIds)
			{
				NotiffyPlugin.Log.LogInfo((object)activeNotifId);
			}
		}

		private static void OnActionInvoked(uint id, string actionIdentifier)
		{
			PrintActiveNotifIds();
			NotiffyPlugin.Log.LogInfo((object)$"Some action invoked: {id}, {actionIdentifier}; current tracked {ActiveNotifIds} -> {ActiveNotifIds.Contains(id)}");
			if (ActiveNotifIds.Contains(id))
			{
				NotificationSystem.NotifySend("Action invoked", $"ID: {id}\nAction ID: {actionIdentifier}");
				NotiffyPlugin.Log.LogInfo((object)$"INVOKED notification with ID {id}, actionIdentifier: {actionIdentifier}");
				ActiveNotifIds.Remove(id);
			}
		}

		private static void OnNotificationClosed(uint id, ClosedReason reason)
		{
			if (ActiveNotifIds.Contains(id))
			{
				NotiffyPlugin.Log.LogInfo((object)$"DISMISSED notification with ID {id}");
			}
		}

		private static void OnNotificationDeleted(uint id)
		{
			if (ActiveNotifIds.Contains(id))
			{
				ActiveNotifIds.Remove(id);
				NotiffyPlugin.Log.LogInfo((object)$"DELETED notification with ID {id}");
			}
		}
	}
	[BepInPlugin("com.github.end-4.notiffy", "Notiffy", "0.1.2")]
	public class NotiffyPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.github.end-4.notiffy";

		public const string PluginName = "Notiffy";

		public const string PluginVersion = "0.1.2";

		public static string workingPath = Assembly.GetExecutingAssembly().Location;

		public static string workingDir = Path.GetDirectoryName(workingPath);

		internal static ManualLogSource Log;

		private float previousTimeScale;

		private void Awake()
		{
			Log = Logger.CreateLogSource("Notiffy");
			Log.LogInfo((object)"Notiffy is waking up...");
			ConfigManager.Initialize();
			NotificationSystem.Initialize();
			NotificationController.Initialize();
			MenuPatcher.Initialize();
			UserHints.Initialize();
			Log.LogInfo((object)"Notiffy Initialized");
		}

		private void Update()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if ((!ConfigManager.UseModifierKey.value || Input.GetKey(ConfigManager.ModifierKey.value)) && Input.GetKeyDown(ConfigManager.NotificationPanelKey.value))
			{
				NotificationController.TogglePanel();
			}
			if (Time.timeScale * previousTimeScale > 0f || Time.timeScale + previousTimeScale == 0f)
			{
				NotificationController.UpdatePopupTail();
			}
			previousTimeScale = Time.timeScale;
		}
	}
	internal static class UserHints
	{
		private static void IssueFirstRunNoticeIfNecessary()
		{
			if (ConfigManager.FirstRun.value)
			{
				ConfigManager.FirstRun.value = false;
				NotificationSystem.NotifySend("<color=#f2ca3a>Notiffy</color>: instructions", "To open notification panel, press [" + ConfigManager.GetFormattedPanelKeybind() + "]. This can be configured in <color=#55c7f6>Options > Plugin Config > Notiffy</color>", null, Path.Combine(NotiffyPlugin.workingDir, "icon.png"), Urgency.Critical);
			}
		}

		private static void OnSceneLoaded(Scene s, LoadSceneMode m)
		{
			IssueFirstRunNoticeIfNecessary();
		}

		public static void Initialize()
		{
		}

		static UserHints()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
		}
	}
}
namespace Notiffy.Utils
{
	public static class Img2Sprite
	{
		public static Sprite LoadNewSprite(string filePath, float pixelsPerUnit = 100f, SpriteMeshType spriteType = 1)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = LoadTexture(filePath);
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0f, 0f), pixelsPerUnit, 0u, spriteType);
		}

		public static Sprite ConvertTextureToSprite(Texture2D texture, float pixelsPerUnit = 100f, SpriteMeshType spriteType = 1)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0f, 0f), pixelsPerUnit, 0u, spriteType);
		}

		public static Texture2D LoadTexture(string FilePath)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			if (File.Exists(FilePath))
			{
				byte[] array = File.ReadAllBytes(FilePath);
				Texture2D val = new Texture2D(2, 2);
				if (ImageConversion.LoadImage(val, array))
				{
					return val;
				}
			}
			return null;
		}
	}
}
namespace Notiffy.UI
{
	internal static class MenuPatcher
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__TogglePanel;
		}

		private static string PauseNotifToggleButtonName;

		private static GameObject _notifButton;

		private static GameObject? FindNestedObject(GameObject baseObject, string path, bool warnings = true)
		{
			Transform val = baseObject.transform;
			string[] array = path.Split("/");
			foreach (string text in array)
			{
				val = ((Component)val).transform.Find(text);
				if ((Object)(object)val == (Object)null)
				{
					if (warnings)
					{
						NotiffyPlugin.Log.LogWarning((object)(text + " not found for object path " + ((Object)baseObject).name + "/" + path));
					}
					return null;
				}
			}
			return ((Component)val).gameObject;
		}

		public static void Initialize()
		{
		}

		static MenuPatcher()
		{
			PauseNotifToggleButtonName = "ToggleNotificationPanel";
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			PatchPauseMenu();
		}

		public static void UpdateAppearance()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = _notifButton.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(component.sizeDelta.y, component.sizeDelta.y);
			bool flag = ConfigManager.PauseMenuButtonType.value == PauseMenuButtonTypeEnum.MenuConfiggyAligned;
			((Transform)component).localPosition = new Vector3((float)(flag ? 107 : 170), 90f, 0f);
			_notifButton.SetActive(ConfigManager.PauseMenuButtonType.value == PauseMenuButtonTypeEnum.MenuRight || ConfigManager.PauseMenuButtonType.value == PauseMenuButtonTypeEnum.MenuConfiggyAligned);
		}

		private static void PatchPauseMenu()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject baseObject = (from obj in ((Scene)(ref activeScene)).GetRootGameObjects()
				where ((Object)obj).name == "Canvas"
				select obj).FirstOrDefault();
			if (Object.op_Implicit((Object)(object)FindNestedObject(baseObject, "PauseMenu/" + PauseNotifToggleButtonName, warnings: false)))
			{
				return;
			}
			GameObject val = FindNestedObject(baseObject, "PauseMenu");
			GameObject val2 = FindNestedObject(baseObject, "PauseMenu/Resume");
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				_notifButton = Object.Instantiate<GameObject>(val2);
				_notifButton.transform.SetParent(val.transform, false);
				((Object)_notifButton).name = PauseNotifToggleButtonName;
				Button component = _notifButton.GetComponent<Button>();
				component.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick = component.onClick;
				object obj2 = <>O.<0>__TogglePanel;
				if (obj2 == null)
				{
					UnityAction val3 = NotificationController.TogglePanel;
					<>O.<0>__TogglePanel = val3;
					obj2 = (object)val3;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj2);
				GameObject val4 = FindNestedObject(_notifButton, "Text");
				if ((Object)(object)val4 != (Object)null)
				{
					Object.Destroy((Object)(object)val4);
				}
				GameObject obj3 = Object.Instantiate<GameObject>(NotificationController.Bundle.LoadAsset<GameObject>("NotiffyToggleIcon"));
				obj3.transform.SetParent(_notifButton.transform, false);
				RectTransform component2 = obj3.GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(0.33f, 0.33f);
				component2.anchorMax = new Vector2(0.67f, 0.67f);
				obj3.SetActive(true);
				UpdateAppearance();
			}
		}
	}
	internal static class NotificationController
	{
		private enum NotificationArea
		{
			Popup,
			Panel,
			Both
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__ClosePanel;

			public static UnityAction <1>__OpenPanel;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Action <>9__30_0;

			public static UnityAction <>9__30_1;

			public static UnityAction <>9__30_2;

			public static Func<GameObject, bool> <>9__32_0;

			internal void <LoadPanelFromBundle>b__30_0()
			{
				_notifPanel.SetActive(false);
			}

			internal void <LoadPanelFromBundle>b__30_1()
			{
				NotificationSystem.Server.ClearNotifications();
			}

			internal void <LoadPanelFromBundle>b__30_2()
			{
				ConfigManager.Silent.value = !ConfigManager.Silent.value;
				List<int> list = new List<int>();
				foreach (uint key in PopupNotifObjectDict.Keys)
				{
					list.Add((int)key);
				}
				foreach (int item in list)
				{
					OnNotificationClosed((uint)item);
				}
				UpdateSilentButtonFill();
			}

			internal bool <ParentStuffToCanvas>b__32_0(GameObject obj)
			{
				return ((Object)obj).name == "Canvas";
			}
		}

		private static readonly string BundlePath;

		private static GameObject? _notifPanel;

		private static GameObject? _notifPopupPanel;

		private const string PanelObjectName = "NotiffyPanel";

		private const string PopupPanelObjectName = "NotiffyPopupPanel";

		private static readonly NotificationServer Server;

		internal static readonly AssetBundle Bundle;

		private static readonly Dictionary<uint, GameObject> NotifObjectDict;

		private static readonly Dictionary<uint, GameObject> PopupNotifObjectDict;

		private static Sprite _largeBorder;

		private static Sprite _largeFill;

		static NotificationController()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			BundlePath = Path.Combine(NotiffyPlugin.workingDir, "assets", "notiffy_ui");
			Server = NotificationSystem.Server;
			NotifObjectDict = new Dictionary<uint, GameObject>();
			PopupNotifObjectDict = new Dictionary<uint, GameObject>();
			_largeBorder = Addressables.LoadAssetAsync<Sprite>((object)"Assets/Textures/UI/Controls/Round_BorderLarge.png").WaitForCompletion();
			_largeFill = Addressables.LoadAssetAsync<Sprite>((object)"Assets/Textures/UI/Controls/Round_FillLarge.png").WaitForCompletion();
			if (!((Object)(object)Bundle != (Object)null))
			{
				Bundle = AssetBundle.LoadFromFile(BundlePath);
				if ((Object)(object)Bundle == (Object)null)
				{
					NotiffyPlugin.Log.LogError((object)"Could not find asset bundle!");
				}
				SceneManager.sceneLoaded += OnSceneLoaded;
				Server.OnNotificationAdded += OnNotificationAdded;
				Server.OnNotificationUpdated += OnNotificationUpdated;
				Server.OnNotificationClosed += OnNotificationClosed;
				Server.OnNotificationDeleted += OnNotificationDeleted;
			}
		}

		public static void Initialize()
		{
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			ParentStuffToCanvas();
			UpdateSilentButtonFill();
			NotificationSystem.SignalReadyForScene();
		}

		private static void OnNotificationAdded(uint id, Notification notif)
		{
			OnNotificationAdded(id, notif, NotificationArea.Both);
		}

		private static void OnNotificationAdded(uint id, Notification notif, NotificationArea area)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			if ((Object)(object)_notifPanel != (Object)null && area != 0)
			{
				Transform val = _notifPanel.transform.Find("Scroll View/Viewport/NotiffyPanelContent");
				GameObject val2 = CreateNotificationGameObject(notif, id);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.transform.SetParent(val, false);
					NotifObjectDict.Add(id, val2);
				}
				LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)val);
			}
			if (!ConfigManager.Silent.value && (Object)(object)_notifPopupPanel != (Object)null && _notifPopupPanel.activeSelf && area != NotificationArea.Panel)
			{
				Transform transform = _notifPopupPanel.transform;
				GameObject val3 = CreateNotificationGameObject(notif, id, isPopup: true);
				if ((Object)(object)val3 != (Object)null)
				{
					val3.transform.SetParent(transform, false);
					PopupNotifObjectDict.Add(id, val3);
				}
				LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)transform);
				UpdatePopupTail();
			}
			UpdatePanelEmptyPlaceholder();
		}

		private static void OnNotificationUpdated(uint id, Notification notif)
		{
			if (NotifObjectDict.TryGetValue(id, out GameObject value))
			{
				UpdateNotificationGameObjectContent(value, notif);
			}
			if (PopupNotifObjectDict.TryGetValue(id, out GameObject value2))
			{
				UpdateNotificationGameObjectContent(value2, notif);
			}
			UpdatePanelEmptyPlaceholder();
		}

		private static void OnNotificationClosed(uint id, ClosedReason reason = ClosedReason.Expired)
		{
			if (PopupNotifObjectDict.TryGetValue(id, out GameObject value))
			{
				Object.Destroy((Object)(object)value);
				PopupNotifObjectDict.Remove(id);
				UpdatePopupTail();
			}
		}

		private static void OnNotificationDeleted(uint id)
		{
			if (NotifObjectDict.TryGetValue(id, out GameObject value))
			{
				Object.Destroy((Object)(object)value);
				NotifObjectDict.Remove(id);
			}
			if (PopupNotifObjectDict.TryGetValue(id, out GameObject value2))
			{
				Object.Destroy((Object)(object)value2);
				PopupNotifObjectDict.Remove(id);
			}
			UpdatePanelEmptyPlaceholder();
		}

		public static void UpdateKeybindText()
		{
			UpdatePanelTitle();
			UpdatePopupTail();
		}

		private static void UpdateNotificationGameObjectContent(GameObject notifObj, Notification notif)
		{
			((TMP_Text)((Component)notifObj.transform.Find("NotificationTextLayout/SummaryText")).GetComponent<TextMeshProUGUI>()).text = notif.Summary;
			((TMP_Text)((Component)notifObj.transform.Find("NotificationTextLayout/BodyText")).GetComponent<TextMeshProUGUI>()).text = notif.Body;
			if ((Object)(object)notif.NotificationIcon != (Object)null)
			{
				((Component)notifObj.transform.Find("AppIconMask/Image")).GetComponent<Image>().sprite = notif.NotificationIcon;
			}
		}

		private static GameObject? CreateNotificationGameObject(Notification notif, uint id, bool isPopup = false)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(Bundle.LoadAsset<GameObject>("NotiffyNotification"));
			((UnityEvent)((Component)val.transform.Find("CloseButton")).GetComponent<Button>().onClick).AddListener(isPopup ? ((UnityAction)delegate
			{
				NotificationSystem.Server.CloseNotification(id, ClosedReason.Dismissed);
			}) : ((UnityAction)delegate
			{
				NotificationSystem.Server.DeleteNotification(id);
			}));
			UpdateNotificationGameObjectContent(val, notif);
			Transform val2 = val.transform.Find("NotificationTextLayout/ActionLayout");
			Transform val3 = val.transform.Find("NotificationTextLayout");
			List<string> actions = notif.Actions;
			if (actions != null && actions.Count > 0)
			{
				GameObject val4 = Bundle.LoadAsset<GameObject>("NotiffyActionButton");
				for (int i = 0; i + 1 < notif.Actions.Count; i += 2)
				{
					string identifier = notif.Actions[i];
					string text = notif.Actions[i + 1];
					GameObject obj = Object.Instantiate<GameObject>(val4);
					obj.transform.SetParent(((Component)val2).transform, false);
					((TMP_Text)obj.GetComponentInChildren<TextMeshProUGUI>()).text = text;
					((UnityEvent)obj.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
					{
						NotificationSystem.Server.InvokeAction(id, identifier);
					});
				}
			}
			LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)val2).GetComponent<RectTransform>());
			LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)val3).GetComponent<RectTransform>());
			LayoutRebuilder.ForceRebuildLayoutImmediate(val.GetComponent<RectTransform>());
			val.SetActive(true);
			return val;
		}

		private static void SyncNotificationObjects()
		{
			NotifObjectDict.Clear();
			IReadOnlyList<NotificationEntry> history = NotificationSystem.Server.History;
			for (int i = 0; i < history.Count; i++)
			{
				OnNotificationAdded(history[i].Id, history[i].Data, NotificationArea.Panel);
			}
		}

		private static void SyncPopupNotificationObjects()
		{
			PopupNotifObjectDict.Clear();
			foreach (NotificationEntry activeNotification in NotificationSystem.Server.ActiveNotifications)
			{
				OnNotificationAdded(activeNotification.Id, activeNotification.Data, NotificationArea.Popup);
			}
		}

		private static void UpdateSilentButtonFill()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_notifPanel == (Object)null))
			{
				bool value = ConfigManager.Silent.value;
				Image component = ((Component)_notifPanel.transform.Find("Header/NotiffyHeaderSilent")).GetComponent<Image>();
				Image component2 = ((Component)_notifPanel.transform.Find("Header/NotiffyHeaderSilent/Image")).GetComponent<Image>();
				component.sprite = (value ? _largeFill : _largeBorder);
				((Graphic)component2).color = (value ? Color.black : Color.white);
			}
		}

		public static void UpdatePanelTitle()
		{
			if (!((Object)(object)_notifPanel == (Object)null))
			{
				string text = "NOTIFICATIONS<size=60%> [" + ConfigManager.GetFormattedPanelKeybind() + "]";
				((TMP_Text)((Component)_notifPanel.transform.Find("Header/NotiffyHeaderText")).GetComponent<TextMeshProUGUI>()).text = text;
			}
		}

		public static void UpdatePanelEmptyPlaceholder()
		{
			if (_notifPanel != null)
			{
				((Component)_notifPanel.transform.Find("Scroll View/EmptyPlaceholder")).gameObject.SetActive(NotifObjectDict.Count == 0);
			}
		}

		private static void UpdatePopupTailText()
		{
			if (_notifPopupPanel != null)
			{
				string text = ((PopupNotifObjectDict.Count > 0) ? "all notifications" : "notifications");
				string text2 = "Show " + text + "<size=80%> [" + ConfigManager.GetFormattedPanelKeybind() + "]";
				((TMP_Text)((Component)_notifPopupPanel.transform.Find("ShowAllRow/ShowAllButton/ShowAllButtonText")).GetComponent<TextMeshProUGUI>()).text = text2;
			}
		}

		public static void UpdatePopupTail()
		{
			if (_notifPopupPanel != null)
			{
				UpdatePopupTailText();
				GameObject gameObject = ((Component)_notifPopupPanel.transform.Find("ShowAllRow")).gameObject;
				bool flag = PopupNotifObjectDict.Count > 0 && PopupNotifObjectDict.Count < NotifObjectDict.Count;
				bool flag2 = ConfigManager.PauseMenuButtonType.value == PauseMenuButtonTypeEnum.Corner && Time.timeScale == 0f && (MonoSingleton<OptionsManager>.Instance?.paused ?? false);
				((LayoutGroup)gameObject.GetComponent<HorizontalLayoutGroup>()).padding.right = ((PopupNotifObjectDict.Count > 0) ? 6 : 0);
				gameObject.SetActive(flag || flag2);
			}
		}

		private static void LoadPanelFromBundle()
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			_notifPanel = Object.Instantiate<GameObject>(Bundle.LoadAsset<GameObject>("NotiffyPanel"));
			_notifPanel.SetActive(true);
			_notifPanel.SetActive(false);
			((Object)_notifPanel).name = "NotiffyPanel";
			Object.DontDestroyOnLoad((Object)(object)_notifPanel);
			SlideFadeToggleEffect slideFadeToggleEffect = _notifPanel.AddComponent<SlideFadeToggleEffect>();
			slideFadeToggleEffect.OnExitComplete += delegate
			{
				_notifPanel.SetActive(false);
			};
			slideFadeToggleEffect.hiddenOffset = new Vector2(_notifPanel.GetComponent<RectTransform>().sizeDelta.x, 0f);
			ButtonClickedEvent onClick = ((Component)_notifPanel.transform.Find("NotiffyPanelClose/CloseButton")).GetComponent<Button>().onClick;
			object obj = <>O.<0>__ClosePanel;
			if (obj == null)
			{
				UnityAction val = ClosePanel;
				<>O.<0>__ClosePanel = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			ButtonClickedEvent onClick2 = ((Component)_notifPanel.transform.Find("Header/NotiffyHeaderClear")).GetComponent<Button>().onClick;
			object obj2 = <>c.<>9__30_1;
			if (obj2 == null)
			{
				UnityAction val2 = delegate
				{
					NotificationSystem.Server.ClearNotifications();
				};
				<>c.<>9__30_1 = val2;
				obj2 = (object)val2;
			}
			((UnityEvent)onClick2).AddListener((UnityAction)obj2);
			ButtonClickedEvent onClick3 = ((Component)_notifPanel.transform.Find("Header/NotiffyHeaderSilent")).GetComponent<Button>().onClick;
			object obj3 = <>c.<>9__30_2;
			if (obj3 == null)
			{
				UnityAction val3 = delegate
				{
					ConfigManager.Silent.value = !ConfigManager.Silent.value;
					List<int> list = new List<int>();
					foreach (uint key in PopupNotifObjectDict.Keys)
					{
						list.Add((int)key);
					}
					foreach (int item in list)
					{
						OnNotificationClosed((uint)item);
					}
					UpdateSilentButtonFill();
				};
				<>c.<>9__30_2 = val3;
				obj3 = (object)val3;
			}
			((UnityEvent)onClick3).AddListener((UnityAction)obj3);
			UpdatePanelTitle();
			UpdatePanelEmptyPlaceholder();
			SyncNotificationObjects();
		}

		private static void LoadPopupPanelFromBundle()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			_notifPopupPanel = Object.Instantiate<GameObject>(Bundle.LoadAsset<GameObject>("NotiffyPopupContent"));
			_notifPopupPanel.SetActive(true);
			((Object)_notifPopupPanel).name = "NotiffyPopupPanel";
			ButtonClickedEvent onClick = ((Component)_notifPopupPanel.transform.Find("ShowAllRow/ShowAllButton")).GetComponent<Button>().onClick;
			object obj = <>O.<1>__OpenPanel;
			if (obj == null)
			{
				UnityAction val = OpenPanel;
				<>O.<1>__OpenPanel = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			Object.DontDestroyOnLoad((Object)(object)_notifPopupPanel);
			SyncPopupNotificationObjects();
			UpdatePopupTail();
		}

		private static void ParentStuffToCanvas()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_notifPanel == (Object)null)
			{
				_notifPanel = GameObject.Find("NotiffyPanel");
				_notifPopupPanel = GameObject.Find("NotiffyPopupPanel");
				if ((Object)(object)_notifPanel == (Object)null)
				{
					LoadPanelFromBundle();
				}
				if ((Object)(object)_notifPopupPanel == (Object)null)
				{
					LoadPopupPanelFromBundle();
				}
			}
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject val = (from obj in ((Scene)(ref activeScene)).GetRootGameObjects()
				where ((Object)obj).name == "Canvas"
				select obj).FirstOrDefault();
			if ((Object)(object)val != (Object)null && (Object)(object)_notifPanel != (Object)null && (Object)(object)_notifPopupPanel != (Object)null)
			{
				Transform transform = _notifPanel.transform;
				Transform transform2 = _notifPopupPanel.transform;
				transform.SetParent(val.transform, false);
				transform2.SetParent(val.transform, false);
				transform.SetAsLastSibling();
				transform2.SetAsLastSibling();
			}
		}

		public static void TogglePanel()
		{
			if (_notifPanel != null && _notifPopupPanel != null)
			{
				if (!_notifPanel.activeSelf)
				{
					_notifPanel.SetActive(true);
					_notifPopupPanel.SetActive(false);
				}
				else
				{
					_notifPanel.GetComponent<SlideFadeToggleEffect>().StartExit();
					_notifPopupPanel.SetActive(true);
				}
				if (_notifPanel.activeSelf)
				{
					NotificationSystem.Server.ClearNotifications(delete: false);
					LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)_notifPanel.transform.Find("Scroll View/Viewport/NotiffyPanelContent")).GetComponent<RectTransform>());
				}
			}
		}

		public static void OpenPanel()
		{
			if (_notifPanel != null && _notifPopupPanel != null && !_notifPanel.activeSelf)
			{
				TogglePanel();
			}
		}

		public static void ClosePanel()
		{
			if (_notifPanel != null && _notifPopupPanel != null && _notifPanel.activeSelf)
			{
				TogglePanel();
			}
		}
	}
	public class SlideFadeToggleEffect : MonoBehaviour
	{
		private enum State
		{
			Idle,
			Entering,
			Exiting
		}

		private State currentState;

		private RectTransform rect;

		private CanvasGroup? canvasGroup;

		private float originalAlpha;

		private Vector2 originalPos;

		public float hiddenAlpha;

		public float speed = 18f;

		public Vector2 hiddenOffset = Vector2.zero;

		private float currentExitSpeed;

		private Vector2 hiddenPos => originalPos + hiddenOffset;

		public event Action OnExitComplete;

		private void Initialize()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)rect == (Object)null)
			{
				rect = ((Component)this).GetComponent<RectTransform>();
			}
			if ((Object)canvasGroup == (Object)null)
			{
				canvasGroup = ((Component)this).GetComponent<CanvasGroup>();
			}
			CanvasGroup? obj = canvasGroup;
			originalAlpha = ((obj != null) ? obj.alpha : 1f);
			originalPos = rect.anchoredPosition;
		}

		private void OnEnable()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			rect.anchoredPosition = hiddenPos;
			if (canvasGroup != null)
			{
				canvasGroup.alpha = hiddenAlpha;
			}
			currentState = State.Entering;
		}

		public void StartExit()
		{
			currentState = State.Exiting;
		}

		private void Awake()
		{
			Initialize();
		}

		private void Update()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			if (currentState == State.Idle)
			{
				return;
			}
			bool num = currentState == State.Entering;
			Vector2 val = (num ? originalPos : hiddenPos);
			float num2 = (num ? originalAlpha : hiddenAlpha);
			Vector2 anchoredPosition = rect.anchoredPosition;
			CanvasGroup? obj = canvasGroup;
			float num3 = ((obj != null) ? obj.alpha : 1f);
			float num5;
			float num6;
			if (num)
			{
				float num4 = Time.unscaledDeltaTime * speed;
				num5 = (Vector2.Distance(anchoredPosition, val) + 0.1f) * num4;
				num6 = (Mathf.Abs(num2 - num3) + 0.1f) * num4;
				currentExitSpeed = 0f;
			}
			else
			{
				currentExitSpeed += speed * 7f * Time.unscaledDeltaTime;
				num5 = currentExitSpeed;
				num6 = currentExitSpeed * 0.01f;
			}
			rect.anchoredPosition = Vector2.MoveTowards(anchoredPosition, val, num5);
			if (canvasGroup != null)
			{
				canvasGroup.alpha = Mathf.MoveTowards(num3, num2, num6);
			}
			if (rect.anchoredPosition == val && (canvasGroup == null || Mathf.Approximately(canvasGroup.alpha, num2)))
			{
				State num7 = currentState;
				currentState = State.Idle;
				currentExitSpeed = 0f;
				if (num7 == State.Exiting)
				{
					this.OnExitComplete?.Invoke();
				}
			}
		}
	}
}
namespace Notiffy.Server
{
	internal class NotificationEntry
	{
		public Notification Data;

		public float StartTime;

		public uint Id;

		public NotificationEntry(Notification notification, uint id)
		{
			UpdateNotification(notification);
			Id = id;
		}

		public void UpdateNotification(Notification notification)
		{
			Data = notification;
			StartTime = Time.time;
		}

		public bool IsTimedout()
		{
			return Time.time >= StartTime + (float)Data.ExpirationTimeout;
		}
	}
	internal class NotificationServer : MonoBehaviour, INotificationServer
	{
		private ManualLogSource Log;

		private readonly Dictionary<uint, NotificationEntry> _activeNotifs;

		private uint _nextId = 1u;

		private readonly List<uint> _removalBuffer = new List<uint>();

		private readonly List<NotificationEntry> _history = new List<NotificationEntry>();

		public IReadOnlyList<NotificationEntry> History => _history;

		public IEnumerable<NotificationEntry> ActiveNotifications => _activeNotifs.Values;

		public event Action<uint, Notification>? OnNotificationAdded;

		public event Action<uint, Notification>? OnNotificationUpdated;

		public event Action<uint, ClosedReason>? OnNotificationClosed;

		public event Action<uint>? OnNotificationDeleted;

		public event Action<uint, ClosedReason>? NotificationClosed;

		public event Action<uint>? NotificationDeleted;

		public event Action<uint, string>? ActionInvoked;

		private bool NotificationIsActive(uint id)
		{
			return _activeNotifs.ContainsKey(id);
		}

		public void TrimHistory()
		{
			if (_history.Count <= ConfigManager.MaxHistory.value)
			{
				return;
			}
			_removalBuffer.Clear();
			for (int i = 0; i < _history.Count - ConfigManager.MaxHistory.value; i++)
			{
				NotificationEntry notificationEntry = _history[i];
				_removalBuffer.Add(notificationEntry.Id);
			}
			foreach (uint item in _removalBuffer)
			{
				DeleteNotification(item);
			}
		}

		private void AddToHistory(NotificationEntry notification)
		{
			_history.Add(notification);
			TrimHistory();
		}

		private void RemoveFromHistory(uint id)
		{
			int num = _history.FindIndex((NotificationEntry x) => x.Id == id);
			if (num != -1)
			{
				_history.RemoveAt(num);
			}
		}

		public void DeleteNotification(uint id, ClosedReason reason = ClosedReason.Dismissed, bool notifySenders = true)
		{
			if (NotificationIsActive(id))
			{
				CloseNotification(id, reason, notifySenders);
			}
			if (_history.FindIndex((NotificationEntry x) => x.Id == id) != -1)
			{
				RemoveFromHistory(id);
				if (notifySenders)
				{
					this.NotificationDeleted?.Invoke(id);
				}
				this.OnNotificationDeleted?.Invoke(id);
			}
		}

		public void CloseNotification(uint id, ClosedReason reason, bool notifySenders = true)
		{
			if (NotificationIsActive(id))
			{
				_activeNotifs.Remove(id);
				if (notifySenders)
				{
					this.NotificationClosed?.Invoke(id, reason);
				}
				this.OnNotificationClosed?.Invoke(id, reason);
			}
		}

		public void ClearNotifications(bool delete = true)
		{
			_removalBuffer.Clear();
			foreach (NotificationEntry item in _history)
			{
				_removalBuffer.Add(item.Id);
			}
			foreach (uint item2 in _removalBuffer)
			{
				if (delete)
				{
					DeleteNotification(item2);
				}
				else
				{
					CloseNotification(item2, ClosedReason.Dismissed);
				}
			}
		}

		public void InvokeAction(uint id, string actionIdentifier)
		{
			DeleteNotification(id, ClosedReason.Dismissed, notifySenders: false);
			this.ActionInvoked?.Invoke(id, actionIdentifier);
		}

		public uint Notify(Notification notification)
		{
			uint num;
			if (notification.ReplacesId != 0 && _activeNotifs.TryGetValue(notification.ReplacesId, out NotificationEntry value))
			{
				value.UpdateNotification(notification);
				num = notification.ReplacesId;
				this.OnNotificationUpdated?.Invoke(num, notification);
			}
			else
			{
				num = _nextId++;
				NotificationEntry notificationEntry = new NotificationEntry(notification, num);
				_activeNotifs.Add(num, notificationEntry);
				AddToHistory(notificationEntry);
				this.OnNotificationAdded?.Invoke(num, notification);
			}
			return num;
		}

		public void CloseNotification(uint id)
		{
			CloseNotification(id, ClosedReason.APIClosed);
		}

		public NotificationServer()
		{
			Log = Logger.CreateLogSource("Notiffy.Server");
			_activeNotifs = new Dictionary<uint, NotificationEntry>();
			Log.LogInfo((object)"Initialized");
		}

		private void Update()
		{
			if (_activeNotifs.Count == 0)
			{
				return;
			}
			float time = Time.time;
			_removalBuffer.Clear();
			foreach (NotificationEntry value2 in _activeNotifs.Values)
			{
				float num = ((value2.Data.ExpirationTimeout > 0) ? ((float)(value2.Data.ExpirationTimeout / 1000)) : ConfigManager.DefaultTimeout.value);
				Dictionary<string, object> hints = value2.Data.Hints;
				if (hints != null && hints.TryGetValue("urgency", out object value) && (Urgency)value == Urgency.Critical)
				{
					num = time - value2.StartTime + 1f;
				}
				if (time - value2.StartTime >= num)
				{
					_removalBuffer.Add(value2.Id);
				}
			}
			for (int i = 0; i < _removalBuffer.Count; i++)
			{
				CloseNotification(_removalBuffer[i], ClosedReason.Expired);
			}
		}
	}
}
namespace Notiffy.API
{
	public enum ClosedReason : uint
	{
		Expired = 1u,
		Dismissed,
		APIClosed,
		Undefined
	}
	public interface INotificationServer
	{
		event Action<uint, ClosedReason>? NotificationClosed;

		event Action<uint>? NotificationDeleted;

		event Action<uint, string>? ActionInvoked;

		uint Notify(Notification notification);

		void CloseNotification(uint id);
	}
	public struct Notification
	{
		public string ApplicationName;

		public uint ReplacesId;

		public Sprite NotificationIcon;

		public string Summary;

		public string Body;

		public int ExpirationTimeout;

		public Dictionary<string, object> Hints;

		public List<string> Actions;
	}
	public static class NotificationSystem
	{
		internal static NotificationServer Server;

		public static event Action<uint, ClosedReason> NotificationClosed
		{
			add
			{
				Server.NotificationClosed += value;
			}
			remove
			{
				Server.NotificationClosed -= value;
			}
		}

		public static event Action<uint> NotificationDeleted
		{
			add
			{
				Server.NotificationDeleted += value;
			}
			remove
			{
				Server.NotificationDeleted -= value;
			}
		}

		public static event Action<uint, string> ActionInvoked
		{
			add
			{
				Server.ActionInvoked += value;
			}
			remove
			{
				Server.ActionInvoked -= value;
			}
		}

		[Obsolete]
		public static event Action ReadyForScene;

		public static uint NotifySend(string summary, string body, Sprite iconSprite = null, string iconFilePath = "", Urgency urgency = Urgency.Normal, string appName = "NotifySend", uint replaceId = 0u, Dictionary<string, string> actions = null, int expireTime = -1)
		{
			Notification notification = default(Notification);
			notification.Summary = summary;
			notification.Body = body;
			Notification notification2 = notification;
			notification2.ApplicationName = appName;
			if (iconFilePath != "")
			{
				Sprite notificationIcon = Img2Sprite.LoadNewSprite(iconFilePath, 100f, (SpriteMeshType)1);
				notification2.NotificationIcon = notificationIcon;
			}
			else if ((Object)(object)iconSprite != (Object)null)
			{
				notification2.NotificationIcon = iconSprite;
			}
			notification2.ExpirationTimeout = expireTime;
			if (replaceId != 0)
			{
				notification2.ReplacesId = replaceId;
			}
			if (actions != null)
			{
				notification2.Actions = new List<string>();
				foreach (KeyValuePair<string, string> action in actions)
				{
					notification2.Actions.Add(action.Key);
					notification2.Actions.Add(action.Value);
				}
			}
			if (urgency != Urgency.Normal)
			{
				notification2.Hints = new Dictionary<string, object>();
				if (urgency != Urgency.Normal)
				{
					notification2.Hints.Add("urgency", urgency);
				}
			}
			return Notify(notification2);
		}

		public static uint Notify(Notification notification)
		{
			return Server.Notify(notification);
		}

		public static void CloseNotification(uint id)
		{
			Server.CloseNotification(id);
		}

		internal static void SignalReadyForScene()
		{
			NotificationSystem.ReadyForScene?.Invoke();
		}

		internal static void Initialize()
		{
		}

		static NotificationSystem()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			GameObject val = new GameObject("Notiffy_Server");
			Server = val.AddComponent<NotificationServer>();
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
		}
	}
	public enum Urgency : uint
	{
		Low,
		Normal,
		Critical
	}
}