feat(auth): Login-Timeout (10s) mit Hinweisbanner

Haengt der interaktive Login (Browser-Tab/Token-Exchange) bei Verbindungsabbruch/Issuer-Hang, bricht er nach 10s ab; LoginPage zeigt 'Einloggen nicht moeglich. Spaeter erneut versuchen.' (Unauthenticated.loginTimedOut).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dennis Nemec
2026-06-18 13:08:18 +02:00
parent 7544760c34
commit 467f4b4ed2
4 changed files with 55 additions and 5 deletions

View File

@ -12,10 +12,19 @@ import 'package:hl_lieferservice/feature/authentication/bloc/auth_state.dart';
/// Browser-Tab, der RedirectURI `holzleitner://oauth2redirect` kommt
/// zurück, der Code wird gegen Tokens getauscht.
class LoginPage extends StatelessWidget {
const LoginPage({super.key, this.sessionExpired = false});
const LoginPage({
super.key,
this.sessionExpired = false,
this.loginTimedOut = false,
});
final bool sessionExpired;
/// Hinweis-Banner, dass der vorherige Login-Versuch ins 10-s-Timeout
/// gelaufen ist (typisch: Verbindungsabbruch oder hängender Issuer).
/// Wird vom `LoginEnforcer` aus `Unauthenticated.loginTimedOut` gefüttert.
final bool loginTimedOut;
@override
Widget build(BuildContext context) {
return Scaffold(
@ -36,6 +45,20 @@ class LoginPage extends StatelessWidget {
),
actions: const [SizedBox.shrink()],
),
if (loginTimedOut)
MaterialBanner(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
content: const Text(
'Einloggen nicht möglich. Später erneut versuchen.',
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.red.shade700,
leading: const Icon(
Icons.cloud_off,
color: Colors.white,
),
actions: const [SizedBox.shrink()],
),
Expanded(
child: Center(
child: Column(