initial codex commit
Some checks failed
Release / build (push) Failing after 48s
Release / release-dev (push) Has been skipped
Release / release-master (push) Has been skipped
Release / windows-build (push) Has been cancelled

This commit is contained in:
2025-12-11 01:08:30 +00:00
parent e6d7e71a36
commit 40ee16d2d5
20 changed files with 2902 additions and 283 deletions

View File

@@ -13,7 +13,6 @@ class LoginScreen extends StatelessWidget {
color: Theme.of(context).scaffoldBackgroundColor,
child: Center(
child: Column(
spacing: 50,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text.rich(
@@ -39,14 +38,15 @@ class LoginScreen extends StatelessWidget {
style: TextStyle(
decoration: TextDecoration.none,
color: Colors.white,
fontFamily: "Tomatoes",
fontSize: 50,
),
fontFamily: "Tomatoes",
fontSize: 50,
),
),
LoginPanel(),
],
),
),
const SizedBox(height: 50),
LoginPanel(),
],
),
),
),
);
@@ -115,7 +115,7 @@ class _LoginPanelContentState extends State<LoginPanelContent> {
bool _loggingIn = false;
void login() async {
Future<void> login() async {
final username = _usernameController.text;
final password = _passwordController.text;
@@ -126,19 +126,18 @@ class _LoginPanelContentState extends State<LoginPanelContent> {
});
try {
await auth.login(username, password);
print('Login successful');
if (!mounted) return;
setState(() {
_loggingIn = false;
});
} catch (e) {
// Handle error
print('Login failed: $e');
if (!mounted) return;
setState(() {
_loggingIn = false;
});
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('Login failed')));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Login failed: $e')),
);
}
}
@@ -163,7 +162,6 @@ class _LoginPanelContentState extends State<LoginPanelContent> {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 50),
@@ -172,6 +170,7 @@ class _LoginPanelContentState extends State<LoginPanelContent> {
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
),
const SizedBox(height: 8),
TextFormField(
controller: _usernameController,
decoration: InputDecoration(
@@ -180,6 +179,7 @@ class _LoginPanelContentState extends State<LoginPanelContent> {
),
onFieldSubmitted: (_) => login(),
),
const SizedBox(height: 8),
TextFormField(
controller: _passwordController,
obscureText: true,
@@ -189,11 +189,12 @@ class _LoginPanelContentState extends State<LoginPanelContent> {
),
onFieldSubmitted: (_) => login(),
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 10,
children: [
FilledButton(onPressed: login, child: loginButtonContent),
const SizedBox(width: 10),
ElevatedButton(
onPressed: widget.registerCb,
child: Text("Register"),
@@ -205,7 +206,7 @@ class _LoginPanelContentState extends State<LoginPanelContent> {
}
}
class RegisterPanelContent extends StatelessWidget {
class RegisterPanelContent extends StatefulWidget {
const RegisterPanelContent({
super.key,
required this.onBack,
@@ -213,20 +214,64 @@ class RegisterPanelContent extends StatelessWidget {
});
final VoidCallback onBack;
final AuthService authService;
void register() {}
@override
State<RegisterPanelContent> createState() => _RegisterPanelContentState();
}
class _RegisterPanelContentState extends State<RegisterPanelContent> {
final _usernameController = TextEditingController();
final _displayNameController = TextEditingController();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _inviteController = TextEditingController();
bool _registering = false;
@override
void dispose() {
_usernameController.dispose();
_displayNameController.dispose();
_emailController.dispose();
_passwordController.dispose();
_inviteController.dispose();
super.dispose();
}
Future<void> _register() async {
setState(() => _registering = true);
try {
await widget.authService.register(
username: _usernameController.text.trim(),
email: _emailController.text.trim(),
fullName: _displayNameController.text.trim(),
password: _passwordController.text,
inviteCode: _inviteController.text.trim(),
);
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Registration successful. Please log in.')),
);
widget.onBack();
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Registration failed: $e')),
);
} finally {
if (mounted) setState(() => _registering = false);
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
Row(
children: [
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: onBack,
icon: const Icon(Icons.arrow_back),
onPressed: widget.onBack,
tooltip: 'Back to login',
),
Expanded(
@@ -237,47 +282,64 @@ class RegisterPanelContent extends StatelessWidget {
),
),
),
// Spacer to balance the row visually
SizedBox(width: 48), // matches IconButton size
const SizedBox(width: 48),
],
),
SizedBox(height: 16),
const SizedBox(height: 16),
TextField(
decoration: InputDecoration(
controller: _usernameController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Username",
),
),
const SizedBox(height: 8),
TextField(
decoration: InputDecoration(
controller: _displayNameController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Display Name",
),
),
const SizedBox(height: 8),
TextField(
decoration: InputDecoration(
controller: _emailController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Email",
),
),
const SizedBox(height: 8),
TextField(
controller: _passwordController,
obscureText: true,
decoration: InputDecoration(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Password",
),
),
const SizedBox(height: 8),
TextField(
decoration: InputDecoration(
controller: _inviteController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Invite Code",
),
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 10,
children: [
FilledButton(onPressed: register, child: Text("Register")),
FilledButton(
onPressed: _registering ? null : _register,
child: _registering
? const SizedBox(
height: 14,
width: 14,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text("Register"),
),
],
),
],