execute method
- void onSubProgress(
- double subFraction
override
Performs the startup work for this task.
Called by StartupOrchestrator exactly once per startup. Must complete without error for the orchestrator to proceed to the next task.
The optional onSubProgress callback lets a task report intra-task
progress as a fraction in the range [0.0, 1.0]. The orchestrator maps
this to a global progress fraction and forwards it to StartupCubit so
the splash screen can animate continuously during long-running tasks.
Tasks that do not have meaningful sub-steps can ignore this parameter.
Implementation
@override
Future<void> execute({void Function(double subFraction)? onSubProgress}) async {
_logger.info('[AuthCheckTask] Starting auth check');
// Sub-progress 10%: about to hit storage/network for token + user resolution.
onSubProgress?.call(0.1);
// Step 1: Resolve initial status — token inspection, user fetch/fallback,
// and the resolved user are all returned together to avoid a second fetch.
final (AuthenticationStatus status, UserModel? user) = await _authRepository.resolveInitialStatus();
// Sub-progress 50%: token validated and user resolved (the heaviest async step).
onSubProgress?.call(0.5);
// Step 2: Subscribe to the stream BEFORE dispatching the event so we cannot
// miss the state transition in the microtask gap between the dispatch and
// a check-then-subscribe pattern. The future is only awaited in Step 3.
final Future<AuthenticationState>? settleFuture = _authenticationBloc.state.status == AuthenticationStatus.unknown
? _authenticationBloc.stream
.firstWhere((AuthenticationState s) => s.status != AuthenticationStatus.unknown)
.timeout(
const Duration(seconds: 10),
onTimeout: () => throw TimeoutException('[AuthCheckTask] Timed out waiting for AuthenticationBloc to leave unknown state'),
)
: null;
// Seed the bloc now — the stream subscription is already live above.
_authenticationBloc.add(StartupAuthResolved(status: status, user: user));
// Sub-progress 70%: startup event dispatched, waiting for bloc to settle.
onSubProgress?.call(0.7);
// Step 3: Await the pre-subscribed future (null means bloc was already settled).
if (settleFuture != null) {
await settleFuture;
}
// Sub-progress 90%: bloc settled, about to activate live streams.
onSubProgress?.call(0.9);
// Step 4: Now safe to start live listening — startup is fully settled.
_authenticationBloc.add(const StartLiveListening());
_logger.info(
'[AuthCheckTask] Auth check complete — '
'status: $status',
);
}