Microsoft Login

This commit is contained in:
Hillel Coren 2022-06-19 11:55:08 +03:00
parent 9b60c43388
commit d29be59a6a
11 changed files with 212 additions and 37 deletions

View File

@ -20,8 +20,10 @@ class AppToggleButtons extends StatelessWidget {
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
final bool isDesktop = calculateLayout(context) != AppLayout.mobile;
final double toggleWidth =
isDesktop ? 208 : (constraints.maxWidth - 36) / 2;
double toggleWidth = (constraints.maxWidth - 36) / tabLabels.length;
if (isDesktop) {
toggleWidth -= 46 / tabLabels.length;
}
return Padding(
padding: const EdgeInsets.only(bottom: 20),
@ -37,8 +39,22 @@ class AppToggleButtons extends StatelessWidget {
height: 40,
child: Center(child: Text(tabLabels[1])),
),
if (tabLabels.length == 3)
Container(
width: toggleWidth,
height: 40,
child: Center(child: Text(tabLabels[2])),
),
],
isSelected: selectedIndex == 0 ? [true, false] : [false, true],
isSelected: tabLabels.length == 3
? (selectedIndex == 0
? [true, false, false]
: selectedIndex == 1
? [false, true, false]
: [false, false, true])
: selectedIndex == 0
? [true, false]
: [false, true],
onPressed: (index) => onTabChanged(index),
),
);

View File

@ -62,10 +62,14 @@ class _LoginState extends State<LoginView> {
static const String OTP_ERROR = 'OTP_REQUIRED';
static const String LOGIN_TYPE_EMAIL = 'email';
static const String LOGIN_TYPE_GOOGLE = 'google';
static const String LOGIN_TYPE_MICROSOFT = 'microsoft';
String _loginError = '';
String _loginType = LOGIN_TYPE_GOOGLE;
bool _tokenLogin = false;
bool _emailLogin = false;
bool _isSelfHosted = false;
bool _createAccount = false;
bool _hideGoogle = false;
@ -83,15 +87,15 @@ class _LoginState extends State<LoginView> {
final authState = widget.viewModel.authState;
_isSelfHosted = authState.isSelfHost;
if (_isSelfHosted) {
_emailLogin = true;
_loginType = LOGIN_TYPE_EMAIL;
} else if (WebUtils.getHtmlValue('login') == 'false') {
_createAccount = true;
}
} else if (isApple() || !GoogleOAuth.isEnabled) {
_emailLogin = true;
_loginType = LOGIN_TYPE_EMAIL;
_hideGoogle = true;
} else if (isWindows() || isLinux()) {
_emailLogin = true;
_loginType = LOGIN_TYPE_EMAIL;
_hideGoogle = true;
}
}
@ -107,7 +111,7 @@ class _LoginState extends State<LoginView> {
_lastNameController.text = 'TEST';
_privacyChecked = true;
_termsChecked = true;
_emailLogin = true;
_loginType = LOGIN_TYPE_EMAIL;
}
if (_urlController.text.isEmpty) {
@ -192,7 +196,7 @@ class _LoginState extends State<LoginView> {
});
});
if (_emailLogin) {
if (_loginType == LOGIN_TYPE_EMAIL) {
viewModel.onSignUpPressed(
context,
completer,
@ -249,7 +253,7 @@ class _LoginState extends State<LoginView> {
? kAppStagingUrl
: kAppProductionUrl;
if (_emailLogin) {
if (_loginType == LOGIN_TYPE_EMAIL) {
if (_recoverPassword) {
viewModel.onRecoverPressed(
context,
@ -376,33 +380,33 @@ class _LoginState extends State<LoginView> {
_createAccount = false;
_loginError = '';
if (index == 1) {
_emailLogin = true;
_loginType == LOGIN_TYPE_EMAIL;
}
});
},
),
],
if (!_isSelfHosted && !_hideGoogle) ...[
if (!_isSelfHosted &&
(!kReleaseMode || !_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,
tabLabels: [
'Google',
'Microsoft',
localization.email,
],
selectedIndex: _loginType == LOGIN_TYPE_EMAIL
? 2
: _loginType == LOGIN_TYPE_MICROSOFT
? 1
: 0,
onTabChanged: (index) {
setState(() {
_emailLogin = index == 1;
_loginType = index == 2
? LOGIN_TYPE_EMAIL
: index == 1
? LOGIN_TYPE_MICROSOFT
: LOGIN_TYPE_GOOGLE;
_loginError = '';
});
},
@ -413,7 +417,7 @@ class _LoginState extends State<LoginView> {
horizontal: horizontalPadding),
child: Column(
children: [
if (_emailLogin)
if (_loginType == LOGIN_TYPE_EMAIL)
DecoratedFormField(
controller: _emailController,
label: localization.email,
@ -427,7 +431,8 @@ class _LoginState extends State<LoginView> {
autofocus: true,
onSavePressed: (_) => _submitForm(),
),
if (_emailLogin && !_recoverPassword)
if (_loginType == LOGIN_TYPE_EMAIL &&
!_recoverPassword)
PasswordFormField(
controller: _passwordController,
autoValidate: false,
@ -568,7 +573,7 @@ class _LoginState extends State<LoginView> {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (_emailLogin)
if (_loginType == LOGIN_TYPE_EMAIL)
Icon(Icons.mail, color: Colors.white)
else
ClipOval(
@ -582,12 +587,16 @@ class _LoginState extends State<LoginView> {
_recoverPassword
? localization.recoverPassword
: _createAccount
? (_emailLogin
? (_loginType == LOGIN_TYPE_EMAIL
? localization.emailSignUp
: localization.googleSignUp)
: (_emailLogin
: _loginType == LOGIN_TYPE_MICROSOFT
? localization.microsoftSignUp
: localization.googleSignUp)
: (_loginType == LOGIN_TYPE_EMAIL
? localization.emailSignIn
: localization.googleSignIn),
: _loginType == LOGIN_TYPE_MICROSOFT
? localization.microsoftSignIn
: localization.googleSignIn),
style:
TextStyle(fontSize: 18, color: Colors.white),
)

View File

@ -55,6 +55,8 @@ class LoginVM {
@required this.onSignUpPressed,
@required this.onGoogleLoginPressed,
@required this.onGoogleSignUpPressed,
@required this.onMicrosoftLoginPressed,
@required this.onMicrosoftSignUpPressed,
@required this.onTokenLoginPressed,
});
@ -97,6 +99,13 @@ class LoginVM {
{String url, String secret, String oneTimePassword}) onGoogleLoginPressed;
final Function(BuildContext, Completer<Null> completer) onGoogleSignUpPressed;
final Function(BuildContext, Completer<Null> completer,
{String url,
String secret,
String oneTimePassword}) onMicrosoftLoginPressed;
final Function(BuildContext, Completer<Null> completer)
onMicrosoftSignUpPressed;
static LoginVM fromStore(Store<AppState> store) {
void _handleLogin({BuildContext context, bool isSignUp = false}) {
final layout = calculateLayout(context);
@ -201,6 +210,74 @@ class LoginVM {
print('## onGoogleSignUpPressed: $error');
}
},
onMicrosoftLoginPressed: (
BuildContext context,
Completer<Null> completer, {
@required String url,
@required String secret,
@required String oneTimePassword,
}) async {
try {
/*
await GoogleOAuth.signOut();
final signedIn = await GoogleOAuth.signIn((idToken, accessToken) {
if (idToken.isEmpty || accessToken.isEmpty) {
GoogleOAuth.signOut();
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
} else {
store.dispatch(OAuthLoginRequest(
completer: completer,
idToken: idToken,
accessToken: accessToken,
url: _formatApiUrl(url),
secret: secret.trim(),
platform: getPlatform(context),
oneTimePassword: oneTimePassword,
));
completer.future.then((_) => _handleLogin(context: context));
}
});
if (!signedIn) {
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
}
*/
} catch (error) {
completer.completeError(error);
print('## onMicrosoftLoginPressed: $error');
}
},
onMicrosoftSignUpPressed:
(BuildContext context, Completer<Null> completer) async {
try {
/*
await GoogleOAuth.signOut();
final signedIn = await GoogleOAuth.signUp((idToken, accessToken) {
if (idToken.isEmpty || accessToken.isEmpty) {
GoogleOAuth.signOut();
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
} else {
store.dispatch(OAuthSignUpRequest(
completer: completer,
idToken: idToken,
accessToken: accessToken,
));
completer.future
.then((_) => _handleLogin(context: context, isSignUp: true));
}
});
if (!signedIn) {
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
}
*/
} catch (error) {
completer.completeError(error);
print('## onMicrosoftSignUpPressed: $error');
}
},
onSignUpPressed: (
BuildContext context,
Completer<Null> completer, {

View File

@ -16,6 +16,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = {
'en': {
// STARTER: lang key - do not remove comment
'microsoft_sign_in': 'Login with Microsoft',
'microsoft_sign_up': 'Sign up with Microsoft',
'emailed_purchase_order': 'Successfully queued purchase order to be sent',
'emailed_purchase_orders':
'Successfully queued purchase orders to be sent',
@ -70699,6 +70701,16 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]['emailed_purchase_orders'] ??
_localizedValues['en']['emailed_purchase_orders'];
String get microsoftSignUp =>
_localizedValues[localeCode]['microsoft_sign_up'] ??
_localizedValues['en']['microsoft_sign_up'] ??
'';
String get microsoftSignIn =>
_localizedValues[localeCode]['microsoft_sign_in'] ??
_localizedValues['en']['microsoft_sign_in'] ??
'';
// STARTER: lang field - do not remove comment
String lookup(String key) {

View File

@ -6,11 +6,15 @@
#include "generated_plugin_registrant.h"
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
#include <printing/printing_plugin.h>
#include <sentry_flutter/sentry_flutter_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
g_autoptr(FlPluginRegistrar) printing_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin");
printing_plugin_register_with_registrar(printing_registrar);

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_linux
printing
sentry_flutter
url_launcher_linux

View File

@ -5,6 +5,7 @@
import FlutterMacOS
import Foundation
import flutter_secure_storage_macos
import package_info
import package_info_plus_macos
import path_provider_macos
@ -15,6 +16,7 @@ import sqflite
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterSecureStorageMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageMacosPlugin"))
FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))

View File

@ -8,6 +8,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "31.0.0"
aad_oauth:
dependency: "direct main"
description:
name: aad_oauth
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0"
analyzer:
dependency: transitive
description:
@ -380,6 +387,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.2"
flutter_secure_storage:
dependency: transitive
description:
name: flutter_secure_storage
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.2"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
flutter_slidable:
dependency: "direct main"
description:
@ -1380,7 +1429,7 @@ packages:
name: webview_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.0"
version: "3.0.4"
webview_flutter_android:
dependency: transitive
description:

View File

@ -45,7 +45,7 @@ dependencies:
image_picker: ^0.8.3+1
flutter_colorpicker: ^1.0.3
flutter_json_viewer: ^1.0.1
webview_flutter: ^2.0.10
webview_flutter: ^3.0.4
timeago: ^3.1.0
package_info: ^2.0.2
rounded_loading_button: ^2.0.5
@ -69,6 +69,7 @@ dependencies:
html2md: ^1.2.5
printing: ^5.8.0
image_cropper: ^2.0.2
aad_oauth: ^0.4.0
# bitsdojo_window: ^0.1.2
# quick_actions: ^0.2.1
# idb_shim: ^1.11.1+1

View File

@ -6,11 +6,14 @@
#include "generated_plugin_registrant.h"
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <printing/printing_plugin.h>
#include <sentry_flutter/sentry_flutter_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
PrintingPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PrintingPlugin"));
SentryFlutterPluginRegisterWithRegistrar(

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_windows
printing
sentry_flutter
url_launcher_windows