import 'package:flutter/material.dart'; import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:sheetless/api.dart'; import 'package:sheetless/home_page.dart'; import 'package:sheetless/storage_helper.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { final TextEditingController _urlController = TextEditingController( text: "https://sheetable.julian-mutter.de", ); final TextEditingController _emailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); final StorageHelper _storageHelper = StorageHelper(); String? _error; @override void initState() { super.initState(); _checkJwtValidity(); } Future _checkJwtValidity() async { final jwt = await _storageHelper.readSecure(SecureStorageKey.jwt); if (jwt != null) { final isValid = await _validateJwt(jwt); if (isValid) { _navigateToMainPage(); return; } else { final url = await _storageHelper.readSecure(SecureStorageKey.url); final email = await _storageHelper.readSecure(SecureStorageKey.email); final password = await _storageHelper.readSecure( SecureStorageKey.password, ); if (url != null && email != null && password != null) { _login(url, email, password); } } } } Future _validateJwt(String jwt) async { try { bool expired = JwtDecoder.isExpired(jwt); return !expired; } on FormatException { return false; } } Future _login(String serverUrl, String email, String password) async { setState(() { _error = null; }); serverUrl = "$serverUrl/api"; final apiClient = ApiClient(baseUrl: serverUrl); final loginResult = await apiClient.login(email, password); if (loginResult.isOk()) { await _storageHelper.writeSecure(SecureStorageKey.url, serverUrl); await _storageHelper.writeSecure(SecureStorageKey.jwt, apiClient.token!); await _storageHelper.writeSecure(SecureStorageKey.email, email); await _storageHelper.writeSecure(SecureStorageKey.password, password); _navigateToMainPage(); } else { setState(() { _error = "Login failed.\n${loginResult.error()}"; }); } } Future _navigateToMainPage() async { final config = await _storageHelper.readConfig(); Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (_) => MyHomePage(config: config)), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Login')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextField( controller: _urlController, decoration: InputDecoration(labelText: 'Url'), ), TextField( controller: _emailController, decoration: InputDecoration(labelText: 'Email'), ), TextField( controller: _passwordController, decoration: InputDecoration(labelText: 'Password'), obscureText: true, ), if (_error != null) Padding( padding: const EdgeInsets.only(top: 8.0), child: Text(_error!, style: TextStyle(color: Colors.red)), ), SizedBox(height: 16), ElevatedButton( onPressed: () { _login( _urlController.text, _emailController.text, _passwordController.text, ); }, child: Text('Login'), ), ], ), ), ); } }