70 lines
2.3 KiB
C#
70 lines
2.3 KiB
C#
namespace NucleicApp.Services;
|
|
|
|
public enum OnboardingPhase
|
|
{
|
|
Idle,
|
|
StartingHost,
|
|
Connecting,
|
|
Ready,
|
|
Failed,
|
|
}
|
|
|
|
/// First-run coordinator for the item-11 core. Component installation and OAuth screens plug
|
|
/// into the same phase surface once their host intents land; host launch + authenticated local
|
|
/// sync are real today.
|
|
public sealed class OnboardingService
|
|
{
|
|
private readonly HostdLauncher launcher;
|
|
private readonly HostConnection connection;
|
|
|
|
public OnboardingPhase Phase { get; private set; } = OnboardingPhase.Idle;
|
|
public string? Failure { get; private set; }
|
|
public event Action<OnboardingPhase>? PhaseChanged;
|
|
|
|
public OnboardingService(HostdLauncher launcher, HostConnection connection)
|
|
{
|
|
this.launcher = launcher;
|
|
this.connection = connection;
|
|
}
|
|
|
|
public async Task StartAsync(string rendezvousPath, CancellationToken cancellationToken = default)
|
|
{
|
|
try
|
|
{
|
|
SetPhase(OnboardingPhase.StartingHost);
|
|
_ = await launcher.EnsureRunningAsync(cancellationToken).ConfigureAwait(false);
|
|
SetPhase(OnboardingPhase.Connecting);
|
|
|
|
var ready = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
void Changed(HostConnectionState state)
|
|
{
|
|
if (state == HostConnectionState.Connected) ready.TrySetResult();
|
|
else if (state == HostConnectionState.Failed)
|
|
ready.TrySetException(new InvalidOperationException(
|
|
connection.LastProtocolState?.Message ?? "local host connection failed"));
|
|
}
|
|
connection.StateChanged += Changed;
|
|
try
|
|
{
|
|
await connection.StartLocalAsync(rendezvousPath, cancellationToken).ConfigureAwait(false);
|
|
await ready.Task.WaitAsync(TimeSpan.FromSeconds(30), cancellationToken).ConfigureAwait(false);
|
|
}
|
|
finally { connection.StateChanged -= Changed; }
|
|
SetPhase(OnboardingPhase.Ready);
|
|
}
|
|
catch (Exception error)
|
|
{
|
|
Failure = error.Message;
|
|
SetPhase(OnboardingPhase.Failed);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private void SetPhase(OnboardingPhase phase)
|
|
{
|
|
if (Phase == phase) return;
|
|
Phase = phase;
|
|
PhaseChanged?.Invoke(phase);
|
|
}
|
|
}
|