import 'dart:html'; import 'package:flutter/material.dart'; import 'package:grpc/grpc_web.dart'; import 'package:softplayer_web/api/grpc/accounts.dart'; class LoginForm extends StatefulWidget { const LoginForm({ super.key, required this.grpcChannel, }); final GrpcWebClientChannel grpcChannel; @override State createState() => _LoginFormState(); } enum Action { singIn, signUp } class _LoginFormState extends State { final _formKey = GlobalKey(); final usernameCtrl = TextEditingController(); final passwordCtrl = TextEditingController(); final passwordVerifyCtrl = TextEditingController(); final emailCtrl = TextEditingController(); late AccountsGrpc accountsGrpc; Action action = Action.singIn; static const dialogName = "Login"; void submitSignUp() { // Validate returns true if the form is valid, or false otherwise. if (_formKey.currentState!.validate()) { final username = usernameCtrl.text; final password = passwordCtrl.text; final email = emailCtrl.text; accountsGrpc.signUp(username, email, password).then((rs) { window.localStorage["token"] = rs.token; window.localStorage["uuid"] = rs.uuid; Navigator.of(context, rootNavigator: true).pop(); }).catchError((e) { GrpcError error = e; String msg; if (error.message != null) { msg = error.message!; } else { msg = error.toString(); } ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(msg), backgroundColor: Colors.red, showCloseIcon: true, behavior: SnackBarBehavior.floating, )); passwordCtrl.clear(); }); } } void submitSignIn() { // Validate returns true if the form is valid, or false otherwise. if (_formKey.currentState!.validate()) { final username = usernameCtrl.text; final password = passwordCtrl.text; accountsGrpc.signIn(username, "", password).then((rs) { window.localStorage["token"] = rs.token; window.localStorage["uuid"] = rs.uuid; Navigator.of(context, rootNavigator: true).pop(); }).catchError((e) { print(e); GrpcError error = e; String msg; if (error.message != null) { msg = error.message!; } else { msg = error.toString(); } ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(msg), backgroundColor: Colors.red, showCloseIcon: true, behavior: SnackBarBehavior.floating, )); passwordCtrl.clear(); }); } } Widget signInForm() => SizedBox( width: 420, height: 280, child: Form( key: _formKey, child: Center( child: Column(children: [ TextFormField( autofocus: true, controller: usernameCtrl, decoration: const InputDecoration( hintText: "Enter your username", icon: Icon(Icons.account_circle), label: Text("Username"), ), cursorWidth: 1, cursorHeight: 18, cursorRadius: const Radius.circular(10), ), TextFormField( controller: passwordCtrl, obscureText: true, decoration: const InputDecoration( hintText: "Enter your password", icon: Icon(Icons.password), label: Text("Password")), cursorWidth: 1, cursorHeight: 18, cursorRadius: const Radius.circular(10), ), ])))); List signInActions() => [ TextButton( onPressed: () => setState(() { action = Action.signUp; }), child: const Text('Sing Up'), ), TextButton( onPressed: submitSignIn, child: const Text('OK'), ), ]; List signUpActions() => [ TextButton( onPressed: () => setState(() { action = Action.singIn; }), child: const Text('Sing In'), ), TextButton( onPressed: submitSignUp, child: const Text('OK'), ), ]; Widget signUpForm() => SizedBox( width: 420, height: 280, child: Form( key: _formKey, child: Center( child: Column(children: [ TextFormField( autofocus: true, controller: usernameCtrl, decoration: const InputDecoration( hintText: "Enter your username", icon: Icon(Icons.account_circle), label: Text("Username"), ), cursorWidth: 1, cursorHeight: 18, cursorRadius: const Radius.circular(10), ), TextFormField( controller: emailCtrl, autofocus: true, decoration: const InputDecoration( hintText: "Enter your email", icon: Icon(Icons.email), label: Text("Email"), ), cursorWidth: 1, cursorHeight: 18, cursorRadius: const Radius.circular(10), ), TextFormField( controller: passwordCtrl, obscureText: true, decoration: const InputDecoration( hintText: "Enter your password", icon: Icon(Icons.password), label: Text("Password")), cursorWidth: 1, cursorHeight: 18, cursorRadius: const Radius.circular(10), ), TextFormField( controller: passwordVerifyCtrl, obscureText: true, decoration: const InputDecoration( hintText: "Verify your password", icon: Icon(Icons.password), label: Text("Confirm Password")), cursorWidth: 1, cursorHeight: 18, cursorRadius: const Radius.circular(10), ), ])))); @override void initState() { super.initState(); accountsGrpc = AccountsGrpc(channel: widget.grpcChannel); accountsGrpc.init(); } @override Widget build(BuildContext context) => AlertDialog( title: const Text(dialogName), content: action == Action.singIn ? signInForm() : signUpForm(), actions: action == Action.singIn ? signInActions() : signUpActions(), ); }