82 lines
2.2 KiB
Dart
82 lines
2.2 KiB
Dart
import 'dart:convert';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../../../main.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
class SplashScreen extends ConsumerStatefulWidget {
|
|
const SplashScreen({super.key});
|
|
@override
|
|
ConsumerState<SplashScreen> createState() => _SplashState();
|
|
}
|
|
|
|
class _SplashState extends ConsumerState<SplashScreen>
|
|
with SingleTickerProviderStateMixin {
|
|
late final AnimationController _ac = AnimationController(
|
|
vsync: this, duration: const Duration(milliseconds: 600))
|
|
..forward();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_boot();
|
|
}
|
|
|
|
Future<void> _boot() async {
|
|
final tokens = ref.read(tokenStorageProvider);
|
|
final access = await tokens.access;
|
|
var authed = _isJwtValid(access);
|
|
if (!authed) {
|
|
await tokens.refreshAccess();
|
|
authed = _isJwtValid(await tokens.access);
|
|
}
|
|
if (!mounted) return;
|
|
await Future.delayed(
|
|
const Duration(milliseconds: 300)); // kleines Fade-Finish
|
|
if (!mounted) return;
|
|
context.go(authed ? '/igel' : '/login');
|
|
}
|
|
|
|
bool _isJwtValid(String? jwt) {
|
|
if (jwt == null || jwt.isEmpty) return false;
|
|
try {
|
|
final parts = jwt.split('.');
|
|
if (parts.length != 3) return false;
|
|
final payload = jsonDecode(
|
|
utf8.decode(base64Url.decode(base64Url.normalize(parts[1]))))
|
|
as Map<String, dynamic>;
|
|
final exp = (payload['exp'] as num?)?.toInt();
|
|
final now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
|
return exp == null ? true : now < exp - 15;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_ac.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final t = CurvedAnimation(parent: _ac, curve: Curves.easeOut);
|
|
return Scaffold(
|
|
body: FadeTransition(
|
|
opacity: t,
|
|
child: const Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(Icons.pets, size: 96),
|
|
SizedBox(height: 12),
|
|
CircularProgressIndicator(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|