Skip to content

feat(ui_auth): allow to toggle password visibility #104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class LoginScreen extends StatelessWidget {
final double breakpoint;
final Set<FirebaseUIStyle>? styles;

/// {@macro ui.auth.widgets.email_form.showPasswordVisibilityToggle}
final bool showPasswordVisibilityToggle;

const LoginScreen({
super.key,
required this.action,
Expand All @@ -69,6 +72,7 @@ class LoginScreen extends StatelessWidget {
this.loginViewKey,
this.breakpoint = 800,
this.styles,
this.showPasswordVisibilityToggle = false,
});

@override
Expand All @@ -87,6 +91,7 @@ class LoginScreen extends StatelessWidget {
showAuthActionSwitch: showAuthActionSwitch,
subtitleBuilder: subtitleBuilder,
footerBuilder: footerBuilder,
showPasswordVisibilityToggle: showPasswordVisibilityToggle,
),
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@ class DifferentMethodSignInView extends StatelessWidget {
/// the [availableProviders].
final VoidCallback? onSignedIn;

/// {@macro ui.auth.widgets.email_from.showPasswordVisibilityToggle}
final bool showPasswordVisibilityToggle;

/// {@macro ui.auth.views.different_method_sign_in_view}
const DifferentMethodSignInView({
super.key,
required this.availableProviders,
required this.providers,
this.auth,
this.onSignedIn,
this.showPasswordVisibilityToggle = false,
});

@override
Expand Down Expand Up @@ -59,6 +63,7 @@ class DifferentMethodSignInView extends StatelessWidget {
action: AuthAction.signIn,
providers: providers,
showTitle: false,
showPasswordVisibilityToggle: showPasswordVisibilityToggle,
),
listener: (oldState, newState, ctrl) {
if (newState is SignedIn) {
Expand Down
6 changes: 6 additions & 0 deletions packages/firebase_ui_auth/lib/src/views/login_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class LoginView extends StatefulWidget {
/// A label that would be used for the "Sign in" button.
final String? actionButtonLabelOverride;

/// {@macro ui.auth.widgets.email_from.showPasswordVisibilityToggle}
final bool showPasswordVisibilityToggle;

/// {@macro ui.auth.views.login_view}
const LoginView({
super.key,
Expand All @@ -68,6 +71,7 @@ class LoginView extends StatefulWidget {
this.footerBuilder,
this.subtitleBuilder,
this.actionButtonLabelOverride,
this.showPasswordVisibilityToggle = false,
});

@override
Expand Down Expand Up @@ -222,6 +226,8 @@ class _LoginViewState extends State<LoginView> {
provider: provider,
email: widget.email,
actionButtonLabelOverride: widget.actionButtonLabelOverride,
showPasswordVisibilityToggle:
widget.showPasswordVisibilityToggle,
)
] else if (provider is PhoneAuthProvider) ...[
const SizedBox(height: 8),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ class ReauthenticateView extends StatelessWidget {
/// A label that would be used for the "Sign in" button.
final String? actionButtonLabelOverride;

/// {@macro ui.auth.widgets.email_from.showPasswordVisibilityToggle}
final bool showPasswordVisibilityToggle;

/// {@macro ui.auth.views.reauthenticate_view}
const ReauthenticateView({
super.key,
required this.providers,
this.auth,
this.onSignedIn,
this.actionButtonLabelOverride,
this.showPasswordVisibilityToggle = false,
});

@override
Expand Down Expand Up @@ -63,6 +67,7 @@ class ReauthenticateView extends StatelessWidget {
showTitle: false,
showAuthActionSwitch: false,
actionButtonLabelOverride: actionButtonLabelOverride,
showPasswordVisibilityToggle: showPasswordVisibilityToggle,
),
listener: (oldState, newState, ctrl) {
if (newState is SignedIn) {
Expand Down
11 changes: 11 additions & 0 deletions packages/firebase_ui_auth/lib/src/widgets/email_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ class EmailForm extends StatelessWidget {
/// ```
final EmailFormStyle? style;

/// {@template ui.auth.widgets.email_from.showPasswordVisibilityToggle}
/// Whether to show the password visibility toggle button.
/// {@endtemplate}
final bool showPasswordVisibilityToggle;

/// {@macro ui.auth.widgets.email_form}
const EmailForm({
super.key,
Expand All @@ -141,6 +146,7 @@ class EmailForm extends StatelessWidget {
this.email,
this.actionButtonLabelOverride,
this.style,
this.showPasswordVisibilityToggle = false,
});

@override
Expand All @@ -153,6 +159,7 @@ class EmailForm extends StatelessWidget {
onSubmit: onSubmit,
actionButtonLabelOverride: actionButtonLabelOverride,
style: style,
showPasswordVisibilityToggle: showPasswordVisibilityToggle,
);

return AuthFlowBuilder<EmailAuthController>(
Expand All @@ -175,6 +182,7 @@ class _SignInFormContent extends StatefulWidget {
final EmailAuthProvider? provider;

final String? actionButtonLabelOverride;
final bool showPasswordVisibilityToggle;

final EmailFormStyle? style;

Expand All @@ -186,6 +194,7 @@ class _SignInFormContent extends StatefulWidget {
this.provider,
this.actionButtonLabelOverride,
this.style,
this.showPasswordVisibilityToggle = false,
});

@override
Expand Down Expand Up @@ -258,6 +267,7 @@ class _SignInFormContentState extends State<_SignInFormContent> {
controller: passwordCtrl,
onSubmit: _submit,
placeholder: l.passwordInputLabel,
showVisibilityToggle: widget.showPasswordVisibilityToggle,
),
if (widget.action == AuthAction.signIn) ...[
const SizedBox(height: 8),
Expand Down Expand Up @@ -297,6 +307,7 @@ class _SignInFormContentState extends State<_SignInFormContent> {
)
]),
placeholder: l.confirmPasswordInputLabel,
showVisibilityToggle: widget.showPasswordVisibilityToggle,
),
const SizedBox(height: 8),
],
Expand Down
80 changes: 52 additions & 28 deletions packages/firebase_ui_auth/lib/src/widgets/email_sign_up_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,50 +23,74 @@ class EmailSignUpDialog extends StatelessWidget {
/// An instance of [EmailAuthProvider] that should be used to authenticate.
final EmailAuthProvider provider;

/// {@macro ui.auth.widgets.email_from.showPasswordVisibilityToggle}
final bool showPasswordVisibilityToggle;

/// {@macro ui.auth.widget.email_sign_up_dialog}
const EmailSignUpDialog({
super.key,
this.auth,
required this.provider,
required this.action,
this.showPasswordVisibilityToggle = false,
});

AuthStateListenerCallback<EmailAuthController> onAuthStateChanged(
BuildContext context,
) {
return (AuthState oldState, AuthState newState, _) {
if (newState is CredentialLinked) {
Navigator.of(context).pop();
}

return null;
};
}

@override
Widget build(BuildContext context) {
final l = FirebaseUILocalizations.labelsOf(context);

return _DialogWrapper(
child: Dialog(
child: AuthStateListener<EmailAuthController>(
listener: onAuthStateChanged(context),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 16),
Title(text: l.provideEmail),
const SizedBox(height: 32),
EmailForm(
auth: auth,
action: action,
provider: provider,
showPasswordVisibilityToggle: showPasswordVisibilityToggle,
),
],
),
),
),
),
);
}
}

class _DialogWrapper extends StatelessWidget {
final Widget child;

const _DialogWrapper({required this.child});

@override
Widget build(BuildContext context) {
return Center(
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 500),
child: Dialog(
child: AuthStateListener<EmailAuthController>(
listener: (oldState, newState, ctrl) {
if (newState is CredentialLinked) {
Navigator.of(context).pop();
}

return null;
},
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 16),
Title(text: l.provideEmail),
const SizedBox(height: 32),
EmailForm(
auth: auth,
action: action,
provider: provider,
),
],
),
),
),
),
child: child,
),
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class UniversalIconButton extends PlatformWidget {
Widget buildCupertino(BuildContext context) {
return CupertinoButton(
onPressed: onPressed,
padding: EdgeInsets.zero,
child: Icon(cupertinoIcon, size: size),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class UniversalTextFormField extends PlatformWidget {
final bool autocorrect;
final Widget? prefix;
final Iterable<String>? autofillHints;
final Widget? suffixIcon;

const UniversalTextFormField({
super.key,
Expand All @@ -40,34 +41,49 @@ class UniversalTextFormField extends PlatformWidget {
this.enableSuggestions,
this.autocorrect = false,
this.autofillHints,
this.suffixIcon,
});

@override
Widget buildCupertino(BuildContext context) {
return Container(
padding: const EdgeInsets.only(bottom: 8),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: CupertinoColors.inactiveGray,
return Stack(
children: [
Container(
padding: const EdgeInsets.only(bottom: 8),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: CupertinoColors.inactiveGray,
),
),
),
child: CupertinoTextFormFieldRow(
autocorrect: autocorrect,
autofillHints: autofillHints,
focusNode: focusNode,
padding: EdgeInsets.zero,
controller: controller,
placeholder: placeholder,
validator: validator,
onFieldSubmitted: onSubmitted,
autofocus: autofocus,
inputFormatters: inputFormatters,
keyboardType: keyboardType,
obscureText: obscureText,
prefix: prefix,
),
),
),
child: CupertinoTextFormFieldRow(
autocorrect: autocorrect,
autofillHints: autofillHints,
focusNode: focusNode,
padding: EdgeInsets.zero,
controller: controller,
placeholder: placeholder,
validator: validator,
onFieldSubmitted: onSubmitted,
autofocus: autofocus,
inputFormatters: inputFormatters,
keyboardType: keyboardType,
obscureText: obscureText,
prefix: prefix,
),
if (suffixIcon != null)
Positioned.fill(
child: Align(
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: suffixIcon,
),
),
),
],
);
}

Expand All @@ -82,6 +98,7 @@ class UniversalTextFormField extends PlatformWidget {
decoration: InputDecoration(
labelText: placeholder,
prefix: prefix,
suffixIcon: suffixIcon,
),
validator: validator,
onFieldSubmitted: onSubmitted,
Expand Down
Loading