diff --git a/Assets/Tests/Editor/OnionAssemblyDependencyTests.cs b/Assets/Tests/Editor/OnionAssemblyDependencyTests.cs
index 46b321f811..0e571ffef3 100644
--- a/Assets/Tests/Editor/OnionAssemblyDependencyTests.cs
+++ b/Assets/Tests/Editor/OnionAssemblyDependencyTests.cs
@@ -884,9 +884,28 @@ public void SetupWizardStartup_WhenLoaded_SchedulesVersionCheckInsteadOfReadingS
// Tests that Setup Wizard settings reads run after the synchronous Editor startup hook.
string setupWizardSource = ReadProductionSource(
"Packages/src/Editor/Presentation/Setup/SetupWizardWindow.cs");
+ string setupWizardStartupFlowSource = ReadProductionSource(
+ "Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs");
- Assert.That(setupWizardSource, Does.Contain("EditorApplication.delayCall += TryShowOnVersionChange;"));
- Assert.That(setupWizardSource, Does.Not.Contain("\n TryShowOnVersionChange();"));
+ Assert.That(
+ setupWizardSource,
+ Does.Contain("EditorApplication.delayCall += startupFlow.TryShowOnVersionChange;"));
+ Assert.That(
+ setupWizardStartupFlowSource,
+ Does.Contain("EditorApplication.delayCall += () => _showWindowOnVersionChange();"));
+ Assert.That(setupWizardSource, Does.Not.Contain("\n startupFlow.TryShowOnVersionChange();"));
+ }
+
+ [Test]
+ public void SetupWizardStartup_WhenMigrationAutoScanIsRequested_SchedulesAutoScanThroughDelayCall()
+ {
+ // Tests that startup migration auto-scan runs through a delayed Editor callback.
+ string setupWizardStartupFlowSource = ReadProductionSource(
+ "Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs");
+
+ Assert.That(
+ setupWizardStartupFlowSource,
+ Does.Contain("EditorApplication.delayCall += () => _showThirdPartyMigrationAutoScan();"));
}
[Test]
diff --git a/Assets/Tests/Editor/SetupWizardWindowTests.cs b/Assets/Tests/Editor/SetupWizardWindowTests.cs
index eacab5a0c8..738e4b7eaf 100644
--- a/Assets/Tests/Editor/SetupWizardWindowTests.cs
+++ b/Assets/Tests/Editor/SetupWizardWindowTests.cs
@@ -48,7 +48,6 @@ public void SetUp()
UnityCliLoopEditorSessionStateTestFactory.ClearAll();
SetupWizardWindow.InitializeEditorServices(
_editorSettingsPort,
- _sessionFlagsRepository,
CreateCliSetupApplicationService(),
CreateSkillSetupUseCase());
_editorSettingsRepository.InvalidateCache();
@@ -85,7 +84,7 @@ public void ShouldAutoShowForVersion_ReturnsExpectedValue(
{
// Verifies that package and dispatcher requirement changes auto-show only for actionable updates.
bool shouldAutoShow =
- SetupWizardWindow.ShouldAutoShowForVersion(
+ SetupWizardStartupFlow.ShouldAutoShowForVersion(
currentVersion,
lastSeenVersion,
currentMinimumDispatcherVersion,
@@ -108,7 +107,7 @@ public void HasSkillUpdateForSetupWizard_WhenOutdatedTargetHasSkillsDirectory_Re
installState: SkillInstallState.Outdated)
};
- bool hasSkillUpdate = SetupWizardWindow.HasSkillUpdateForSetupWizard(targets);
+ bool hasSkillUpdate = SetupWizardStartupFlow.HasSkillUpdateForSetupWizard(targets);
Assert.That(hasSkillUpdate, Is.True);
}
@@ -127,7 +126,7 @@ public void HasSkillUpdateForSetupWizard_WhenTargetIsNotOutdated_ReturnsFalse(
installState)
};
- bool hasSkillUpdate = SetupWizardWindow.HasSkillUpdateForSetupWizard(targets);
+ bool hasSkillUpdate = SetupWizardStartupFlow.HasSkillUpdateForSetupWizard(targets);
Assert.That(hasSkillUpdate, Is.False);
}
@@ -143,7 +142,7 @@ public void HasSkillUpdateForSetupWizard_WhenOutdatedTargetHasNoSkillsDirectory_
installState: SkillInstallState.Outdated)
};
- bool hasSkillUpdate = SetupWizardWindow.HasSkillUpdateForSetupWizard(targets);
+ bool hasSkillUpdate = SetupWizardStartupFlow.HasSkillUpdateForSetupWizard(targets);
Assert.That(hasSkillUpdate, Is.False);
}
@@ -160,7 +159,7 @@ public void HasSkillUpdateForSetupWizard_WhenTargetHasDifferentLayoutSkills_Retu
hasDifferentLayoutSkills: true)
};
- bool hasSkillUpdate = SetupWizardWindow.HasSkillUpdateForSetupWizard(targets);
+ bool hasSkillUpdate = SetupWizardStartupFlow.HasSkillUpdateForSetupWizard(targets);
Assert.That(hasSkillUpdate, Is.True);
}
@@ -179,7 +178,7 @@ public void ShouldAutoScanThirdPartyToolMigration_ReturnsExpectedValue(
{
// Verifies that V3 startup scans run for V2 upgrades or missing prior setup state.
bool shouldAutoScan =
- SetupWizardWindow.ShouldAutoScanThirdPartyToolMigration(currentVersion, lastSeenVersion);
+ SetupWizardStartupFlow.ShouldAutoScanThirdPartyToolMigration(currentVersion, lastSeenVersion);
Assert.That(shouldAutoScan, Is.EqualTo(expected));
}
@@ -188,7 +187,7 @@ public void ShouldAutoScanThirdPartyToolMigration_ReturnsExpectedValue(
public void MaybeMarkThirdPartyToolMigrationAutoScan_WhenEnabled_SetsSessionFlag()
{
// Verifies that the V2-to-V3 upgrade signal is stored only in the current Editor session.
- SetupWizardWindow.MaybeMarkThirdPartyToolMigrationAutoScan(true);
+ SetupWizardStartupFlow.MaybeMarkThirdPartyToolMigrationAutoScan(_sessionFlagsRepository, true);
Assert.That(_sessionFlagsRepository.GetShouldAutoScanThirdPartyToolMigration(), Is.True);
}
@@ -197,7 +196,7 @@ public void MaybeMarkThirdPartyToolMigrationAutoScan_WhenEnabled_SetsSessionFlag
public void MaybeMarkThirdPartyToolMigrationAutoScan_WhenDisabled_KeepsSessionFlagFalse()
{
// Verifies that non-upgrade version checks do not request migration scans.
- SetupWizardWindow.MaybeMarkThirdPartyToolMigrationAutoScan(false);
+ SetupWizardStartupFlow.MaybeMarkThirdPartyToolMigrationAutoScan(_sessionFlagsRepository, false);
Assert.That(_sessionFlagsRepository.GetShouldAutoScanThirdPartyToolMigration(), Is.False);
}
@@ -205,13 +204,18 @@ public void MaybeMarkThirdPartyToolMigrationAutoScan_WhenDisabled_KeepsSessionFl
[Test]
public void MaybeRecordLastSeenSetupWizardState_WhenAutoShow_UpdatesStoredState()
{
+ // Verifies that auto-show records the setup wizard version state.
_editorSettingsPort.SaveSettings(new UnityCliLoopEditorSettingsData
{
lastSeenSetupWizardVersion = "1.7.2",
lastSeenSetupWizardMinimumDispatcherVersion = "3.0.1"
});
- SetupWizardWindow.MaybeRecordLastSeenSetupWizardState(true, "1.7.3", "3.0.2");
+ SetupWizardStartupFlow.MaybeRecordLastSeenSetupWizardState(
+ _editorSettingsPort,
+ true,
+ "1.7.3",
+ "3.0.2");
Assert.That(_editorSettingsPort.GetLastSeenSetupWizardVersion(), Is.EqualTo("1.7.3"));
Assert.That(
@@ -222,13 +226,18 @@ public void MaybeRecordLastSeenSetupWizardState_WhenAutoShow_UpdatesStoredState(
[Test]
public void MaybeRecordLastSeenSetupWizardState_WhenManualShow_KeepsStoredState()
{
+ // Verifies that manual opens do not update the setup wizard version state.
_editorSettingsPort.SaveSettings(new UnityCliLoopEditorSettingsData
{
lastSeenSetupWizardVersion = "1.7.2",
lastSeenSetupWizardMinimumDispatcherVersion = "3.0.1"
});
- SetupWizardWindow.MaybeRecordLastSeenSetupWizardState(false, "1.7.3", "3.0.2");
+ SetupWizardStartupFlow.MaybeRecordLastSeenSetupWizardState(
+ _editorSettingsPort,
+ false,
+ "1.7.3",
+ "3.0.2");
Assert.That(_editorSettingsPort.GetLastSeenSetupWizardVersion(), Is.EqualTo("1.7.2"));
Assert.That(
@@ -239,13 +248,18 @@ public void MaybeRecordLastSeenSetupWizardState_WhenManualShow_KeepsStoredState(
[Test]
public void MaybeRecordSuppressedSetupWizardState_WhenAutoShowSuppressed_UpdatesStoredState()
{
+ // Verifies that suppressing auto-show records the current setup wizard state.
_editorSettingsPort.SaveSettings(new UnityCliLoopEditorSettingsData
{
lastSeenSetupWizardVersion = "1.7.2",
lastSeenSetupWizardMinimumDispatcherVersion = "3.0.1"
});
- SetupWizardWindow.MaybeRecordSuppressedSetupWizardState(true, "1.7.3", "3.0.2");
+ SetupWizardStartupFlow.MaybeRecordSuppressedSetupWizardState(
+ _editorSettingsPort,
+ true,
+ "1.7.3",
+ "3.0.2");
Assert.That(_editorSettingsPort.GetLastSeenSetupWizardVersion(), Is.EqualTo("1.7.3"));
Assert.That(
@@ -256,13 +270,18 @@ public void MaybeRecordSuppressedSetupWizardState_WhenAutoShowSuppressed_Updates
[Test]
public void MaybeRecordSuppressedSetupWizardState_WhenAutoShowAllowed_KeepsStoredState()
{
+ // Verifies that allowing auto-show leaves the stored setup wizard state unchanged.
_editorSettingsPort.SaveSettings(new UnityCliLoopEditorSettingsData
{
lastSeenSetupWizardVersion = "1.7.2",
lastSeenSetupWizardMinimumDispatcherVersion = "3.0.1"
});
- SetupWizardWindow.MaybeRecordSuppressedSetupWizardState(false, "1.7.3", "3.0.2");
+ SetupWizardStartupFlow.MaybeRecordSuppressedSetupWizardState(
+ _editorSettingsPort,
+ false,
+ "1.7.3",
+ "3.0.2");
Assert.That(_editorSettingsPort.GetLastSeenSetupWizardVersion(), Is.EqualTo("1.7.2"));
Assert.That(
diff --git a/Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs b/Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs
new file mode 100644
index 0000000000..d0cf8aaeaa
--- /dev/null
+++ b/Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs
@@ -0,0 +1,311 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using UnityEditor;
+using UnityEngine;
+
+using io.github.hatayama.UnityCliLoop.Application;
+using io.github.hatayama.UnityCliLoop.Domain;
+using io.github.hatayama.UnityCliLoop.ToolContracts;
+
+namespace io.github.hatayama.UnityCliLoop.Presentation
+{
+ ///
+ /// Coordinates setup wizard startup auto-show and migration auto-scan decisions.
+ ///
+ internal sealed class SetupWizardStartupFlow
+ {
+ private static readonly char[] VersionMajorSeparators = { '.', '-' };
+
+ private readonly IUnityCliLoopEditorSettingsPort _editorSettingsPort;
+ private readonly ISessionFlagsRepository _sessionFlagsRepository;
+ private readonly CliSetupApplicationService _cliSetupApplicationService;
+ private readonly SkillSetupUseCase _skillSetupUseCase;
+ private readonly System.Action _showWindowOnVersionChange;
+ private readonly System.Action _showThirdPartyMigrationAutoScan;
+
+ internal SetupWizardStartupFlow(
+ IUnityCliLoopEditorSettingsPort editorSettingsPort,
+ ISessionFlagsRepository sessionFlagsRepository,
+ CliSetupApplicationService cliSetupApplicationService,
+ SkillSetupUseCase skillSetupUseCase,
+ System.Action showWindowOnVersionChange,
+ System.Action showThirdPartyMigrationAutoScan)
+ {
+ Debug.Assert(editorSettingsPort != null, "editorSettingsPort must not be null");
+ Debug.Assert(sessionFlagsRepository != null, "sessionFlagsRepository must not be null");
+ Debug.Assert(cliSetupApplicationService != null, "cliSetupApplicationService must not be null");
+ Debug.Assert(skillSetupUseCase != null, "skillSetupUseCase must not be null");
+ Debug.Assert(showWindowOnVersionChange != null, "showWindowOnVersionChange must not be null");
+ Debug.Assert(showThirdPartyMigrationAutoScan != null, "showThirdPartyMigrationAutoScan must not be null");
+
+ _editorSettingsPort = editorSettingsPort
+ ?? throw new System.ArgumentNullException(nameof(editorSettingsPort));
+ _sessionFlagsRepository = sessionFlagsRepository
+ ?? throw new System.ArgumentNullException(nameof(sessionFlagsRepository));
+ _cliSetupApplicationService = cliSetupApplicationService
+ ?? throw new System.ArgumentNullException(nameof(cliSetupApplicationService));
+ _skillSetupUseCase = skillSetupUseCase ?? throw new System.ArgumentNullException(nameof(skillSetupUseCase));
+ _showWindowOnVersionChange = showWindowOnVersionChange
+ ?? throw new System.ArgumentNullException(nameof(showWindowOnVersionChange));
+ _showThirdPartyMigrationAutoScan = showThirdPartyMigrationAutoScan
+ ?? throw new System.ArgumentNullException(nameof(showThirdPartyMigrationAutoScan));
+ }
+
+ internal static bool ShouldAutoShowForVersion(
+ string currentVersion,
+ string lastSeenVersion,
+ string currentMinimumDispatcherVersion,
+ string lastSeenMinimumDispatcherVersion,
+ bool suppressAutoShow,
+ bool needsCliUpdate,
+ bool hasSkillUpdate)
+ {
+ bool versionChanged = !string.Equals(currentVersion, lastSeenVersion, System.StringComparison.Ordinal);
+ bool minimumDispatcherVersionChanged = !string.Equals(
+ currentMinimumDispatcherVersion,
+ lastSeenMinimumDispatcherVersion,
+ System.StringComparison.Ordinal);
+ if (!versionChanged && !minimumDispatcherVersionChanged) return false;
+ if (suppressAutoShow) return false;
+
+ return string.IsNullOrEmpty(lastSeenVersion)
+ || needsCliUpdate
+ || (versionChanged && hasSkillUpdate);
+ }
+
+ internal static bool ShouldAutoScanThirdPartyToolMigration(string currentVersion, string lastSeenVersion)
+ {
+ if (!TryGetMajorVersion(currentVersion, out int currentMajorVersion))
+ {
+ return false;
+ }
+
+ if (string.IsNullOrEmpty(lastSeenVersion))
+ {
+ return currentMajorVersion == 3;
+ }
+
+ if (!TryGetMajorVersion(lastSeenVersion, out int lastSeenMajorVersion))
+ {
+ return false;
+ }
+
+ return lastSeenMajorVersion < 3 && currentMajorVersion == 3;
+ }
+
+ internal static void MaybeMarkThirdPartyToolMigrationAutoScan(
+ ISessionFlagsRepository sessionFlagsRepository,
+ bool shouldAutoScan)
+ {
+ Debug.Assert(sessionFlagsRepository != null, "sessionFlagsRepository must not be null");
+
+ if (!shouldAutoScan)
+ {
+ return;
+ }
+
+ sessionFlagsRepository.SetShouldAutoScanThirdPartyToolMigration(true);
+ }
+
+ internal static void MaybeRecordLastSeenSetupWizardState(
+ IUnityCliLoopEditorSettingsPort editorSettingsPort,
+ bool shouldRecordState,
+ string version,
+ string minimumDispatcherVersion)
+ {
+ Debug.Assert(editorSettingsPort != null, "editorSettingsPort must not be null");
+
+ if (!shouldRecordState) return;
+
+ Debug.Assert(!string.IsNullOrEmpty(version), "version must not be null or empty");
+ Debug.Assert(
+ !string.IsNullOrEmpty(minimumDispatcherVersion),
+ "minimumDispatcherVersion must not be null or empty");
+
+ editorSettingsPort.UpdateSettings((UnityCliLoopEditorSettingsData settings) => settings with
+ {
+ lastSeenSetupWizardVersion = version,
+ lastSeenSetupWizardMinimumDispatcherVersion = minimumDispatcherVersion
+ });
+ }
+
+ internal static void MaybeRecordSuppressedSetupWizardState(
+ IUnityCliLoopEditorSettingsPort editorSettingsPort,
+ bool suppressAutoShow,
+ string version,
+ string minimumDispatcherVersion)
+ {
+ if (!suppressAutoShow) return;
+
+ MaybeRecordLastSeenSetupWizardState(editorSettingsPort, true, version, minimumDispatcherVersion);
+ }
+
+ internal static bool HasSkillUpdateForSetupWizard(IEnumerable targets)
+ {
+ Debug.Assert(targets != null, "targets must not be null");
+ return targets.Any(
+ target => target.HasSkillsDirectory
+ && (target.InstallState == SkillInstallState.Outdated
+ || target.HasDifferentLayoutSkills));
+ }
+
+ internal void TryShowOnVersionChange()
+ {
+ EvaluateVersionChange(CancellationToken.None);
+ }
+
+ private static bool TryGetMajorVersion(string version, out int majorVersion)
+ {
+ majorVersion = 0;
+ if (string.IsNullOrWhiteSpace(version))
+ {
+ return false;
+ }
+
+ int separatorIndex = version.IndexOfAny(VersionMajorSeparators);
+ string majorText = separatorIndex < 0 ? version : version.Substring(0, separatorIndex);
+ return int.TryParse(majorText, out majorVersion);
+ }
+
+ private async void EvaluateVersionChange(CancellationToken ct)
+ {
+ string currentVersion = UnityCliLoopConstants.PackageInfo.version;
+ string currentMinimumDispatcherVersion = _cliSetupApplicationService.GetMinimumRequiredCliVersion();
+ UnityCliLoopEditorSettingsData settings = _editorSettingsPort.GetSettings();
+ bool suppressAutoShow = settings.suppressSetupWizardAutoShow;
+ string lastSeenVersion = settings.lastSeenSetupWizardVersion ?? string.Empty;
+ string lastSeenMinimumDispatcherVersion =
+ settings.lastSeenSetupWizardMinimumDispatcherVersion ?? string.Empty;
+ if (ct.IsCancellationRequested)
+ {
+ return;
+ }
+
+ bool shouldAutoScanThirdPartyToolMigration = ShouldAutoScanThirdPartyToolMigration(
+ currentVersion,
+ lastSeenVersion);
+ MaybeScheduleThirdPartyToolMigrationAutoScan(shouldAutoScanThirdPartyToolMigration);
+
+ bool versionChanged = !string.Equals(
+ currentVersion,
+ lastSeenVersion,
+ System.StringComparison.Ordinal);
+ bool minimumDispatcherVersionChanged = !string.Equals(
+ currentMinimumDispatcherVersion,
+ lastSeenMinimumDispatcherVersion,
+ System.StringComparison.Ordinal);
+ if (suppressAutoShow)
+ {
+ MaybeRecordSuppressedSetupWizardState(
+ _editorSettingsPort,
+ suppressAutoShow,
+ currentVersion,
+ currentMinimumDispatcherVersion);
+ return;
+ }
+
+ if (!versionChanged && !minimumDispatcherVersionChanged)
+ {
+ return;
+ }
+
+ bool needsCliUpdate = false;
+ bool hasSkillUpdate = false;
+ if (!string.IsNullOrEmpty(lastSeenVersion))
+ {
+ needsCliUpdate = await NeedsCliUpdateForSetupWizardAsync(ct);
+ if (ct.IsCancellationRequested)
+ {
+ return;
+ }
+
+ if (versionChanged && !needsCliUpdate)
+ {
+ hasSkillUpdate = await HasSkillUpdateForSetupWizardAsync(ct);
+ if (ct.IsCancellationRequested)
+ {
+ return;
+ }
+ }
+ }
+
+ bool shouldAutoShow = ShouldAutoShowForVersion(
+ currentVersion,
+ lastSeenVersion,
+ currentMinimumDispatcherVersion,
+ lastSeenMinimumDispatcherVersion,
+ suppressAutoShow,
+ needsCliUpdate,
+ hasSkillUpdate);
+
+ if (!shouldAutoShow)
+ {
+ MaybeRecordLastSeenSetupWizardState(
+ _editorSettingsPort,
+ true,
+ currentVersion,
+ currentMinimumDispatcherVersion);
+ return;
+ }
+
+ EditorApplication.delayCall += () => _showWindowOnVersionChange();
+ }
+
+ private async Task NeedsCliUpdateForSetupWizardAsync(CancellationToken ct)
+ {
+ await _cliSetupApplicationService.ForceRefreshCliVersionAsync(ct);
+ string cliVersion = _cliSetupApplicationService.GetCachedCliVersion();
+ bool cliIsDispatcher = _cliSetupApplicationService.GetCachedCliIsDispatcher();
+ if (string.IsNullOrEmpty(cliVersion))
+ {
+ return false;
+ }
+
+ CliSetupCompatibilityState state = EvaluateCliSetupCompatibility(
+ cliVersion,
+ cliIsDispatcher);
+ return state.NeedsUpdate;
+ }
+
+ private CliSetupCompatibilityState EvaluateCliSetupCompatibility(
+ string cliVersion,
+ bool cliIsDispatcher)
+ {
+ string minimumRequiredCliVersion = _cliSetupApplicationService.GetMinimumRequiredCliVersion();
+ return CliSetupCompatibility.Evaluate(
+ cliVersion,
+ cliIsDispatcher,
+ minimumRequiredCliVersion);
+ }
+
+ private async Task HasSkillUpdateForSetupWizardAsync(CancellationToken ct)
+ {
+ string projectRoot = UnityCliLoopPathResolver.GetProjectRoot();
+ List targets = await Task.Run(
+ () => _skillSetupUseCase.DetectSkillTargetsForLayoutAtProjectRoot(
+ projectRoot,
+ !SetupWizardWindow.ForceFlatSkillInstall),
+ ct);
+ if (ct.IsCancellationRequested)
+ {
+ return false;
+ }
+
+ return HasSkillUpdateForSetupWizard(targets);
+ }
+
+ private void MaybeScheduleThirdPartyToolMigrationAutoScan(bool shouldAutoScan)
+ {
+ MaybeMarkThirdPartyToolMigrationAutoScan(_sessionFlagsRepository, shouldAutoScan);
+ if (!shouldAutoScan)
+ {
+ return;
+ }
+
+ EditorApplication.delayCall += () => _showThirdPartyMigrationAutoScan();
+ }
+ }
+}
diff --git a/Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs.meta b/Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs.meta
new file mode 100644
index 0000000000..8d71315c04
--- /dev/null
+++ b/Packages/src/Editor/Presentation/Setup/SetupWizardStartupFlow.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 62783612b3514214a7a2f1c318d972ad
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/src/Editor/Presentation/Setup/SetupWizardWindow.cs b/Packages/src/Editor/Presentation/Setup/SetupWizardWindow.cs
index e38ed02247..eaa2da9dce 100644
--- a/Packages/src/Editor/Presentation/Setup/SetupWizardWindow.cs
+++ b/Packages/src/Editor/Presentation/Setup/SetupWizardWindow.cs
@@ -24,10 +24,8 @@ public class SetupWizardWindow : EditorWindow
private const string UXML_RELATIVE_PATH = "Editor/Presentation/Setup/SetupWizardWindow.uxml";
private const string USS_RELATIVE_PATH = "Editor/Presentation/Setup/SetupWizardWindow.uss";
private const string GITHUB_ICON_RELATIVE_PATH = "Editor/Presentation/Setup/GitHub_Invertocat_White.png";
- private const bool ForceFlatSkillInstall = true;
- private static readonly char[] VersionMajorSeparators = { '.', '-' };
+ internal const bool ForceFlatSkillInstall = true;
private static IUnityCliLoopEditorSettingsPort RegisteredEditorSettingsPort;
- private static ISessionFlagsRepository RegisteredSessionFlagsRepository;
private static CliSetupApplicationService RegisteredCliSetupApplicationService;
private static SkillSetupUseCase RegisteredSkillSetupUseCase;
@@ -39,31 +37,33 @@ internal static void InitializeForEditorStartup(
{
InitializeEditorServices(
editorSettingsPort,
- sessionFlagsRepository,
cliSetupApplicationService,
skillSetupUseCase);
if (AssetDatabase.IsAssetImportWorkerProcess()) return;
if (UnityEngine.Application.isBatchMode) return;
- EditorApplication.delayCall += TryShowOnVersionChange;
+ SetupWizardStartupFlow startupFlow = new(
+ editorSettingsPort,
+ sessionFlagsRepository,
+ cliSetupApplicationService,
+ skillSetupUseCase,
+ ShowWindowOnVersionChange,
+ ThirdPartyToolMigrationWizardWindow.ShowWindowForAutoScan);
+ EditorApplication.delayCall += startupFlow.TryShowOnVersionChange;
}
internal static void InitializeEditorServices(
IUnityCliLoopEditorSettingsPort editorSettingsPort,
- ISessionFlagsRepository sessionFlagsRepository,
CliSetupApplicationService cliSetupApplicationService,
SkillSetupUseCase skillSetupUseCase)
{
Debug.Assert(editorSettingsPort != null, "editorSettingsPort must not be null");
- Debug.Assert(sessionFlagsRepository != null, "sessionFlagsRepository must not be null");
Debug.Assert(cliSetupApplicationService != null, "cliSetupApplicationService must not be null");
Debug.Assert(skillSetupUseCase != null, "skillSetupUseCase must not be null");
RegisteredEditorSettingsPort = editorSettingsPort
?? throw new System.ArgumentNullException(nameof(editorSettingsPort));
- RegisteredSessionFlagsRepository = sessionFlagsRepository
- ?? throw new System.ArgumentNullException(nameof(sessionFlagsRepository));
RegisteredCliSetupApplicationService = cliSetupApplicationService
?? throw new System.ArgumentNullException(nameof(cliSetupApplicationService));
RegisteredSkillSetupUseCase = skillSetupUseCase
@@ -76,209 +76,6 @@ public static void ShowWindow()
ShowWindowInternal(false);
}
- internal static bool ShouldAutoShowForVersion(
- string currentVersion,
- string lastSeenVersion,
- string currentMinimumDispatcherVersion,
- string lastSeenMinimumDispatcherVersion,
- bool suppressAutoShow,
- bool needsCliUpdate,
- bool hasSkillUpdate)
- {
- bool versionChanged = !string.Equals(currentVersion, lastSeenVersion, System.StringComparison.Ordinal);
- bool minimumDispatcherVersionChanged = !string.Equals(
- currentMinimumDispatcherVersion,
- lastSeenMinimumDispatcherVersion,
- System.StringComparison.Ordinal);
- if (!versionChanged && !minimumDispatcherVersionChanged) return false;
- if (suppressAutoShow) return false;
-
- return string.IsNullOrEmpty(lastSeenVersion)
- || needsCliUpdate
- || (versionChanged && hasSkillUpdate);
- }
-
- internal static bool ShouldAutoScanThirdPartyToolMigration(string currentVersion, string lastSeenVersion)
- {
- if (!TryGetMajorVersion(currentVersion, out int currentMajorVersion))
- {
- return false;
- }
-
- if (string.IsNullOrEmpty(lastSeenVersion))
- {
- return currentMajorVersion == 3;
- }
-
- if (!TryGetMajorVersion(lastSeenVersion, out int lastSeenMajorVersion))
- {
- return false;
- }
-
- return lastSeenMajorVersion < 3 && currentMajorVersion == 3;
- }
-
- internal static void MaybeMarkThirdPartyToolMigrationAutoScan(bool shouldAutoScan)
- {
- if (!shouldAutoScan)
- {
- return;
- }
-
- GetSessionFlagsRepository().SetShouldAutoScanThirdPartyToolMigration(true);
- }
-
- internal static void MaybeRecordLastSeenSetupWizardState(
- bool shouldRecordState,
- string version,
- string minimumDispatcherVersion)
- {
- if (!shouldRecordState) return;
-
- Debug.Assert(!string.IsNullOrEmpty(version), "version must not be null or empty");
- Debug.Assert(
- !string.IsNullOrEmpty(minimumDispatcherVersion),
- "minimumDispatcherVersion must not be null or empty");
-
- GetEditorSettingsPort().UpdateSettings((UnityCliLoopEditorSettingsData settings) => settings with
- {
- lastSeenSetupWizardVersion = version,
- lastSeenSetupWizardMinimumDispatcherVersion = minimumDispatcherVersion
- });
- }
-
- internal static void MaybeRecordSuppressedSetupWizardState(
- bool suppressAutoShow,
- string version,
- string minimumDispatcherVersion)
- {
- if (!suppressAutoShow) return;
-
- MaybeRecordLastSeenSetupWizardState(true, version, minimumDispatcherVersion);
- }
-
- private static void TryShowOnVersionChange()
- {
- EvaluateVersionChange(CancellationToken.None);
- }
-
- private static async void EvaluateVersionChange(CancellationToken ct)
- {
- string currentVersion = UnityCliLoopConstants.PackageInfo.version;
- string currentMinimumDispatcherVersion = GetMinimumRequiredCliVersion();
- IUnityCliLoopEditorSettingsPort editorSettingsPort = GetEditorSettingsPort();
- UnityCliLoopEditorSettingsData settings = editorSettingsPort.GetSettings();
- bool suppressAutoShow = settings.suppressSetupWizardAutoShow;
- string lastSeenVersion = settings.lastSeenSetupWizardVersion ?? string.Empty;
- string lastSeenMinimumDispatcherVersion =
- settings.lastSeenSetupWizardMinimumDispatcherVersion ?? string.Empty;
- if (ct.IsCancellationRequested)
- {
- return;
- }
-
- bool shouldAutoScanThirdPartyToolMigration = ShouldAutoScanThirdPartyToolMigration(
- currentVersion,
- lastSeenVersion);
- MaybeScheduleThirdPartyToolMigrationAutoScan(shouldAutoScanThirdPartyToolMigration);
-
- bool versionChanged = !string.Equals(
- currentVersion,
- lastSeenVersion,
- System.StringComparison.Ordinal);
- bool minimumDispatcherVersionChanged = !string.Equals(
- currentMinimumDispatcherVersion,
- lastSeenMinimumDispatcherVersion,
- System.StringComparison.Ordinal);
- if (suppressAutoShow)
- {
- MaybeRecordSuppressedSetupWizardState(
- suppressAutoShow,
- currentVersion,
- currentMinimumDispatcherVersion);
- return;
- }
-
- if (!versionChanged && !minimumDispatcherVersionChanged)
- {
- return;
- }
-
- bool needsCliUpdate = false;
- bool hasSkillUpdate = false;
- if (!string.IsNullOrEmpty(lastSeenVersion))
- {
- needsCliUpdate = await NeedsCliUpdateForSetupWizardAsync(ct);
- if (ct.IsCancellationRequested)
- {
- return;
- }
-
- if (versionChanged && !needsCliUpdate)
- {
- hasSkillUpdate = await HasSkillUpdateForSetupWizardAsync(ct);
- if (ct.IsCancellationRequested)
- {
- return;
- }
- }
- }
-
- bool shouldAutoShow = ShouldAutoShowForVersion(
- currentVersion,
- lastSeenVersion,
- currentMinimumDispatcherVersion,
- lastSeenMinimumDispatcherVersion,
- suppressAutoShow,
- needsCliUpdate,
- hasSkillUpdate);
-
- if (!shouldAutoShow)
- {
- MaybeRecordLastSeenSetupWizardState(
- true,
- currentVersion,
- currentMinimumDispatcherVersion);
- return;
- }
-
- EditorApplication.delayCall += ShowWindowOnVersionChange;
- }
-
- private static async Task NeedsCliUpdateForSetupWizardAsync(CancellationToken ct)
- {
- CliSetupApplicationService cliSetupApplicationService = GetCliSetupApplicationService();
- await cliSetupApplicationService.ForceRefreshCliVersionAsync(ct);
- string cliVersion = cliSetupApplicationService.GetCachedCliVersion();
- bool cliIsDispatcher = cliSetupApplicationService.GetCachedCliIsDispatcher();
- if (string.IsNullOrEmpty(cliVersion))
- {
- return false;
- }
-
- CliSetupCompatibilityState state = EvaluateCliSetupCompatibilityForSetupWizard(
- cliVersion,
- cliIsDispatcher);
- return state.NeedsUpdate;
- }
-
- private static async Task HasSkillUpdateForSetupWizardAsync(CancellationToken ct)
- {
- string projectRoot = UnityCliLoopPathResolver.GetProjectRoot();
- SkillSetupUseCase skillSetupUseCase = GetSkillSetupUseCase();
- List targets = await Task.Run(
- () => skillSetupUseCase.DetectSkillTargetsForLayoutAtProjectRoot(
- projectRoot,
- !ForceFlatSkillInstall),
- ct);
- if (ct.IsCancellationRequested)
- {
- return false;
- }
-
- return HasSkillUpdateForSetupWizard(targets);
- }
-
private static void ShowWindowOnVersionChange()
{
ShowWindowInternal(true);
@@ -334,7 +131,8 @@ internal static bool TryReuseOpenWindow(
!string.IsNullOrEmpty(currentMinimumDispatcherVersion),
"currentMinimumDispatcherVersion must not be null or empty");
focusExistingWindow();
- MaybeRecordLastSeenSetupWizardState(
+ SetupWizardStartupFlow.MaybeRecordLastSeenSetupWizardState(
+ GetEditorSettingsPort(),
shouldRecordVersion,
currentVersion,
currentMinimumDispatcherVersion);
@@ -373,16 +171,6 @@ private static IUnityCliLoopEditorSettingsPort GetEditorSettingsPort()
return RegisteredEditorSettingsPort;
}
- private static ISessionFlagsRepository GetSessionFlagsRepository()
- {
- if (RegisteredSessionFlagsRepository == null)
- {
- throw new System.InvalidOperationException("Setup Wizard session flags repository is not initialized.");
- }
-
- return RegisteredSessionFlagsRepository;
- }
-
private static CliSetupApplicationService GetCliSetupApplicationService()
{
if (RegisteredCliSetupApplicationService == null)
@@ -404,30 +192,6 @@ private static SkillSetupUseCase GetSkillSetupUseCase()
return RegisteredSkillSetupUseCase;
}
- private static void MaybeScheduleThirdPartyToolMigrationAutoScan(bool shouldAutoScan)
- {
- MaybeMarkThirdPartyToolMigrationAutoScan(shouldAutoScan);
- if (!shouldAutoScan)
- {
- return;
- }
-
- EditorApplication.delayCall += ThirdPartyToolMigrationWizardWindow.ShowWindowForAutoScan;
- }
-
- private static bool TryGetMajorVersion(string version, out int majorVersion)
- {
- majorVersion = 0;
- if (string.IsNullOrWhiteSpace(version))
- {
- return false;
- }
-
- int separatorIndex = version.IndexOfAny(VersionMajorSeparators);
- string majorText = separatorIndex < 0 ? version : version.Substring(0, separatorIndex);
- return int.TryParse(majorText, out majorVersion);
- }
-
// Prerequisite
private VisualElement _nodejsWarning;
private VisualElement _nodejsOk;
@@ -507,7 +271,8 @@ private void InitializeFirstInstallSkillsUiState()
private void RecordLastSeenSetupWizardStateAfterSuccessfulCreateGui()
{
- MaybeRecordLastSeenSetupWizardState(
+ SetupWizardStartupFlow.MaybeRecordLastSeenSetupWizardState(
+ _editorSettingsPort,
_shouldRecordLastSeenVersionAfterCreateGui,
UnityCliLoopConstants.PackageInfo.version,
GetMinimumRequiredCliVersion());
@@ -791,16 +556,6 @@ internal static List FilterInstallableSkillTargets(
.ToList();
}
- internal static bool HasSkillUpdateForSetupWizard(
- IEnumerable targets)
- {
- Debug.Assert(targets != null, "targets must not be null");
- return targets.Any(
- target => target.HasSkillsDirectory
- && (target.InstallState == SkillInstallState.Outdated
- || target.HasDifferentLayoutSkills));
- }
-
internal static bool ShouldShowSkillsInstalledDialog(
IEnumerable targets)
{
@@ -1380,7 +1135,8 @@ private void HandleOpenSettings()
private void HandleSuppressAutoShowChanged(bool suppressAutoShow)
{
_editorSettingsPort.SetSuppressSetupWizardAutoShow(suppressAutoShow);
- MaybeRecordSuppressedSetupWizardState(
+ SetupWizardStartupFlow.MaybeRecordSuppressedSetupWizardState(
+ _editorSettingsPort,
suppressAutoShow,
UnityCliLoopConstants.PackageInfo.version,
GetMinimumRequiredCliVersion());