import 'dart:async'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../../../common/router/app_router.dart'; import 'auth_controller.dart'; import 'one_key_login_service.dart'; /// Shared login entry: launch the carrier-owned authorization page first and /// use the Flutter SMS page only as a deliberate fallback. abstract final class LoginLauncher { static final _service = OneKeyLoginService(); static bool _starting = false; static Future start( BuildContext context, WidgetRef ref, { String? next, }) async { if (_starting) return; _starting = true; final dismissLoading = _showLoading(context); try { final observer = _OneKeyLoginLifecycleObserver(_service); WidgetsBinding.instance.addObserver(observer); late final OneKeyLoginOutcome outcome; try { outcome = await _service.start( context: context, verifyToken: ref.read(authProvider.notifier).verifyOneKeyLogin, onNativeRequestDispatched: dismissLoading, onAuthPageOpened: dismissLoading, ); } catch (_) { outcome = OneKeyLoginOutcome.fallback; } finally { WidgetsBinding.instance.removeObserver(observer); } if (!context.mounted) return; if (outcome == OneKeyLoginOutcome.success) { context.go(next?.isNotEmpty == true ? next! : AppRoutes.profile); return; } if (outcome == OneKeyLoginOutcome.fallback || outcome == OneKeyLoginOutcome.unsupported) { final target = next == null || next.isEmpty ? AppRoutes.login : '${AppRoutes.login}?next=${Uri.encodeComponent(next)}'; if (GoRouterState.of(context).matchedLocation != AppRoutes.login) { await context.push(target); } } } finally { dismissLoading(); _starting = false; } } static VoidCallback _showLoading(BuildContext context) { var visible = true; unawaited( showDialog( context: context, useRootNavigator: true, barrierDismissible: false, builder: (_) => const PopScope( canPop: false, child: Center(child: CircularProgressIndicator()), ), ), ); return () { if (visible && context.mounted) { Navigator.of(context, rootNavigator: true).pop(); } visible = false; }; } } class _OneKeyLoginLifecycleObserver with WidgetsBindingObserver { _OneKeyLoginLifecycleObserver(this._service); final OneKeyLoginService _service; @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) _service.onAppResumed(); } }