feat: share screen and tests

pull/406/head
RuiAlonso 3 years ago
parent ca1f0c31da
commit c69ef9a5ba

@ -2,3 +2,4 @@ export 'initials_input_display.dart';
export 'initials_submission_failure_display.dart';
export 'initials_submission_success_display.dart';
export 'loading_display.dart';
export '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 used tries to share the 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 to share score on 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<void> onLoad() async {
await super.onLoad();
text = readProvider<AppLocalizations>().letEveryone;
}
}
class _SharingYourScoreTextComponent extends TextComponent with HasGameRef {
_SharingYourScoreTextComponent()
: super(
anchor: Anchor.center,
position: Vector2(0, 2.5),
textRenderer: _descriptionTextPaint,
);
@override
Future<void> onLoad() async {
await super.onLoad();
text = readProvider<AppLocalizations>().bySharingYourScore;
}
}
class _SocialMediaTextComponent extends TextComponent with HasGameRef {
_SocialMediaTextComponent()
: super(
anchor: Anchor.center,
position: Vector2(0, 5),
textRenderer: _descriptionTextPaint,
);
@override
Future<void> onLoad() async {
await super.onLoad();
text = readProvider<AppLocalizations>().socialMediaAccount;
}
}
class _SocialNetworksComponent extends PositionComponent with HasGameRef {
_SocialNetworksComponent({
OnSocialShareTap? onShare,
}) : super(
anchor: Anchor.center,
position: Vector2(0, 10),
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<void> 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<void> onLoad() async {
await super.onLoad();
final sprite = Sprite(
gameRef.images.fromCache(Assets.images.backbox.button.twitter.keyName),
);
this.sprite = sprite;
size = sprite.originalSize / 25;
}
}

@ -100,6 +100,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.googleWord.letter1.lit.keyName),
images.load(components.Assets.images.googleWord.letter1.dimmed.keyName),
images.load(components.Assets.images.googleWord.letter2.lit.keyName),

@ -17,7 +17,7 @@ import 'package:pinball_flame/pinball_flame.dart';
import 'package:pinball_theme/pinball_theme.dart';
class PinballGame extends PinballForge2DGame
with HasKeyboardHandlerComponents, MultiTouchTapDetector {
with HasKeyboardHandlerComponents, MultiTouchTapDetector, HasTappables {
PinballGame({
required CharacterTheme characterTheme,
required this.leaderboardRepository,

@ -128,4 +128,17 @@
"@ioPinball": {
"description": "I/O Pinball - Name of the game"
}
,
"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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

@ -54,6 +54,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');
@ -66,9 +69,6 @@ class $AssetsImagesBackboxGen {
class $AssetsImagesBallGen {
const $AssetsImagesBallGen();
/// File path: assets/images/ball/ball.png
AssetGenImage get ball => const AssetGenImage('assets/images/ball/ball.png');
/// File path: assets/images/ball/flame_effect.png
AssetGenImage get flameEffect =>
const AssetGenImage('assets/images/ball/flame_effect.png');
@ -380,6 +380,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();

@ -88,6 +88,7 @@ flutter:
- assets/images/multiplier/x6/
- assets/images/score/
- assets/images/backbox/
- assets/images/backbox/button/
- assets/images/flapper/
- assets/images/skill_shot/

@ -291,6 +291,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.4"
share_repository:
dependency: transitive
description:
path: "../../share_repository"
relative: true
source: path
version: "1.0.0+1"
shared_preferences:
dependency: transitive
description:

@ -576,6 +576,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
share_repository:
dependency: "direct main"
description:
path: "packages/share_repository"
relative: true
source: path
version: "1.0.0+1"
shelf:
dependency: transitive
description:

@ -43,6 +43,8 @@ dependencies:
path: packages/pinball_ui
platform_helper:
path: packages/platform_helper
share_repository:
path: packages/share_repository
dev_dependencies:
bloc_test: ^9.0.2

@ -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<void> onLoad() async {
await super.onLoad();
images.prefix = '';
await images.loadAll(
[
Assets.images.backbox.button.facebook.keyName,
Assets.images.backbox.button.twitter.keyName,
],
);
}
Future<void> pump(ShareDisplay component) {
return ensureAdd(
FlameBlocProvider<GameBloc, GameState>.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 tap on Facebook button',
(game) async {
var tapped = false;
final tapDownInfo = _MockTapDownInfo();
final component = ShareDisplay(
onShare: (_) => tapped = true,
);
await game.pump(component);
final facebookButton =
component.descendants().whereType<FacebookButtonComponent>().first;
facebookButton.onTapDown(tapDownInfo);
expect(tapped, isTrue);
},
);
flameTester.test(
'calls onShare when tap on Twitter button',
(game) async {
var tapped = false;
final tapDownInfo = _MockTapDownInfo();
final component = ShareDisplay(
onShare: (_) => tapped = true,
);
await game.pump(component);
final twitterButton =
component.descendants().whereType<TwitterButtonComponent>().first;
twitterButton.onTapDown(tapDownInfo);
expect(tapped, isTrue);
},
);
});
}
Loading…
Cancel
Save