Skip to content

Commit

Permalink
1.6.1 - Feature/different type of games (#109)
Browse files Browse the repository at this point in the history
* separating main games from expansions in the collection list

* adding total main and expansion games

* updating styles of the search results

* creating games view model and moving logic to it from the board games store

* grouping expansions on the collect screen

* fixing duplicate players created when importing plays from bgg again

* adding a TODO
  • Loading branch information
mkieres authored Jul 13, 2022
1 parent 3e8d3f5 commit 980c39c
Show file tree
Hide file tree
Showing 20 changed files with 444 additions and 351 deletions.
10 changes: 10 additions & 0 deletions board_games_companion/lib/app.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:board_games_companion/pages/games/games_view_model.dart';
import 'package:firebase_analytics/observer.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
Expand All @@ -23,6 +24,7 @@ import 'services/analytics_service.dart';
import 'services/board_games_geek_service.dart';
import 'services/preferences_service.dart';
import 'services/rate_and_review_service.dart';
import 'stores/board_games_filters_store.dart';
import 'stores/board_games_store.dart';
import 'stores/playthroughs_store.dart';
import 'utilities/analytics_route_observer.dart';
Expand Down Expand Up @@ -59,10 +61,18 @@ class _BoardGamesCompanionAppState extends State<BoardGamesCompanionApp> {
final analyticsService = getIt<AnalyticsService>();
final rateAndReviewService = getIt<RateAndReviewService>();
final playersViewModel = getIt<PlayersViewModel>();
final _boardGamesFiltersStore = getIt<BoardGamesFiltersStore>();

final _boardGamesStore = Provider.of<BoardGamesStore>(
context,
listen: false,
);
final gamesViewModel = GamesViewModel(_boardGamesStore, _boardGamesFiltersStore);

return HomePage(
analyticsService: analyticsService,
rateAndReviewService: rateAndReviewService,
gamesViewModel: gamesViewModel,
playersViewModel: playersViewModel,
);
},
Expand Down
4 changes: 4 additions & 0 deletions board_games_companion/lib/common/app_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class AppText {
static const searchBoardGamesPageHotBoardGamesErrorPartOne =
'''Sorry, we couldn't retrieve hot board games at this time. Please check your Internet connectivity and try again.''';
static const searchBoardGamesPageHotBoardGamesErrorRetryButtonText = 'Retry';
static const hotBoardGamesSliverSectionTitle = 'Hot Board Games';

static const gamesPageMainGamesSliverSectionTitleFormat = 'Main Games (%s)';
static const gamesPageExpansionsSliverSectionTitleFormat = '%s Expansions (%s)';

static const playtimeDurationHoursFormat = '%ih %imin';
static const playtimeDurationDaysFormat = '%i day%s %ih';
Expand Down
25 changes: 14 additions & 11 deletions board_games_companion/lib/injectable.config.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 21 additions & 17 deletions board_games_companion/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';

import 'package:board_games_companion/pages/games/games_view_model.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/foundation.dart';
Expand Down Expand Up @@ -29,7 +30,6 @@ import 'models/hive/user.dart';
import 'models/sort_by.dart';
import 'pages/players/players_view_model.dart';
import 'services/analytics_service.dart';
import 'services/board_games_filters_service.dart';
import 'services/board_games_geek_service.dart';
import 'services/board_games_service.dart';
import 'services/player_service.dart';
Expand Down Expand Up @@ -148,33 +148,20 @@ class App extends StatelessWidget {
create: (context) => getIt<PlaythroughsStore>(),
),
ChangeNotifierProvider<BoardGamesFiltersStore>(
create: (context) {
final BoardGamesFiltersService boardGamesFiltersService =
getIt<BoardGamesFiltersService>();
final AnalyticsService analyticsService = getIt<AnalyticsService>();
return BoardGamesFiltersStore(boardGamesFiltersService, analyticsService);
},
create: (context) => getIt<BoardGamesFiltersStore>(),
),
ChangeNotifierProxyProvider<BoardGamesFiltersStore, BoardGamesStore>(
ChangeNotifierProvider<BoardGamesStore>(
create: (context) {
final BoardGamesService boardGamesService = getIt<BoardGamesService>();
final PlaythroughService playthroughService = getIt<PlaythroughService>();
final ScoreService scoreService = getIt<ScoreService>();
final PlayerService playerService = getIt<PlayerService>();
final boardGamesStore = BoardGamesStore(
return BoardGamesStore(
boardGamesService,
playthroughService,
scoreService,
playerService,
Provider.of<BoardGamesFiltersStore>(context, listen: false),
);

boardGamesStore.loadBoardGames();
return boardGamesStore;
},
update: (_, filtersStore, boardGamesStore) {
boardGamesStore!.applyFilters();
return boardGamesStore;
},
),
ChangeNotifierProxyProvider2<BoardGamesStore, PlaythroughsStore,
Expand All @@ -184,6 +171,23 @@ class App extends StatelessWidget {
return playthroughStatisticsStore!;
},
),
ChangeNotifierProxyProvider2<BoardGamesFiltersStore, BoardGamesStore, GamesViewModel>(
create: (context) {
final boardGamesFiltersStore = getIt<BoardGamesFiltersStore>();
final boardGamesStore = Provider.of<BoardGamesStore>(
context,
listen: false,
);
final gamesViewModel = GamesViewModel(boardGamesStore, boardGamesFiltersStore);
gamesViewModel.loadBoardGames();

return gamesViewModel;
},
update: (_, filtersStore, boardGamesStore, gamesViewModel) {
gamesViewModel!.applyFilters();
return gamesViewModel;
},
),
],
child: const BoardGamesCompanionApp(),
);
Expand Down
2 changes: 2 additions & 0 deletions board_games_companion/lib/mixins/import_collection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ mixin ImportCollection {
}

void _showSuccessSnackBar(BuildContext context) {
// TODO MK Consider using a "global context" to show a snackbar in case a user switches between pages
// https://stackoverflow.com/a/65607336/510627
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
margin: Dimensions.snackbarMargin,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import '../../common/enums/collection_type.dart';
import '../../common/styles.dart';
import '../../models/hive/board_game_details.dart';
import '../../services/preferences_service.dart';
import '../../stores/board_game_details_in_collection_store.dart';
import '../../stores/board_games_store.dart';
import '../../utilities/launcher_helper.dart';
import '../../widgets/board_games/board_game_image.dart';
Expand Down Expand Up @@ -66,7 +65,7 @@ class _BoardGamesDetailsPageState extends BasePageState<BoardGamesDetailsPage> {
child: CustomScrollView(
slivers: <Widget>[
_Header(
boardGameDetailsStore: widget.boardGameDetailsStore,
viewModel: widget.boardGameDetailsStore,
boardGameName: widget.boardGameName,
),
SliverPadding(
Expand All @@ -93,12 +92,8 @@ class _BoardGamesDetailsPageState extends BasePageState<BoardGamesDetailsPage> {
context,
listen: false,
);
final boardGameDetailsInCollectionStore = BoardGameDetailsInCollectionStore(
boardGamesStore,
widget.boardGameDetailsStore.boardGameDetails,
);

if (!boardGameDetailsInCollectionStore.isInCollection &&
if (!boardGamesStore.isInAnyCollection(widget.boardGameDetailsStore.boardGameDetails?.id) &&
widget.navigatingFromType == PlaythroughsPage) {
Navigator.popUntil(context, ModalRoute.withName(HomePage.pageRoute));
return false;
Expand All @@ -111,14 +106,14 @@ class _BoardGamesDetailsPageState extends BasePageState<BoardGamesDetailsPage> {
class _Header extends StatelessWidget {
const _Header({
Key? key,
required BoardGameDetailsViewModel boardGameDetailsStore,
required BoardGameDetailsViewModel viewModel,
required String boardGameName,
}) : _boardGameDetailsStore = boardGameDetailsStore,
}) : _viewModel = viewModel,
_boardGameName = boardGameName,
super(key: key);

final String _boardGameName;
final BoardGameDetailsViewModel _boardGameDetailsStore;
final BoardGameDetailsViewModel _viewModel;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -152,12 +147,12 @@ class _Header extends StatelessWidget {
),
),
background: ChangeNotifierProvider<BoardGameDetailsViewModel>.value(
value: _boardGameDetailsStore,
value: _viewModel,
child: Consumer<BoardGameDetailsViewModel>(
builder: (_, store, __) {
// TODO Add shadow to the image
return BoardGameImage(
_boardGameDetailsStore.boardGameDetails,
_viewModel.boardGameDetails,
minImageHeight: Constants.BoardGameDetailsImageHeight,
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class BoardGameDetailsViewModel with ChangeNotifier {
return _boardGameDetails!;
}
for (final boardGameExpansion in boardGameDetails.expansions) {
final boardGameExpansionDetails = _boardGamesStore.allboardGames.firstWhereOrNull(
final boardGameExpansionDetails = _boardGamesStore.allBoardGames.firstWhereOrNull(
(boardGame) => boardGame.id == boardGameExpansion.id,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,21 +479,15 @@ class _ActionButtons extends StatelessWidget {
if (!viewModel.playthoughEnded) ...[
ElevatedIconButton(
title: AppText.stop,
icon: const DefaultIcon(
Icons.stop,
),
icon: const DefaultIcon(Icons.stop),
color: AppTheme.blueColor,
onPressed: onStop,
),
const SizedBox(
width: Dimensions.standardSpacing,
),
const SizedBox(width: Dimensions.standardSpacing),
],
ElevatedIconButton(
title: 'Save',
icon: const DefaultIcon(
Icons.save,
),
icon: const DefaultIcon(Icons.save),
color: AppTheme.accentColor,
onPressed: onSave,
),
Expand Down
6 changes: 3 additions & 3 deletions board_games_companion/lib/pages/games/games_filter_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class _Filters extends StatelessWidget {
alignment: Alignment.centerLeft,
child: Text('Number of players', style: AppTheme.sectionHeaderTextStyle),
),
if (boardGamesStore.allboardGames.isNotEmpty)
if (boardGamesStore.allBoardGames.isNotEmpty)
_FilterNumberOfPlayersSlider(
boardGamesFiltersStore: boardGamesFiltersStore,
boardGamesStore: boardGamesStore,
Expand Down Expand Up @@ -270,13 +270,13 @@ class _FilterNumberOfPlayersSlider extends StatelessWidget {
@override
Widget build(BuildContext context) {
final minNumberOfPlayers = max(
boardGamesStore.allboardGames
boardGamesStore.allBoardGames
.where((boardGameDetails) => boardGameDetails.minPlayers != null)
.map((boardGameDetails) => boardGameDetails.minPlayers!)
.reduce(min),
Constants.minNumberOfPlayers);
final maxNumberOfPlayers = min(
boardGamesStore.allboardGames
boardGamesStore.allBoardGames
.where((boardGameDetails) => boardGameDetails.maxPlayers != null)
.map((boardGameDetails) => boardGameDetails.maxPlayers!)
.reduce(max),
Expand Down
Loading

0 comments on commit 980c39c

Please sign in to comment.