private async Task LoadBlueprints(string blueprintDirectory)
        {
            if (string.IsNullOrWhiteSpace(blueprintDirectory))
            {
                throw new ArgumentException($"'{nameof(blueprintDirectory)}' cannot be null or whitespace", nameof(blueprintDirectory));
            }
            var knownWriteDateTime = DateTime.MinValue;

            int exceptions = 0;

            while (true)
            {
                try
                {
                    var lastWriteDateTime = Directory.GetLastWriteTime(blueprintDirectory);

                    if (knownWriteDateTime < lastWriteDateTime)
                    {
                        knownWriteDateTime = lastWriteDateTime;

                        foreach (string bpDir in Directory.GetDirectories(blueprintDirectory))
                        {
                            if (!LoadedBlueprints.ContainsKey(bpDir) && Directory.Exists(bpDir) &&
                                File.Exists($"{bpDir}/blueprint.json"))
                            {
                                BlueprintContext bp = BlueprintContext.FromFolderPath(bpDir);
                                LoadedBlueprints.Add(bpDir, bp);

                                GameObject newButton = buttonObjectPool.GetObject();
                                newButton.transform.SetParent(contentPanel);
                                BlueprintButton blueprintButton = newButton.GetComponent <BlueprintButton>();
                                blueprintButton.Setup(bp);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    if (exceptions++ < 10)
                    {
                        Debug.LogException(e);
                    }
                }
                finally
                {
                    await Task.Delay(2000);
                }
            }
        }
        private void OnChanged(object sender, FileSystemEventArgs e)// different thread
        {
            try
            {
                string path   = e.FullPath;
                bool   exists = Directory.Exists(path) || File.Exists(path);

                if (exists)
                {
                    FileAttributes fileAttributes = File.GetAttributes(path);
                    if ((fileAttributes & FileAttributes.Directory) != FileAttributes.Directory)
                    {
                        path = Directory.GetParent(path)?.FullName;
                    }
                    if (LoadedBlueprints.TryGetValue(path, out var blueprintCtx))
                    {
                        _ = RunMain(() =>
                        {
                            blueprintCtx.LoadDescription();
                            blueprintCtx.LoadIcon();
                            blueprintCtx.btn.Initialize();
                            if (SelectedBlueprintButton == blueprintCtx.btn)
                            {
                                SelectBlueprintButton(SelectedBlueprintButton);
                            }
                        }).LogErrors();
                    }
                    else if (File.Exists($"{path}/blueprint.json"))
                    {
                        _ = RunMain(() =>
                        {
                            BlueprintContext bp = BlueprintContext.FromFolderPath(path);
                            LoadedBlueprints.Add(path, bp);

                            GameObject newButton = buttonObjectPool.GetObject();
                            newButton.transform.SetParent(contentPanel);
                            BlueprintButton blueprintButton = newButton.GetComponent <BlueprintButton>();
                            blueprintButton.Setup(bp);
                        }).LogErrors();
                    }
                }
                else
                {
                    if (path.Contains('.')) // assume it's a file
                    {
                        path = path.Substring(0, path.LastIndexOf(Path.DirectorySeparatorChar));
                    }
                    if (LoadedBlueprints.TryGetValue(path, out var blueprintCtx))
                    {
                        _ = RunMain(() =>
                        {
                            if (SelectedBlueprintButton == blueprintCtx.btn)
                            {
                                titleField.text       = string.Empty;
                                descriptionField.text = string.Empty;
                                applyButton.gameObject.SetActive(false);
                            }
                            Destroy(blueprintCtx.btn.gameObject);
                            LoadedBlueprints.Remove(path);
                        }).LogErrors();
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
            }
        }