From 2de9b1ed6a6896c4a203f5dedfebbfab1a80188a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Mon, 19 Feb 2024 21:10:40 +0100
Subject: [PATCH] Use flutter linter, apply lints, update dependencies

---
 analysis_options.yaml                         |   1 +
 android/app/build.gradle                      |   2 +-
 android/gradle.properties                     |   4 +-
 .../metadata/android/en-US/changelogs/58.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/58.txt  |   1 +
 lib/entities/moving_tile.dart                 |  87 ++++++------
 lib/entities/tile.dart                        |  15 +-
 lib/main.dart                                 |   9 +-
 lib/provider/data.dart                        |  17 +--
 lib/screens/game.dart                         | 132 +++++++++---------
 lib/screens/home.dart                         | 106 +++++++-------
 lib/utils/game_utils.dart                     |  49 +++----
 lib/utils/get_images_list.dart                |  13 +-
 pubspec.lock                                  |  70 ++++++----
 pubspec.yaml                                  |   5 +-
 15 files changed, 269 insertions(+), 243 deletions(-)
 create mode 100644 analysis_options.yaml
 create mode 100644 fastlane/metadata/android/en-US/changelogs/58.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/58.txt

diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..f9b3034
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:flutter_lints/flutter.yaml
diff --git a/android/app/build.gradle b/android/app/build.gradle
index c83a8f2..ae56e97 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -44,7 +44,7 @@ android {
 
     defaultConfig {
         applicationId "org.benoitharrault.puzzlegame"
-        minSdkVersion 16
+        minSdkVersion flutter.minSdkVersion
         targetSdkVersion 30
         versionCode appVersionCode.toInteger()
         versionName appVersionName
diff --git a/android/gradle.properties b/android/gradle.properties
index 547a7f8..ecb37da 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.57
-app.versionCode=57
+app.versionName=0.0.58
+app.versionCode=58
diff --git a/fastlane/metadata/android/en-US/changelogs/58.txt b/fastlane/metadata/android/en-US/changelogs/58.txt
new file mode 100644
index 0000000..6ab1115
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/58.txt
@@ -0,0 +1 @@
+Add automatic flutter linter. Apply code lints. Update dependencies.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/58.txt b/fastlane/metadata/android/fr-FR/changelogs/58.txt
new file mode 100644
index 0000000..609f5cf
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/58.txt
@@ -0,0 +1 @@
+Ajout d'un correcteur automatique de code. Application des corrections. Mise à jour des dépendances.
diff --git a/lib/entities/moving_tile.dart b/lib/entities/moving_tile.dart
index 0698ec2..99fa0a9 100644
--- a/lib/entities/moving_tile.dart
+++ b/lib/entities/moving_tile.dart
@@ -1,4 +1,5 @@
 import 'package:flutter/material.dart';
+
 import 'package:puzzlegame/entities/tile.dart';
 import 'package:puzzlegame/provider/data.dart';
 
@@ -6,8 +7,14 @@ class MovingTile extends Tile {
   int currentCol;
   int currentRow;
 
-  MovingTile(image, size, originalCol, originalRow, this.currentCol, this.currentRow)
-      : super(image, size, originalCol, originalRow);
+  MovingTile({
+    required this.currentCol,
+    required this.currentRow,
+    required super.image,
+    required super.size,
+    required super.originalCol,
+    required super.originalRow,
+  });
 
   Container _tileWidget() {
     return Container(
@@ -19,55 +26,55 @@ class MovingTile extends Tile {
         ),
       ),
       child: Image(
-        image: this.image.image,
-        width: this.size,
-        height: this.size,
+        image: image.image,
+        width: size,
+        height: size,
         fit: BoxFit.fill,
       ),
     );
   }
 
-  Container widget(Data myProvider) {
-    return Container(
-      child: DragTarget<List<int>>(
-        builder: (
-          BuildContext context,
-          List<dynamic> accepted,
-          List<dynamic> rejected,
-        ) {
-          return Container(
-            height: this.size,
-            width: this.size,
-            color: Colors.cyan,
-            child: Draggable<List<int>>(
-              data: [
-                this.currentCol,
-                this.currentRow,
-              ],
-
-              // Widget when draggable is stationary
-              child: this._tileWidget(),
+  @override
+  Widget widget(Data myProvider) {
+    return DragTarget<List<int>>(
+      builder: (
+        BuildContext context,
+        List<dynamic> accepted,
+        List<dynamic> rejected,
+      ) {
+        return Container(
+          height: size,
+          width: size,
+          color: Colors.cyan,
+          child: Draggable<List<int>>(
+            data: [
+              currentCol,
+              currentRow,
+            ],
 
-              // Widget when draggable is being dragged
-              feedback: this._tileWidget(),
+            // Widget when draggable is being dragged
+            feedback: _tileWidget(),
 
-              // Widget to display on original place when being dragged
-              childWhenDragging: Container(
-                height: this.size,
-                width: this.size,
-                color: Colors.pinkAccent,
-              ),
+            // Widget to display on original place when being dragged
+            childWhenDragging: Container(
+              height: size,
+              width: size,
+              color: Colors.pinkAccent,
             ),
-          );
-        },
-        onAccept: (List<int> data) {
-          myProvider.swapTiles([this.currentCol, this.currentRow], data);
-        },
-      ),
+
+            // Widget when draggable is stationary
+            child: _tileWidget(),
+          ),
+        );
+      },
+      onAcceptWithDetails: (DragTargetDetails<List<int>> source) {
+        myProvider.swapTiles([currentCol, currentRow], source.data);
+      },
     );
   }
 
+  @override
   bool isCorrect() {
-    return ((this.currentRow == this.originalRow) && (this.currentCol == this.originalCol));
+    return ((currentRow == originalRow) && (currentCol == originalCol));
   }
 }
diff --git a/lib/entities/tile.dart b/lib/entities/tile.dart
index 4971154..76e58df 100644
--- a/lib/entities/tile.dart
+++ b/lib/entities/tile.dart
@@ -1,4 +1,5 @@
 import 'package:flutter/material.dart';
+
 import 'package:puzzlegame/provider/data.dart';
 
 class Tile {
@@ -7,14 +8,14 @@ class Tile {
   final int originalCol;
   final int originalRow;
 
-  Tile(
-    this.image,
-    this.size,
-    this.originalCol,
-    this.originalRow,
-  );
+  Tile({
+    required this.image,
+    required this.size,
+    required this.originalCol,
+    required this.originalRow,
+  });
 
-  Container widget(Data myProvider) {
+  Widget widget(Data myProvider) {
     return Container();
   }
 
diff --git a/lib/main.dart b/lib/main.dart
index 6a402c5..33c9734 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,16 +1,19 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:provider/provider.dart';
+
 import 'package:puzzlegame/provider/data.dart';
 import 'package:puzzlegame/screens/home.dart';
 
 void main() {
   WidgetsFlutterBinding.ensureInitialized();
   SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
-      .then((value) => runApp(MyApp()));
+      .then((value) => runApp(const MyApp()));
 }
 
 class MyApp extends StatelessWidget {
+  const MyApp({super.key});
+
   @override
   Widget build(BuildContext context) {
     return ChangeNotifierProvider(
@@ -23,9 +26,9 @@ class MyApp extends StatelessWidget {
               primaryColor: Colors.blue,
               visualDensity: VisualDensity.adaptivePlatformDensity,
             ),
-            home: Home(),
+            home: const Home(),
             routes: {
-              Home.id: (context) => Home(),
+              Home.id: (context) => const Home(),
             },
           );
         },
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
index 62ea928..dd85da9 100644
--- a/lib/provider/data.dart
+++ b/lib/provider/data.dart
@@ -1,4 +1,5 @@
 import 'package:flutter/foundation.dart';
+
 import 'package:puzzlegame/entities/moving_tile.dart';
 
 class Data extends ChangeNotifier {
@@ -6,7 +7,7 @@ class Data extends ChangeNotifier {
   int _tilesCount = 4;
 
   // Game data
-  List _availableImages = [];
+  List<String> _availableImages = [];
   String _selectedImage = '';
   List<MovingTile> _tiles = [];
   double _tileImageSize = 1.0;
@@ -35,9 +36,9 @@ class Data extends ChangeNotifier {
     notifyListeners();
   }
 
-  List get availableImages => _availableImages;
+  List<String> get availableImages => _availableImages;
 
-  void updateAvailableImages(List availableImages) {
+  void updateAvailableImages(List<String> availableImages) {
     _availableImages = availableImages;
     notifyListeners();
   }
@@ -79,20 +80,20 @@ class Data extends ChangeNotifier {
   }
 
   void swapTiles(List<int> tile1, List<int> tile2) {
-    int indexTile1 = _tiles.indexWhere(
+    final int indexTile1 = _tiles.indexWhere(
         (tile) => ((tile.currentCol == tile1[0]) && (tile.currentRow == tile1[1])));
-    int indexTile2 = _tiles.indexWhere(
+    final int indexTile2 = _tiles.indexWhere(
         (tile) => ((tile.currentCol == tile2[0]) && (tile.currentRow == tile2[1])));
 
-    MovingTile swap = _tiles[indexTile1];
+    final MovingTile swap = _tiles[indexTile1];
     _tiles[indexTile1] = _tiles[indexTile2];
     _tiles[indexTile2] = swap;
 
-    int swapCol = _tiles[indexTile1].currentCol;
+    final int swapCol = _tiles[indexTile1].currentCol;
     _tiles[indexTile1].currentCol = _tiles[indexTile2].currentCol;
     _tiles[indexTile2].currentCol = swapCol;
 
-    int swapRow = _tiles[indexTile1].currentRow;
+    final int swapRow = _tiles[indexTile1].currentRow;
     _tiles[indexTile1].currentRow = _tiles[indexTile2].currentRow;
     _tiles[indexTile2].currentRow = swapRow;
 
diff --git a/lib/screens/game.dart b/lib/screens/game.dart
index 38bc89a..073e39b 100644
--- a/lib/screens/game.dart
+++ b/lib/screens/game.dart
@@ -1,4 +1,5 @@
 import 'package:flutter/material.dart';
+
 import 'package:puzzlegame/entities/moving_tile.dart';
 import 'package:puzzlegame/provider/data.dart';
 import 'package:puzzlegame/utils/game_utils.dart';
@@ -8,24 +9,25 @@ class Game {
     myProvider.updateIsTipImageDisplayed(!myProvider.displayTipImage);
   }
 
-  static Container buildTilesetWidget(Data myProvider) {
-    List<MovingTile> tiles = myProvider.tiles;
+  static Widget buildTilesetWidget(Data myProvider) {
+    final List<MovingTile> tiles = myProvider.tiles;
 
-    Color borderColor = GameUtils.checkTilesetIsCleared(tiles) ? Colors.green : Colors.orange;
+    final Color borderColor =
+        GameUtils.checkTilesetIsCleared(tiles) ? Colors.green : Colors.orange;
     int tileIndex = 0;
 
-    Table tileset = Table(
-      defaultColumnWidth: IntrinsicColumnWidth(),
+    final Table tileset = Table(
+      defaultColumnWidth: const IntrinsicColumnWidth(),
       border: TableBorder.all(
         color: Colors.black,
         style: BorderStyle.solid,
         width: 2,
       ),
       children: [
-        for (var row = 0; row < myProvider.tilesCount; row++)
+        for (int row = 0; row < myProvider.tilesCount; row++)
           TableRow(
             children: [
-              for (var col = 0; col < myProvider.tilesCount; col++)
+              for (int col = 0; col < myProvider.tilesCount; col++)
                 Column(children: [tiles[tileIndex++].widget(myProvider)]),
             ],
           ),
@@ -33,8 +35,8 @@ class Game {
     );
 
     return Container(
-      margin: EdgeInsets.all(8),
-      padding: EdgeInsets.all(8),
+      margin: const EdgeInsets.all(8),
+      padding: const EdgeInsets.all(8),
       decoration: BoxDecoration(
         color: borderColor,
         borderRadius: BorderRadius.circular(8),
@@ -47,16 +49,16 @@ class Game {
     );
   }
 
-  static Container buildTipWidget(Data myProvider) {
+  static Widget buildTipWidget(Data myProvider) {
     return Container(
-      margin: EdgeInsets.all(2),
-      padding: EdgeInsets.all(2),
+      margin: const EdgeInsets.all(2),
+      padding: const EdgeInsets.all(2),
       child: Table(
-        defaultColumnWidth: IntrinsicColumnWidth(),
+        defaultColumnWidth: const IntrinsicColumnWidth(),
         children: [
           TableRow(
             children: [
-              Column(
+              const Column(
                 children: [
                   Image(
                     image: AssetImage('assets/images/placeholder.png'),
@@ -89,7 +91,7 @@ class Game {
                   ),
                 ],
               ),
-              Column(
+              const Column(
                 children: [
                   Image(
                     image: AssetImage('assets/images/placeholder.png'),
@@ -104,33 +106,31 @@ class Game {
     );
   }
 
-  static Container buildGameWidget(Data myProvider) {
-    return Container(
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.center,
-        children: [
-          SizedBox(height: 8),
-          buildTopIndicatorWidget(myProvider),
-          SizedBox(height: 2),
-          Expanded(
-            child: buildGameBoard(myProvider),
-          ),
-          SizedBox(height: 2),
-          Container(
-            child: GameUtils.checkTilesetIsCleared(myProvider.tiles)
-                ? Game.buildWinMessage(myProvider)
-                : Game.buildTipWidget(myProvider),
-          ),
-        ],
-      ),
+  static Widget buildGameWidget(Data myProvider) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: [
+        const SizedBox(height: 8),
+        buildTopIndicatorWidget(myProvider),
+        const SizedBox(height: 2),
+        Expanded(
+          child: buildGameBoard(myProvider),
+        ),
+        const SizedBox(height: 2),
+        Container(
+          child: GameUtils.checkTilesetIsCleared(myProvider.tiles)
+              ? Game.buildWinMessage(myProvider)
+              : Game.buildTipWidget(myProvider),
+        ),
+      ],
     );
   }
 
-  static Container buildGameBoard(Data myProvider) {
+  static Widget buildGameBoard(Data myProvider) {
     return Container(
-      margin: EdgeInsets.all(4),
-      padding: EdgeInsets.all(4),
+      margin: const EdgeInsets.all(4),
+      padding: const EdgeInsets.all(4),
       child: Column(
         children: [
           buildTilesetWidget(myProvider),
@@ -147,30 +147,30 @@ class Game {
             Column(children: [
               Text(
                 myProvider.movesCount.toString(),
-                style: TextStyle(
+                style: const TextStyle(
                   fontSize: 40,
                   fontWeight: FontWeight.w600,
                   color: Colors.black,
                 ),
               ),
             ]),
-            Column(children: []),
+            const Column(children: []),
           ],
         ),
       ],
     );
   }
 
-  static Container buildWinMessage(Data myProvider) {
+  static Widget buildWinMessage(Data myProvider) {
     return Container(
-      margin: EdgeInsets.all(2),
-      padding: EdgeInsets.all(2),
+      margin: const EdgeInsets.all(2),
+      padding: const EdgeInsets.all(2),
       child: Table(
-        defaultColumnWidth: IntrinsicColumnWidth(),
+        defaultColumnWidth: const IntrinsicColumnWidth(),
         children: [
           TableRow(
             children: [
-              Column(
+              const Column(
                 children: [
                   Image(
                     image: AssetImage('assets/icons/game_win.png'),
@@ -181,17 +181,15 @@ class Game {
               Column(
                 children: [
                   TextButton(
-                    child: Container(
-                      child: Image(
-                        image: AssetImage('assets/icons/button_back.png'),
-                        fit: BoxFit.fill,
-                      ),
+                    child: const Image(
+                      image: AssetImage('assets/icons/button_back.png'),
+                      fit: BoxFit.fill,
                     ),
                     onPressed: () => GameUtils.resetGame(myProvider),
                   ),
                 ],
               ),
-              Column(
+              const Column(
                 children: [
                   Image(
                     image: AssetImage('assets/icons/game_win.png'),
@@ -206,24 +204,22 @@ class Game {
     );
   }
 
-  static Container buildShufflingIndicatorWidget() {
-    return Container(
-      child: Column(
-        mainAxisSize: MainAxisSize.min,
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: [
-          Text(
-            '⏳',
-            style: TextStyle(
-              fontSize: 60,
-              fontWeight: FontWeight.w600,
-              color: Colors.black,
-            ),
+  static Widget buildShufflingIndicatorWidget() {
+    return const Column(
+      mainAxisSize: MainAxisSize.min,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Text(
+          '⏳',
+          style: TextStyle(
+            fontSize: 60,
+            fontWeight: FontWeight.w600,
+            color: Colors.black,
           ),
-          SizedBox(height: 20),
-          CircularProgressIndicator(),
-        ],
-      ),
+        ),
+        SizedBox(height: 20),
+        CircularProgressIndicator(),
+      ],
     );
   }
 }
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
index f2047d4..1cee132 100644
--- a/lib/screens/home.dart
+++ b/lib/screens/home.dart
@@ -1,22 +1,23 @@
 import 'dart:async';
 
 import 'package:flutter/material.dart';
-
 import 'package:provider/provider.dart';
+
 import 'package:puzzlegame/provider/data.dart';
 import 'package:puzzlegame/screens/game.dart';
 import 'package:puzzlegame/utils/game_utils.dart';
 import 'package:puzzlegame/utils/get_images_list.dart';
 
 class Home extends StatelessWidget {
+  const Home({super.key});
+
   static const String id = 'home';
 
   final Color themePrimaryColor = Colors.blue;
   final int _selectImageColumnsCount = 3;
 
   Future<void> getImagesList(Data myProvider) async {
-    GetImagesList getImagesList;
-    getImagesList = GetImagesList();
+    GetImagesList getImagesList = GetImagesList();
     await getImagesList.init();
     if (getImagesList.availableImages.isNotEmpty) {
       myProvider.updateAvailableImages(getImagesList.availableImages);
@@ -29,56 +30,54 @@ class Home extends StatelessWidget {
   }
 
   void shuffleAvailableImages(Data myProvider) {
-    List images = myProvider.availableImages;
+    final List<String> images = myProvider.availableImages;
     images.shuffle();
     myProvider.updateAvailableImages(images);
   }
 
-  Container _buildImageSelectorItem(Data myProvider, String image) {
-    return Container(
-      child: TextButton(
-        style: TextButton.styleFrom(
-          padding: EdgeInsets.all(2),
-        ),
-        child: Container(
-          decoration: BoxDecoration(
-            borderRadius: BorderRadius.circular(4),
-            border: Border.all(
-              color: Colors.blue.shade200,
-              width: 4,
-            ),
-          ),
-          child: Image(
-            image: AssetImage(GameUtils.getImageAssetName(image)),
-            fit: BoxFit.fill,
+  Widget _buildImageSelectorItem(Data myProvider, String image) {
+    return TextButton(
+      style: TextButton.styleFrom(
+        padding: const EdgeInsets.all(2),
+      ),
+      child: Container(
+        decoration: BoxDecoration(
+          borderRadius: BorderRadius.circular(4),
+          border: Border.all(
+            color: Colors.blue.shade200,
+            width: 4,
           ),
         ),
-        onPressed: () {
-          selectImage(myProvider, image);
-        },
+        child: Image(
+          image: AssetImage(GameUtils.getImageAssetName(image)),
+          fit: BoxFit.fill,
+        ),
       ),
+      onPressed: () {
+        selectImage(myProvider, image);
+      },
     );
   }
 
-  Container _buildImageSelector(Data myProvider) {
-    if (myProvider.availableImages.length == 0) {
+  Widget _buildImageSelector(Data myProvider) {
+    if (myProvider.availableImages.isEmpty) {
       getImagesList(myProvider);
     }
-    List images = myProvider.availableImages;
+    final List<String> images = myProvider.availableImages;
 
     return Container(
-      padding: EdgeInsets.all(2),
+      padding: const EdgeInsets.all(2),
       child: ListView(
         children: [
           Table(
-            defaultColumnWidth: IntrinsicColumnWidth(),
+            defaultColumnWidth: const IntrinsicColumnWidth(),
             children: [
-              for (var imgIndex = 0;
+              for (int imgIndex = 0;
                   imgIndex < images.length;
                   imgIndex += _selectImageColumnsCount)
                 TableRow(
                   children: [
-                    for (var colIndex = 0; colIndex < _selectImageColumnsCount; colIndex++)
+                    for (int colIndex = 0; colIndex < _selectImageColumnsCount; colIndex++)
                       Column(
                         children: [
                           if (imgIndex + colIndex < images.length)
@@ -95,8 +94,7 @@ class Home extends StatelessWidget {
   }
 
   TextButton _buildTilesetSizeSelectorItem(Data myProvider, int value) {
-    String assetName =
-        'assets/icons/difficulty_' + value.toString() + 'x' + value.toString() + '.png';
+    String assetName = 'assets/icons/difficulty_${value}x$value.png';
 
     Color borderColor = themePrimaryColor;
 
@@ -126,28 +124,28 @@ class Home extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    Data _myProvider = Provider.of<Data>(context);
+    final Data myProvider = Provider.of<Data>(context);
 
-    var content;
+    Widget content;
 
-    _myProvider.updateTileImageSize(
-        (MediaQuery.of(context).size.width - 70) / _myProvider.tilesCount);
+    myProvider
+        .updateTileImageSize((MediaQuery.of(context).size.width - 70) / myProvider.tilesCount);
 
-    if (_myProvider.isShufflingBoard) {
+    if (myProvider.isShufflingBoard) {
       content = Game.buildShufflingIndicatorWidget();
-      precacheImage(new AssetImage('assets/icons/game_win.png'), context);
+      precacheImage(const AssetImage('assets/icons/game_win.png'), context);
     } else {
-      if (_myProvider.selectedImage == '') {
-        content = _buildImageSelector(_myProvider);
+      if (myProvider.selectedImage == '') {
+        content = _buildImageSelector(myProvider);
       } else {
-        content = Game.buildGameWidget(_myProvider);
+        content = Game.buildGameWidget(myProvider);
       }
     }
 
-    List<Widget> menuActions = [
-      _buildTilesetSizeSelectorItem(_myProvider, 3),
-      _buildTilesetSizeSelectorItem(_myProvider, 4),
-      _buildTilesetSizeSelectorItem(_myProvider, 5),
+    final List<Widget> menuActions = [
+      _buildTilesetSizeSelectorItem(myProvider, 3),
+      _buildTilesetSizeSelectorItem(myProvider, 4),
+      _buildTilesetSizeSelectorItem(myProvider, 5),
       TextButton(
         child: Container(
           decoration: BoxDecoration(
@@ -157,12 +155,12 @@ class Home extends StatelessWidget {
               width: 4,
             ),
           ),
-          child: Image(
+          child: const Image(
             image: AssetImage('assets/icons/button_shuffle.png'),
             fit: BoxFit.fill,
           ),
         ),
-        onPressed: () => shuffleAvailableImages(_myProvider),
+        onPressed: () => shuffleAvailableImages(myProvider),
       ),
       TextButton(
         child: Container(
@@ -173,16 +171,16 @@ class Home extends StatelessWidget {
               width: 4,
             ),
           ),
-          child: Image(
+          child: const Image(
             image: AssetImage('assets/icons/button_random_pick.png'),
             fit: BoxFit.fill,
           ),
         ),
-        onPressed: () => GameUtils.startRandomGame(_myProvider),
+        onPressed: () => GameUtils.startRandomGame(myProvider),
       ),
     ];
 
-    List<Widget> gameActions = [
+    final List<Widget> gameActions = [
       TextButton(
         child: Container(
           decoration: BoxDecoration(
@@ -192,19 +190,19 @@ class Home extends StatelessWidget {
               width: 4,
             ),
           ),
-          child: Image(
+          child: const Image(
             image: AssetImage('assets/icons/button_back.png'),
             fit: BoxFit.fill,
           ),
         ),
-        onPressed: () => GameUtils.resetGame(_myProvider),
+        onPressed: () => GameUtils.resetGame(myProvider),
       ),
     ];
 
     return Scaffold(
       appBar: AppBar(
         backgroundColor: themePrimaryColor,
-        actions: _myProvider.selectedImage == '' ? menuActions : gameActions,
+        actions: myProvider.selectedImage == '' ? menuActions : gameActions,
       ),
       body: SafeArea(
         child: Center(child: content),
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
index 7b9bd20..db7d57a 100644
--- a/lib/utils/game_utils.dart
+++ b/lib/utils/game_utils.dart
@@ -5,30 +5,31 @@ import 'dart:typed_data';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart' show rootBundle;
 import 'package:image/image.dart' as imglib;
+
 import 'package:puzzlegame/entities/moving_tile.dart';
 import 'package:puzzlegame/entities/tile.dart';
 import 'package:puzzlegame/provider/data.dart';
 
 class GameUtils {
   static String getImageAssetName(String imageCode) {
-    return 'assets/images/' + imageCode + '.png';
+    return 'assets/images/$imageCode.png';
   }
 
   static startGame(Data myProvider, String imageCode) {
     myProvider.updateIsShufflingBoard(true);
     myProvider.updateSelectedImage(imageCode);
 
-    new Timer(new Duration(seconds: 1), () {
+    Timer(const Duration(seconds: 1), () {
       GameUtils.splitImageInTiles(myProvider);
     });
   }
 
   static startRandomGame(Data myProvider) {
-    List sizes = [3, 4, 5];
+    final List<int> sizes = [3, 4, 5];
     sizes.shuffle();
     myProvider.updateTilesCount(sizes[0]);
 
-    List images = myProvider.availableImages;
+    final List<String> images = myProvider.availableImages;
     images.shuffle();
 
     startGame(myProvider, images[0]);
@@ -49,22 +50,22 @@ class GameUtils {
   }
 
   static List<MovingTile> shuffleMovingTiles(List<MovingTile> tiles) {
-    var random = new Random();
-    int tilesCount = tiles.length;
+    final Random random = Random();
+    final int tilesCount = tiles.length;
 
     for (int i = 0; i < (10 * tilesCount); i++) {
-      int indexTile1 = random.nextInt(tilesCount);
-      int indexTile2 = random.nextInt(tilesCount);
+      final int indexTile1 = random.nextInt(tilesCount);
+      final int indexTile2 = random.nextInt(tilesCount);
 
-      MovingTile swap = tiles[indexTile1];
+      final MovingTile swap = tiles[indexTile1];
       tiles[indexTile1] = tiles[indexTile2];
       tiles[indexTile2] = swap;
 
-      int swapCol = tiles[indexTile1].currentCol;
+      final int swapCol = tiles[indexTile1].currentCol;
       tiles[indexTile1].currentCol = tiles[indexTile2].currentCol;
       tiles[indexTile2].currentCol = swapCol;
 
-      int swapRow = tiles[indexTile1].currentRow;
+      final int swapRow = tiles[indexTile1].currentRow;
       tiles[indexTile1].currentRow = tiles[indexTile2].currentRow;
       tiles[indexTile2].currentRow = swapRow;
     }
@@ -73,10 +74,10 @@ class GameUtils {
   }
 
   static Future<void> splitImageInTiles(Data myProvider) async {
-    String imageAsset = getImageAssetName(myProvider.selectedImage);
-    Uint8List imageData = (await rootBundle.load(imageAsset)).buffer.asUint8List();
+    final String imageAsset = getImageAssetName(myProvider.selectedImage);
+    final Uint8List imageData = (await rootBundle.load(imageAsset)).buffer.asUint8List();
 
-    imglib.Image image = imglib.decodeImage(imageData) ??
+    final imglib.Image image = imglib.decodeImage(imageData) ??
         imglib.Image.fromBytes(
           height: 1,
           width: 1,
@@ -84,13 +85,13 @@ class GameUtils {
         );
 
     int x = 0, y = 0;
-    int width = (image.width / myProvider.tilesCount).round();
-    int height = (image.height / myProvider.tilesCount).round();
+    final int width = (image.width / myProvider.tilesCount).round();
+    final int height = (image.height / myProvider.tilesCount).round();
 
-    List<MovingTile> tiles = [];
+    final List<MovingTile> tiles = [];
     for (int i = 0; i < myProvider.tilesCount; i++) {
       for (int j = 0; j < myProvider.tilesCount; j++) {
-        Uint8List tileData = new Uint8List.fromList(imglib.encodeJpg(imglib.copyCrop(
+        final Uint8List tileData = Uint8List.fromList(imglib.encodeJpg(imglib.copyCrop(
           image,
           x: x,
           y: y,
@@ -99,12 +100,12 @@ class GameUtils {
         )));
 
         tiles.add(MovingTile(
-          Image.memory(tileData),
-          myProvider.tileImageSize,
-          j,
-          i,
-          j,
-          i,
+          currentCol: j,
+          currentRow: i,
+          image: Image.memory(tileData),
+          size: myProvider.tileImageSize,
+          originalCol: j,
+          originalRow: i,
         ));
 
         x += width;
diff --git a/lib/utils/get_images_list.dart b/lib/utils/get_images_list.dart
index 4f5f4f1..ea5210d 100644
--- a/lib/utils/get_images_list.dart
+++ b/lib/utils/get_images_list.dart
@@ -1,11 +1,12 @@
 import 'dart:async';
 import 'dart:convert';
+
 import 'package:flutter/services.dart';
 
 class GetImagesList {
   GetImagesList();
 
-  List _availableImages = [];
+  List<String> _availableImages = [];
 
   init() async {
     await imagesFromLocalFile();
@@ -16,8 +17,12 @@ class GetImagesList {
     try {
       jsonString = await rootBundle.loadString('assets/files/images.json');
       final jsonResponse = await json.decode(jsonString);
-      List imagesList = jsonResponse['images'];
-      _availableImages = imagesList;
+
+      List imagesList = jsonResponse['images'] as List;
+
+      for (var image in imagesList) {
+        _availableImages.add(image.toString());
+      }
     } catch (e) {
       _availableImages = [];
     }
@@ -26,5 +31,5 @@ class GetImagesList {
     _availableImages.removeWhere((value) => (value == ''));
   }
 
-  List get availableImages => _availableImages;
+  List<String> get availableImages => _availableImages;
 }
diff --git a/pubspec.lock b/pubspec.lock
index a32d491..7b344e7 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,10 +5,10 @@ packages:
     dependency: transitive
     description:
       name: archive
-      sha256: "06a96f1249f38a00435b3b0c9a3246d934d7dbc8183fc7c9e56989860edb99d4"
+      sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
       url: "https://pub.dev"
     source: hosted
-    version: "3.4.4"
+    version: "3.4.10"
   characters:
     dependency: transitive
     description:
@@ -21,10 +21,10 @@ packages:
     dependency: transitive
     description:
       name: collection
-      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
+      sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
       url: "https://pub.dev"
     source: hosted
-    version: "1.17.2"
+    version: "1.18.0"
   convert:
     dependency: transitive
     description:
@@ -46,38 +46,54 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_lints:
+    dependency: "direct dev"
+    description:
+      name: flutter_lints
+      sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.1"
   image:
     dependency: "direct main"
     description:
       name: image
-      sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271"
+      sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
       url: "https://pub.dev"
     source: hosted
-    version: "4.1.3"
+    version: "4.1.7"
   js:
     dependency: transitive
     description:
       name: js
-      sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
+      sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
       url: "https://pub.dev"
     source: hosted
-    version: "0.6.7"
+    version: "0.7.1"
+  lints:
+    dependency: transitive
+    description:
+      name: lints
+      sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.0"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
+      sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.0"
+    version: "0.8.0"
   meta:
     dependency: transitive
     description:
       name: meta
-      sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+      sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
       url: "https://pub.dev"
     source: hosted
-    version: "1.9.1"
+    version: "1.11.0"
   nested:
     dependency: transitive
     description:
@@ -90,34 +106,34 @@ packages:
     dependency: transitive
     description:
       name: path
-      sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
+      sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
       url: "https://pub.dev"
     source: hosted
-    version: "1.8.3"
+    version: "1.9.0"
   petitparser:
     dependency: transitive
     description:
       name: petitparser
-      sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
+      sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
       url: "https://pub.dev"
     source: hosted
-    version: "5.4.0"
+    version: "6.0.2"
   pointycastle:
     dependency: transitive
     description:
       name: pointycastle
-      sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
+      sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
       url: "https://pub.dev"
     source: hosted
-    version: "3.7.3"
+    version: "3.7.4"
   provider:
     dependency: "direct main"
     description:
       name: provider
-      sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
+      sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096"
       url: "https://pub.dev"
     source: hosted
-    version: "6.0.5"
+    version: "6.1.1"
   sky_engine:
     dependency: transitive
     description: flutter
@@ -139,22 +155,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.1.4"
-  web:
-    dependency: transitive
-    description:
-      name: web
-      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
-      url: "https://pub.dev"
-    source: hosted
-    version: "0.1.4-beta"
   xml:
     dependency: transitive
     description:
       name: xml
-      sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
+      sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
       url: "https://pub.dev"
     source: hosted
-    version: "6.3.0"
+    version: "6.5.0"
 sdks:
-  dart: ">=3.1.0-185.0.dev <4.0.0"
+  dart: ">=3.2.0 <4.0.0"
   flutter: ">=1.16.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index eed24b7..a3d41eb 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,7 @@
 name: puzzlegame
 description: A puzzle game application.
 publish_to: 'none'
-version: 1.0.0+1
+version: 0.0.58+58
 
 environment:
   sdk: '^3.0.0'
@@ -12,6 +12,9 @@ dependencies:
   image: ^4.1.3
   provider: ^6.0.5
 
+dev_dependencies:
+  flutter_lints: ^3.0.1
+
 flutter:
   uses-material-design: true
   assets:
-- 
GitLab