Decompiled source of OnTogetherPomoSound v1.0.0

OnTogetherPomoSound.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SleepeyDev.OnTogetherPomoSound.Patches;
using SleepeyDev.OnTogetherPomoSound.Pomodoro;
using SleepeyDev.OnTogetherPomoSound.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
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("SleepeyDev")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("OnTogetherPomoSound")]
[assembly: AssemblyTitle("OnTogetherPomoSound")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 SleepeyDev.OnTogetherPomoSound
{
	public static class Conflict
	{
		private const string LocalPlaylistGuid = "com.sleepeydev.ontogether.localplaylist";

		private static readonly Version SplitVersion = new Version(0, 6, 0);

		private static bool _checked;

		private static bool _standDown;

		public static bool StandDown
		{
			get
			{
				if (_checked)
				{
					return _standDown;
				}
				_checked = true;
				_standDown = Detect();
				return _standDown;
			}
		}

		private static bool Detect()
		{
			try
			{
				if (!Chainloader.PluginInfos.TryGetValue("com.sleepeydev.ontogether.localplaylist", out var value) || value == null || value.Metadata == null)
				{
					return false;
				}
				Version version = value.Metadata.Version;
				if (version == null || version >= SplitVersion)
				{
					return false;
				}
				Plugin.Log.LogWarning((object)("On-Together Local Playlist " + version?.ToString() + " is installed and still carries the Pomodoro tick volume itself, so this mod is standing down to avoid a duplicate row and two plugins fighting over the same AudioSource."));
				Plugin.Log.LogWarning((object)("Update Local Playlist to " + SplitVersion?.ToString() + " or newer and this mod takes over. Your tick volume stays where it is either way."));
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not check for an older Local Playlist: " + ex.Message));
				return false;
			}
		}
	}
	public static class HarmonyBootstrap
	{
		private static readonly Type[] PatchClasses = new Type[1] { typeof(UiBuildPatches) };

		public static void ApplyAll()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			Harmony val = new Harmony("com.sleepeydev.ontogether.pomosound");
			int num = 0;
			Type[] patchClasses = PatchClasses;
			foreach (Type type in patchClasses)
			{
				try
				{
					val.CreateClassProcessor(type).Patch();
					num++;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Patch class " + type.Name + " failed to apply (that feature is off): " + ex.Message));
				}
			}
			Plugin.Log.LogInfo((object)("Applied " + num + "/" + PatchClasses.Length + " patch classes."));
		}
	}
	public static class ModConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<float> TickTockVolumeScale;

		public static ConfigEntry<bool> TickRowEnabled;

		public static ConfigEntry<bool> RowShrink;

		public static ConfigEntry<float> RowHeight;

		public static ConfigEntry<string> TickRowLabel;

		public static ConfigEntry<bool> VerboseLogging;

		public static ConfigEntry<bool> DumpUi;

		public static ConfigEntry<KeyCode> DumpUiKey;

		public static void Bind(ConfigFile cfg)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			Enabled = cfg.Bind<bool>("Pomodoro", "Enabled", true, "Master switch for the tick-tock volume fix.");
			TickTockVolumeScale = cfg.Bind<float>("Pomodoro", "TickTockVolumeScale", 0f, new ConfigDescription("Loudness of the Pomodoro ticking clock, as a fraction of the phase-end bell volume.\nThe game itself forces these two to be equal (SoundManager.SetPomodoroVolume), which is why\nturning the bell down also turns the ticking down. 0 = ticking silent, bell unchanged.\n1 = vanilla behaviour. The game's own per-phase tick toggles keep working either way.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			TickRowEnabled = cfg.Bind<bool>("UI", "TickRowEnabled", true, "Add a 'Tick volume' slider to the Pomodoro sound settings, under the bell volume.");
			RowShrink = cfg.Bind<bool>("UI", "RowShrink", true, "Shrink the Pomodoro sound rows so the added one fits inside the panel. The four vanilla\nrows already just overflow it, so a fifth needs the room.");
			RowHeight = cfg.Bind<float>("UI", "RowHeight", 79f, new ConfigDescription("Height of each Pomodoro sound row when RowShrink is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(40f, 110f), Array.Empty<object>()));
			TickRowLabel = cfg.Bind<string>("UI", "TickRowLabel", "Tick volume", "Caption of the added Pomodoro row.");
			VerboseLogging = cfg.Bind<bool>("Diagnostics", "VerboseLogging", false, "Log what the row build did. Noisy; for bug reports.");
			DumpUi = cfg.Bind<bool>("Diagnostics", "DumpUi", false, "Dump the Pomodoro sound settings tree to the log when it is built. Attach the log to a\nbug report if the row lands in the wrong place.");
			DumpUiKey = cfg.Bind<KeyCode>("Diagnostics", "DumpUiKey", (KeyCode)283, "Key that dumps that tree on demand. F4-F6 and F10-F11 are taken by Day and Night,\nF7-F9 by FrameCare and BlueSage, and F3 by Local Playlist, so F1-F2 are the free ones.");
		}
	}
	public sealed class ModRoot : MonoBehaviour
	{
		public static ModRoot Instance { get; private set; }

		public static void Create()
		{
			//IL_0013: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("OTPS_ModRoot")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<ModRoot>();
			}
		}

		private void Update()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				TickTockVolume.Tick();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("TickTockVolume.Tick threw, disabling: " + ex));
				TickTockVolume.Disable();
			}
			if (ModConfig.DumpUiKey != null && Input.GetKeyDown(ModConfig.DumpUiKey.Value))
			{
				UiBuilder.DumpNow();
			}
		}
	}
	[BepInPlugin("com.sleepeydev.ontogether.pomosound", "On-Together Pomodoro Sound", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.sleepeydev.ontogether.pomosound";

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				ModConfig.Bind(((BaseUnityPlugin)this).Config);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Config binding failed - some features will switch themselves off: " + ex));
			}
			ModRoot.Create();
			HarmonyBootstrap.ApplyAll();
			Log.LogInfo((object)("Pomodoro Sound " + ((BaseUnityPlugin)this).Info.Metadata.Version?.ToString() + " ready."));
			Refl.LogHealth();
		}
	}
	public static class Refl
	{
		private static readonly List<string> Missing = new List<string>();

		public static readonly FieldRef<SoundManager, AudioSource> PomodoroBell = Field<SoundManager, AudioSource>("_pomodoroBell");

		public static readonly FieldRef<SoundManager, AudioSource> PomodoroTickTock = Field<SoundManager, AudioSource>("_pomodoroTickTock");

		public static readonly FieldRef<PomodoroController, Slider> PomodoroBellVolume = Field<PomodoroController, Slider>("_pomodoroBellVolume");

		public static bool PomodoroReady
		{
			get
			{
				if (PomodoroBell != null)
				{
					return PomodoroTickTock != null;
				}
				return false;
			}
		}

		public static bool PomodoroUiReady
		{
			get
			{
				if (PomodoroReady)
				{
					return PomodoroBellVolume != null;
				}
				return false;
			}
		}

		private static FieldRef<TOwner, TField> Field<TOwner, TField>(string name)
		{
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(TOwner), name);
				if (fieldInfo == null || !typeof(TField).IsAssignableFrom(fieldInfo.FieldType))
				{
					Missing.Add(typeof(TOwner).Name + "." + name);
					return null;
				}
				return AccessTools.FieldRefAccess<TOwner, TField>(name);
			}
			catch (Exception)
			{
				Missing.Add(typeof(TOwner).Name + "." + name);
				return null;
			}
		}

		public static void LogHealth()
		{
			if (Missing.Count == 0)
			{
				Plugin.Log.LogInfo((object)"Game handles: all resolved.");
				return;
			}
			Plugin.Log.LogWarning((object)("Game handles missing (the game was probably updated): " + string.Join(", ", Missing.ToArray())));
			Plugin.Log.LogWarning((object)("Feature availability - tick volume fix: " + (PomodoroReady ? "on" : "OFF") + ", tick volume slider: " + (PomodoroUiReady ? "on" : "OFF")));
		}
	}
}
namespace SleepeyDev.OnTogetherPomoSound.UI
{
	public sealed class DragWatcher : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IPointerUpHandler
	{
		public bool IsDragging { get; private set; }

		public event Action Down;

		public event Action Up;

		public static DragWatcher Attach(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return null;
			}
			DragWatcher component = go.GetComponent<DragWatcher>();
			if (!((Object)(object)component != (Object)null))
			{
				return go.AddComponent<DragWatcher>();
			}
			return component;
		}

		public void OnPointerDown(PointerEventData eventData)
		{
			if (!IsDragging)
			{
				IsDragging = true;
				Fire(this.Down);
			}
		}

		public void OnPointerUp(PointerEventData eventData)
		{
			Release();
		}

		private void Update()
		{
			if (IsDragging && !Input.GetMouseButton(0))
			{
				Release();
			}
		}

		private void OnDisable()
		{
			if (IsDragging)
			{
				Release();
			}
		}

		private void Release()
		{
			if (IsDragging)
			{
				IsDragging = false;
				Fire(this.Up);
			}
		}

		private void Fire(Action a)
		{
			if (a == null)
			{
				return;
			}
			try
			{
				a();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("DragWatcher handler threw: " + ex));
			}
		}
	}
	public static class GameUi
	{
		public const string Prefix = "OTPS_";

		public static Transform Existing(Transform parent, string name)
		{
			if (!((Object)(object)parent == (Object)null))
			{
				return parent.Find(name);
			}
			return null;
		}

		public static GameObject CloneObject(GameObject donor, Transform parent, string name)
		{
			if ((Object)(object)donor == (Object)null || (Object)(object)parent == (Object)null)
			{
				return null;
			}
			GameObject obj = Object.Instantiate<GameObject>(donor, parent, false);
			((Object)obj).name = name;
			StripLocalizers(obj);
			obj.SetActive(true);
			return obj;
		}

		public static void ClearListeners<T>(UnityEvent<T> evt)
		{
			if (evt != null)
			{
				for (int num = ((UnityEventBase)evt).GetPersistentEventCount() - 1; num >= 0; num--)
				{
					((UnityEventBase)evt).SetPersistentListenerState(num, (UnityEventCallState)0);
				}
				((UnityEventBase)evt).RemoveAllListeners();
			}
		}

		public static void ClearListeners(UnityEvent evt)
		{
			if (evt != null)
			{
				for (int num = ((UnityEventBase)evt).GetPersistentEventCount() - 1; num >= 0; num--)
				{
					((UnityEventBase)evt).SetPersistentListenerState(num, (UnityEventCallState)0);
				}
				((UnityEventBase)evt).RemoveAllListeners();
			}
		}

		public static int StripScripts(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return 0;
			}
			Assembly assembly = typeof(SoundManager).Assembly;
			int num = 0;
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Type type = ((object)val).GetType();
					bool flag = type.Name.IndexOf("Localize", StringComparison.Ordinal) >= 0;
					bool flag2 = type.Assembly == assembly;
					if (flag || flag2)
					{
						Object.Destroy((Object)(object)val);
						num++;
					}
				}
			}
			return num;
		}

		public static int StripLocalizers(GameObject root)
		{
			return StripScripts(root);
		}

		public static void Place(RectTransform rt, Vector2 anchoredPos, Vector2 sizeDelta)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rt == (Object)null)
			{
				return;
			}
			LayoutGroup val = (((Object)(object)((Transform)rt).parent == (Object)null) ? null : ((Component)((Transform)rt).parent).GetComponent<LayoutGroup>());
			if ((Object)(object)val == (Object)null)
			{
				rt.anchoredPosition = anchoredPos;
				rt.sizeDelta = sizeDelta;
				return;
			}
			HorizontalOrVerticalLayoutGroup val2 = (HorizontalOrVerticalLayoutGroup)(object)((val is HorizontalOrVerticalLayoutGroup) ? val : null);
			if ((Object)(object)val2 != (Object)null && val2.childControlHeight)
			{
				LayoutElement val3 = ((Component)rt).GetComponent<LayoutElement>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = ((Component)rt).gameObject.AddComponent<LayoutElement>();
				}
				val3.preferredHeight = sizeDelta.y;
			}
			else
			{
				rt.sizeDelta = new Vector2(rt.sizeDelta.x, sizeDelta.y);
			}
		}

		public static void DropFocus()
		{
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
		}

		public static void DumpHierarchy(Transform root, string title, int maxDepth = 6)
		{
			if ((Object)(object)root == (Object)null)
			{
				Plugin.Log.LogInfo((object)("[dump] " + title + ": <null>"));
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("[dump] ").Append(title).Append('\n');
			Describe(root, stringBuilder, 0, maxDepth);
			Plugin.Log.LogInfo((object)stringBuilder.ToString());
		}

		private static void Describe(Transform t, StringBuilder sb, int depth, int maxDepth)
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)t == (Object)null || depth > maxDepth)
			{
				return;
			}
			sb.Append(' ', depth * 2).Append(((Object)t).name);
			sb.Append("  [").Append(((Component)t).gameObject.activeSelf ? "on" : "off").Append(", sib ")
				.Append(t.GetSiblingIndex())
				.Append(']');
			Component[] components = ((Component)t).GetComponents<Component>();
			sb.Append("  {");
			for (int i = 0; i < components.Length; i++)
			{
				if (i > 0)
				{
					sb.Append(", ");
				}
				sb.Append(((Object)(object)components[i] == (Object)null) ? "<missing>" : ((object)components[i]).GetType().Name);
			}
			sb.Append('}');
			RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null);
			if (val != null)
			{
				sb.Append("  aMin").Append(V(val.anchorMin)).Append(" aMax")
					.Append(V(val.anchorMax))
					.Append(" piv")
					.Append(V(val.pivot))
					.Append(" pos")
					.Append(V(val.anchoredPosition))
					.Append(" size")
					.Append(V(val.sizeDelta))
					.Append(" scale")
					.Append(V(((Transform)val).localScale));
			}
			LayoutGroup val2 = (((Object)(object)t.parent == (Object)null) ? null : ((Component)t.parent).GetComponent<LayoutGroup>());
			if ((Object)(object)val2 != (Object)null)
			{
				sb.Append("  [LAYOUT-DRIVEN by ").Append(((object)val2).GetType().Name).Append(']');
			}
			LayoutGroup component = ((Component)t).GetComponent<LayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				sb.Append("  ").Append(DescribeLayout(component));
			}
			Selectable component2 = ((Component)t).GetComponent<Selectable>();
			Slider val3 = (Slider)(object)((component2 is Slider) ? component2 : null);
			if (val3 != null)
			{
				sb.Append("  slider(persistent=").Append(((UnityEventBase)val3.onValueChanged).GetPersistentEventCount()).Append(')');
			}
			else
			{
				Button val4 = (Button)(object)((component2 is Button) ? component2 : null);
				if (val4 != null)
				{
					sb.Append("  button(persistent=").Append(((UnityEventBase)val4.onClick).GetPersistentEventCount()).Append(')');
				}
			}
			TMP_Text component3 = ((Component)t).GetComponent<TMP_Text>();
			if ((Object)(object)component3 != (Object)null)
			{
				string text = component3.text ?? "";
				if (text.Length > 40)
				{
					text = text.Substring(0, 40) + "...";
				}
				sb.Append("  text=\"").Append(text).Append('"');
			}
			sb.Append('\n');
			for (int j = 0; j < t.childCount; j++)
			{
				Describe(t.GetChild(j), sb, depth + 1, maxDepth);
			}
		}

		public static string DescribeLayout(LayoutGroup g)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)g == (Object)null)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(((object)g).GetType().Name).Append("(pad ").Append(g.padding.left)
				.Append(',')
				.Append(g.padding.right)
				.Append(',')
				.Append(g.padding.top)
				.Append(',')
				.Append(g.padding.bottom)
				.Append(" align=")
				.Append(g.childAlignment);
			HorizontalOrVerticalLayoutGroup val = (HorizontalOrVerticalLayoutGroup)(object)((g is HorizontalOrVerticalLayoutGroup) ? g : null);
			if (val != null)
			{
				stringBuilder.Append(" spacing=").Append(val.spacing).Append(" ctrlW=")
					.Append(val.childControlWidth)
					.Append(" ctrlH=")
					.Append(val.childControlHeight)
					.Append(" expW=")
					.Append(val.childForceExpandWidth)
					.Append(" expH=")
					.Append(val.childForceExpandHeight)
					.Append(" reverse=")
					.Append(val.reverseArrangement);
			}
			return stringBuilder.Append(')').ToString();
		}

		private static string V(Vector2 v)
		{
			return "(" + v.x.ToString("0.##") + "," + v.y.ToString("0.##") + ")";
		}

		private static string V(Vector3 v)
		{
			return "(" + v.x.ToString("0.##") + "," + v.y.ToString("0.##") + ")";
		}
	}
	public sealed class StaticText : MonoBehaviour
	{
		private TMP_Text _label;

		public string Text;

		public static StaticText Apply(TMP_Text label, string text)
		{
			if ((Object)(object)label == (Object)null)
			{
				return null;
			}
			StaticText staticText = ((Component)label).gameObject.GetComponent<StaticText>();
			if ((Object)(object)staticText == (Object)null)
			{
				staticText = ((Component)label).gameObject.AddComponent<StaticText>();
			}
			staticText._label = label;
			staticText.Text = text;
			label.text = text;
			return staticText;
		}

		private void OnEnable()
		{
			if ((Object)(object)_label != (Object)null && Text != null)
			{
				_label.text = Text;
			}
		}
	}
	public static class TickVolumeRow
	{
		private const string RowName = "OTPS_TickVolumeRow";

		private static bool _failed;

		public static void Build(PomodoroController pc)
		{
			if (_failed || Conflict.StandDown || !ModConfig.TickRowEnabled.Value)
			{
				return;
			}
			if (!Refl.PomodoroUiReady)
			{
				Plugin.Log.LogWarning((object)"Tick volume row: game handles missing, skipping. The ticking volume still follows Pomodoro/TickTockVolumeScale.");
				_failed = true;
				return;
			}
			Slider val = Refl.PomodoroBellVolume.Invoke(pc);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Tick volume row: no bell-volume slider on this PomodoroController.");
				return;
			}
			Transform parent = ((Component)val).transform.parent;
			Transform val2 = (((Object)(object)parent != (Object)null) ? parent.parent : null);
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Tick volume row: the bell slider is not two levels inside a settings group.");
			}
			else
			{
				if ((Object)(object)GameUi.Existing(val2, "OTPS_TickVolumeRow") != (Object)null)
				{
					return;
				}
				GameObject val3 = GameUi.CloneObject(((Component)parent).gameObject, val2, "OTPS_TickVolumeRow");
				if ((Object)(object)val3 == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Tick volume row: cloning the bell row failed.");
					return;
				}
				val3.transform.SetSiblingIndex(parent.GetSiblingIndex() + 1);
				Slider componentInChildren = val3.GetComponentInChildren<Slider>(true);
				if ((Object)(object)componentInChildren == (Object)null)
				{
					Object.Destroy((Object)(object)val3);
					Plugin.Log.LogWarning((object)"Tick volume row: the cloned row has no slider.");
					return;
				}
				GameUi.ClearListeners<float>((UnityEvent<float>)(object)componentInChildren.onValueChanged);
				componentInChildren.minValue = 0f;
				componentInChildren.maxValue = 1f;
				componentInChildren.wholeNumbers = false;
				componentInChildren.SetValueWithoutNotify(TickTockVolume.Scale);
				((UnityEvent<float>)(object)componentInChildren.onValueChanged).AddListener((UnityAction<float>)TickTockVolume.SetLive);
				DragWatcher.Attach(((Component)componentInChildren).gameObject).Up += GameUi.DropFocus;
				TMP_Text val4 = FindLabel(val3.transform, ((Component)componentInChildren).transform);
				if ((Object)(object)val4 != (Object)null)
				{
					StaticText.Apply(val4, ModConfig.TickRowLabel.Value);
				}
				else
				{
					Plugin.Log.LogWarning((object)"Tick volume row: no label found in the clone; the row is unlabelled.");
				}
				ShrinkRows(val2);
				Plugin.Log.LogInfo((object)("Tick volume row added at sibling " + val3.transform.GetSiblingIndex() + " under " + ((Object)val2).name + " " + GameUi.DescribeLayout(((Component)val2).GetComponent<LayoutGroup>())));
			}
		}

		private static TMP_Text FindLabel(Transform row, Transform slider)
		{
			TMP_Text[] componentsInChildren = ((Component)row).GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !val.transform.IsChildOf(slider))
				{
					return val;
				}
			}
			return null;
		}

		private static void ShrinkRows(Transform group)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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)
			if (!ModConfig.RowShrink.Value)
			{
				return;
			}
			float num = Mathf.Max(20f, ModConfig.RowHeight.Value);
			int num2 = 0;
			for (int i = 0; i < group.childCount; i++)
			{
				Transform child = group.GetChild(i);
				RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null);
				if (val != null && ((Component)val).gameObject.activeSelf)
				{
					GameUi.Place(val, val.anchoredPosition, new Vector2(val.sizeDelta.x, num));
					num2++;
				}
			}
			if (ModConfig.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Tick volume row: shrank " + num2 + " row(s) to " + num + " px."));
			}
		}

		public static void Reset()
		{
			_failed = false;
		}
	}
	public static class UiBuilder
	{
		private static PomodoroController _pomodoro;

		public static void BuildPomodoroUi(PomodoroController pc)
		{
			if (!((Object)(object)pc == (Object)null))
			{
				_pomodoro = pc;
				try
				{
					TickVolumeRow.Build(pc);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Tick volume row build failed: " + ex));
				}
				if (ModConfig.DumpUi.Value)
				{
					Dump();
				}
			}
		}

		public static void DumpNow()
		{
			Dump();
		}

		private static void Dump()
		{
			try
			{
				if (!((Object)(object)_pomodoro == (Object)null) && Refl.PomodoroBellVolume != null)
				{
					Slider val = Refl.PomodoroBellVolume.Invoke(_pomodoro);
					GameUi.DumpHierarchy(((Object)(object)val != (Object)null && (Object)(object)((Component)val).transform.parent != (Object)null) ? ((Component)val).transform.parent.parent : null, "pomodoro sound settings (Group_Sounds)");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("UI dump failed: " + ex));
			}
		}
	}
}
namespace SleepeyDev.OnTogetherPomoSound.Pomodoro
{
	public static class TickTockVolume
	{
		private const float CommitDelay = 0.6f;

		private static bool _disabled;

		private static bool _wasApplying;

		private static bool _loggedOnce;

		private static AudioSource _bell;

		private static AudioSource _tick;

		private static float _nextResolveTime;

		private static bool _hasLive;

		private static float _live;

		private static float _commitAt;

		public static float Scale => Mathf.Clamp01(_hasLive ? _live : ModConfig.TickTockVolumeScale.Value);

		public static void Disable()
		{
			_disabled = true;
		}

		public static void SetLive(float scale)
		{
			_live = Mathf.Clamp01(scale);
			_hasLive = true;
			_commitAt = Time.unscaledTime + 0.6f;
		}

		public static void Tick()
		{
			if (_disabled || Conflict.StandDown || !Refl.PomodoroReady)
			{
				return;
			}
			CommitIfDue();
			bool value = ModConfig.Enabled.Value;
			if (!Resolve())
			{
				return;
			}
			if (!value)
			{
				if (_wasApplying)
				{
					_tick.volume = _bell.volume;
					_wasApplying = false;
				}
				return;
			}
			float num = _bell.volume * Scale;
			if (!Mathf.Approximately(_tick.volume, num))
			{
				_tick.volume = num;
			}
			if (!_wasApplying)
			{
				_wasApplying = true;
				if (!_loggedOnce)
				{
					_loggedOnce = true;
					Plugin.Log.LogInfo((object)("Pomodoro tick-tock volume decoupled from the bell (scale " + Scale.ToString("0.00") + ")."));
				}
			}
		}

		private static void CommitIfDue()
		{
			if (_hasLive && !(_commitAt <= 0f) && !(Time.unscaledTime < _commitAt))
			{
				_commitAt = 0f;
				if (!Mathf.Approximately(ModConfig.TickTockVolumeScale.Value, _live))
				{
					ModConfig.TickTockVolumeScale.Value = _live;
					Plugin.Log.LogInfo((object)("Tick volume saved: " + _live.ToString("0.00")));
				}
			}
		}

		private static bool Resolve()
		{
			if ((Object)(object)_bell != (Object)null && (Object)(object)_tick != (Object)null)
			{
				return true;
			}
			if (Time.unscaledTime < _nextResolveTime)
			{
				return false;
			}
			_nextResolveTime = Time.unscaledTime + 1f;
			SoundManager i = MonoSingleton<SoundManager>.I;
			if ((Object)(object)i == (Object)null)
			{
				return false;
			}
			_bell = Refl.PomodoroBell.Invoke(i);
			_tick = Refl.PomodoroTickTock.Invoke(i);
			if ((Object)(object)_bell != (Object)null)
			{
				return (Object)(object)_tick != (Object)null;
			}
			return false;
		}
	}
}
namespace SleepeyDev.OnTogetherPomoSound.Patches
{
	[HarmonyPatch]
	public static class UiBuildPatches
	{
		[HarmonyPatch(typeof(PomodoroController), "Start")]
		[HarmonyPostfix]
		private static void PomodoroController_Start_Postfix(PomodoroController __instance)
		{
			try
			{
				UiBuilder.BuildPomodoroUi(__instance);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("BuildPomodoroUi: " + ex));
			}
		}
	}
}