Skip to content

Commit

Permalink
Align logos and sort Apple first (#1161)
Browse files Browse the repository at this point in the history
  • Loading branch information
dnys1 authored Dec 1, 2021
1 parent 9bf1e5b commit a7b0607
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 28 deletions.
35 changes: 23 additions & 12 deletions packages/amplify_authenticator/lib/src/widgets/form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class AuthenticatorFormState<T extends AuthenticatorForm<T>>
List<AuthenticatorFormField> runtimeFields(BuildContext context) => const [];

/// Additional actions defined at runtime.
List<AuthenticatorComponent> runtimeActions(BuildContext context) => const [];
List<Widget> runtimeActions(BuildContext context) => const [];

final ValueNotifier<bool> obscureTextToggleValue = ValueNotifier(true);

Expand Down Expand Up @@ -319,7 +319,7 @@ class _SignInFormState extends AuthenticatorFormState<SignInForm> {
_SignInFormState() : super._();

@override
List<AuthenticatorButton> runtimeActions(BuildContext context) {
List<Widget> runtimeActions(BuildContext context) {
if (!widget.includeDefaultSocialProviders) {
return const [];
}
Expand All @@ -335,21 +335,32 @@ class _SignInFormState extends AuthenticatorFormState<SignInForm> {
return const [];
}

return socialProviders
.map((provider) {
switch (provider) {
// Sort Apple first based off their app guidelines.
socialProviders.sort((a, b) {
if (a == SocialProvider.apple) {
return -1;
} else if (b == SocialProvider.apple) {
return 1;
}
return describeEnum(a).compareTo(describeEnum(b));
});

return [
SocialSignInButtons(
providers: socialProviders.map((e) {
switch (e) {
case SocialProvider.facebook:
return const SocialSignInButton.facebook();
return AuthProvider.facebook;
case SocialProvider.google:
return const SocialSignInButton.google();
return AuthProvider.google;
case SocialProvider.amazon:
return const SocialSignInButton.amazon();
return AuthProvider.amazon;
case SocialProvider.apple:
return const SocialSignInButton.apple();
return AuthProvider.apple;
}
})
.whereType<AuthenticatorButton>()
.toList();
}).toList(),
),
];
}
}

Expand Down
117 changes: 101 additions & 16 deletions packages/amplify_authenticator/lib/src/widgets/social/social_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,78 @@
* permissions and limitations under the License.
*/

import 'dart:math';

import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:amplify_authenticator/src/l10n/auth_strings_resolver.dart';
import 'package:amplify_authenticator/src/state/auth_viewmodel.dart';
import 'package:amplify_authenticator/src/theme/amplify_theme.dart';
import 'package:amplify_authenticator/src/utils/list.dart';
import 'package:amplify_authenticator/src/widgets/button.dart';
import 'package:amplify_authenticator/src/widgets/component.dart';
import 'package:amplify_authenticator/src/widgets/social/social_icons.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class SocialSignInButtons extends StatelessAuthenticatorComponent {
const SocialSignInButtons({
Key? key,
required this.providers,
}) : super(key: key);

final List<AuthProvider> providers;

@override
Widget builder(
BuildContext context,
AuthViewModel viewModel,
AuthStringResolver stringResolver,
) {
return LayoutBuilder(builder: (context, constraints) {
// Perform a layout on each of the Text items to determine the maximum
// width, so that we can size all button labels to that width and align
// the logos in the column.
var maxWidth = 0.0;
for (var provider in providers) {
final text = stringResolver.buttons.resolve(
context,
ButtonResolverKey.signInWith(provider),
);
final style = Theme.of(context)
.outlinedButtonTheme
.style
?.textStyle
?.resolve({}) ??
Theme.of(context).textTheme.button;
final tp = TextPainter(
text: TextSpan(
text: text,
style: style,
),
maxLines: 1,
textDirection: TextDirection.ltr,
)..layout(maxWidth: constraints.maxWidth);
maxWidth = max(maxWidth, tp.width);
}

return Column(
children: <Widget>[
for (var provider in providers)
SocialSignInButton(provider: provider, maxWidth: maxWidth),
].spacedBy(const SizedBox(height: 12)),
);
});
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(IterableProperty<AuthProvider>('providers', providers));
}
}

/// {@template authenticator.social_sign_in_button}
/// A button for launching a social sign in UI.
/// {@endtemplate}
Expand All @@ -32,6 +93,7 @@ class SocialSignInButton extends AuthenticatorButton<SocialSignInButton> {
const SocialSignInButton({
Key? key,
required this.provider,
this.maxWidth = double.infinity,
}) : super(key: key);

/// A social sign-in button for Facebook.
Expand All @@ -53,6 +115,9 @@ class SocialSignInButton extends AuthenticatorButton<SocialSignInButton> {
/// The Cognito social sign-in provider.
final AuthProvider provider;

/// The maximum width of the button texts. Used to align logos properly.
final double maxWidth;

@override
ButtonResolverKey get labelKey => ButtonResolverKey.signInWith(provider);

Expand All @@ -71,11 +136,14 @@ class SocialSignInButton extends AuthenticatorButton<SocialSignInButton> {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(EnumProperty<AuthProvider>('provider', provider));
properties.add(DoubleProperty('maxWidth', maxWidth));
}
}

class _SocialSignInButtonState
extends AuthenticatorButtonState<SocialSignInButton> {
static const _spacing = 5.0;

Widget get icon {
final bool isDark = AmplifyTheme.of(context).isDark;
switch (widget.provider) {
Expand Down Expand Up @@ -106,6 +174,15 @@ class _SocialSignInButtonState
}
}

double calculatePadding(BoxConstraints constraints) {
final logoWidth = constraints.maxHeight + _spacing;
final textWidth = widget.maxWidth;
return max(
0,
(constraints.maxWidth - logoWidth - textWidth) / 2,
);
}

@override
Widget build(BuildContext context) {
final resolver = stringResolver.buttons;
Expand Down Expand Up @@ -136,23 +213,31 @@ class _SocialSignInButtonState
onPressed: viewModel.isBusy
? null
: () => viewModel.signInWithProvider(widget.provider),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: widget.provider.padding,
child: AspectRatio(
aspectRatio: 1,
child: icon,
),
child: LayoutBuilder(builder: (context, constraints) {
final padding = calculatePadding(constraints);
return Padding(
padding: EdgeInsets.symmetric(horizontal: padding),
child: Row(
mainAxisAlignment: padding == 0
? MainAxisAlignment.center
: MainAxisAlignment.start,
children: [
Padding(
padding: widget.provider.padding,
child: AspectRatio(
aspectRatio: 1,
child: icon,
),
),
const SizedBox(width: _spacing),
Text(resolver.resolve(
context,
ButtonResolverKey.signInWith(widget.provider),
)),
],
),
const SizedBox(width: 5),
Text(resolver.resolve(
context,
ButtonResolverKey.signInWith(widget.provider),
)),
],
),
);
}),
),
);
}
Expand Down

0 comments on commit a7b0607

Please sign in to comment.