mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-01-05 19:21:23 -06:00
[client] Extract password login fragment
This commit is contained in:
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:js_interop';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:offtheline/offtheline.dart';
|
||||
import 'package:phylum/libphylum/phylum_account.dart';
|
||||
@@ -79,7 +80,7 @@ class _AccountSelectorState extends State<AccountSelector> {
|
||||
context.select<AccountManagerState<PhylumAccount>, PhylumAccount?>((state) => state.selectedAccount);
|
||||
|
||||
if (account == null) {
|
||||
return const LoginPage();
|
||||
return kDebugMode ? const LoginPage() : LoginPage(fixedInstanceUrl: Uri());
|
||||
}
|
||||
return AppLayout.create(account);
|
||||
}
|
||||
|
||||
33
client/lib/ui/login/instance_url_fragment.dart
Normal file
33
client/lib/ui/login/instance_url_fragment.dart
Normal file
@@ -0,0 +1,33 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class InstanceUrlFragment extends StatefulWidget {
|
||||
final Function(Uri) onSubmitted;
|
||||
|
||||
const InstanceUrlFragment({super.key, required this.onSubmitted});
|
||||
|
||||
@override
|
||||
State<InstanceUrlFragment> createState() => _InstanceUrlFragmentState();
|
||||
}
|
||||
|
||||
class _InstanceUrlFragmentState extends State<InstanceUrlFragment> {
|
||||
Uri? _url;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
label: const Text('Instance URL'),
|
||||
hintText: 'http://localhost:2448/',
|
||||
),
|
||||
keyboardType: TextInputType.url,
|
||||
onChanged: (value) => setState(() => _url = kIsWeb && value == '' ? Uri() : Uri.tryParse(value)),
|
||||
onSubmitted: _url == null ? null : (value) => widget.onSubmitted(_url!),
|
||||
),
|
||||
ElevatedButton(onPressed: _url == null ? null : () => widget.onSubmitted(_url!), child: Text('Next'))
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,27 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:phylum/ui/common/logo_row.dart';
|
||||
import 'package:phylum/ui/login/instance_url_fragment.dart';
|
||||
import 'package:phylum/ui/login/password_login_fragment.dart';
|
||||
|
||||
import 'login_request.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
const LoginPage({super.key});
|
||||
final Uri? fixedInstanceUrl;
|
||||
|
||||
const LoginPage({super.key, this.fixedInstanceUrl});
|
||||
|
||||
@override
|
||||
State<LoginPage> createState() => _LoginPageState();
|
||||
}
|
||||
|
||||
class _LoginPageState extends State<LoginPage> {
|
||||
String _email = '';
|
||||
String _password = '';
|
||||
Uri? serverUrl = kIsWeb ? Uri() : null;
|
||||
String? urlError;
|
||||
String? emailError;
|
||||
Uri? _instanceUrl;
|
||||
|
||||
bool get serverUrlValid =>
|
||||
(kIsWeb && serverUrl == Uri()) || (serverUrl?.hasScheme == true && serverUrl?.hasAuthority == true);
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_instanceUrl = widget.fixedInstanceUrl;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -38,60 +40,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
padding: EdgeInsets.only(bottom: 12.0),
|
||||
child: LogoRow(),
|
||||
),
|
||||
if (kDebugMode || !kIsWeb)
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
label: const Text('Server URL'),
|
||||
hintText: 'http://localhost:2448/',
|
||||
errorText: urlError,
|
||||
),
|
||||
keyboardType: TextInputType.url,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
serverUrl = kIsWeb && value == '' ? Uri() : Uri.tryParse(value);
|
||||
urlError = serverUrl == null ? 'Invalid URL' : null;
|
||||
});
|
||||
},
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Email'),
|
||||
),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_email = value.trim();
|
||||
});
|
||||
},
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Password'),
|
||||
),
|
||||
obscureText: true,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_password = value.trim();
|
||||
});
|
||||
},
|
||||
onSubmitted: serverUrlValid
|
||||
? (value) {
|
||||
performLogin(context, serverUrl ?? Uri(), _email, _password);
|
||||
}
|
||||
: null,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: serverUrlValid && _email.isNotEmpty
|
||||
? () async {
|
||||
performLogin(context, serverUrl ?? Uri(), _email, _password);
|
||||
}
|
||||
: null,
|
||||
child: const Text('Login'),
|
||||
),
|
||||
),
|
||||
_buildBody(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -100,4 +49,12 @@ class _LoginPageState extends State<LoginPage> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(BuildContext context) {
|
||||
final instanceUrl = _instanceUrl;
|
||||
if (instanceUrl == null) {
|
||||
return InstanceUrlFragment(onSubmitted: (url) => setState(() => _instanceUrl = url));
|
||||
}
|
||||
return PasswordLoginFragment(onSubmitted: (email, password) => performLogin(context, instanceUrl, email, password));
|
||||
}
|
||||
}
|
||||
|
||||
44
client/lib/ui/login/password_login_fragment.dart
Normal file
44
client/lib/ui/login/password_login_fragment.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PasswordLoginFragment extends StatefulWidget {
|
||||
final Function(String, String) onSubmitted;
|
||||
|
||||
const PasswordLoginFragment({super.key, required this.onSubmitted});
|
||||
|
||||
@override
|
||||
State<PasswordLoginFragment> createState() => _PasswordLoginFragmentState();
|
||||
}
|
||||
|
||||
class _PasswordLoginFragmentState extends State<PasswordLoginFragment> {
|
||||
String _email = '';
|
||||
String _password = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Email'),
|
||||
),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
onChanged: (value) => setState(() => _email = value.trim()),
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
label: Text('Password'),
|
||||
),
|
||||
obscureText: true,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
onChanged: (value) => setState(() => _password = value),
|
||||
onSubmitted: _email.isNotEmpty ? (value) => widget.onSubmitted(_email, _password) : null,
|
||||
),
|
||||
TextButton(onPressed: () {}, child: Text('Forgot Password')),
|
||||
ElevatedButton(
|
||||
onPressed: _email.isEmpty || _password.isEmpty ? null : () => widget.onSubmitted(_email, _password),
|
||||
child: Text('Login'),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user