From cc57819e7ca981024e2566154d87fcf3fa7f333d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Tue, 22 Oct 2024 23:47:54 +0200
Subject: [PATCH] Normalize Activity application architecture

---
 assets/translations/en.json                   |   3 +
 assets/translations/fr.json                   |   3 +
 .../metadata/android/en-US/changelogs/38.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/38.txt  |   1 +
 lib/common/config/activity_page.dart          |  50 +++++
 lib/common/config/screen.dart                 |  55 +++++
 lib/common/cubit/nav/nav_cubit_pages.dart     |  33 +++
 lib/common/cubit/nav/nav_cubit_screens.dart   |  37 ++++
 lib/common/ui/nav/bottom_nav_bar.dart         |  46 +++++
 .../ui/nav}/global_app_bar.dart               |  39 ++--
 .../ui/pages/game.dart}                       |  16 +-
 lib/common/ui/pages/parameters.dart           | 148 ++++++++++++++
 .../ui/parameters/parameter_painter.dart      |  20 +-
 .../ui/parameters/parameter_widget.dart       |  40 ++--
 .../ui/screens/about.dart}                    |   4 +-
 lib/common/ui/screens/activity.dart           |  18 ++
 .../ui/screens/settings.dart}                 |   4 +-
 lib/config/application_config.dart            |   3 +
 ...gs.dart => default_activity_settings.dart} |   6 +-
 lib/config/menu.dart                          |  52 -----
 lib/cubit/activity/activity_cubit.dart        | 188 ++++++++++++++++++
 lib/cubit/activity/activity_state.dart        |  15 ++
 lib/cubit/game_cubit.dart                     | 188 ------------------
 lib/cubit/game_state.dart                     |  15 --
 lib/cubit/nav_cubit.dart                      |  37 ----
 .../settings/settings_activity_cubit.dart     |  73 +++++++
 .../settings/settings_activity_state.dart     |  15 ++
 .../{ => settings}/settings_global_cubit.dart |   0
 .../{ => settings}/settings_global_state.dart |   0
 lib/cubit/settings_game_cubit.dart            |  71 -------
 lib/cubit/settings_game_state.dart            |  15 --
 lib/main.dart                                 |  36 +++-
 .../game.dart => activity/activity.dart}      |  71 +++----
 lib/models/{game => activity}/board.dart      |  12 +-
 lib/models/{game => activity}/cell.dart       |   0
 .../{game => activity}/cell_location.dart     |   0
 lib/models/settings/settings_activity.dart    |  59 ++++++
 lib/models/settings/settings_game.dart        |  59 ------
 lib/ui/game/game_top.dart                     |  18 +-
 lib/ui/layouts/parameters_layout.dart         | 141 -------------
 lib/ui/painters/game_board_painter.dart       |  30 +--
 lib/ui/screens/page_game.dart                 |  24 ---
 lib/ui/skeleton.dart                          |  37 ++--
 .../actions/button_delete_saved_game.dart     |   4 +-
 lib/ui/widgets/actions/button_game_quit.dart  |   7 +-
 .../actions/button_game_start_new.dart        |  17 +-
 .../actions/button_resume_saved_game.dart     |   7 +-
 lib/ui/widgets/game/board.dart                |  38 ++--
 .../indicator_available_blocks.dart           |  11 +-
 .../indicators/indicator_moves_count.dart     |   8 +-
 .../widgets/indicators/indicator_score.dart   |   8 +-
 .../indicators/indicator_shuffle_button.dart  |  11 +-
 pubspec.lock                                  |   8 +-
 pubspec.yaml                                  |   2 +-
 54 files changed, 997 insertions(+), 807 deletions(-)
 create mode 100644 fastlane/metadata/android/en-US/changelogs/38.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/38.txt
 create mode 100644 lib/common/config/activity_page.dart
 create mode 100644 lib/common/config/screen.dart
 create mode 100644 lib/common/cubit/nav/nav_cubit_pages.dart
 create mode 100644 lib/common/cubit/nav/nav_cubit_screens.dart
 create mode 100644 lib/common/ui/nav/bottom_nav_bar.dart
 rename lib/{ui/widgets => common/ui/nav}/global_app_bar.dart (58%)
 rename lib/{ui/layouts/game_layout.dart => common/ui/pages/game.dart} (64%)
 create mode 100644 lib/common/ui/pages/parameters.dart
 rename lib/{ => common}/ui/parameters/parameter_painter.dart (94%)
 rename lib/{ => common}/ui/parameters/parameter_widget.dart (81%)
 rename lib/{ui/screens/page_about.dart => common/ui/screens/about.dart} (93%)
 create mode 100644 lib/common/ui/screens/activity.dart
 rename lib/{ui/screens/page_settings.dart => common/ui/screens/settings.dart} (87%)
 create mode 100644 lib/config/application_config.dart
 rename lib/config/{default_game_settings.dart => default_activity_settings.dart} (91%)
 delete mode 100644 lib/config/menu.dart
 create mode 100644 lib/cubit/activity/activity_cubit.dart
 create mode 100644 lib/cubit/activity/activity_state.dart
 delete mode 100644 lib/cubit/game_cubit.dart
 delete mode 100644 lib/cubit/game_state.dart
 delete mode 100644 lib/cubit/nav_cubit.dart
 create mode 100644 lib/cubit/settings/settings_activity_cubit.dart
 create mode 100644 lib/cubit/settings/settings_activity_state.dart
 rename lib/cubit/{ => settings}/settings_global_cubit.dart (100%)
 rename lib/cubit/{ => settings}/settings_global_state.dart (100%)
 delete mode 100644 lib/cubit/settings_game_cubit.dart
 delete mode 100644 lib/cubit/settings_game_state.dart
 rename lib/models/{game/game.dart => activity/activity.dart} (81%)
 rename lib/models/{game => activity}/board.dart (77%)
 rename lib/models/{game => activity}/cell.dart (100%)
 rename lib/models/{game => activity}/cell_location.dart (100%)
 create mode 100644 lib/models/settings/settings_activity.dart
 delete mode 100644 lib/models/settings/settings_game.dart
 delete mode 100644 lib/ui/layouts/parameters_layout.dart
 delete mode 100644 lib/ui/screens/page_game.dart

diff --git a/assets/translations/en.json b/assets/translations/en.json
index 6924de1..65e22e6 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,6 +1,9 @@
 {
   "app_name": "Jeweled",
 
+  "page_home": "Home",
+  "page_game": "Game",
+
   "settings_title": "Settings",
   "settings_label_theme": "Theme mode",
 
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 23adc4c..4d13af3 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -1,6 +1,9 @@
 {
   "app_name": "Jeweled",
 
+  "page_home": "Accueil",
+  "page_game": "Jeu",
+
   "settings_title": "Réglages",
   "settings_label_theme": "Thème de couleurs",
 
diff --git a/fastlane/metadata/android/en-US/changelogs/38.txt b/fastlane/metadata/android/en-US/changelogs/38.txt
new file mode 100644
index 0000000..ac2c90e
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/38.txt
@@ -0,0 +1 @@
+Normalize Activity application architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/38.txt b/fastlane/metadata/android/fr-FR/changelogs/38.txt
new file mode 100644
index 0000000..1d6843d
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/38.txt
@@ -0,0 +1 @@
+Harmonisation des applications en Activity.
diff --git a/lib/common/config/activity_page.dart b/lib/common/config/activity_page.dart
new file mode 100644
index 0000000..ecf719a
--- /dev/null
+++ b/lib/common/config/activity_page.dart
@@ -0,0 +1,50 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/common/ui/pages/game.dart';
+import 'package:jeweled/common/ui/pages/parameters.dart';
+
+class ActivityPageItem {
+  final String code;
+  final Icon icon;
+  final Widget page;
+
+  const ActivityPageItem({
+    required this.code,
+    required this.icon,
+    required this.page,
+  });
+}
+
+class ActivityPage {
+  static const bool displayBottomNavBar = false;
+
+  static const indexHome = 0;
+  static const pageHome = ActivityPageItem(
+    code: 'page_home',
+    icon: Icon(UniconsLine.home),
+    page: PageParameters(),
+  );
+
+  static const indexGame = 1;
+  static const pageGame = ActivityPageItem(
+    code: 'page_game',
+    icon: Icon(UniconsLine.star),
+    page: PageGame(),
+  );
+
+  static const Map<int, ActivityPageItem> items = {
+    indexHome: pageHome,
+    indexGame: pageGame,
+  };
+
+  static int defaultPageIndex = indexHome;
+
+  static bool isIndexAllowed(int pageIndex) {
+    return items.keys.contains(pageIndex);
+  }
+
+  static Widget getWidget(int pageIndex) {
+    return items[pageIndex]?.page ?? pageHome.page;
+  }
+}
diff --git a/lib/common/config/screen.dart b/lib/common/config/screen.dart
new file mode 100644
index 0000000..d18634c
--- /dev/null
+++ b/lib/common/config/screen.dart
@@ -0,0 +1,55 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/common/ui/screens/about.dart';
+import 'package:jeweled/common/ui/screens/activity.dart';
+import 'package:jeweled/common/ui/screens/settings.dart';
+
+class ScreenItem {
+  final String code;
+  final Icon icon;
+  final Widget screen;
+
+  const ScreenItem({
+    required this.code,
+    required this.icon,
+    required this.screen,
+  });
+}
+
+class Screen {
+  static const indexActivity = 0;
+  static const screenActivity = ScreenItem(
+    code: 'screen_activity',
+    icon: Icon(UniconsLine.home),
+    screen: ScreenActivity(),
+  );
+
+  static const indexSettings = 1;
+  static const screenSettings = ScreenItem(
+    code: 'screen_settings',
+    icon: Icon(UniconsLine.setting),
+    screen: ScreenSettings(),
+  );
+
+  static const indexAbout = 2;
+  static const screenAbout = ScreenItem(
+    code: 'screen_about',
+    icon: Icon(UniconsLine.info_circle),
+    screen: ScreenAbout(),
+  );
+
+  static Map<int, ScreenItem> items = {
+    indexActivity: screenActivity,
+    indexSettings: screenSettings,
+    indexAbout: screenAbout,
+  };
+
+  static bool isIndexAllowed(int screenIndex) {
+    return items.keys.contains(screenIndex);
+  }
+
+  static Widget getWidget(int screenIndex) {
+    return items[screenIndex]?.screen ?? screenActivity.screen;
+  }
+}
diff --git a/lib/common/cubit/nav/nav_cubit_pages.dart b/lib/common/cubit/nav/nav_cubit_pages.dart
new file mode 100644
index 0000000..6e8bfc7
--- /dev/null
+++ b/lib/common/cubit/nav/nav_cubit_pages.dart
@@ -0,0 +1,33 @@
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/common/config/activity_page.dart';
+
+class NavCubitPage extends HydratedCubit<int> {
+  NavCubitPage() : super(0);
+
+  void updateIndex(int index) {
+    if (ActivityPage.isIndexAllowed(index)) {
+      emit(index);
+    } else {
+      emit(ActivityPage.indexHome);
+    }
+  }
+
+  void goToPageHome() {
+    updateIndex(ActivityPage.indexHome);
+  }
+
+  void goToPageGame() {
+    updateIndex(ActivityPage.indexGame);
+  }
+
+  @override
+  int fromJson(Map<String, dynamic> json) {
+    return ActivityPage.indexHome;
+  }
+
+  @override
+  Map<String, dynamic>? toJson(int state) {
+    return <String, int>{'index': state};
+  }
+}
diff --git a/lib/common/cubit/nav/nav_cubit_screens.dart b/lib/common/cubit/nav/nav_cubit_screens.dart
new file mode 100644
index 0000000..f0d82d8
--- /dev/null
+++ b/lib/common/cubit/nav/nav_cubit_screens.dart
@@ -0,0 +1,37 @@
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/common/config/screen.dart';
+
+class NavCubitScreen extends HydratedCubit<int> {
+  NavCubitScreen() : super(0);
+
+  void updateIndex(int index) {
+    if (Screen.isIndexAllowed(index)) {
+      emit(index);
+    } else {
+      goToScreenActivity();
+    }
+  }
+
+  void goToScreenActivity() {
+    emit(Screen.indexActivity);
+  }
+
+  void goToScreenSettings() {
+    emit(Screen.indexSettings);
+  }
+
+  void goToScreenAbout() {
+    emit(Screen.indexAbout);
+  }
+
+  @override
+  int fromJson(Map<String, dynamic> json) {
+    return Screen.indexActivity;
+  }
+
+  @override
+  Map<String, dynamic>? toJson(int state) {
+    return <String, int>{'index': state};
+  }
+}
diff --git a/lib/common/ui/nav/bottom_nav_bar.dart b/lib/common/ui/nav/bottom_nav_bar.dart
new file mode 100644
index 0000000..0ed2afb
--- /dev/null
+++ b/lib/common/ui/nav/bottom_nav_bar.dart
@@ -0,0 +1,46 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/common/config/activity_page.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_pages.dart';
+
+class BottomNavBar extends StatelessWidget {
+  const BottomNavBar({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      margin: const EdgeInsets.only(top: 1, right: 4, left: 4),
+      elevation: 4,
+      shadowColor: Theme.of(context).colorScheme.shadow,
+      color: Theme.of(context).colorScheme.surfaceContainerHighest,
+      shape: const RoundedRectangleBorder(
+        borderRadius: BorderRadius.only(
+          topLeft: Radius.circular(16),
+          topRight: Radius.circular(16),
+        ),
+      ),
+      child: BlocBuilder<NavCubitPage, int>(builder: (BuildContext context, int state) {
+        final List<BottomNavigationBarItem> items = [];
+
+        ActivityPage.items.forEach((int pageIndex, ActivityPageItem item) {
+          items.add(BottomNavigationBarItem(
+            icon: item.icon,
+            label: tr(item.code),
+          ));
+        });
+
+        return BottomNavigationBar(
+          currentIndex: state,
+          onTap: (int index) => BlocProvider.of<NavCubitPage>(context).updateIndex(index),
+          type: BottomNavigationBarType.fixed,
+          elevation: 0,
+          backgroundColor: Colors.transparent,
+          selectedItemColor: Theme.of(context).colorScheme.primary,
+          unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
+          items: items,
+        );
+      }),
+    );
+  }
+}
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/common/ui/nav/global_app_bar.dart
similarity index 58%
rename from lib/ui/widgets/global_app_bar.dart
rename to lib/common/ui/nav/global_app_bar.dart
index 6ac5318..77b379e 100644
--- a/lib/ui/widgets/global_app_bar.dart
+++ b/lib/common/ui/nav/global_app_bar.dart
@@ -1,30 +1,33 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.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/game.dart';
+import 'package:jeweled/common/config/screen.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_pages.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_screens.dart';
+
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
+import 'package:jeweled/models/activity/activity.dart';
 
 class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
   const GlobalAppBar({super.key});
 
   @override
   Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        return BlocBuilder<NavCubit, int>(
+    return BlocBuilder<ActivityCubit, ActivityState>(
+      builder: (BuildContext context, ActivityState activityState) {
+        return BlocBuilder<NavCubitScreen, int>(
           builder: (BuildContext context, int pageIndex) {
-            final Game currentGame = gameState.currentGame;
+            final Activity currentActivity = activityState.currentActivity;
 
             final List<Widget> menuActions = [];
 
-            if (currentGame.isRunning && !currentGame.isFinished) {
+            if (currentActivity.isRunning && !currentActivity.isFinished) {
               menuActions.add(StyledButton(
                 color: Colors.red,
                 onPressed: () {},
                 onLongPress: () {
-                  BlocProvider.of<GameCubit>(context).quitGame();
+                  BlocProvider.of<ActivityCubit>(context).quitActivity();
+                  BlocProvider.of<NavCubitPage>(context).goToPageHome();
                 },
                 child: const Image(
                   image: AssetImage('assets/ui/button_back.png'),
@@ -32,44 +35,44 @@ class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
                 ),
               ));
             } else {
-              if (pageIndex == Menu.indexGame) {
+              if (pageIndex == Screen.indexActivity) {
                 // go to Settings page
                 menuActions.add(ElevatedButton(
                   onPressed: () {
-                    BlocProvider.of<NavCubit>(context).goToSettingsPage();
+                    BlocProvider.of<NavCubitScreen>(context).goToScreenSettings();
                   },
                   style: ElevatedButton.styleFrom(
                     shape: const CircleBorder(),
                   ),
-                  child: Menu.menuItemSettings.icon,
+                  child: Screen.screenSettings.icon,
                 ));
 
                 // go to About page
                 menuActions.add(ElevatedButton(
                   onPressed: () {
-                    BlocProvider.of<NavCubit>(context).goToAboutPage();
+                    BlocProvider.of<NavCubitScreen>(context).goToScreenAbout();
                   },
                   style: ElevatedButton.styleFrom(
                     shape: const CircleBorder(),
                   ),
-                  child: Menu.menuItemAbout.icon,
+                  child: Screen.screenAbout.icon,
                 ));
               } else {
                 // back to Home page
                 menuActions.add(ElevatedButton(
                   onPressed: () {
-                    BlocProvider.of<NavCubit>(context).goToGamePage();
+                    BlocProvider.of<NavCubitScreen>(context).goToScreenActivity();
                   },
                   style: ElevatedButton.styleFrom(
                     shape: const CircleBorder(),
                   ),
-                  child: Menu.menuItemGame.icon,
+                  child: Screen.screenActivity.icon,
                 ));
               }
             }
 
             return AppBar(
-              title: const AppTitle(text: 'app_name'),
+              title: const AppHeader(text: 'app_name'),
               actions: menuActions,
             );
           },
diff --git a/lib/ui/layouts/game_layout.dart b/lib/common/ui/pages/game.dart
similarity index 64%
rename from lib/ui/layouts/game_layout.dart
rename to lib/common/ui/pages/game.dart
index 0894955..b605c3c 100644
--- a/lib/ui/layouts/game_layout.dart
+++ b/lib/common/ui/pages/game.dart
@@ -1,20 +1,20 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/cubit/game_cubit.dart';
-import 'package:jeweled/models/game/game.dart';
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
+import 'package:jeweled/models/activity/activity.dart';
 import 'package:jeweled/ui/game/game_end.dart';
 import 'package:jeweled/ui/game/game_top.dart';
 import 'package:jeweled/ui/widgets/game/board.dart';
 
-class GameLayout extends StatelessWidget {
-  const GameLayout({super.key});
+class PageGame extends StatelessWidget {
+  const PageGame({super.key});
 
   @override
   Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        final Game currentGame = gameState.currentGame;
+    return BlocBuilder<ActivityCubit, ActivityState>(
+      builder: (BuildContext context, ActivityState activityState) {
+        final Activity currentActivity = activityState.currentActivity;
 
         return Container(
           alignment: AlignmentDirectional.topCenter,
@@ -28,7 +28,7 @@ class GameLayout extends StatelessWidget {
               const BoardWidget(),
               const SizedBox(height: 8),
               const Expanded(child: SizedBox.shrink()),
-              currentGame.isFinished ? const GameEndWidget() : const SizedBox.shrink(),
+              currentActivity.isFinished ? const GameEndWidget() : const SizedBox.shrink(),
             ],
           ),
         );
diff --git a/lib/common/ui/pages/parameters.dart b/lib/common/ui/pages/parameters.dart
new file mode 100644
index 0000000..b4fa148
--- /dev/null
+++ b/lib/common/ui/pages/parameters.dart
@@ -0,0 +1,148 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/common/ui/parameters/parameter_widget.dart';
+
+import 'package:jeweled/config/default_activity_settings.dart';
+import 'package:jeweled/config/default_global_settings.dart';
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
+import 'package:jeweled/cubit/settings/settings_activity_cubit.dart';
+import 'package:jeweled/cubit/settings/settings_global_cubit.dart';
+import 'package:jeweled/models/activity/activity.dart';
+import 'package:jeweled/ui/widgets/actions/button_delete_saved_game.dart';
+import 'package:jeweled/ui/widgets/actions/button_game_start_new.dart';
+import 'package:jeweled/ui/widgets/actions/button_resume_saved_game.dart';
+
+class PageParameters extends StatelessWidget {
+  const PageParameters({super.key});
+
+  final double separatorHeight = 8.0;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<ActivityCubit, ActivityState>(
+      builder: (BuildContext context, ActivityState activityState) {
+        final Activity currentActivity = activityState.currentActivity;
+
+        final List<Widget> lines = [];
+
+        // Game settings
+        for (String code in DefaultActivitySettings.availableParameters) {
+          lines.add(Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: buildParametersLine(
+              code: code,
+              isGlobal: false,
+            ),
+          ));
+
+          lines.add(SizedBox(height: separatorHeight));
+        }
+
+        lines.add(Expanded(
+          child: SizedBox(height: separatorHeight),
+        ));
+
+        if (currentActivity.canBeResumed == false) {
+          // Start new game
+          lines.add(
+            const AspectRatio(
+              aspectRatio: 3,
+              child: StartNewGameButton(),
+            ),
+          );
+        } else {
+          // Resume game
+          lines.add(const AspectRatio(
+            aspectRatio: 3,
+            child: ResumeSavedGameButton(),
+          ));
+          // Delete saved game
+          lines.add(SizedBox.square(
+            dimension: MediaQuery.of(context).size.width / 5,
+            child: const DeleteSavedGameButton(),
+          ));
+        }
+
+        lines.add(SizedBox(height: separatorHeight));
+
+        // Global settings
+        for (String code in DefaultGlobalSettings.availableParameters) {
+          lines.add(Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: buildParametersLine(
+              code: code,
+              isGlobal: true,
+            ),
+          ));
+
+          lines.add(SizedBox(height: separatorHeight));
+        }
+
+        return Column(
+          children: lines,
+        );
+      },
+    );
+  }
+
+  List<Widget> buildParametersLine({
+    required String code,
+    required bool isGlobal,
+  }) {
+    final List<Widget> parameterButtons = [];
+
+    final List<String> availableValues = isGlobal
+        ? DefaultGlobalSettings.getAvailableValues(code)
+        : DefaultActivitySettings.getAvailableValues(code);
+
+    if (availableValues.length <= 1) {
+      return [];
+    }
+
+    for (String value in availableValues) {
+      final Widget parameterButton = BlocBuilder<ActivitySettingsCubit, ActivitySettingsState>(
+        builder: (BuildContext context, ActivitySettingsState activitySettingsState) {
+          return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+            builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+              final ActivitySettingsCubit activitySettingsCubit =
+                  BlocProvider.of<ActivitySettingsCubit>(context);
+              final GlobalSettingsCubit globalSettingsCubit =
+                  BlocProvider.of<GlobalSettingsCubit>(context);
+
+              final String currentValue = isGlobal
+                  ? globalSettingsCubit.getParameterValue(code)
+                  : activitySettingsCubit.getParameterValue(code);
+
+              final bool isSelected = (value == currentValue);
+
+              final double displayWidth = MediaQuery.of(context).size.width;
+              final double itemWidth = displayWidth / availableValues.length - 4;
+
+              return SizedBox.square(
+                dimension: itemWidth,
+                child: ParameterWidget(
+                  code: code,
+                  value: value,
+                  isSelected: isSelected,
+                  size: itemWidth,
+                  activitySettings: activitySettingsState.settings,
+                  globalSettings: globalSettingsState.settings,
+                  onPressed: () {
+                    isGlobal
+                        ? globalSettingsCubit.setParameterValue(code, value)
+                        : activitySettingsCubit.setParameterValue(code, value);
+                  },
+                ),
+              );
+            },
+          );
+        },
+      );
+
+      parameterButtons.add(parameterButton);
+    }
+
+    return parameterButtons;
+  }
+}
diff --git a/lib/ui/parameters/parameter_painter.dart b/lib/common/ui/parameters/parameter_painter.dart
similarity index 94%
rename from lib/ui/parameters/parameter_painter.dart
rename to lib/common/ui/parameters/parameter_painter.dart
index e63459a..bd83f24 100644
--- a/lib/ui/parameters/parameter_painter.dart
+++ b/lib/common/ui/parameters/parameter_painter.dart
@@ -5,22 +5,22 @@ import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
 import 'package:jeweled/config/color_theme.dart';
-import 'package:jeweled/config/default_game_settings.dart';
+import 'package:jeweled/config/default_activity_settings.dart';
 import 'package:jeweled/config/default_global_settings.dart';
-import 'package:jeweled/models/settings/settings_game.dart';
+import 'package:jeweled/models/settings/settings_activity.dart';
 import 'package:jeweled/models/settings/settings_global.dart';
 
 class ParameterPainter extends CustomPainter {
   const ParameterPainter({
     required this.code,
     required this.value,
-    required this.gameSettings,
+    required this.activitySettings,
     required this.globalSettings,
   });
 
   final String code;
   final String value;
-  final GameSettings gameSettings;
+  final ActivitySettings activitySettings;
   final GlobalSettings globalSettings;
 
   @override
@@ -30,10 +30,10 @@ class ParameterPainter extends CustomPainter {
 
     // content
     switch (code) {
-      case DefaultGameSettings.parameterCodeColorsCount:
+      case DefaultActivitySettings.parameterCodeColorsCount:
         paintColorsCountParameterItem(canvas, canvasSize);
         break;
-      case DefaultGameSettings.parameterCodeBoardSize:
+      case DefaultActivitySettings.parameterCodeBoardSize:
         paintBoardSizeParameterItem(canvas, canvasSize);
         break;
       case DefaultGlobalSettings.parameterCodeColorsTheme:
@@ -92,16 +92,16 @@ class ParameterPainter extends CustomPainter {
     int gridWidth = 1;
 
     switch (value) {
-      case DefaultGameSettings.boardSizeValueSmall:
+      case DefaultActivitySettings.boardSizeValueSmall:
         gridWidth = 2;
         break;
-      case DefaultGameSettings.boardSizeValueMedium:
+      case DefaultActivitySettings.boardSizeValueMedium:
         gridWidth = 3;
         break;
-      case DefaultGameSettings.boardSizeValueLarge:
+      case DefaultActivitySettings.boardSizeValueLarge:
         gridWidth = 4;
         break;
-      case DefaultGameSettings.boardSizeValueExtraLarge:
+      case DefaultActivitySettings.boardSizeValueExtraLarge:
         gridWidth = 5;
         break;
       default:
diff --git a/lib/ui/parameters/parameter_widget.dart b/lib/common/ui/parameters/parameter_widget.dart
similarity index 81%
rename from lib/ui/parameters/parameter_widget.dart
rename to lib/common/ui/parameters/parameter_widget.dart
index 915121d..ed48652 100644
--- a/lib/ui/parameters/parameter_widget.dart
+++ b/lib/common/ui/parameters/parameter_widget.dart
@@ -1,12 +1,12 @@
 import 'package:flutter/material.dart';
-
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/config/default_game_settings.dart';
+import 'package:jeweled/common/ui/parameters/parameter_painter.dart';
+
+import 'package:jeweled/config/default_activity_settings.dart';
 import 'package:jeweled/config/default_global_settings.dart';
-import 'package:jeweled/models/settings/settings_game.dart';
+import 'package:jeweled/models/settings/settings_activity.dart';
 import 'package:jeweled/models/settings/settings_global.dart';
-import 'package:jeweled/ui/parameters/parameter_painter.dart';
 
 class ParameterWidget extends StatelessWidget {
   const ParameterWidget({
@@ -15,7 +15,7 @@ class ParameterWidget extends StatelessWidget {
     required this.value,
     required this.isSelected,
     required this.size,
-    required this.gameSettings,
+    required this.activitySettings,
     required this.globalSettings,
     required this.onPressed,
   });
@@ -24,7 +24,7 @@ class ParameterWidget extends StatelessWidget {
   final String value;
   final bool isSelected;
   final double size;
-  final GameSettings gameSettings;
+  final ActivitySettings activitySettings;
   final GlobalSettings globalSettings;
   final VoidCallback onPressed;
 
@@ -38,10 +38,10 @@ class ParameterWidget extends StatelessWidget {
     Widget content = const SizedBox.shrink();
 
     switch (code) {
-      case DefaultGameSettings.parameterCodeColorsCount:
+      case DefaultActivitySettings.parameterCodeColorsCount:
         content = getColorsCountParameterItem();
         break;
-      case DefaultGameSettings.parameterCodeBoardSize:
+      case DefaultActivitySettings.parameterCodeBoardSize:
         content = getBoardSizeParameterItem();
         break;
       case DefaultGlobalSettings.parameterCodeColorsTheme:
@@ -83,16 +83,16 @@ class ParameterWidget extends StatelessWidget {
     Color backgroundColor = Colors.grey;
 
     switch (value) {
-      case DefaultGameSettings.colorsCountValueLow:
+      case DefaultActivitySettings.colorsCountValueLow:
         backgroundColor = Colors.green;
         break;
-      case DefaultGameSettings.colorsCountValueMedium:
+      case DefaultActivitySettings.colorsCountValueMedium:
         backgroundColor = Colors.orange;
         break;
-      case DefaultGameSettings.colorsCountValueHigh:
+      case DefaultActivitySettings.colorsCountValueHigh:
         backgroundColor = Colors.red;
         break;
-      case DefaultGameSettings.colorsCountValueVeryHigh:
+      case DefaultActivitySettings.colorsCountValueVeryHigh:
         backgroundColor = Colors.purple;
         break;
       default:
@@ -108,7 +108,7 @@ class ParameterWidget extends StatelessWidget {
         painter: ParameterPainter(
           code: code,
           value: value,
-          gameSettings: gameSettings,
+          activitySettings: activitySettings,
           globalSettings: globalSettings,
         ),
         isComplex: true,
@@ -120,16 +120,16 @@ class ParameterWidget extends StatelessWidget {
     Color backgroundColor = Colors.grey;
 
     switch (value) {
-      case DefaultGameSettings.boardSizeValueSmall:
+      case DefaultActivitySettings.boardSizeValueSmall:
         backgroundColor = Colors.green;
         break;
-      case DefaultGameSettings.boardSizeValueMedium:
+      case DefaultActivitySettings.boardSizeValueMedium:
         backgroundColor = Colors.orange;
         break;
-      case DefaultGameSettings.boardSizeValueLarge:
+      case DefaultActivitySettings.boardSizeValueLarge:
         backgroundColor = Colors.red;
         break;
-      case DefaultGameSettings.boardSizeValueExtraLarge:
+      case DefaultActivitySettings.boardSizeValueExtraLarge:
         backgroundColor = Colors.purple;
         break;
       default:
@@ -145,7 +145,7 @@ class ParameterWidget extends StatelessWidget {
         painter: ParameterPainter(
           code: code,
           value: value,
-          gameSettings: gameSettings,
+          activitySettings: activitySettings,
           globalSettings: globalSettings,
         ),
         isComplex: true,
@@ -165,7 +165,7 @@ class ParameterWidget extends StatelessWidget {
         painter: ParameterPainter(
           code: code,
           value: value,
-          gameSettings: gameSettings,
+          activitySettings: activitySettings,
           globalSettings: globalSettings,
         ),
         isComplex: true,
@@ -185,7 +185,7 @@ class ParameterWidget extends StatelessWidget {
         painter: ParameterPainter(
           code: code,
           value: value,
-          gameSettings: gameSettings,
+          activitySettings: activitySettings,
           globalSettings: globalSettings,
         ),
         isComplex: true,
diff --git a/lib/ui/screens/page_about.dart b/lib/common/ui/screens/about.dart
similarity index 93%
rename from lib/ui/screens/page_about.dart
rename to lib/common/ui/screens/about.dart
index ab73e30..f7a14a9 100644
--- a/lib/ui/screens/page_about.dart
+++ b/lib/common/ui/screens/about.dart
@@ -1,8 +1,8 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-class PageAbout extends StatelessWidget {
-  const PageAbout({super.key});
+class ScreenAbout extends StatelessWidget {
+  const ScreenAbout({super.key});
 
   @override
   Widget build(BuildContext context) {
diff --git a/lib/common/ui/screens/activity.dart b/lib/common/ui/screens/activity.dart
new file mode 100644
index 0000000..5eca4ca
--- /dev/null
+++ b/lib/common/ui/screens/activity.dart
@@ -0,0 +1,18 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/common/config/activity_page.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_pages.dart';
+
+class ScreenActivity extends StatelessWidget {
+  const ScreenActivity({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<NavCubitPage, int>(
+      builder: (BuildContext context, int pageIndex) {
+        return ActivityPage.getWidget(pageIndex);
+      },
+    );
+  }
+}
diff --git a/lib/ui/screens/page_settings.dart b/lib/common/ui/screens/settings.dart
similarity index 87%
rename from lib/ui/screens/page_settings.dart
rename to lib/common/ui/screens/settings.dart
index 50964ef..7981b1c 100644
--- a/lib/ui/screens/page_settings.dart
+++ b/lib/common/ui/screens/settings.dart
@@ -1,8 +1,8 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-class PageSettings extends StatelessWidget {
-  const PageSettings({super.key});
+class ScreenSettings extends StatelessWidget {
+  const ScreenSettings({super.key});
 
   @override
   Widget build(BuildContext context) {
diff --git a/lib/config/application_config.dart b/lib/config/application_config.dart
new file mode 100644
index 0000000..8c9cd93
--- /dev/null
+++ b/lib/config/application_config.dart
@@ -0,0 +1,3 @@
+class ApplicationConfig {
+  static const String appTitle = 'Jeweled';
+}
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_activity_settings.dart
similarity index 91%
rename from lib/config/default_game_settings.dart
rename to lib/config/default_activity_settings.dart
index ae24687..5439a6c 100644
--- a/lib/config/default_game_settings.dart
+++ b/lib/config/default_activity_settings.dart
@@ -1,6 +1,6 @@
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-class DefaultGameSettings {
+class DefaultActivitySettings {
   // available game parameters codes
   static const String parameterCodeBoardSize = 'boardSize';
   static const String parameterCodeColorsCount = 'colorsCount';
@@ -41,9 +41,9 @@ class DefaultGameSettings {
   static List<String> getAvailableValues(String parameterCode) {
     switch (parameterCode) {
       case parameterCodeBoardSize:
-        return DefaultGameSettings.allowedBoardSizeValues;
+        return DefaultActivitySettings.allowedBoardSizeValues;
       case parameterCodeColorsCount:
-        return DefaultGameSettings.allowedColorsCountValues;
+        return DefaultActivitySettings.allowedColorsCountValues;
     }
 
     printlog('Did not find any available value for game parameter "$parameterCode".');
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
deleted file mode 100644
index af47718..0000000
--- a/lib/config/menu.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
-
-import 'package:jeweled/ui/screens/page_game.dart';
-import 'package:jeweled/ui/screens/page_settings.dart';
-import 'package:jeweled/ui/screens/page_about.dart';
-
-class MenuItem {
-  final Icon icon;
-  final Widget page;
-
-  const MenuItem({
-    required this.icon,
-    required this.page,
-  });
-}
-
-class Menu {
-  static const indexGame = 0;
-  static const menuItemGame = MenuItem(
-    icon: Icon(UniconsLine.home),
-    page: PageGame(),
-  );
-
-  static const indexSettings = 1;
-  static const menuItemSettings = MenuItem(
-    icon: Icon(UniconsLine.setting),
-    page: PageSettings(),
-  );
-
-  static const indexAbout = 2;
-  static const menuItemAbout = MenuItem(
-    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;
-}
diff --git a/lib/cubit/activity/activity_cubit.dart b/lib/cubit/activity/activity_cubit.dart
new file mode 100644
index 0000000..55b5ba4
--- /dev/null
+++ b/lib/cubit/activity/activity_cubit.dart
@@ -0,0 +1,188 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/config/default_activity_settings.dart';
+import 'package:jeweled/models/activity/cell_location.dart';
+import 'package:jeweled/models/activity/activity.dart';
+import 'package:jeweled/models/settings/settings_activity.dart';
+import 'package:jeweled/models/settings/settings_global.dart';
+
+part 'activity_state.dart';
+
+class ActivityCubit extends HydratedCubit<ActivityState> {
+  ActivityCubit()
+      : super(ActivityState(
+          currentActivity: Activity.createEmpty(),
+        ));
+
+  void updateState(Activity activity) {
+    emit(ActivityState(
+      currentActivity: activity,
+    ));
+  }
+
+  void refresh() {
+    final Activity activity = Activity(
+      // Settings
+      activitySettings: state.currentActivity.activitySettings,
+      globalSettings: state.currentActivity.globalSettings,
+      // State
+      isRunning: state.currentActivity.isRunning,
+      isStarted: state.currentActivity.isStarted,
+      isFinished: state.currentActivity.isFinished,
+      animationInProgress: state.currentActivity.animationInProgress,
+      // Base data
+      board: state.currentActivity.board,
+      // Game data
+      shuffledColors: state.currentActivity.shuffledColors,
+      availableBlocksCount: state.currentActivity.availableBlocksCount,
+      score: state.currentActivity.score,
+      movesCount: state.currentActivity.movesCount,
+    );
+    // game.dump();
+
+    updateState(activity);
+  }
+
+  void startNewActivity({
+    required ActivitySettings activitySettings,
+    required GlobalSettings globalSettings,
+  }) {
+    final Activity newActivity = Activity.createNew(
+      activitySettings: activitySettings,
+      globalSettings: globalSettings,
+    );
+
+    newActivity.dump();
+
+    updateState(newActivity);
+    postAnimate();
+  }
+
+  void quitActivity() {
+    state.currentActivity.isRunning = false;
+    refresh();
+  }
+
+  void resumeSavedActivity() {
+    state.currentActivity.isRunning = true;
+    refresh();
+  }
+
+  void deleteSavedActivity() {
+    state.currentActivity.isRunning = false;
+    state.currentActivity.isFinished = true;
+    refresh();
+  }
+
+  void updateCellValue(CellLocation locationToUpdate, int? value) {
+    state.currentActivity.updateCellValue(locationToUpdate, value);
+    refresh();
+  }
+
+  void increaseMovesCount() {
+    state.currentActivity.isStarted = true;
+    state.currentActivity.increaseMovesCount();
+    refresh();
+  }
+
+  void increaseScore(int increment) {
+    state.currentActivity.increaseScore(increment);
+    refresh();
+  }
+
+  void updateAvailableBlocksCount() {
+    state.currentActivity.updateAvailableBlocksCount();
+    refresh();
+  }
+
+  void updateGameIsFinished(bool gameIsFinished) {
+    state.currentActivity.isFinished = gameIsFinished;
+    refresh();
+  }
+
+  void shuffleColors(final String colorsTheme) {
+    state.currentActivity.shuffleColorsAgain(colorsTheme);
+  }
+
+  moveCellsDown() {
+    final Activity currentActivity = state.currentActivity;
+
+    final int boardSizeHorizontal = currentActivity.activitySettings.boardSizeValue;
+    final int boardSizeVertical = currentActivity.activitySettings.boardSizeValue;
+
+    for (int row = 0; row < boardSizeVertical; row++) {
+      for (int col = 0; col < boardSizeHorizontal; col++) {
+        // empty cell?
+        if (currentActivity.getCellValue(CellLocation.go(row, col)) == null) {
+          // move cells down
+          for (int r = row; r > 0; r--) {
+            updateCellValue(CellLocation.go(r, col),
+                currentActivity.getCellValue(CellLocation.go(r - 1, col)));
+          }
+          // fill top empty cell
+          updateCellValue(CellLocation.go(0, col),
+              currentActivity.getFillValue(CellLocation.go(row, col)));
+        }
+      }
+    }
+  }
+
+  void deleteBlock(List<CellLocation> block) {
+    // Sort cells from top to bottom
+    block.sort((cell1, cell2) => cell1.row.compareTo(cell2.row));
+    // Delete all cells
+    for (CellLocation blockItemToDelete in block) {
+      updateCellValue(blockItemToDelete, null);
+    }
+  }
+
+  int getScoreFromBlock(int blockSize) {
+    return 3 * (blockSize - 2);
+  }
+
+  List<CellLocation> tapOnCell(CellLocation tappedCellLocation) {
+    final Activity currentActivity = state.currentActivity;
+
+    final int? cellValue = currentActivity.getCellValue(tappedCellLocation);
+
+    if (cellValue != null) {
+      List<CellLocation> blockCells = currentActivity.getSiblingCells(tappedCellLocation, []);
+      if (blockCells.length >= DefaultActivitySettings.blockMinimumCellsCount) {
+        deleteBlock(blockCells);
+        increaseMovesCount();
+        increaseScore(getScoreFromBlock(blockCells.length));
+        return blockCells;
+      }
+    }
+
+    return [];
+  }
+
+  void postAnimate() {
+    moveCellsDown();
+    updateAvailableBlocksCount();
+    refresh();
+
+    if (!state.currentActivity.hasAtLeastOneAvailableBlock()) {
+      printlog('no more block found. finish game.');
+      updateGameIsFinished(true);
+    }
+  }
+
+  @override
+  ActivityState? fromJson(Map<String, dynamic> json) {
+    final Activity currentActivity = json['currentActivity'] as Activity;
+
+    return ActivityState(
+      currentActivity: currentActivity,
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(ActivityState state) {
+    return <String, dynamic>{
+      'currentActivity': state.currentActivity.toJson(),
+    };
+  }
+}
diff --git a/lib/cubit/activity/activity_state.dart b/lib/cubit/activity/activity_state.dart
new file mode 100644
index 0000000..887b45e
--- /dev/null
+++ b/lib/cubit/activity/activity_state.dart
@@ -0,0 +1,15 @@
+part of 'activity_cubit.dart';
+
+@immutable
+class ActivityState extends Equatable {
+  const ActivityState({
+    required this.currentActivity,
+  });
+
+  final Activity currentActivity;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        currentActivity,
+      ];
+}
diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart
deleted file mode 100644
index 3bddd1a..0000000
--- a/lib/cubit/game_cubit.dart
+++ /dev/null
@@ -1,188 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
-
-import 'package:jeweled/config/default_game_settings.dart';
-import 'package:jeweled/models/game/cell_location.dart';
-import 'package:jeweled/models/game/game.dart';
-import 'package:jeweled/models/settings/settings_game.dart';
-import 'package:jeweled/models/settings/settings_global.dart';
-
-part 'game_state.dart';
-
-class GameCubit extends HydratedCubit<GameState> {
-  GameCubit()
-      : super(GameState(
-          currentGame: Game.createEmpty(),
-        ));
-
-  void updateState(Game game) {
-    emit(GameState(
-      currentGame: game,
-    ));
-  }
-
-  void refresh() {
-    final Game game = Game(
-      // Settings
-      gameSettings: state.currentGame.gameSettings,
-      globalSettings: state.currentGame.globalSettings,
-      // State
-      isRunning: state.currentGame.isRunning,
-      isStarted: state.currentGame.isStarted,
-      isFinished: state.currentGame.isFinished,
-      animationInProgress: state.currentGame.animationInProgress,
-      // Base data
-      board: state.currentGame.board,
-      // Game data
-      shuffledColors: state.currentGame.shuffledColors,
-      availableBlocksCount: state.currentGame.availableBlocksCount,
-      score: state.currentGame.score,
-      movesCount: state.currentGame.movesCount,
-    );
-    // game.dump();
-
-    updateState(game);
-  }
-
-  void startNewGame({
-    required GameSettings gameSettings,
-    required GlobalSettings globalSettings,
-  }) {
-    final Game newGame = Game.createNew(
-      gameSettings: gameSettings,
-      globalSettings: globalSettings,
-    );
-
-    newGame.dump();
-
-    updateState(newGame);
-    postAnimate();
-  }
-
-  void quitGame() {
-    state.currentGame.isRunning = false;
-    refresh();
-  }
-
-  void resumeSavedGame() {
-    state.currentGame.isRunning = true;
-    refresh();
-  }
-
-  void deleteSavedGame() {
-    state.currentGame.isRunning = false;
-    state.currentGame.isFinished = true;
-    refresh();
-  }
-
-  void updateCellValue(CellLocation locationToUpdate, int? value) {
-    state.currentGame.updateCellValue(locationToUpdate, value);
-    refresh();
-  }
-
-  void increaseMovesCount() {
-    state.currentGame.isStarted = true;
-    state.currentGame.increaseMovesCount();
-    refresh();
-  }
-
-  void increaseScore(int increment) {
-    state.currentGame.increaseScore(increment);
-    refresh();
-  }
-
-  void updateAvailableBlocksCount() {
-    state.currentGame.updateAvailableBlocksCount();
-    refresh();
-  }
-
-  void updateGameIsFinished(bool gameIsFinished) {
-    state.currentGame.isFinished = gameIsFinished;
-    refresh();
-  }
-
-  void shuffleColors(final String colorsTheme) {
-    state.currentGame.shuffleColorsAgain(colorsTheme);
-  }
-
-  moveCellsDown() {
-    final Game currentGame = state.currentGame;
-
-    final int boardSizeHorizontal = currentGame.gameSettings.boardSizeValue;
-    final int boardSizeVertical = currentGame.gameSettings.boardSizeValue;
-
-    for (int row = 0; row < boardSizeVertical; row++) {
-      for (int col = 0; col < boardSizeHorizontal; col++) {
-        // empty cell?
-        if (currentGame.getCellValue(CellLocation.go(row, col)) == null) {
-          // move cells down
-          for (int r = row; r > 0; r--) {
-            updateCellValue(CellLocation.go(r, col),
-                currentGame.getCellValue(CellLocation.go(r - 1, col)));
-          }
-          // fill top empty cell
-          updateCellValue(
-              CellLocation.go(0, col), currentGame.getFillValue(CellLocation.go(row, col)));
-        }
-      }
-    }
-  }
-
-  void deleteBlock(List<CellLocation> block) {
-    // Sort cells from top to bottom
-    block.sort((cell1, cell2) => cell1.row.compareTo(cell2.row));
-    // Delete all cells
-    for (CellLocation blockItemToDelete in block) {
-      updateCellValue(blockItemToDelete, null);
-    }
-  }
-
-  int getScoreFromBlock(int blockSize) {
-    return 3 * (blockSize - 2);
-  }
-
-  List<CellLocation> tapOnCell(CellLocation tappedCellLocation) {
-    final Game currentGame = state.currentGame;
-
-    final int? cellValue = currentGame.getCellValue(tappedCellLocation);
-
-    if (cellValue != null) {
-      List<CellLocation> blockCells = currentGame.getSiblingCells(tappedCellLocation, []);
-      if (blockCells.length >= DefaultGameSettings.blockMinimumCellsCount) {
-        deleteBlock(blockCells);
-        increaseMovesCount();
-        increaseScore(getScoreFromBlock(blockCells.length));
-        return blockCells;
-      }
-    }
-
-    return [];
-  }
-
-  void postAnimate() {
-    moveCellsDown();
-    updateAvailableBlocksCount();
-    refresh();
-
-    if (!state.currentGame.hasAtLeastOneAvailableBlock()) {
-      printlog('no more block found. finish game.');
-      updateGameIsFinished(true);
-    }
-  }
-
-  @override
-  GameState? fromJson(Map<String, dynamic> json) {
-    final Game currentGame = json['currentGame'] as Game;
-
-    return GameState(
-      currentGame: currentGame,
-    );
-  }
-
-  @override
-  Map<String, dynamic>? toJson(GameState state) {
-    return <String, dynamic>{
-      'currentGame': state.currentGame.toJson(),
-    };
-  }
-}
diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart
deleted file mode 100644
index 00e2116..0000000
--- a/lib/cubit/game_state.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-part of 'game_cubit.dart';
-
-@immutable
-class GameState extends Equatable {
-  const GameState({
-    required this.currentGame,
-  });
-
-  final Game currentGame;
-
-  @override
-  List<dynamic> get props => <dynamic>[
-        currentGame,
-      ];
-}
diff --git a/lib/cubit/nav_cubit.dart b/lib/cubit/nav_cubit.dart
deleted file mode 100644
index cbccfa8..0000000
--- a/lib/cubit/nav_cubit.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:flutter_custom_toolbox/flutter_toolbox.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 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};
-  }
-}
diff --git a/lib/cubit/settings/settings_activity_cubit.dart b/lib/cubit/settings/settings_activity_cubit.dart
new file mode 100644
index 0000000..338113b
--- /dev/null
+++ b/lib/cubit/settings/settings_activity_cubit.dart
@@ -0,0 +1,73 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/config/default_activity_settings.dart';
+import 'package:jeweled/models/settings/settings_activity.dart';
+
+part 'settings_activity_state.dart';
+
+class ActivitySettingsCubit extends HydratedCubit<ActivitySettingsState> {
+  ActivitySettingsCubit()
+      : super(ActivitySettingsState(settings: ActivitySettings.createDefault()));
+
+  void setValues({
+    String? boardSize,
+    String? colorsCount,
+  }) {
+    emit(
+      ActivitySettingsState(
+        settings: ActivitySettings(
+          boardSize: boardSize ?? state.settings.boardSize,
+          colorsCount: colorsCount ?? state.settings.colorsCount,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultActivitySettings.parameterCodeBoardSize:
+        return ActivitySettings.getBoardSizeValueFromUnsafe(state.settings.boardSize);
+      case DefaultActivitySettings.parameterCodeColorsCount:
+        return ActivitySettings.getColorsCountValueFromUnsafe(state.settings.colorsCount);
+    }
+
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String boardSize = code == DefaultActivitySettings.parameterCodeBoardSize
+        ? value
+        : getParameterValue(DefaultActivitySettings.parameterCodeBoardSize);
+    final String colorsCount = code == DefaultActivitySettings.parameterCodeColorsCount
+        ? value
+        : getParameterValue(DefaultActivitySettings.parameterCodeColorsCount);
+
+    setValues(
+      boardSize: boardSize,
+      colorsCount: colorsCount,
+    );
+  }
+
+  @override
+  ActivitySettingsState? fromJson(Map<String, dynamic> json) {
+    final String boardSize = json[DefaultActivitySettings.parameterCodeBoardSize] as String;
+    final String colorsCount =
+        json[DefaultActivitySettings.parameterCodeColorsCount] as String;
+
+    return ActivitySettingsState(
+      settings: ActivitySettings(
+        boardSize: boardSize,
+        colorsCount: colorsCount,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(ActivitySettingsState state) {
+    return <String, dynamic>{
+      DefaultActivitySettings.parameterCodeBoardSize: state.settings.boardSize,
+      DefaultActivitySettings.parameterCodeColorsCount: state.settings.colorsCount,
+    };
+  }
+}
diff --git a/lib/cubit/settings/settings_activity_state.dart b/lib/cubit/settings/settings_activity_state.dart
new file mode 100644
index 0000000..2b2de42
--- /dev/null
+++ b/lib/cubit/settings/settings_activity_state.dart
@@ -0,0 +1,15 @@
+part of 'settings_activity_cubit.dart';
+
+@immutable
+class ActivitySettingsState extends Equatable {
+  const ActivitySettingsState({
+    required this.settings,
+  });
+
+  final ActivitySettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+}
diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings/settings_global_cubit.dart
similarity index 100%
rename from lib/cubit/settings_global_cubit.dart
rename to lib/cubit/settings/settings_global_cubit.dart
diff --git a/lib/cubit/settings_global_state.dart b/lib/cubit/settings/settings_global_state.dart
similarity index 100%
rename from lib/cubit/settings_global_state.dart
rename to lib/cubit/settings/settings_global_state.dart
diff --git a/lib/cubit/settings_game_cubit.dart b/lib/cubit/settings_game_cubit.dart
deleted file mode 100644
index 2aee5b7..0000000
--- a/lib/cubit/settings_game_cubit.dart
+++ /dev/null
@@ -1,71 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
-
-import 'package:jeweled/config/default_game_settings.dart';
-import 'package:jeweled/models/settings/settings_game.dart';
-
-part 'settings_game_state.dart';
-
-class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
-  GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault()));
-
-  void setValues({
-    String? boardSize,
-    String? colorsCount,
-  }) {
-    emit(
-      GameSettingsState(
-        settings: GameSettings(
-          boardSize: boardSize ?? state.settings.boardSize,
-          colorsCount: colorsCount ?? state.settings.colorsCount,
-        ),
-      ),
-    );
-  }
-
-  String getParameterValue(String code) {
-    switch (code) {
-      case DefaultGameSettings.parameterCodeBoardSize:
-        return GameSettings.getBoardSizeValueFromUnsafe(state.settings.boardSize);
-      case DefaultGameSettings.parameterCodeColorsCount:
-        return GameSettings.getColorsCountValueFromUnsafe(state.settings.colorsCount);
-    }
-
-    return '';
-  }
-
-  void setParameterValue(String code, String value) {
-    final String boardSize = code == DefaultGameSettings.parameterCodeBoardSize
-        ? value
-        : getParameterValue(DefaultGameSettings.parameterCodeBoardSize);
-    final String colorsCount = code == DefaultGameSettings.parameterCodeColorsCount
-        ? value
-        : getParameterValue(DefaultGameSettings.parameterCodeColorsCount);
-
-    setValues(
-      boardSize: boardSize,
-      colorsCount: colorsCount,
-    );
-  }
-
-  @override
-  GameSettingsState? fromJson(Map<String, dynamic> json) {
-    final String boardSize = json[DefaultGameSettings.parameterCodeBoardSize] as String;
-    final String colorsCount = json[DefaultGameSettings.parameterCodeColorsCount] as String;
-
-    return GameSettingsState(
-      settings: GameSettings(
-        boardSize: boardSize,
-        colorsCount: colorsCount,
-      ),
-    );
-  }
-
-  @override
-  Map<String, dynamic>? toJson(GameSettingsState state) {
-    return <String, dynamic>{
-      DefaultGameSettings.parameterCodeBoardSize: state.settings.boardSize,
-      DefaultGameSettings.parameterCodeColorsCount: state.settings.colorsCount,
-    };
-  }
-}
diff --git a/lib/cubit/settings_game_state.dart b/lib/cubit/settings_game_state.dart
deleted file mode 100644
index 5acd85b..0000000
--- a/lib/cubit/settings_game_state.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-part of 'settings_game_cubit.dart';
-
-@immutable
-class GameSettingsState extends Equatable {
-  const GameSettingsState({
-    required this.settings,
-  });
-
-  final GameSettings settings;
-
-  @override
-  List<dynamic> get props => <dynamic>[
-        settings,
-      ];
-}
diff --git a/lib/main.dart b/lib/main.dart
index 9595cd3..76cf91c 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -4,10 +4,13 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.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/common/cubit/nav/nav_cubit_pages.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_screens.dart';
+
+import 'package:jeweled/config/application_config.dart';
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
+import 'package:jeweled/cubit/settings/settings_activity_cubit.dart';
+import 'package:jeweled/cubit/settings/settings_global_cubit.dart';
 import 'package:jeweled/ui/skeleton.dart';
 
 void main() async {
@@ -45,17 +48,30 @@ class MyApp extends StatelessWidget {
 
     return MultiBlocProvider(
       providers: [
-        BlocProvider<NavCubit>(create: (context) => NavCubit()),
+        // default providers
+        BlocProvider<NavCubitPage>(
+          create: (context) => NavCubitPage(),
+        ),
+        BlocProvider<NavCubitScreen>(
+          create: (context) => NavCubitScreen(),
+        ),
         BlocProvider<ApplicationThemeModeCubit>(
-            create: (context) => ApplicationThemeModeCubit()),
-        BlocProvider<GameCubit>(create: (context) => GameCubit()),
-        BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()),
-        BlocProvider<GameSettingsCubit>(create: (context) => GameSettingsCubit()),
+          create: (context) => ApplicationThemeModeCubit(),
+        ),
+        BlocProvider<ActivityCubit>(
+          create: (context) => ActivityCubit(),
+        ),
+        BlocProvider<GlobalSettingsCubit>(
+          create: (context) => GlobalSettingsCubit(),
+        ),
+        BlocProvider<ActivitySettingsCubit>(
+          create: (context) => ActivitySettingsCubit(),
+        ),
       ],
       child: BlocBuilder<ApplicationThemeModeCubit, ApplicationThemeModeState>(
         builder: (BuildContext context, ApplicationThemeModeState state) {
           return MaterialApp(
-            title: 'Jeweled',
+            title: ApplicationConfig.appTitle,
             home: const SkeletonScreen(),
 
             // Theme stuff
diff --git a/lib/models/game/game.dart b/lib/models/activity/activity.dart
similarity index 81%
rename from lib/models/game/game.dart
rename to lib/models/activity/activity.dart
index 26f71be..c955f3a 100644
--- a/lib/models/game/game.dart
+++ b/lib/models/activity/activity.dart
@@ -4,16 +4,16 @@ import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
 import 'package:jeweled/config/color_theme.dart';
 import 'package:jeweled/config/default_global_settings.dart';
-import 'package:jeweled/models/game/board.dart';
-import 'package:jeweled/models/game/cell.dart';
-import 'package:jeweled/models/game/cell_location.dart';
-import 'package:jeweled/models/settings/settings_game.dart';
+import 'package:jeweled/models/activity/board.dart';
+import 'package:jeweled/models/activity/cell.dart';
+import 'package:jeweled/models/activity/cell_location.dart';
+import 'package:jeweled/models/settings/settings_activity.dart';
 import 'package:jeweled/models/settings/settings_global.dart';
 
-class Game {
-  Game({
+class Activity {
+  Activity({
     // Settings
-    required this.gameSettings,
+    required this.activitySettings,
     required this.globalSettings,
 
     // State
@@ -33,7 +33,7 @@ class Game {
   });
 
   // Settings
-  final GameSettings gameSettings;
+  final ActivitySettings activitySettings;
   final GlobalSettings globalSettings;
 
   // State
@@ -51,10 +51,10 @@ class Game {
   int score;
   int movesCount;
 
-  factory Game.createEmpty() {
-    return Game(
+  factory Activity.createEmpty() {
+    return Activity(
       // Settings
-      gameSettings: GameSettings.createDefault(),
+      activitySettings: ActivitySettings.createDefault(),
       globalSettings: GlobalSettings.createDefault(),
       // Base data
       board: Board.createEmpty(),
@@ -63,21 +63,22 @@ class Game {
     );
   }
 
-  factory Game.createNew({
-    GameSettings? gameSettings,
+  factory Activity.createNew({
+    ActivitySettings? activitySettings,
     GlobalSettings? globalSettings,
   }) {
-    final GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
+    final ActivitySettings newActivitySettings =
+        activitySettings ?? ActivitySettings.createDefault();
     final GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
 
-    return Game(
+    return Activity(
       // Settings
-      gameSettings: newGameSettings,
+      activitySettings: newActivitySettings,
       globalSettings: newGlobalSettings,
       // State
       isRunning: true,
       // Base data
-      board: Board.createRandom(newGameSettings),
+      board: Board.createRandom(newActivitySettings),
       // Game data
       shuffledColors: shuffleColors(newGlobalSettings.colorsTheme),
     );
@@ -132,8 +133,8 @@ class Game {
     final CellLocation referenceCellLocation,
     List<CellLocation> siblingCells,
   ) {
-    final int boardSizeHorizontal = gameSettings.boardSizeValue;
-    final int boardSizeVertical = gameSettings.boardSizeValue;
+    final int boardSizeHorizontal = activitySettings.boardSizeValue;
+    final int boardSizeVertical = activitySettings.boardSizeValue;
 
     final int? referenceValue = getCellValue(referenceCellLocation);
 
@@ -168,16 +169,16 @@ class Game {
     return siblingCells;
   }
 
-  List<List<CellLocation>> getAvailableBlocks(final Game game) {
-    final int boardSizeHorizontal = game.gameSettings.boardSizeValue;
-    final int boardSizeVertical = game.gameSettings.boardSizeValue;
+  List<List<CellLocation>> getAvailableBlocks(final Activity activity) {
+    final int boardSizeHorizontal = activity.activitySettings.boardSizeValue;
+    final int boardSizeVertical = activity.activitySettings.boardSizeValue;
 
     final List<List<CellLocation>> blocks = [];
 
     for (int row = 0; row < boardSizeVertical; row++) {
       for (int col = 0; col < boardSizeHorizontal; col++) {
         final CellLocation cellLocation = CellLocation.go(row, col);
-        if (game.getCellValue(cellLocation) != null) {
+        if (activity.getCellValue(cellLocation) != null) {
           // if current cell not already in a found block
           bool alreadyFound = false;
 
@@ -189,7 +190,7 @@ class Game {
             }
           }
           if (!alreadyFound) {
-            final List<CellLocation> block = game.getSiblingCells(cellLocation, []);
+            final List<CellLocation> block = activity.getSiblingCells(cellLocation, []);
             if (block.length >= 3) {
               blocks.add(block);
             }
@@ -202,8 +203,8 @@ class Game {
   }
 
   bool hasAtLeastOneAvailableBlock() {
-    final int boardSizeHorizontal = gameSettings.boardSizeValue;
-    final int boardSizeVertical = gameSettings.boardSizeValue;
+    final int boardSizeHorizontal = activitySettings.boardSizeValue;
+    final int boardSizeVertical = activitySettings.boardSizeValue;
 
     for (int row = 0; row < boardSizeVertical; row++) {
       for (int col = 0; col < boardSizeHorizontal; col++) {
@@ -223,7 +224,7 @@ class Game {
   }
 
   bool isInBoard(CellLocation cell) {
-    final int boardSize = gameSettings.boardSizeValue;
+    final int boardSize = activitySettings.boardSizeValue;
 
     if (cell.row > 0 && cell.row < boardSize && cell.col > 0 && cell.col < boardSize) {
       return true;
@@ -239,14 +240,14 @@ class Game {
     final List<int> values = [];
 
     // All eligible values (twice)
-    final int maxValue = gameSettings.colorsCountValue;
+    final int maxValue = activitySettings.colorsCountValue;
     for (int i = 1; i <= maxValue; i++) {
       values.add(i);
       values.add(i);
     }
 
     // Add values of current col (twice)
-    for (int r = 0; r <= gameSettings.boardSizeValue; r++) {
+    for (int r = 0; r <= activitySettings.boardSizeValue; r++) {
       if (isInBoard(CellLocation.go(r, col))) {
         final int? value = getCellValue(CellLocation.go(r, col));
         if (value != null) {
@@ -259,12 +260,12 @@ class Game {
     // Add values of sibling cols (twice for top rows)
     for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
       final int c = col + deltaCol;
-      for (int r = 0; r < gameSettings.boardSizeValue; r++) {
+      for (int r = 0; r < activitySettings.boardSizeValue; r++) {
         if (isInBoard(CellLocation.go(r, c))) {
           final int? value = getCellValue(CellLocation.go(r, c));
           if (value != null) {
             values.add(value);
-            if (row < gameSettings.boardSizeValue / 3) {
+            if (row < activitySettings.boardSizeValue / 3) {
               values.add(value);
             }
           }
@@ -294,9 +295,9 @@ class Game {
     printlog('');
     printlog('## Current game dump:');
     printlog('');
-    printlog('$Game:');
+    printlog('$Activity:');
     printlog('  Settings');
-    gameSettings.dump();
+    activitySettings.dump();
     globalSettings.dump();
     printlog('  State');
     printlog('    isRunning: $isRunning');
@@ -315,13 +316,13 @@ class Game {
 
   @override
   String toString() {
-    return '$Game(${toJson()})';
+    return '$Activity(${toJson()})';
   }
 
   Map<String, dynamic>? toJson() {
     return <String, dynamic>{
       // Settings
-      'gameSettings': gameSettings.toJson(),
+      'activitySettings': activitySettings.toJson(),
       'globalSettings': globalSettings.toJson(),
       // State
       'isRunning': isRunning,
diff --git a/lib/models/game/board.dart b/lib/models/activity/board.dart
similarity index 77%
rename from lib/models/game/board.dart
rename to lib/models/activity/board.dart
index bc3dfc0..af933d1 100644
--- a/lib/models/game/board.dart
+++ b/lib/models/activity/board.dart
@@ -2,8 +2,8 @@ import 'dart:math';
 
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/models/game/cell.dart';
-import 'package:jeweled/models/settings/settings_game.dart';
+import 'package:jeweled/models/activity/cell.dart';
+import 'package:jeweled/models/settings/settings_activity.dart';
 
 class Board {
   final List<List<Cell>> cells;
@@ -16,10 +16,10 @@ class Board {
     return Board(cells: []);
   }
 
-  factory Board.createRandom(GameSettings gameSettings) {
-    final int boardSizeHorizontal = gameSettings.boardSizeValue;
-    final int boardSizeVertical = gameSettings.boardSizeValue;
-    final int maxValue = gameSettings.colorsCountValue;
+  factory Board.createRandom(ActivitySettings activitySettings) {
+    final int boardSizeHorizontal = activitySettings.boardSizeValue;
+    final int boardSizeVertical = activitySettings.boardSizeValue;
+    final int maxValue = activitySettings.colorsCountValue;
 
     final rand = Random();
 
diff --git a/lib/models/game/cell.dart b/lib/models/activity/cell.dart
similarity index 100%
rename from lib/models/game/cell.dart
rename to lib/models/activity/cell.dart
diff --git a/lib/models/game/cell_location.dart b/lib/models/activity/cell_location.dart
similarity index 100%
rename from lib/models/game/cell_location.dart
rename to lib/models/activity/cell_location.dart
diff --git a/lib/models/settings/settings_activity.dart b/lib/models/settings/settings_activity.dart
new file mode 100644
index 0000000..106c7a1
--- /dev/null
+++ b/lib/models/settings/settings_activity.dart
@@ -0,0 +1,59 @@
+import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
+
+import 'package:jeweled/config/default_activity_settings.dart';
+
+class ActivitySettings {
+  final String boardSize;
+  final String colorsCount;
+
+  ActivitySettings({
+    required this.boardSize,
+    required this.colorsCount,
+  });
+
+  // Getters to convert String to int
+  int get boardSizeValue => int.parse(boardSize);
+  int get colorsCountValue => int.parse(colorsCount);
+
+  static String getBoardSizeValueFromUnsafe(String size) {
+    if (DefaultActivitySettings.allowedBoardSizeValues.contains(size)) {
+      return size;
+    }
+
+    return DefaultActivitySettings.defaultBoardSizeValue;
+  }
+
+  static String getColorsCountValueFromUnsafe(String colorsCount) {
+    if (DefaultActivitySettings.allowedColorsCountValues.contains(colorsCount)) {
+      return colorsCount;
+    }
+
+    return DefaultActivitySettings.defaultColorsCountValue;
+  }
+
+  factory ActivitySettings.createDefault() {
+    return ActivitySettings(
+      boardSize: DefaultActivitySettings.defaultBoardSizeValue,
+      colorsCount: DefaultActivitySettings.defaultColorsCountValue,
+    );
+  }
+
+  void dump() {
+    printlog('$ActivitySettings:');
+    printlog('  ${DefaultActivitySettings.parameterCodeBoardSize}: $boardSize');
+    printlog('  ${DefaultActivitySettings.parameterCodeColorsCount}: $colorsCount');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$ActivitySettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultActivitySettings.parameterCodeBoardSize: boardSize,
+      DefaultActivitySettings.parameterCodeColorsCount: colorsCount,
+    };
+  }
+}
diff --git a/lib/models/settings/settings_game.dart b/lib/models/settings/settings_game.dart
deleted file mode 100644
index c733c1a..0000000
--- a/lib/models/settings/settings_game.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
-
-import 'package:jeweled/config/default_game_settings.dart';
-
-class GameSettings {
-  final String boardSize;
-  final String colorsCount;
-
-  GameSettings({
-    required this.boardSize,
-    required this.colorsCount,
-  });
-
-  // Getters to convert String to int
-  int get boardSizeValue => int.parse(boardSize);
-  int get colorsCountValue => int.parse(colorsCount);
-
-  static String getBoardSizeValueFromUnsafe(String size) {
-    if (DefaultGameSettings.allowedBoardSizeValues.contains(size)) {
-      return size;
-    }
-
-    return DefaultGameSettings.defaultBoardSizeValue;
-  }
-
-  static String getColorsCountValueFromUnsafe(String colorsCount) {
-    if (DefaultGameSettings.allowedColorsCountValues.contains(colorsCount)) {
-      return colorsCount;
-    }
-
-    return DefaultGameSettings.defaultColorsCountValue;
-  }
-
-  factory GameSettings.createDefault() {
-    return GameSettings(
-      boardSize: DefaultGameSettings.defaultBoardSizeValue,
-      colorsCount: DefaultGameSettings.defaultColorsCountValue,
-    );
-  }
-
-  void dump() {
-    printlog('$GameSettings:');
-    printlog('  ${DefaultGameSettings.parameterCodeBoardSize}: $boardSize');
-    printlog('  ${DefaultGameSettings.parameterCodeColorsCount}: $colorsCount');
-    printlog('');
-  }
-
-  @override
-  String toString() {
-    return '$GameSettings(${toJson()})';
-  }
-
-  Map<String, dynamic>? toJson() {
-    return <String, dynamic>{
-      DefaultGameSettings.parameterCodeBoardSize: boardSize,
-      DefaultGameSettings.parameterCodeColorsCount: colorsCount,
-    };
-  }
-}
diff --git a/lib/ui/game/game_top.dart b/lib/ui/game/game_top.dart
index 920171a..6fc6299 100644
--- a/lib/ui/game/game_top.dart
+++ b/lib/ui/game/game_top.dart
@@ -1,8 +1,8 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/cubit/game_cubit.dart';
-import 'package:jeweled/models/game/game.dart';
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
+import 'package:jeweled/models/activity/activity.dart';
 import 'package:jeweled/ui/widgets/indicators/indicator_available_blocks.dart';
 import 'package:jeweled/ui/widgets/indicators/indicator_moves_count.dart';
 import 'package:jeweled/ui/widgets/indicators/indicator_score.dart';
@@ -13,24 +13,24 @@ class GameTopWidget extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        final Game currentGame = gameState.currentGame;
+    return BlocBuilder<ActivityCubit, ActivityState>(
+      builder: (BuildContext context, ActivityState activityState) {
+        final Activity currentActivity = activityState.currentActivity;
 
         return Column(
           children: [
-            ScoreIndicator(game: currentGame),
+            ScoreIndicator(activity: currentActivity),
             Table(
               defaultVerticalAlignment: TableCellVerticalAlignment.middle,
               children: [
                 TableRow(
                   children: [
                     Center(
-                      child: MovesCountsIndicator(game: currentGame),
+                      child: MovesCountsIndicator(activity: currentActivity),
                     ),
-                    AvailableBlocksCountIndicator(game: currentGame),
+                    AvailableBlocksCountIndicator(activity: currentActivity),
                     Center(
-                      child: ShuffleButton(game: currentGame),
+                      child: ShuffleButton(activity: currentActivity),
                     ),
                   ],
                 )
diff --git a/lib/ui/layouts/parameters_layout.dart b/lib/ui/layouts/parameters_layout.dart
deleted file mode 100644
index f702b4f..0000000
--- a/lib/ui/layouts/parameters_layout.dart
+++ /dev/null
@@ -1,141 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
-
-import 'package:jeweled/config/default_game_settings.dart';
-import 'package:jeweled/config/default_global_settings.dart';
-import 'package:jeweled/cubit/settings_game_cubit.dart';
-import 'package:jeweled/cubit/settings_global_cubit.dart';
-import 'package:jeweled/ui/parameters/parameter_widget.dart';
-import 'package:jeweled/ui/widgets/actions/button_delete_saved_game.dart';
-import 'package:jeweled/ui/widgets/actions/button_game_start_new.dart';
-import 'package:jeweled/ui/widgets/actions/button_resume_saved_game.dart';
-
-class ParametersLayout extends StatelessWidget {
-  const ParametersLayout({super.key, required this.canResume});
-
-  final bool canResume;
-
-  final double separatorHeight = 8.0;
-
-  @override
-  Widget build(BuildContext context) {
-    final List<Widget> lines = [];
-
-    // Game settings
-    for (String code in DefaultGameSettings.availableParameters) {
-      lines.add(Row(
-        mainAxisAlignment: MainAxisAlignment.spaceBetween,
-        children: buildParametersLine(
-          code: code,
-          isGlobal: false,
-        ),
-      ));
-
-      lines.add(SizedBox(height: separatorHeight));
-    }
-
-    lines.add(Expanded(
-      child: SizedBox(height: separatorHeight),
-    ));
-
-    if (canResume == false) {
-      // Start new game
-      lines.add(
-        const AspectRatio(
-          aspectRatio: 3,
-          child: StartNewGameButton(),
-        ),
-      );
-    } else {
-      // Resume game
-      lines.add(const AspectRatio(
-        aspectRatio: 3,
-        child: ResumeSavedGameButton(),
-      ));
-      // Delete saved game
-      lines.add(SizedBox.square(
-        dimension: MediaQuery.of(context).size.width / 5,
-        child: const DeleteSavedGameButton(),
-      ));
-    }
-
-    lines.add(SizedBox(height: separatorHeight));
-
-    // Global settings
-    for (String code in DefaultGlobalSettings.availableParameters) {
-      lines.add(Row(
-        mainAxisAlignment: MainAxisAlignment.spaceBetween,
-        children: buildParametersLine(
-          code: code,
-          isGlobal: true,
-        ),
-      ));
-
-      lines.add(SizedBox(height: separatorHeight));
-    }
-
-    return Column(
-      children: lines,
-    );
-  }
-
-  List<Widget> buildParametersLine({
-    required String code,
-    required bool isGlobal,
-  }) {
-    final List<Widget> parameterButtons = [];
-
-    final List<String> availableValues = isGlobal
-        ? DefaultGlobalSettings.getAvailableValues(code)
-        : DefaultGameSettings.getAvailableValues(code);
-
-    if (availableValues.length <= 1) {
-      return [];
-    }
-
-    for (String value in availableValues) {
-      final Widget parameterButton = BlocBuilder<GameSettingsCubit, GameSettingsState>(
-        builder: (BuildContext context, GameSettingsState gameSettingsState) {
-          return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
-            builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
-              final GameSettingsCubit gameSettingsCubit =
-                  BlocProvider.of<GameSettingsCubit>(context);
-              final GlobalSettingsCubit globalSettingsCubit =
-                  BlocProvider.of<GlobalSettingsCubit>(context);
-
-              final String currentValue = isGlobal
-                  ? globalSettingsCubit.getParameterValue(code)
-                  : gameSettingsCubit.getParameterValue(code);
-
-              final bool isSelected = (value == currentValue);
-
-              final double displayWidth = MediaQuery.of(context).size.width;
-              final double itemWidth = displayWidth / availableValues.length - 4;
-
-              return SizedBox.square(
-                dimension: itemWidth,
-                child: ParameterWidget(
-                  code: code,
-                  value: value,
-                  isSelected: isSelected,
-                  size: itemWidth,
-                  gameSettings: gameSettingsState.settings,
-                  globalSettings: globalSettingsState.settings,
-                  onPressed: () {
-                    isGlobal
-                        ? globalSettingsCubit.setParameterValue(code, value)
-                        : gameSettingsCubit.setParameterValue(code, value);
-                  },
-                ),
-              );
-            },
-          );
-        },
-      );
-
-      parameterButtons.add(parameterButton);
-    }
-
-    return parameterButtons;
-  }
-}
diff --git a/lib/ui/painters/game_board_painter.dart b/lib/ui/painters/game_board_painter.dart
index f1523f0..989a114 100644
--- a/lib/ui/painters/game_board_painter.dart
+++ b/lib/ui/painters/game_board_painter.dart
@@ -6,21 +6,21 @@ import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
 import 'package:jeweled/config/color_theme.dart';
 import 'package:jeweled/config/default_global_settings.dart';
-import 'package:jeweled/models/game/cell_location.dart';
-import 'package:jeweled/models/game/game.dart';
+import 'package:jeweled/models/activity/cell_location.dart';
+import 'package:jeweled/models/activity/activity.dart';
 
 class GameBoardPainter extends CustomPainter {
   const GameBoardPainter({
-    required this.game,
+    required this.activity,
     required this.animations,
   });
 
-  final Game game;
+  final Activity activity;
   final List<List<Animation<double>?>> animations;
 
   @override
   void paint(Canvas canvas, Size size) {
-    String graphicTheme = game.globalSettings.graphicTheme;
+    String graphicTheme = activity.globalSettings.graphicTheme;
 
     final double canvasSize = min(size.width, size.height);
 
@@ -32,14 +32,14 @@ class GameBoardPainter extends CustomPainter {
         drawBoard(
           canvas: canvas,
           canvasSize: canvasSize,
-          game: game,
+          activity: activity,
         );
         break;
       case DefaultGlobalSettings.graphicThemeGradientAndBorder:
         drawBoard(
           canvas: canvas,
           canvasSize: canvasSize,
-          game: game,
+          activity: activity,
           borderWidth: cellBorderWidth,
           gradientFrom: -10,
           gradientTo: 10,
@@ -49,7 +49,7 @@ class GameBoardPainter extends CustomPainter {
         drawBoard(
           canvas: canvas,
           canvasSize: canvasSize,
-          game: game,
+          activity: activity,
           contentStrings: DefaultGlobalSettings.graphicThemeContentEmojiStrings,
         );
         break;
@@ -57,7 +57,7 @@ class GameBoardPainter extends CustomPainter {
         drawBoard(
           canvas: canvas,
           canvasSize: canvasSize,
-          game: game,
+          activity: activity,
           contentStrings: DefaultGlobalSettings.graphicThemeContentPatternStrings,
         );
         break;
@@ -90,16 +90,16 @@ class GameBoardPainter extends CustomPainter {
   void drawBoard({
     required Canvas canvas,
     required double canvasSize,
-    required Game game,
+    required Activity activity,
     double overlapping = 1,
     int gradientFrom = 0,
     int gradientTo = 0,
     double borderWidth = 0,
     List<String>? contentStrings,
   }) {
-    final int cellsCountHorizontal = game.gameSettings.boardSizeValue;
-    final int cellsCountVertical = game.gameSettings.boardSizeValue;
-    final String colorsTheme = game.globalSettings.colorsTheme;
+    final int cellsCountHorizontal = activity.activitySettings.boardSizeValue;
+    final int cellsCountVertical = activity.activitySettings.boardSizeValue;
+    final String colorsTheme = activity.globalSettings.colorsTheme;
 
     final double size = canvasSize / max(cellsCountHorizontal, cellsCountVertical);
 
@@ -109,7 +109,7 @@ class GameBoardPainter extends CustomPainter {
         final double x = size * col;
 
         final CellLocation cellLocation = CellLocation.go(row, col);
-        final int? cellValue = game.getCellValueShuffled(cellLocation);
+        final int? cellValue = activity.getCellValueShuffled(cellLocation);
         if (cellValue != null) {
           final Animation<double>? translation = animations[row][col];
           final double y = yOrigin + (translation?.value ?? 0) * size;
@@ -187,7 +187,7 @@ class GameBoardPainter extends CustomPainter {
     // draw content
     if (contentStrings != null) {
       final int emojiIndex =
-          cellValue - 1 + game.shuffledColors[0] + 2 * game.shuffledColors[1];
+          cellValue - 1 + activity.shuffledColors[0] + 2 * activity.shuffledColors[1];
       final String text = contentStrings[emojiIndex % contentStrings.length];
 
       final textSpan = TextSpan(
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
deleted file mode 100644
index 46ca3b5..0000000
--- a/lib/ui/screens/page_game.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
-
-import 'package:jeweled/cubit/game_cubit.dart';
-import 'package:jeweled/models/game/game.dart';
-import 'package:jeweled/ui/layouts/game_layout.dart';
-import 'package:jeweled/ui/layouts/parameters_layout.dart';
-
-class PageGame extends StatelessWidget {
-  const PageGame({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        final Game currentGame = gameState.currentGame;
-
-        return currentGame.isRunning
-            ? const GameLayout()
-            : ParametersLayout(canResume: currentGame.canBeResumed);
-      },
-    );
-  }
-}
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index 36e5e54..d778b51 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,24 +1,37 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/config/menu.dart';
-import 'package:jeweled/cubit/nav_cubit.dart';
-import 'package:jeweled/ui/widgets/global_app_bar.dart';
+import 'package:jeweled/common/config/activity_page.dart';
+import 'package:jeweled/common/config/screen.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_screens.dart';
+import 'package:jeweled/common/ui/nav/global_app_bar.dart';
+import 'package:jeweled/common/ui/nav/bottom_nav_bar.dart';
 
 class SkeletonScreen extends StatelessWidget {
   const SkeletonScreen({super.key});
 
   @override
   Widget build(BuildContext context) {
-    return Scaffold(
-      appBar: const GlobalAppBar(),
-      extendBodyBehindAppBar: false,
-      body: BlocBuilder<NavCubit, int>(
-        builder: (BuildContext context, int pageIndex) {
-          return Menu.getPageWidget(pageIndex);
-        },
-      ),
-      backgroundColor: Theme.of(context).colorScheme.surface,
+    return BlocBuilder<NavCubitScreen, int>(
+      builder: (BuildContext context, int screenIndex) {
+        return Scaffold(
+          appBar: const GlobalAppBar(),
+          extendBodyBehindAppBar: false,
+          body: Material(
+            color: Theme.of(context).colorScheme.surface,
+            child: Padding(
+              padding: const EdgeInsets.only(
+                top: 8,
+                left: 2,
+                right: 2,
+              ),
+              child: Screen.getWidget(screenIndex),
+            ),
+          ),
+          backgroundColor: Theme.of(context).colorScheme.surface,
+          bottomNavigationBar: ActivityPage.displayBottomNavBar ? const BottomNavBar() : null,
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/actions/button_delete_saved_game.dart b/lib/ui/widgets/actions/button_delete_saved_game.dart
index 64d9ff2..e339b45 100644
--- a/lib/ui/widgets/actions/button_delete_saved_game.dart
+++ b/lib/ui/widgets/actions/button_delete_saved_game.dart
@@ -1,7 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/cubit/game_cubit.dart';
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
 
 class DeleteSavedGameButton extends StatelessWidget {
   const DeleteSavedGameButton({super.key});
@@ -11,7 +11,7 @@ class DeleteSavedGameButton extends StatelessWidget {
     return StyledButton(
       color: Colors.grey,
       onPressed: () {
-        BlocProvider.of<GameCubit>(context).deleteSavedGame();
+        BlocProvider.of<ActivityCubit>(context).deleteSavedActivity();
       },
       child: const Image(
         image: AssetImage('assets/ui/button_delete_saved_game.png'),
diff --git a/lib/ui/widgets/actions/button_game_quit.dart b/lib/ui/widgets/actions/button_game_quit.dart
index 73697c1..09a2308 100644
--- a/lib/ui/widgets/actions/button_game_quit.dart
+++ b/lib/ui/widgets/actions/button_game_quit.dart
@@ -1,7 +1,9 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/cubit/game_cubit.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_pages.dart';
+
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
 
 class QuitGameButton extends StatelessWidget {
   const QuitGameButton({super.key});
@@ -11,7 +13,8 @@ class QuitGameButton extends StatelessWidget {
     return StyledButton(
       color: Colors.red,
       onPressed: () {
-        BlocProvider.of<GameCubit>(context).quitGame();
+        BlocProvider.of<ActivityCubit>(context).quitActivity();
+        BlocProvider.of<NavCubitPage>(context).goToPageHome();
       },
       child: const Image(
         image: AssetImage('assets/ui/button_back.png'),
diff --git a/lib/ui/widgets/actions/button_game_start_new.dart b/lib/ui/widgets/actions/button_game_start_new.dart
index 443ae93..20737af 100644
--- a/lib/ui/widgets/actions/button_game_start_new.dart
+++ b/lib/ui/widgets/actions/button_game_start_new.dart
@@ -1,26 +1,29 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/cubit/game_cubit.dart';
-import 'package:jeweled/cubit/settings_game_cubit.dart';
-import 'package:jeweled/cubit/settings_global_cubit.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_pages.dart';
+
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
+import 'package:jeweled/cubit/settings/settings_activity_cubit.dart';
+import 'package:jeweled/cubit/settings/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<ActivitySettingsCubit, ActivitySettingsState>(
+      builder: (BuildContext context, ActivitySettingsState activitySettingsState) {
         return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
           builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
             return StyledButton(
               color: Colors.blue,
               onPressed: () {
-                BlocProvider.of<GameCubit>(context).startNewGame(
-                  gameSettings: gameSettingsState.settings,
+                BlocProvider.of<ActivityCubit>(context).startNewActivity(
+                  activitySettings: activitySettingsState.settings,
                   globalSettings: globalSettingsState.settings,
                 );
+                BlocProvider.of<NavCubitPage>(context).goToPageGame();
               },
               child: const Image(
                 image: AssetImage('assets/ui/button_start.png'),
diff --git a/lib/ui/widgets/actions/button_resume_saved_game.dart b/lib/ui/widgets/actions/button_resume_saved_game.dart
index 30eb407..10f9f28 100644
--- a/lib/ui/widgets/actions/button_resume_saved_game.dart
+++ b/lib/ui/widgets/actions/button_resume_saved_game.dart
@@ -1,7 +1,9 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/cubit/game_cubit.dart';
+import 'package:jeweled/common/cubit/nav/nav_cubit_pages.dart';
+
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
 
 class ResumeSavedGameButton extends StatelessWidget {
   const ResumeSavedGameButton({super.key});
@@ -11,7 +13,8 @@ class ResumeSavedGameButton extends StatelessWidget {
     return StyledButton(
       color: Colors.blue,
       onPressed: () {
-        BlocProvider.of<GameCubit>(context).resumeSavedGame();
+        BlocProvider.of<ActivityCubit>(context).resumeSavedActivity();
+        BlocProvider.of<NavCubitPage>(context).goToPageGame();
       },
       child: const Image(
         image: AssetImage('assets/ui/button_resume_game.png'),
diff --git a/lib/ui/widgets/game/board.dart b/lib/ui/widgets/game/board.dart
index 08db3c8..e1c4ffa 100644
--- a/lib/ui/widgets/game/board.dart
+++ b/lib/ui/widgets/game/board.dart
@@ -1,9 +1,9 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/cubit/game_cubit.dart';
-import 'package:jeweled/models/game/cell_location.dart';
-import 'package:jeweled/models/game/game.dart';
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
+import 'package:jeweled/models/activity/cell_location.dart';
+import 'package:jeweled/models/activity/activity.dart';
 import 'package:jeweled/ui/painters/game_board_painter.dart';
 
 class BoardWidget extends StatefulWidget {
@@ -29,8 +29,8 @@ class _BoardWidget extends State<BoardWidget> with TickerProviderStateMixin {
   }
 
   void animateCells(List<CellLocation> cellsToRemove) {
-    final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-    final Game currentGame = gameCubit.state.currentGame;
+    final ActivityCubit activityCubit = BlocProvider.of<ActivityCubit>(context);
+    final Activity currentActivity = activityCubit.state.currentActivity;
 
     // "move down" cells
     final controller = AnimationController(
@@ -55,9 +55,9 @@ class _BoardWidget extends State<BoardWidget> with TickerProviderStateMixin {
         ))
           ..addStatusListener((status) {
             if (status == AnimationStatus.completed) {
-              gameCubit.postAnimate();
+              activityCubit.postAnimate();
 
-              resetAnimations(currentGame.gameSettings.boardSizeValue);
+              resetAnimations(currentActivity.activitySettings.boardSizeValue);
               setState(() {});
 
               controller.dispose();
@@ -66,9 +66,9 @@ class _BoardWidget extends State<BoardWidget> with TickerProviderStateMixin {
 
     // Count translation length for each cell to move
     final List<List<int>> stepsDownCounts = List.generate(
-      currentGame.gameSettings.boardSizeValue,
+      currentActivity.activitySettings.boardSizeValue,
       (i) => List.generate(
-        currentGame.gameSettings.boardSizeValue,
+        currentActivity.activitySettings.boardSizeValue,
         (i) => 0,
       ),
     );
@@ -91,7 +91,7 @@ class _BoardWidget extends State<BoardWidget> with TickerProviderStateMixin {
     controller.forward().orCancel;
 
     if (!needAnimation) {
-      gameCubit.postAnimate();
+      activityCubit.postAnimate();
     }
   }
 
@@ -100,12 +100,12 @@ class _BoardWidget extends State<BoardWidget> with TickerProviderStateMixin {
     final double displayWidth = MediaQuery.of(context).size.width;
 
     return Center(
-      child: BlocBuilder<GameCubit, GameState>(
-        builder: (BuildContext context, GameState gameState) {
-          final Game currentGame = gameState.currentGame;
+      child: BlocBuilder<ActivityCubit, ActivityState>(
+        builder: (BuildContext context, ActivityState activityState) {
+          final Activity currentActivity = activityState.currentActivity;
 
           if (animations.isEmpty) {
-            resetAnimations(currentGame.gameSettings.boardSizeValue);
+            resetAnimations(currentActivity.activitySettings.boardSizeValue);
           }
 
           return GestureDetector(
@@ -123,19 +123,19 @@ class _BoardWidget extends State<BoardWidget> with TickerProviderStateMixin {
                 final double xTap = details.localPosition.dx;
                 final double yTap = details.localPosition.dy;
                 final int col =
-                    xTap ~/ (displayWidth / currentGame.gameSettings.boardSizeValue);
+                    xTap ~/ (displayWidth / currentActivity.activitySettings.boardSizeValue);
                 final int row =
-                    yTap ~/ (displayWidth / currentGame.gameSettings.boardSizeValue);
+                    yTap ~/ (displayWidth / currentActivity.activitySettings.boardSizeValue);
 
-                animateCells(
-                    BlocProvider.of<GameCubit>(context).tapOnCell(CellLocation.go(row, col)));
+                animateCells(BlocProvider.of<ActivityCubit>(context)
+                    .tapOnCell(CellLocation.go(row, col)));
               }
             },
             child: CustomPaint(
               size: Size(displayWidth, displayWidth),
               willChange: false,
               painter: GameBoardPainter(
-                game: currentGame,
+                activity: currentActivity,
                 animations: animations,
               ),
               isComplex: true,
diff --git a/lib/ui/widgets/indicators/indicator_available_blocks.dart b/lib/ui/widgets/indicators/indicator_available_blocks.dart
index a7742e7..3f414d3 100644
--- a/lib/ui/widgets/indicators/indicator_available_blocks.dart
+++ b/lib/ui/widgets/indicators/indicator_available_blocks.dart
@@ -3,12 +3,12 @@ import 'dart:math';
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/models/game/game.dart';
+import 'package:jeweled/models/activity/activity.dart';
 
 class AvailableBlocksCountIndicator extends StatelessWidget {
-  const AvailableBlocksCountIndicator({super.key, required this.game});
+  const AvailableBlocksCountIndicator({super.key, required this.activity});
 
-  final Game game;
+  final Activity activity;
 
   @override
   Widget build(BuildContext context) {
@@ -16,7 +16,8 @@ class AvailableBlocksCountIndicator extends StatelessWidget {
     const minBlocksCount = 6;
 
     // Normalized [0..1] value
-    final double barValue = min(minBlocksCount, game.availableBlocksCount) / minBlocksCount;
+    final double barValue =
+        min(minBlocksCount, activity.availableBlocksCount) / minBlocksCount;
 
     // Bar color: red < orange < green
     final Color baseColor = (barValue < 0.5
@@ -39,7 +40,7 @@ class AvailableBlocksCountIndicator extends StatelessWidget {
           borderRadius: const BorderRadius.all(Radius.circular(15)),
         ),
         OutlinedText(
-          text: game.availableBlocksCount.toString(),
+          text: activity.availableBlocksCount.toString(),
           fontSize: barHeight,
           textColor: textColor,
           outlineColor: outlineColor,
diff --git a/lib/ui/widgets/indicators/indicator_moves_count.dart b/lib/ui/widgets/indicators/indicator_moves_count.dart
index 7af1fd2..b4ed246 100644
--- a/lib/ui/widgets/indicators/indicator_moves_count.dart
+++ b/lib/ui/widgets/indicators/indicator_moves_count.dart
@@ -1,12 +1,12 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/models/game/game.dart';
+import 'package:jeweled/models/activity/activity.dart';
 
 class MovesCountsIndicator extends StatelessWidget {
-  const MovesCountsIndicator({super.key, required this.game});
+  const MovesCountsIndicator({super.key, required this.activity});
 
-  final Game game;
+  final Activity activity;
 
   @override
   Widget build(BuildContext context) {
@@ -14,7 +14,7 @@ class MovesCountsIndicator extends StatelessWidget {
     final Color outlineColor = baseColor.darken();
 
     return OutlinedText(
-      text: game.movesCount.toString(),
+      text: activity.movesCount.toString(),
       fontSize: 40,
       textColor: baseColor,
       outlineColor: outlineColor,
diff --git a/lib/ui/widgets/indicators/indicator_score.dart b/lib/ui/widgets/indicators/indicator_score.dart
index 7d25e7e..563b36b 100644
--- a/lib/ui/widgets/indicators/indicator_score.dart
+++ b/lib/ui/widgets/indicators/indicator_score.dart
@@ -1,12 +1,12 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/models/game/game.dart';
+import 'package:jeweled/models/activity/activity.dart';
 
 class ScoreIndicator extends StatelessWidget {
-  const ScoreIndicator({super.key, required this.game});
+  const ScoreIndicator({super.key, required this.activity});
 
-  final Game game;
+  final Activity activity;
 
   @override
   Widget build(BuildContext context) {
@@ -14,7 +14,7 @@ class ScoreIndicator extends StatelessWidget {
     final Color outlineColor = baseColor.darken();
 
     return OutlinedText(
-      text: game.score.toString(),
+      text: activity.score.toString(),
       fontSize: 70,
       textColor: baseColor,
       outlineColor: outlineColor,
diff --git a/lib/ui/widgets/indicators/indicator_shuffle_button.dart b/lib/ui/widgets/indicators/indicator_shuffle_button.dart
index 56f815c..63f2063 100644
--- a/lib/ui/widgets/indicators/indicator_shuffle_button.dart
+++ b/lib/ui/widgets/indicators/indicator_shuffle_button.dart
@@ -1,13 +1,13 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
 
-import 'package:jeweled/cubit/game_cubit.dart';
-import 'package:jeweled/models/game/game.dart';
+import 'package:jeweled/cubit/activity/activity_cubit.dart';
+import 'package:jeweled/models/activity/activity.dart';
 
 class ShuffleButton extends StatelessWidget {
-  const ShuffleButton({super.key, required this.game});
+  const ShuffleButton({super.key, required this.activity});
 
-  final Game game;
+  final Activity activity;
 
   @override
   Widget build(BuildContext context) {
@@ -22,7 +22,8 @@ class ShuffleButton extends StatelessWidget {
         outlineColor: outlineColor,
       ),
       onPressed: () {
-        BlocProvider.of<GameCubit>(context).shuffleColors(game.globalSettings.colorsTheme);
+        BlocProvider.of<ActivityCubit>(context)
+            .shuffleColors(activity.globalSettings.colorsTheme);
       },
     );
   }
diff --git a/pubspec.lock b/pubspec.lock
index 011ee2e..5f7d30f 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -245,10 +245,10 @@ packages:
     dependency: transitive
     description:
       name: path_provider
-      sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
+      sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.4"
+    version: "2.1.5"
   path_provider_android:
     dependency: transitive
     description:
@@ -442,10 +442,10 @@ packages:
     dependency: transitive
     description:
       name: win32
-      sha256: "2735daae5150e8b1dfeb3eb0544b4d3af0061e9e82cef063adcd583bdae4306a"
+      sha256: "10169d3934549017f0ae278ccb07f828f9d6ea21573bab0fb77b0e1ef0fce454"
       url: "https://pub.dev"
     source: hosted
-    version: "5.7.0"
+    version: "5.7.2"
   xdg_directories:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 2f31c3e..f170d6c 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: Jeweled Game
 
 publish_to: "none"
 
-version: 0.3.1+37
+version: 0.4.0+38
 
 environment:
   sdk: "^3.0.0"
-- 
GitLab