diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1487234c..9328c309 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -136,7 +136,7 @@ These tests require the Firebase Emulator. To start the Firebase Emulator, run this command: ```bash -firebase emulator:start +melos emulator:start ``` Once the Firebase Emulator is up and running, execute the following Melos command from the terminal: diff --git a/packages/firebase_ui_oauth/lib/src/oauth_provider_button_base.dart b/packages/firebase_ui_oauth/lib/src/oauth_provider_button_base.dart index c12d5795..b9a83594 100644 --- a/packages/firebase_ui_oauth/lib/src/oauth_provider_button_base.dart +++ b/packages/firebase_ui_oauth/lib/src/oauth_provider_button_base.dart @@ -388,17 +388,11 @@ class _ButtonContent extends StatelessWidget { required this.iconBackgroundColor, }); - Widget _buildLoadingIndicator() { - return SizedBox( - height: fontSize, - width: fontSize, - child: loadingIndicator, - ); - } + static const kEndPadding = 16.0; @override Widget build(BuildContext context) { - Widget child = Padding( + final icon = Padding( padding: EdgeInsets.all(iconPadding), child: SvgPicture.string( iconSrc, @@ -407,39 +401,96 @@ class _ButtonContent extends StatelessWidget { ), ); - if (label.isNotEmpty) { - final content = isLoading - ? _buildLoadingIndicator() - : Text( - label, - textAlign: TextAlign.center, - style: TextStyle( - height: 1.1, - color: textColor, - fontSize: fontSize, - ), - ); - - final isCupertino = CupertinoUserInterfaceLevel.maybeOf(context) != null; - final topMargin = isCupertino ? (height - fontSize) / 2 : 0.0; + if (label.isEmpty) { + if (!isLoading) return icon; - child = Stack( - children: [ - child, - Align( - alignment: AlignmentDirectional.center, - child: Padding( - padding: EdgeInsets.only(top: topMargin), - child: content, - ), - ), - ], + return SizedBox.square( + dimension: fontSize, + child: loadingIndicator, ); - } else if (isLoading) { - child = _buildLoadingIndicator(); } - return child; + final text = TextSpan( + text: label, + style: TextStyle( + height: 1.1, + color: textColor, + fontSize: fontSize, + ), + ); + + return Row( + children: [ + // + icon, + // + Expanded( + child: LayoutBuilder( + builder: (context, constraints) { + // + final availableWidth = constraints.maxWidth; + + // "height" is also the button's width + final totalIconWidth = height + (iconPadding * 2); + final totalButtonWidth = + availableWidth + totalIconWidth + kEndPadding; + + if (isLoading) { + // "fontSize" is also the indicator's width + final freeSpace = totalButtonWidth - fontSize; + final startPadding = + (freeSpace / 2 - totalIconWidth).clamp(0.0, availableWidth); + + return Padding( + padding: EdgeInsetsDirectional.only( + start: startPadding, + ), + child: Align( + alignment: AlignmentDirectional.centerStart, + child: SizedBox.square( + dimension: fontSize, + child: loadingIndicator, + ), + ), + ); + } + + final isCupertino = + CupertinoUserInterfaceLevel.maybeOf(context) != null; + final topPadding = isCupertino ? (height - fontSize) / 2 : 0.0; + + final textWidth = (TextPainter( + text: text, + textDirection: Directionality.of(context), + maxLines: 1, + )..layout(maxWidth: availableWidth)) + .size + .width; + final freeSpace = totalButtonWidth - textWidth; + final startPadding = + (freeSpace / 2 - totalIconWidth).clamp(0.0, availableWidth); + + return Padding( + padding: EdgeInsetsDirectional.only( + top: topPadding, + start: startPadding, + ), + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: AlignmentDirectional.centerStart, + child: Text.rich( + text, + style: text.style, + ), + ), + ); + }, + ), + ), + // + const SizedBox(width: kEndPadding), + ], + ); } } diff --git a/packages/firebase_ui_oauth/test/flutterfire_ui_oauth_test.dart b/packages/firebase_ui_oauth/test/flutterfire_ui_oauth_test.dart index b80f1480..7abdad99 100644 --- a/packages/firebase_ui_oauth/test/flutterfire_ui_oauth_test.dart +++ b/packages/firebase_ui_oauth/test/flutterfire_ui_oauth_test.dart @@ -205,11 +205,13 @@ void main() { home: Scaffold( body: Row( children: [ - OAuthProviderButtonBase( - provider: provider, - auth: FakeAuth(), - label: 'Sign in with Fake provider', - loadingIndicator: const CircularProgressIndicator(), + Expanded( + child: OAuthProviderButtonBase( + provider: provider, + auth: FakeAuth(), + label: 'Sign in with Fake provider', + loadingIndicator: const CircularProgressIndicator(), + ), ) ], ),