diff --git a/android/app/build.gradle b/android/app/build.gradle index 0100472fb105520210960db71e0ee39ca1c20983..9af8c9b2fe084b5aa32c8e4fda0a87e6793c67fe 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -37,7 +37,7 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 33 + compileSdkVersion 34 namespace "org.benoitharrault.jeweled" defaultConfig { diff --git a/android/gradle.properties b/android/gradle.properties index cc4e56eef743ffd4a67a64f0b67840717af81ff4..9742e8d9ac872ece07c6ae62a041bc05c2a8fcc6 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.0.30 -app.versionCode=30 +app.versionName=0.0.31 +app.versionCode=31 diff --git a/assets/translations/en.json b/assets/translations/en.json index 098a873d7b542216c2369f7618a54e5f9ec4e131..f434c73f8ed825abb5d940da7811389085433a5e 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -1,3 +1,14 @@ { - "app_name": "Jeweled" + "app_name": "Jeweled", + + "bottom_nav_game": "Game", + "bottom_nav_settings": "Settings", + "bottom_nav_about": "About", + + "settings_title": "Settings", + "settings_label_theme": "Theme mode", + + "about_title": "About", + "about_content": "Simple and classic Jeweled game.", + "about_version": "Version: {version}" } diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 098a873d7b542216c2369f7618a54e5f9ec4e131..0952f4587bc4a97d34806a58ff48cd6f0c57b1e7 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -1,3 +1,14 @@ { - "app_name": "Jeweled" + "app_name": "Jeweled", + + "bottom_nav_game": "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": "Jeweled, jeu simple et classique d'associations.", + "about_version": "Version : {version}" } diff --git a/fastlane/metadata/android/en-US/changelogs/31.txt b/fastlane/metadata/android/en-US/changelogs/31.txt new file mode 100644 index 0000000000000000000000000000000000000000..89d0168c47ada3eb75f65e1bda479293c0cbcfd2 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/31.txt @@ -0,0 +1 @@ +Add dark/light theme selector, and "about" page. diff --git a/fastlane/metadata/android/fr-FR/changelogs/31.txt b/fastlane/metadata/android/fr-FR/changelogs/31.txt new file mode 100644 index 0000000000000000000000000000000000000000..07ae206b67faa4ff05667a17d6f105cc46b8fd18 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/31.txt @@ -0,0 +1 @@ +Ajout de la sélection du thème clair/sombre, et d'une page "à propos". diff --git a/lib/config/menu.dart b/lib/config/menu.dart new file mode 100644 index 0000000000000000000000000000000000000000..79af6d0abecd90f7a6292def370ef5a511af60e1 --- /dev/null +++ b/lib/config/menu.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:unicons/unicons.dart'; + +import 'package:jeweled/ui/screens/about_page.dart'; +import 'package:jeweled/ui/screens/game_page.dart'; +import 'package:jeweled/ui/screens/settings_page.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: GamePage(), + ); + + static const indexSettings = 1; + static const menuItemSettings = MenuItem( + code: 'bottom_nav_settings', + icon: Icon(UniconsLine.setting), + page: SettingsPage(), + ); + + static const indexAbout = 2; + static const menuItemAbout = MenuItem( + code: 'bottom_nav_about', + icon: Icon(UniconsLine.info_circle), + page: AboutPage(), + ); + + 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; +} diff --git a/lib/cubit/nav_cubit.dart b/lib/cubit/nav_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..f2f46286f1994d17eb3c6d840938039e205633b8 --- /dev/null +++ b/lib/cubit/nav_cubit.dart @@ -0,0 +1,45 @@ +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:jeweled/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 switchToSettingsPage() { + if (state != Menu.indexSettings) { + emit(Menu.indexSettings); + } else { + goToGamePage(); + } + } + + void switchToAboutPage() { + if (state != Menu.indexAbout) { + emit(Menu.indexAbout); + } else { + goToGamePage(); + } + } + + @override + int fromJson(Map<String, dynamic> json) { + return Menu.indexGame; + } + + @override + Map<String, dynamic>? toJson(int state) { + return <String, int>{'pageIndex': state}; + } +} diff --git a/lib/cubit/theme_cubit.dart b/lib/cubit/theme_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..b793e895dbb0c672d451cd403e0036c3d9ac9b42 --- /dev/null +++ b/lib/cubit/theme_cubit.dart @@ -0,0 +1,31 @@ +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()}; + } +} diff --git a/lib/cubit/theme_state.dart b/lib/cubit/theme_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..e479a50f12fe72a35a1fd1722ff72afbb692a136 --- /dev/null +++ b/lib/cubit/theme_state.dart @@ -0,0 +1,15 @@ +part of 'theme_cubit.dart'; + +@immutable +class ThemeModeState extends Equatable { + const ThemeModeState({ + this.themeMode, + }); + + final ThemeMode? themeMode; + + @override + List<Object?> get props => <Object?>[ + themeMode, + ]; +} diff --git a/lib/main.dart b/lib/main.dart index 5ee1917f0684353e0a71c82e1164f1bad9cf017b..11da37222d1ca96a98c851cf6ce5b00423bb9d33 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,12 +9,14 @@ import 'package:path_provider/path_provider.dart'; import 'package:jeweled/config/theme.dart'; import 'package:jeweled/cubit/game_cubit.dart'; +import 'package:jeweled/cubit/nav_cubit.dart'; import 'package:jeweled/cubit/settings_game_cubit.dart'; import 'package:jeweled/cubit/settings_global_cubit.dart'; +import 'package:jeweled/cubit/theme_cubit.dart'; import 'package:jeweled/ui/skeleton.dart'; void main() async { - /// Initialize packages + // Initialize packages WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); final Directory tmpDir = await getTemporaryDirectory(); @@ -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( - title: 'Jeweled', - theme: appTheme, - home: const SkeletonScreen(), + child: BlocBuilder<ThemeCubit, ThemeModeState>( + builder: (BuildContext context, ThemeModeState state) { + return MaterialApp( + title: 'Jeweled', + home: const SkeletonScreen(), - // Localization stuff - localizationsDelegates: context.localizationDelegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - debugShowCheckedModeBanner: false, + // Theme stuff + theme: lightTheme, + darkTheme: darkTheme, + themeMode: state.themeMode, + + // Localization stuff + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, + locale: context.locale, + debugShowCheckedModeBanner: false, + ); + }, ), ); } diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/about_page.dart new file mode 100644 index 0000000000000000000000000000000000000000..0ffecbc5bcd11b53642e2b8bc80bd73961707b82 --- /dev/null +++ b/lib/ui/screens/about_page.dart @@ -0,0 +1,41 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +import 'package:jeweled/ui/widgets/header_app.dart'; + +class AboutPage extends StatelessWidget { + const AboutPage({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: <Widget>[ + const SizedBox(height: 8), + 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(); + } + }, + ), + ], + ), + ); + } +} diff --git a/lib/ui/screens/game.dart b/lib/ui/screens/game_page.dart similarity index 88% rename from lib/ui/screens/game.dart rename to lib/ui/screens/game_page.dart index 5f56240c35f3f32e05fd7ecd4ba97bf6a6576b03..24694bc5e0db1d9efb841c1a2bc1a3dd601fdd65 100644 --- a/lib/ui/screens/game.dart +++ b/lib/ui/screens/game_page.dart @@ -5,8 +5,8 @@ import 'package:jeweled/cubit/game_cubit.dart'; import 'package:jeweled/ui/widgets/game.dart'; import 'package:jeweled/ui/widgets/parameters.dart'; -class ScreenGame extends StatelessWidget { - const ScreenGame({super.key}); +class GamePage extends StatelessWidget { + const GamePage({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/settings_page.dart new file mode 100644 index 0000000000000000000000000000000000000000..0bf6979befe32f9f30d8d5a21f7db28b0f7faaff --- /dev/null +++ b/lib/ui/screens/settings_page.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +import 'package:jeweled/ui/widgets/header_app.dart'; +import 'package:jeweled/ui/widgets/settings/settings_form.dart'; + +class SettingsPage extends StatelessWidget { + const SettingsPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Padding( + padding: EdgeInsets.symmetric(horizontal: 8), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: <Widget>[ + SizedBox(height: 8), + AppHeader(text: 'settings_title'), + SizedBox(height: 8), + SettingsForm(), + ], + ), + ); + } +} diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart index 8ce8ca5bdf83f8a9a898dd5b1470ea09ca8daf5f..38225b2039ea32532381646c461cacbb6d2bcc4a 100644 --- a/lib/ui/skeleton.dart +++ b/lib/ui/skeleton.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:jeweled/ui/screens/game.dart'; +import 'package:jeweled/config/menu.dart'; +import 'package:jeweled/cubit/nav_cubit.dart'; import 'package:jeweled/ui/widgets/global_app_bar.dart'; class SkeletonScreen extends StatelessWidget { @@ -11,7 +13,11 @@ class SkeletonScreen extends StatelessWidget { return Scaffold( appBar: const GlobalAppBar(), extendBodyBehindAppBar: false, - body: const ScreenGame(), + body: BlocBuilder<NavCubit, int>( + builder: (BuildContext context, int pageIndex) { + return Menu.getPageWidget(pageIndex); + }, + ), backgroundColor: Theme.of(context).colorScheme.background, ); } diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart index 1d425fb65a8cb8994a006b973d64b7718cce2755..51a5fe011afd2297c553f3f3b5b517f4819473d1 100644 --- a/lib/ui/widgets/global_app_bar.dart +++ b/lib/ui/widgets/global_app_bar.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:jeweled/config/menu.dart'; import 'package:jeweled/cubit/game_cubit.dart'; +import 'package:jeweled/cubit/nav_cubit.dart'; import 'package:jeweled/models/game.dart'; import 'package:jeweled/ui/widgets/helpers/app_titles.dart'; @@ -12,27 +14,66 @@ class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget { Widget build(BuildContext context) { return BlocBuilder<GameCubit, GameState>( builder: (BuildContext context, GameState gameState) { - final Game currentGame = gameState.currentGame; - - final List<Widget> menuActions = []; - - if (currentGame.isRunning) { - menuActions.add(TextButton( - child: const Image( - image: AssetImage('assets/icons/button_back.png'), - fit: BoxFit.fill, - ), - onPressed: () {}, - onLongPress: () { - final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); - gameCubit.quitGame(); - }, - )); - } - - return AppBar( - title: const AppTitle(text: 'app_name'), - actions: menuActions, + return BlocBuilder<NavCubit, int>( + builder: (BuildContext context, int pageIndex) { + final Game currentGame = gameState.currentGame; + + final List<Widget> menuActions = []; + + if (currentGame.isRunning) { + menuActions.add(TextButton( + child: const Image( + image: AssetImage('assets/icons/button_back.png'), + fit: BoxFit.fill, + ), + onPressed: () {}, + onLongPress: () { + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + gameCubit.quitGame(); + }, + )); + } else { + if (pageIndex == Menu.indexGame) { + // go to Settings page + menuActions.add(ElevatedButton( + onPressed: () { + context.read<NavCubit>().switchToSettingsPage(); + }, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + ), + child: Menu.menuItemSettings.icon, + )); + + // go to About page + menuActions.add(ElevatedButton( + onPressed: () { + context.read<NavCubit>().switchToAboutPage(); + }, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + ), + child: Menu.menuItemAbout.icon, + )); + } else { + // back to Home page + menuActions.add(ElevatedButton( + onPressed: () { + context.read<NavCubit>().goToGamePage(); + }, + style: ElevatedButton.styleFrom( + shape: const CircleBorder(), + ), + child: Menu.menuItemGame.icon, + )); + } + } + + return AppBar( + title: const AppTitle(text: 'app_name'), + actions: menuActions, + ); + }, ); }, ); diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/header_app.dart new file mode 100644 index 0000000000000000000000000000000000000000..b5c5be05f6636cf488dcdb5bbc4d6f049b98de11 --- /dev/null +++ b/lib/ui/widgets/header_app.dart @@ -0,0 +1,24 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +class AppHeader extends StatelessWidget { + const AppHeader({super.key, required this.text}); + + final String text; + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + tr(text), + textAlign: TextAlign.start, + style: Theme.of(context).textTheme.headlineSmall!.apply(fontWeightDelta: 2), + ), + const SizedBox(height: 8), + ], + ); + } +} diff --git a/lib/ui/widgets/settings/settings_form.dart b/lib/ui/widgets/settings/settings_form.dart new file mode 100644 index 0000000000000000000000000000000000000000..9ae13f325638dcb9219561c4098cf3df1584490d --- /dev/null +++ b/lib/ui/widgets/settings/settings_form.dart @@ -0,0 +1,63 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:unicons/unicons.dart'; + +import 'package:jeweled/ui/widgets/settings/theme_card.dart'; + +class SettingsForm extends StatefulWidget { + const SettingsForm({super.key}); + + @override + State<SettingsForm> createState() => _SettingsFormState(); +} + +class _SettingsFormState extends State<SettingsForm> { + @override + void dispose() { + super.dispose(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: <Widget>[ + // Light/dark theme + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: <Widget>[ + const Text('settings_label_theme').tr(), + const Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ThemeCard( + mode: ThemeMode.system, + icon: UniconsLine.cog, + ), + ThemeCard( + mode: ThemeMode.light, + icon: UniconsLine.sun, + ), + ThemeCard( + mode: ThemeMode.dark, + icon: UniconsLine.moon, + ) + ], + ), + ], + ), + + const SizedBox(height: 16), + ], + ); + } +} diff --git a/lib/ui/widgets/settings/theme_card.dart b/lib/ui/widgets/settings/theme_card.dart new file mode 100644 index 0000000000000000000000000000000000000000..959bfbcb0d84067ad6a5bf067aa47dbb3befa56a --- /dev/null +++ b/lib/ui/widgets/settings/theme_card.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:jeweled/cubit/theme_cubit.dart'; + +class ThemeCard extends StatelessWidget { + const ThemeCard({ + super.key, + required this.mode, + required this.icon, + }); + + final IconData icon; + final ThemeMode mode; + + @override + Widget build(BuildContext context) { + return BlocBuilder<ThemeCubit, ThemeModeState>( + builder: (BuildContext context, ThemeModeState state) { + return Card( + elevation: 2, + shadowColor: Theme.of(context).colorScheme.shadow, + color: state.themeMode == mode + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.surface, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + ), + margin: const EdgeInsets.all(5), + child: InkWell( + onTap: () => BlocProvider.of<ThemeCubit>(context).getTheme( + ThemeModeState(themeMode: mode), + ), + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: Icon( + icon, + size: 32, + color: state.themeMode != mode + ? Theme.of(context).colorScheme.primary + : Colors.white, + ), + ), + ); + }, + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 47304c5bf4f5619ea81f99b24c510318882f2911..25b5be0248780b099e0f72fc5dab70bd5ce13f92 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,18 @@ packages: dependency: transitive description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.5.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" bloc: dependency: transitive description: @@ -53,10 +61,10 @@ packages: dependency: "direct main" description: name: easy_localization - sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c + sha256: "432698c31a488dd64c56d4759f20d04844baba5e9e4f2cb1abb9676257918b17" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" easy_logger: dependency: transitive description: @@ -128,6 +136,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.3" + http: + dependency: transitive + description: + name: http + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" hydrated_bloc: dependency: "direct main" description: @@ -176,6 +200,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + package_info_plus: + dependency: "direct main" + description: + name: package_info_plus + sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0 + url: "https://pub.dev" + source: hosted + version: "8.0.0" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e + url: "https://pub.dev" + source: hosted + version: "3.0.0" path: dependency: transitive description: @@ -188,18 +228,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.4" path_provider_foundation: dependency: transitive description: @@ -260,18 +300,18 @@ packages: dependency: transitive description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_foundation: dependency: transitive description: @@ -317,6 +357,22 @@ packages: description: flutter source: sdk version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" synchronized: dependency: transitive description: @@ -325,6 +381,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0+1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" typed_data: dependency: transitive description: @@ -333,6 +397,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + unicons: + dependency: "direct main" + description: + name: unicons + sha256: dbfcf93ff4d4ea19b324113857e358e4882115ab85db04417a4ba1c72b17a670 + url: "https://pub.dev" + source: hosted + version: "2.1.1" vector_math: dependency: transitive description: @@ -353,10 +425,10 @@ packages: dependency: transitive description: name: win32 - sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "5.5.0" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a11b99ee9c17ec55f13de9efb2be09d2c96da220..03827d382239dd86590e513682880db972935257 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,28 +1,31 @@ name: jeweled description: Jeweled Game -publish_to: 'none' +publish_to: "none" -version: 0.0.30+30 +version: 0.0.31+31 environment: - sdk: '^3.0.0' + sdk: "^3.0.0" dependencies: flutter: sdk: flutter + easy_localization: ^3.0.1 equatable: ^2.0.5 flutter_bloc: ^8.1.1 hive: ^2.2.3 hydrated_bloc: ^9.0.0 + package_info_plus: ^8.0.0 path_provider: ^2.0.11 + unicons: ^2.1.1 dev_dependencies: flutter_lints: ^3.0.1 flutter: - uses-material-design: false + uses-material-design: true assets: - assets/icons/ - assets/translations/