diff --git a/assets/images/bonus_animation/android_spaceship.png b/assets/images/bonus_animation/android_spaceship.png index 200e1c6c..66cc8b6a 100644 Binary files a/assets/images/bonus_animation/android_spaceship.png and b/assets/images/bonus_animation/android_spaceship.png differ diff --git a/assets/images/bonus_animation/dash_nest.png b/assets/images/bonus_animation/dash_nest.png index 210f17cb..42aa8b9e 100644 Binary files a/assets/images/bonus_animation/dash_nest.png and b/assets/images/bonus_animation/dash_nest.png differ diff --git a/assets/images/bonus_animation/dino_chomp.png b/assets/images/bonus_animation/dino_chomp.png index a8a9cfe3..c6825c0b 100644 Binary files a/assets/images/bonus_animation/dino_chomp.png and b/assets/images/bonus_animation/dino_chomp.png differ diff --git a/assets/images/bonus_animation/google_word.png b/assets/images/bonus_animation/google_word.png index c4ab2948..fa07da65 100644 Binary files a/assets/images/bonus_animation/google_word.png and b/assets/images/bonus_animation/google_word.png differ diff --git a/assets/images/bonus_animation/sparky_turbo_charge.png b/assets/images/bonus_animation/sparky_turbo_charge.png index 8b3491e8..c5d2d9d3 100644 Binary files a/assets/images/bonus_animation/sparky_turbo_charge.png and b/assets/images/bonus_animation/sparky_turbo_charge.png differ diff --git a/assets/images/link_box/info_icon.png b/assets/images/link_box/info_icon.png deleted file mode 100644 index 78556be0..00000000 Binary files a/assets/images/link_box/info_icon.png and /dev/null differ diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index 89f03dfa..f621f1e2 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -9,20 +9,24 @@ import 'package:pinball/select_character/select_character.dart'; import 'package:pinball/start_game/start_game.dart'; import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_ui/pinball_ui.dart'; +import 'package:share_repository/share_repository.dart'; class App extends StatelessWidget { const App({ Key? key, required AuthenticationRepository authenticationRepository, required LeaderboardRepository leaderboardRepository, + required ShareRepository shareRepository, required PinballAudioPlayer pinballAudioPlayer, }) : _authenticationRepository = authenticationRepository, _leaderboardRepository = leaderboardRepository, + _shareRepository = shareRepository, _pinballAudioPlayer = pinballAudioPlayer, super(key: key); final AuthenticationRepository _authenticationRepository; final LeaderboardRepository _leaderboardRepository; + final ShareRepository _shareRepository; final PinballAudioPlayer _pinballAudioPlayer; @override @@ -31,6 +35,7 @@ class App extends StatelessWidget { providers: [ RepositoryProvider.value(value: _authenticationRepository), RepositoryProvider.value(value: _leaderboardRepository), + RepositoryProvider.value(value: _shareRepository), RepositoryProvider.value(value: _pinballAudioPlayer), ], child: MultiBlocProvider( diff --git a/lib/assets_manager/cubit/assets_manager_cubit.dart b/lib/assets_manager/cubit/assets_manager_cubit.dart index 65b780c2..eb0f7e31 100644 --- a/lib/assets_manager/cubit/assets_manager_cubit.dart +++ b/lib/assets_manager/cubit/assets_manager_cubit.dart @@ -18,7 +18,7 @@ class AssetsManagerCubit extends Cubit { /// delay here, which is a bit random in duration but enough to let the UI /// do its job without adding too much delay for the user, we are letting /// the UI paint first, and then we start loading the assets. - await Future.delayed(const Duration(milliseconds: 300)); + await Future.delayed(const Duration(seconds: 1)); emit( state.copyWith( loadables: [ diff --git a/lib/game/behaviors/behaviors.dart b/lib/game/behaviors/behaviors.dart index 8d5ee04e..bb196cec 100644 --- a/lib/game/behaviors/behaviors.dart +++ b/lib/game/behaviors/behaviors.dart @@ -4,4 +4,6 @@ export 'bonus_noise_behavior.dart'; export 'bumper_noise_behavior.dart'; export 'camera_focusing_behavior.dart'; export 'character_selection_behavior.dart'; +export 'cow_bumper_noise_behavior.dart'; +export 'kicker_noise_behavior.dart'; export 'scoring_behavior.dart'; diff --git a/lib/game/behaviors/cow_bumper_noise_behavior.dart b/lib/game/behaviors/cow_bumper_noise_behavior.dart new file mode 100644 index 00000000..14ad1307 --- /dev/null +++ b/lib/game/behaviors/cow_bumper_noise_behavior.dart @@ -0,0 +1,13 @@ +// ignore_for_file: public_member_api_docs + +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:pinball_audio/pinball_audio.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +class CowBumperNoiseBehavior extends ContactBehavior { + @override + void beginContact(Object other, Contact contact) { + super.beginContact(other, contact); + readProvider().play(PinballAudio.cowMoo); + } +} diff --git a/lib/game/behaviors/kicker_noise_behavior.dart b/lib/game/behaviors/kicker_noise_behavior.dart new file mode 100644 index 00000000..a04ffeff --- /dev/null +++ b/lib/game/behaviors/kicker_noise_behavior.dart @@ -0,0 +1,11 @@ +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:pinball_audio/pinball_audio.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +class KickerNoiseBehavior extends ContactBehavior { + @override + void beginContact(Object other, Contact contact) { + super.beginContact(other, contact); + readProvider().play(PinballAudio.kicker); + } +} diff --git a/lib/game/bloc/game_bloc.dart b/lib/game/bloc/game_bloc.dart index 795d04e2..c63bf514 100644 --- a/lib/game/bloc/game_bloc.dart +++ b/lib/game/bloc/game_bloc.dart @@ -16,6 +16,8 @@ class GameBloc extends Bloc { on(_onGameStarted); } + static const _maxScore = 9999999999; + void _onGameStarted(GameStarted _, Emitter emit) { emit(state.copyWith(status: GameStatus.playing)); } @@ -25,7 +27,10 @@ class GameBloc extends Bloc { } void _onRoundLost(RoundLost event, Emitter emit) { - final score = state.totalScore + state.roundScore * state.multiplier; + final score = math.min( + state.totalScore + state.roundScore * state.multiplier, + _maxScore, + ); final roundsLeft = math.max(state.rounds - 1, 0); emit( @@ -41,9 +46,11 @@ class GameBloc extends Bloc { void _onScored(Scored event, Emitter emit) { if (state.status.isPlaying) { - emit( - state.copyWith(roundScore: state.roundScore + event.points), + final combinedScore = math.min( + state.totalScore + state.roundScore + event.points, + _maxScore, ); + emit(state.copyWith(roundScore: combinedScore - state.totalScore)); } } diff --git a/lib/game/components/android_acres/android_acres.dart b/lib/game/components/android_acres/android_acres.dart index 902eb11c..fd59ace3 100644 --- a/lib/game/components/android_acres/android_acres.dart +++ b/lib/game/components/android_acres/android_acres.dart @@ -48,6 +48,7 @@ class AndroidAcres extends Component { children: [ ScoringContactBehavior(points: Points.twentyThousand), BumperNoiseBehavior(), + CowBumperNoiseBehavior(), ], )..initialPosition = Vector2(-20.7, -13), AndroidSpaceshipBonusBehavior(), diff --git a/lib/game/components/backbox/backbox.dart b/lib/game/components/backbox/backbox.dart index e455e89f..dad2c118 100644 --- a/lib/game/components/backbox/backbox.dart +++ b/lib/game/components/backbox/backbox.dart @@ -6,10 +6,13 @@ import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:pinball/game/components/backbox/bloc/backbox_bloc.dart'; import 'package:pinball/game/components/backbox/displays/displays.dart'; import 'package:pinball/game/game.dart'; +import 'package:pinball/l10n/l10n.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_theme/pinball_theme.dart' hide Assets; +import 'package:pinball_ui/pinball_ui.dart'; import 'package:platform_helper/platform_helper.dart'; +import 'package:share_repository/share_repository.dart'; /// {@template backbox} /// The [Backbox] of the pinball machine. @@ -18,21 +21,26 @@ class Backbox extends PositionComponent with ZIndex, HasGameRef { /// {@macro backbox} Backbox({ required LeaderboardRepository leaderboardRepository, + required ShareRepository shareRepository, required List? entries, }) : _bloc = BackboxBloc( leaderboardRepository: leaderboardRepository, initialEntries: entries, ), + _shareRepository = shareRepository, _platformHelper = PlatformHelper(); /// {@macro backbox} @visibleForTesting Backbox.test({ required BackboxBloc bloc, + required ShareRepository shareRepository, required PlatformHelper platformHelper, }) : _bloc = bloc, + _shareRepository = shareRepository, _platformHelper = platformHelper; + final ShareRepository _shareRepository; late final Component _display; final BackboxBloc _bloc; final PlatformHelper _platformHelper; @@ -87,6 +95,8 @@ class Backbox extends PositionComponent with ZIndex, HasGameRef { ), ); } else if (state is InitialsSuccessState) { + gameRef.overlays.remove(PinballGame.mobileControlsOverlay); + _display.add( GameOverInfoDisplay( onShare: () { @@ -94,6 +104,20 @@ class Backbox extends PositionComponent with ZIndex, HasGameRef { }, ), ); + } else if (state is ShareState) { + _display.add( + ShareDisplay( + onShare: (platform) { + final message = readProvider() + .iGotScoreAtPinball(state.score); + final url = _shareRepository.shareText( + value: message, + platform: platform, + ); + openLink(url); + }, + ), + ); } else if (state is InitialsFailureState) { _display.add( InitialsSubmissionFailureDisplay( diff --git a/lib/game/components/backbox/bloc/backbox_bloc.dart b/lib/game/components/backbox/bloc/backbox_bloc.dart index 8a89b1bd..cfac4c6f 100644 --- a/lib/game/components/backbox/bloc/backbox_bloc.dart +++ b/lib/game/components/backbox/bloc/backbox_bloc.dart @@ -75,9 +75,7 @@ class BackboxBloc extends Bloc { Emitter emit, ) async { emit( - ShareState( - score: event.score, - ), + ShareState(score: event.score), ); } diff --git a/lib/game/components/backbox/displays/displays.dart b/lib/game/components/backbox/displays/displays.dart index 2b8a38ae..f80c0b54 100644 --- a/lib/game/components/backbox/displays/displays.dart +++ b/lib/game/components/backbox/displays/displays.dart @@ -5,3 +5,4 @@ export 'initials_submission_success_display.dart'; export 'leaderboard_display.dart'; export 'leaderboard_failure_display.dart'; export 'loading_display.dart'; +export 'share_display.dart'; diff --git a/lib/game/components/backbox/displays/share_display.dart b/lib/game/components/backbox/displays/share_display.dart new file mode 100644 index 00000000..ebaaac7e --- /dev/null +++ b/lib/game/components/backbox/displays/share_display.dart @@ -0,0 +1,189 @@ +import 'dart:async'; + +import 'package:flame/components.dart'; +import 'package:flame/input.dart'; +import 'package:flutter/material.dart'; +import 'package:pinball/l10n/l10n.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; +import 'package:pinball_ui/pinball_ui.dart'; +import 'package:share_repository/share_repository.dart'; + +/// Signature for the callback called when the user tries to share their score +/// on the [ShareDisplay]. +typedef OnSocialShareTap = void Function(SharePlatform); + +final _descriptionTextPaint = TextPaint( + style: const TextStyle( + fontSize: 1.6, + color: PinballColors.white, + fontFamily: PinballFonts.pixeloidSans, + ), +); + +/// {@template share_display} +/// Display that allows users to share their score to social networks. +/// {@endtemplate} +class ShareDisplay extends Component with HasGameRef { + /// {@macro share_display} + ShareDisplay({ + OnSocialShareTap? onShare, + }) : super( + children: [ + _ShareInstructionsComponent( + onShare: onShare, + ), + ], + ); +} + +class _ShareInstructionsComponent extends PositionComponent with HasGameRef { + _ShareInstructionsComponent({ + OnSocialShareTap? onShare, + }) : super( + anchor: Anchor.center, + position: Vector2(0, -25), + children: [ + _DescriptionComponent(), + _SocialNetworksComponent( + onShare: onShare, + ), + ], + ); +} + +class _DescriptionComponent extends PositionComponent with HasGameRef { + _DescriptionComponent() + : super( + anchor: Anchor.center, + position: Vector2.zero(), + children: [ + _LetEveryoneTextComponent(), + _SharingYourScoreTextComponent(), + _SocialMediaTextComponent(), + ], + ); +} + +class _LetEveryoneTextComponent extends TextComponent with HasGameRef { + _LetEveryoneTextComponent() + : super( + anchor: Anchor.center, + position: Vector2.zero(), + textRenderer: _descriptionTextPaint, + ); + + @override + Future onLoad() async { + await super.onLoad(); + text = readProvider().letEveryone; + } +} + +class _SharingYourScoreTextComponent extends TextComponent with HasGameRef { + _SharingYourScoreTextComponent() + : super( + anchor: Anchor.center, + position: Vector2(0, 2.5), + textRenderer: _descriptionTextPaint, + ); + + @override + Future onLoad() async { + await super.onLoad(); + text = readProvider().bySharingYourScore; + } +} + +class _SocialMediaTextComponent extends TextComponent with HasGameRef { + _SocialMediaTextComponent() + : super( + anchor: Anchor.center, + position: Vector2(0, 5), + textRenderer: _descriptionTextPaint, + ); + + @override + Future onLoad() async { + await super.onLoad(); + text = readProvider().socialMediaAccount; + } +} + +class _SocialNetworksComponent extends PositionComponent with HasGameRef { + _SocialNetworksComponent({ + OnSocialShareTap? onShare, + }) : super( + anchor: Anchor.center, + position: Vector2(0, 12), + children: [ + FacebookButtonComponent(onTap: onShare), + TwitterButtonComponent(onTap: onShare), + ], + ); +} + +/// {@template facebook_button_component} +/// Button for sharing on Facebook. +/// {@endtemplate} +class FacebookButtonComponent extends SpriteComponent + with HasGameRef, Tappable { + /// {@macro facebook_button_component} + FacebookButtonComponent({ + OnSocialShareTap? onTap, + }) : _onTap = onTap, + super( + anchor: Anchor.center, + position: Vector2(-5, 0), + ); + + final OnSocialShareTap? _onTap; + + @override + bool onTapDown(TapDownInfo info) { + _onTap?.call(SharePlatform.facebook); + return true; + } + + @override + Future onLoad() async { + await super.onLoad(); + final sprite = Sprite( + gameRef.images.fromCache(Assets.images.backbox.button.facebook.keyName), + ); + this.sprite = sprite; + size = sprite.originalSize / 25; + } +} + +/// {@template twitter_button_component} +/// Button for sharing on Twitter. +/// {@endtemplate} +class TwitterButtonComponent extends SpriteComponent with HasGameRef, Tappable { + /// {@macro twitter_button_component} + TwitterButtonComponent({ + OnSocialShareTap? onTap, + }) : _onTap = onTap, + super( + anchor: Anchor.center, + position: Vector2(5, 0), + ); + + final OnSocialShareTap? _onTap; + + @override + bool onTapDown(TapDownInfo info) { + _onTap?.call(SharePlatform.twitter); + return true; + } + + @override + Future onLoad() async { + await super.onLoad(); + final sprite = Sprite( + gameRef.images.fromCache(Assets.images.backbox.button.twitter.keyName), + ); + this.sprite = sprite; + size = sprite.originalSize / 25; + } +} diff --git a/lib/game/components/bottom_group.dart b/lib/game/components/bottom_group.dart index bc644f96..cfa7e434 100644 --- a/lib/game/components/bottom_group.dart +++ b/lib/game/components/bottom_group.dart @@ -52,6 +52,7 @@ class _BottomGroupSide extends Component { children: [ ScoringContactBehavior(points: Points.fiveThousand) ..applyTo(['bouncy_edge']), + KickerNoiseBehavior()..applyTo(['bouncy_edge']), ], )..initialPosition = Vector2( (22.44 * direction) + centerXAdjustment, diff --git a/lib/game/game_assets.dart b/lib/game/game_assets.dart index 1c634bfd..ef6f60df 100644 --- a/lib/game/game_assets.dart +++ b/lib/game/game_assets.dart @@ -102,6 +102,8 @@ extension PinballGameAssetsX on PinballGame { images.load(components.Assets.images.sparky.bumper.c.dimmed.keyName), images.load(components.Assets.images.backbox.marquee.keyName), images.load(components.Assets.images.backbox.displayDivider.keyName), + images.load(components.Assets.images.backbox.button.facebook.keyName), + images.load(components.Assets.images.backbox.button.twitter.keyName), images.load( components.Assets.images.backbox.displayTitleDecoration.keyName, ), diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index 5691b7ba..d455b583 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -15,12 +15,14 @@ import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; import 'package:platform_helper/platform_helper.dart'; +import 'package:share_repository/share_repository.dart'; class PinballGame extends PinballForge2DGame with HasKeyboardHandlerComponents, MultiTouchTapDetector, HasTappables { PinballGame({ required CharacterThemeCubit characterThemeBloc, required this.leaderboardRepository, + required this.shareRepository, required GameBloc gameBloc, required AppLocalizations l10n, required PinballAudioPlayer audioPlayer, @@ -52,6 +54,8 @@ class PinballGame extends PinballForge2DGame final LeaderboardRepository leaderboardRepository; + final ShareRepository shareRepository; + final AppLocalizations _l10n; final GameBloc _gameBloc; @@ -85,6 +89,7 @@ class PinballGame extends PinballForge2DGame providers: [ FlameProvider.value(_audioPlayer), FlameProvider.value(leaderboardRepository), + FlameProvider.value(shareRepository), FlameProvider.value(_l10n), ], children: [ @@ -107,6 +112,7 @@ class PinballGame extends PinballForge2DGame Boundaries(), Backbox( leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, entries: _entries, ), GoogleWord(position: Vector2(-4.45, 1.8)), @@ -189,6 +195,7 @@ class DebugPinballGame extends PinballGame with FPSCounter, PanDetector { DebugPinballGame({ required CharacterThemeCubit characterThemeBloc, required LeaderboardRepository leaderboardRepository, + required ShareRepository shareRepository, required AppLocalizations l10n, required PinballAudioPlayer audioPlayer, required GameBloc gameBloc, @@ -196,6 +203,7 @@ class DebugPinballGame extends PinballGame with FPSCounter, PanDetector { characterThemeBloc: characterThemeBloc, audioPlayer: audioPlayer, leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, l10n: l10n, gameBloc: gameBloc, ); diff --git a/lib/game/view/pinball_game_page.dart b/lib/game/view/pinball_game_page.dart index 6e910817..a36754d8 100644 --- a/lib/game/view/pinball_game_page.dart +++ b/lib/game/view/pinball_game_page.dart @@ -5,13 +5,13 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:pinball/assets_manager/assets_manager.dart'; import 'package:pinball/game/game.dart'; -import 'package:pinball/gen/gen.dart'; import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/more_information/more_information.dart'; import 'package:pinball/select_character/select_character.dart'; import 'package:pinball/start_game/start_game.dart'; import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_ui/pinball_ui.dart'; +import 'package:share_repository/share_repository.dart'; class PinballGamePage extends StatelessWidget { const PinballGamePage({ @@ -26,12 +26,14 @@ class PinballGamePage extends StatelessWidget { final characterThemeBloc = context.read(); final audioPlayer = context.read(); final leaderboardRepository = context.read(); + final shareRepository = context.read(); final gameBloc = context.read(); final game = isDebugMode ? DebugPinballGame( characterThemeBloc: characterThemeBloc, audioPlayer: audioPlayer, leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, l10n: context.l10n, gameBloc: gameBloc, ) @@ -39,6 +41,7 @@ class PinballGamePage extends StatelessWidget { characterThemeBloc: characterThemeBloc, audioPlayer: audioPlayer, leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, l10n: context.l10n, gameBloc: gameBloc, ); @@ -163,7 +166,7 @@ class _PositionedInfoIcon extends StatelessWidget { visible: state.status.isGameOver, child: IconButton( iconSize: 50, - icon: Assets.images.linkBox.infoIcon.image(), + icon: const Icon(Icons.info, color: PinballColors.white), onPressed: () => showMoreInformationDialog(context), ), ); diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart index f0b6fdeb..8d81e5c6 100644 --- a/lib/gen/assets.gen.dart +++ b/lib/gen/assets.gen.dart @@ -14,7 +14,6 @@ class $AssetsImagesGen { const $AssetsImagesBonusAnimationGen(); $AssetsImagesComponentsGen get components => const $AssetsImagesComponentsGen(); - $AssetsImagesLinkBoxGen get linkBox => const $AssetsImagesLinkBoxGen(); $AssetsImagesLoadingGameGen get loadingGame => const $AssetsImagesLoadingGameGen(); $AssetsImagesScoreGen get score => const $AssetsImagesScoreGen(); @@ -56,14 +55,6 @@ 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 $AssetsImagesLoadingGameGen { const $AssetsImagesLoadingGameGen(); diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 8573c585..a9b12291 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -189,7 +189,7 @@ "description": "Text shown on the mobile controls enter button" }, "initialsErrorTitle": "Uh-oh... well, that didn’t work", - "@enter": { + "@initialsErrorTitle": { "description": "Title shown when the initials submission fails" }, "initialsErrorMessage": "Please try a different combination of letters", @@ -200,4 +200,26 @@ "@leaderboardErrorMessage": { "description": "Text shown when the leaderboard had an error while loading" } + , + "letEveryone": "Let everyone know about I/O Pinball", + "@letEveryone": { + "description": "Text displayed on share screen for description" + }, + "bySharingYourScore": "by sharing your score to your preferred", + "@bySharingYourScore": { + "description": "Text displayed on share screen for description" + }, + "socialMediaAccount": "social media account!", + "@socialMediaAccount": { + "description": "Text displayed on share screen for description" + }, + "iGotScoreAtPinball": "I got {score} at the #IOPinball machine, can you beat my score? See you at #GoogleIO!", + "@iGotScoreAtPinball": { + "description": "Text to share score on Social Network", + "placeholders": { + "score": { + "type": "int" + } + } + } } diff --git a/lib/main.dart b/lib/main.dart index 158966c8..cb8c78da 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,10 +6,13 @@ import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:pinball/app/app.dart'; import 'package:pinball/bootstrap.dart'; import 'package:pinball_audio/pinball_audio.dart'; +import 'package:share_repository/share_repository.dart'; void main() { bootstrap((firestore, firebaseAuth) async { final leaderboardRepository = LeaderboardRepository(firestore); + const shareRepository = + ShareRepository(appUrl: ShareRepository.pinballGameUrl); final authenticationRepository = AuthenticationRepository(firebaseAuth); final pinballAudioPlayer = PinballAudioPlayer(); unawaited( @@ -20,6 +23,7 @@ void main() { return App( authenticationRepository: authenticationRepository, leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, pinballAudioPlayer: pinballAudioPlayer, ); }); diff --git a/packages/pinball_audio/assets/sfx/cow_moo.mp3 b/packages/pinball_audio/assets/sfx/cow_moo.mp3 new file mode 100644 index 00000000..ce69e941 Binary files /dev/null and b/packages/pinball_audio/assets/sfx/cow_moo.mp3 differ diff --git a/packages/pinball_audio/assets/sfx/kicker_a.mp3 b/packages/pinball_audio/assets/sfx/kicker_a.mp3 new file mode 100644 index 00000000..475cbc13 Binary files /dev/null and b/packages/pinball_audio/assets/sfx/kicker_a.mp3 differ diff --git a/packages/pinball_audio/assets/sfx/kicker_b.mp3 b/packages/pinball_audio/assets/sfx/kicker_b.mp3 new file mode 100644 index 00000000..2b1bdfbc Binary files /dev/null and b/packages/pinball_audio/assets/sfx/kicker_b.mp3 differ diff --git a/packages/pinball_audio/lib/gen/assets.gen.dart b/packages/pinball_audio/lib/gen/assets.gen.dart index bdd8e09e..c8b66234 100644 --- a/packages/pinball_audio/lib/gen/assets.gen.dart +++ b/packages/pinball_audio/lib/gen/assets.gen.dart @@ -17,11 +17,14 @@ class $AssetsSfxGen { String get android => 'assets/sfx/android.mp3'; String get bumperA => 'assets/sfx/bumper_a.mp3'; String get bumperB => 'assets/sfx/bumper_b.mp3'; + String get cowMoo => 'assets/sfx/cow_moo.mp3'; String get dash => 'assets/sfx/dash.mp3'; String get dino => 'assets/sfx/dino.mp3'; String get gameOverVoiceOver => 'assets/sfx/game_over_voice_over.mp3'; String get google => 'assets/sfx/google.mp3'; String get ioPinballVoiceOver => 'assets/sfx/io_pinball_voice_over.mp3'; + String get kickerA => 'assets/sfx/kicker_a.mp3'; + String get kickerB => 'assets/sfx/kicker_b.mp3'; String get launcher => 'assets/sfx/launcher.mp3'; String get sparky => 'assets/sfx/sparky.mp3'; } diff --git a/packages/pinball_audio/lib/src/pinball_audio.dart b/packages/pinball_audio/lib/src/pinball_audio.dart index 1756d965..98074fc5 100644 --- a/packages/pinball_audio/lib/src/pinball_audio.dart +++ b/packages/pinball_audio/lib/src/pinball_audio.dart @@ -1,32 +1,39 @@ import 'dart:math'; import 'package:audioplayers/audioplayers.dart'; +import 'package:clock/clock.dart'; import 'package:flame_audio/audio_pool.dart'; import 'package:flame_audio/flame_audio.dart'; import 'package:flutter/material.dart'; import 'package:pinball_audio/gen/assets.gen.dart'; -/// Sounds available for play +/// Sounds available to play. enum PinballAudio { - /// Google + /// Google. google, - /// Bumper + /// Bumper. bumper, - /// Background music + /// Cow moo. + cowMoo, + + /// Background music. backgroundMusic, - /// IO Pinball voice over + /// IO Pinball voice over. ioPinballVoiceOver, - /// Game over + /// Game over. gameOverVoiceOver, - /// Launcher + /// Launcher. launcher, - /// Sparky + /// Kicker. + kicker, + + /// Sparky. sparky, /// Android @@ -109,44 +116,79 @@ class _LoopAudio extends _Audio { } } -class _BumperAudio extends _Audio { - _BumperAudio({ +class _RandomABAudio extends _Audio { + _RandomABAudio({ required this.createAudioPool, required this.seed, + required this.audioAssetA, + required this.audioAssetB, + this.volume, }); final CreateAudioPool createAudioPool; final Random seed; + final String audioAssetA; + final String audioAssetB; + final double? volume; - late AudioPool bumperA; - late AudioPool bumperB; + late AudioPool audioA; + late AudioPool audioB; @override Future load() async { await Future.wait( [ createAudioPool( - prefixFile(Assets.sfx.bumperA), + prefixFile(audioAssetA), maxPlayers: 4, prefix: '', - ).then((pool) => bumperA = pool), + ).then((pool) => audioA = pool), createAudioPool( - prefixFile(Assets.sfx.bumperB), + prefixFile(audioAssetB), maxPlayers: 4, prefix: '', - ).then((pool) => bumperB = pool), + ).then((pool) => audioB = pool), ], ); } @override void play() { - (seed.nextBool() ? bumperA : bumperB).start(volume: 0.6); + (seed.nextBool() ? audioA : audioB).start(volume: volume ?? 1); + } +} + +class _ThrottledAudio extends _Audio { + _ThrottledAudio({ + required this.preCacheSingleAudio, + required this.playSingleAudio, + required this.path, + required this.duration, + }); + + final PreCacheSingleAudio preCacheSingleAudio; + final PlaySingleAudio playSingleAudio; + final String path; + final Duration duration; + + DateTime? _lastPlayed; + + @override + Future load() => preCacheSingleAudio(prefixFile(path)); + + @override + void play() { + final now = clock.now(); + if (_lastPlayed == null || + (_lastPlayed != null && now.difference(_lastPlayed!) > duration)) { + _lastPlayed = now; + playSingleAudio(prefixFile(path)); + } } } /// {@template pinball_audio_player} -/// Sound manager for the pinball game +/// Sound manager for the pinball game. /// {@endtemplate} class PinballAudioPlayer { /// {@macro pinball_audio_player} @@ -208,9 +250,25 @@ class PinballAudioPlayer { playSingleAudio: _playSingleAudio, path: Assets.sfx.gameOverVoiceOver, ), - PinballAudio.bumper: _BumperAudio( + PinballAudio.bumper: _RandomABAudio( createAudioPool: _createAudioPool, seed: _seed, + audioAssetA: Assets.sfx.bumperA, + audioAssetB: Assets.sfx.bumperB, + volume: 0.6, + ), + PinballAudio.kicker: _RandomABAudio( + createAudioPool: _createAudioPool, + seed: _seed, + audioAssetA: Assets.sfx.kickerA, + audioAssetB: Assets.sfx.kickerB, + volume: 0.6, + ), + PinballAudio.cowMoo: _ThrottledAudio( + preCacheSingleAudio: _preCacheSingleAudio, + playSingleAudio: _playSingleAudio, + path: Assets.sfx.cowMoo, + duration: const Duration(seconds: 2), ), PinballAudio.backgroundMusic: _LoopAudio( preCacheSingleAudio: _preCacheSingleAudio, @@ -232,19 +290,19 @@ class PinballAudioPlayer { final Random _seed; - /// Registered audios on the Player + /// Registered audios on the Player. @visibleForTesting // ignore: library_private_types_in_public_api late final Map audios; - /// Loads the sounds effects into the memory + /// Loads the sounds effects into the memory. List> load() { _configureAudioCache(FlameAudio.audioCache); return audios.values.map((a) => a.load()).toList(); } - /// Plays the received audio + /// Plays the received audio. void play(PinballAudio audio) { assert( audios.containsKey(audio), diff --git a/packages/pinball_audio/pubspec.yaml b/packages/pinball_audio/pubspec.yaml index 74713dfa..8c99d1fc 100644 --- a/packages/pinball_audio/pubspec.yaml +++ b/packages/pinball_audio/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: audioplayers: ^0.20.1 + clock: ^1.1.0 flame_audio: ^1.0.1 flutter: sdk: flutter diff --git a/packages/pinball_audio/test/src/pinball_audio_test.dart b/packages/pinball_audio/test/src/pinball_audio_test.dart index 8374e820..df21b1ad 100644 --- a/packages/pinball_audio/test/src/pinball_audio_test.dart +++ b/packages/pinball_audio/test/src/pinball_audio_test.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'package:audioplayers/audioplayers.dart'; +import 'package:clock/clock.dart'; import 'package:flame_audio/audio_pool.dart'; import 'package:flame_audio/flame_audio.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -43,6 +44,8 @@ class _MockPreCacheSingleAudio extends Mock implements _PreCacheSingleAudio {} class _MockRandom extends Mock implements Random {} +class _MockClock extends Mock implements Clock {} + void main() { group('PinballAudio', () { late _MockCreateAudioPool createAudioPool; @@ -116,6 +119,26 @@ void main() { ).called(1); }); + test('creates the kicker pools', () async { + await Future.wait(audioPlayer.load()); + + verify( + () => createAudioPool.onCall( + 'packages/pinball_audio/${Assets.sfx.kickerA}', + maxPlayers: 4, + prefix: '', + ), + ).called(1); + + verify( + () => createAudioPool.onCall( + 'packages/pinball_audio/${Assets.sfx.kickerB}', + maxPlayers: 4, + prefix: '', + ), + ).called(1); + }); + test('configures the audio cache instance', () async { await Future.wait(audioPlayer.load()); @@ -171,6 +194,10 @@ void main() { () => preCacheSingleAudio .onCall('packages/pinball_audio/assets/sfx/launcher.mp3'), ).called(1); + verify( + () => preCacheSingleAudio + .onCall('packages/pinball_audio/assets/sfx/cow_moo.mp3'), + ).called(1); verify( () => preCacheSingleAudio .onCall('packages/pinball_audio/assets/music/background.mp3'), @@ -227,6 +254,91 @@ void main() { }); }); + group('kicker', () { + late AudioPool kickerAPool; + late AudioPool kickerBPool; + + setUp(() { + kickerAPool = _MockAudioPool(); + when(() => kickerAPool.start(volume: any(named: 'volume'))) + .thenAnswer((_) async => () {}); + when( + () => createAudioPool.onCall( + 'packages/pinball_audio/${Assets.sfx.kickerA}', + maxPlayers: any(named: 'maxPlayers'), + prefix: any(named: 'prefix'), + ), + ).thenAnswer((_) async => kickerAPool); + + kickerBPool = _MockAudioPool(); + when(() => kickerBPool.start(volume: any(named: 'volume'))) + .thenAnswer((_) async => () {}); + when( + () => createAudioPool.onCall( + 'packages/pinball_audio/${Assets.sfx.kickerB}', + maxPlayers: any(named: 'maxPlayers'), + prefix: any(named: 'prefix'), + ), + ).thenAnswer((_) async => kickerBPool); + }); + + group('when seed is true', () { + test('plays the kicker A sound pool', () async { + when(seed.nextBool).thenReturn(true); + await Future.wait(audioPlayer.load()); + audioPlayer.play(PinballAudio.kicker); + + verify(() => kickerAPool.start(volume: 0.6)).called(1); + }); + }); + + group('when seed is false', () { + test('plays the kicker B sound pool', () async { + when(seed.nextBool).thenReturn(false); + await Future.wait(audioPlayer.load()); + audioPlayer.play(PinballAudio.kicker); + + verify(() => kickerBPool.start(volume: 0.6)).called(1); + }); + }); + }); + + group('cow moo', () { + test('plays the correct file', () async { + await Future.wait(audioPlayer.load()); + audioPlayer.play(PinballAudio.cowMoo); + + verify( + () => playSingleAudio + .onCall('packages/pinball_audio/${Assets.sfx.cowMoo}'), + ).called(1); + }); + + test('only plays the sound again after 2 seconds', () async { + final clock = _MockClock(); + await withClock(clock, () async { + when(clock.now).thenReturn(DateTime(2022)); + await Future.wait(audioPlayer.load()); + audioPlayer + ..play(PinballAudio.cowMoo) + ..play(PinballAudio.cowMoo); + + verify( + () => playSingleAudio + .onCall('packages/pinball_audio/${Assets.sfx.cowMoo}'), + ).called(1); + + when(clock.now).thenReturn(DateTime(2022, 1, 1, 1, 2)); + audioPlayer.play(PinballAudio.cowMoo); + + verify( + () => playSingleAudio + .onCall('packages/pinball_audio/${Assets.sfx.cowMoo}'), + ).called(1); + }); + }); + }); + group('google', () { test('plays the correct file', () async { await Future.wait(audioPlayer.load()); diff --git a/packages/pinball_components/assets/images/backbox/button/facebook.png b/packages/pinball_components/assets/images/backbox/button/facebook.png new file mode 100644 index 00000000..f6d29ab2 Binary files /dev/null and b/packages/pinball_components/assets/images/backbox/button/facebook.png differ diff --git a/packages/pinball_components/assets/images/backbox/button/twitter.png b/packages/pinball_components/assets/images/backbox/button/twitter.png new file mode 100644 index 00000000..f109a4b8 Binary files /dev/null and b/packages/pinball_components/assets/images/backbox/button/twitter.png differ diff --git a/packages/pinball_components/assets/images/backbox/marquee.png b/packages/pinball_components/assets/images/backbox/marquee.png index ee98a495..8603c9b8 100644 Binary files a/packages/pinball_components/assets/images/backbox/marquee.png and b/packages/pinball_components/assets/images/backbox/marquee.png differ diff --git a/packages/pinball_components/assets/images/ball/flame_effect.png b/packages/pinball_components/assets/images/ball/flame_effect.png index 03a6fca6..b1397f36 100644 Binary files a/packages/pinball_components/assets/images/ball/flame_effect.png and b/packages/pinball_components/assets/images/ball/flame_effect.png differ diff --git a/packages/pinball_components/assets/images/baseboard/left.png b/packages/pinball_components/assets/images/baseboard/left.png index d13b4e31..552c6e1d 100644 Binary files a/packages/pinball_components/assets/images/baseboard/left.png and b/packages/pinball_components/assets/images/baseboard/left.png differ diff --git a/packages/pinball_components/assets/images/baseboard/right.png b/packages/pinball_components/assets/images/baseboard/right.png index 8ad93045..9088d7e0 100644 Binary files a/packages/pinball_components/assets/images/baseboard/right.png and b/packages/pinball_components/assets/images/baseboard/right.png differ diff --git a/packages/pinball_components/assets/images/board_background.png b/packages/pinball_components/assets/images/board_background.png index dabf9026..41af91ec 100644 Binary files a/packages/pinball_components/assets/images/board_background.png and b/packages/pinball_components/assets/images/board_background.png differ diff --git a/packages/pinball_components/assets/images/boundary/bottom.png b/packages/pinball_components/assets/images/boundary/bottom.png index 523e6156..a9e5785b 100644 Binary files a/packages/pinball_components/assets/images/boundary/bottom.png and b/packages/pinball_components/assets/images/boundary/bottom.png differ diff --git a/packages/pinball_components/assets/images/boundary/outer.png b/packages/pinball_components/assets/images/boundary/outer.png index 75ccdb6b..d7bc719e 100644 Binary files a/packages/pinball_components/assets/images/boundary/outer.png and b/packages/pinball_components/assets/images/boundary/outer.png differ diff --git a/packages/pinball_components/assets/images/boundary/outer_bottom.png b/packages/pinball_components/assets/images/boundary/outer_bottom.png index 508bcee8..9f5cd308 100644 Binary files a/packages/pinball_components/assets/images/boundary/outer_bottom.png and b/packages/pinball_components/assets/images/boundary/outer_bottom.png differ diff --git a/packages/pinball_components/assets/images/dash/animatronic.png b/packages/pinball_components/assets/images/dash/animatronic.png index 13f7b794..d2aa19c5 100644 Binary files a/packages/pinball_components/assets/images/dash/animatronic.png and b/packages/pinball_components/assets/images/dash/animatronic.png differ diff --git a/packages/pinball_components/assets/images/dino/animatronic/head.png b/packages/pinball_components/assets/images/dino/animatronic/head.png index 87332679..44ce80f2 100644 Binary files a/packages/pinball_components/assets/images/dino/animatronic/head.png and b/packages/pinball_components/assets/images/dino/animatronic/head.png differ diff --git a/packages/pinball_components/assets/images/dino/animatronic/mouth.png b/packages/pinball_components/assets/images/dino/animatronic/mouth.png index 4955bdf3..98b1386b 100644 Binary files a/packages/pinball_components/assets/images/dino/animatronic/mouth.png and b/packages/pinball_components/assets/images/dino/animatronic/mouth.png differ diff --git a/packages/pinball_components/assets/images/error_background.png b/packages/pinball_components/assets/images/error_background.png index 5aa6595f..73e934ca 100644 Binary files a/packages/pinball_components/assets/images/error_background.png and b/packages/pinball_components/assets/images/error_background.png differ diff --git a/packages/pinball_components/assets/images/launch_ramp/background_railing.png b/packages/pinball_components/assets/images/launch_ramp/background_railing.png index aa7d5774..e9201957 100644 Binary files a/packages/pinball_components/assets/images/launch_ramp/background_railing.png and b/packages/pinball_components/assets/images/launch_ramp/background_railing.png differ diff --git a/packages/pinball_components/assets/images/launch_ramp/foreground_railing.png b/packages/pinball_components/assets/images/launch_ramp/foreground_railing.png index f953fdf5..1a48f663 100644 Binary files a/packages/pinball_components/assets/images/launch_ramp/foreground_railing.png and b/packages/pinball_components/assets/images/launch_ramp/foreground_railing.png differ diff --git a/packages/pinball_components/assets/images/launch_ramp/ramp.png b/packages/pinball_components/assets/images/launch_ramp/ramp.png index 61481f5a..6b2edde1 100644 Binary files a/packages/pinball_components/assets/images/launch_ramp/ramp.png and b/packages/pinball_components/assets/images/launch_ramp/ramp.png differ diff --git a/packages/pinball_components/assets/images/plunger/plunger.png b/packages/pinball_components/assets/images/plunger/plunger.png index 2ec6e001..df5812cd 100644 Binary files a/packages/pinball_components/assets/images/plunger/plunger.png and b/packages/pinball_components/assets/images/plunger/plunger.png differ diff --git a/packages/pinball_components/assets/images/plunger/rocket.png b/packages/pinball_components/assets/images/plunger/rocket.png index a8f89152..ef2df7e5 100644 Binary files a/packages/pinball_components/assets/images/plunger/rocket.png and b/packages/pinball_components/assets/images/plunger/rocket.png differ diff --git a/packages/pinball_components/assets/images/score/five_thousand.png b/packages/pinball_components/assets/images/score/five_thousand.png index d373e2e1..a2c37dec 100644 Binary files a/packages/pinball_components/assets/images/score/five_thousand.png and b/packages/pinball_components/assets/images/score/five_thousand.png differ diff --git a/packages/pinball_components/assets/images/score/one_million.png b/packages/pinball_components/assets/images/score/one_million.png index 5c7ec15b..fcbd4919 100644 Binary files a/packages/pinball_components/assets/images/score/one_million.png and b/packages/pinball_components/assets/images/score/one_million.png differ diff --git a/packages/pinball_components/assets/images/score/twenty_thousand.png b/packages/pinball_components/assets/images/score/twenty_thousand.png index 2f9bfd57..cebdf3b5 100644 Binary files a/packages/pinball_components/assets/images/score/twenty_thousand.png and b/packages/pinball_components/assets/images/score/twenty_thousand.png differ diff --git a/packages/pinball_components/assets/images/score/two_hundred_thousand.png b/packages/pinball_components/assets/images/score/two_hundred_thousand.png index a6f19db4..672b18a0 100644 Binary files a/packages/pinball_components/assets/images/score/two_hundred_thousand.png and b/packages/pinball_components/assets/images/score/two_hundred_thousand.png differ diff --git a/packages/pinball_components/assets/images/signpost/active1.png b/packages/pinball_components/assets/images/signpost/active1.png index 78997bf6..23f5836f 100644 Binary files a/packages/pinball_components/assets/images/signpost/active1.png and b/packages/pinball_components/assets/images/signpost/active1.png differ diff --git a/packages/pinball_components/assets/images/signpost/active2.png b/packages/pinball_components/assets/images/signpost/active2.png index 39caa821..6f79aa47 100644 Binary files a/packages/pinball_components/assets/images/signpost/active2.png and b/packages/pinball_components/assets/images/signpost/active2.png differ diff --git a/packages/pinball_components/assets/images/signpost/active3.png b/packages/pinball_components/assets/images/signpost/active3.png index f43c190c..7d54547a 100644 Binary files a/packages/pinball_components/assets/images/signpost/active3.png and b/packages/pinball_components/assets/images/signpost/active3.png differ diff --git a/packages/pinball_components/assets/images/signpost/inactive.png b/packages/pinball_components/assets/images/signpost/inactive.png index 9fa23330..f0721f3c 100644 Binary files a/packages/pinball_components/assets/images/signpost/inactive.png and b/packages/pinball_components/assets/images/signpost/inactive.png differ diff --git a/packages/pinball_components/assets/images/skill_shot/decal.png b/packages/pinball_components/assets/images/skill_shot/decal.png index 120d70aa..02fbd5cf 100644 Binary files a/packages/pinball_components/assets/images/skill_shot/decal.png and b/packages/pinball_components/assets/images/skill_shot/decal.png differ diff --git a/packages/pinball_components/assets/images/skill_shot/dimmed.png b/packages/pinball_components/assets/images/skill_shot/dimmed.png index 7cc32bd4..4e3a5ca9 100644 Binary files a/packages/pinball_components/assets/images/skill_shot/dimmed.png and b/packages/pinball_components/assets/images/skill_shot/dimmed.png differ diff --git a/packages/pinball_components/assets/images/skill_shot/lit.png b/packages/pinball_components/assets/images/skill_shot/lit.png index d1bce99b..cc825171 100644 Binary files a/packages/pinball_components/assets/images/skill_shot/lit.png and b/packages/pinball_components/assets/images/skill_shot/lit.png differ diff --git a/packages/pinball_components/assets/images/skill_shot/pin.png b/packages/pinball_components/assets/images/skill_shot/pin.png index 5b64e1ab..61126586 100644 Binary files a/packages/pinball_components/assets/images/skill_shot/pin.png and b/packages/pinball_components/assets/images/skill_shot/pin.png differ diff --git a/packages/pinball_components/assets/images/sparky/animatronic.png b/packages/pinball_components/assets/images/sparky/animatronic.png index cc57e405..a19c3dac 100644 Binary files a/packages/pinball_components/assets/images/sparky/animatronic.png and b/packages/pinball_components/assets/images/sparky/animatronic.png differ diff --git a/packages/pinball_components/assets/images/sparky/computer/base.png b/packages/pinball_components/assets/images/sparky/computer/base.png index 188e4329..9abd60d8 100644 Binary files a/packages/pinball_components/assets/images/sparky/computer/base.png and b/packages/pinball_components/assets/images/sparky/computer/base.png differ diff --git a/packages/pinball_components/assets/images/sparky/computer/glow.png b/packages/pinball_components/assets/images/sparky/computer/glow.png index 7fd9a0c8..8190d131 100644 Binary files a/packages/pinball_components/assets/images/sparky/computer/glow.png and b/packages/pinball_components/assets/images/sparky/computer/glow.png differ diff --git a/packages/pinball_components/assets/images/sparky/computer/top.png b/packages/pinball_components/assets/images/sparky/computer/top.png index 085771cd..445a8027 100644 Binary files a/packages/pinball_components/assets/images/sparky/computer/top.png and b/packages/pinball_components/assets/images/sparky/computer/top.png differ diff --git a/packages/pinball_components/lib/gen/assets.gen.dart b/packages/pinball_components/lib/gen/assets.gen.dart index 0c51342b..f233596c 100644 --- a/packages/pinball_components/lib/gen/assets.gen.dart +++ b/packages/pinball_components/lib/gen/assets.gen.dart @@ -59,6 +59,9 @@ class $AssetsImagesAndroidGen { class $AssetsImagesBackboxGen { const $AssetsImagesBackboxGen(); + $AssetsImagesBackboxButtonGen get button => + const $AssetsImagesBackboxButtonGen(); + /// File path: assets/images/backbox/display_divider.png AssetGenImage get displayDivider => const AssetGenImage('assets/images/backbox/display_divider.png'); @@ -386,6 +389,18 @@ class $AssetsImagesAndroidSpaceshipGen { const AssetGenImage('assets/images/android/spaceship/saucer.png'); } +class $AssetsImagesBackboxButtonGen { + const $AssetsImagesBackboxButtonGen(); + + /// File path: assets/images/backbox/button/facebook.png + AssetGenImage get facebook => + const AssetGenImage('assets/images/backbox/button/facebook.png'); + + /// File path: assets/images/backbox/button/twitter.png + AssetGenImage get twitter => + const AssetGenImage('assets/images/backbox/button/twitter.png'); +} + class $AssetsImagesDashBumperGen { const $AssetsImagesDashBumperGen(); diff --git a/packages/pinball_components/pubspec.yaml b/packages/pinball_components/pubspec.yaml index c430d670..3301a0fc 100644 --- a/packages/pinball_components/pubspec.yaml +++ b/packages/pinball_components/pubspec.yaml @@ -90,6 +90,7 @@ flutter: - assets/images/multiplier/x6/ - assets/images/score/ - assets/images/backbox/ + - assets/images/backbox/button/ - assets/images/flapper/ - assets/images/skill_shot/ diff --git a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/down.png b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/down.png index a84d84c2..58180a63 100644 Binary files a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/down.png and b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/down.png differ diff --git a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/middle.png b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/middle.png index 0515f5f5..b6d31b1f 100644 Binary files a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/middle.png and b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/middle.png differ diff --git a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/up.png b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/up.png index 0a2d4674..48a834c0 100644 Binary files a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/up.png and b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/up.png differ diff --git a/packages/pinball_components/test/src/components/golden/baseboard.png b/packages/pinball_components/test/src/components/golden/baseboard.png index 01141551..4b051dfa 100644 Binary files a/packages/pinball_components/test/src/components/golden/baseboard.png and b/packages/pinball_components/test/src/components/golden/baseboard.png differ diff --git a/packages/pinball_components/test/src/components/golden/board_background.png b/packages/pinball_components/test/src/components/golden/board_background.png index 31abceb1..c15a29ce 100644 Binary files a/packages/pinball_components/test/src/components/golden/board_background.png and b/packages/pinball_components/test/src/components/golden/board_background.png differ diff --git a/packages/pinball_components/test/src/components/golden/boundaries.png b/packages/pinball_components/test/src/components/golden/boundaries.png index e8075f63..ab6716dd 100644 Binary files a/packages/pinball_components/test/src/components/golden/boundaries.png and b/packages/pinball_components/test/src/components/golden/boundaries.png differ diff --git a/packages/pinball_components/test/src/components/golden/camera_zoom/finished.png b/packages/pinball_components/test/src/components/golden/camera_zoom/finished.png index 035a152f..f31d05e0 100644 Binary files a/packages/pinball_components/test/src/components/golden/camera_zoom/finished.png and b/packages/pinball_components/test/src/components/golden/camera_zoom/finished.png differ diff --git a/packages/pinball_components/test/src/components/golden/camera_zoom/in_between.png b/packages/pinball_components/test/src/components/golden/camera_zoom/in_between.png index 23c1142d..f2074da8 100644 Binary files a/packages/pinball_components/test/src/components/golden/camera_zoom/in_between.png and b/packages/pinball_components/test/src/components/golden/camera_zoom/in_between.png differ diff --git a/packages/pinball_components/test/src/components/golden/camera_zoom/no_zoom.png b/packages/pinball_components/test/src/components/golden/camera_zoom/no_zoom.png index 200ab49f..2975ac0d 100644 Binary files a/packages/pinball_components/test/src/components/golden/camera_zoom/no_zoom.png and b/packages/pinball_components/test/src/components/golden/camera_zoom/no_zoom.png differ diff --git a/packages/pinball_components/test/src/components/golden/dash_animatronic/end.png b/packages/pinball_components/test/src/components/golden/dash_animatronic/end.png index c8218fe1..3ee917ee 100644 Binary files a/packages/pinball_components/test/src/components/golden/dash_animatronic/end.png and b/packages/pinball_components/test/src/components/golden/dash_animatronic/end.png differ diff --git a/packages/pinball_components/test/src/components/golden/dash_animatronic/middle.png b/packages/pinball_components/test/src/components/golden/dash_animatronic/middle.png index 9e79695a..e57d0f07 100644 Binary files a/packages/pinball_components/test/src/components/golden/dash_animatronic/middle.png and b/packages/pinball_components/test/src/components/golden/dash_animatronic/middle.png differ diff --git a/packages/pinball_components/test/src/components/golden/dash_animatronic/start.png b/packages/pinball_components/test/src/components/golden/dash_animatronic/start.png index 3e5e91f5..5a16627d 100644 Binary files a/packages/pinball_components/test/src/components/golden/dash_animatronic/start.png and b/packages/pinball_components/test/src/components/golden/dash_animatronic/start.png differ diff --git a/packages/pinball_components/test/src/components/golden/launch_ramp.png b/packages/pinball_components/test/src/components/golden/launch_ramp.png index 50a4ed4c..0ff6ef45 100644 Binary files a/packages/pinball_components/test/src/components/golden/launch_ramp.png and b/packages/pinball_components/test/src/components/golden/launch_ramp.png differ diff --git a/packages/pinball_components/test/src/components/golden/plunger/pull.png b/packages/pinball_components/test/src/components/golden/plunger/pull.png index 0ec27a4e..cdbb3e31 100644 Binary files a/packages/pinball_components/test/src/components/golden/plunger/pull.png and b/packages/pinball_components/test/src/components/golden/plunger/pull.png differ diff --git a/packages/pinball_components/test/src/components/golden/plunger/release.png b/packages/pinball_components/test/src/components/golden/plunger/release.png index 61f7a4d9..cda853c3 100644 Binary files a/packages/pinball_components/test/src/components/golden/plunger/release.png and b/packages/pinball_components/test/src/components/golden/plunger/release.png differ diff --git a/packages/pinball_components/test/src/components/golden/rocket.png b/packages/pinball_components/test/src/components/golden/rocket.png index f9dc36f8..8ee4009d 100644 Binary files a/packages/pinball_components/test/src/components/golden/rocket.png and b/packages/pinball_components/test/src/components/golden/rocket.png differ diff --git a/packages/pinball_components/test/src/components/golden/score/1m.png b/packages/pinball_components/test/src/components/golden/score/1m.png index bb2f5631..7045a039 100644 Binary files a/packages/pinball_components/test/src/components/golden/score/1m.png and b/packages/pinball_components/test/src/components/golden/score/1m.png differ diff --git a/packages/pinball_components/test/src/components/golden/score/200k.png b/packages/pinball_components/test/src/components/golden/score/200k.png index c25d116b..46503f3d 100644 Binary files a/packages/pinball_components/test/src/components/golden/score/200k.png and b/packages/pinball_components/test/src/components/golden/score/200k.png differ diff --git a/packages/pinball_components/test/src/components/golden/score/20k.png b/packages/pinball_components/test/src/components/golden/score/20k.png index 2a4446c3..42721119 100644 Binary files a/packages/pinball_components/test/src/components/golden/score/20k.png and b/packages/pinball_components/test/src/components/golden/score/20k.png differ diff --git a/packages/pinball_components/test/src/components/golden/score/5k.png b/packages/pinball_components/test/src/components/golden/score/5k.png index 8f2a7973..1e5117f1 100644 Binary files a/packages/pinball_components/test/src/components/golden/score/5k.png and b/packages/pinball_components/test/src/components/golden/score/5k.png differ diff --git a/packages/pinball_components/test/src/components/golden/signpost/active1.png b/packages/pinball_components/test/src/components/golden/signpost/active1.png index 0e0f9e79..9b8ac5dd 100644 Binary files a/packages/pinball_components/test/src/components/golden/signpost/active1.png and b/packages/pinball_components/test/src/components/golden/signpost/active1.png differ diff --git a/packages/pinball_components/test/src/components/golden/signpost/active2.png b/packages/pinball_components/test/src/components/golden/signpost/active2.png index 9dfae564..e86ee7bf 100644 Binary files a/packages/pinball_components/test/src/components/golden/signpost/active2.png and b/packages/pinball_components/test/src/components/golden/signpost/active2.png differ diff --git a/packages/pinball_components/test/src/components/golden/signpost/active3.png b/packages/pinball_components/test/src/components/golden/signpost/active3.png index a99c9e48..557e9605 100644 Binary files a/packages/pinball_components/test/src/components/golden/signpost/active3.png and b/packages/pinball_components/test/src/components/golden/signpost/active3.png differ diff --git a/packages/pinball_components/test/src/components/golden/signpost/inactive.png b/packages/pinball_components/test/src/components/golden/signpost/inactive.png index 7f089716..5e67d706 100644 Binary files a/packages/pinball_components/test/src/components/golden/signpost/inactive.png and b/packages/pinball_components/test/src/components/golden/signpost/inactive.png differ diff --git a/packages/pinball_components/test/src/components/golden/sparky_animatronic/end.png b/packages/pinball_components/test/src/components/golden/sparky_animatronic/end.png index 5e963f14..d499e754 100644 Binary files a/packages/pinball_components/test/src/components/golden/sparky_animatronic/end.png and b/packages/pinball_components/test/src/components/golden/sparky_animatronic/end.png differ diff --git a/packages/pinball_components/test/src/components/golden/sparky_animatronic/middle.png b/packages/pinball_components/test/src/components/golden/sparky_animatronic/middle.png index 2665c5cb..dea793d9 100644 Binary files a/packages/pinball_components/test/src/components/golden/sparky_animatronic/middle.png and b/packages/pinball_components/test/src/components/golden/sparky_animatronic/middle.png differ diff --git a/packages/pinball_components/test/src/components/golden/sparky_animatronic/start.png b/packages/pinball_components/test/src/components/golden/sparky_animatronic/start.png index ea3e6344..663d8090 100644 Binary files a/packages/pinball_components/test/src/components/golden/sparky_animatronic/start.png and b/packages/pinball_components/test/src/components/golden/sparky_animatronic/start.png differ diff --git a/packages/pinball_components/test/src/components/golden/sparky_computer.png b/packages/pinball_components/test/src/components/golden/sparky_computer.png index ebe2e98e..22fdc7e5 100644 Binary files a/packages/pinball_components/test/src/components/golden/sparky_computer.png and b/packages/pinball_components/test/src/components/golden/sparky_computer.png differ diff --git a/packages/pinball_theme/assets/images/android/animation.png b/packages/pinball_theme/assets/images/android/animation.png index fc7465be..47f5f74c 100644 Binary files a/packages/pinball_theme/assets/images/android/animation.png and b/packages/pinball_theme/assets/images/android/animation.png differ diff --git a/packages/pinball_theme/assets/images/android/background.jpg b/packages/pinball_theme/assets/images/android/background.jpg index f446e140..bb1a6992 100644 Binary files a/packages/pinball_theme/assets/images/android/background.jpg and b/packages/pinball_theme/assets/images/android/background.jpg differ diff --git a/packages/pinball_theme/assets/images/android/ball.png b/packages/pinball_theme/assets/images/android/ball.png index ca2eebe3..8310c098 100644 Binary files a/packages/pinball_theme/assets/images/android/ball.png and b/packages/pinball_theme/assets/images/android/ball.png differ diff --git a/packages/pinball_theme/assets/images/android/icon.png b/packages/pinball_theme/assets/images/android/icon.png index ff365ffe..03857b0a 100644 Binary files a/packages/pinball_theme/assets/images/android/icon.png and b/packages/pinball_theme/assets/images/android/icon.png differ diff --git a/packages/pinball_theme/assets/images/android/leaderboard_icon.png b/packages/pinball_theme/assets/images/android/leaderboard_icon.png index 238e29ef..ae97c412 100644 Binary files a/packages/pinball_theme/assets/images/android/leaderboard_icon.png and b/packages/pinball_theme/assets/images/android/leaderboard_icon.png differ diff --git a/packages/pinball_theme/assets/images/dash/animation.png b/packages/pinball_theme/assets/images/dash/animation.png index e812415f..97d4fb07 100644 Binary files a/packages/pinball_theme/assets/images/dash/animation.png and b/packages/pinball_theme/assets/images/dash/animation.png differ diff --git a/packages/pinball_theme/assets/images/dash/background.jpg b/packages/pinball_theme/assets/images/dash/background.jpg index dc698060..667454f4 100644 Binary files a/packages/pinball_theme/assets/images/dash/background.jpg and b/packages/pinball_theme/assets/images/dash/background.jpg differ diff --git a/packages/pinball_theme/assets/images/dash/ball.png b/packages/pinball_theme/assets/images/dash/ball.png index 69e8dffa..f93023f6 100644 Binary files a/packages/pinball_theme/assets/images/dash/ball.png and b/packages/pinball_theme/assets/images/dash/ball.png differ diff --git a/packages/pinball_theme/assets/images/dash/icon.png b/packages/pinball_theme/assets/images/dash/icon.png index 45bba327..0df550ea 100644 Binary files a/packages/pinball_theme/assets/images/dash/icon.png and b/packages/pinball_theme/assets/images/dash/icon.png differ diff --git a/packages/pinball_theme/assets/images/dash/leaderboard_icon.png b/packages/pinball_theme/assets/images/dash/leaderboard_icon.png index 5c172d47..69b2919c 100644 Binary files a/packages/pinball_theme/assets/images/dash/leaderboard_icon.png and b/packages/pinball_theme/assets/images/dash/leaderboard_icon.png differ diff --git a/packages/pinball_theme/assets/images/dino/animation.png b/packages/pinball_theme/assets/images/dino/animation.png index c75b16f9..de7e1b60 100644 Binary files a/packages/pinball_theme/assets/images/dino/animation.png and b/packages/pinball_theme/assets/images/dino/animation.png differ diff --git a/packages/pinball_theme/assets/images/dino/background.jpg b/packages/pinball_theme/assets/images/dino/background.jpg index 45272247..6cf0626e 100644 Binary files a/packages/pinball_theme/assets/images/dino/background.jpg and b/packages/pinball_theme/assets/images/dino/background.jpg differ diff --git a/packages/pinball_theme/assets/images/dino/ball.png b/packages/pinball_theme/assets/images/dino/ball.png index 1a2102d8..7c1885a2 100644 Binary files a/packages/pinball_theme/assets/images/dino/ball.png and b/packages/pinball_theme/assets/images/dino/ball.png differ diff --git a/packages/pinball_theme/assets/images/dino/icon.png b/packages/pinball_theme/assets/images/dino/icon.png index 0114060e..28682c73 100644 Binary files a/packages/pinball_theme/assets/images/dino/icon.png and b/packages/pinball_theme/assets/images/dino/icon.png differ diff --git a/packages/pinball_theme/assets/images/dino/leaderboard_icon.png b/packages/pinball_theme/assets/images/dino/leaderboard_icon.png index b1033371..4a230b39 100644 Binary files a/packages/pinball_theme/assets/images/dino/leaderboard_icon.png and b/packages/pinball_theme/assets/images/dino/leaderboard_icon.png differ diff --git a/packages/pinball_theme/assets/images/pinball_button.png b/packages/pinball_theme/assets/images/pinball_button.png index 62373b85..8d10ec7c 100644 Binary files a/packages/pinball_theme/assets/images/pinball_button.png and b/packages/pinball_theme/assets/images/pinball_button.png differ diff --git a/packages/pinball_theme/assets/images/select_character_background.png b/packages/pinball_theme/assets/images/select_character_background.png index 69120148..7ba7f17f 100644 Binary files a/packages/pinball_theme/assets/images/select_character_background.png and b/packages/pinball_theme/assets/images/select_character_background.png differ diff --git a/packages/pinball_theme/assets/images/sparky/animation.png b/packages/pinball_theme/assets/images/sparky/animation.png index 1aff4772..ce51eb0d 100644 Binary files a/packages/pinball_theme/assets/images/sparky/animation.png and b/packages/pinball_theme/assets/images/sparky/animation.png differ diff --git a/packages/pinball_theme/assets/images/sparky/background.jpg b/packages/pinball_theme/assets/images/sparky/background.jpg index ad19a47a..08ad2dba 100644 Binary files a/packages/pinball_theme/assets/images/sparky/background.jpg and b/packages/pinball_theme/assets/images/sparky/background.jpg differ diff --git a/packages/pinball_theme/assets/images/sparky/ball.png b/packages/pinball_theme/assets/images/sparky/ball.png index fe3f4e82..7fd20368 100644 Binary files a/packages/pinball_theme/assets/images/sparky/ball.png and b/packages/pinball_theme/assets/images/sparky/ball.png differ diff --git a/packages/pinball_theme/assets/images/sparky/icon.png b/packages/pinball_theme/assets/images/sparky/icon.png index 4e484438..46b8dfa3 100644 Binary files a/packages/pinball_theme/assets/images/sparky/icon.png and b/packages/pinball_theme/assets/images/sparky/icon.png differ diff --git a/packages/pinball_theme/assets/images/sparky/leaderboard_icon.png b/packages/pinball_theme/assets/images/sparky/leaderboard_icon.png index 76001516..bd5e56e1 100644 Binary files a/packages/pinball_theme/assets/images/sparky/leaderboard_icon.png and b/packages/pinball_theme/assets/images/sparky/leaderboard_icon.png differ diff --git a/packages/pinball_ui/assets/images/button/dpad_down.png b/packages/pinball_ui/assets/images/button/dpad_down.png index 11bbb26f..71c4b0a7 100644 Binary files a/packages/pinball_ui/assets/images/button/dpad_down.png and b/packages/pinball_ui/assets/images/button/dpad_down.png differ diff --git a/packages/pinball_ui/assets/images/button/dpad_left.png b/packages/pinball_ui/assets/images/button/dpad_left.png index 943cacc4..a0979677 100644 Binary files a/packages/pinball_ui/assets/images/button/dpad_left.png and b/packages/pinball_ui/assets/images/button/dpad_left.png differ diff --git a/packages/pinball_ui/assets/images/button/dpad_right.png b/packages/pinball_ui/assets/images/button/dpad_right.png index 724b9f3e..9e7a2be9 100644 Binary files a/packages/pinball_ui/assets/images/button/dpad_right.png and b/packages/pinball_ui/assets/images/button/dpad_right.png differ diff --git a/packages/pinball_ui/assets/images/button/dpad_up.png b/packages/pinball_ui/assets/images/button/dpad_up.png index d1175d57..6113e3de 100644 Binary files a/packages/pinball_ui/assets/images/button/dpad_up.png and b/packages/pinball_ui/assets/images/button/dpad_up.png differ diff --git a/packages/pinball_ui/assets/images/button/pinball_button.png b/packages/pinball_ui/assets/images/button/pinball_button.png index 62373b85..8d10ec7c 100644 Binary files a/packages/pinball_ui/assets/images/button/pinball_button.png and b/packages/pinball_ui/assets/images/button/pinball_button.png differ diff --git a/packages/pinball_ui/assets/images/dialog/background.png b/packages/pinball_ui/assets/images/dialog/background.png index 0aad300f..82b3cb58 100644 Binary files a/packages/pinball_ui/assets/images/dialog/background.png and b/packages/pinball_ui/assets/images/dialog/background.png differ diff --git a/packages/share_repository/lib/src/share_repository.dart b/packages/share_repository/lib/src/share_repository.dart index e01f5746..16c29aee 100644 --- a/packages/share_repository/lib/src/share_repository.dart +++ b/packages/share_repository/lib/src/share_repository.dart @@ -17,6 +17,9 @@ class ShareRepository { /// Url to the Google IO Event. static const googleIOEvent = 'https://events.google.com/io/'; + /// Url to the Pinball game. + static const pinballGameUrl = 'https://ashehwkdkdjruejdnensjsjdne.web.app/#/'; + /// Returns a url to share the [value] on the given [platform]. /// /// The returned url can be opened using the [url_launcher](https://pub.dev/packages/url_launcher) package. diff --git a/pubspec.yaml b/pubspec.yaml index 1b71a25f..7f925688 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,7 +64,6 @@ flutter: - assets/images/components/ - assets/images/bonus_animation/ - assets/images/score/ - - assets/images/link_box/ - assets/images/loading_game/ flutter_gen: diff --git a/test/app/view/app_test.dart b/test/app/view/app_test.dart index 4612641d..d247a562 100644 --- a/test/app/view/app_test.dart +++ b/test/app/view/app_test.dart @@ -5,6 +5,7 @@ import 'package:mocktail/mocktail.dart'; import 'package:pinball/app/app.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_audio/pinball_audio.dart'; +import 'package:share_repository/share_repository.dart'; class _MockAuthenticationRepository extends Mock implements AuthenticationRepository {} @@ -14,15 +15,19 @@ class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { } +class _MockShareRepository extends Mock implements ShareRepository {} + void main() { group('App', () { late AuthenticationRepository authenticationRepository; late LeaderboardRepository leaderboardRepository; + late ShareRepository shareRepository; late PinballAudioPlayer pinballAudioPlayer; setUp(() { authenticationRepository = _MockAuthenticationRepository(); leaderboardRepository = _MockLeaderboardRepository(); + shareRepository = _MockShareRepository(); pinballAudioPlayer = _MockPinballAudioPlayer(); when(pinballAudioPlayer.load).thenAnswer((_) => [Future.value()]); }); @@ -32,10 +37,11 @@ void main() { App( authenticationRepository: authenticationRepository, leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, pinballAudioPlayer: pinballAudioPlayer, ), ); - await tester.pump(const Duration(milliseconds: 400)); + await tester.pump(const Duration(milliseconds: 1100)); expect(find.byType(PinballGamePage), findsOneWidget); }); }); diff --git a/test/game/behaviors/bumper_noise_behavior_test.dart b/test/game/behaviors/bumper_noise_behavior_test.dart index 58bda07d..cf6c7900 100644 --- a/test/game/behaviors/bumper_noise_behavior_test.dart +++ b/test/game/behaviors/bumper_noise_behavior_test.dart @@ -16,9 +16,7 @@ class _TestGame extends Forge2DGame { return ensureAdd( FlameProvider.value( audioPlayer, - children: [ - child, - ], + children: [child], ), ); } diff --git a/test/game/behaviors/cow_bumper_noise_behavior_test.dart b/test/game/behaviors/cow_bumper_noise_behavior_test.dart new file mode 100644 index 00000000..27a62e0b --- /dev/null +++ b/test/game/behaviors/cow_bumper_noise_behavior_test.dart @@ -0,0 +1,58 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball/game/behaviors/behaviors.dart'; +import 'package:pinball_audio/pinball_audio.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +class _TestGame extends Forge2DGame { + Future pump( + _TestBodyComponent child, { + required PinballAudioPlayer audioPlayer, + }) { + return ensureAdd( + FlameProvider.value( + audioPlayer, + children: [child], + ), + ); + } +} + +class _TestBodyComponent extends BodyComponent { + @override + Body createBody() => world.createBody(BodyDef()); +} + +class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} + +class _MockContact extends Mock implements Contact {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('CowBumperNoiseBehavior', () { + late PinballAudioPlayer audioPlayer; + final flameTester = FlameTester(_TestGame.new); + + setUp(() { + audioPlayer = _MockPinballAudioPlayer(); + }); + flameTester.testGameWidget( + 'plays cow moo sound on contact', + setUp: (game, _) async { + final behavior = CowBumperNoiseBehavior(); + final parent = _TestBodyComponent(); + await game.pump(parent, audioPlayer: audioPlayer); + await parent.ensureAdd(behavior); + behavior.beginContact(Object(), _MockContact()); + }, + verify: (_, __) async { + verify(() => audioPlayer.play(PinballAudio.cowMoo)).called(1); + }, + ); + }); +} diff --git a/test/game/behaviors/kicker_noise_behavior_test.dart b/test/game/behaviors/kicker_noise_behavior_test.dart new file mode 100644 index 00000000..4db18ab4 --- /dev/null +++ b/test/game/behaviors/kicker_noise_behavior_test.dart @@ -0,0 +1,59 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball/game/behaviors/behaviors.dart'; +import 'package:pinball_audio/pinball_audio.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +class _TestGame extends Forge2DGame { + Future pump( + _TestBodyComponent child, { + required PinballAudioPlayer audioPlayer, + }) { + return ensureAdd( + FlameProvider.value( + audioPlayer, + children: [child], + ), + ); + } +} + +class _TestBodyComponent extends BodyComponent { + @override + Body createBody() => world.createBody(BodyDef()); +} + +class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} + +class _MockContact extends Mock implements Contact {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('KickerNoiseBehavior', () { + late PinballAudioPlayer audioPlayer; + final flameTester = FlameTester(_TestGame.new); + + setUp(() { + audioPlayer = _MockPinballAudioPlayer(); + }); + + flameTester.testGameWidget( + 'plays kicker sound', + setUp: (game, _) async { + final behavior = KickerNoiseBehavior(); + final parent = _TestBodyComponent(); + await game.pump(parent, audioPlayer: audioPlayer); + await parent.ensureAdd(behavior); + behavior.beginContact(Object(), _MockContact()); + }, + verify: (_, __) async { + verify(() => audioPlayer.play(PinballAudio.kicker)).called(1); + }, + ); + }); +} diff --git a/test/game/bloc/game_bloc_test.dart b/test/game/bloc/game_bloc_test.dart index 9e8c6354..2108b950 100644 --- a/test/game/bloc/game_bloc_test.dart +++ b/test/game/bloc/game_bloc_test.dart @@ -91,6 +91,28 @@ void main() { ], ); + blocTest( + "multiplier doesn't increase score above the max score", + build: GameBloc.new, + seed: () => const GameState( + totalScore: 9999999998, + roundScore: 1, + multiplier: 2, + rounds: 1, + bonusHistory: [], + status: GameStatus.playing, + ), + act: (bloc) => bloc.add(const RoundLost()), + expect: () => [ + isA() + ..having( + (state) => state.totalScore, + 'totalScore', + 9999999999, + ) + ], + ); + blocTest( 'resets multiplier when round is lost', build: GameBloc.new, @@ -167,6 +189,23 @@ void main() { ), ], ); + + blocTest( + "doesn't increase score above the max score", + build: GameBloc.new, + seed: () => const GameState( + totalScore: 9999999998, + roundScore: 0, + multiplier: 1, + rounds: 1, + bonusHistory: [], + status: GameStatus.playing, + ), + act: (bloc) => bloc.add(const Scored(points: 2)), + expect: () => [ + isA()..having((state) => state.roundScore, 'roundScore', 1) + ], + ); }); group('MultiplierIncreased', () { diff --git a/test/game/components/android_acres/android_acres_test.dart b/test/game/components/android_acres/android_acres_test.dart index 5bf22da9..5c750818 100644 --- a/test/game/components/android_acres/android_acres_test.dart +++ b/test/game/components/android_acres/android_acres_test.dart @@ -4,7 +4,7 @@ import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:pinball/game/behaviors/bumper_noise_behavior.dart'; +import 'package:pinball/game/behaviors/behaviors.dart'; import 'package:pinball/game/components/android_acres/behaviors/behaviors.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -124,11 +124,26 @@ void main() { for (final bumper in bumpers) { expect( bumper.firstChild(), - isNotNull, + isA(), ); } }, ); + + flameTester.test( + 'one AndroidBumper with CowBumperNoiseBehavior', + (game) async { + await game.pump(AndroidAcres()); + final bumpers = game.descendants().whereType(); + + expect( + bumpers.singleWhere( + (bumper) => bumper.firstChild() != null, + ), + isA(), + ); + }, + ); }); flameTester.test('adds a FlameBlocProvider', (game) async { diff --git a/test/game/components/backbox/backbox_test.dart b/test/game/components/backbox/backbox_test.dart index 65474cd2..b99b86ab 100644 --- a/test/game/components/backbox/backbox_test.dart +++ b/test/game/components/backbox/backbox_test.dart @@ -20,7 +20,10 @@ import 'package:pinball/l10n/l10n.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_theme/pinball_theme.dart' as theme; +import 'package:pinball_ui/pinball_ui.dart'; import 'package:platform_helper/platform_helper.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'package:share_repository/share_repository.dart'; class _TestGame extends Forge2DGame with HasKeyboardHandlerComponents, HasTappables { @@ -36,6 +39,8 @@ class _TestGame extends Forge2DGame character.leaderboardIcon.keyName, Assets.images.backbox.marquee.keyName, Assets.images.backbox.displayDivider.keyName, + Assets.images.backbox.button.facebook.keyName, + Assets.images.backbox.button.twitter.keyName, Assets.images.backbox.displayTitleDecoration.keyName, ]); } @@ -75,8 +80,14 @@ class _MockBackboxBloc extends Mock implements BackboxBloc {} class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { } +class _MockShareRepository extends Mock implements ShareRepository {} + class _MockTapDownInfo extends Mock implements TapDownInfo {} +class _MockUrlLauncher extends Mock + with MockPlatformInterfaceMixin + implements UrlLauncherPlatform {} + class _MockAppLocalizations extends Mock implements AppLocalizations { @override String get score => ''; @@ -105,6 +116,15 @@ class _MockAppLocalizations extends Mock implements AppLocalizations { @override String get loading => ''; + @override + String get letEveryone => ''; + + @override + String get bySharingYourScore => ''; + + @override + String get socialMediaAccount => ''; + @override String get shareYourScore => ''; @@ -134,6 +154,9 @@ class _MockAppLocalizations extends Mock implements AppLocalizations { @override String get leaderboardErrorMessage => ''; + + @override + String iGotScoreAtPinball(int _) => ''; } void main() { @@ -143,6 +166,7 @@ void main() { late BackboxBloc bloc; late PlatformHelper platformHelper; + late UrlLauncherPlatform urlLauncher; setUp(() { bloc = _MockBackboxBloc(); @@ -161,6 +185,7 @@ void main() { (game) async { final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -178,6 +203,7 @@ void main() { await game.pump( Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ), ); @@ -199,6 +225,7 @@ void main() { leaderboardRepository: _MockLeaderboardRepository(), initialEntries: [LeaderboardEntryData.empty], ), + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -230,6 +257,7 @@ void main() { ); final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -258,6 +286,7 @@ void main() { ); final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -270,7 +299,8 @@ void main() { ); flameTester.test( - 'adds the mobile controls overlay when platform is mobile', + 'adds the mobile controls overlay ' + 'when platform is mobile at InitialsFormState', (game) async { final bloc = _MockBackboxBloc(); final platformHelper = _MockPlatformHelper(); @@ -286,6 +316,7 @@ void main() { when(() => platformHelper.isMobile).thenReturn(true); final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -297,6 +328,33 @@ void main() { }, ); + flameTester.test( + 'remove the mobile controls overlay ' + 'when InitialsSuccessState', + (game) async { + final bloc = _MockBackboxBloc(); + final platformHelper = _MockPlatformHelper(); + final state = InitialsSuccessState(score: 10); + whenListen( + bloc, + Stream.empty(), + initialState: state, + ); + when(() => platformHelper.isMobile).thenReturn(true); + final backbox = Backbox.test( + bloc: bloc, + shareRepository: _MockShareRepository(), + platformHelper: platformHelper, + ); + await game.pump(backbox); + + expect( + game.overlays.value, + isNot(contains(PinballGame.mobileControlsOverlay)), + ); + }, + ); + flameTester.test( 'adds InitialsSubmissionSuccessDisplay on InitialsSuccessState', (game) async { @@ -308,6 +366,7 @@ void main() { ); final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -330,6 +389,7 @@ void main() { ); final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -359,6 +419,7 @@ void main() { ); final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -373,6 +434,145 @@ void main() { }, ); + group('ShareDisplay', () { + setUp(() async { + urlLauncher = _MockUrlLauncher(); + UrlLauncherPlatform.instance = urlLauncher; + }); + + flameTester.test( + 'adds ShareDisplay on ShareState', + (game) async { + final state = ShareState(score: 100); + whenListen( + bloc, + const Stream.empty(), + initialState: state, + ); + final backbox = Backbox.test( + bloc: bloc, + shareRepository: _MockShareRepository(), + platformHelper: platformHelper, + ); + await game.pump(backbox); + + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); + + flameTester.test( + 'opens Facebook link when sharing with Facebook', + (game) async { + when(() => urlLauncher.canLaunch(any())) + .thenAnswer((_) async => true); + when( + () => urlLauncher.launch( + any(), + useSafariVC: any(named: 'useSafariVC'), + useWebView: any(named: 'useWebView'), + enableJavaScript: any(named: 'enableJavaScript'), + enableDomStorage: any(named: 'enableDomStorage'), + universalLinksOnly: any(named: 'universalLinksOnly'), + headers: any(named: 'headers'), + ), + ).thenAnswer((_) async => true); + + final state = ShareState(score: 100); + whenListen( + bloc, + const Stream.empty(), + initialState: state, + ); + + final shareRepository = _MockShareRepository(); + const fakeUrl = 'http://fakeUrl'; + when( + () => shareRepository.shareText( + value: any(named: 'value'), + platform: SharePlatform.facebook, + ), + ).thenReturn(fakeUrl); + + final backbox = Backbox.test( + bloc: bloc, + shareRepository: shareRepository, + platformHelper: platformHelper, + ); + await game.pump(backbox); + + final facebookButton = + game.descendants().whereType().first; + facebookButton.onTapDown(_MockTapDownInfo()); + + await game.ready(); + + verify( + () => shareRepository.shareText( + value: any(named: 'value'), + platform: SharePlatform.facebook, + ), + ).called(1); + }, + ); + + flameTester.test( + 'opens Twitter link when sharing with Twitter', + (game) async { + final state = ShareState(score: 100); + whenListen( + bloc, + Stream.value(state), + initialState: state, + ); + + final shareRepository = _MockShareRepository(); + const fakeUrl = 'http://fakeUrl'; + when( + () => shareRepository.shareText( + value: any(named: 'value'), + platform: SharePlatform.twitter, + ), + ).thenReturn(fakeUrl); + when(() => urlLauncher.canLaunch(any())) + .thenAnswer((_) async => true); + when( + () => urlLauncher.launch( + any(), + useSafariVC: any(named: 'useSafariVC'), + useWebView: any(named: 'useWebView'), + enableJavaScript: any(named: 'enableJavaScript'), + enableDomStorage: any(named: 'enableDomStorage'), + universalLinksOnly: any(named: 'universalLinksOnly'), + headers: any(named: 'headers'), + ), + ).thenAnswer((_) async => true); + + final backbox = Backbox.test( + bloc: bloc, + shareRepository: shareRepository, + platformHelper: platformHelper, + ); + await game.pump(backbox); + + final facebookButton = + game.descendants().whereType().first; + facebookButton.onTapDown(_MockTapDownInfo()); + + await game.ready(); + + verify( + () => shareRepository.shareText( + value: any(named: 'value'), + platform: SharePlatform.twitter, + ), + ).called(1); + }, + ); + }); + flameTester.test( 'adds LeaderboardDisplay on LeaderboardSuccessState', (game) async { @@ -384,6 +584,7 @@ void main() { final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -406,6 +607,7 @@ void main() { final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -429,6 +631,7 @@ void main() { final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); @@ -469,6 +672,7 @@ void main() { final backbox = Backbox.test( bloc: bloc, + shareRepository: _MockShareRepository(), platformHelper: platformHelper, ); await game.pump(backbox); diff --git a/test/game/components/backbox/bloc/backbox_bloc_test.dart b/test/game/components/backbox/bloc/backbox_bloc_test.dart index aec46186..050307dc 100644 --- a/test/game/components/backbox/bloc/backbox_bloc_test.dart +++ b/test/game/components/backbox/bloc/backbox_bloc_test.dart @@ -137,6 +137,25 @@ void main() { ); }); + group('ShareScoreRequested', () { + blocTest( + 'emits ShareState', + setUp: () { + leaderboardRepository = _MockLeaderboardRepository(); + }, + build: () => BackboxBloc( + leaderboardRepository: leaderboardRepository, + initialEntries: emptyEntries, + ), + act: (bloc) => bloc.add( + ShareScoreRequested(score: 100), + ), + expect: () => [ + ShareState(score: 100), + ], + ); + }); + group('LeaderboardRequested', () { blocTest( 'adds [LoadingState, LeaderboardSuccessState] when request succeeds', diff --git a/test/game/components/backbox/bloc/backbox_state_test.dart b/test/game/components/backbox/bloc/backbox_state_test.dart index c41562b0..ba6d1c08 100644 --- a/test/game/components/backbox/bloc/backbox_state_test.dart +++ b/test/game/components/backbox/bloc/backbox_state_test.dart @@ -203,5 +203,23 @@ void main() { }); }); }); + + group('ShareState', () { + test('can be instantiated', () { + expect( + ShareState(score: 0), + isNotNull, + ); + }); + + test('supports value comparison', () { + expect( + ShareState(score: 0), + equals( + ShareState(score: 0), + ), + ); + }); + }); }); } diff --git a/test/game/components/backbox/displays/share_display_test.dart b/test/game/components/backbox/displays/share_display_test.dart new file mode 100644 index 00000000..1f882223 --- /dev/null +++ b/test/game/components/backbox/displays/share_display_test.dart @@ -0,0 +1,112 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame/game.dart'; +import 'package:flame/input.dart'; +import 'package:flame_bloc/flame_bloc.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball/game/bloc/game_bloc.dart'; +import 'package:pinball/game/components/backbox/displays/share_display.dart'; +import 'package:pinball/l10n/l10n.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_flame/pinball_flame.dart'; + +class _TestGame extends Forge2DGame with HasTappables { + @override + Future onLoad() async { + await super.onLoad(); + images.prefix = ''; + await images.loadAll( + [ + Assets.images.backbox.button.facebook.keyName, + Assets.images.backbox.button.twitter.keyName, + ], + ); + } + + Future pump(ShareDisplay component) { + return ensureAdd( + FlameBlocProvider.value( + value: GameBloc(), + children: [ + FlameProvider.value( + _MockAppLocalizations(), + children: [component], + ), + ], + ), + ); + } +} + +class _MockAppLocalizations extends Mock implements AppLocalizations { + @override + String get letEveryone => ''; + + @override + String get bySharingYourScore => ''; + + @override + String get socialMediaAccount => ''; +} + +class _MockTapDownInfo extends Mock implements TapDownInfo {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + final flameTester = FlameTester(_TestGame.new); + + group('ShareDisplay', () { + flameTester.test( + 'loads correctly', + (game) async { + final component = ShareDisplay(); + await game.pump(component); + expect(game.descendants(), contains(component)); + }, + ); + + flameTester.test( + 'calls onShare when Facebook button is tapped', + (game) async { + var tapped = false; + + final tapDownInfo = _MockTapDownInfo(); + final component = ShareDisplay( + onShare: (_) => tapped = true, + ); + await game.pump(component); + + final facebookButton = + component.descendants().whereType().first; + + facebookButton.onTapDown(tapDownInfo); + + expect(tapped, isTrue); + }, + ); + + flameTester.test( + 'calls onShare when Twitter button is tapped', + (game) async { + var tapped = false; + + final tapDownInfo = _MockTapDownInfo(); + final component = ShareDisplay( + onShare: (_) => tapped = true, + ); + await game.pump(component); + + final twitterButton = + component.descendants().whereType().first; + + twitterButton.onTapDown(tapDownInfo); + + expect(tapped, isTrue); + }, + ); + }); +} diff --git a/test/game/components/game_bloc_status_listener_test.dart b/test/game/components/game_bloc_status_listener_test.dart index 3151e70b..cc1729b8 100644 --- a/test/game/components/game_bloc_status_listener_test.dart +++ b/test/game/components/game_bloc_status_listener_test.dart @@ -14,6 +14,7 @@ import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_theme/pinball_theme.dart' as theme; +import 'package:share_repository/share_repository.dart'; class _TestGame extends Forge2DGame { @override @@ -65,6 +66,8 @@ class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { } +class _MockShareRepository extends Mock implements ShareRepository {} + class _MockAppLocalizations extends Mock implements AppLocalizations { @override String get score => ''; @@ -149,9 +152,11 @@ void main() { 'changes the backbox display', (game) async { final component = GameBlocStatusListener(); - final repository = _MockLeaderboardRepository(); + final leaderboardRepository = _MockLeaderboardRepository(); + final shareRepository = _MockShareRepository(); final backbox = Backbox( - leaderboardRepository: repository, + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, entries: const [], ); @@ -165,9 +170,11 @@ void main() { 'removes FlipperKeyControllingBehavior from Flipper', (game) async { final component = GameBlocStatusListener(); - final repository = _MockLeaderboardRepository(); + final leaderboardRepository = _MockLeaderboardRepository(); + final shareRepository = _MockShareRepository(); final backbox = Backbox( - leaderboardRepository: repository, + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, entries: const [], ); final flipper = Flipper.test(side: BoardSide.left); @@ -193,9 +200,11 @@ void main() { (game) async { final audioPlayer = _MockPinballAudioPlayer(); final component = GameBlocStatusListener(); - final repository = _MockLeaderboardRepository(); + final leaderboardRepository = _MockLeaderboardRepository(); + final shareRepository = _MockShareRepository(); final backbox = Backbox( - leaderboardRepository: repository, + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, entries: const [], ); await game.pump( @@ -245,9 +254,11 @@ void main() { 'adds key controlling behavior to Flippers when the game is started', (game) async { final component = GameBlocStatusListener(); - final repository = _MockLeaderboardRepository(); + final leaderboardRepository = _MockLeaderboardRepository(); + final shareRepository = _MockShareRepository(); final backbox = Backbox( - leaderboardRepository: repository, + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, entries: const [], ); final flipper = Flipper.test(side: BoardSide.left); diff --git a/test/game/components/golden/backbox.png b/test/game/components/golden/backbox.png index 962573ab..15426d4f 100644 Binary files a/test/game/components/golden/backbox.png and b/test/game/components/golden/backbox.png differ diff --git a/test/game/pinball_game_test.dart b/test/game/pinball_game_test.dart index d64333cc..19760f64 100644 --- a/test/game/pinball_game_test.dart +++ b/test/game/pinball_game_test.dart @@ -16,12 +16,14 @@ import 'package:pinball/game/game.dart'; import 'package:pinball/select_character/select_character.dart'; import 'package:pinball_audio/src/pinball_audio.dart'; import 'package:pinball_components/pinball_components.dart'; +import 'package:share_repository/share_repository.dart'; class _TestPinballGame extends PinballGame { _TestPinballGame() : super( characterThemeBloc: CharacterThemeCubit(), leaderboardRepository: _MockLeaderboardRepository(), + shareRepository: _MockShareRepository(), gameBloc: GameBloc(), l10n: _MockAppLocalizations(), audioPlayer: _MockPinballAudioPlayer(), @@ -41,6 +43,7 @@ class _TestDebugPinballGame extends DebugPinballGame { : super( characterThemeBloc: CharacterThemeCubit(), leaderboardRepository: _MockLeaderboardRepository(), + shareRepository: _MockShareRepository(), gameBloc: GameBloc(), l10n: _MockAppLocalizations(), audioPlayer: _MockPinballAudioPlayer(), @@ -81,6 +84,8 @@ class _MockDragEndInfo extends Mock implements DragEndInfo {} class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { } +class _MockShareRepository extends Mock implements ShareRepository {} + class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} void main() { diff --git a/test/game/view/pinball_game_page_test.dart b/test/game/view/pinball_game_page_test.dart index b2cde26e..fce6e74e 100644 --- a/test/game/view/pinball_game_page_test.dart +++ b/test/game/view/pinball_game_page_test.dart @@ -10,12 +10,12 @@ import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:mocktail/mocktail.dart'; import 'package:pinball/assets_manager/assets_manager.dart'; import 'package:pinball/game/game.dart'; -import 'package:pinball/gen/gen.dart'; import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/more_information/more_information.dart'; import 'package:pinball/select_character/select_character.dart'; import 'package:pinball/start_game/start_game.dart'; import 'package:pinball_audio/pinball_audio.dart'; +import 'package:share_repository/share_repository.dart'; import '../../helpers/helpers.dart'; @@ -24,6 +24,7 @@ class _TestPinballGame extends PinballGame { : super( characterThemeBloc: CharacterThemeCubit(), leaderboardRepository: _MockLeaderboardRepository(), + shareRepository: _MockShareRepository(), gameBloc: GameBloc(), l10n: _MockAppLocalizations(), audioPlayer: _MockPinballAudioPlayer(), @@ -60,6 +61,8 @@ class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { } +class _MockShareRepository extends Mock implements ShareRepository {} + void main() { final game = _TestPinballGame(); @@ -312,7 +315,7 @@ void main() { gameBloc: gameBloc, startGameBloc: startGameBloc, ); - expect(find.image(Assets.images.linkBox.infoIcon), findsOneWidget); + expect(find.byIcon(Icons.info), findsOneWidget); }); testWidgets('opens MoreInformationDialog when tapped', (tester) async { diff --git a/test/helpers/pump_app.dart b/test/helpers/pump_app.dart index 8be03f03..df75efae 100644 --- a/test/helpers/pump_app.dart +++ b/test/helpers/pump_app.dart @@ -12,12 +12,15 @@ import 'package:pinball/select_character/select_character.dart'; import 'package:pinball/start_game/start_game.dart'; import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_ui/pinball_ui.dart'; +import 'package:share_repository/share_repository.dart'; class _MockAssetsManagerCubit extends Mock implements AssetsManagerCubit {} class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { } +class _MockShareRepository extends Mock implements ShareRepository {} + class _MockCharacterThemeCubit extends Mock implements CharacterThemeCubit {} class _MockGameBloc extends Mock implements GameBloc {} @@ -55,6 +58,7 @@ extension PumpApp on WidgetTester { AssetsManagerCubit? assetsManagerCubit, CharacterThemeCubit? characterThemeCubit, LeaderboardRepository? leaderboardRepository, + ShareRepository? shareRepository, PinballAudioPlayer? pinballAudioPlayer, }) { return runAsync(() { @@ -64,6 +68,9 @@ extension PumpApp on WidgetTester { RepositoryProvider.value( value: leaderboardRepository ?? _MockLeaderboardRepository(), ), + RepositoryProvider.value( + value: shareRepository ?? _MockShareRepository(), + ), RepositoryProvider.value( value: pinballAudioPlayer ?? _buildDefaultPinballAudioPlayer(), ),