ios permissions
This commit is contained in:
parent
159e82811a
commit
755e73d63a
|
|
@ -295,449 +295,451 @@ class _LoginState extends State<LoginView> {
|
||||||
final double horizontalPadding =
|
final double horizontalPadding =
|
||||||
calculateLayout(context) == AppLayout.desktop ? 40 : 16;
|
calculateLayout(context) == AppLayout.desktop ? 40 : 16;
|
||||||
|
|
||||||
return ScrollableListView(
|
return SafeArea(
|
||||||
children: <Widget>[
|
child: ScrollableListView(
|
||||||
if (isDesktopOS())
|
children: <Widget>[
|
||||||
AppTitleBar()
|
if (isDesktopOS())
|
||||||
else
|
AppTitleBar()
|
||||||
Container(
|
else
|
||||||
width: double.infinity,
|
Container(
|
||||||
height: 24,
|
width: double.infinity,
|
||||||
color: state.accentColor,
|
height: 24,
|
||||||
),
|
color: state.accentColor,
|
||||||
Padding(
|
),
|
||||||
padding: EdgeInsets.symmetric(vertical: 25),
|
Padding(
|
||||||
child: Center(
|
padding: EdgeInsets.symmetric(vertical: 25),
|
||||||
child: InkWell(
|
child: Center(
|
||||||
// TODO correct this
|
child: InkWell(
|
||||||
child: Image.asset(
|
// TODO correct this
|
||||||
state.prefState.enableDarkMode
|
child: Image.asset(
|
||||||
? 'assets/images/logo_dark.png'
|
state.prefState.enableDarkMode
|
||||||
: 'assets/images/logo_light.png',
|
? 'assets/images/logo_dark.png'
|
||||||
height: 50),
|
: 'assets/images/logo_light.png',
|
||||||
onTap: isApple()
|
height: 50),
|
||||||
? null
|
onTap: isApple()
|
||||||
: () {
|
? null
|
||||||
launch(kSiteUrl,
|
: () {
|
||||||
forceSafariVC: false, forceWebView: false);
|
launch(kSiteUrl,
|
||||||
},
|
forceSafariVC: false, forceWebView: false);
|
||||||
onLongPress: () {
|
},
|
||||||
if (kReleaseMode) {
|
onLongPress: () {
|
||||||
return;
|
if (kReleaseMode) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setState(() => _tokenLogin = !_tokenLogin);
|
setState(() => _tokenLogin = !_tokenLogin);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
if (_tokenLogin)
|
||||||
if (_tokenLogin)
|
FormCard(
|
||||||
FormCard(
|
forceNarrow: calculateLayout(context) != AppLayout.mobile,
|
||||||
forceNarrow: calculateLayout(context) != AppLayout.mobile,
|
children: [
|
||||||
children: [
|
DecoratedFormField(
|
||||||
DecoratedFormField(
|
autofocus: true,
|
||||||
autofocus: true,
|
label: localization.token,
|
||||||
label: localization.token,
|
controller: _tokenController,
|
||||||
controller: _tokenController,
|
keyboardType: TextInputType.text,
|
||||||
keyboardType: TextInputType.text,
|
),
|
||||||
),
|
AppButton(
|
||||||
AppButton(
|
label: localization.submit.toUpperCase(),
|
||||||
label: localization.submit.toUpperCase(),
|
onPressed: () {
|
||||||
onPressed: () {
|
final Completer<Null> completer = Completer<Null>();
|
||||||
final Completer<Null> completer = Completer<Null>();
|
viewModel.onTokenLoginPressed(context, completer,
|
||||||
viewModel.onTokenLoginPressed(context, completer,
|
token: _tokenController.text);
|
||||||
token: _tokenController.text);
|
},
|
||||||
},
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
AnimatedOpacity(
|
||||||
AnimatedOpacity(
|
duration: Duration(milliseconds: 500),
|
||||||
duration: Duration(milliseconds: 500),
|
opacity: viewModel.authState.isAuthenticated ? 0 : 1,
|
||||||
opacity: viewModel.authState.isAuthenticated ? 0 : 1,
|
child: Form(
|
||||||
child: Form(
|
key: _formKey,
|
||||||
key: _formKey,
|
child: AutofillGroup(
|
||||||
child: AutofillGroup(
|
child: FormCard(
|
||||||
child: FormCard(
|
elevation: 20,
|
||||||
elevation: 20,
|
forceNarrow: calculateLayout(context) != AppLayout.mobile,
|
||||||
forceNarrow: calculateLayout(context) != AppLayout.mobile,
|
internalPadding: const EdgeInsets.all(0),
|
||||||
internalPadding: const EdgeInsets.all(0),
|
children: <Widget>[
|
||||||
children: <Widget>[
|
Column(
|
||||||
Column(
|
children: <Widget>[
|
||||||
children: <Widget>[
|
if (!isApple() &&
|
||||||
if (!isApple() &&
|
(!kIsWeb || !state.authState.isSelfHost))
|
||||||
(!kIsWeb || !state.authState.isSelfHost))
|
Row(
|
||||||
Row(
|
children: [
|
||||||
children: [
|
Expanded(
|
||||||
Expanded(
|
child: Material(
|
||||||
child: Material(
|
color: _createAccount
|
||||||
color: _createAccount
|
? state.accentColor
|
||||||
? state.accentColor
|
: Colors.transparent,
|
||||||
: Colors.transparent,
|
child: InkWell(
|
||||||
child: InkWell(
|
child: Center(
|
||||||
child: Center(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(16),
|
||||||
padding: const EdgeInsets.all(16),
|
child: Text(
|
||||||
child: Text(
|
localization.signUp,
|
||||||
localization.signUp,
|
style: Theme.of(context)
|
||||||
style: Theme.of(context)
|
.textTheme
|
||||||
.textTheme
|
.headline6
|
||||||
.headline6
|
.copyWith(
|
||||||
.copyWith(
|
fontWeight: FontWeight.w600,
|
||||||
fontWeight: FontWeight.w600,
|
fontSize: 18,
|
||||||
fontSize: 18,
|
color: _createAccount
|
||||||
color: _createAccount
|
? Colors.white
|
||||||
? Colors.white
|
: null),
|
||||||
: null),
|
),
|
||||||
),
|
)),
|
||||||
)),
|
onTap: () {
|
||||||
onTap: () {
|
setState(() {
|
||||||
setState(() {
|
_createAccount = true;
|
||||||
_createAccount = true;
|
_isSelfHosted = false;
|
||||||
_isSelfHosted = false;
|
_loginError = '';
|
||||||
_loginError = '';
|
});
|
||||||
});
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
Expanded(
|
child: Material(
|
||||||
child: Material(
|
color: _createAccount
|
||||||
color: _createAccount
|
? Colors.transparent
|
||||||
? Colors.transparent
|
: state.accentColor,
|
||||||
: state.accentColor,
|
child: InkWell(
|
||||||
child: InkWell(
|
child: Center(
|
||||||
child: Center(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(16),
|
||||||
padding: const EdgeInsets.all(16),
|
child: Text(
|
||||||
child: Text(
|
localization.login,
|
||||||
localization.login,
|
style: Theme.of(context)
|
||||||
style: Theme.of(context)
|
.textTheme
|
||||||
.textTheme
|
.headline6
|
||||||
.headline6
|
.copyWith(
|
||||||
.copyWith(
|
fontWeight: FontWeight.w600,
|
||||||
fontWeight: FontWeight.w600,
|
fontSize: 18,
|
||||||
fontSize: 18,
|
color: _createAccount
|
||||||
color: _createAccount
|
? null
|
||||||
? null
|
: Colors.white),
|
||||||
: Colors.white),
|
),
|
||||||
),
|
)),
|
||||||
)),
|
onTap: () {
|
||||||
onTap: () {
|
setState(() {
|
||||||
setState(() {
|
_createAccount = false;
|
||||||
_createAccount = false;
|
_loginError = '';
|
||||||
_loginError = '';
|
});
|
||||||
});
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
if (!_recoverPassword) ...[
|
||||||
|
if (!_createAccount && (!kIsWeb || !kReleaseMode)) ...[
|
||||||
|
RuledText(localization.selectPlatform),
|
||||||
|
AppToggleButtons(
|
||||||
|
tabLabels: [
|
||||||
|
localization.hosted,
|
||||||
|
localization.selfhosted,
|
||||||
|
],
|
||||||
|
selectedIndex: _isSelfHosted ? 1 : 0,
|
||||||
|
onTabChanged: (index) {
|
||||||
|
setState(() {
|
||||||
|
_isSelfHosted = index == 1;
|
||||||
|
_loginError = '';
|
||||||
|
if (index == 1) {
|
||||||
|
_emailLogin = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
if (!_isSelfHosted && !_hideGoogle) ...[
|
||||||
SizedBox(height: 20),
|
RuledText(localization.selectMethod),
|
||||||
if (!_recoverPassword) ...[
|
AppToggleButtons(
|
||||||
if (!_createAccount && (!kIsWeb || !kReleaseMode)) ...[
|
tabLabels:
|
||||||
RuledText(localization.selectPlatform),
|
calculateLayout(context) == AppLayout.mobile
|
||||||
AppToggleButtons(
|
? [
|
||||||
tabLabels: [
|
'Google',
|
||||||
localization.hosted,
|
localization.email,
|
||||||
localization.selfhosted,
|
]
|
||||||
|
: [
|
||||||
|
_createAccount
|
||||||
|
? localization.googleSignUp
|
||||||
|
: localization.googleSignIn,
|
||||||
|
_createAccount
|
||||||
|
? localization.emailSignUp
|
||||||
|
: localization.emailSignIn,
|
||||||
|
],
|
||||||
|
selectedIndex: _emailLogin ? 1 : 0,
|
||||||
|
onTabChanged: (index) {
|
||||||
|
setState(() {
|
||||||
|
_emailLogin = index == 1;
|
||||||
|
_loginError = '';
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
Padding(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(horizontal: horizontalPadding),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (_emailLogin)
|
||||||
|
DecoratedFormField(
|
||||||
|
controller: _emailController,
|
||||||
|
label: localization.email,
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
autovalidate: _autoValidate,
|
||||||
|
validator: (val) =>
|
||||||
|
val.isEmpty || val.trim().isEmpty
|
||||||
|
? localization.pleaseEnterYourEmail
|
||||||
|
: null,
|
||||||
|
autofillHints: [AutofillHints.email],
|
||||||
|
autofocus: true,
|
||||||
|
onSavePressed: (_) => _submitForm(),
|
||||||
|
),
|
||||||
|
if (_emailLogin && !_recoverPassword)
|
||||||
|
PasswordFormField(
|
||||||
|
controller: _passwordController,
|
||||||
|
autoValidate: false,
|
||||||
|
newPassword: _createAccount,
|
||||||
|
onSavePressed: (_) => _submitForm(),
|
||||||
|
),
|
||||||
|
if (!_createAccount && !_recoverPassword)
|
||||||
|
DecoratedFormField(
|
||||||
|
controller: _oneTimePasswordController,
|
||||||
|
label:
|
||||||
|
'${localization.oneTimePassword} (${localization.optional})',
|
||||||
|
onSavePressed: (_) => _submitForm(),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
autofillHints: [AutofillHints.oneTimeCode],
|
||||||
|
),
|
||||||
|
if (_isSelfHosted && !kIsWeb)
|
||||||
|
DecoratedFormField(
|
||||||
|
controller: _urlController,
|
||||||
|
label: localization.url,
|
||||||
|
validator: (val) =>
|
||||||
|
val.isEmpty || val.trim().isEmpty
|
||||||
|
? localization.pleaseEnterYourUrl
|
||||||
|
: null,
|
||||||
|
keyboardType: TextInputType.url,
|
||||||
|
onSavePressed: (_) => _submitForm(),
|
||||||
|
),
|
||||||
|
if (_isSelfHosted && !_recoverPassword)
|
||||||
|
PasswordFormField(
|
||||||
|
labelText:
|
||||||
|
'${localization.secret} (${localization.optional})',
|
||||||
|
controller: _secretController,
|
||||||
|
autoValidate: _autoValidate,
|
||||||
|
validate: false,
|
||||||
|
onSavePressed: (_) => _submitForm(),
|
||||||
|
),
|
||||||
|
if (_createAccount)
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 10),
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
CheckboxListTile(
|
||||||
|
onChanged: (value) =>
|
||||||
|
setState(() => _termsChecked = value),
|
||||||
|
controlAffinity:
|
||||||
|
ListTileControlAffinity.leading,
|
||||||
|
activeColor: convertHexStringToColor(
|
||||||
|
kDefaultAccentColor),
|
||||||
|
value: _termsChecked,
|
||||||
|
title: RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
children: <TextSpan>[
|
||||||
|
TextSpan(
|
||||||
|
style: aboutTextStyle,
|
||||||
|
text: localization.iAgreeToThe +
|
||||||
|
' ',
|
||||||
|
),
|
||||||
|
LinkTextSpan(
|
||||||
|
style: linkStyle,
|
||||||
|
url: kTermsOfServiceURL,
|
||||||
|
text: localization.termsOfService,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CheckboxListTile(
|
||||||
|
onChanged: (value) => setState(
|
||||||
|
() => _privacyChecked = value),
|
||||||
|
controlAffinity:
|
||||||
|
ListTileControlAffinity.leading,
|
||||||
|
activeColor: convertHexStringToColor(
|
||||||
|
kDefaultAccentColor),
|
||||||
|
value: _privacyChecked,
|
||||||
|
title: RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
children: <TextSpan>[
|
||||||
|
TextSpan(
|
||||||
|
style: aboutTextStyle,
|
||||||
|
text: localization.iAgreeToThe +
|
||||||
|
' ',
|
||||||
|
),
|
||||||
|
LinkTextSpan(
|
||||||
|
style: linkStyle,
|
||||||
|
url: kPrivacyPolicyURL,
|
||||||
|
text: localization.privacyPolicy,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
selectedIndex: _isSelfHosted ? 1 : 0,
|
|
||||||
onTabChanged: (index) {
|
|
||||||
setState(() {
|
|
||||||
_isSelfHosted = index == 1;
|
|
||||||
_loginError = '';
|
|
||||||
if (index == 1) {
|
|
||||||
_emailLogin = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
if (!_isSelfHosted && !_hideGoogle) ...[
|
|
||||||
RuledText(localization.selectMethod),
|
|
||||||
AppToggleButtons(
|
|
||||||
tabLabels:
|
|
||||||
calculateLayout(context) == AppLayout.mobile
|
|
||||||
? [
|
|
||||||
'Google',
|
|
||||||
localization.email,
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
_createAccount
|
|
||||||
? localization.googleSignUp
|
|
||||||
: localization.googleSignIn,
|
|
||||||
_createAccount
|
|
||||||
? localization.emailSignUp
|
|
||||||
: localization.emailSignIn,
|
|
||||||
],
|
|
||||||
selectedIndex: _emailLogin ? 1 : 0,
|
|
||||||
onTabChanged: (index) {
|
|
||||||
setState(() {
|
|
||||||
_emailLogin = index == 1;
|
|
||||||
_loginError = '';
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
Padding(
|
),
|
||||||
padding:
|
if (_loginError.isNotEmpty &&
|
||||||
EdgeInsets.symmetric(horizontal: horizontalPadding),
|
!_loginError.contains(OTP_ERROR))
|
||||||
child: Column(
|
Container(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: 20,
|
||||||
|
left: horizontalPadding,
|
||||||
|
right: horizontalPadding),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SelectableText(
|
||||||
|
_loginError,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.content_copy),
|
||||||
|
tooltip: localization.copyError,
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(
|
||||||
|
ClipboardData(text: _loginError));
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: 20, bottom: 10, left: 16, right: 16),
|
||||||
|
child: RoundedLoadingButton(
|
||||||
|
height: 50,
|
||||||
|
borderRadius: 4,
|
||||||
|
width: 430,
|
||||||
|
controller: _buttonController,
|
||||||
|
color: state.accentColor,
|
||||||
|
onPressed: () => _submitForm(),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if (_emailLogin)
|
if (_emailLogin)
|
||||||
DecoratedFormField(
|
Icon(Icons.mail, color: Colors.white)
|
||||||
controller: _emailController,
|
else
|
||||||
label: localization.email,
|
ClipOval(
|
||||||
keyboardType: TextInputType.emailAddress,
|
child: Image.asset(
|
||||||
autovalidate: _autoValidate,
|
'assets/images/google_logo.png',
|
||||||
validator: (val) =>
|
width: 30,
|
||||||
val.isEmpty || val.trim().isEmpty
|
height: 30),
|
||||||
? localization.pleaseEnterYourEmail
|
|
||||||
: null,
|
|
||||||
autofillHints: [AutofillHints.email],
|
|
||||||
autofocus: true,
|
|
||||||
onSavePressed: (_) => _submitForm(),
|
|
||||||
),
|
|
||||||
if (_emailLogin && !_recoverPassword)
|
|
||||||
PasswordFormField(
|
|
||||||
controller: _passwordController,
|
|
||||||
autoValidate: false,
|
|
||||||
newPassword: _createAccount,
|
|
||||||
onSavePressed: (_) => _submitForm(),
|
|
||||||
),
|
|
||||||
if (!_createAccount && !_recoverPassword)
|
|
||||||
DecoratedFormField(
|
|
||||||
controller: _oneTimePasswordController,
|
|
||||||
label:
|
|
||||||
'${localization.oneTimePassword} (${localization.optional})',
|
|
||||||
onSavePressed: (_) => _submitForm(),
|
|
||||||
keyboardType: TextInputType.number,
|
|
||||||
autofillHints: [AutofillHints.oneTimeCode],
|
|
||||||
),
|
|
||||||
if (_isSelfHosted && !kIsWeb)
|
|
||||||
DecoratedFormField(
|
|
||||||
controller: _urlController,
|
|
||||||
label: localization.url,
|
|
||||||
validator: (val) =>
|
|
||||||
val.isEmpty || val.trim().isEmpty
|
|
||||||
? localization.pleaseEnterYourUrl
|
|
||||||
: null,
|
|
||||||
keyboardType: TextInputType.url,
|
|
||||||
onSavePressed: (_) => _submitForm(),
|
|
||||||
),
|
|
||||||
if (_isSelfHosted && !_recoverPassword)
|
|
||||||
PasswordFormField(
|
|
||||||
labelText:
|
|
||||||
'${localization.secret} (${localization.optional})',
|
|
||||||
controller: _secretController,
|
|
||||||
autoValidate: _autoValidate,
|
|
||||||
validate: false,
|
|
||||||
onSavePressed: (_) => _submitForm(),
|
|
||||||
),
|
|
||||||
if (_createAccount)
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(top: 10),
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
CheckboxListTile(
|
|
||||||
onChanged: (value) =>
|
|
||||||
setState(() => _termsChecked = value),
|
|
||||||
controlAffinity:
|
|
||||||
ListTileControlAffinity.leading,
|
|
||||||
activeColor: convertHexStringToColor(
|
|
||||||
kDefaultAccentColor),
|
|
||||||
value: _termsChecked,
|
|
||||||
title: RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
children: <TextSpan>[
|
|
||||||
TextSpan(
|
|
||||||
style: aboutTextStyle,
|
|
||||||
text: localization.iAgreeToThe +
|
|
||||||
' ',
|
|
||||||
),
|
|
||||||
LinkTextSpan(
|
|
||||||
style: linkStyle,
|
|
||||||
url: kTermsOfServiceURL,
|
|
||||||
text: localization.termsOfService,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
CheckboxListTile(
|
|
||||||
onChanged: (value) => setState(
|
|
||||||
() => _privacyChecked = value),
|
|
||||||
controlAffinity:
|
|
||||||
ListTileControlAffinity.leading,
|
|
||||||
activeColor: convertHexStringToColor(
|
|
||||||
kDefaultAccentColor),
|
|
||||||
value: _privacyChecked,
|
|
||||||
title: RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
children: <TextSpan>[
|
|
||||||
TextSpan(
|
|
||||||
style: aboutTextStyle,
|
|
||||||
text: localization.iAgreeToThe +
|
|
||||||
' ',
|
|
||||||
),
|
|
||||||
LinkTextSpan(
|
|
||||||
style: linkStyle,
|
|
||||||
url: kPrivacyPolicyURL,
|
|
||||||
text: localization.privacyPolicy,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
Text(
|
||||||
|
_recoverPassword
|
||||||
|
? localization.recoverPassword
|
||||||
|
: _createAccount
|
||||||
|
? (_emailLogin
|
||||||
|
? localization.emailSignUp
|
||||||
|
: localization.googleSignUp)
|
||||||
|
: (_emailLogin
|
||||||
|
? localization.emailSignIn
|
||||||
|
: localization.googleSignIn),
|
||||||
|
style: TextStyle(fontSize: 18, color: Colors.white),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
SizedBox(height: 4),
|
||||||
if (_loginError.isNotEmpty &&
|
Flex(
|
||||||
!_loginError.contains(OTP_ERROR))
|
direction: calculateLayout(context) == AppLayout.desktop
|
||||||
Container(
|
? Axis.horizontal
|
||||||
padding: EdgeInsets.only(
|
: Axis.vertical,
|
||||||
top: 20,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
left: horizontalPadding,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
right: horizontalPadding),
|
children: <Widget>[
|
||||||
child: Row(
|
if (!_createAccount && _emailLogin)
|
||||||
children: [
|
InkWell(
|
||||||
Expanded(
|
onTap: () {
|
||||||
child: SelectableText(
|
setState(() {
|
||||||
_loginError,
|
_recoverPassword = !_recoverPassword;
|
||||||
style: TextStyle(
|
});
|
||||||
color: Colors.red,
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
if (!_recoverPassword)
|
||||||
|
Icon(MdiIcons.lock, size: 16),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text(_recoverPassword
|
||||||
|
? localization.cancel
|
||||||
|
: localization.recoverPassword),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!_recoverPassword && !_isSelfHosted)
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
launch(kStatusCheckUrl);
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.security, size: 16),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text(localization.checkStatus)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
if (!_recoverPassword && kIsWeb)
|
||||||
icon: Icon(Icons.content_copy),
|
InkWell(
|
||||||
tooltip: localization.copyError,
|
onTap: () => launch(getNativeAppUrl(platform)),
|
||||||
onPressed: () {
|
child: Padding(
|
||||||
Clipboard.setData(
|
padding: const EdgeInsets.all(14),
|
||||||
ClipboardData(text: _loginError));
|
child: Row(
|
||||||
}),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
top: 20, bottom: 10, left: 16, right: 16),
|
|
||||||
child: RoundedLoadingButton(
|
|
||||||
height: 50,
|
|
||||||
borderRadius: 4,
|
|
||||||
width: 430,
|
|
||||||
controller: _buttonController,
|
|
||||||
color: state.accentColor,
|
|
||||||
onPressed: () => _submitForm(),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
if (_emailLogin)
|
|
||||||
Icon(Icons.mail, color: Colors.white)
|
|
||||||
else
|
|
||||||
ClipOval(
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/google_logo.png',
|
|
||||||
width: 30,
|
|
||||||
height: 30),
|
|
||||||
),
|
|
||||||
SizedBox(width: 10),
|
|
||||||
Text(
|
|
||||||
_recoverPassword
|
|
||||||
? localization.recoverPassword
|
|
||||||
: _createAccount
|
|
||||||
? (_emailLogin
|
|
||||||
? localization.emailSignUp
|
|
||||||
: localization.googleSignUp)
|
|
||||||
: (_emailLogin
|
|
||||||
? localization.emailSignIn
|
|
||||||
: localization.googleSignIn),
|
|
||||||
style: TextStyle(fontSize: 18, color: Colors.white),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 4),
|
|
||||||
Flex(
|
|
||||||
direction: calculateLayout(context) == AppLayout.desktop
|
|
||||||
? Axis.horizontal
|
|
||||||
: Axis.vertical,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
if (!_createAccount && _emailLogin)
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
setState(() {
|
|
||||||
_recoverPassword = !_recoverPassword;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(14),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: [
|
||||||
if (!_recoverPassword)
|
Icon(getNativeAppIcon(platform), size: 16),
|
||||||
Icon(MdiIcons.lock, size: 16),
|
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Text(_recoverPassword
|
Text('$platform ${localization.app}')
|
||||||
? localization.cancel
|
],
|
||||||
: localization.recoverPassword),
|
),
|
||||||
]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (!_recoverPassword && !_isSelfHosted)
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
launch(kStatusCheckUrl);
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(14),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(Icons.security, size: 16),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Text(localization.checkStatus)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
if (!_recoverPassword && kIsWeb)
|
),
|
||||||
InkWell(
|
SizedBox(height: 16),
|
||||||
onTap: () => launch(getNativeAppUrl(platform)),
|
],
|
||||||
child: Padding(
|
),
|
||||||
padding: const EdgeInsets.all(14),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(getNativeAppIcon(platform), size: 16),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Text('$platform ${localization.app}')
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 16),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import 'package:contacts_service/contacts_service.dart';
|
||||||
// Project imports:
|
// Project imports:
|
||||||
import 'package:invoiceninja_flutter/constants.dart';
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
|
||||||
|
|
@ -131,24 +132,24 @@ class ClientEditDetailsState extends State<ClientEditDetails> {
|
||||||
String countryId;
|
String countryId;
|
||||||
|
|
||||||
countryMap.keys.forEach((countryId) {
|
countryMap.keys.forEach((countryId) {
|
||||||
final country = countryMap[countryId];
|
final country = countryMap[countryId] ?? CountryEntity();
|
||||||
if (country.name.toLowerCase() == contactAddress.country.toLowerCase()) {
|
if (country.name.toLowerCase() == contactAddress?.country?.toLowerCase()) {
|
||||||
countryId = country.id;
|
countryId = country.id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
widget.viewModel.onChanged(client.rebuild((b) => b
|
widget.viewModel.onChanged(client.rebuild((b) => b
|
||||||
..name = contact.company ?? ''
|
..name = (contact?.company ?? '').trim()
|
||||||
..address1 = contactAddress.street ?? ''
|
..address1 = (contactAddress?.street ?? '').trim()
|
||||||
..city = contactAddress.city ?? ''
|
..city = (contactAddress?.city ?? '').trim()
|
||||||
..state = contactAddress.region ?? ''
|
..state = (contactAddress?.region ?? '').trim()
|
||||||
..postalCode = contactAddress.postcode ?? ''
|
..postalCode = (contactAddress?.postcode ?? '').trim()
|
||||||
..countryId = countryId
|
..countryId = countryId ?? ''
|
||||||
..contacts[0] = client.contacts[0].rebuild((b) => b
|
..contacts[0] = client.contacts[0].rebuild((b) => b
|
||||||
..firstName = contact.givenName ?? ''
|
..firstName = (contact?.givenName ?? '').trim()
|
||||||
..lastName = contact.familyName ?? ''
|
..lastName = (contact?.familyName ?? '').trim()
|
||||||
..email = contactEmail.value ?? ''
|
..email = (contactEmail?.value ?? '').trim()
|
||||||
..phone = contactPhone.value ?? '')
|
..phone = (contactPhone?.value ?? '').trim())
|
||||||
..updatedAt = DateTime.now().millisecondsSinceEpoch));
|
..updatedAt = DateTime.now().millisecondsSinceEpoch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import 'package:contacts_service/contacts_service.dart';
|
||||||
// Project imports:
|
// Project imports:
|
||||||
import 'package:invoiceninja_flutter/constants.dart';
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
||||||
|
|
@ -129,24 +130,24 @@ class VendorEditDetailsState extends State<VendorEditDetails> {
|
||||||
String countryId;
|
String countryId;
|
||||||
|
|
||||||
countryMap.keys.forEach((countryId) {
|
countryMap.keys.forEach((countryId) {
|
||||||
final country = countryMap[countryId];
|
final country = countryMap[countryId] ?? CountryEntity();
|
||||||
if (country.name.toLowerCase() == contactAddress.country.toLowerCase()) {
|
if (country.name.toLowerCase() == contactAddress?.country?.toLowerCase()) {
|
||||||
countryId = country.id;
|
countryId = country.id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
widget.viewModel.onChanged(vendor.rebuild((b) => b
|
widget.viewModel.onChanged(vendor.rebuild((b) => b
|
||||||
..name = contact.company ?? ''
|
..name = (contact?.company ?? '').trim()
|
||||||
..address1 = contactAddress.street ?? ''
|
..address1 = (contactAddress?.street ?? '').trim()
|
||||||
..city = contactAddress.city ?? ''
|
..city = (contactAddress?.city ?? '').trim()
|
||||||
..state = contactAddress.region ?? ''
|
..state = (contactAddress?.region ?? '').trim()
|
||||||
..postalCode = contactAddress.postcode ?? ''
|
..postalCode = (contactAddress?.postcode ?? '').trim()
|
||||||
..countryId = countryId
|
..countryId = countryId ?? ''
|
||||||
..contacts[0] = vendor.contacts[0].rebuild((b) => b
|
..contacts[0] = vendor.contacts[0].rebuild((b) => b
|
||||||
..firstName = contact.givenName ?? ''
|
..firstName = (contact?.givenName ?? '').trim()
|
||||||
..lastName = contact.familyName ?? ''
|
..lastName = (contact?.familyName ?? '').trim()
|
||||||
..email = contactEmail.value ?? ''
|
..email = (contactEmail?.value ?? '').trim()
|
||||||
..phone = contactPhone.value ?? '')
|
..phone = (contactPhone?.value ?? '').trim())
|
||||||
..updatedAt = DateTime.now().millisecondsSinceEpoch));
|
..updatedAt = DateTime.now().millisecondsSinceEpoch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue