mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 20:39:51 +00:00
add authentication logic
This commit is contained in:
parent
ec3e5d449e
commit
93b7ea29e5
11 changed files with 360 additions and 41 deletions
11
lib/core/email_validator.dart
Normal file
11
lib/core/email_validator.dart
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import 'package:cake_wallet/core/validator.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
|
||||||
|
class EmailValidator extends TextValidator {
|
||||||
|
EmailValidator()
|
||||||
|
: super(
|
||||||
|
errorMessage: 'Invalid email address',
|
||||||
|
pattern:
|
||||||
|
'^[^@]+@[^@]+\.[^@]+',
|
||||||
|
);
|
||||||
|
}
|
26
lib/di.dart
26
lib/di.dart
|
@ -1,6 +1,8 @@
|
||||||
import 'package:cake_wallet/core/yat_service.dart';
|
import 'package:cake_wallet/core/yat_service.dart';
|
||||||
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||||
import 'package:cake_wallet/entities/wake_lock.dart';
|
import 'package:cake_wallet/entities/wake_lock.dart';
|
||||||
|
import 'package:cake_wallet/ionia/ionia.dart';
|
||||||
|
import 'package:cake_wallet/ionia/ionia_api.dart';
|
||||||
import 'package:cake_wallet/monero/monero.dart';
|
import 'package:cake_wallet/monero/monero.dart';
|
||||||
import 'package:cake_wallet/haven/haven.dart';
|
import 'package:cake_wallet/haven/haven.dart';
|
||||||
import 'package:cake_wallet/haven/haven.dart';
|
import 'package:cake_wallet/haven/haven.dart';
|
||||||
|
@ -8,8 +10,10 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_pay/auth/create_account_page.dart';
|
import 'package:cake_wallet/src/screens/cake_pay/auth/create_account_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_pay/auth/forgot_password_page.dart';
|
import 'package:cake_wallet/src/screens/cake_pay/auth/forgot_password_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_pay/auth/login_page.dart';
|
import 'package:cake_wallet/src/screens/cake_pay/auth/login_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/cake_pay/auth/verify_otp_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
|
import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
|
||||||
import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
|
import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
|
||||||
|
import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:cake_wallet/core/backup_service.dart';
|
import 'package:cake_wallet/core/backup_service.dart';
|
||||||
import 'package:cw_core/wallet_service.dart';
|
import 'package:cw_core/wallet_service.dart';
|
||||||
|
@ -645,13 +649,23 @@ Future setup(
|
||||||
|
|
||||||
getIt.registerFactory(() => AddressResolver(yatService: getIt.get<YatService>()));
|
getIt.registerFactory(() => AddressResolver(yatService: getIt.get<YatService>()));
|
||||||
|
|
||||||
getIt.registerFactory(() => WelcomePage());
|
|
||||||
|
|
||||||
getIt.registerFactory(() => LoginPage());
|
|
||||||
|
|
||||||
getIt.registerFactory(() => CreateAccountPage());
|
|
||||||
|
|
||||||
getIt.registerFactory(() => ForgotPassword());
|
getIt.registerFactory(() => ForgotPassword());
|
||||||
|
|
||||||
|
getIt.registerFactory(() => IoniaApi());
|
||||||
|
|
||||||
|
getIt.registerFactory<IoniaService>(
|
||||||
|
() => IoniaService(getIt.get<FlutterSecureStorage>(), getIt.get<IoniaApi>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(() => IoniaViewModel(ioniaService: getIt.get<IoniaService>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(() => CreateAccountPage(getIt.get<IoniaViewModel>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(() => LoginPage(getIt.get<IoniaViewModel>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(() => VerifyIoniaOtp(getIt.get<IoniaViewModel>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(() => WelcomePage(getIt.get<IoniaViewModel>()));
|
||||||
|
|
||||||
|
|
||||||
_isSetupFinished = true;
|
_isSetupFinished = true;
|
||||||
}
|
}
|
||||||
|
|
29
lib/ionia/ionia_create_state.dart
Normal file
29
lib/ionia/ionia_create_state.dart
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
abstract class IoniaCreateState {}
|
||||||
|
|
||||||
|
class IoniaCreateStateSuccess extends IoniaCreateState {}
|
||||||
|
|
||||||
|
class IoniaCreateStateLoading extends IoniaCreateState {}
|
||||||
|
|
||||||
|
class IoniaCreateStateFailure extends IoniaCreateState {
|
||||||
|
IoniaCreateStateFailure({@required this.error});
|
||||||
|
|
||||||
|
final String error;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class IoniaOtpState {}
|
||||||
|
|
||||||
|
class IoniaOtpValidating extends IoniaOtpState {}
|
||||||
|
|
||||||
|
class IoniaOtpSuccess extends IoniaOtpState {}
|
||||||
|
|
||||||
|
class IoniaOtpSendDisabled extends IoniaOtpState {}
|
||||||
|
|
||||||
|
class IoniaOtpSendEnabled extends IoniaOtpState {}
|
||||||
|
|
||||||
|
class IoniaOtpFailure extends IoniaOtpState {
|
||||||
|
IoniaOtpFailure({@required this.error});
|
||||||
|
|
||||||
|
final String error;
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/buy/pre_order_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_pay/auth/create_account_page.dart';
|
import 'package:cake_wallet/src/screens/cake_pay/auth/create_account_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_pay/auth/forgot_password_page.dart';
|
import 'package:cake_wallet/src/screens/cake_pay/auth/forgot_password_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_pay/auth/login_page.dart';
|
import 'package:cake_wallet/src/screens/cake_pay/auth/login_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/cake_pay/auth/verify_otp_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
|
import 'package:cake_wallet/src/screens/cake_pay/cake_pay.dart';
|
||||||
import 'package:cake_wallet/src/screens/order_details/order_details_page.dart';
|
import 'package:cake_wallet/src/screens/order_details/order_details_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||||
|
@ -417,6 +418,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
|
|
||||||
case Routes.cakePayForgotPasswordPage:
|
case Routes.cakePayForgotPasswordPage:
|
||||||
return CupertinoPageRoute<void>(builder: (_) => getIt.get<ForgotPassword>());
|
return CupertinoPageRoute<void>(builder: (_) => getIt.get<ForgotPassword>());
|
||||||
|
|
||||||
|
case Routes.verifyIoniaOtpPage:
|
||||||
|
return CupertinoPageRoute<void>(builder: (_) => getIt.get<VerifyIoniaOtp>());
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
|
|
|
@ -64,4 +64,5 @@ class Routes {
|
||||||
static const cakePayCreateAccountPage = '/cake_pay_create_account_page';
|
static const cakePayCreateAccountPage = '/cake_pay_create_account_page';
|
||||||
static const cakePayLoginPage = '/cake_pay_login_page';
|
static const cakePayLoginPage = '/cake_pay_login_page';
|
||||||
static const cakePayForgotPasswordPage = '/cake_pay_forgot_password_page';
|
static const cakePayForgotPasswordPage = '/cake_pay_forgot_password_page';
|
||||||
|
static const verifyIoniaOtpPage = '/cake_pay_verify_otp_page';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,34 @@
|
||||||
|
import 'package:cake_wallet/core/email_validator.dart';
|
||||||
|
import 'package:cake_wallet/ionia/ionia_create_state.dart';
|
||||||
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||||
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
|
import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
class CreateAccountPage extends BasePage {
|
class CreateAccountPage extends BasePage {
|
||||||
CreateAccountPage() : _formKey = GlobalKey<FormState>();
|
final IoniaViewModel _ioniaViewModel;
|
||||||
|
|
||||||
|
CreateAccountPage(this._ioniaViewModel)
|
||||||
|
: _emailFocus = FocusNode(),
|
||||||
|
_emailController = TextEditingController(),
|
||||||
|
_formKey = GlobalKey<FormState>() {
|
||||||
|
_emailController.text = _ioniaViewModel.email;
|
||||||
|
_emailController.addListener(() => _ioniaViewModel.email = _emailController.text);
|
||||||
|
}
|
||||||
|
|
||||||
final GlobalKey<FormState> _formKey;
|
final GlobalKey<FormState> _formKey;
|
||||||
|
|
||||||
|
final FocusNode _emailFocus;
|
||||||
|
final TextEditingController _emailController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget middle(BuildContext context) {
|
Widget middle(BuildContext context) {
|
||||||
return Text(
|
return Text(
|
||||||
|
@ -24,21 +43,24 @@ class CreateAccountPage extends BasePage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
|
reaction((_) => _ioniaViewModel.createUserState, (IoniaCreateState state) {
|
||||||
|
if (state is IoniaCreateStateFailure) {
|
||||||
|
_onCreateUserFailure(context, state.error);
|
||||||
|
}
|
||||||
|
if (state is IoniaCreateStateSuccess) {
|
||||||
|
_onCreateSuccessful(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return ScrollableWithBottomSection(
|
return ScrollableWithBottomSection(
|
||||||
contentPadding: EdgeInsets.all(24),
|
contentPadding: EdgeInsets.all(24),
|
||||||
content: Form(
|
content: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(
|
child: BaseTextFormField(
|
||||||
mainAxisSize: MainAxisSize.min,
|
hintText: 'Email Address',
|
||||||
children: <Widget>[
|
focusNode: _emailFocus,
|
||||||
BaseTextFormField(
|
validator: EmailValidator(),
|
||||||
hintText: 'Email Address *',
|
controller: _emailController,
|
||||||
),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
BaseTextFormField(
|
|
||||||
hintText: 'Password *',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
bottomSectionPadding: EdgeInsets.symmetric(vertical: 36, horizontal: 24),
|
bottomSectionPadding: EdgeInsets.symmetric(vertical: 36, horizontal: 24),
|
||||||
|
@ -47,11 +69,19 @@ class CreateAccountPage extends BasePage {
|
||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
PrimaryButton(
|
Observer(
|
||||||
text: S.of(context).create_account,
|
builder: (_) => LoadingPrimaryButton(
|
||||||
onPressed: () {},
|
text: S.of(context).create_account,
|
||||||
color: Theme.of(context).accentTextTheme.body2.color,
|
onPressed: () async {
|
||||||
textColor: Colors.white,
|
if (!_formKey.currentState.validate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await _ioniaViewModel.createUser(_emailController.text);
|
||||||
|
},
|
||||||
|
isLoading: _ioniaViewModel.createUserState is IoniaCreateStateLoading,
|
||||||
|
color: Theme.of(context).accentTextTheme.body2.color,
|
||||||
|
textColor: Colors.white,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
|
@ -92,3 +122,17 @@ class CreateAccountPage extends BasePage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onCreateUserFailure(BuildContext context, String error) {
|
||||||
|
showPopUp<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithOneAction(
|
||||||
|
alertTitle: S.current.create_account,
|
||||||
|
alertContent: error,
|
||||||
|
buttonText: S.of(context).ok,
|
||||||
|
buttonAction: () => Navigator.of(context).pop());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onCreateSuccessful(BuildContext context) => Navigator.pushNamed(context, Routes.verifyIoniaOtpPage);
|
||||||
|
|
|
@ -1,19 +1,36 @@
|
||||||
|
import 'package:cake_wallet/core/email_validator.dart';
|
||||||
|
import 'package:cake_wallet/ionia/ionia_create_state.dart';
|
||||||
import 'package:cake_wallet/palette.dart';
|
import 'package:cake_wallet/palette.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||||
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
|
import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
class LoginPage extends BasePage {
|
class LoginPage extends BasePage {
|
||||||
LoginPage() : _formKey = GlobalKey<FormState>();
|
final IoniaViewModel _ioniaViewModel;
|
||||||
|
LoginPage(this._ioniaViewModel)
|
||||||
|
: _formKey = GlobalKey<FormState>(),
|
||||||
|
_emailFocus = FocusNode(),
|
||||||
|
_emailController = TextEditingController() {
|
||||||
|
_emailController.text = _ioniaViewModel.email;
|
||||||
|
_emailController.addListener(() => _ioniaViewModel.email = _emailController.text);
|
||||||
|
}
|
||||||
|
|
||||||
final GlobalKey<FormState> _formKey;
|
final GlobalKey<FormState> _formKey;
|
||||||
@override
|
@override
|
||||||
Color get titleColor => Colors.black;
|
Color get titleColor => Colors.black;
|
||||||
|
|
||||||
|
final FocusNode _emailFocus;
|
||||||
|
final TextEditingController _emailController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget middle(BuildContext context) {
|
Widget middle(BuildContext context) {
|
||||||
return Text(
|
return Text(
|
||||||
|
@ -28,21 +45,22 @@ class LoginPage extends BasePage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
|
reaction((_) => _ioniaViewModel.createUserState, (IoniaCreateState state) {
|
||||||
|
if (state is IoniaCreateStateFailure) {
|
||||||
|
_onLoginUserFailure(context, state.error);
|
||||||
|
}
|
||||||
|
if (state is IoniaCreateStateSuccess) {
|
||||||
|
_onLoginSuccessful(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
return ScrollableWithBottomSection(
|
return ScrollableWithBottomSection(
|
||||||
contentPadding: EdgeInsets.all(24),
|
contentPadding: EdgeInsets.all(24),
|
||||||
content: Form(
|
content: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(
|
child: BaseTextFormField(
|
||||||
mainAxisSize: MainAxisSize.min,
|
hintText: 'Email Address',
|
||||||
children: <Widget>[
|
validator: EmailValidator(),
|
||||||
BaseTextFormField(
|
controller: _emailController,
|
||||||
hintText: 'Email Address',
|
|
||||||
),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
BaseTextFormField(
|
|
||||||
hintText: 'Password',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
bottomSectionPadding: EdgeInsets.symmetric(vertical: 36, horizontal: 24),
|
bottomSectionPadding: EdgeInsets.symmetric(vertical: 36, horizontal: 24),
|
||||||
|
@ -51,11 +69,19 @@ class LoginPage extends BasePage {
|
||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
PrimaryButton(
|
Observer(
|
||||||
text: S.of(context).login,
|
builder: (_) => LoadingPrimaryButton(
|
||||||
onPressed: () {},
|
text: S.of(context).login,
|
||||||
color: Theme.of(context).accentTextTheme.body2.color,
|
onPressed: () async {
|
||||||
textColor: Colors.white,
|
if (!_formKey.currentState.validate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await _ioniaViewModel.createUser(_emailController.text);
|
||||||
|
},
|
||||||
|
isLoading: _ioniaViewModel.createUserState is IoniaCreateStateLoading,
|
||||||
|
color: Theme.of(context).accentTextTheme.body2.color,
|
||||||
|
textColor: Colors.white,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
|
@ -78,3 +104,17 @@ class LoginPage extends BasePage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onLoginUserFailure(BuildContext context, String error) {
|
||||||
|
showPopUp<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithOneAction(
|
||||||
|
alertTitle: S.current.login,
|
||||||
|
alertContent: error,
|
||||||
|
buttonText: S.of(context).ok,
|
||||||
|
buttonAction: () => Navigator.of(context).pop());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onLoginSuccessful(BuildContext context) => Navigator.pushNamed(context, Routes.verifyIoniaOtpPage);
|
||||||
|
|
103
lib/src/screens/cake_pay/auth/verify_otp_page.dart
Normal file
103
lib/src/screens/cake_pay/auth/verify_otp_page.dart
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
import 'package:cake_wallet/ionia/ionia_create_state.dart';
|
||||||
|
import 'package:cake_wallet/palette.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||||
|
import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
|
||||||
|
class VerifyIoniaOtp extends BasePage {
|
||||||
|
final IoniaViewModel _ioniaViewModel;
|
||||||
|
|
||||||
|
VerifyIoniaOtp(this._ioniaViewModel)
|
||||||
|
: _codeController = TextEditingController(),
|
||||||
|
_codeFocus = FocusNode() {
|
||||||
|
_codeController.addListener(() {
|
||||||
|
final otp = _codeController.text;
|
||||||
|
_ioniaViewModel.otp = otp;
|
||||||
|
if (otp.length > 3) {
|
||||||
|
_ioniaViewModel.otpState = IoniaOtpSendEnabled();
|
||||||
|
} else {
|
||||||
|
_ioniaViewModel.otpState = IoniaOtpSendDisabled();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget middle(BuildContext context) {
|
||||||
|
return Text(
|
||||||
|
S.current.verification,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
fontFamily: 'Lato',
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final TextEditingController _codeController;
|
||||||
|
final FocusNode _codeFocus;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget body(BuildContext context) {
|
||||||
|
return ScrollableWithBottomSection(
|
||||||
|
contentPadding: EdgeInsets.all(24),
|
||||||
|
content: Column(
|
||||||
|
children: [
|
||||||
|
BaseTextFormField(
|
||||||
|
hintText: 'Enter code',
|
||||||
|
focusNode: _codeFocus,
|
||||||
|
controller: _codeController,
|
||||||
|
),
|
||||||
|
SizedBox(height: 14),
|
||||||
|
Text(
|
||||||
|
S.of(context).fill_code,
|
||||||
|
style: TextStyle(color: Color(0xff7A93BA), fontSize: 12),
|
||||||
|
),
|
||||||
|
SizedBox(height: 34),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(S.of(context).dont_get_code),
|
||||||
|
SizedBox(width: 20),
|
||||||
|
Text(
|
||||||
|
S.of(context).resend_code,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Palette.blueCraiola,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
bottomSectionPadding: EdgeInsets.symmetric(vertical: 36, horizontal: 24),
|
||||||
|
bottomSection: Column(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
Observer(
|
||||||
|
builder: (_) => LoadingPrimaryButton(
|
||||||
|
text: S.of(context).continue_text,
|
||||||
|
onPressed: () async => await _ioniaViewModel.verifyEmail(_codeController.text),
|
||||||
|
isDisabled: _ioniaViewModel.otpState is IoniaOtpSendDisabled,
|
||||||
|
isLoading: _ioniaViewModel.otpState is IoniaOtpValidating,
|
||||||
|
color: Theme.of(context).accentTextTheme.body2.color,
|
||||||
|
textColor: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,17 @@ import 'package:cake_wallet/palette.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||||
|
import 'package:cake_wallet/view_model/ionia/ionia_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/src/widgets/framework.dart';
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
class WelcomePage extends BasePage {
|
class WelcomePage extends BasePage {
|
||||||
|
final IoniaViewModel _ioniaViewModel;
|
||||||
|
|
||||||
|
WelcomePage(this._ioniaViewModel);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get titleColor => Colors.black;
|
Color get titleColor => Colors.black;
|
||||||
|
|
||||||
|
@ -24,6 +30,11 @@ class WelcomePage extends BasePage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
|
reaction((_) => _ioniaViewModel.isLoggedIn, (bool state) {
|
||||||
|
if (state) {
|
||||||
|
// TODO:: Navigate to main page
|
||||||
|
}
|
||||||
|
});
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(24.0),
|
padding: const EdgeInsets.all(24.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
58
lib/view_model/ionia/ionia_view_model.dart
Normal file
58
lib/view_model/ionia/ionia_view_model.dart
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import 'package:cake_wallet/ionia/ionia.dart';
|
||||||
|
import 'package:cake_wallet/ionia/ionia_create_state.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
part 'ionia_view_model.g.dart';
|
||||||
|
|
||||||
|
class IoniaViewModel = IoniaViewModelBase with _$IoniaViewModel;
|
||||||
|
|
||||||
|
abstract class IoniaViewModelBase with Store {
|
||||||
|
IoniaViewModelBase({this.ioniaService})
|
||||||
|
: createUserState = IoniaCreateStateSuccess(),
|
||||||
|
otpState = IoniaOtpSendDisabled() {
|
||||||
|
_getAuthStatus().then((value) => isLoggedIn = value);
|
||||||
|
}
|
||||||
|
|
||||||
|
final IoniaService ioniaService;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
IoniaCreateState createUserState;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
IoniaOtpState otpState;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String email;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String otp;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool isLoggedIn;
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> createUser(String email) async {
|
||||||
|
createUserState = IoniaCreateStateLoading();
|
||||||
|
try {
|
||||||
|
await ioniaService.createUser(email);
|
||||||
|
|
||||||
|
createUserState = IoniaCreateStateSuccess();
|
||||||
|
} catch (e) {
|
||||||
|
createUserState = IoniaCreateStateFailure(error: 'Something went wrong!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> verifyEmail(String code) async {
|
||||||
|
try {
|
||||||
|
otpState = IoniaOtpValidating();
|
||||||
|
await ioniaService.verifyEmail(code);
|
||||||
|
otpState = IoniaOtpSuccess();
|
||||||
|
} catch (_) {
|
||||||
|
otpState = IoniaOtpFailure(error: 'Invalid OTP. Try again');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _getAuthStatus() async {
|
||||||
|
return await ioniaService.isLogined();
|
||||||
|
}
|
||||||
|
}
|
|
@ -546,5 +546,9 @@
|
||||||
"manage_cards": "Manage Cards",
|
"manage_cards": "Manage Cards",
|
||||||
"setup_your_debit_card": "Set up your debit card",
|
"setup_your_debit_card": "Set up your debit card",
|
||||||
"no_id_required": "No ID required. Top up and spend anywhere",
|
"no_id_required": "No ID required. Top up and spend anywhere",
|
||||||
"how_to_use_card": "How to use this card"
|
"how_to_use_card": "How to use this card",
|
||||||
|
"verification": "Verification",
|
||||||
|
"fill_code": "Please fill in the verification code provided to your email",
|
||||||
|
"dont_get_code": "Don't get code",
|
||||||
|
"resend_code": "Please resend it"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue