From 278d3b0cf6a75fdf5662ab47a8064ea3ffa5cc2c Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 26 Aug 2019 10:13:25 +0300 Subject: [PATCH] Create account --- lib/constants.dart | 1 + lib/ui/app/progress_button.dart | 27 ++--- lib/ui/auth/login_view.dart | 193 ++++++++++++++++++-------------- lib/utils/i18n.dart | 10 ++ 4 files changed, 134 insertions(+), 97 deletions(-) diff --git a/lib/constants.dart b/lib/constants.dart index 6db45295e..9a66f46a7 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; // This version must be updated in tandem with the pubspec version. const String kAppVersion = '0.1.47'; +const String kSiteUrl = 'https://invoiceninja.com'; const String kAppUrl = 'https://app.invoiceninja.com'; const String kAppleStoreUrl = diff --git a/lib/ui/app/progress_button.dart b/lib/ui/app/progress_button.dart index 234a28793..a0b8d5c5f 100644 --- a/lib/ui/app/progress_button.dart +++ b/lib/ui/app/progress_button.dart @@ -17,21 +17,18 @@ class ProgressButton extends StatelessWidget { @override Widget build(BuildContext context) { - return Padding( - padding: padding ?? EdgeInsets.only(left: 16.0, right: 16.0, top: 2.0), - child: isLoading - ? Center( - child: SizedBox( - height: 48, - width: 48, - child: CircularProgressIndicator(), - ), - ) - : ElevatedButton( - width: double.infinity, - label: label, - onPressed: () => this.onPressed(), + return isLoading + ? Center( + child: SizedBox( + height: 48, + width: 48, + child: CircularProgressIndicator(), ), - ); + ) + : ElevatedButton( + width: double.infinity, + label: label, + onPressed: () => this.onPressed(), + ); } } diff --git a/lib/ui/auth/login_view.dart b/lib/ui/auth/login_view.dart index 387c82270..abfd7bc63 100644 --- a/lib/ui/auth/login_view.dart +++ b/lib/ui/auth/login_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_state.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart'; import 'package:invoiceninja_flutter/ui/app/progress_button.dart'; @@ -7,6 +8,7 @@ import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart'; +import 'package:url_launcher/url_launcher.dart'; class LoginView extends StatefulWidget { const LoginView({ @@ -33,6 +35,7 @@ class _LoginState extends State { final FocusNode _focusNode1 = new FocusNode(); + bool _createAccount = false; bool _isSelfHosted = false; bool _autoValidate = false; @@ -166,92 +169,118 @@ class _LoginState extends State { focusNode: _focusNode1, onFieldSubmitted: (value) => _submitForm(), ), - _isSelfHosted - ? TextFormField( - controller: _urlController, - key: ValueKey(localization.url), - autocorrect: false, - autovalidate: _autoValidate, - decoration: InputDecoration( - labelText: localization.url), - validator: (val) => - val.isEmpty || val.trim().isEmpty - ? localization.pleaseEnterYourUrl - : null, - keyboardType: TextInputType.url, - ) - : Container(), - _isSelfHosted - ? TextFormField( - controller: _secretController, - key: ValueKey(localization.secret), - autocorrect: false, - decoration: InputDecoration( - labelText: localization.secret), - obscureText: true, - ) - : Container(), - ], - ), - viewModel.authState.error == null || error.contains(OTP_ERROR) - ? Container() - : Container( - padding: EdgeInsets.only(top: 26.0), - child: Center( - child: Text( - viewModel.authState.error, - style: TextStyle( - color: Colors.red, - fontWeight: FontWeight.bold, + if (_isSelfHosted) + TextFormField( + controller: _urlController, + key: ValueKey(localization.url), + autocorrect: false, + autovalidate: _autoValidate, + decoration: InputDecoration( + labelText: localization.url), + validator: (val) => + val.isEmpty || val.trim().isEmpty + ? localization.pleaseEnterYourUrl + : null, + keyboardType: TextInputType.url, + ), + if (_isSelfHosted) + TextFormField( + controller: _secretController, + key: ValueKey(localization.secret), + autocorrect: false, + decoration: InputDecoration( + labelText: localization.secret), + obscureText: true, ), - ), - ), - ), - SizedBox(height: 24.0), - ProgressButton( - padding: EdgeInsets.only(top: 12.0, bottom: 12.0), - isLoading: viewModel.isLoading, - label: localization.login.toUpperCase(), - onPressed: () => _submitForm(), - ), - isOneTimePassword - ? Container() - : Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _isSelfHosted - ? FlatButton( - onPressed: () => - setState(() => _isSelfHosted = false), - child: Text(localization.hostedLogin)) - : FlatButton( - key: ValueKey(localization.selfhostLogin), - onPressed: () => - setState(() => _isSelfHosted = true), - child: Text(localization.selfhostLogin)), - FlatButton( - onPressed: () => viewModel.onGoogleLoginPressed( - context, - _urlController.text, - _secretController.text), - child: Text(localization.googleLogin)), ], ), - isOneTimePassword && !viewModel.isLoading - ? Padding( - padding: EdgeInsets.only(top: 12.0, bottom: 12.0), - child: ElevatedButton( - label: localization.cancel.toUpperCase(), - color: Colors.grey, - onPressed: () { - setState(() { - _oneTimePasswordController.text = ''; - }); - viewModel.onCancel2FAPressed(); - }, + if (viewModel.authState.error != null && + !error.contains(OTP_ERROR)) + Container( + padding: EdgeInsets.only(top: 26.0), + child: Center( + child: Text( + viewModel.authState.error, + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.bold, ), - ) - : Container(), + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 35, bottom: 10), + child: Row( + children: [ + Expanded( + child: ProgressButton( + isLoading: viewModel.isLoading, + label: localization.emailLogin.toUpperCase(), + onPressed: () => _submitForm(), + ), + ), + SizedBox(width: 20), + Expanded( + child: ElevatedButton( + label: localization.googleLogin.toUpperCase(), + onPressed: () => viewModel.onGoogleLoginPressed( + context, + _urlController.text, + _secretController.text), + ), + ), + ], + ), + ), + if (!isOneTimePassword) + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _createAccount + ? FlatButton( + onPressed: () => + setState(() => _createAccount = false), + child: Text(localization.login)) + : FlatButton( + key: ValueKey(localization.selfhostLogin), + onPressed: () => + setState(() => _createAccount = true), + child: Text(localization.createAccount)), + _isSelfHosted + ? FlatButton( + onPressed: () => + setState(() => _isSelfHosted = false), + child: Text(localization.hostedLogin)) + : FlatButton( + key: ValueKey(localization.selfhostLogin), + onPressed: () => + setState(() => _isSelfHosted = true), + child: Text(localization.selfhostLogin)), + FlatButton( + child: Text(localization.viewWebsite), + onPressed: () async { + if (await canLaunch(kSiteUrl)) { + await launch(kSiteUrl, + forceSafariVC: false, forceWebView: false); + } + }, + ), + ], + ), + if (isOneTimePassword && !viewModel.isLoading) + Padding( + padding: EdgeInsets.only(top: 12.0, bottom: 12.0), + child: ElevatedButton( + label: localization.cancel.toUpperCase(), + color: Colors.grey, + onPressed: () { + setState(() { + _oneTimePasswordController.text = ''; + }); + viewModel.onCancel2FAPressed(); + }, + ), + ), ], ), ), diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 098922829..076054679 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -14,6 +14,9 @@ abstract class LocaleCodeAware { mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { + 'view_website': 'View Website', + 'create_account': 'Create Account', + 'email_login': 'Email Login', 'create_new': 'Create New', 'no_record_selected': 'No record selected', 'error_unsaved_changes': 'Please save or cancel your changes', @@ -13803,6 +13806,13 @@ mixin LocalizationsProvider on LocaleCodeAware { String get createNew => _localizedValues[localeCode]['create_new']; + String get emailLogin => _localizedValues[localeCode]['email_login']; + + String get createAccount => _localizedValues[localeCode]['create_account']; + + String get viewWebsite => _localizedValues[localeCode]['view_website']; + + String lookup(String key) { final lookupKey = toSnakeCase(key); return _localizedValues[localeCode][lookupKey] ??