login_screen: redesign

This commit is contained in:
pato05 2021-04-05 00:59:07 +02:00
parent 519adc910f
commit ccb00191ad

View file

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
@ -12,16 +11,14 @@ import '../api/definitions.dart';
import 'home_screen.dart'; import 'home_screen.dart';
class LoginWidget extends StatefulWidget { class LoginWidget extends StatefulWidget {
final Function callback;
Function callback; LoginWidget({this.callback, Key key}) : super(key: key);
LoginWidget({this.callback, Key key}): super(key: key);
@override @override
_LoginWidgetState createState() => _LoginWidgetState(); _LoginWidgetState createState() => _LoginWidgetState();
} }
class _LoginWidgetState extends State<LoginWidget> { class _LoginWidgetState extends State<LoginWidget> {
String _arl; String _arl;
String _error; String _error;
@ -38,6 +35,7 @@ class _LoginWidgetState extends State<LoginWidget> {
await hp.save(); await hp.save();
} }
} }
//Call _init() //Call _init()
void _start() async { void _start() async {
if (settings.arl != null) { if (settings.arl != null) {
@ -50,20 +48,21 @@ class _LoginWidgetState extends State<LoginWidget> {
//Check if deezer available in current country //Check if deezer available in current country
void _checkAvailability() async { void _checkAvailability() async {
bool available = await DeezerAPI.chceckAvailability(); bool available = await DeezerAPI.chceckAvailability();
if (!(available??true)) { if (!(available ?? true)) {
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
title: Text("Deezer is unavailable".i18n), title: Text("Deezer is unavailable".i18n),
content: Text("Deezer is unavailable in your country, Freezer might not work properly. Please use a VPN".i18n), content: Text(
actions: [ "Deezer is unavailable in your country, Freezer might not work properly. Please use a VPN"
TextButton( .i18n),
child: Text('Continue'.i18n), actions: [
onPressed: () => Navigator.of(context).pop(), TextButton(
) child: Text('Continue'.i18n),
], onPressed: () => Navigator.of(context).pop(),
) )
); ],
));
} }
} }
@ -82,29 +81,29 @@ class _LoginWidgetState extends State<LoginWidget> {
void errorDialog() { void errorDialog() {
showDialog( showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: Text('Error'.i18n), title: Text('Error'.i18n),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text('Error logging in! Please check your token and internet connection and try again.'.i18n), Text(
if (_error != null) 'Error logging in! Please check your token and internet connection and try again.'
Text('\n\n$_error') .i18n),
if (_error != null) Text('\n\n$_error')
],
),
actions: <Widget>[
TextButton(
child: Text('Dismiss'.i18n),
onPressed: () {
Navigator.of(context).pop();
},
)
], ],
), );
actions: <Widget>[ });
FlatButton(
child: Text('Dismiss'.i18n),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
}
);
} }
void _update() async { void _update() async {
@ -113,11 +112,13 @@ class _LoginWidgetState extends State<LoginWidget> {
//Try logging in //Try logging in
try { try {
deezerAPI.arl = settings.arl; deezerAPI.arl = settings.arl;
bool resp = await deezerAPI.rawAuthorize(onError: (e) => setState(() => _error = e.toString())); bool resp = await deezerAPI.rawAuthorize(
if (resp == false) { //false, not null onError: (e) => setState(() => _error = e.toString()));
if (resp == false) {
//false, not null
if (settings.arl.length != 192) { if (settings.arl.length != 192) {
if (_error == null) _error = ''; if (_error == null) _error = '';
_error += 'Invalid ARL length!'; _error += 'Invalid ARL length!';
} }
setState(() => settings.arl = null); setState(() => settings.arl = null);
errorDialog(); errorDialog();
@ -147,7 +148,6 @@ class _LoginWidgetState extends State<LoginWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
//If arl non null, show loading //If arl non null, show loading
if (settings.arl != null) if (settings.arl != null)
return Scaffold( return Scaffold(
@ -157,137 +157,146 @@ class _LoginWidgetState extends State<LoginWidget> {
); );
TextEditingController _controller = new TextEditingController(); TextEditingController _controller = new TextEditingController();
// For "DPAD center" key handling on remote controls // For "DPAD center" key handling on remote controls
FocusNode focusNode = FocusNode(skipTraversal: true,descendantsAreFocusable: false,onKey: (node, event) { FocusNode focusNode = FocusNode(
if (event.logicalKey == LogicalKeyboardKey.select) { skipTraversal: true,
goARL(node, _controller); descendantsAreFocusable: false,
} onKey: (node, event) {
return true; if (event.logicalKey == LogicalKeyboardKey.select) {
}); goARL(node, _controller);
}
return true;
});
if (settings.arl == null) if (settings.arl == null)
return Scaffold( return Scaffold(
body: Padding( body: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0), padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0),
child: ListView( child: Theme(
data: Theme.of(context).copyWith(
outlinedButtonTheme: OutlinedButtonThemeData(
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.all(Colors.white)))),
//data: ThemeData(
// outlinedButtonTheme: OutlinedButtonThemeData(
// style: ButtonStyle(
// foregroundColor:
// MaterialStateProperty.all(Colors.white)))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
Container(height: 16.0,), Expanded(
Text( child: Padding(
'Welcome to'.i18n, padding: EdgeInsets.symmetric(horizontal: 32.0),
textAlign: TextAlign.center, child: Column(
style: TextStyle( mainAxisAlignment: MainAxisAlignment.center,
fontSize: 16.0 crossAxisAlignment: CrossAxisAlignment.stretch,
), children: [
), FreezerTitle(),
FreezerTitle(), Container(height: 16.0),
Container(height: 8.0,), Text(
Text( "Please login using your Deezer account.".i18n,
"Please login using your Deezer account.".i18n, textAlign: TextAlign.center,
textAlign: TextAlign.center, style: TextStyle(fontSize: 16.0),
style: TextStyle(
fontSize: 16.0
),
),
Container(height: 16.0,),
//Email login dialog
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.0),
child: OutlineButton(
child: Text(
'Login using email'.i18n,
),
onPressed: () {
showDialog(
context: context,
builder: (context) => EmailLogin(_update)
);
},
)
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.0),
child: OutlineButton(
child: Text('Login using browser'.i18n),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => LoginBrowser(_update))
);
},
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.0),
child: OutlineButton(
child: Text('Login using token'.i18n),
onPressed: () {
showDialog(
context: context,
builder: (context) {
Future.delayed(Duration(seconds: 1), () => {focusNode.requestFocus()}); // autofocus doesn't work - it's replacement
return AlertDialog(
title: Text('Enter ARL'.i18n),
content: Container(
child: TextField(
onChanged: (String s) => _arl = s,
decoration: InputDecoration(
labelText: 'Token (ARL)'.i18n
),
focusNode: focusNode,
controller: _controller,
onSubmitted: (String s) {
goARL(focusNode, _controller);
},
),
), ),
actions: <Widget>[ Container(
FlatButton( height: 16.0,
child: Text('Save'.i18n), ),
onPressed: () => goARL(null, _controller), //Email login dialog
) OutlinedButton(
], child: Text(
); 'Login using email'.i18n,
} ),
); onPressed: () {
}, showDialog(
), context: context,
), builder: (context) => EmailLogin(_update));
Container(height: 16.0,), },
),
OutlinedButton(
child: Text('Login using browser'.i18n),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
LoginBrowser(_update)));
},
),
OutlinedButton(
child: Text('Login using token'.i18n),
onPressed: () {
showDialog(
context: context,
builder: (context) {
Future.delayed(
Duration(seconds: 1),
() => {
focusNode.requestFocus()
}); // autofocus doesn't work - it's replacement
return AlertDialog(
title: Text('Enter ARL'.i18n),
content: Container(
child: TextField(
onChanged: (String s) => _arl = s,
decoration: InputDecoration(
labelText: 'Token (ARL)'.i18n),
focusNode: focusNode,
controller: _controller,
onSubmitted: (String s) {
goARL(focusNode, _controller);
},
),
),
actions: <Widget>[
TextButton(
child: Text('Save'.i18n),
onPressed: () =>
goARL(null, _controller),
)
],
);
});
},
),
]))),
Container(height: 16.0),
Text( Text(
"If you don't have account, you can register on deezer.com for free.".i18n, "If you don't have account, you can register on deezer.com for free."
.i18n,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(fontSize: 16.0),
fontSize: 16.0
),
), ),
Container(height: 8.0),
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 32.0), padding: EdgeInsets.symmetric(horizontal: 32.0),
child: OutlineButton( child: OutlinedButton(
child: Text('Open in browser'.i18n), child: Text('Open in browser'.i18n),
onPressed: () { onPressed: () {
InAppBrowser.openWithSystemBrowser(url: 'https://deezer.com/register'); InAppBrowser.openWithSystemBrowser(
url: 'https://deezer.com/register');
}, },
), ),
), ),
Container(height: 8.0,), Container(
height: 8.0,
),
Divider(), Divider(),
Container(height: 8.0,), Container(
height: 8.0,
),
Text( Text(
"By using this app, you don't agree with the Deezer ToS".i18n, "By using this app, you don't agree with the Deezer ToS".i18n,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(fontSize: 14.0),
fontSize: 16.0
),
) )
], ],
), ),
), ),
); ));
return null; return null;
} }
} }
class LoginBrowser extends StatelessWidget { class LoginBrowser extends StatelessWidget {
final Function updateParent;
Function updateParent;
LoginBrowser(this.updateParent); LoginBrowser(this.updateParent);
@override @override
@ -298,11 +307,12 @@ class LoginBrowser extends StatelessWidget {
child: Container( child: Container(
child: InAppWebView( child: InAppWebView(
initialUrl: 'https://deezer.com/login', initialUrl: 'https://deezer.com/login',
onLoadStart: (InAppWebViewController controller, String url) async { onLoadStart:
(InAppWebViewController controller, String url) async {
//Offers URL //Offers URL
if (!url.contains('/login') && !url.contains('/register')) { if (!url.contains('/login') && !url.contains('/register')) {
controller.evaluateJavascript(source: 'window.location.href = "/open_app"'); controller.evaluateJavascript(
source: 'window.location.href = "/open_app"');
} }
//Parse arl from url //Parse arl from url
@ -330,16 +340,14 @@ class LoginBrowser extends StatelessWidget {
} }
class EmailLogin extends StatefulWidget { class EmailLogin extends StatefulWidget {
final Function callback;
Function callback; EmailLogin(this.callback, {Key key}) : super(key: key);
EmailLogin(this.callback, {Key key}): super(key: key);
@override @override
_EmailLoginState createState() => _EmailLoginState(); _EmailLoginState createState() => _EmailLoginState();
} }
class _EmailLoginState extends State<EmailLogin> { class _EmailLoginState extends State<EmailLogin> {
String _email; String _email;
String _password; String _password;
bool _loading = false; bool _loading = false;
@ -368,20 +376,21 @@ class _EmailLoginState extends State<EmailLogin> {
//Error //Error
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
title: Text("Error logging in!".i18n), title: Text("Error logging in!".i18n),
content: Text("Error logging in using email, please check your credentials.\nError: " + exception), content: Text(
actions: [ "Error logging in using email, please check your credentials.\nError: " +
TextButton( exception),
child: Text('Dismiss'.i18n), actions: [
onPressed: () { TextButton(
Navigator.of(context).pop(); child: Text('Dismiss'.i18n),
}, onPressed: () {
) Navigator.of(context).pop();
], },
) )
); ],
));
} }
@override @override
@ -390,25 +399,22 @@ class _EmailLoginState extends State<EmailLogin> {
title: Text('Email Login'.i18n), title: Text('Email Login'.i18n),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: children: _loading
_loading ? [ ? [CircularProgressIndicator()]
CircularProgressIndicator() : [
]: [ TextField(
TextField( decoration: InputDecoration(labelText: 'Email'.i18n),
decoration: InputDecoration( onChanged: (s) => _email = s,
labelText: 'Email'.i18n ),
), Container(
onChanged: (s) => _email = s, height: 8.0,
), ),
Container(height: 8.0,), TextField(
TextField( obscureText: true,
obscureText: true, decoration: InputDecoration(labelText: "Password".i18n),
decoration: InputDecoration( onChanged: (s) => _password = s,
labelText: "Password".i18n )
), ],
onChanged: (s) => _password = s,
)
],
), ),
actions: [ actions: [
if (!_loading) if (!_loading)
@ -419,10 +425,9 @@ class _EmailLoginState extends State<EmailLogin> {
await _login(); await _login();
else else
Fluttertoast.showToast( Fluttertoast.showToast(
msg: "Missing email or password!".i18n, msg: "Missing email or password!".i18n,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
toastLength: Toast.LENGTH_SHORT toastLength: Toast.LENGTH_SHORT);
);
}, },
) )
], ],