mirror of https://github.com/flutter/pinball.git
feat: adding assets manager (#163)
parent
d7216bbe6d
commit
5fe5fc007d
@ -0,0 +1,27 @@
|
|||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
part 'assets_manager_state.dart';
|
||||||
|
|
||||||
|
/// {@template assets_manager_cubit}
|
||||||
|
/// Cubit responsable for pre loading any game assets
|
||||||
|
/// {@endtemplate}
|
||||||
|
class AssetsManagerCubit extends Cubit<AssetsManagerState> {
|
||||||
|
/// {@macro assets_manager_cubit}
|
||||||
|
AssetsManagerCubit(List<Future> loadables)
|
||||||
|
: super(
|
||||||
|
AssetsManagerState.initial(
|
||||||
|
loadables: loadables,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Loads the assets
|
||||||
|
Future<void> load() async {
|
||||||
|
final all = state.loadables.map((loadable) async {
|
||||||
|
await loadable;
|
||||||
|
emit(state.copyWith(loaded: [...state.loaded, loadable]));
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
await Future.wait(all);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
part of 'assets_manager_cubit.dart';
|
||||||
|
|
||||||
|
/// {@template assets_manager_state}
|
||||||
|
/// State used to load the game assets
|
||||||
|
/// {@endtemplate}
|
||||||
|
class AssetsManagerState extends Equatable {
|
||||||
|
/// {@macro assets_manager_state}
|
||||||
|
const AssetsManagerState({
|
||||||
|
required this.loadables,
|
||||||
|
required this.loaded,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// {@macro assets_manager_state}
|
||||||
|
const AssetsManagerState.initial({
|
||||||
|
required List<Future> loadables,
|
||||||
|
}) : this(loadables: loadables, loaded: const []);
|
||||||
|
|
||||||
|
/// List of futures to load
|
||||||
|
final List<Future> loadables;
|
||||||
|
|
||||||
|
/// List of loaded futures
|
||||||
|
final List<Future> loaded;
|
||||||
|
|
||||||
|
/// Returns a value between 0 and 1 to indicate the loading progress
|
||||||
|
double get progress => loaded.length / loadables.length;
|
||||||
|
|
||||||
|
/// Returns a copy of this instance with the given parameters
|
||||||
|
/// updated
|
||||||
|
AssetsManagerState copyWith({
|
||||||
|
List<Future>? loadables,
|
||||||
|
List<Future>? loaded,
|
||||||
|
}) {
|
||||||
|
return AssetsManagerState(
|
||||||
|
loadables: loadables ?? this.loadables,
|
||||||
|
loaded: loaded ?? this.loaded,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [loaded, loadables];
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:bloc_test/bloc_test.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:pinball/game/game.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('AssetsManagerCubit', () {
|
||||||
|
final completer1 = Completer<void>();
|
||||||
|
final completer2 = Completer<void>();
|
||||||
|
|
||||||
|
final future1 = completer1.future;
|
||||||
|
final future2 = completer2.future;
|
||||||
|
|
||||||
|
blocTest<AssetsManagerCubit, AssetsManagerState>(
|
||||||
|
'emits the loaded on the order that they load',
|
||||||
|
build: () => AssetsManagerCubit([future1, future2]),
|
||||||
|
act: (cubit) {
|
||||||
|
cubit.load();
|
||||||
|
completer2.complete();
|
||||||
|
completer1.complete();
|
||||||
|
},
|
||||||
|
expect: () => [
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future1, future2],
|
||||||
|
loaded: [future2],
|
||||||
|
),
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future1, future2],
|
||||||
|
loaded: [future2, future1],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
// ignore_for_file: prefer_const_constructors
|
||||||
|
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:pinball/game/game.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('AssetsManagerState', () {
|
||||||
|
test('can be instantiated', () {
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(loadables: const [], loaded: const []),
|
||||||
|
isNotNull,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('has the correct initial state', () {
|
||||||
|
final future = Future<void>.value();
|
||||||
|
expect(
|
||||||
|
AssetsManagerState.initial(loadables: [future]),
|
||||||
|
equals(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future],
|
||||||
|
loaded: const [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('progress', () {
|
||||||
|
final future1 = Future<void>.value();
|
||||||
|
final future2 = Future<void>.value();
|
||||||
|
|
||||||
|
test('returns 0 when no future is loaded', () {
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future1, future2],
|
||||||
|
loaded: const [],
|
||||||
|
).progress,
|
||||||
|
equals(0),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns the correct value when some of the futures are loaded', () {
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future1, future2],
|
||||||
|
loaded: [future1],
|
||||||
|
).progress,
|
||||||
|
equals(0.5),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns the 1 when all futures are loaded', () {
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future1, future2],
|
||||||
|
loaded: [future1, future2],
|
||||||
|
).progress,
|
||||||
|
equals(1),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('copyWith', () {
|
||||||
|
final future = Future<void>.value();
|
||||||
|
|
||||||
|
test('returns a copy with the updated loadables', () {
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: const [],
|
||||||
|
loaded: const [],
|
||||||
|
).copyWith(loadables: [future]),
|
||||||
|
equals(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future],
|
||||||
|
loaded: const [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns a copy with the updated loaded', () {
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: const [],
|
||||||
|
loaded: const [],
|
||||||
|
).copyWith(loaded: [future]),
|
||||||
|
equals(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: const [],
|
||||||
|
loaded: [future],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('supports value comparison', () {
|
||||||
|
final future1 = Future<void>.value();
|
||||||
|
final future2 = Future<void>.value();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: const [],
|
||||||
|
loaded: const [],
|
||||||
|
),
|
||||||
|
equals(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: const [],
|
||||||
|
loaded: const [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future1],
|
||||||
|
loaded: const [],
|
||||||
|
),
|
||||||
|
isNot(
|
||||||
|
equals(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: [future2],
|
||||||
|
loaded: const [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: const [],
|
||||||
|
loaded: [future1],
|
||||||
|
),
|
||||||
|
isNot(
|
||||||
|
equals(
|
||||||
|
AssetsManagerState(
|
||||||
|
loadables: const [],
|
||||||
|
loaded: [future2],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in new issue