Google login

This commit is contained in:
Hillel Coren 2018-08-14 23:02:34 -07:00
parent 1e76adbdd2
commit 3eb618c5e0
8 changed files with 97 additions and 41 deletions

1
.gitignore vendored
View File

@ -14,3 +14,4 @@ build/
.env.dart
key.properties
google-services.json

View File

@ -12,6 +12,7 @@ if (flutterRoot == null) {
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystorePropertiesFile = rootProject.file("key.properties")

View File

@ -6,6 +6,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.google.gms:google-services:3.2.1'
}
}

View File

@ -5,7 +5,6 @@ import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_email_view.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:redux/redux.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/redux/auth/auth_state.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart';
import 'package:invoiceninja_flutter/ui/app/progress_button.dart';
import 'package:invoiceninja_flutter/ui/auth/login_vm.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
@ -9,15 +10,11 @@ import 'package:invoiceninja_flutter/utils/keys.dart';
class LoginView extends StatefulWidget {
final bool isLoading;
final AuthState authState;
final Function(BuildContext, String, String, String, String) onLoginPressed;
final LoginVM viewModel;
const LoginView({
Key key,
@required this.isLoading,
@required this.authState,
@required this.onLoginPressed,
@required this.viewModel,
}) : super(key: key);
@override
@ -40,7 +37,7 @@ class _LoginState extends State<LoginView> {
@override
void didChangeDependencies() {
final state = widget.authState;
final state = widget.viewModel.authState;
_emailController.text = state.email;
_passwordController.text = state.password;
_urlController.text = formatApiUrlReadable(state.url);
@ -62,7 +59,10 @@ class _LoginState extends State<LoginView> {
@override
Widget build(BuildContext context) {
if (!widget.authState.isInitialized) {
final localization = AppLocalization.of(context);
final viewModel = widget.viewModel;
if (!viewModel.authState.isInitialized) {
return Container();
}
@ -83,10 +83,10 @@ class _LoginState extends State<LoginView> {
key: _emailKey,
autocorrect: false,
decoration: InputDecoration(
labelText: AppLocalization.of(context).email),
labelText: localization.email),
keyboardType: TextInputType.emailAddress,
validator: (val) => val.isEmpty || val.trim().isEmpty
? AppLocalization.of(context).pleaseEnterYourEmail
? localization.pleaseEnterYourEmail
: null,
),
TextFormField(
@ -94,9 +94,9 @@ class _LoginState extends State<LoginView> {
key: _passwordKey,
autocorrect: false,
decoration: InputDecoration(
labelText: AppLocalization.of(context).password),
labelText: localization.password),
validator: (val) => val.isEmpty || val.trim().isEmpty
? AppLocalization.of(context).pleaseEnterYourPassword
? localization.pleaseEnterYourPassword
: null,
obscureText: true,
),
@ -105,9 +105,9 @@ class _LoginState extends State<LoginView> {
key: _urlKey,
autocorrect: false,
decoration:
InputDecoration(labelText: AppLocalization.of(context).url),
InputDecoration(labelText: localization.url),
validator: (val) => val.isEmpty || val.trim().isEmpty
? AppLocalization.of(context).pleaseEnterYourUrl
? localization.pleaseEnterYourUrl
: null,
keyboardType: TextInputType.url,
),
@ -116,21 +116,16 @@ class _LoginState extends State<LoginView> {
key: _secretKey,
autocorrect: false,
decoration: InputDecoration(
labelText: AppLocalization.of(context).secret),
/*
validator: (val) => val.isEmpty || val.trim().length == 0
? AppLocalization.of(context).pleaseEnterYourPassword
: null,
*/
labelText: localization.secret),
obscureText: true,
),
widget.authState.error == null
viewModel.authState.error == null
? Container()
: Container(
padding: EdgeInsets.only(top: 26.0, bottom: 4.0),
child: Center(
child: Text(
widget.authState.error,
viewModel.authState.error,
style: TextStyle(
color: Colors.red,
fontWeight: FontWeight.bold,
@ -142,13 +137,13 @@ class _LoginState extends State<LoginView> {
),
),
ProgressButton(
label: AppLocalization.of(context).login.toUpperCase(),
isLoading: widget.isLoading,
label: localization.login.toUpperCase(),
isLoading: viewModel.isLoading,
onPressed: () {
if (!_formKey.currentState.validate()) {
return;
}
widget.onLoginPressed(
viewModel.onLoginPressed(
context,
_emailController.text,
_passwordController.text,
@ -156,6 +151,13 @@ class _LoginState extends State<LoginView> {
_secretController.text);
},
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: ElevatedButton(
label: 'Google ${localization.login}'.toUpperCase(),
onPressed: () => viewModel.onGoogleLoginPressed(context),
),
),
],
);
}

View File

@ -11,6 +11,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/auth/auth_actions.dart';
import 'package:invoiceninja_flutter/ui/auth/login.dart';
import 'package:invoiceninja_flutter/redux/auth/auth_state.dart';
import 'package:google_sign_in/google_sign_in.dart';
class LoginScreen extends StatelessWidget {
const LoginScreen({Key key}) : super(key: key);
@ -22,11 +23,9 @@ class LoginScreen extends StatelessWidget {
return Scaffold(
body: StoreConnector<AppState, LoginVM>(
converter: LoginVM.fromStore,
builder: (context, vm) {
builder: (context, viewModel) {
return LoginView(
isLoading: vm.isLoading,
authState: vm.authState,
onLoginPressed: vm.onLoginPressed,
viewModel: viewModel,
);
},
),
@ -38,31 +37,68 @@ class LoginVM {
bool isLoading;
AuthState authState;
final Function(BuildContext, String, String, String, String) onLoginPressed;
final Function(BuildContext) onGoogleLoginPressed;
LoginVM({
@required this.isLoading,
@required this.authState,
@required this.onLoginPressed,
@required this.onGoogleLoginPressed,
});
static LoginVM fromStore(Store<AppState> store) {
final GoogleSignIn _googleSignIn = new GoogleSignIn(
scopes: [
'email',
'openid',
'profile',
],
);
_googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount account) {
print('gogole account: $account');
if (account != null) {
account.authentication.then((GoogleSignInAuthentication value) {
print('token: ${value.idToken}');
print('token: ${value.accessToken}');
});
}
});
//_googleSignIn.signInSilently();
return LoginVM(
isLoading: store.state.isLoading,
authState: store.state.authState,
onGoogleLoginPressed: (context) async {
try {
final result = await _googleSignIn.signIn();
print(result);
} catch (error) {
print(error);
}
},
onLoginPressed: (BuildContext context, String email, String password,
String url, String secret) {
String url, String secret) async {
try {
await _googleSignIn.signIn();
} catch (error) {
print(error);
}
if (store.state.isLoading) {
return;
}
final Completer<Null> completer = Completer<Null>();
store.dispatch(UserLoginRequest(
completer: completer,
email: email.trim(),
password: password.trim(),
url: url.trim(),
secret: secret.trim(),
platform: getPlatform(context),
completer: completer,
email: email.trim(),
password: password.trim(),
url: url.trim(),
secret: secret.trim(),
platform: getPlatform(context),
));
completer.future.then((_) {
Navigator.of(context).pushReplacementNamed(DashboardScreen.route);

View File

@ -162,6 +162,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.1"
firebase_auth:
dependency: "direct main"
description:
name: firebase_auth
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.18"
fixnum:
dependency: transitive
description:
@ -199,7 +206,7 @@ packages:
name: flutter_html_view
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.3"
version: "0.5.4"
flutter_localizations:
dependency: "direct main"
description: flutter
@ -252,6 +259,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.7"
google_sign_in:
dependency: "direct main"
description:
name: google_sign_in
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.4"
graphs:
dependency: transitive
description:
@ -620,7 +634,7 @@ packages:
name: video_player
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.4"
version: "0.6.4"
vm_service_client:
dependency: transitive
description:

View File

@ -25,6 +25,8 @@ dependencies:
intl: ^0.15.6
flutter_pdf_viewer: ^0.0.2
flutter_html_view: ^0.5.2
google_sign_in: ^3.0.4
firebase_auth: ^0.5.14
dev_dependencies:
flutter_driver: