fix: only rebuild AuthGate on actual login state changes

- AuthGate now tracks wasLoggedIn vs isLoggedIn and only calls setState
  when the login status actually flips, preventing token-refresh events
  from tearing down open dialogs and causing _dependents.isEmpty crashes
- Fix TextEditingController disposal order in scanner manual entry dialog
This commit is contained in:
Lukas Müllner 2026-02-23 08:50:39 +01:00
parent 7a6975e146
commit bbcacc0664
2 changed files with 16 additions and 9 deletions

View file

@ -59,18 +59,24 @@ class _AuthGateState extends State<AuthGate> {
// 1. Check for an existing session on cold start.
_session = supabase.auth.currentSession;
// 2. Listen for auth state changes (sign-in, sign-out,
// password-recovery deep link, token refresh, etc.)
// 2. Listen for auth state changes but only rebuild when login
// status actually changes (signed-in signed-out), NOT on
// every token refresh, to avoid tearing down open dialogs.
supabase.auth.onAuthStateChange.listen(
(AuthState authState) {
if (!mounted) return;
setState(() {
_session = authState.session;
});
final wasLoggedIn = _session != null;
final isLoggedIn = authState.session != null;
_session = authState.session;
// Only rebuild the tree when login state actually flips.
if (wasLoggedIn != isLoggedIn) {
setState(() {});
}
// If the user just clicked a password-reset link from their email,
// Supabase fires a PASSWORD_RECOVERY event. We can navigate them
// to a "set new password" screen here.
// Supabase fires a PASSWORD_RECOVERY event.
if (authState.event == AuthChangeEvent.passwordRecovery) {
_showResetPasswordDialog();
}

View file

@ -243,10 +243,11 @@ class _ScannerScreenState extends State<ScannerScreen> {
),
);
controller.dispose();
if (result != null && context.mounted) {
controller.dispose();
Navigator.of(context).pop(result);
} else {
controller.dispose();
}
}
}