feat: add how to play dialog (#45)

* feat: add how to play dialog

* style: comma for readability
pull/46/head
Allison Ryan 4 years ago committed by GitHub
parent 78a616ccd1
commit 45f1c6e48b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,6 +4,18 @@
"@play": { "@play": {
"description": "Text displayed on the landing page play button" "description": "Text displayed on the landing page play button"
}, },
"howToPlay": "How to Play",
"@howToPlay": {
"description": "Text displayed on the landing page how to play button"
},
"launchControls": "Launch Controls",
"@launchControls": {
"description": "Text displayed on the how to play dialog with the launch controls"
},
"flipperControls": "Flipper Controls",
"@flipperControls": {
"description": "Text displayed on the how to play dialog with the flipper controls"
},
"start": "Start", "start": "Start",
"@start": { "@start": {
"description": "Text displayed on the character selection page start button" "description": "Text displayed on the character selection page start button"

@ -13,11 +13,181 @@ class LandingPage extends StatelessWidget {
return Scaffold( return Scaffold(
body: Center( body: Center(
child: TextButton( child: Column(
onPressed: () => mainAxisAlignment: MainAxisAlignment.center,
Navigator.of(context).push<void>(CharacterSelectionPage.route()), children: [
TextButton(
onPressed: () => Navigator.of(context).push<void>(
CharacterSelectionPage.route(),
),
child: Text(l10n.play), child: Text(l10n.play),
), ),
TextButton(
onPressed: () => showDialog<void>(
context: context,
builder: (_) => const _HowToPlayDialog(),
),
child: Text(l10n.howToPlay),
),
],
),
),
);
}
}
class _HowToPlayDialog extends StatelessWidget {
const _HowToPlayDialog({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
const spacing = SizedBox(height: 16);
return Dialog(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(l10n.howToPlay),
spacing,
const _LaunchControls(),
spacing,
const _FlipperControls(),
],
),
),
);
}
}
class _LaunchControls extends StatelessWidget {
const _LaunchControls({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
const spacing = SizedBox(width: 10);
return Column(
children: [
Text(l10n.launchControls),
const SizedBox(height: 10),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
KeyIndicator.fromIcon(keyIcon: Icons.keyboard_arrow_down),
spacing,
KeyIndicator.fromKeyName(keyName: 'SPACE'),
spacing,
KeyIndicator.fromKeyName(keyName: 'S'),
],
)
],
);
}
}
class _FlipperControls extends StatelessWidget {
const _FlipperControls({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
const rowSpacing = SizedBox(width: 20);
return Column(
children: [
Text(l10n.flipperControls),
const SizedBox(height: 10),
Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
KeyIndicator.fromIcon(keyIcon: Icons.keyboard_arrow_left),
rowSpacing,
KeyIndicator.fromIcon(keyIcon: Icons.keyboard_arrow_right),
],
),
const SizedBox(height: 8),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
KeyIndicator.fromKeyName(keyName: 'A'),
rowSpacing,
KeyIndicator.fromKeyName(keyName: 'D'),
],
)
],
)
],
);
}
}
// TODO(allisonryan0002): remove visibility when adding final UI.
@visibleForTesting
class KeyIndicator extends StatelessWidget {
const KeyIndicator._({
Key? key,
required String keyName,
required IconData keyIcon,
required bool fromIcon,
}) : _keyName = keyName,
_keyIcon = keyIcon,
_fromIcon = fromIcon,
super(key: key);
const KeyIndicator.fromKeyName({Key? key, required String keyName})
: this._(
key: key,
keyName: keyName,
keyIcon: Icons.keyboard_arrow_down,
fromIcon: false,
);
const KeyIndicator.fromIcon({Key? key, required IconData keyIcon})
: this._(
key: key,
keyName: '',
keyIcon: keyIcon,
fromIcon: true,
);
final String _keyName;
final IconData _keyIcon;
final bool _fromIcon;
@override
Widget build(BuildContext context) {
const iconPadding = EdgeInsets.all(15);
const textPadding = EdgeInsets.symmetric(vertical: 20, horizontal: 22);
final boarderColor = Colors.blue.withOpacity(0.5);
final color = Colors.blue.withOpacity(0.7);
return DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
border: Border.all(
color: boarderColor,
width: 3,
),
),
child: _fromIcon
? Padding(
padding: iconPadding,
child: Icon(_keyIcon, color: color),
)
: Padding(
padding: textPadding,
child: Text(_keyName, style: TextStyle(color: color)),
), ),
); );
} }

@ -1,33 +1,71 @@
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockingjay/mockingjay.dart'; import 'package:mockingjay/mockingjay.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/landing/landing.dart'; import 'package:pinball/landing/landing.dart';
import '../../helpers/helpers.dart'; import '../../helpers/helpers.dart';
void main() { void main() {
group('LandingPage', () { group('LandingPage', () {
testWidgets('renders TextButton', (tester) async { testWidgets('renders correctly', (tester) async {
await tester.pumpApp(const LandingPage()); final l10n = await AppLocalizations.delegate.load(Locale('en'));
expect(find.byType(TextButton), findsOneWidget); await tester.pumpApp(LandingPage());
expect(find.byType(TextButton), findsNWidgets(2));
expect(find.text(l10n.play), findsOneWidget);
expect(find.text(l10n.howToPlay), findsOneWidget);
}); });
testWidgets('tapping on TextButton navigates to CharacterSelectionPage', testWidgets('tapping on play button navigates to CharacterSelectionPage',
(tester) async { (tester) async {
final l10n = await AppLocalizations.delegate.load(Locale('en'));
final navigator = MockNavigator(); final navigator = MockNavigator();
when(() => navigator.push<void>(any())).thenAnswer((_) async {}); when(() => navigator.push<void>(any())).thenAnswer((_) async {});
await tester.pumpApp( await tester.pumpApp(
const LandingPage(), LandingPage(),
navigator: navigator, navigator: navigator,
); );
await tester.tap(
find.byType( await tester.tap(find.widgetWithText(TextButton, l10n.play));
TextButton,
),
);
verify(() => navigator.push<void>(any())).called(1); verify(() => navigator.push<void>(any())).called(1);
}); });
testWidgets('tapping on how to play button displays dialog with controls',
(tester) async {
final l10n = await AppLocalizations.delegate.load(Locale('en'));
await tester.pumpApp(LandingPage());
await tester.tap(find.widgetWithText(TextButton, l10n.howToPlay));
await tester.pump();
expect(find.byType(Dialog), findsOneWidget);
});
});
group('KeyIndicator', () {
testWidgets('fromKeyName renders correctly', (tester) async {
const keyName = 'A';
await tester.pumpApp(
KeyIndicator.fromKeyName(keyName: keyName),
);
expect(find.text(keyName), findsOneWidget);
});
testWidgets('fromIcon renders correctly', (tester) async {
const keyIcon = Icons.keyboard_arrow_down;
await tester.pumpApp(
KeyIndicator.fromIcon(keyIcon: keyIcon),
);
expect(find.byIcon(keyIcon), findsOneWidget);
});
}); });
} }

Loading…
Cancel
Save