import 'package:flutter/material.dart'; import 'package:app_links/app_links.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hl_lieferservice/feature/authentication/bloc/auth_bloc.dart'; import 'package:hl_lieferservice/feature/authentication/bloc/auth_event.dart'; import 'package:url_launcher/url_launcher.dart'; import 'dart:async'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { final _loginFormKey = GlobalKey(); bool _isLoading = false; late AppLinks _appLinks; StreamSubscription? _linkSubscription; @override void initState() { super.initState(); _appLinks = AppLinks(); } @override void dispose() { _linkSubscription?.cancel(); super.dispose(); } void _onPressLogin() async { setState(() => _isLoading = true); try { debugPrint("🔵 Setting up deep link listener..."); final completer = Completer(); // Listen for deep links BEFORE opening browser _linkSubscription = _appLinks.uriLinkStream.listen( (Uri uri) { debugPrint("🟢 Deep link received: $uri"); if (uri.scheme == 'myapp' && !completer.isCompleted) { completer.complete(uri); } }, onError: (err) { debugPrint("🔴 Deep link error: $err"); if (!completer.isCompleted) { completer.completeError(err); } }, ); // Small delay to ensure listener is ready await Future.delayed(const Duration(milliseconds: 500)); debugPrint("🔵 Opening browser to: http://localhost:3000/login"); final loginUrl = Uri.parse('http://192.168.1.9:3000/login'); final launched = await launchUrl( loginUrl, mode: LaunchMode.externalApplication, ); if (!launched) { throw Exception('Could not launch browser'); } debugPrint("🔵 Browser opened. Waiting for callback..."); // Wait for the deep link callback final callbackUri = await completer.future.timeout( const Duration(minutes: 5), onTimeout: () { debugPrint("⏱️ Timeout - no callback received"); throw TimeoutException('Login timeout'); }, ); final sessionId = callbackUri.queryParameters['session_id']!; debugPrint("✅ Success! Callback: $callbackUri"); debugPrint("✅ Session ID: $sessionId"); await _linkSubscription?.cancel(); _linkSubscription = null; if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Login erfolgreich!'), backgroundColor: Colors.green, ), ); context.read().add(SetAuthenticatedEvent(sessionId: sessionId)); } } on TimeoutException { debugPrint("❌ Timeout"); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Login Timeout')), ); } } catch (e) { debugPrint("❌ Error: $e"); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Fehler: $e')), ); } } finally { await _linkSubscription?.cancel(); _linkSubscription = null; if (mounted) { setState(() => _isLoading = false); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(50), child: Column( children: [ Image.asset( "assets/holzleitner_Logo_2017_RZ_transparent.png", ), const Padding( padding: EdgeInsets.only(top: 20), child: Text( "Auslieferservice", style: TextStyle( fontWeight: FontWeight.w400, fontSize: 20, ), ), ), ], ), ), Form( key: _loginFormKey, child: FractionallySizedBox( widthFactor: 0.8, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(top: 15, bottom: 15), child: _isLoading ? const Column( children: [ CircularProgressIndicator(), SizedBox(height: 16), Text('Warte auf Login...'), ], ) : OutlinedButton( onPressed: _onPressLogin, child: const Text("Anmelden mit Holzleitner Login"), ), ), ], ), ), ), ], ), ), ); } }