import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'mainpage.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'config.dart'; Future main() async { await dotenv.load(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return FutureBuilder( future: SharedPreferences.getInstance(), builder: (context, snapshot) { if (!snapshot.hasData) { return const CircularProgressIndicator(); } final prefs = snapshot.data!; final jwt = prefs.getString('jwt'); return MaterialApp( title: 'Litecloud alpha', theme: ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: const Color.fromARGB(255, 72, 4, 117)), useMaterial3: true, ), home: jwt != null ? const MainPage() : const AuthScreen(), ); }, ); } } class AuthScreen extends StatefulWidget { const AuthScreen({super.key}); @override State createState() => _AuthScreenState(); } class _AuthScreenState extends State { bool _isLogin = true; final _emailController = TextEditingController(); final _passwordController = TextEditingController(); final _confirmController = TextEditingController(); bool _loading = false; String? _error; void _toggleAuthMode() { setState(() { _isLogin = !_isLogin; _error = null; }); } Future _submit() async { setState(() { _loading = true; _error = null; }); final email = _emailController.text.trim(); final password = _passwordController.text.trim(); if (!_isLogin && password != _confirmController.text.trim()) { setState(() { _error = "Le password non coincidono"; _loading = false; }); return; } final url = Uri.parse('${Config.apiUrl}/${_isLogin ? "login" : "register"}'); final body = jsonEncode({ "username": email, "password": password, }); try { final response = await http.post( url, headers: {'Content-Type': 'application/json'}, body: body, ); if (response.statusCode == 200 || response.statusCode == 201) { final data = jsonDecode(response.body); final token = data['token']; final prefs = await SharedPreferences.getInstance(); await prefs.setString('jwt', token); if (mounted) { Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (_) => const MainPage()), ); } } else { setState(() { _error = "Credenziali non valide"; }); } } catch (e) { setState(() { _error = "Errore di rete"; }); } finally { setState(() { _loading = false; }); } } @override Widget build(BuildContext context) { final deviceSize = MediaQuery.of(context).size; return Scaffold( body: Container( width: deviceSize.width, height: deviceSize.height, decoration: const BoxDecoration( gradient: LinearGradient( colors: [Colors.purple, Color.fromARGB(255, 72, 4, 117)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: SafeArea( child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 60), // Logo and tagline Container( margin: const EdgeInsets.only(bottom: 40.0), child: Column( children: [ Text( 'Litecloud', style: TextStyle( fontSize: 42, fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.onPrimary, ), ), const SizedBox(height: 8), Text( 'Rust based cloud storage', style: TextStyle( fontSize: 16, color: Theme.of(context).colorScheme.onPrimary, ), ), const SizedBox(height: 8), Text( 'Version 0.0.1 pre-alpha', style: TextStyle( fontSize: 8, color: Theme.of(context).colorScheme.onPrimary, ), ), ], ), ), // Auth card Card( margin: const EdgeInsets.symmetric(horizontal: 600.0), elevation: 8.0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.0), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Text( _isLogin ? 'Login' : 'Register', style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox(height: 40), TextFormField( controller: _emailController, decoration: const InputDecoration( labelText: 'Username', prefixIcon: Icon(Icons.person), border: OutlineInputBorder(), ), keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 16), TextFormField( controller: _passwordController, decoration: const InputDecoration( labelText: 'Password', prefixIcon: Icon(Icons.lock), border: OutlineInputBorder(), ), obscureText: true, ), if (!_isLogin) const SizedBox(height: 16), if (!_isLogin) TextFormField( controller: _confirmController, decoration: const InputDecoration( labelText: 'Confirm Password', prefixIcon: Icon(Icons.lock), border: OutlineInputBorder(), ), obscureText: true, ), const SizedBox(height: 24), FilledButton( onPressed: _loading ? null : _submit, style: FilledButton.styleFrom( minimumSize: const Size(double.infinity, 50), ), child: _loading ? const CircularProgressIndicator() : Text( _isLogin ? 'LOGIN' : 'REGISTER', style: const TextStyle(fontSize: 16), ), ), if (_error != null) Padding( padding: const EdgeInsets.only(top: 8.0), child: Text(_error!, style: const TextStyle(color: Colors.red)), ), const SizedBox(height: 12), TextButton( onPressed: _toggleAuthMode, child: Text( _isLogin ? 'Create new account' : 'I already have an account', ), ), ], ), ), ), ], ), ), ), ), ), ); } }