From 3fd829fbd6557132f3c81d8b18a18163b8d5b20e Mon Sep 17 00:00:00 2001 From: arturplaczek Date: Fri, 15 Apr 2022 13:54:41 +0200 Subject: [PATCH] feat: extract HowToPlayDialog from Landing page --- lib/start_game/start_game.dart | 1 + .../widgets/how_to_play_dialog.dart | 161 ++++++++++++++++++ lib/start_game/widgets/widgets.dart | 1 + .../widgets/how_to_play_dialog_test.dart | 39 +++++ 4 files changed, 202 insertions(+) create mode 100644 lib/start_game/widgets/how_to_play_dialog.dart create mode 100644 lib/start_game/widgets/widgets.dart create mode 100644 test/start_game/widgets/how_to_play_dialog_test.dart diff --git a/lib/start_game/start_game.dart b/lib/start_game/start_game.dart index 7171c66d..1556b533 100644 --- a/lib/start_game/start_game.dart +++ b/lib/start_game/start_game.dart @@ -1 +1,2 @@ export 'bloc/start_game_bloc.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/start_game/widgets/how_to_play_dialog.dart b/lib/start_game/widgets/how_to_play_dialog.dart new file mode 100644 index 00000000..aed7a3e3 --- /dev/null +++ b/lib/start_game/widgets/how_to_play_dialog.dart @@ -0,0 +1,161 @@ +// ignore_for_file: public_member_api_docs + +import 'package:flutter/material.dart'; +import 'package:pinball/l10n/l10n.dart'; + +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)), + ), + ); + } +} diff --git a/lib/start_game/widgets/widgets.dart b/lib/start_game/widgets/widgets.dart new file mode 100644 index 00000000..bad2c6b5 --- /dev/null +++ b/lib/start_game/widgets/widgets.dart @@ -0,0 +1 @@ +export 'how_to_play_dialog.dart'; diff --git a/test/start_game/widgets/how_to_play_dialog_test.dart b/test/start_game/widgets/how_to_play_dialog_test.dart new file mode 100644 index 00000000..082f102e --- /dev/null +++ b/test/start_game/widgets/how_to_play_dialog_test.dart @@ -0,0 +1,39 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/start_game/start_game.dart'; + +import '../../helpers/helpers.dart'; + +void main() { + group('HowToPlayDialog', () { + testWidgets('displays dialog', (tester) async { + await tester.pumpApp(HowToPlayDialog()); + + 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); + }); + }); +}