Skip to content
Snippets Groups Projects
Commit 4b944918 authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Merge branch '14-clean-update-code' into 'master'

Resolve "Clean/update code"

Closes #14

See merge request !14
parents 859227b6 6c20de9d
No related branches found
No related tags found
1 merge request!14Resolve "Clean/update code"
Pipeline #5660 passed
Showing
with 341 additions and 50 deletions
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=0.0.25
app.versionCode=25
app.versionName=0.0.26
app.versionCode=26
{
"app_name": "SortGame"
"app_name": "SortGame",
"bottom_nav_home": "Game",
"bottom_nav_settings": "Settings",
"bottom_nav_about": "About",
"settings_title": "Settings",
"settings_label_theme": "Theme mode",
"about_title": "About",
"about_content": "Sort game, simple and classic.",
"about_version": "Version: {version}"
}
{
"app_name": "SortGame"
"app_name": "SortGame",
"bottom_nav_home": "Jeu",
"bottom_nav_settings": "Réglages",
"bottom_nav_about": "Infos",
"settings_title": "Réglages",
"settings_label_theme": "Thème de couleurs",
"about_title": "Informations",
"about_content": "Jeu de tri.",
"about_version": "Version : {version}"
}
Clean/update some code. Add dark/light theme selector page. Add "about" page.
Nettoyage/mise à jour de code. Ajout de page de thème clair/sombre. Ajout de page "informations".
......@@ -2,23 +2,27 @@ import 'package:sortgame/data/fetch_data_helper.dart';
import 'package:sortgame/utils/tools.dart';
class DefaultGameSettings {
// available game parameters codes
static const String parameterCodeItemsCount = 'itemsCount';
static const String parameterCodeThemeIndex = 'theme';
static const List<String> availableParameters = [
'itemsCount',
'theme',
parameterCodeItemsCount,
parameterCodeThemeIndex,
];
// items count: available values
static const int itemsCountValueLow = 5;
static const int itemsCountValueMedium = 10;
static const int itemsCountValueHigh = 15;
static const int itemsCountValueVeryHigh = 20;
static const int defaultItemsCountValue = itemsCountValueMedium;
static const List<int> allowedItemsCountValues = [
itemsCountValueLow,
itemsCountValueMedium,
itemsCountValueHigh,
itemsCountValueVeryHigh,
];
// items count: default value
static const int defaultItemsCountValue = itemsCountValueMedium;
static const int defaultThemeValue = 0;
......@@ -26,9 +30,6 @@ class DefaultGameSettings {
switch (parameterCode) {
case 'itemsCount':
return DefaultGameSettings.allowedItemsCountValues;
}
switch (parameterCode) {
case 'theme':
final int count = FetchDataHelper().getThemes().length;
return List<int>.generate(count, (i) => i);
......
import 'package:flutter/material.dart';
import 'package:unicons/unicons.dart';
import 'package:sortgame/ui/screens/page_about.dart';
import 'package:sortgame/ui/screens/page_game.dart';
import 'package:sortgame/ui/screens/page_settings.dart';
class MenuItem {
final String code;
final Icon icon;
final Widget page;
const MenuItem({
required this.code,
required this.icon,
required this.page,
});
}
class Menu {
static const indexGame = 0;
static const menuItemGame = MenuItem(
code: 'bottom_nav_game',
icon: Icon(UniconsLine.home),
page: PageGame(),
);
static const indexSettings = 1;
static const menuItemSettings = MenuItem(
code: 'bottom_nav_settings',
icon: Icon(UniconsLine.setting),
page: PageSettings(),
);
static const indexAbout = 2;
static const menuItemAbout = MenuItem(
code: 'bottom_nav_about',
icon: Icon(UniconsLine.info_circle),
page: PageAbout(),
);
static Map<int, MenuItem> items = {
indexGame: menuItemGame,
indexSettings: menuItemSettings,
indexAbout: menuItemAbout,
};
static bool isIndexAllowed(int pageIndex) {
return items.keys.contains(pageIndex);
}
static Widget getPageWidget(int pageIndex) {
return items[pageIndex]?.page ?? menuItemGame.page;
}
static int itemsCount = Menu.items.length;
}
......@@ -34,6 +34,21 @@ class GameCubit extends HydratedCubit<GameState> {
updateState(game);
}
void startNewGame({
required GameSettings gameSettings,
required GlobalSettings globalSettings,
}) {
Game newGame = Game.createNew(
gameSettings: gameSettings,
globalSettings: globalSettings,
);
newGame.dump();
updateState(newGame);
refresh();
}
void quitGame() {
state.currentGame.updateGameIsRunning(false);
refresh();
......@@ -53,21 +68,6 @@ class GameCubit extends HydratedCubit<GameState> {
refresh();
}
void startNewGame({
required GameSettings gameSettings,
required GlobalSettings globalSettings,
}) {
Game newGame = Game.createNew(
gameSettings: gameSettings,
globalSettings: globalSettings,
);
newGame.dump();
updateState(newGame);
refresh();
}
@override
GameState? fromJson(Map<String, dynamic> json) {
Game currentGame = json['currentGame'] as Game;
......
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:sortgame/config/menu.dart';
class NavCubit extends HydratedCubit<int> {
NavCubit() : super(0);
void updateIndex(int index) {
if (Menu.isIndexAllowed(index)) {
emit(index);
} else {
goToGamePage();
}
}
void goToGamePage() {
emit(Menu.indexGame);
}
void goToSettingsPage() {
emit(Menu.indexSettings);
}
void goToAboutPage() {
emit(Menu.indexAbout);
}
@override
int fromJson(Map<String, dynamic> json) {
return Menu.indexGame;
}
@override
Map<String, dynamic>? toJson(int state) {
return <String, int>{'pageIndex': state};
}
}
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
part 'theme_state.dart';
class ThemeCubit extends HydratedCubit<ThemeModeState> {
ThemeCubit() : super(const ThemeModeState());
void getTheme(ThemeModeState state) {
emit(state);
}
@override
ThemeModeState? fromJson(Map<String, dynamic> json) {
switch (json['themeMode']) {
case 'ThemeMode.dark':
return const ThemeModeState(themeMode: ThemeMode.dark);
case 'ThemeMode.light':
return const ThemeModeState(themeMode: ThemeMode.light);
case 'ThemeMode.system':
default:
return const ThemeModeState(themeMode: ThemeMode.system);
}
}
@override
Map<String, String>? toJson(ThemeModeState state) {
return <String, String>{'themeMode': state.themeMode.toString()};
}
}
part of 'theme_cubit.dart';
@immutable
class ThemeModeState extends Equatable {
const ThemeModeState({
this.themeMode,
});
final ThemeMode? themeMode;
@override
List<Object?> get props => <Object?>[
themeMode,
];
}
......@@ -9,8 +9,10 @@ import 'package:path_provider/path_provider.dart';
import 'package:sortgame/config/theme.dart';
import 'package:sortgame/cubit/game_cubit.dart';
import 'package:sortgame/cubit/nav_cubit.dart';
import 'package:sortgame/cubit/settings_game_cubit.dart';
import 'package:sortgame/cubit/settings_global_cubit.dart';
import 'package:sortgame/cubit/theme_cubit.dart';
import 'package:sortgame/ui/skeleton.dart';
void main() async {
......@@ -44,20 +46,30 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<NavCubit>(create: (context) => NavCubit()),
BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
BlocProvider<GameCubit>(create: (context) => GameCubit()),
BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()),
BlocProvider<GameSettingsCubit>(create: (context) => GameSettingsCubit()),
],
child: MaterialApp(
child: BlocBuilder<ThemeCubit, ThemeModeState>(
builder: (BuildContext context, ThemeModeState state) {
return MaterialApp(
title: 'SortGame',
theme: appTheme,
home: const SkeletonScreen(),
// Theme stuff
theme: lightTheme,
darkTheme: darkTheme,
themeMode: state.themeMode,
// Localization stuff
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
debugShowCheckedModeBanner: false,
);
},
),
);
}
......
......@@ -60,7 +60,7 @@ class ParameterPainter extends CustomPainter {
return false;
}
// "unknown" parameter -> simple bock with text
// "unknown" parameter -> simple block with text
void paintUnknownParameterItem(
final int value,
final Canvas canvas,
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:sortgame/ui/widgets/helpers/app_header.dart';
class PageAbout extends StatelessWidget {
const PageAbout({super.key});
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
const AppHeader(text: 'about_title'),
const Text('about_content').tr(),
FutureBuilder<PackageInfo>(
future: PackageInfo.fromPlatform(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
return const Text('about_version').tr(
namedArgs: {
'version': snapshot.data!.version,
},
);
default:
return const SizedBox();
}
},
),
],
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sortgame/cubit/game_cubit.dart';
import 'package:sortgame/ui/widgets/game/game.dart';
import 'package:sortgame/ui/widgets/parameters.dart';
class PageGame extends StatelessWidget {
const PageGame({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<GameCubit, GameState>(
builder: (BuildContext context, GameState gameState) {
return gameState.currentGame.isRunning ? const GameWidget() : const Parameters();
});
}
}
import 'package:flutter/material.dart';
import 'package:sortgame/ui/widgets/helpers/app_header.dart';
import 'package:sortgame/ui/widgets/settings/settings_form.dart';
class PageSettings extends StatelessWidget {
const PageSettings({super.key});
@override
Widget build(BuildContext context) {
return const Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
AppHeader(text: 'settings_title'),
SizedBox(height: 8),
SettingsForm(),
],
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sortgame/cubit/game_cubit.dart';
import 'package:sortgame/ui/screens/screen_game.dart';
import 'package:sortgame/ui/screens/screen_parameters.dart';
import 'package:sortgame/config/menu.dart';
import 'package:sortgame/cubit/nav_cubit.dart';
import 'package:sortgame/ui/widgets/global_app_bar.dart';
class SkeletonScreen extends StatelessWidget {
......@@ -16,11 +15,16 @@ class SkeletonScreen extends StatelessWidget {
extendBodyBehindAppBar: false,
body: Material(
color: Theme.of(context).colorScheme.background,
child: BlocBuilder<GameCubit, GameState>(
builder: (BuildContext context, GameState gameState) {
return gameState.currentGame.isRunning
? const ScreenGame()
: const ScreenParameters();
child: BlocBuilder<NavCubit, int>(
builder: (BuildContext context, int pageIndex) {
return Padding(
padding: const EdgeInsets.only(
top: 8,
left: 2,
right: 2,
),
child: Menu.getPageWidget(pageIndex),
);
},
),
),
......
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sortgame/cubit/game_cubit.dart';
import 'package:sortgame/cubit/settings_game_cubit.dart';
import 'package:sortgame/cubit/settings_global_cubit.dart';
class StartNewGameButton extends StatelessWidget {
const StartNewGameButton({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<GameSettingsCubit, GameSettingsState>(
builder: (BuildContext context, GameSettingsState gameSettingsState) {
return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
return TextButton(
child: const Image(
image: AssetImage('assets/icons/button_start.png'),
fit: BoxFit.fill,
),
onPressed: () => gameCubit.startNewGame(
gameSettings: gameSettingsState.settings,
globalSettings: globalSettingsState.settings,
),
);
},
);
},
);
}
}
......@@ -3,12 +3,12 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sortgame/cubit/game_cubit.dart';
import 'package:sortgame/models/game.dart';
import 'package:sortgame/ui/widgets/game_bottom_buttons.dart';
import 'package:sortgame/ui/widgets/game_question.dart';
import 'package:sortgame/ui/widgets/game_top_indicator.dart';
import 'package:sortgame/ui/widgets/game/game_bottom_buttons.dart';
import 'package:sortgame/ui/widgets/game/game_question.dart';
import 'package:sortgame/ui/widgets/game/game_top_indicator.dart';
class ScreenGame extends StatelessWidget {
const ScreenGame({super.key});
class GameWidget extends StatelessWidget {
const GameWidget({super.key});
@override
Widget build(BuildContext context) {
......@@ -20,7 +20,6 @@ class ScreenGame extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 8),
const GameTopIndicatorWidget(),
const SizedBox(height: 8),
Expanded(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment