refactor: decrease theme cubit scope

pull/20/head
Allison Ryan 4 years ago
parent e6813e2ed6
commit 96af0f7fa7

@ -6,20 +6,16 @@
// https://opensource.org/licenses/MIT. // https://opensource.org/licenses/MIT.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/landing/landing.dart'; import 'package:pinball/landing/landing.dart';
import 'package:pinball/theme/theme.dart';
class App extends StatelessWidget { class App extends StatelessWidget {
const App({Key? key}) : super(key: key); const App({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return MaterialApp(
create: (_) => ThemeCubit(),
child: MaterialApp(
title: 'I/O Pinball', title: 'I/O Pinball',
theme: ThemeData( theme: ThemeData(
appBarTheme: const AppBarTheme(color: Color(0xFF13B9FF)), appBarTheme: const AppBarTheme(color: Color(0xFF13B9FF)),
@ -33,7 +29,6 @@ class App extends StatelessWidget {
], ],
supportedLocales: AppLocalizations.supportedLocales, supportedLocales: AppLocalizations.supportedLocales,
home: const LandingPage(), home: const LandingPage(),
),
); );
} }
} }

@ -1,7 +1,6 @@
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/theme/theme.dart';
class Ball extends PositionBodyComponent<PinballGame, SpriteComponent> { class Ball extends PositionBodyComponent<PinballGame, SpriteComponent> {
Ball({ Ball({
@ -19,13 +18,7 @@ class Ball extends PositionBodyComponent<PinballGame, SpriteComponent> {
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
final sprite = await gameRef.loadSprite(spritePath); final sprite = await gameRef.loadSprite(spritePath);
final tint = gameRef final tint = gameRef.theme.characterTheme.ballColor.withOpacity(0.5);
.read<ThemeCubit>()
.state
.theme
.characterTheme
.ballColor
.withOpacity(0.5);
positionComponent = SpriteComponent(sprite: sprite, size: ballSize) positionComponent = SpriteComponent(sprite: sprite, size: ballSize)
..tint(tint); ..tint(tint);
} }

@ -3,8 +3,20 @@ import 'dart:async';
import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball_theme/pinball_theme.dart';
class PinballGame extends Forge2DGame with FlameBloc { class PinballGame extends Forge2DGame with FlameBloc {
PinballGame({required this.theme});
PinballGame.initial()
: this(
theme: const PinballTheme(
characterTheme: DashTheme(),
),
);
final PinballTheme theme;
void spawnBall() { void spawnBall() {
add( add(
Ball(position: ballStartingPosition), Ball(position: ballStartingPosition),

@ -2,16 +2,19 @@ import 'package:flame/game.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball_theme/pinball_theme.dart';
class PinballGamePage extends StatelessWidget { class PinballGamePage extends StatelessWidget {
const PinballGamePage({Key? key}) : super(key: key); const PinballGamePage({Key? key, required this.theme}) : super(key: key);
static Route route() { final PinballTheme theme;
static Route route({required PinballTheme theme}) {
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
builder: (_) { builder: (_) {
return BlocProvider( return BlocProvider(
create: (_) => GameBloc(), create: (_) => GameBloc(),
child: const PinballGamePage(), child: PinballGamePage(theme: theme),
); );
}, },
); );
@ -19,12 +22,14 @@ class PinballGamePage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const PinballGameView(); return PinballGameView(theme: theme);
} }
} }
class PinballGameView extends StatefulWidget { class PinballGameView extends StatefulWidget {
const PinballGameView({Key? key}) : super(key: key); const PinballGameView({Key? key, required this.theme}) : super(key: key);
final PinballTheme theme;
@override @override
State<PinballGameView> createState() => _PinballGameViewState(); State<PinballGameView> createState() => _PinballGameViewState();
@ -40,7 +45,7 @@ class _PinballGameViewState extends State<PinballGameView> {
// TODO(erickzanardo): Revisit this when we start to have more assets // TODO(erickzanardo): Revisit this when we start to have more assets
// this could expose a Stream (maybe even a cubit?) so we could show the // this could expose a Stream (maybe even a cubit?) so we could show the
// the loading progress with some fancy widgets. // the loading progress with some fancy widgets.
_game = PinballGame()..preLoadAssets(); _game = PinballGame(theme: widget.theme)..preLoadAssets();
} }
@override @override

@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/theme/theme.dart'; import 'package:pinball/theme/theme.dart';
import 'package:pinball_theme/pinball_theme.dart'; import 'package:pinball_theme/pinball_theme.dart';
import 'package:provider/provider.dart';
class CharacterSelectionPage extends StatelessWidget { class CharacterSelectionPage extends StatelessWidget {
const CharacterSelectionPage({Key? key}) : super(key: key); const CharacterSelectionPage({Key? key}) : super(key: key);
@ -16,7 +16,10 @@ class CharacterSelectionPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const CharacterSelectionView(); return BlocProvider(
create: (_) => ThemeCubit(),
child: const CharacterSelectionView(),
);
} }
} }
@ -42,7 +45,9 @@ class CharacterSelectionView extends StatelessWidget {
const SizedBox(height: 20), const SizedBox(height: 20),
TextButton( TextButton(
onPressed: () => Navigator.of(context).push<void>( onPressed: () => Navigator.of(context).push<void>(
PinballGamePage.route(), PinballGamePage.route(
theme: context.read<ThemeCubit>().state.theme,
),
), ),
child: Text(l10n.start), child: Text(l10n.start),
), ),

@ -9,7 +9,7 @@ void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
group('Anchor', () { group('Anchor', () {
final flameTester = FlameTester(PinballGame.new); final flameTester = FlameTester(PinballGame.initial);
flameTester.test( flameTester.test(
'loads correctly', 'loads correctly',

@ -6,7 +6,6 @@ import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart'; import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/theme/cubit/theme_cubit.dart';
import '../../helpers/helpers.dart'; import '../../helpers/helpers.dart';
@ -15,7 +14,6 @@ void main() {
group('Ball', () { group('Ball', () {
final gameBloc = MockGameBloc(); final gameBloc = MockGameBloc();
final themeCubit = MockThemeCubit();
setUp(() { setUp(() {
whenListen( whenListen(
@ -23,21 +21,13 @@ void main() {
const Stream<GameState>.empty(), const Stream<GameState>.empty(),
initialState: const GameState.initial(), initialState: const GameState.initial(),
); );
whenListen(
themeCubit,
const Stream<ThemeState>.empty(),
initialState: const ThemeState.initial(),
);
}); });
final tester = flameBlocTester( final tester = flameBlocTester(gameBloc: gameBloc);
gameBloc: gameBloc,
themeCubit: themeCubit,
);
tester.widgetTest( tester.test(
'loads correctly', 'loads correctly',
(game, tester) async { (game) async {
final ball = Ball(position: Vector2.zero()); final ball = Ball(position: Vector2.zero());
await game.ensureAdd(ball); await game.ensureAdd(ball);
@ -46,9 +36,9 @@ void main() {
); );
group('body', () { group('body', () {
tester.widgetTest( tester.test(
'positions correctly', 'positions correctly',
(game, tester) async { (game) async {
final position = Vector2.all(10); final position = Vector2.all(10);
final ball = Ball(position: position); final ball = Ball(position: position);
await game.ensureAdd(ball); await game.ensureAdd(ball);
@ -58,9 +48,9 @@ void main() {
}, },
); );
tester.widgetTest( tester.test(
'is dynamic', 'is dynamic',
(game, tester) async { (game) async {
final ball = Ball(position: Vector2.zero()); final ball = Ball(position: Vector2.zero());
await game.ensureAdd(ball); await game.ensureAdd(ball);
@ -70,9 +60,9 @@ void main() {
}); });
group('first fixture', () { group('first fixture', () {
tester.widgetTest( tester.test(
'exists', 'exists',
(game, tester) async { (game) async {
final ball = Ball(position: Vector2.zero()); final ball = Ball(position: Vector2.zero());
await game.ensureAdd(ball); await game.ensureAdd(ball);
@ -80,9 +70,9 @@ void main() {
}, },
); );
tester.widgetTest( tester.test(
'is dense', 'is dense',
(game, tester) async { (game) async {
final ball = Ball(position: Vector2.zero()); final ball = Ball(position: Vector2.zero());
await game.ensureAdd(ball); await game.ensureAdd(ball);
@ -91,9 +81,9 @@ void main() {
}, },
); );
tester.widgetTest( tester.test(
'shape is circular', 'shape is circular',
(game, tester) async { (game) async {
final ball = Ball(position: Vector2.zero()); final ball = Ball(position: Vector2.zero());
await game.ensureAdd(ball); await game.ensureAdd(ball);

@ -5,13 +5,12 @@ import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart'; import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/theme/theme.dart';
import '../../helpers/helpers.dart'; import '../../helpers/helpers.dart';
void main() { void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(PinballGame.new); final flameTester = FlameTester(PinballGame.initial);
group('Plunger', () { group('Plunger', () {
flameTester.test( flameTester.test(
@ -131,7 +130,6 @@ void main() {
late Anchor anchor; late Anchor anchor;
final gameBloc = MockGameBloc(); final gameBloc = MockGameBloc();
final themeCubit = MockThemeCubit();
setUp(() { setUp(() {
plunger = Plunger(position: Vector2.zero()); plunger = Plunger(position: Vector2.zero());
@ -141,17 +139,9 @@ void main() {
const Stream<GameState>.empty(), const Stream<GameState>.empty(),
initialState: const GameState.initial(), initialState: const GameState.initial(),
); );
whenListen(
themeCubit,
const Stream<ThemeState>.empty(),
initialState: const ThemeState.initial(),
);
}); });
final flameTester = flameBlocTester( final flameTester = flameBlocTester(gameBloc: gameBloc);
gameBloc: gameBloc,
themeCubit: themeCubit,
);
flameTester.test( flameTester.test(
'throws AssertionError ' 'throws AssertionError '

@ -32,7 +32,7 @@ void main() {
}, },
); );
}); });
final flameTester = FlameTester(PinballGame.new); final flameTester = FlameTester(PinballGame.initial);
flameTester.test( flameTester.test(
'loads correctly', 'loads correctly',

@ -1,4 +1,8 @@
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:pinball/game/game.dart';
import '../helpers/helpers.dart';
void main() { void main() {
group('PinballGame', () { group('PinballGame', () {
@ -6,4 +10,23 @@ void main() {
// [BallScorePointsCallback] once the following issue is resolved: // [BallScorePointsCallback] once the following issue is resolved:
// https://github.com/flame-engine/flame/issues/1416 // https://github.com/flame-engine/flame/issues/1416
}); });
group('PinballGame.initial', () {
final gameBloc = MockGameBloc();
setUp(() {
whenListen(
gameBloc,
const Stream<GameState>.empty(),
initialState: const GameState.initial(),
);
});
flameBlocTester(gameBloc: gameBloc).test(
'has initial theme',
(game) async {
expect(game.theme, PinballGame.initial().theme);
},
);
});
} }

@ -4,10 +4,13 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/theme/theme.dart'; import 'package:pinball/theme/theme.dart';
import 'package:pinball_theme/pinball_theme.dart';
import '../../helpers/helpers.dart'; import '../../helpers/helpers.dart';
void main() { void main() {
const theme = PinballTheme(characterTheme: DashTheme());
group('PinballGamePage', () { group('PinballGamePage', () {
testWidgets('renders PinballGameView', (tester) async { testWidgets('renders PinballGameView', (tester) async {
final gameBloc = MockGameBloc(); final gameBloc = MockGameBloc();
@ -17,7 +20,10 @@ void main() {
initialState: const GameState.initial(), initialState: const GameState.initial(),
); );
await tester.pumpApp(const PinballGamePage(), gameBloc: gameBloc); await tester.pumpApp(
const PinballGamePage(theme: theme),
gameBloc: gameBloc,
);
expect(find.byType(PinballGameView), findsOneWidget); expect(find.byType(PinballGameView), findsOneWidget);
}); });
@ -35,7 +41,8 @@ void main() {
builder: (context) { builder: (context) {
return ElevatedButton( return ElevatedButton(
onPressed: () { onPressed: () {
Navigator.of(context).push<void>(PinballGamePage.route()); Navigator.of(context)
.push<void>(PinballGamePage.route(theme: theme));
}, },
child: const Text('Tap me'), child: const Text('Tap me'),
); );
@ -65,7 +72,10 @@ void main() {
initialState: const GameState.initial(), initialState: const GameState.initial(),
); );
await tester.pumpApp(const PinballGameView(), gameBloc: gameBloc); await tester.pumpApp(
const PinballGameView(theme: theme),
gameBloc: gameBloc,
);
expect( expect(
find.byWidgetPredicate((w) => w is GameWidget<PinballGame>), find.byWidgetPredicate((w) => w is GameWidget<PinballGame>),
findsOneWidget, findsOneWidget,
@ -91,7 +101,7 @@ void main() {
); );
await tester.pumpApp( await tester.pumpApp(
const PinballGameView(), const PinballGameView(theme: theme),
gameBloc: gameBloc, gameBloc: gameBloc,
themeCubit: themeCubit, themeCubit: themeCubit,
); );

@ -1,27 +1,16 @@
import 'package:flame_test/flame_test.dart'; import 'package:flame_test/flame_test.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/theme/theme.dart';
import 'mocks.dart';
FlameTester<PinballGame> flameBlocTester({ FlameTester<PinballGame> flameBlocTester({
GameBloc? gameBloc, required GameBloc gameBloc,
ThemeCubit? themeCubit,
}) { }) {
return FlameTester<PinballGame>( return FlameTester<PinballGame>(
PinballGame.new, PinballGame.initial,
pumpWidget: (gameWidget, tester) async { pumpWidget: (gameWidget, tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MultiBlocProvider(
providers: [
BlocProvider.value(
value: gameBloc ?? MockGameBloc(),
),
BlocProvider.value( BlocProvider.value(
value: themeCubit ?? MockThemeCubit(), value: gameBloc,
),
],
child: gameWidget, child: gameWidget,
), ),
); );

Loading…
Cancel
Save