freezer/lib/ui/login_screen.dart

294 lines
8.8 KiB
Dart
Raw Normal View History

2020-06-23 19:23:12 +00:00
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
2020-10-31 20:52:23 +00:00
import 'package:flutter/services.dart';
2020-06-23 19:23:12 +00:00
import 'package:freezer/api/deezer.dart';
import 'package:freezer/api/player.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:freezer/translations.i18n.dart';
2020-06-23 19:23:12 +00:00
import '../settings.dart';
import '../api/definitions.dart';
import 'home_screen.dart';
class LoginWidget extends StatefulWidget {
Function callback;
LoginWidget({this.callback, Key key}): super(key: key);
@override
_LoginWidgetState createState() => _LoginWidgetState();
}
class _LoginWidgetState extends State<LoginWidget> {
String _arl;
String _error;
2020-06-23 19:23:12 +00:00
//Initialize deezer etc
Future _init() async {
deezerAPI.arl = settings.arl;
await playerHelper.start();
//Pre-cache homepage
if (!await HomePage().exists()) {
await deezerAPI.authorize();
settings.offlineMode = false;
HomePage hp = await deezerAPI.homePage();
await hp.save();
}
}
//Call _init()
void _start() async {
if (settings.arl != null) {
_init().then((_) {
if (widget.callback != null) widget.callback();
});
}
}
@override
void didUpdateWidget(LoginWidget oldWidget) {
_start();
super.didUpdateWidget(oldWidget);
}
@override
void initState() {
_start();
super.initState();
}
void errorDialog() {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Error'.i18n),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Error logging in! Please check your token and internet connection and try again.'.i18n),
if (_error != null)
Text('\n\n$_error')
],
),
2020-06-23 19:23:12 +00:00
actions: <Widget>[
FlatButton(
child: Text('Dismiss'.i18n),
2020-06-23 19:23:12 +00:00
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
}
);
}
void _update() async {
setState(() => {});
//Try logging in
try {
deezerAPI.arl = settings.arl;
bool resp = await deezerAPI.rawAuthorize(onError: (e) => setState(() => _error = e.toString()));
2020-06-23 19:23:12 +00:00
if (resp == false) { //false, not null
if (settings.arl.length != 192) {
if (_error == null) _error = '';
_error += 'Invalid ARL length!';
}
2020-06-23 19:23:12 +00:00
setState(() => settings.arl = null);
errorDialog();
}
//On error show dialog and reset to null
} catch (e) {
_error = e.toString();
print('Login error: ' + e.toString());
2020-06-23 19:23:12 +00:00
setState(() => settings.arl = null);
errorDialog();
}
await settings.save();
_start();
}
2020-10-31 20:52:23 +00:00
// ARL auth: called on "Save" click, Enter and DPAD_Center press
void goARL(FocusNode node, TextEditingController _controller) {
if (node != null) {
node.unfocus();
}
_controller.clear();
settings.arl = _arl.trim();
Navigator.of(context).pop();
_update();
}
2020-06-23 19:23:12 +00:00
@override
Widget build(BuildContext context) {
//If arl non null, show loading
if (settings.arl != null)
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
2020-10-31 20:52:23 +00:00
TextEditingController _controller = new TextEditingController();
// For "DPAD center" key handling on remote controls
FocusNode focusNode = FocusNode(skipTraversal: true,descendantsAreFocusable: false,onKey: (node, event) {
if (event.logicalKey == LogicalKeyboardKey.select) {
goARL(node, _controller);
}
return true;
});
2020-06-23 19:23:12 +00:00
if (settings.arl == null)
return Scaffold(
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: ListView(
children: <Widget>[
Container(height: 16.0,),
Text(
'Welcome to'.i18n,
2020-06-23 19:23:12 +00:00
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16.0
),
),
FreezerTitle(),
Container(height: 8.0,),
Text(
"Please login using your Deezer account.".i18n,
2020-06-23 19:23:12 +00:00
textAlign: TextAlign.center,
style: TextStyle(
2020-07-19 12:41:05 +00:00
fontSize: 16.0
2020-06-23 19:23:12 +00:00
),
),
Container(height: 16.0,),
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.0),
child: OutlineButton(
child: Text('Login using browser'.i18n),
2020-06-23 19:23:12 +00:00
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),
2020-06-23 19:23:12 +00:00
onPressed: () {
showDialog(
context: context,
builder: (context) {
2020-10-31 20:52:23 +00:00
Future.delayed(Duration(seconds: 1), () => {focusNode.requestFocus()}); // autofocus doesn't work - it's replacement
2020-06-23 19:23:12 +00:00
return AlertDialog(
title: Text('Enter ARL'.i18n),
2020-06-23 19:23:12 +00:00
content: Container(
child: TextField(
onChanged: (String s) => _arl = s,
decoration: InputDecoration(
labelText: 'Token (ARL)'.i18n
2020-06-23 19:23:12 +00:00
),
2020-10-31 20:52:23 +00:00
focusNode: focusNode,
controller: _controller,
onSubmitted: (String s) {
goARL(focusNode, _controller);
},
2020-06-23 19:23:12 +00:00
),
),
actions: <Widget>[
FlatButton(
child: Text('Save'.i18n),
2020-10-31 20:52:23 +00:00
onPressed: () => goARL(null, _controller),
2020-06-23 19:23:12 +00:00
)
],
);
}
);
},
),
),
Container(height: 16.0,),
Text(
"If you don't have account, you can register on deezer.com for free.".i18n,
2020-06-23 19:23:12 +00:00
textAlign: TextAlign.center,
style: TextStyle(
2020-07-19 12:41:05 +00:00
fontSize: 16.0
2020-06-23 19:23:12 +00:00
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.0),
child: OutlineButton(
child: Text('Open in browser'.i18n),
2020-06-23 19:23:12 +00:00
onPressed: () {
InAppBrowser.openWithSystemBrowser(url: 'https://deezer.com/register');
},
),
),
Container(height: 8.0,),
Divider(),
Container(height: 8.0,),
Text(
"By using this app, you don't agree with the Deezer ToS".i18n,
2020-06-23 19:23:12 +00:00
textAlign: TextAlign.center,
style: TextStyle(
2020-07-19 12:41:05 +00:00
fontSize: 16.0
2020-06-23 19:23:12 +00:00
),
)
],
),
),
);
return null;
}
}
class LoginBrowser extends StatelessWidget {
Function updateParent;
LoginBrowser(this.updateParent);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: 'https://deezer.com/login',
onLoadStart: (InAppWebViewController controller, String url) async {
2020-09-22 20:22:55 +00:00
//Offers URL
if (!url.contains('/login') && !url.contains('/register')) {
2020-09-22 20:22:55 +00:00
controller.evaluateJavascript(source: 'window.location.href = "/open_app"');
}
2020-06-23 19:23:12 +00:00
//Parse arl from url
if (url.startsWith('intent://deezer.page.link')) {
try {
//Parse url
Uri uri = Uri.parse(url);
//Actual url is in `link` query parameter
Uri linkUri = Uri.parse(uri.queryParameters['link']);
String arl = linkUri.queryParameters['arl'];
if (arl != null) {
settings.arl = arl;
Navigator.of(context).pop();
updateParent();
}
} catch (e) {}
}
},
),
),
),
],
);
}
}