From 9fdb9355376a500d78fdf50bc141fe29ab4f6469 Mon Sep 17 00:00:00 2001 From: Erick Date: Fri, 6 May 2022 12:11:48 -0300 Subject: [PATCH 1/5] fix: flkay tests (#362) --- .../android_spaceship_bonus_behavior_test.dart | 3 +++ test/game/components/multiballs/multiballs_test.dart | 11 ++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/test/game/components/android_acres/behaviors/android_spaceship_bonus_behavior_test.dart b/test/game/components/android_acres/behaviors/android_spaceship_bonus_behavior_test.dart index 4ecdb05b..e6b03c5f 100644 --- a/test/game/components/android_acres/behaviors/android_spaceship_bonus_behavior_test.dart +++ b/test/game/components/android_acres/behaviors/android_spaceship_bonus_behavior_test.dart @@ -42,6 +42,9 @@ class _TestGame extends Forge2DGame { AndroidAcres child, { required GameBloc gameBloc, }) async { + // Not needed once https://github.com/flame-engine/flame/issues/1607 + // is fixed + await onLoad(); await ensureAdd( FlameBlocProvider.value( value: gameBloc, diff --git a/test/game/components/multiballs/multiballs_test.dart b/test/game/components/multiballs/multiballs_test.dart index 1841d0a3..da736c27 100644 --- a/test/game/components/multiballs/multiballs_test.dart +++ b/test/game/components/multiballs/multiballs_test.dart @@ -17,8 +17,11 @@ class _TestGame extends Forge2DGame { ]); } - Future pump(Multiballs child, {GameBloc? gameBloc}) { - return ensureAdd( + Future pump(Multiballs child, {GameBloc? gameBloc}) async { + // Not needed once https://github.com/flame-engine/flame/issues/1607 + // is fixed + await onLoad(); + await ensureAdd( FlameBlocProvider.value( value: gameBloc ?? GameBloc(), children: [child], @@ -38,7 +41,9 @@ void main() { setUp: (game, tester) async { final multiballs = Multiballs(); await game.pump(multiballs); - expect(game.descendants(), contains(multiballs)); + }, + verify: (game, tester) async { + expect(game.descendants().whereType().length, equals(1)); }, ); From 2f94cf84d692c380397f22b933a9692783d3a445 Mon Sep 17 00:00:00 2001 From: arturplaczek <33895544+arturplaczek@users.noreply.github.com> Date: Fri, 6 May 2022 17:30:38 +0200 Subject: [PATCH 2/5] chore: `LinkBoxDialog` - generated files (#360) --- assets/images/link_box/info_icon.png | Bin 0 -> 6389 bytes lib/gen/assets.gen.dart | 9 ++++ lib/l10n/arb/app_en.arb | 40 ++++++++++++++++++ .../lib/src/theme/pinball_text_style.dart | 7 +++ .../lib/src/theme/pinball_theme.dart | 1 + pubspec.yaml | 3 +- 6 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 assets/images/link_box/info_icon.png diff --git a/assets/images/link_box/info_icon.png b/assets/images/link_box/info_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..78556be0ace02fc55dd02cbe062547453d5b1601 GIT binary patch literal 6389 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 const $AssetsImagesComponentsGen(); + $AssetsImagesLinkBoxGen get linkBox => const $AssetsImagesLinkBoxGen(); $AssetsImagesScoreGen get score => const $AssetsImagesScoreGen(); } @@ -53,6 +54,14 @@ class $AssetsImagesComponentsGen { const AssetGenImage('assets/images/components/space.png'); } +class $AssetsImagesLinkBoxGen { + const $AssetsImagesLinkBoxGen(); + + /// File path: assets/images/link_box/info_icon.png + AssetGenImage get infoIcon => + const AssetGenImage('assets/images/link_box/info_icon.png'); +} + class $AssetsImagesScoreGen { const $AssetsImagesScoreGen(); diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 03fde0bd..3d15d9fd 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -120,6 +120,46 @@ "@footerGoogleIOText": { "description": "Text shown on the footer which mentions Google I/O" }, + "linkBoxTitle": "Resources", + "@linkBoxTitle": { + "description": "Text shown on the link box title section." + }, + "linkBoxMadeWithText": "Made with ", + "@linkBoxMadeWithText": { + "description": "Text shown on the link box which mentions technologies used to build the app." + }, + "linkBoxFlutterLinkText": "Flutter", + "@linkBoxFlutterLinkText": { + "description": "Text on the link shown on the link box which navigates to the Flutter page" + }, + "linkBoxFirebaseLinkText": "Firebase", + "@linkBoxFirebaseLinkText": { + "description": "Text on the link shown on the link box which navigates to the Firebase page" + }, + "linkBoxOpenSourceCode": "Open Source Code", + "@linkBoxOpenSourceCode": { + "description": "Text shown on the link box which redirects to github project" + }, + "linkBoxGoogleIOText": "Google I/O", + "@linkBoxGoogleIOText": { + "description": "Text shown on the link box which mentions Google I/O" + }, + "linkBoxFlutterGames": "Flutter Games", + "@linkBoxFlutterGames": { + "description": "Text shown on the link box which redirects to flutter games article" + }, + "linkBoxHowItsMade": "How it’s made", + "@linkBoxHowItsMade": { + "description": "Text shown on the link box which redirects to Very Good Blog article" + }, + "linkBoxTermsOfService": "Terms of Service", + "@linkBoxTermsOfService": { + "description": "Text shown on the link box which redirect to terms of service" + }, + "linkBoxPrivacyPolicy": "Privacy Policy", + "@linkBoxPrivacyPolicy": { + "description": "Text shown on the link box which redirect to privacy policy" + }, "loading": "Loading", "@loading": { "description": "Text shown to indicate loading times" diff --git a/packages/pinball_ui/lib/src/theme/pinball_text_style.dart b/packages/pinball_ui/lib/src/theme/pinball_text_style.dart index 10383abf..18968680 100644 --- a/packages/pinball_ui/lib/src/theme/pinball_text_style.dart +++ b/packages/pinball_ui/lib/src/theme/pinball_text_style.dart @@ -37,6 +37,13 @@ abstract class PinballTextStyle { fontFamily: _primaryFontFamily, ); + static const headline5 = TextStyle( + color: PinballColors.white, + fontSize: 14, + package: _fontPackage, + fontFamily: _primaryFontFamily, + ); + static const subtitle2 = TextStyle( color: PinballColors.white, fontSize: 16, diff --git a/packages/pinball_ui/lib/src/theme/pinball_theme.dart b/packages/pinball_ui/lib/src/theme/pinball_theme.dart index cf62b2ef..43322391 100644 --- a/packages/pinball_ui/lib/src/theme/pinball_theme.dart +++ b/packages/pinball_ui/lib/src/theme/pinball_theme.dart @@ -16,6 +16,7 @@ class PinballTheme { headline2: PinballTextStyle.headline2, headline3: PinballTextStyle.headline3, headline4: PinballTextStyle.headline4, + headline5: PinballTextStyle.headline5, subtitle1: PinballTextStyle.subtitle1, subtitle2: PinballTextStyle.subtitle2, ); diff --git a/pubspec.yaml b/pubspec.yaml index fcee1e6e..dcfa6f3d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: flame: ^1.1.1 flame_bloc: ^1.4.0 flame_forge2d: - git: + git: url: https://github.com/flame-engine/flame/ path: packages/flame_forge2d/ ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f @@ -60,6 +60,7 @@ flutter: - assets/images/components/ - assets/images/bonus_animation/ - assets/images/score/ + - assets/images/link_box/ flutter_gen: line_length: 80 From c8a2150787eb221bff63723278efdfb1dab666be Mon Sep 17 00:00:00 2001 From: Erick Date: Fri, 6 May 2022 12:42:04 -0300 Subject: [PATCH 3/5] feat: adding leaderboard display (#352) * feat: adding leaderboard display * feat: pr suggestions * fix: conflicts * lint Co-authored-by: Alejandro Santiago --- lib/game/components/backbox/backbox.dart | 5 + .../components/backbox/bloc/backbox_bloc.dart | 17 +++ .../backbox/bloc/backbox_event.dart | 6 + .../backbox/bloc/backbox_state.dart | 10 +- .../components/backbox/displays/displays.dart | 1 + .../backbox/displays/leaderboard_display.dart | 120 ++++++++++++++++++ .../game/components/backbox/backbox_test.dart | 40 +++++- .../backbox/bloc/backbox_bloc_test.dart | 36 ++++++ .../backbox/bloc/backbox_event_test.dart | 10 ++ .../backbox/bloc/backbox_state_test.dart | 24 +++- .../displays/leaderboard_display_test.dart | 109 ++++++++++++++++ 11 files changed, 371 insertions(+), 7 deletions(-) create mode 100644 lib/game/components/backbox/displays/leaderboard_display.dart create mode 100644 test/game/components/backbox/displays/leaderboard_display_test.dart diff --git a/lib/game/components/backbox/backbox.dart b/lib/game/components/backbox/backbox.dart index 9414ae96..b3743df3 100644 --- a/lib/game/components/backbox/backbox.dart +++ b/lib/game/components/backbox/backbox.dart @@ -34,8 +34,11 @@ class Backbox extends PositionComponent with ZIndex { anchor = Anchor.bottomCenter; zIndex = ZIndexes.backbox; + _bloc.add(LeaderboardRequested()); + await add(_BackboxSpriteComponent()); await add(_display = Component()); + _build(_bloc.state); _subscription = _bloc.stream.listen((state) { _display.children.removeWhere((_) => true); @@ -52,6 +55,8 @@ class Backbox extends PositionComponent with ZIndex { void _build(BackboxState state) { if (state is LoadingState) { _display.add(LoadingDisplay()); + } else if (state is LeaderboardSuccessState) { + _display.add(LeaderboardDisplay(entries: state.entries)); } else if (state is InitialsFormState) { _display.add( InitialsInputDisplay( diff --git a/lib/game/components/backbox/bloc/backbox_bloc.dart b/lib/game/components/backbox/bloc/backbox_bloc.dart index f315189e..b3952a0c 100644 --- a/lib/game/components/backbox/bloc/backbox_bloc.dart +++ b/lib/game/components/backbox/bloc/backbox_bloc.dart @@ -18,6 +18,7 @@ class BackboxBloc extends Bloc { super(LoadingState()) { on(_onPlayerInitialsRequested); on(_onPlayerInitialsSubmitted); + on(_onLeaderboardRequested); } final LeaderboardRepository _leaderboardRepository; @@ -53,4 +54,20 @@ class BackboxBloc extends Bloc { emit(InitialsFailureState()); } } + + Future _onLeaderboardRequested( + LeaderboardRequested event, + Emitter emit, + ) async { + try { + emit(LoadingState()); + + final entries = await _leaderboardRepository.fetchTop10Leaderboard(); + + emit(LeaderboardSuccessState(entries: entries)); + } catch (error, stackTrace) { + addError(error, stackTrace); + emit(LeaderboardFailureState()); + } + } } diff --git a/lib/game/components/backbox/bloc/backbox_event.dart b/lib/game/components/backbox/bloc/backbox_event.dart index 42203cdc..40ad4bfb 100644 --- a/lib/game/components/backbox/bloc/backbox_event.dart +++ b/lib/game/components/backbox/bloc/backbox_event.dart @@ -51,3 +51,9 @@ class PlayerInitialsSubmitted extends BackboxEvent { @override List get props => [score, initials, character]; } + +/// Event that triggers the fetching of the leaderboard +class LeaderboardRequested extends BackboxEvent { + @override + List get props => []; +} diff --git a/lib/game/components/backbox/bloc/backbox_state.dart b/lib/game/components/backbox/bloc/backbox_state.dart index e1f2c801..482bb298 100644 --- a/lib/game/components/backbox/bloc/backbox_state.dart +++ b/lib/game/components/backbox/bloc/backbox_state.dart @@ -14,10 +14,18 @@ class LoadingState extends BackboxState { List get props => []; } +/// {@template leaderboard_success_state} /// State when the leaderboard was successfully loaded. +/// {@endtemplate} class LeaderboardSuccessState extends BackboxState { + /// {@macro leaderboard_success_state} + const LeaderboardSuccessState({required this.entries}); + + /// Current entries + final List entries; + @override - List get props => []; + List get props => [entries]; } /// State when the leaderboard failed to load. diff --git a/lib/game/components/backbox/displays/displays.dart b/lib/game/components/backbox/displays/displays.dart index a516587d..4dda7048 100644 --- a/lib/game/components/backbox/displays/displays.dart +++ b/lib/game/components/backbox/displays/displays.dart @@ -1,4 +1,5 @@ export 'initials_input_display.dart'; export 'initials_submission_failure_display.dart'; export 'initials_submission_success_display.dart'; +export 'leaderboard_display.dart'; export 'loading_display.dart'; diff --git a/lib/game/components/backbox/displays/leaderboard_display.dart b/lib/game/components/backbox/displays/leaderboard_display.dart new file mode 100644 index 00000000..ac7a798d --- /dev/null +++ b/lib/game/components/backbox/displays/leaderboard_display.dart @@ -0,0 +1,120 @@ +import 'package:flame/components.dart'; +import 'package:flutter/material.dart'; +import 'package:leaderboard_repository/leaderboard_repository.dart'; +import 'package:pinball/l10n/l10n.dart'; +import 'package:pinball/leaderboard/models/leader_board_entry.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; +import 'package:pinball_ui/pinball_ui.dart'; + +final _titleTextPaint = TextPaint( + style: const TextStyle( + fontSize: 2, + color: PinballColors.red, + fontFamily: PinballFonts.pixeloidSans, + ), +); + +final _bodyTextPaint = TextPaint( + style: const TextStyle( + fontSize: 1.8, + color: PinballColors.white, + fontFamily: PinballFonts.pixeloidSans, + ), +); + +/// {@template leaderboard_display} +/// Component that builds the leaderboard list of the Backbox. +/// {@endtemplate} +class LeaderboardDisplay extends PositionComponent with HasGameRef { + /// {@macro leaderboard_display} + LeaderboardDisplay({required List entries}) + : _entries = entries; + + final List _entries; + + double _calcY(int i) => (i * 3.2) + 3.2; + + static const _columns = [-15.0, 0.0, 15.0]; + + String _rank(int number) { + switch (number) { + case 1: + return '${number}st'; + case 2: + return '${number}nd'; + case 3: + return '${number}rd'; + default: + return '${number}th'; + } + } + + @override + Future onLoad() async { + position = Vector2(0, -30); + + final l10n = readProvider(); + final ranking = _entries.take(5).toList(); + await add( + PositionComponent( + position: Vector2(0, 4), + children: [ + PositionComponent( + children: [ + TextComponent( + text: l10n.rank, + textRenderer: _titleTextPaint, + position: Vector2(_columns[0], 0), + anchor: Anchor.center, + ), + TextComponent( + text: l10n.score, + textRenderer: _titleTextPaint, + position: Vector2(_columns[1], 0), + anchor: Anchor.center, + ), + TextComponent( + text: l10n.name, + textRenderer: _titleTextPaint, + position: Vector2(_columns[2], 0), + anchor: Anchor.center, + ), + ], + ), + for (var i = 0; i < ranking.length; i++) + PositionComponent( + children: [ + TextComponent( + text: _rank(i + 1), + textRenderer: _bodyTextPaint, + position: Vector2(_columns[0], _calcY(i)), + anchor: Anchor.center, + ), + TextComponent( + text: ranking[i].score.formatScore(), + textRenderer: _bodyTextPaint, + position: Vector2(_columns[1], _calcY(i)), + anchor: Anchor.center, + ), + SpriteComponent.fromImage( + gameRef.images.fromCache( + ranking[i].character.toTheme.leaderboardIcon.keyName, + ), + anchor: Anchor.center, + size: Vector2(1.8, 1.8), + position: Vector2(_columns[2] - 2.5, _calcY(i) + .25), + ), + TextComponent( + text: ranking[i].playerInitials, + textRenderer: _bodyTextPaint, + position: Vector2(_columns[2] + 1, _calcY(i)), + anchor: Anchor.center, + ), + ], + ), + ], + ), + ); + } +} diff --git a/test/game/components/backbox/backbox_test.dart b/test/game/components/backbox/backbox_test.dart index 52e2746e..d61bd83a 100644 --- a/test/game/components/backbox/backbox_test.dart +++ b/test/game/components/backbox/backbox_test.dart @@ -76,6 +76,9 @@ class _MockAppLocalizations extends Mock implements AppLocalizations { @override String get name => ''; + @override + String get rank => ''; + @override String get enterInitials => ''; @@ -106,7 +109,7 @@ void main() { bloc = _MockBackboxBloc(); whenListen( bloc, - Stream.value(LoadingState()), + Stream.empty(), initialState: LoadingState(), ); }); @@ -121,6 +124,16 @@ void main() { }, ); + flameTester.test( + 'adds LeaderboardRequested when loaded', + (game) async { + final backbox = Backbox.test(bloc: bloc); + await game.pump(backbox); + + verify(() => bloc.add(LeaderboardRequested())).called(1); + }, + ); + flameTester.testGameWidget( 'renders correctly', setUp: (game, tester) async { @@ -173,7 +186,7 @@ void main() { ); whenListen( bloc, - Stream.value(state), + Stream.empty(), initialState: state, ); final backbox = Backbox.test(bloc: bloc); @@ -197,7 +210,7 @@ void main() { (game) async { whenListen( bloc, - Stream.value(InitialsSuccessState()), + Stream.empty(), initialState: InitialsSuccessState(), ); final backbox = Backbox.test(bloc: bloc); @@ -218,7 +231,7 @@ void main() { (game) async { whenListen( bloc, - Stream.value(InitialsFailureState()), + Stream.empty(), initialState: InitialsFailureState(), ); final backbox = Backbox.test(bloc: bloc); @@ -234,6 +247,25 @@ void main() { }, ); + flameTester.test( + 'adds LeaderboardDisplay on LeaderboardSuccessState', + (game) async { + whenListen( + bloc, + Stream.empty(), + initialState: LeaderboardSuccessState(entries: const []), + ); + + final backbox = Backbox.test(bloc: bloc); + await game.pump(backbox); + + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); + flameTester.test( 'closes the subscription when it is removed', (game) async { diff --git a/test/game/components/backbox/bloc/backbox_bloc_test.dart b/test/game/components/backbox/bloc/backbox_bloc_test.dart index c2fbc088..3958adb5 100644 --- a/test/game/components/backbox/bloc/backbox_bloc_test.dart +++ b/test/game/components/backbox/bloc/backbox_bloc_test.dart @@ -88,5 +88,41 @@ void main() { ], ); }); + + group('LeaderboardRequested', () { + blocTest( + 'adds [LoadingState, LeaderboardSuccessState] when request succeeds', + setUp: () { + leaderboardRepository = _MockLeaderboardRepository(); + when( + () => leaderboardRepository.fetchTop10Leaderboard(), + ).thenAnswer( + (_) async => [LeaderboardEntryData.empty], + ); + }, + build: () => BackboxBloc(leaderboardRepository: leaderboardRepository), + act: (bloc) => bloc.add(LeaderboardRequested()), + expect: () => [ + LoadingState(), + LeaderboardSuccessState(entries: const [LeaderboardEntryData.empty]), + ], + ); + + blocTest( + 'adds [LoadingState, LeaderboardFailureState] when request fails', + setUp: () { + leaderboardRepository = _MockLeaderboardRepository(); + when( + () => leaderboardRepository.fetchTop10Leaderboard(), + ).thenThrow(Exception('Error')); + }, + build: () => BackboxBloc(leaderboardRepository: leaderboardRepository), + act: (bloc) => bloc.add(LeaderboardRequested()), + expect: () => [ + LoadingState(), + LeaderboardFailureState(), + ], + ); + }); }); } diff --git a/test/game/components/backbox/bloc/backbox_event_test.dart b/test/game/components/backbox/bloc/backbox_event_test.dart index 5fc766a9..80f7fbb1 100644 --- a/test/game/components/backbox/bloc/backbox_event_test.dart +++ b/test/game/components/backbox/bloc/backbox_event_test.dart @@ -122,5 +122,15 @@ void main() { ); }); }); + + group('LeaderboardRequested', () { + test('can be instantiated', () { + expect(LeaderboardRequested(), isNotNull); + }); + + test('supports value comparison', () { + expect(LeaderboardRequested(), equals(LeaderboardRequested())); + }); + }); }); } diff --git a/test/game/components/backbox/bloc/backbox_state_test.dart b/test/game/components/backbox/bloc/backbox_state_test.dart index 4708c9bb..dd262408 100644 --- a/test/game/components/backbox/bloc/backbox_state_test.dart +++ b/test/game/components/backbox/bloc/backbox_state_test.dart @@ -1,6 +1,7 @@ // ignore_for_file: prefer_const_constructors import 'package:flutter_test/flutter_test.dart'; +import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:pinball/game/components/backbox/bloc/backbox_bloc.dart'; import 'package:pinball_theme/pinball_theme.dart'; @@ -18,11 +19,30 @@ void main() { group('LeaderboardSuccessState', () { test('can be instantiated', () { - expect(LeaderboardSuccessState(), isNotNull); + expect( + LeaderboardSuccessState(entries: const []), + isNotNull, + ); }); test('supports value comparison', () { - expect(LeaderboardSuccessState(), equals(LeaderboardSuccessState())); + expect( + LeaderboardSuccessState(entries: const []), + equals( + LeaderboardSuccessState(entries: const []), + ), + ); + + expect( + LeaderboardSuccessState(entries: const []), + isNot( + equals( + LeaderboardSuccessState( + entries: const [LeaderboardEntryData.empty], + ), + ), + ), + ); }); }); diff --git a/test/game/components/backbox/displays/leaderboard_display_test.dart b/test/game/components/backbox/displays/leaderboard_display_test.dart new file mode 100644 index 00000000..263222fc --- /dev/null +++ b/test/game/components/backbox/displays/leaderboard_display_test.dart @@ -0,0 +1,109 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame/components.dart'; +import 'package:flame_forge2d/forge2d_game.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:leaderboard_repository/leaderboard_repository.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball/game/components/backbox/displays/leaderboard_display.dart'; +import 'package:pinball/l10n/l10n.dart'; +import 'package:pinball_flame/pinball_flame.dart'; +import 'package:pinball_theme/pinball_theme.dart'; + +class _MockAppLocalizations extends Mock implements AppLocalizations { + @override + String get rank => 'rank'; + + @override + String get score => 'score'; + + @override + String get name => 'name'; +} + +class _TestGame extends Forge2DGame { + @override + Future onLoad() async { + await super.onLoad(); + images.prefix = ''; + await images.load(const AndroidTheme().leaderboardIcon.keyName); + } + + Future pump(LeaderboardDisplay component) { + return ensureAdd( + FlameProvider.value( + _MockAppLocalizations(), + children: [component], + ), + ); + } +} + +void main() { + group('LeaderboardDisplay', () { + TestWidgetsFlutterBinding.ensureInitialized(); + + final flameTester = FlameTester(_TestGame.new); + + flameTester.test('renders the titles', (game) async { + await game.pump(LeaderboardDisplay(entries: const [])); + + final textComponents = + game.descendants().whereType().toList(); + expect(textComponents.length, equals(3)); + expect(textComponents[0].text, equals('rank')); + expect(textComponents[1].text, equals('score')); + expect(textComponents[2].text, equals('name')); + }); + + flameTester.test('renders the entries', (game) async { + await game.pump( + LeaderboardDisplay( + entries: const [ + LeaderboardEntryData( + playerInitials: 'AAA', + score: 123, + character: CharacterType.android, + ), + LeaderboardEntryData( + playerInitials: 'BBB', + score: 1234, + character: CharacterType.android, + ), + LeaderboardEntryData( + playerInitials: 'CCC', + score: 12345, + character: CharacterType.android, + ), + LeaderboardEntryData( + playerInitials: 'DDD', + score: 12346, + character: CharacterType.android, + ), + ], + ), + ); + + for (final text in [ + 'AAA', + 'BBB', + 'CCC', + 'DDD', + '1st', + '2nd', + '3rd', + '4th' + ]) { + expect( + game + .descendants() + .whereType() + .where((textComponent) => textComponent.text == text) + .length, + equals(1), + ); + } + }); + }); +} From 43d3a4fd5199e940623d5fdffa3770962e63c97e Mon Sep 17 00:00:00 2001 From: arturplaczek <33895544+arturplaczek@users.noreply.github.com> Date: Fri, 6 May 2022 17:54:41 +0200 Subject: [PATCH 4/5] fix: hide GameHud on game over (#361) --- lib/game/view/pinball_game_page.dart | 44 ++++++++++++++-------- test/game/view/pinball_game_page_test.dart | 31 +++++++++++++++ 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/lib/game/view/pinball_game_page.dart b/lib/game/view/pinball_game_page.dart index be6615f1..c0d5d1d8 100644 --- a/lib/game/view/pinball_game_page.dart +++ b/lib/game/view/pinball_game_page.dart @@ -114,14 +114,6 @@ class PinballGameLoadedView extends StatelessWidget { @override Widget build(BuildContext context) { - final isPlaying = context.select( - (StartGameBloc bloc) => bloc.state.status == StartGameStatus.play, - ); - final gameWidgetWidth = MediaQuery.of(context).size.height * 9 / 16; - final screenWidth = MediaQuery.of(context).size.width; - final leftMargin = (screenWidth / 2) - (gameWidgetWidth / 1.8); - final clampedMargin = leftMargin > 0 ? leftMargin : 0.0; - return StartGameListener( child: Stack( children: [ @@ -141,16 +133,36 @@ class PinballGameLoadedView extends StatelessWidget { }, ), ), - Positioned( - top: 0, - left: clampedMargin, - child: Visibility( - visible: isPlaying, - child: const GameHud(), - ), - ), + const _PositionedGameHud(), ], ), ); } } + +class _PositionedGameHud extends StatelessWidget { + const _PositionedGameHud({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final isPlaying = context.select( + (StartGameBloc bloc) => bloc.state.status == StartGameStatus.play, + ); + final isGameOver = context.select( + (GameBloc bloc) => bloc.state.status.isGameOver, + ); + final gameWidgetWidth = MediaQuery.of(context).size.height * 9 / 16; + final screenWidth = MediaQuery.of(context).size.width; + final leftMargin = (screenWidth / 2) - (gameWidgetWidth / 1.8); + final clampedMargin = leftMargin > 0 ? leftMargin : 0.0; + + return Positioned( + top: 0, + left: clampedMargin, + child: Visibility( + visible: isPlaying && !isGameOver, + child: const GameHud(), + ), + ); + } +} diff --git a/test/game/view/pinball_game_page_test.dart b/test/game/view/pinball_game_page_test.dart index f78f6278..5aef07dd 100644 --- a/test/game/view/pinball_game_page_test.dart +++ b/test/game/view/pinball_game_page_test.dart @@ -260,5 +260,36 @@ void main() { findsOneWidget, ); }); + + testWidgets('hide a hud on game over', (tester) async { + final startGameState = StartGameState.initial().copyWith( + status: StartGameStatus.play, + ); + final gameState = GameState.initial().copyWith( + status: GameStatus.gameOver, + ); + + whenListen( + startGameBloc, + Stream.value(startGameState), + initialState: startGameState, + ); + whenListen( + gameBloc, + Stream.value(gameState), + initialState: gameState, + ); + + await tester.pumpApp( + PinballGameView(game: game), + gameBloc: gameBloc, + startGameBloc: startGameBloc, + ); + + expect( + find.byType(GameHud), + findsNothing, + ); + }); }); } From 0502d97400ed70d01732e3d807951c72d5014058 Mon Sep 17 00:00:00 2001 From: Erick Date: Fri, 6 May 2022 14:44:07 -0300 Subject: [PATCH 5/5] feat: adding error component (#355) * feat: adding error component * Update packages/pinball_components/lib/src/components/error_component.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * Update packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * Update packages/pinball_components/sandbox/lib/stories/error_component/stories.dart Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> * pr suggestions * fix tests * suggestions Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> --- .../assets/images/error_background.png | Bin 0 -> 2349 bytes .../lib/gen/assets.gen.dart | 176 +----------------- .../pinball_components/lib/gen/fonts.gen.dart | 5 - .../lib/src/components/components.dart | 1 + .../lib/src/components/error_component.dart | 95 ++++++++++ packages/pinball_components/pubspec.yaml | 3 + .../pinball_components/sandbox/lib/main.dart | 1 + .../error_component/error_component_game.dart | 24 +++ .../lib/stories/error_component/stories.dart | 16 ++ .../sandbox/lib/stories/stories.dart | 1 + .../pinball_components/sandbox/pubspec.lock | 9 +- .../src/components/error_component_test.dart | 57 ++++++ 12 files changed, 208 insertions(+), 180 deletions(-) create mode 100644 packages/pinball_components/assets/images/error_background.png create mode 100644 packages/pinball_components/lib/src/components/error_component.dart create mode 100644 packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart create mode 100644 packages/pinball_components/sandbox/lib/stories/error_component/stories.dart create mode 100644 packages/pinball_components/test/src/components/error_component_test.dart diff --git a/packages/pinball_components/assets/images/error_background.png b/packages/pinball_components/assets/images/error_background.png new file mode 100644 index 0000000000000000000000000000000000000000..5aa6595fb286242efbd9ce322add13709b0e7a34 GIT binary patch literal 2349 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 bh(*r@f4Zq+C5e~>p#jOk&A!Mk@IU_pe|RES literal 0 HcmV?d00001 diff --git a/packages/pinball_components/lib/gen/assets.gen.dart b/packages/pinball_components/lib/gen/assets.gen.dart index cac04cc0..0d603727 100644 --- a/packages/pinball_components/lib/gen/assets.gen.dart +++ b/packages/pinball_components/lib/gen/assets.gen.dart @@ -3,8 +3,6 @@ /// FlutterGen /// ***************************************************** -// ignore_for_file: directives_ordering,unnecessary_import - import 'package:flutter/widgets.dart'; class $AssetsImagesGen { @@ -14,14 +12,13 @@ class $AssetsImagesGen { $AssetsImagesBackboxGen get backbox => const $AssetsImagesBackboxGen(); $AssetsImagesBallGen get ball => const $AssetsImagesBallGen(); $AssetsImagesBaseboardGen get baseboard => const $AssetsImagesBaseboardGen(); - - /// File path: assets/images/board-background.png AssetGenImage get boardBackground => const AssetGenImage('assets/images/board-background.png'); - $AssetsImagesBoundaryGen get boundary => const $AssetsImagesBoundaryGen(); $AssetsImagesDashGen get dash => const $AssetsImagesDashGen(); $AssetsImagesDinoGen get dino => const $AssetsImagesDinoGen(); + AssetGenImage get errorBackground => + const AssetGenImage('assets/images/error_background.png'); $AssetsImagesFlapperGen get flapper => const $AssetsImagesFlapperGen(); $AssetsImagesFlipperGen get flipper => const $AssetsImagesFlipperGen(); $AssetsImagesGoogleWordGen get googleWord => @@ -54,11 +51,8 @@ class $AssetsImagesAndroidGen { class $AssetsImagesBackboxGen { const $AssetsImagesBackboxGen(); - /// File path: assets/images/backbox/display-divider.png AssetGenImage get displayDivider => const AssetGenImage('assets/images/backbox/display-divider.png'); - - /// File path: assets/images/backbox/marquee.png AssetGenImage get marquee => const AssetGenImage('assets/images/backbox/marquee.png'); } @@ -66,10 +60,6 @@ class $AssetsImagesBackboxGen { class $AssetsImagesBallGen { const $AssetsImagesBallGen(); - /// File path: assets/images/ball/ball.png - AssetGenImage get ball => const AssetGenImage('assets/images/ball/ball.png'); - - /// File path: assets/images/ball/flame_effect.png AssetGenImage get flameEffect => const AssetGenImage('assets/images/ball/flame_effect.png'); } @@ -77,11 +67,8 @@ class $AssetsImagesBallGen { class $AssetsImagesBaseboardGen { const $AssetsImagesBaseboardGen(); - /// File path: assets/images/baseboard/left.png AssetGenImage get left => const AssetGenImage('assets/images/baseboard/left.png'); - - /// File path: assets/images/baseboard/right.png AssetGenImage get right => const AssetGenImage('assets/images/baseboard/right.png'); } @@ -89,15 +76,10 @@ class $AssetsImagesBaseboardGen { class $AssetsImagesBoundaryGen { const $AssetsImagesBoundaryGen(); - /// File path: assets/images/boundary/bottom.png AssetGenImage get bottom => const AssetGenImage('assets/images/boundary/bottom.png'); - - /// File path: assets/images/boundary/outer-bottom.png AssetGenImage get outerBottom => const AssetGenImage('assets/images/boundary/outer-bottom.png'); - - /// File path: assets/images/boundary/outer.png AssetGenImage get outer => const AssetGenImage('assets/images/boundary/outer.png'); } @@ -105,10 +87,8 @@ class $AssetsImagesBoundaryGen { class $AssetsImagesDashGen { const $AssetsImagesDashGen(); - /// File path: assets/images/dash/animatronic.png AssetGenImage get animatronic => const AssetGenImage('assets/images/dash/animatronic.png'); - $AssetsImagesDashBumperGen get bumper => const $AssetsImagesDashBumperGen(); } @@ -117,16 +97,10 @@ class $AssetsImagesDinoGen { $AssetsImagesDinoAnimatronicGen get animatronic => const $AssetsImagesDinoAnimatronicGen(); - - /// File path: assets/images/dino/bottom-wall.png AssetGenImage get bottomWall => const AssetGenImage('assets/images/dino/bottom-wall.png'); - - /// File path: assets/images/dino/top-wall-tunnel.png AssetGenImage get topWallTunnel => const AssetGenImage('assets/images/dino/top-wall-tunnel.png'); - - /// File path: assets/images/dino/top-wall.png AssetGenImage get topWall => const AssetGenImage('assets/images/dino/top-wall.png'); } @@ -134,15 +108,10 @@ class $AssetsImagesDinoGen { class $AssetsImagesFlapperGen { const $AssetsImagesFlapperGen(); - /// File path: assets/images/flapper/back-support.png AssetGenImage get backSupport => const AssetGenImage('assets/images/flapper/back-support.png'); - - /// File path: assets/images/flapper/flap.png AssetGenImage get flap => const AssetGenImage('assets/images/flapper/flap.png'); - - /// File path: assets/images/flapper/front-support.png AssetGenImage get frontSupport => const AssetGenImage('assets/images/flapper/front-support.png'); } @@ -150,11 +119,8 @@ class $AssetsImagesFlapperGen { class $AssetsImagesFlipperGen { const $AssetsImagesFlipperGen(); - /// File path: assets/images/flipper/left.png AssetGenImage get left => const AssetGenImage('assets/images/flipper/left.png'); - - /// File path: assets/images/flipper/right.png AssetGenImage get right => const AssetGenImage('assets/images/flipper/right.png'); } @@ -186,15 +152,10 @@ class $AssetsImagesKickerGen { class $AssetsImagesLaunchRampGen { const $AssetsImagesLaunchRampGen(); - /// File path: assets/images/launch_ramp/background-railing.png AssetGenImage get backgroundRailing => const AssetGenImage('assets/images/launch_ramp/background-railing.png'); - - /// File path: assets/images/launch_ramp/foreground-railing.png AssetGenImage get foregroundRailing => const AssetGenImage('assets/images/launch_ramp/foreground-railing.png'); - - /// File path: assets/images/launch_ramp/ramp.png AssetGenImage get ramp => const AssetGenImage('assets/images/launch_ramp/ramp.png'); } @@ -202,11 +163,8 @@ class $AssetsImagesLaunchRampGen { class $AssetsImagesMultiballGen { const $AssetsImagesMultiballGen(); - /// File path: assets/images/multiball/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/multiball/dimmed.png'); - - /// File path: assets/images/multiball/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/multiball/lit.png'); } @@ -224,11 +182,8 @@ class $AssetsImagesMultiplierGen { class $AssetsImagesPlungerGen { const $AssetsImagesPlungerGen(); - /// File path: assets/images/plunger/plunger.png AssetGenImage get plunger => const AssetGenImage('assets/images/plunger/plunger.png'); - - /// File path: assets/images/plunger/rocket.png AssetGenImage get rocket => const AssetGenImage('assets/images/plunger/rocket.png'); } @@ -236,19 +191,12 @@ class $AssetsImagesPlungerGen { class $AssetsImagesScoreGen { const $AssetsImagesScoreGen(); - /// File path: assets/images/score/five-thousand.png AssetGenImage get fiveThousand => const AssetGenImage('assets/images/score/five-thousand.png'); - - /// File path: assets/images/score/one-million.png AssetGenImage get oneMillion => const AssetGenImage('assets/images/score/one-million.png'); - - /// File path: assets/images/score/twenty-thousand.png AssetGenImage get twentyThousand => const AssetGenImage('assets/images/score/twenty-thousand.png'); - - /// File path: assets/images/score/two-hundred-thousand.png AssetGenImage get twoHundredThousand => const AssetGenImage('assets/images/score/two-hundred-thousand.png'); } @@ -256,19 +204,12 @@ class $AssetsImagesScoreGen { class $AssetsImagesSignpostGen { const $AssetsImagesSignpostGen(); - /// File path: assets/images/signpost/active1.png AssetGenImage get active1 => const AssetGenImage('assets/images/signpost/active1.png'); - - /// File path: assets/images/signpost/active2.png AssetGenImage get active2 => const AssetGenImage('assets/images/signpost/active2.png'); - - /// File path: assets/images/signpost/active3.png AssetGenImage get active3 => const AssetGenImage('assets/images/signpost/active3.png'); - - /// File path: assets/images/signpost/inactive.png AssetGenImage get inactive => const AssetGenImage('assets/images/signpost/inactive.png'); } @@ -276,19 +217,12 @@ class $AssetsImagesSignpostGen { class $AssetsImagesSkillShotGen { const $AssetsImagesSkillShotGen(); - /// File path: assets/images/skill_shot/decal.png AssetGenImage get decal => const AssetGenImage('assets/images/skill_shot/decal.png'); - - /// File path: assets/images/skill_shot/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/skill_shot/dimmed.png'); - - /// File path: assets/images/skill_shot/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/skill_shot/lit.png'); - - /// File path: assets/images/skill_shot/pin.png AssetGenImage get pin => const AssetGenImage('assets/images/skill_shot/pin.png'); } @@ -296,11 +230,8 @@ class $AssetsImagesSkillShotGen { class $AssetsImagesSlingshotGen { const $AssetsImagesSlingshotGen(); - /// File path: assets/images/slingshot/lower.png AssetGenImage get lower => const AssetGenImage('assets/images/slingshot/lower.png'); - - /// File path: assets/images/slingshot/upper.png AssetGenImage get upper => const AssetGenImage('assets/images/slingshot/upper.png'); } @@ -308,10 +239,8 @@ class $AssetsImagesSlingshotGen { class $AssetsImagesSparkyGen { const $AssetsImagesSparkyGen(); - /// File path: assets/images/sparky/animatronic.png AssetGenImage get animatronic => const AssetGenImage('assets/images/sparky/animatronic.png'); - $AssetsImagesSparkyBumperGen get bumper => const $AssetsImagesSparkyBumperGen(); $AssetsImagesSparkyComputerGen get computer => @@ -332,11 +261,8 @@ class $AssetsImagesAndroidBumperGen { class $AssetsImagesAndroidRailGen { const $AssetsImagesAndroidRailGen(); - /// File path: assets/images/android/rail/exit.png AssetGenImage get exit => const AssetGenImage('assets/images/android/rail/exit.png'); - - /// File path: assets/images/android/rail/main.png AssetGenImage get main => const AssetGenImage('assets/images/android/rail/main.png'); } @@ -346,20 +272,12 @@ class $AssetsImagesAndroidRampGen { $AssetsImagesAndroidRampArrowGen get arrow => const $AssetsImagesAndroidRampArrowGen(); - - /// File path: assets/images/android/ramp/board-opening.png AssetGenImage get boardOpening => const AssetGenImage('assets/images/android/ramp/board-opening.png'); - - /// File path: assets/images/android/ramp/main.png AssetGenImage get main => const AssetGenImage('assets/images/android/ramp/main.png'); - - /// File path: assets/images/android/ramp/railing-background.png AssetGenImage get railingBackground => const AssetGenImage('assets/images/android/ramp/railing-background.png'); - - /// File path: assets/images/android/ramp/railing-foreground.png AssetGenImage get railingForeground => const AssetGenImage('assets/images/android/ramp/railing-foreground.png'); } @@ -367,15 +285,10 @@ class $AssetsImagesAndroidRampGen { class $AssetsImagesAndroidSpaceshipGen { const $AssetsImagesAndroidSpaceshipGen(); - /// File path: assets/images/android/spaceship/animatronic.png AssetGenImage get animatronic => const AssetGenImage('assets/images/android/spaceship/animatronic.png'); - - /// File path: assets/images/android/spaceship/light-beam.png AssetGenImage get lightBeam => const AssetGenImage('assets/images/android/spaceship/light-beam.png'); - - /// File path: assets/images/android/spaceship/saucer.png AssetGenImage get saucer => const AssetGenImage('assets/images/android/spaceship/saucer.png'); } @@ -392,11 +305,8 @@ class $AssetsImagesDashBumperGen { class $AssetsImagesDinoAnimatronicGen { const $AssetsImagesDinoAnimatronicGen(); - /// File path: assets/images/dino/animatronic/head.png AssetGenImage get head => const AssetGenImage('assets/images/dino/animatronic/head.png'); - - /// File path: assets/images/dino/animatronic/mouth.png AssetGenImage get mouth => const AssetGenImage('assets/images/dino/animatronic/mouth.png'); } @@ -404,11 +314,8 @@ class $AssetsImagesDinoAnimatronicGen { class $AssetsImagesGoogleWordLetter1Gen { const $AssetsImagesGoogleWordLetter1Gen(); - /// File path: assets/images/google_word/letter1/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/google_word/letter1/dimmed.png'); - - /// File path: assets/images/google_word/letter1/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/google_word/letter1/lit.png'); } @@ -416,11 +323,8 @@ class $AssetsImagesGoogleWordLetter1Gen { class $AssetsImagesGoogleWordLetter2Gen { const $AssetsImagesGoogleWordLetter2Gen(); - /// File path: assets/images/google_word/letter2/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/google_word/letter2/dimmed.png'); - - /// File path: assets/images/google_word/letter2/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/google_word/letter2/lit.png'); } @@ -428,11 +332,8 @@ class $AssetsImagesGoogleWordLetter2Gen { class $AssetsImagesGoogleWordLetter3Gen { const $AssetsImagesGoogleWordLetter3Gen(); - /// File path: assets/images/google_word/letter3/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/google_word/letter3/dimmed.png'); - - /// File path: assets/images/google_word/letter3/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/google_word/letter3/lit.png'); } @@ -440,11 +341,8 @@ class $AssetsImagesGoogleWordLetter3Gen { class $AssetsImagesGoogleWordLetter4Gen { const $AssetsImagesGoogleWordLetter4Gen(); - /// File path: assets/images/google_word/letter4/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/google_word/letter4/dimmed.png'); - - /// File path: assets/images/google_word/letter4/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/google_word/letter4/lit.png'); } @@ -452,11 +350,8 @@ class $AssetsImagesGoogleWordLetter4Gen { class $AssetsImagesGoogleWordLetter5Gen { const $AssetsImagesGoogleWordLetter5Gen(); - /// File path: assets/images/google_word/letter5/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/google_word/letter5/dimmed.png'); - - /// File path: assets/images/google_word/letter5/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/google_word/letter5/lit.png'); } @@ -464,11 +359,8 @@ class $AssetsImagesGoogleWordLetter5Gen { class $AssetsImagesGoogleWordLetter6Gen { const $AssetsImagesGoogleWordLetter6Gen(); - /// File path: assets/images/google_word/letter6/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/google_word/letter6/dimmed.png'); - - /// File path: assets/images/google_word/letter6/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/google_word/letter6/lit.png'); } @@ -476,11 +368,8 @@ class $AssetsImagesGoogleWordLetter6Gen { class $AssetsImagesKickerLeftGen { const $AssetsImagesKickerLeftGen(); - /// File path: assets/images/kicker/left/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/kicker/left/dimmed.png'); - - /// File path: assets/images/kicker/left/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/kicker/left/lit.png'); } @@ -488,11 +377,8 @@ class $AssetsImagesKickerLeftGen { class $AssetsImagesKickerRightGen { const $AssetsImagesKickerRightGen(); - /// File path: assets/images/kicker/right/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/kicker/right/dimmed.png'); - - /// File path: assets/images/kicker/right/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/kicker/right/lit.png'); } @@ -500,11 +386,8 @@ class $AssetsImagesKickerRightGen { class $AssetsImagesMultiplierX2Gen { const $AssetsImagesMultiplierX2Gen(); - /// File path: assets/images/multiplier/x2/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/multiplier/x2/dimmed.png'); - - /// File path: assets/images/multiplier/x2/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/multiplier/x2/lit.png'); } @@ -512,11 +395,8 @@ class $AssetsImagesMultiplierX2Gen { class $AssetsImagesMultiplierX3Gen { const $AssetsImagesMultiplierX3Gen(); - /// File path: assets/images/multiplier/x3/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/multiplier/x3/dimmed.png'); - - /// File path: assets/images/multiplier/x3/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/multiplier/x3/lit.png'); } @@ -524,11 +404,8 @@ class $AssetsImagesMultiplierX3Gen { class $AssetsImagesMultiplierX4Gen { const $AssetsImagesMultiplierX4Gen(); - /// File path: assets/images/multiplier/x4/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/multiplier/x4/dimmed.png'); - - /// File path: assets/images/multiplier/x4/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/multiplier/x4/lit.png'); } @@ -536,11 +413,8 @@ class $AssetsImagesMultiplierX4Gen { class $AssetsImagesMultiplierX5Gen { const $AssetsImagesMultiplierX5Gen(); - /// File path: assets/images/multiplier/x5/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/multiplier/x5/dimmed.png'); - - /// File path: assets/images/multiplier/x5/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/multiplier/x5/lit.png'); } @@ -548,11 +422,8 @@ class $AssetsImagesMultiplierX5Gen { class $AssetsImagesMultiplierX6Gen { const $AssetsImagesMultiplierX6Gen(); - /// File path: assets/images/multiplier/x6/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/multiplier/x6/dimmed.png'); - - /// File path: assets/images/multiplier/x6/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/multiplier/x6/lit.png'); } @@ -568,15 +439,10 @@ class $AssetsImagesSparkyBumperGen { class $AssetsImagesSparkyComputerGen { const $AssetsImagesSparkyComputerGen(); - /// File path: assets/images/sparky/computer/base.png AssetGenImage get base => const AssetGenImage('assets/images/sparky/computer/base.png'); - - /// File path: assets/images/sparky/computer/glow.png AssetGenImage get glow => const AssetGenImage('assets/images/sparky/computer/glow.png'); - - /// File path: assets/images/sparky/computer/top.png AssetGenImage get top => const AssetGenImage('assets/images/sparky/computer/top.png'); } @@ -584,11 +450,8 @@ class $AssetsImagesSparkyComputerGen { class $AssetsImagesAndroidBumperAGen { const $AssetsImagesAndroidBumperAGen(); - /// File path: assets/images/android/bumper/a/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/android/bumper/a/dimmed.png'); - - /// File path: assets/images/android/bumper/a/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/android/bumper/a/lit.png'); } @@ -596,11 +459,8 @@ class $AssetsImagesAndroidBumperAGen { class $AssetsImagesAndroidBumperBGen { const $AssetsImagesAndroidBumperBGen(); - /// File path: assets/images/android/bumper/b/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/android/bumper/b/dimmed.png'); - - /// File path: assets/images/android/bumper/b/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/android/bumper/b/lit.png'); } @@ -608,11 +468,8 @@ class $AssetsImagesAndroidBumperBGen { class $AssetsImagesAndroidBumperCowGen { const $AssetsImagesAndroidBumperCowGen(); - /// File path: assets/images/android/bumper/cow/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/android/bumper/cow/dimmed.png'); - - /// File path: assets/images/android/bumper/cow/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/android/bumper/cow/lit.png'); } @@ -620,27 +477,16 @@ class $AssetsImagesAndroidBumperCowGen { class $AssetsImagesAndroidRampArrowGen { const $AssetsImagesAndroidRampArrowGen(); - /// File path: assets/images/android/ramp/arrow/active1.png AssetGenImage get active1 => const AssetGenImage('assets/images/android/ramp/arrow/active1.png'); - - /// File path: assets/images/android/ramp/arrow/active2.png AssetGenImage get active2 => const AssetGenImage('assets/images/android/ramp/arrow/active2.png'); - - /// File path: assets/images/android/ramp/arrow/active3.png AssetGenImage get active3 => const AssetGenImage('assets/images/android/ramp/arrow/active3.png'); - - /// File path: assets/images/android/ramp/arrow/active4.png AssetGenImage get active4 => const AssetGenImage('assets/images/android/ramp/arrow/active4.png'); - - /// File path: assets/images/android/ramp/arrow/active5.png AssetGenImage get active5 => const AssetGenImage('assets/images/android/ramp/arrow/active5.png'); - - /// File path: assets/images/android/ramp/arrow/inactive.png AssetGenImage get inactive => const AssetGenImage('assets/images/android/ramp/arrow/inactive.png'); } @@ -648,11 +494,8 @@ class $AssetsImagesAndroidRampArrowGen { class $AssetsImagesDashBumperAGen { const $AssetsImagesDashBumperAGen(); - /// File path: assets/images/dash/bumper/a/active.png AssetGenImage get active => const AssetGenImage('assets/images/dash/bumper/a/active.png'); - - /// File path: assets/images/dash/bumper/a/inactive.png AssetGenImage get inactive => const AssetGenImage('assets/images/dash/bumper/a/inactive.png'); } @@ -660,11 +503,8 @@ class $AssetsImagesDashBumperAGen { class $AssetsImagesDashBumperBGen { const $AssetsImagesDashBumperBGen(); - /// File path: assets/images/dash/bumper/b/active.png AssetGenImage get active => const AssetGenImage('assets/images/dash/bumper/b/active.png'); - - /// File path: assets/images/dash/bumper/b/inactive.png AssetGenImage get inactive => const AssetGenImage('assets/images/dash/bumper/b/inactive.png'); } @@ -672,11 +512,8 @@ class $AssetsImagesDashBumperBGen { class $AssetsImagesDashBumperMainGen { const $AssetsImagesDashBumperMainGen(); - /// File path: assets/images/dash/bumper/main/active.png AssetGenImage get active => const AssetGenImage('assets/images/dash/bumper/main/active.png'); - - /// File path: assets/images/dash/bumper/main/inactive.png AssetGenImage get inactive => const AssetGenImage('assets/images/dash/bumper/main/inactive.png'); } @@ -684,11 +521,8 @@ class $AssetsImagesDashBumperMainGen { class $AssetsImagesSparkyBumperAGen { const $AssetsImagesSparkyBumperAGen(); - /// File path: assets/images/sparky/bumper/a/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/sparky/bumper/a/dimmed.png'); - - /// File path: assets/images/sparky/bumper/a/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/sparky/bumper/a/lit.png'); } @@ -696,11 +530,8 @@ class $AssetsImagesSparkyBumperAGen { class $AssetsImagesSparkyBumperBGen { const $AssetsImagesSparkyBumperBGen(); - /// File path: assets/images/sparky/bumper/b/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/sparky/bumper/b/dimmed.png'); - - /// File path: assets/images/sparky/bumper/b/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/sparky/bumper/b/lit.png'); } @@ -708,11 +539,8 @@ class $AssetsImagesSparkyBumperBGen { class $AssetsImagesSparkyBumperCGen { const $AssetsImagesSparkyBumperCGen(); - /// File path: assets/images/sparky/bumper/c/dimmed.png AssetGenImage get dimmed => const AssetGenImage('assets/images/sparky/bumper/c/dimmed.png'); - - /// File path: assets/images/sparky/bumper/c/lit.png AssetGenImage get lit => const AssetGenImage('assets/images/sparky/bumper/c/lit.png'); } diff --git a/packages/pinball_components/lib/gen/fonts.gen.dart b/packages/pinball_components/lib/gen/fonts.gen.dart index 5f77da16..b15f2dd0 100644 --- a/packages/pinball_components/lib/gen/fonts.gen.dart +++ b/packages/pinball_components/lib/gen/fonts.gen.dart @@ -3,14 +3,9 @@ /// FlutterGen /// ***************************************************** -// ignore_for_file: directives_ordering,unnecessary_import - class FontFamily { FontFamily._(); - /// Font family: PixeloidMono static const String pixeloidMono = 'PixeloidMono'; - - /// Font family: PixeloidSans static const String pixeloidSans = 'PixeloidSans'; } diff --git a/packages/pinball_components/lib/src/components/components.dart b/packages/pinball_components/lib/src/components/components.dart index db2f7d38..55fe6bb5 100644 --- a/packages/pinball_components/lib/src/components/components.dart +++ b/packages/pinball_components/lib/src/components/components.dart @@ -12,6 +12,7 @@ export 'chrome_dino/chrome_dino.dart'; export 'dash_animatronic.dart'; export 'dash_nest_bumper/dash_nest_bumper.dart'; export 'dino_walls.dart'; +export 'error_component.dart'; export 'fire_effect.dart'; export 'flapper/flapper.dart'; export 'flipper.dart'; diff --git a/packages/pinball_components/lib/src/components/error_component.dart b/packages/pinball_components/lib/src/components/error_component.dart new file mode 100644 index 00000000..49be8069 --- /dev/null +++ b/packages/pinball_components/lib/src/components/error_component.dart @@ -0,0 +1,95 @@ +import 'package:flame/components.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_ui/pinball_ui.dart'; + +final _boldLabelTextPaint = TextPaint( + style: const TextStyle( + fontSize: 1.8, + color: PinballColors.white, + fontFamily: PinballFonts.pixeloidSans, + fontWeight: FontWeight.w700, + ), +); + +final _labelTextPaint = TextPaint( + style: const TextStyle( + fontSize: 1.8, + color: PinballColors.white, + fontFamily: PinballFonts.pixeloidSans, + fontWeight: FontWeight.w400, + ), +); + +/// {@template error_component} +/// A plain visual component used to show errors for the user. +/// {@endtemplate} +class ErrorComponent extends SpriteComponent with HasGameRef { + /// {@macro error_component} + ErrorComponent({required this.label, Vector2? position}) + : _textPaint = _labelTextPaint, + super( + position: position, + ); + + /// {@macro error_component} + ErrorComponent.bold({required this.label, Vector2? position}) + : _textPaint = _boldLabelTextPaint, + super( + position: position, + ); + + /// Text shown on the error message. + final String label; + final TextPaint _textPaint; + + List _splitInLines() { + final maxWidth = size.x - 8; + final lines = []; + var currentLine = ''; + final words = label.split(' '); + while (words.isNotEmpty) { + final word = words.removeAt(0); + + if (_textPaint.measureTextWidth('$currentLine $word') <= maxWidth) { + currentLine = '$currentLine $word'.trim(); + } else { + lines.add(currentLine); + currentLine = word; + } + } + + lines.add(currentLine); + return lines; + } + + @override + Future onLoad() async { + anchor = Anchor.center; + final sprite = await gameRef.loadSprite( + Assets.images.errorBackground.keyName, + ); + + size = sprite.originalSize / 20; + this.sprite = sprite; + + final lines = _splitInLines(); + + // Calculates vertical offset based on the number of lines of text to be + // displayed. This offset is used to keep the middle of the multi-line text + // at the center of the [ErrorComponent]. + final yOffset = ((size.y / 2.2) / lines.length) * 1.5; + + for (var i = 0; i < lines.length; i++) { + await add( + TextComponent( + position: Vector2(size.x / 2, yOffset + 2.2 * i), + size: Vector2(size.x - 4, 2.2), + text: lines[i], + textRenderer: _textPaint, + anchor: Anchor.center, + ), + ); + } + } +} diff --git a/packages/pinball_components/pubspec.yaml b/packages/pinball_components/pubspec.yaml index 4f66c220..573fe353 100644 --- a/packages/pinball_components/pubspec.yaml +++ b/packages/pinball_components/pubspec.yaml @@ -23,6 +23,8 @@ dependencies: path: ../pinball_flame pinball_theme: path: ../pinball_theme + pinball_ui: + path: ../pinball_ui dev_dependencies: bloc_test: ^9.0.3 @@ -33,6 +35,7 @@ dev_dependencies: very_good_analysis: ^2.4.0 flutter: + uses-material-design: true generate: true fonts: - family: PixeloidSans diff --git a/packages/pinball_components/sandbox/lib/main.dart b/packages/pinball_components/sandbox/lib/main.dart index ccb1b0bc..714bbee5 100644 --- a/packages/pinball_components/sandbox/lib/main.dart +++ b/packages/pinball_components/sandbox/lib/main.dart @@ -8,6 +8,7 @@ void main() { addBallStories(dashbook); addLayerStories(dashbook); addEffectsStories(dashbook); + addErrorComponentStories(dashbook); addFlutterForestStories(dashbook); addSparkyScorchStories(dashbook); addAndroidAcresStories(dashbook); diff --git a/packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart b/packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart new file mode 100644 index 00000000..c64e6d48 --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart @@ -0,0 +1,24 @@ +import 'package:flame/components.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:sandbox/common/common.dart'; + +class ErrorComponentGame extends AssetsGame { + ErrorComponentGame({required this.text}); + + static const description = 'Shows how ErrorComponents are rendered.'; + + final String text; + + @override + Future onLoad() async { + camera.followVector2(Vector2.zero()); + + await add(ErrorComponent(label: text)); + await add( + ErrorComponent.bold( + label: text, + position: Vector2(0, 10), + ), + ); + } +} diff --git a/packages/pinball_components/sandbox/lib/stories/error_component/stories.dart b/packages/pinball_components/sandbox/lib/stories/error_component/stories.dart new file mode 100644 index 00000000..cecd9dae --- /dev/null +++ b/packages/pinball_components/sandbox/lib/stories/error_component/stories.dart @@ -0,0 +1,16 @@ +import 'package:dashbook/dashbook.dart'; +import 'package:sandbox/common/common.dart'; +import 'package:sandbox/stories/error_component/error_component_game.dart'; + +void addErrorComponentStories(Dashbook dashbook) { + dashbook.storiesOf('ErrorComponent').addGame( + title: 'Basic', + description: ErrorComponentGame.description, + gameBuilder: (context) => ErrorComponentGame( + text: context.textProperty( + 'label', + 'Oh no, something went wrong!', + ), + ), + ); +} diff --git a/packages/pinball_components/sandbox/lib/stories/stories.dart b/packages/pinball_components/sandbox/lib/stories/stories.dart index b48770ba..0a514eb9 100644 --- a/packages/pinball_components/sandbox/lib/stories/stories.dart +++ b/packages/pinball_components/sandbox/lib/stories/stories.dart @@ -4,6 +4,7 @@ export 'bottom_group/stories.dart'; export 'boundaries/stories.dart'; export 'dino_desert/stories.dart'; export 'effects/stories.dart'; +export 'error_component/stories.dart'; export 'flutter_forest/stories.dart'; export 'google_word/stories.dart'; export 'launch_ramp/stories.dart'; diff --git a/packages/pinball_components/sandbox/pubspec.lock b/packages/pinball_components/sandbox/pubspec.lock index d2500fbe..a22d42c8 100644 --- a/packages/pinball_components/sandbox/pubspec.lock +++ b/packages/pinball_components/sandbox/pubspec.lock @@ -270,6 +270,13 @@ packages: relative: true source: path version: "1.0.0+1" + pinball_ui: + dependency: transitive + description: + path: "../../pinball_ui" + relative: true + source: path + version: "1.0.0+1" platform: dependency: transitive description: @@ -407,7 +414,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.20" + version: "6.1.0" url_launcher_android: dependency: transitive description: diff --git a/packages/pinball_components/test/src/components/error_component_test.dart b/packages/pinball_components/test/src/components/error_component_test.dart new file mode 100644 index 00000000..c50ac629 --- /dev/null +++ b/packages/pinball_components/test/src/components/error_component_test.dart @@ -0,0 +1,57 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame/components.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball_components/pinball_components.dart'; + +import '../../helpers/helpers.dart'; + +extension _IterableX on Iterable { + int countTexts(String value) { + return where( + (component) => component is TextComponent && component.text == value, + ).length; + } +} + +void main() { + group('ErrorComponent', () { + TestWidgetsFlutterBinding.ensureInitialized(); + final assets = [ + Assets.images.errorBackground.keyName, + ]; + final flameTester = FlameTester(() => TestGame(assets)); + + flameTester.test('renders correctly', (game) async { + await game.ensureAdd(ErrorComponent(label: 'Error Message')); + final count = game.descendants().countTexts('Error Message'); + + expect(count, equals(1)); + }); + + group('when the text is longer than one line', () { + flameTester.test('renders correctly', (game) async { + await game.ensureAdd( + ErrorComponent( + label: 'Error With A Longer Message', + ), + ); + final count1 = game.descendants().countTexts('Error With A'); + final count2 = game.descendants().countTexts('Longer Message'); + + expect(count1, equals(1)); + expect(count2, equals(1)); + }); + }); + + group('when using the bold font', () { + flameTester.test('renders correctly', (game) async { + await game.ensureAdd(ErrorComponent.bold(label: 'Error Message')); + final count = game.descendants().countTexts('Error Message'); + + expect(count, equals(1)); + }); + }); + }); +}