using AssetStoreTools.Uploader; using System; using System.Linq; using System.Threading.Tasks; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; namespace AssetStoreTools.Utility { [InitializeOnLoad] internal class ASToolsUpdater : AssetStoreToolsWindow { private const string AssetStoreToolsUrl = "https://assetstore.unity.com/packages/tools/utilities/asset-store-publishing-tools-115"; protected override string WindowTitle => "Asset Store Tools Update Check"; private VisualElement _loadingContainer; private VisualElement _versionInfoContainer; private Image _loadingImage; private double _lastTimeSinceStartup; private double _timeSinceLoadingImageChange; private int _loadingImageIndex; private static bool _updateCheckPerformed { get { return SessionState.GetBool("AST_UpdateChecked", false); } set { SessionState.SetBool("AST_UpdateChecked", value); } } static ASToolsUpdater() { // Retrieving cached SessionState/PlayerPrefs values is not allowed from an instance field initializer EditorApplication.update += CheckForUpdatesAfterEditorUpdate; } private static async void CheckForUpdatesAfterEditorUpdate() { EditorApplication.update -= CheckForUpdatesAfterEditorUpdate; if (!ShouldCheckForUpdates()) return; await CheckForUpdates((success, currentVersion, latestVersion) => { if (success && currentVersion < latestVersion) { AssetStoreTools.OpenUpdateChecker(); } }); } private static bool ShouldCheckForUpdates() { if (!ASToolsPreferences.Instance.CheckForUpdates) return false; return _updateCheckPerformed == false; } private static async Task CheckForUpdates(Action OnUpdatesChecked) { _updateCheckPerformed = true; var latestVersionResult = await AssetStoreAPI.GetLatestAssetStoreToolsVersion(); if (!latestVersionResult.Success) { OnUpdatesChecked?.Invoke(false, null, null); return; } Version currentVersion = null; Version latestVersion = null; try { var latestVersionStr = latestVersionResult.Response["version"].AsString(); var currentVersionStr = PackageUtility.GetAllPackages().FirstOrDefault(x => x.name == "com.unity.asset-store-tools").version; currentVersion = new Version(currentVersionStr); latestVersion = new Version(latestVersionStr); } catch { OnUpdatesChecked?.Invoke(false, null, null); } OnUpdatesChecked?.Invoke(true, currentVersion, latestVersion); } protected override void Init() { base.Init(); rootVisualElement.styleSheets.Add(StyleSelector.UpdaterWindow.UpdaterWindowStyle); rootVisualElement.styleSheets.Add(StyleSelector.UpdaterWindow.UpdaterWindowTheme); SetupLoadingSpinner(); _ = CheckForUpdates(OnVersionsRetrieved); } private void OnVersionsRetrieved(bool success, Version currentVersion, Version latestVersion) { if (_loadingContainer != null) _loadingContainer.style.display = DisplayStyle.None; if (success) { SetupVersionInfo(currentVersion, latestVersion); } else { SetupFailInfo(); } } private void SetupLoadingSpinner() { _loadingContainer = new VisualElement(); _loadingContainer.AddToClassList("loading-container"); _loadingImage = new Image(); EditorApplication.update += LoadingSpinLoop; _loadingContainer.Add(_loadingImage); rootVisualElement.Add(_loadingContainer); } private void SetupVersionInfo(Version currentVersion, Version latestVersion) { _versionInfoContainer = new VisualElement(); _versionInfoContainer.AddToClassList("version-info-container"); AddDescriptionLabels(currentVersion, latestVersion); AddUpdateButtons(currentVersion, latestVersion); AddCheckForUpdatesToggle(); rootVisualElement.Add(_versionInfoContainer); } private void AddDescriptionLabels(Version currentVersion, Version latestVersion) { var descriptionText = currentVersion < latestVersion ? "An update to the Asset Store Publishing Tools is available. Updating to the latest version is highly recommended." : "Asset Store Publishing Tools are up to date!"; var labelContainer = new VisualElement(); labelContainer.AddToClassList("version-info-container-labels"); var descriptionLabel = new Label(descriptionText); descriptionLabel.AddToClassList("version-info-container-labels-description"); var currentVersionRow = new VisualElement(); currentVersionRow.AddToClassList("version-info-container-labels-row"); var latestVersionRow = new VisualElement(); latestVersionRow.AddToClassList("version-info-container-labels-row"); var currentVersionLabel = new Label("Current version:"); currentVersionLabel.AddToClassList("version-info-container-labels-row-identifier"); var latestVersionLabel = new Label("Latest version:"); latestVersionLabel.AddToClassList("version-info-container-labels-row-identifier"); var currentVersionLabelValue = new Label(currentVersion.ToString()); var latestVersionLabelValue = new Label(latestVersion.ToString()); currentVersionRow.Add(currentVersionLabel); currentVersionRow.Add(currentVersionLabelValue); latestVersionRow.Add(latestVersionLabel); latestVersionRow.Add(latestVersionLabelValue); labelContainer.Add(descriptionLabel); labelContainer.Add(currentVersionRow); labelContainer.Add(latestVersionRow); _versionInfoContainer.Add(labelContainer); } private void AddUpdateButtons(Version currentVersion, Version latestVersion) { if (currentVersion >= latestVersion) return; var buttonContainer = new VisualElement(); buttonContainer.AddToClassList("version-info-container-buttons"); var latestVersionButton = new Button(() => Application.OpenURL(AssetStoreToolsUrl)) { text = "Get the latest version" }; var skipVersionButton = new Button(Close) { text = "Skip for now" }; buttonContainer.Add(latestVersionButton); buttonContainer.Add(skipVersionButton); _versionInfoContainer.Add(buttonContainer); } private void AddCheckForUpdatesToggle() { var toggleContainer = new VisualElement(); toggleContainer.AddToClassList("version-info-container-toggle"); var checkForUpdatesToggle = new Toggle() { text = "Check for Updates", value = ASToolsPreferences.Instance.CheckForUpdates }; checkForUpdatesToggle.RegisterValueChangedCallback(OnCheckForUpdatesToggleChanged); toggleContainer.Add(checkForUpdatesToggle); _versionInfoContainer.Add(toggleContainer); } private void OnCheckForUpdatesToggleChanged(ChangeEvent evt) { ASToolsPreferences.Instance.CheckForUpdates = evt.newValue; ASToolsPreferences.Instance.Save(); } private void SetupFailInfo() { var failContainer = new VisualElement(); failContainer.AddToClassList("fail-container"); var failImage = new Image(); var failDescription = new Label("Asset Store Publishing Tools could not retrieve information about the latest version."); failContainer.Add(failImage); failContainer.Add(failDescription); rootVisualElement.Add(failContainer); } private void LoadingSpinLoop() { var currentTimeSinceStartup = EditorApplication.timeSinceStartup; var deltaTime = EditorApplication.timeSinceStartup - _lastTimeSinceStartup; _lastTimeSinceStartup = currentTimeSinceStartup; _timeSinceLoadingImageChange += deltaTime; if (_timeSinceLoadingImageChange < 0.075) return; _timeSinceLoadingImageChange = 0; _loadingImage.image = EditorGUIUtility.IconContent($"WaitSpin{_loadingImageIndex++:00}").image; if (_loadingImageIndex > 11) _loadingImageIndex = 0; } private void OnDestroy() { EditorApplication.update -= LoadingSpinLoop; } } }