Skip to content

Commit

Permalink
refactor(ui): refactor platform specific widget styling (#8333)
Browse files Browse the repository at this point in the history
  • Loading branch information
lesnitsky committed Mar 29, 2022
1 parent 1937f27 commit ecbff15
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 118 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart'
show FirebaseAuth, FirebaseAuthException;
import 'package:flutter/cupertino.dart';
import 'package:flutterfire_ui/auth.dart';
import 'package:flutterfire_ui/i10n.dart';
import '../widgets/internal/loading_button.dart';
import 'package:flutter/material.dart';
import '../widgets/internal/universal_button.dart';

typedef DeleteFailedCallback = void Function(Exception exception);
typedef SignInRequiredCallback = Future<bool> Function();
Expand All @@ -13,12 +14,14 @@ class DeleteAccountButton extends StatefulWidget {
final FirebaseAuth? auth;
final SignInRequiredCallback? onSignInRequired;
final DeleteFailedCallback? onDeleteFailed;
final ButtonVariant? variant;

const DeleteAccountButton({
Key? key,
this.auth,
this.onSignInRequired,
this.onDeleteFailed,
this.variant,
}) : super(key: key);

@override
Expand Down Expand Up @@ -67,6 +70,7 @@ class _DeleteAccountButtonState extends State<DeleteAccountButton> {
icon: isCupertino ? CupertinoIcons.delete : Icons.delete,
label: l.deleteAccount,
onTap: _deleteAccount,
variant: widget.variant,
);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutterfire_ui/auth.dart';

class LoadingButton extends StatelessWidget {
final bool isLoading;
final String label;
final IconData? icon;
final Color? color;
final VoidCallback onTap;
import 'universal_button.dart';

const LoadingButton({
class _LoadingButtonContent extends StatelessWidget {
final String label;
final bool isLoading;
const _LoadingButtonContent({
Key? key,
required this.label,
required this.onTap,
this.isLoading = false,
this.icon,
this.color,
required this.isLoading,
}) : super(key: key);

@override
Expand All @@ -31,59 +25,38 @@ class LoadingButton extends StatelessWidget {
);
}

ButtonStyle? style;

if (color != null) {
style = ButtonStyle(
foregroundColor: MaterialStateColor.resolveWith(
(states) => color!,
),
overlayColor: MaterialStateColor.resolveWith(
(states) => color!.withAlpha(20),
),
);
}

if (isCupertino) {
if (icon != null) {
child = Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(icon, size: 20),
const SizedBox(width: 8),
child,
],
);
}
return child;
}
}

final button = CupertinoButton.filled(
onPressed: onTap,
child: child,
);
class LoadingButton extends StatelessWidget {
final bool isLoading;
final String label;
final IconData? icon;
final Color? color;
final VoidCallback onTap;
final ButtonVariant? variant;

return color != null
? CupertinoTheme(
data: CupertinoTheme.of(context).copyWith(
primaryColor: color,
),
child: button,
)
: button;
}
const LoadingButton({
Key? key,
required this.label,
required this.onTap,
this.isLoading = false,
this.icon,
this.color,
this.variant = ButtonVariant.text,
}) : super(key: key);

if (icon != null) {
return OutlinedButton.icon(
onPressed: onTap,
icon: Icon(icon),
label: child,
style: style,
);
}
@override
Widget build(BuildContext context) {
final content = _LoadingButtonContent(label: label, isLoading: isLoading);

return OutlinedButton(
return UniversalButton(
color: color,
icon: icon,
onPressed: onTap,
style: style,
child: child,
variant: variant,
child: content,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@ abstract class PlatformWidget extends StatelessWidget {
Widget buildCupertino(BuildContext context);
Widget buildMaterial(BuildContext context);

Widget? buildWrapper(BuildContext context, Widget child) {
return null;
}

@override
Widget build(BuildContext context) {
final isCupertino = CupertinoUserInterfaceLevel.maybeOf(context) != null;
late Widget child;

if (isCupertino) {
return buildCupertino(context);
child = buildCupertino(context);
} else {
child = buildMaterial(context);
}

final wrapper = buildWrapper(context, child);

if (wrapper == null) {
return child;
} else {
return buildMaterial(context);
return wrapper;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'platform_widget.dart';

class Subtitle extends StatelessWidget {
class Subtitle extends PlatformWidget {
final String text;
const Subtitle({Key? key, required this.text}) : super(key: key);

@override
Widget build(BuildContext context) {
final isCupertino = CupertinoUserInterfaceLevel.maybeOf(context) != null;
final titleStyle = isCupertino
? CupertinoTheme.of(context).textTheme.navTitleTextStyle
: Theme.of(context).textTheme.subtitle1;
Widget buildCupertino(BuildContext context) {
return Text(
text,
style: CupertinoTheme.of(context).textTheme.navTitleTextStyle,
);
}

@override
Widget buildMaterial(BuildContext context) {
return Text(
text,
style: titleStyle,
style: Theme.of(context).textTheme.subtitle1,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,78 +6,144 @@ import 'platform_widget.dart';
enum ButtonVariant {
text,
filled,
outlined,
}

class UniversalButton extends PlatformWidget {
final VoidCallback? onPressed;
final String text;
final String? text;
final Widget? child;
final IconData? icon;
final TextDirection? direction;
final ButtonVariant variant;
final ButtonVariant? variant;
final Color? color;

const UniversalButton({
Key? key,
required this.text,
this.text,
this.child,
this.onPressed,
this.icon,
this.direction,
this.variant = ButtonVariant.filled,
}) : super(key: key);
this.direction = TextDirection.ltr,
this.variant,
this.color,
}) : assert(text != null || child != null),
super(key: key);

ButtonVariant get _variant {
return variant ?? ButtonVariant.filled;
}

@override
Widget buildCupertino(BuildContext context) {
late Widget button;

final child = Row(
textDirection: direction,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(text),
if (icon != null) ...[const SizedBox(width: 8), Icon(icon, size: 20)],
if (icon != null) ...[
if (direction == TextDirection.rtl) const SizedBox(width: 8),
Icon(icon, size: 20),
if (direction == TextDirection.ltr) const SizedBox(width: 8),
],
this.child ?? Text(text!),
],
);

if (variant == ButtonVariant.text) {
return CupertinoButton(
if (_variant == ButtonVariant.text || _variant == ButtonVariant.outlined) {
button = CupertinoButton(
padding: EdgeInsets.zero,
onPressed: onPressed,
child: child,
);
} else {
return CupertinoButton.filled(
button = CupertinoButton.filled(
onPressed: onPressed,
child: child,
);
}

if (color != null) {
return CupertinoTheme(
data: CupertinoTheme.of(context).copyWith(primaryColor: color),
child: button,
);
} else {
return button;
}
}

@override
Widget buildMaterial(BuildContext context) {
final child = Text(text);
final child = this.child ?? Text(text!);

ButtonStyle? style;

if (color != null) {
MaterialStateColor? foregroundColor;
MaterialStateColor? backgroundColor;

if (icon != null) {
if (variant == ButtonVariant.text) {
return TextButton.icon(
icon: Icon(icon),
onPressed: onPressed,
label: child,
);
foregroundColor = MaterialStateColor.resolveWith((_) => color!);
} else {
return ElevatedButton.icon(
icon: Icon(icon),
onPressed: onPressed,
label: child,
);
backgroundColor = MaterialStateColor.resolveWith((_) => color!);
}
} else {
if (variant == ButtonVariant.text) {
return TextButton(
onPressed: onPressed,
child: child,
);
} else {}
return ElevatedButton(
onPressed: onPressed,
child: child,

style = ButtonStyle(
foregroundColor: foregroundColor,
backgroundColor: backgroundColor,
overlayColor: MaterialStateColor.resolveWith(
(states) => color!.withAlpha(20),
),
);
}

if (icon != null) {
switch (_variant) {
case ButtonVariant.text:
return TextButton.icon(
icon: Icon(icon),
onPressed: onPressed,
label: child,
style: style,
);
case ButtonVariant.filled:
return ElevatedButton.icon(
onPressed: onPressed,
icon: Icon(icon),
label: child,
style: style,
);
case ButtonVariant.outlined:
return OutlinedButton.icon(
onPressed: onPressed,
icon: Icon(icon),
label: child,
style: style,
);
}
} else {
switch (_variant) {
case ButtonVariant.text:
return TextButton(
onPressed: onPressed,
style: style,
child: child,
);
case ButtonVariant.filled:
return ElevatedButton(
onPressed: onPressed,
style: style,
child: child,
);
case ButtonVariant.outlined:
return OutlinedButton(
onPressed: onPressed,
style: style,
child: child,
);
}
}
}
}

0 comments on commit ecbff15

Please sign in to comment.