import 'package:flutter/material.dart'; import 'package:real_estate_mobile/core/constants/app_colors.dart'; import 'package:real_estate_mobile/core/services/twitter_auth_service.dart'; import 'package:webview_flutter/webview_flutter.dart'; /// Opens a webview for Twitter OAuth 2.0 PKCE login. /// Returns the user data map on success, or null on cancel/failure. class TwitterLoginScreen extends StatefulWidget { const TwitterLoginScreen({super.key}); @override State createState() => _TwitterLoginScreenState(); } class _TwitterLoginScreenState extends State { late final TwitterAuthService _authService; late final WebViewController _webViewController; bool _isExchanging = false; @override void initState() { super.initState(); _authService = TwitterAuthService(); _webViewController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setUserAgent( 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) ' 'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 ' 'Mobile/15E148 Safari/604.1', ) ..setNavigationDelegate(NavigationDelegate( onPageStarted: (url) { final code = _authService.extractCodeFromUrl(url); if (code != null) { _handleCode(code); } }, onNavigationRequest: (request) { final code = _authService.extractCodeFromUrl(request.url); if (code != null) { _handleCode(code); return NavigationDecision.prevent; } // User cancelled — Twitter redirects to main page or login final url = request.url; if (url == 'https://twitter.com/' || url == 'https://x.com/' || url.startsWith('https://twitter.com/home') || url.startsWith('https://x.com/home') || url.startsWith('https://twitter.com/i/flow/login') || url.startsWith('https://x.com/i/flow/login')) { Navigator.pop(context, null); return NavigationDecision.prevent; } return NavigationDecision.navigate; }, )) ..loadRequest(Uri.parse(_authService.authorizationUrl)); } Future _handleCode(String code) async { if (_isExchanging) return; setState(() => _isExchanging = true); try { final userData = await _authService.exchangeCodeForUser(code); if (mounted) Navigator.pop(context, userData); } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('X login failed. Please try again.')), ); Navigator.pop(context, null); } } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SafeArea( child: Column( children: [ // Minimal top bar with back button SizedBox( height: 44, child: Row( children: [ IconButton( icon: const Icon(Icons.arrow_back_ios_new_rounded, size: 18, color: AppColors.primaryDark), onPressed: () => Navigator.pop(context, null), ), const Expanded( child: Text( 'Sign in with X', textAlign: TextAlign.center, style: TextStyle( fontFamily: 'Fractul', fontSize: 15, fontWeight: FontWeight.w600, color: AppColors.primaryDark, ), ), ), const SizedBox(width: 48), ], ), ), // Webview Expanded( child: Stack( children: [ WebViewWidget(controller: _webViewController), if (_isExchanging) Container( color: Colors.white.withValues(alpha: 0.8), child: const Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator( color: AppColors.accentOrange), SizedBox(height: 16), Text('Signing in...', style: TextStyle( fontFamily: 'Fractul', fontSize: 14, color: AppColors.primaryDark, )), ], ), ), ), ], ), ), ], ), ), ); } }