Decompiled source of SmileOsViewer v1.0.0

smileosviewer/SmileOsViewer.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SmileOsViewer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SmileOsViewer")]
[assembly: AssemblyTitle("SmileOsViewer")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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;
		}
	}
}
namespace SmileosRecordingViewer
{
	[BepInPlugin("com.smileo.recordingviewer", "Smileos Recording Viewer", "1.0.0")]
	public class MainPlugin : BaseUnityPlugin
	{
		public static ManualLogSource ModLogger;

		public static string ClipsFolder;

		public static string TempFramesFolder;

		public static string FFmpegPath;

		private void Awake()
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			ModLogger = ((BaseUnityPlugin)this).Logger;
			ModLogger.LogInfo((object)"[MainPlugin] Awake() called. Initializing paths...");
			string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			ClipsFolder = Path.Combine(directoryName, "Clips");
			TempFramesFolder = Path.Combine(directoryName, "TempFrames");
			FFmpegPath = Path.Combine(directoryName, "ffmpeg.exe");
			Directory.CreateDirectory(ClipsFolder);
			Directory.CreateDirectory(TempFramesFolder);
			if (!File.Exists(FFmpegPath))
			{
				ModLogger.LogError((object)("[MainPlugin] CRITICAL: ffmpeg.exe was not found at '" + FFmpegPath + "'! Video clipping will not work."));
			}
			else
			{
				ModLogger.LogInfo((object)"[MainPlugin] ffmpeg.exe found successfully.");
			}
			Harmony val = new Harmony("com.smileo.recordingviewer");
			val.PatchAll();
			ModLogger.LogInfo((object)"[MainPlugin] Harmony patches applied.");
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			if ((Object)(object)GameObject.Find("SmileosFrameClipperObj") == (Object)null)
			{
				ModLogger.LogInfo((object)("[MainPlugin] Scene loaded (" + ((Scene)(ref scene)).name + "). Spawning FrameClipper object..."));
				GameObject val = new GameObject("SmileosFrameClipperObj");
				Object.DontDestroyOnLoad((Object)(object)val);
				val.AddComponent<FrameClipper>();
				ModLogger.LogInfo((object)"[MainPlugin] FrameClipper component successfully added!");
			}
		}
	}
	public class FrameClipper : MonoBehaviour
	{
		private const int MaxFrames = 450;

		private Queue<byte[]> frameBuffer = new Queue<byte[]>();

		private bool isSaving = false;

		private const int DownscaleDivisor = 4;

		private Texture2D? fullScreenTex = null;

		private Texture2D? smallTex = null;

		private void Start()
		{
			MainPlugin.ModLogger.LogInfo((object)"[FrameClipper] Start() triggered. Launching ultra-lightweight CaptureRoutine...");
			((MonoBehaviour)this).StartCoroutine(CaptureRoutine());
		}

		private void Update()
		{
			if ((Input.GetKeyDown((KeyCode)96) || Input.GetKeyDown((KeyCode)289)) && !isSaving)
			{
				MainPlugin.ModLogger.LogInfo((object)"[FrameClipper] Hotkey triggered! Attempting to save clip...");
				((MonoBehaviour)this).StartCoroutine(SaveClipRoutine());
			}
		}

		private IEnumerator CaptureRoutine()
		{
			MainPlugin.ModLogger.LogInfo((object)"[CaptureRoutine] Started lightweight 15 FPS frame capture loop.");
			while (Screen.width <= 0 || Screen.height <= 0)
			{
				yield return null;
			}
			float nextCaptureTime = Time.realtimeSinceStartup;
			float captureInterval = 1f / 15f;
			while (true)
			{
				yield return (object)new WaitForEndOfFrame();
				if (isSaving || Time.realtimeSinceStartup < nextCaptureTime)
				{
					continue;
				}
				nextCaptureTime += captureInterval;
				if (Screen.width <= 0 || Screen.height <= 0)
				{
					continue;
				}
				int targetWidth = Mathf.Max(160, Screen.width / 4);
				int targetHeight = Mathf.Max(90, Screen.height / 4);
				if ((Object)(object)fullScreenTex == (Object)null || ((Texture)fullScreenTex).width != Screen.width || ((Texture)fullScreenTex).height != Screen.height)
				{
					if ((Object)(object)fullScreenTex != (Object)null)
					{
						Object.Destroy((Object)(object)fullScreenTex);
					}
					if ((Object)(object)smallTex != (Object)null)
					{
						Object.Destroy((Object)(object)smallTex);
					}
					fullScreenTex = new Texture2D(Screen.width, Screen.height, (TextureFormat)3, false);
					smallTex = new Texture2D(targetWidth, targetHeight, (TextureFormat)3, false);
				}
				byte[] bytes = null;
				RenderTexture tempRt = null;
				try
				{
					fullScreenTex.ReadPixels(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), 0, 0, false);
					fullScreenTex.Apply();
					tempRt = RenderTexture.GetTemporary(targetWidth, targetHeight, 0);
					Graphics.Blit((Texture)(object)fullScreenTex, tempRt);
					RenderTexture.active = tempRt;
					smallTex.ReadPixels(new Rect(0f, 0f, (float)targetWidth, (float)targetHeight), 0, 0, false);
					smallTex.Apply();
					RenderTexture.active = null;
					bytes = ImageConversion.EncodeToJPG(smallTex, 40);
				}
				catch (Exception ex)
				{
					Exception ex2 = ex;
					MainPlugin.ModLogger.LogError((object)("[CaptureRoutine] Exception during frame capture: " + ex2.Message));
				}
				finally
				{
					if ((Object)(object)tempRt != (Object)null)
					{
						RenderTexture.ReleaseTemporary(tempRt);
					}
				}
				if (bytes != null)
				{
					frameBuffer.Enqueue(bytes);
					if (frameBuffer.Count > 450)
					{
						frameBuffer.Dequeue();
					}
				}
			}
		}

		private IEnumerator SaveClipRoutine()
		{
			if (!File.Exists(MainPlugin.FFmpegPath))
			{
				MainPlugin.ModLogger.LogError((object)"[SaveClipRoutine] Cannot save clip: ffmpeg.exe is missing!");
				yield break;
			}
			isSaving = true;
			MainPlugin.ModLogger.LogInfo((object)"[SaveClipRoutine] Saving clip, dumping frames to disk...");
			byte[][] framesToDump = frameBuffer.ToArray();
			MainPlugin.ModLogger.LogInfo((object)$"[SaveClipRoutine] Total frames to dump: {framesToDump.Length}");
			for (int i = 0; i < framesToDump.Length; i++)
			{
				string filePath = Path.Combine(MainPlugin.TempFramesFolder, $"frame_{i:D4}.jpg");
				File.WriteAllBytes(filePath, framesToDump[i]);
			}
			string outputFile = Path.Combine(path2: "Clip_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".mp4", path1: MainPlugin.ClipsFolder);
			string normalizedTempFolder = MainPlugin.TempFramesFolder.Replace("\\", "/");
			ProcessStartInfo startInfo = new ProcessStartInfo
			{
				FileName = MainPlugin.FFmpegPath,
				Arguments = "-framerate 15 -i \"" + normalizedTempFolder + "/frame_%04d.jpg\" -r 15 -c:v libx264 -pix_fmt yuv420p \"" + outputFile + "\"",
				UseShellExecute = false,
				CreateNoWindow = true
			};
			MainPlugin.ModLogger.LogInfo((object)"[SaveClipRoutine] Starting FFmpeg process...");
			Process process;
			try
			{
				process = Process.Start(startInfo);
			}
			catch (Exception ex)
			{
				Exception ex2 = ex;
				MainPlugin.ModLogger.LogError((object)("[SaveClipRoutine] Failed to start FFmpeg: " + ex2.Message));
				isSaving = false;
				yield break;
			}
			if (process != null)
			{
				while (!process.HasExited)
				{
					yield return null;
				}
				MainPlugin.ModLogger.LogInfo((object)"[SaveClipRoutine] FFmpeg encoding finished.");
			}
			MainPlugin.ModLogger.LogInfo((object)"[SaveClipRoutine] Cleaning up temp frame files...");
			string[] files = Directory.GetFiles(MainPlugin.TempFramesFolder);
			foreach (string file in files)
			{
				try
				{
					File.Delete(file);
				}
				catch
				{
				}
			}
			isSaving = false;
			MainPlugin.ModLogger.LogInfo((object)("[SaveClipRoutine] Clip saved successfully to: " + outputFile));
		}

		private void OnDestroy()
		{
			if ((Object)(object)fullScreenTex != (Object)null)
			{
				Object.Destroy((Object)(object)fullScreenTex);
			}
			if ((Object)(object)smallTex != (Object)null)
			{
				Object.Destroy((Object)(object)smallTex);
			}
		}
	}
	[HarmonyPatch]
	public static class TerminalInjectionPatch
	{
		private static MethodBase? TargetMethod()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = assembly.GetType("ShopZone");
				if (type != null)
				{
					MainPlugin.ModLogger.LogInfo((object)"Found ShopZone type in assembly!");
					return type.GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			MainPlugin.ModLogger.LogError((object)"Could not find ShopZone type!");
			return null;
		}

		private static Transform? FindChildRecursive(Transform parent, string exactName)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			if (((Object)parent).name == exactName)
			{
				return parent;
			}
			foreach (Transform item in parent)
			{
				Transform parent2 = item;
				Transform val = FindChildRecursive(parent2, exactName);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static Transform? FindFirstButton(Transform parent)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			foreach (Transform item in parent)
			{
				Transform val = item;
				if (((Object)val).name != "RecordingsButton" && (Object)(object)((Component)val).GetComponent<Button>() != (Object)null)
				{
					return val;
				}
				Transform val2 = FindFirstButton(val);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}

		private static void Postfix(Component __instance)
		{
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Expected O, but got Unknown
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Expected O, but got Unknown
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Expected O, but got Unknown
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b5: Expected O, but got Unknown
			//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_0569: Expected O, but got Unknown
			//IL_0597: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_060b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0615: Expected O, but got Unknown
			//IL_064c: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c1: Expected O, but got Unknown
			//IL_06f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0740: Unknown result type (might be due to invalid IL or missing references)
			//IL_0757: Unknown result type (might be due to invalid IL or missing references)
			//IL_076e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0785: Unknown result type (might be due to invalid IL or missing references)
			//IL_079c: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0804: Expected O, but got Unknown
			//IL_0837: Unknown result type (might be due to invalid IL or missing references)
			//IL_0883: Unknown result type (might be due to invalid IL or missing references)
			//IL_089a: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_08c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_08df: Unknown result type (might be due to invalid IL or missing references)
			//IL_093d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0947: Expected O, but got Unknown
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			MainPlugin.ModLogger.LogInfo((object)"ShopZone::Start Postfix triggered!");
			Canvas componentInChildren = __instance.GetComponentInChildren<Canvas>(true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				MainPlugin.ModLogger.LogWarning((object)"Shop canvas could not be found under ShopZone!");
				return;
			}
			Transform transform = ((Component)componentInChildren).transform;
			Transform mainMenu = FindChildRecursive(transform, "Main Menu");
			if ((Object)(object)mainMenu == (Object)null)
			{
				MainPlugin.ModLogger.LogWarning((object)"Could not find object named 'Main Menu'.");
			}
			else
			{
				if ((Object)(object)mainMenu.Find("RecordingsButton") != (Object)null)
				{
					return;
				}
				Transform[] componentsInChildren = ((Component)mainMenu).GetComponentsInChildren<Transform>(true);
				foreach (Transform val in componentsInChildren)
				{
					if (((Object)val).name == "RecordingsButton")
					{
						return;
					}
				}
				Transform templateBtn = FindFirstButton(mainMenu);
				if ((Object)(object)templateBtn == (Object)null)
				{
					MainPlugin.ModLogger.LogWarning((object)"Could not find any button component to use as a template under Main Menu!");
					return;
				}
				GameObject listPanel = new GameObject("SmileosListPanel", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				listPanel.transform.SetParent(transform, false);
				RectTransform component = listPanel.GetComponent<RectTransform>();
				component.sizeDelta = new Vector2(650f, 450f);
				component.anchoredPosition = Vector2.zero;
				((Graphic)listPanel.GetComponent<Image>()).color = new Color(0.05f, 0.05f, 0.05f, 0.95f);
				listPanel.SetActive(false);
				GameObject val2 = new GameObject("ClipScrollView", new Type[2]
				{
					typeof(RectTransform),
					typeof(ScrollRect)
				});
				val2.transform.SetParent(listPanel.transform, false);
				RectTransform component2 = val2.GetComponent<RectTransform>();
				component2.sizeDelta = new Vector2(600f, 320f);
				component2.anchoredPosition = new Vector2(0f, 30f);
				GameObject val3 = new GameObject("Viewport", new Type[4]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image),
					typeof(Mask)
				});
				val3.transform.SetParent(val2.transform, false);
				RectTransform component3 = val3.GetComponent<RectTransform>();
				component3.anchorMin = Vector2.zero;
				component3.anchorMax = Vector2.one;
				component3.sizeDelta = Vector2.zero;
				((Graphic)val3.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.05f);
				val3.GetComponent<Mask>().showMaskGraphic = false;
				GameObject contentObj = new GameObject("Content", new Type[3]
				{
					typeof(RectTransform),
					typeof(VerticalLayoutGroup),
					typeof(ContentSizeFitter)
				});
				contentObj.transform.SetParent(val3.transform, false);
				RectTransform component4 = contentObj.GetComponent<RectTransform>();
				component4.anchorMin = new Vector2(0f, 1f);
				component4.anchorMax = new Vector2(1f, 1f);
				component4.pivot = new Vector2(0.5f, 1f);
				component4.sizeDelta = new Vector2(0f, 0f);
				VerticalLayoutGroup component5 = contentObj.GetComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)component5).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)component5).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)component5).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)component5).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)component5).spacing = 8f;
				((LayoutGroup)component5).padding = new RectOffset(5, 5, 5, 5);
				ContentSizeFitter component6 = contentObj.GetComponent<ContentSizeFitter>();
				component6.verticalFit = (FitMode)2;
				ScrollRect component7 = val2.GetComponent<ScrollRect>();
				component7.content = component4;
				component7.viewport = component3;
				component7.horizontal = false;
				component7.vertical = true;
				GameObject videoPanel = new GameObject("SmileosVideoPanel", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				videoPanel.transform.SetParent(transform, false);
				RectTransform component8 = videoPanel.GetComponent<RectTransform>();
				component8.sizeDelta = new Vector2(650f, 450f);
				component8.anchoredPosition = Vector2.zero;
				((Graphic)videoPanel.GetComponent<Image>()).color = new Color(0.05f, 0.05f, 0.05f, 0.95f);
				videoPanel.SetActive(false);
				GameObject val4 = new GameObject("VideoDisplay", new Type[3]
				{
					typeof(RectTransform),
					typeof(RawImage),
					typeof(VideoPlayer)
				});
				val4.transform.SetParent(videoPanel.transform, false);
				RectTransform component9 = val4.GetComponent<RectTransform>();
				component9.sizeDelta = new Vector2(560f, 315f);
				component9.anchoredPosition = new Vector2(0f, 35f);
				RawImage rawImage = val4.GetComponent<RawImage>();
				((Graphic)rawImage).color = Color.black;
				VideoPlayer videoPlayer = val4.GetComponent<VideoPlayer>();
				videoPlayer.playOnAwake = false;
				videoPlayer.renderMode = (VideoRenderMode)4;
				videoPlayer.prepareCompleted += (EventHandler)delegate(VideoPlayer source)
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					((Graphic)rawImage).color = Color.white;
					rawImage.texture = source.texture;
					source.Play();
				};
				Transform parent = templateBtn.parent;
				GameObject val5 = Object.Instantiate<GameObject>(((Component)templateBtn).gameObject, parent, false);
				((Object)val5).name = "RecordingsButton";
				val5.transform.localScale = Vector3.one;
				val5.transform.SetAsLastSibling();
				TMP_Text componentInChildren2 = val5.GetComponentInChildren<TMP_Text>();
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					componentInChildren2.text = "RECORDINGS";
					componentInChildren2.enableWordWrapping = false;
				}
				Button component10 = val5.GetComponent<Button>();
				((UnityEventBase)component10.onClick).RemoveAllListeners();
				((UnityEvent)component10.onClick).AddListener((UnityAction)delegate
				{
					//IL_004a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0050: Expected O, but got Unknown
					//IL_0145: Unknown result type (might be due to invalid IL or missing references)
					//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
					//IL_01fc: Expected O, but got Unknown
					MainPlugin.ModLogger.LogInfo((object)"Recordings button clicked! Populating clip list...");
					((Component)mainMenu).gameObject.SetActive(false);
					listPanel.SetActive(true);
					foreach (Transform item in contentObj.transform)
					{
						Transform val8 = item;
						Object.Destroy((Object)(object)((Component)val8).gameObject);
					}
					if (!string.IsNullOrEmpty(MainPlugin.ClipsFolder) && Directory.Exists(MainPlugin.ClipsFolder))
					{
						string[] files = Directory.GetFiles(MainPlugin.ClipsFolder, "*.mp4");
						if (files.Length != 0)
						{
							Array.Sort(files, (string a, string b) => File.GetCreationTime(b).CompareTo(File.GetCreationTime(a)));
							string[] array = files;
							foreach (string text in array)
							{
								GameObject val9 = Object.Instantiate<GameObject>(((Component)templateBtn).gameObject, contentObj.transform, false);
								((Object)val9).name = "ClipButton_" + Path.GetFileName(text);
								val9.transform.localScale = Vector3.one;
								LayoutElement val10 = val9.GetComponent<LayoutElement>();
								if ((Object)(object)val10 == (Object)null)
								{
									val10 = val9.AddComponent<LayoutElement>();
								}
								val10.preferredHeight = 40f;
								TMP_Text componentInChildren5 = val9.GetComponentInChildren<TMP_Text>();
								if ((Object)(object)componentInChildren5 != (Object)null)
								{
									componentInChildren5.text = $"{Path.GetFileName(text)} ({File.GetCreationTime(text):yyyy-MM-dd HH:mm:ss})";
									componentInChildren5.enableWordWrapping = false;
								}
								Button component17 = val9.GetComponent<Button>();
								((UnityEventBase)component17.onClick).RemoveAllListeners();
								string capturedPath = text;
								((UnityEvent)component17.onClick).AddListener((UnityAction)delegate
								{
									MainPlugin.ModLogger.LogInfo((object)("Loading selected clip: " + capturedPath));
									listPanel.SetActive(false);
									videoPanel.SetActive(true);
									videoPlayer.url = capturedPath;
									videoPlayer.Prepare();
								});
							}
						}
						else
						{
							MainPlugin.ModLogger.LogWarning((object)"No clips found in Clips folder!");
						}
					}
				});
				GameObject val6 = Object.Instantiate<GameObject>(((Component)templateBtn).gameObject, listPanel.transform, false);
				((Object)val6).name = "ListBackButton";
				val6.transform.localScale = Vector3.one;
				val6.transform.SetAsLastSibling();
				LayoutElement component11 = val6.GetComponent<LayoutElement>();
				if ((Object)(object)component11 != (Object)null)
				{
					Object.Destroy((Object)(object)component11);
				}
				RectTransform component12 = val6.GetComponent<RectTransform>();
				component12.anchorMin = new Vector2(0.5f, 0f);
				component12.anchorMax = new Vector2(0.5f, 0f);
				component12.pivot = new Vector2(0.5f, 0f);
				component12.sizeDelta = new Vector2(160f, 35f);
				component12.anchoredPosition = new Vector2(0f, 20f);
				TMP_Text componentInChildren3 = val6.GetComponentInChildren<TMP_Text>();
				if ((Object)(object)componentInChildren3 != (Object)null)
				{
					componentInChildren3.text = "< BACK";
					componentInChildren3.enableWordWrapping = false;
				}
				Button component13 = val6.GetComponent<Button>();
				((UnityEventBase)component13.onClick).RemoveAllListeners();
				((UnityEvent)component13.onClick).AddListener((UnityAction)delegate
				{
					listPanel.SetActive(false);
					((Component)mainMenu).gameObject.SetActive(true);
				});
				GameObject val7 = Object.Instantiate<GameObject>(((Component)templateBtn).gameObject, videoPanel.transform, false);
				((Object)val7).name = "VideoBackButton";
				val7.transform.localScale = Vector3.one;
				val7.transform.SetAsLastSibling();
				LayoutElement component14 = val7.GetComponent<LayoutElement>();
				if ((Object)(object)component14 != (Object)null)
				{
					Object.Destroy((Object)(object)component14);
				}
				RectTransform component15 = val7.GetComponent<RectTransform>();
				component15.anchorMin = new Vector2(0.5f, 0f);
				component15.anchorMax = new Vector2(0.5f, 0f);
				component15.pivot = new Vector2(0.5f, 0f);
				component15.sizeDelta = new Vector2(160f, 35f);
				component15.anchoredPosition = new Vector2(0f, 20f);
				TMP_Text componentInChildren4 = val7.GetComponentInChildren<TMP_Text>();
				if ((Object)(object)componentInChildren4 != (Object)null)
				{
					componentInChildren4.text = "< BACK TO LIST";
					componentInChildren4.enableWordWrapping = false;
				}
				Button component16 = val7.GetComponent<Button>();
				((UnityEventBase)component16.onClick).RemoveAllListeners();
				((UnityEvent)component16.onClick).AddListener((UnityAction)delegate
				{
					if (videoPlayer.isPlaying)
					{
						videoPlayer.Stop();
					}
					videoPanel.SetActive(false);
					listPanel.SetActive(true);
				});
				LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)parent).GetComponent<RectTransform>());
				MainPlugin.ModLogger.LogInfo((object)"Terminal injection with clip selector complete!");
			}
		}
	}
}