From 27a5bc16bc949a60d16cf2c58ab34ade123c0050 Mon Sep 17 00:00:00 2001 From: Mark M2 Macbook Date: Tue, 2 Jun 2026 10:20:25 +0200 Subject: [PATCH] ricostruzione sessione manuale per aggirare gorouter che distrugge il token --- lib/features/auth/ui/set_password_screen.dart | 60 ++++++++++++++++--- lib/main.dart | 10 +++- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/lib/features/auth/ui/set_password_screen.dart b/lib/features/auth/ui/set_password_screen.dart index df24a20..67d630b 100644 --- a/lib/features/auth/ui/set_password_screen.dart +++ b/lib/features/auth/ui/set_password_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flux/main.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; class SetPasswordScreen extends StatefulWidget { @@ -16,6 +17,15 @@ class _SetPasswordScreenState extends State { bool _obscurePassword = true; String? _errorMessage; + // Variabile per abilitare l'inserimento + bool _isSessionReady = false; + + @override + void initState() { + super.initState(); + _forceSessionRecovery(); + } + @override void dispose() { _passwordController.dispose(); @@ -23,17 +33,58 @@ class _SetPasswordScreenState extends State { super.dispose(); } + // 🎯 LA VERA MAGIA: RICOSTRUIAMO LA SESSIONE A MANO + Future _forceSessionRecovery() async { + try { + // 1. Prendiamo il frammento dalla cassaforte + final fragment = initialRecoveryFragment ?? Uri.base.fragment; + + if (fragment.contains('access_token=')) { + // 2. Dividiamo la stringa in una mappa chiave:valore + final params = Uri.splitQueryString(fragment); + final refreshToken = params['refresh_token']; + + if (refreshToken != null) { + // 3. Forziamo Supabase a loggare l'utente col refresh token! + await Supabase.instance.client.auth.setSession(refreshToken); + + if (mounted) { + setState(() { + _isSessionReady = true; + _errorMessage = null; + }); + } + return; + } + } + + // Fallback: se Supabase ce l'aveva già fatta miracolosamente + if (Supabase.instance.client.auth.currentSession != null) { + setState(() => _isSessionReady = true); + } + } catch (e) { + print("Errore ripristino manuale sessione: $e"); + } + } + Future _submitNewPassword() async { if (!_formKey.currentState!.validate()) return; + if (!_isSessionReady) { + setState(() { + _errorMessage = + "Sincronizzazione di sicurezza fallita. Il link potrebbe essere scaduto."; + }); + return; + } + setState(() { _isLoading = true; _errorMessage = null; }); try { - // 🥷 LA MOFFA DEL NINJA: Aggiorniamo la password dell'utente corrente - // che si è loggato in automatico grazie al token nell'URL + // Ora questo updateUser troverà la sessione viva e vegeta! await Supabase.instance.client.auth.updateUser( UserAttributes(password: _passwordController.text.trim()), ); @@ -47,11 +98,6 @@ class _SetPasswordScreenState extends State { backgroundColor: Colors.green, ), ); - - // Non serve forzare i redirect qui! - // Il SessionCubit nel costruttore ha un listener su 'onAuthStateChange'. - // Sentirà che l'utente ora è perfettamente valido, richiamerà 'initializeSession()' - // e lo scaricherà automaticamente nella pagina di Onboarding corretta. } } on AuthException catch (e) { setState(() { diff --git a/lib/main.dart b/lib/main.dart index 7ef6077..2296470 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'dart:developer'; import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; @@ -48,9 +49,16 @@ import 'package:flux/features/settings/ui/settings.dart'; import 'package:flutter_web_plugins/url_strategy.dart'; import 'package:url_launcher/url_launcher.dart'; +String? initialRecoveryFragment; void main() async { WidgetsFlutterBinding.ensureInitialized(); - print("URL VERO ALL'AVVIO: ${Uri.base.toString()}"); + final initialUri = Uri.base; + if (initialUri.fragment.contains('access_token=')) { + initialRecoveryFragment = initialUri.fragment; + log( + "Ninja attivato: Token catturato in cassaforte! $initialRecoveryFragment", + ); + } await dotenv.load(fileName: ".env"); // Inizializza le dipendenze PRIMA di lanciare l'app