Browse Source

Merge branch 'hotfix/plum-frog' of lyq/flutter_2048 into main

天问 3 years ago
parent
commit
5b9ac781d5

+ 1 - 0
.devcontainer/Dockerfile

@@ -0,0 +1 @@
+FROM jianboy/flutter-dev-container:3.0.5

+ 45 - 0
.devcontainer/devcontainer.json

@@ -0,0 +1,45 @@
+// java8 + android env
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
+// https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/java-8
+{
+    "name": "Java 11",
+    "build": {
+        "dockerfile": "Dockerfile",
+        "args": {
+            // Use the VARIANT arg to pick a Debian OS version: buster, bullseye
+            // Use bullseye when running on local arm64/Apple Silicon.
+            "VARIANT": "buster",
+            // Options
+            "INSTALL_MAVEN": "true",
+            "INSTALL_GRADLE": "true",
+            "NODE_VERSION": "lts/*"
+        }
+    },
+    // Set *default* container specific settings.json values on container create.
+    "settings": {
+        "java.home": "/docker-java-home",
+        "java.import.gradle.java.home": "/usr/local/sdkman/candidates/java/current",
+        "java.configuration.runtimes": [
+            {
+                "default": true,
+                "name": "JavaSE-11",
+                "path": "/usr/local/sdkman/candidates/java/current"
+            }
+        ]
+    },
+    // Add the IDs of extensions you want installed when the container is created.
+    "extensions": [
+        "vscjava.vscode-java-pack",
+        "dart-code.dart-code",
+        "dart-code.flutter"
+    ],
+    // Use 'forwardPorts' to make a list of ports inside the container available locally.
+    // "forwardPorts": [],
+    // Use 'postCreateCommand' to run commands after the container is created.
+    // "postCreateCommand": "java -version",
+    // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
+    "remoteUser": "vscode",
+    "features": {
+        "docker-in-docker": "latest"
+    }
+}

+ 3 - 3
.github/workflows/build.yml

@@ -17,18 +17,18 @@ jobs:
         uses: actions/setup-java@v2
         with:
           distribution: 'adopt'
-          java-version: "8.x"
+          java-version: "11"
 
       - name: Setup gradle
         uses: eskatos/gradle-command-action@v1
         with:
-          gradle-version: 6.5
+          gradle-version: 7.3.3
 
       - name: Flutter action
         uses: subosito/flutter-action@v1.5.3
         with:
           channel: "stable"
-          flutter-version: "2.0.5"
+          flutter-version: "3.0.5"
       
       - name: Cache Dependencies
         id: cache

+ 66 - 0
.gitpod.Dockerfile

@@ -0,0 +1,66 @@
+FROM gitpod/workspace-full-vnc
+SHELL ["/bin/bash", "-c"]
+
+ENV ANDROID_HOME=/home/gitpod/androidsdk \
+    FLUTTER_VERSION=2.10.5-stable
+
+# Install dart
+USER root
+RUN curl -fsSL https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
+    && curl -fsSL https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list \
+    && install-packages build-essential dart libkrb5-dev gcc make gradle android-tools-adb android-tools-fastboot
+
+# Install flutter
+USER gitpod
+RUN cd /home/gitpod \
+    && wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}.tar.xz \
+    && tar -xvf flutter*.tar.xz \
+    && rm -f flutter*.tar.xz
+
+RUN flutter/bin/flutter precache
+RUN echo 'export PATH="$PATH:/home/gitpod/flutter/bin"' >> /home/gitpod/.bashrc
+
+# Install Open JDK
+USER gitpod
+RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh && \
+    sdk install java 11.0.16-amzn && \
+    sdk default java 11.0.16-amzn"
+
+# Install SDK Manager
+USER gitpod
+RUN  wget https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip \
+    && mkdir -p $ANDROID_HOME/cmdline-tools/latest \
+    && unzip commandlinetools-linux-*.zip -d $ANDROID_HOME \
+    && rm -f commandlinetools-linux-*.zip \
+    && mv $ANDROID_HOME/cmdline-tools/bin $ANDROID_HOME/cmdline-tools/latest \
+    && mv $ANDROID_HOME/cmdline-tools/lib $ANDROID_HOME/cmdline-tools/latest
+
+RUN echo "export ANDROID_HOME=$ANDROID_HOME" >> /home/gitpod/.bashrc \
+    && echo 'export PATH=$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/cmdline-tools/bin:$ANDROID_HOME/platform-tools:$PATH' >> /home/gitpod/.bashrc
+
+# Install Android Image version 30
+USER gitpod
+RUN yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "platform-tools" "platforms;android-30" "emulator"
+RUN yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "system-images;android-30;google_apis;x86_64"
+RUN echo no | $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager create avd -n avd28 -k "system-images;android-30;google_apis;x86_64"
+
+
+# Install Google Chrome
+USER root
+RUN apt-get update \
+  && apt-get install -y apt-transport-https \
+  && curl -sSL https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \
+  && echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \
+  && apt-get update \
+  && sudo apt-get install -y google-chrome-stable
+
+# misc deps
+RUN apt-get install -y \
+  libasound2-dev \
+  libgtk-3-dev \
+  libnss3-dev \
+  fonts-noto \
+  fonts-noto-cjk
+
+# For Qt WebEngine on docker
+ENV QTWEBENGINE_DISABLE_SANDBOX 1

+ 75 - 0
.gitpod.yml

@@ -0,0 +1,75 @@
+image:
+  file: .gitpod.Dockerfile
+tasks:
+  - before: sudo mount -t tmpfs shm -osize=4096m /dev/shm
+  - init: |
+      flutter channel beta
+      flutter upgrade
+
+      # flutter config --enable-web
+      flutter config --android-sdk /home/gitpod/androidsdk
+      yes | flutter doctor --android-licenses
+
+      # flutter doctor
+
+      # flutter pub get
+
+      # flutter build -v bundle
+      # flutter build -v web
+      # flutter build -v appbundle
+      # flutter build -v apk
+      
+  # - command: |
+  #     # Gitpod is not able to run emulators within a worspace at this stage as
+  #     # Google Kubernetes Engine does not support Nested Virtualization.
+  #     #
+  #     # If running Gitpod on your own infrastructure or via the Dockerfile locally
+  #     # on infrastructure that exposes vmx or svm then this command will launch
+  #     # the emulator.
+  #     #
+  #     # $ emulator -avd avd28 -no-audio -no-window 
+  #     #
+  #     # Until this restriction is mitigated you can run native mobile apps in your
+  #     # browser via https://appetize.io/
+
+  #     if [[ -z "$APPETIZE_API_TOKEN" ]]; then
+  #         echo "Appetize API token not set. Run:"
+  #         echo ""
+  #         echo "    gp env APPETIZE_API_TOKEN=your_token"
+  #         echo ""
+  #         echo "and restart this workspace in order to get an app preview."
+  #         echo ""
+  #         echo "Request your token here: https://appetize.io/docs#request-api-token"
+  #     else
+  #         curl -sS --http1.1 "https://$APPETIZE_API_TOKEN@api.appetize.io/v1/apps/$APPETIZE_PUBLICKEY" \
+  #             -F "file=@/workspace/template-flutter/build/app/outputs/flutter-apk/app.apk" \
+  #             -F platform=android \
+  #             -F "buttonText=Start App" \
+  #             -F "postSessionButtonText=Start App" \
+  #             > .appetize.json
+
+  #         APPETIZE_PUBLICKEY=$(jq -r .publicKey .appetize.json)
+  #         gp env "APPETIZE_PUBLICKEY=$APPETIZE_PUBLICKEY"
+  #         export APPETIZE_PUBLICKEY
+
+  #         python -m webbrowser "https://appetize.io/embed/$APPETIZE_PUBLICKEY?device=pixel4&autoplay=true"
+  #     fi
+
+  #     flutter devices
+    
+  #     flutter run --web-port 8080
+
+
+ports:
+  - port: 5900
+    onOpen: ignore
+    # vnc
+  - port: 6080
+    onOpen: open-preview
+    # flutter
+  - port: 8080
+    onOpen: open-preview
+
+vscode:
+  extensions:
+    - dart-code.flutter

+ 2 - 2
android/app/build.gradle

@@ -25,7 +25,7 @@ apply plugin: 'com.android.application'
 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
 
 android {
-    compileSdkVersion 30
+    compileSdkVersion 31
     signingConfigs {
         release {
             storeFile file("sign/flutter_2048.jks")
@@ -41,7 +41,7 @@ android {
     defaultConfig {
         applicationId "yoqi.me.flutter_2048"
         minSdkVersion 16
-        targetSdkVersion 30
+        targetSdkVersion 31
         versionCode flutterVersionCode.toInteger()
         versionName flutterVersionName
     }

+ 0 - 6
android/app/src/main/AndroidManifest.xml

@@ -1,12 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="yoqi.me.flutter_2048">
-    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
-         calls FlutterMain.startInitialization(this); in its onCreate method.
-         In most cases you can leave this as-is, but you if you want to provide
-         additional functionality it is fine to subclass or reimplement
-         FlutterApplication and put your custom class here. -->
     <application
-        android:name="io.flutter.app.FlutterApplication"
         android:label="flutter_2048"
         android:icon="@mipmap/ic_launcher">
         <activity

+ 1 - 1
android/build.gradle

@@ -5,7 +5,7 @@ buildscript {
     }
 
     dependencies {
-        classpath 'com.android.tools.build:gradle:4.1.0'
+        classpath 'com.android.tools.build:gradle:7.2.2'
     }
 }
 

+ 1 - 1
android/gradle/wrapper/gradle-wrapper.properties

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip

+ 6 - 6
lib/generated/intl/messages_all.dart

@@ -20,8 +20,8 @@ import 'messages_zh.dart' as messages_zh;
 
 typedef Future<dynamic> LibraryLoader();
 Map<String, LibraryLoader> _deferredLibraries = {
-  'en': () => new Future.value(null),
-  'zh': () => new Future.value(null),
+  'en': () => Future.value(null),
+  'zh': () => Future.value(null),
 };
 
 MessageLookupByLibrary _findExact(String localeName) {
@@ -42,13 +42,13 @@ Future<bool> initializeMessages(String localeName) async {
     (locale) => _deferredLibraries[locale] != null,
     onFailure: (_) => null);
   if (availableLocale == null) {
-    return new Future.value(false);
+    return Future.value(false);
   }
   var lib = _deferredLibraries[availableLocale];
-  await (lib == null ? new Future.value(false) : lib());
-  initializeInternalMessageLookup(() => new CompositeMessageLookup());
+  await (lib == null ? Future.value(false) : lib());
+  initializeInternalMessageLookup(() => CompositeMessageLookup());
   messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
-  return new Future.value(true);
+  return Future.value(true);
 }
 
 bool _messagesExistFor(String locale) {

+ 2 - 2
lib/generated/intl/messages_en.dart

@@ -12,7 +12,7 @@
 import 'package:intl/intl.dart';
 import 'package:intl/message_lookup_by_library.dart';
 
-final messages = new MessageLookup();
+final messages = MessageLookup();
 
 typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
 
@@ -21,7 +21,7 @@ class MessageLookup extends MessageLookupByLibrary {
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static _notInlinedMessages(_) => <String, Function> {
-    "btnNewGame" : MessageLookupByLibrary.simpleMessage("New Game"),
+    "btnNewGame" : MessageLookupByLibrary.simpleMessage("Game"),
     "labelBest" : MessageLookupByLibrary.simpleMessage("BEST"),
     "labelScore" : MessageLookupByLibrary.simpleMessage("SCORE"),
     "titleName" : MessageLookupByLibrary.simpleMessage("2048"),

+ 1 - 1
lib/generated/intl/messages_zh.dart

@@ -12,7 +12,7 @@
 import 'package:intl/intl.dart';
 import 'package:intl/message_lookup_by_library.dart';
 
-final messages = new MessageLookup();
+final messages = MessageLookup();
 
 typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
 

+ 2 - 2
lib/generated/l10n.dart

@@ -85,10 +85,10 @@ class S {
     );
   }
 
-  /// `New Game`
+  /// `Game`
   String get btnNewGame {
     return Intl.message(
-      'New Game',
+      'Game',
       name: 'btnNewGame',
       desc: '',
       args: [],

+ 2 - 8
lib/main.dart

@@ -6,17 +6,15 @@ import 'package:flutter_localizations/flutter_localizations.dart';
 void main() => runApp(GameApp());
 
 class GameApp extends StatefulWidget {
-  
   @override
   State<StatefulWidget> createState() => _GameAppState();
 }
 
 class _GameAppState extends State<GameApp> {
-
   @override
   Widget build(BuildContext context) {
     return MaterialApp(
-        localizationsDelegates: [
+      localizationsDelegates: [
         S.delegate,
         GlobalMaterialLocalizations.delegate,
         GlobalWidgetsLocalizations.delegate,
@@ -31,11 +29,7 @@ class _GameAppState extends State<GameApp> {
         child: SafeArea(
           left: false,
           right: false,
-          child: Stack(
-            children: [
-              IndexPage(),
-            ],
-          ),
+          child: IndexPage(),
         ),
       ),
     );

+ 13 - 5
lib/model/block_info.dart

@@ -1,19 +1,27 @@
 class BlockInfo {
-  BlockInfo({this.value, this.current, this.before, this.isNew = true}) {
-    this.before = this.before == null ? this.current : this.before;
+  BlockInfo(
+      {required this.value,
+      required this.current,
+      this.before ,
+      this.myis = true}) {
+    if (this.before == null) {
+      this.before = this.current;
+    } else {
+      this.before = this.before;
+    }
   }
 
   int value;
   int current;
-  int before;
+  int? before;
   bool needMove = false;
   bool needCombine = false;
-  bool isNew = false;
+  bool myis = false;
 
   void reset() {
     value = 0;
     needMove = false;
     needCombine = false;
-    isNew = false;
+    myis = false;
   }
 }

+ 5 - 5
lib/model/game_status.dart

@@ -1,11 +1,11 @@
 /// 当前状态
 class GameStatus {
   GameStatus({
-    this.adds,
-    this.moves,
-    this.scores,
-    this.total,
-    this.end,
+    required this.adds,
+    required this.moves,
+    required this.scores,
+    required this.total,
+    required this.end,
   });
 
   int scores;

+ 2 - 3
lib/pages/index_page.dart

@@ -16,7 +16,6 @@ import '../store/game_state.dart';
 
 /// 首页
 class IndexPage extends StatelessWidget {
-
   @override
   Widget build(BuildContext context) {
     //ScreenUtil 初始化实例
@@ -25,7 +24,7 @@ class IndexPage extends StatelessWidget {
             maxWidth: MediaQuery.of(context).size.width,
             maxHeight: MediaQuery.of(context).size.height),
         designSize: Size(360, 640),
-        orientation: Orientation.portrait);  // 竖屏
+        orientation: Orientation.portrait); // 竖屏
 
     return StoreProvider(
       store: Store<GameState>(
@@ -69,5 +68,5 @@ class IndexPage extends StatelessWidget {
 class GameProps {
   bool started;
 
-  GameProps({this.started});
+  GameProps({required this.started});
 }

+ 4 - 4
lib/responsive.dart

@@ -9,10 +9,10 @@ class Responsive extends StatelessWidget {
   final Widget desktop;
 
   const Responsive({
-    Key key,
-    @required this.mobile,
-    @required this.tablet,
-    @required this.desktop,
+    Key? key,
+    required this.mobile,
+    required this.tablet,
+    required this.desktop,
   }) : super(key: key);
 
 // This size work fine on my design, maybe you need some customization depends on your design

+ 4 - 3
lib/router/routes.dart → lib/routes.dart

@@ -1,15 +1,16 @@
 import 'package:flutter/cupertino.dart';
 
 class Routes {
-  static final Router router = new Router(
+  static const ROOT = '/';
+
+  static final Router router = Router(
     routerDelegate: null,
   );
-  static const ROOT = '/';
   static Routes _instance;
 
   static Routes get instance {
     if (_instance == null) {
-      _instance = new Routes();
+      _instance = Routes();
     }
     return _instance;
   }

+ 1 - 2
lib/service/block_factory.dart

@@ -1,4 +1,3 @@
-import 'package:flutter/animation.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_2048/views/block/combin_block.dart';
 import 'package:flutter_2048/views/block/move_block.dart';
@@ -23,7 +22,7 @@ class BlockFactory {
   }
 
   Widget create(BlockInfo info) {
-    if (info.isNew) {
+    if (info.myis) {
       return NewBlock(
         info: info,
         controller: this.addController,

+ 1 - 2
lib/service/gameInit.dart

@@ -9,8 +9,7 @@ gameInit(Store<GameState> store, int mode) async {
 
   var key = 'total_' + mode.toString();
 
-  if (store.state.status.total != null &&
-      store.state.status.scores > store.state.status.total) {
+  if (store.state.status.scores > store.state.status.total) {
     prefs.setInt(key, store.state.status.scores);
   }
   var state = GameState.initial(mode);

+ 6 - 6
lib/store/game_state.dart

@@ -4,7 +4,7 @@ import 'package:flutter_2048/model/block_info.dart';
 import 'package:flutter_2048/model/game_status.dart';
 
 class GameState {
-  GameState({this.data, this.status, this.mode});
+  GameState({required this.data, required this.status, required this.mode});
 
   int mode;
   GameStatus status;
@@ -12,7 +12,7 @@ class GameState {
 
   /// 初始化
   static GameState initial(int mode) {
-    var random = new Random(DateTime.now().millisecondsSinceEpoch);
+    var random = Random(DateTime.now().millisecondsSinceEpoch);
     var gamesize = mode * mode;
     var block1 = random.nextInt(gamesize);
     var block2 = random.nextInt(gamesize);
@@ -55,7 +55,7 @@ class GameState {
     for (var i = 0; i < mode; i++) {
       for (var j = 0; j < mode; j++) {
         var block = getBlock(i, j);
-        block.isNew = false;
+        block.myis= false;
         if (block.value == 0) {
           count++;
         }
@@ -65,13 +65,13 @@ class GameState {
     // 有空格
     if (count > 0) {
       // 生成新的数字
-      var random = new Random(DateTime.now().millisecondsSinceEpoch);
+      var random = Random(DateTime.now().millisecondsSinceEpoch);
       var newpos = getBlankPosition(random.nextInt(count));
 
       var newblock = getBlock(newpos ~/ mode, newpos % mode);
       newblock.value = (random.nextInt(2) + 1) * 2;
       newblock.before = newblock.current = newpos;
-      newblock.isNew = true;
+      newblock.myis = true;
       newblock.needCombine = newblock.needMove = false;
     }
 
@@ -136,7 +136,7 @@ class GameState {
         row.add(BlockInfo(
           current: data[i][j].current,
           value: data[i][j].value,
-          isNew: false,
+          myis: false,
         ));
       }
       newdata.add(row);

+ 53 - 0
lib/utils/sp_utils.dart

@@ -0,0 +1,53 @@
+import 'package:shared_preferences/shared_preferences.dart';
+
+class SpUtil {
+  static Future<SharedPreferences> sharedPreferences =
+      SharedPreferences.getInstance();
+
+  static Future<T> get<T>(String key, T defaultValue) {
+    return sharedPreferences.then((s) {
+      if (s.get(key) == null) {
+        return defaultValue;
+      } else {
+        return s.get(key) as T;
+      }
+    });
+  }
+
+  static Future<bool> save<T>(String key, T value) async {
+    return sharedPreferences.then((s) {
+      if (value == null) {
+        return s.remove(key);
+      } else {
+        if (value is int) {
+          return s.setInt(key, value);
+        }
+        if (value is double) {
+          return s.setDouble(key, value);
+        }
+        if (value is String) {
+          return s.setString(key, value);
+        }
+        if (value is List<String>) {
+          return s.setStringList(key, value);
+        }
+        if (value is bool) {
+          return s.setBool(key, value);
+        }
+      }
+      return false;
+    });
+  }
+
+  static Future<bool> remove(String key) {
+    return sharedPreferences.then((s) {
+      return s.remove(key);
+    });
+  }
+
+  static Future<bool> clear() {
+    return sharedPreferences.then((s) {
+      return s.clear();
+    });
+  }
+}

+ 2 - 2
lib/views/block/base_block.dart

@@ -4,7 +4,7 @@ import 'package:flutter_2048/utils/screen.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 
 abstract class BaseBlock extends AnimatedWidget {
-  BaseBlock({Key key, Animation animation})
+  BaseBlock({Key? key, required Animation animation})
       : super(
           key: key,
           listenable: animation,
@@ -34,5 +34,5 @@ class BlockProps {
   double borderWidth;
   int mode;
 
-  BlockProps({this.blockWidth, this.borderWidth, this.mode});
+  BlockProps({required this.blockWidth, required this.borderWidth, required this.mode});
 }

+ 6 - 6
lib/views/block/combin_block.dart

@@ -10,11 +10,11 @@ class CombinBlock extends BaseBlock {
   final AnimationController moveController;
 
   CombinBlock({
-    Key key,
-    this.info,
-    this.mode,
-    this.moveController,
-    AnimationController combinController,
+    Key? key,
+    required this.info,
+    required this.mode,
+    required this.moveController,
+    required AnimationController combinController,
   }) : super(
           key: key,
           animation:
@@ -29,7 +29,7 @@ class CombinBlock extends BaseBlock {
       children: [
         MoveBlock(
           info: BlockInfo(
-            isNew: false,
+            myis: false,
             value: info.value ~/ 2,
             before: info.before,
             current: info.current,

+ 4 - 4
lib/views/block/move_block.dart

@@ -16,10 +16,10 @@ class MoveBlock extends BaseBlock {
   final int mode;
 
   MoveBlock({
-    Key key,
-    this.info,
-    this.mode,
-    AnimationController controller,
+    Key? key,
+    required this.info,
+    required this.mode,
+    required AnimationController controller,
   }) : super(
           key: key,
           animation: Tween<double>(begin: getBegin(info, mode), end: 0)

+ 4 - 4
lib/views/block/new_block.dart

@@ -7,12 +7,12 @@ class NewBlock extends BaseBlock {
   final BlockInfo info;
 
   NewBlock({
-    Key key,
-    this.info,
-    AnimationController controller,
+    Key? key,
+    required this.info,
+    required AnimationController controller,
   }) : super(
           key: key,
-          animation: new Tween<double>(begin: 0.1, end: 1.0).animate(controller),
+          animation: Tween<double>(begin: 0.1, end: 1.0).animate(controller),
         );
 
   @override

+ 4 - 4
lib/views/block/static_block.dart

@@ -8,13 +8,13 @@ class StaticBlock extends BaseBlock {
   final BlockInfo info;
 
   StaticBlock({
-    Key key,
-    this.info,
-    AnimationController controller,
+    Key? key,
+    required this.info,
+    required AnimationController controller,
   }) : super(
           key: key,
           animation:
-              new Tween<double>(begin: 0.0, end: 0.0).animate(controller),
+              Tween<double>(begin: 0.0, end: 0.0).animate(controller),
         );
 
   @override

+ 1 - 1
lib/views/blocks.dart

@@ -56,5 +56,5 @@ class BlocksProps {
   double padding;
   List<List<BlockInfo>> data;
 
-  BlocksProps({this.padding, this.mode, this.data});
+  BlocksProps({required this.padding, required this.mode, required this.data});
 }

+ 1 - 1
lib/views/game_bg.dart

@@ -71,5 +71,5 @@ class GameBgProps {
   double blockWidth; //块大小
   int mode; //游戏模式,3*3 4*4 6*6
 
-  GameBgProps({this.borderWidth, this.blockWidth, this.mode});
+  GameBgProps({required this.borderWidth, required this.blockWidth, required this.mode});
 }

+ 1 - 1
lib/views/mode_selector.dart

@@ -40,7 +40,7 @@ class ModeSelector extends StatelessWidget {
 }
 
 class ModeSelectorProps {
-  ModeSelectorProps({this.mode, this.onChange});
+  ModeSelectorProps({required this.mode, required this.onChange});
 
   int mode;
   Function onChange;

+ 4 - 4
lib/views/number_text.dart

@@ -4,7 +4,7 @@ class BlockStyle {
   Color textColor;
   Color background;
 
-  BlockStyle({this.textColor, this.background});
+  BlockStyle({required this.textColor, required this.background});
 }
 
 var styles = Map.fromEntries([
@@ -36,7 +36,7 @@ class NumberText extends StatelessWidget {
   final int value;
   final double size;
 
-  NumberText({this.value, this.size});
+  NumberText({required this.value, required this.size});
 
   @override
   Widget build(BuildContext context) {
@@ -57,8 +57,8 @@ class NumberText extends StatelessWidget {
           style: TextStyle(
             fontWeight: FontWeight.bold,
             color: (this.value ~/ 2048) > 1
-                ? styles[this.value ~/ 2048].textColor
-                : styles[this.value].textColor,
+                ? styles[this.value ~/ 2048]?.textColor
+                : styles[this.value]?.textColor,
             fontSize:
                 size / (numberText.length <= 2 ? 2 : numberText.length * 0.8),
           ),

+ 9 - 10
lib/views/playground.dart

@@ -1,5 +1,4 @@
 import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 import '../reducers/moveDown.dart';
 import '../reducers/moveLeft.dart';
@@ -80,9 +79,9 @@ class Playground extends StatelessWidget {
   void onVerticalDragEnd(DragEndDetails evt, PlaygroundProps props) {
     if (DateTime.now().millisecondsSinceEpoch - props.startTime >
             pressTimeout ||
-        evt.primaryVelocity.abs() < dragLength) return;
+        evt.primaryVelocity!.abs() < dragLength) return;
     // 是否ios和android纵轴是相反的?
-    if (evt.primaryVelocity < 0) {
+    if (evt.primaryVelocity! < 0) {
       props.onUp();
     } else {
       props.onDown();
@@ -100,12 +99,12 @@ class PlaygroundProps {
   Function onDown;
 
   PlaygroundProps({
-    this.end,
-    this.mode,
-    this.startTime,
-    this.onDown,
-    this.onLeft,
-    this.onRight,
-    this.onUp,
+    required this.end,
+    required this.mode,
+    required this.startTime,
+    required this.onDown,
+    required this.onLeft,
+    required this.onRight,
+    required this.onUp,
   });
 }

+ 1 - 1
lib/views/scores.dart

@@ -128,7 +128,7 @@ class Scores extends StatelessWidget {
 }
 
 class ScoresProps {
-  ScoresProps({this.mode, this.total, this.scores, this.isEnd, this.reset});
+  ScoresProps({required this.mode, required this.total, required this.scores, required this.isEnd, required this.reset});
 
   int mode;
   int total;

+ 2 - 0
linux/flutter/generated_plugin_registrant.cc

@@ -2,6 +2,8 @@
 //  Generated file. Do not edit.
 //
 
+// clang-format off
+
 #include "generated_plugin_registrant.h"
 
 

+ 2 - 0
linux/flutter/generated_plugin_registrant.h

@@ -2,6 +2,8 @@
 //  Generated file. Do not edit.
 //
 
+// clang-format off
+
 #ifndef GENERATED_PLUGIN_REGISTRANT_
 #define GENERATED_PLUGIN_REGISTRANT_
 

+ 8 - 0
linux/flutter/generated_plugins.cmake

@@ -5,6 +5,9 @@
 list(APPEND FLUTTER_PLUGIN_LIST
 )
 
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+)
+
 set(PLUGIN_BUNDLED_LIBRARIES)
 
 foreach(plugin ${FLUTTER_PLUGIN_LIST})
@@ -13,3 +16,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
   list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
   list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
 endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
+  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)

+ 53 - 39
pubspec.lock

@@ -7,7 +7,7 @@ packages:
       name: async
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.5.0"
+    version: "2.8.2"
   boolean_selector:
     dependency: transitive
     description:
@@ -21,14 +21,14 @@ packages:
       name: characters
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.1.0"
+    version: "1.2.0"
   charcode:
     dependency: transitive
     description:
       name: charcode
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.2.0"
+    version: "1.3.1"
   clock:
     dependency: transitive
     description:
@@ -42,21 +42,21 @@ packages:
       name: collection
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.15.0"
+    version: "1.16.0"
   cupertino_icons:
     dependency: "direct main"
     description:
       name: cupertino_icons
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.0.3"
+    version: "1.0.5"
   device_info:
     dependency: "direct main"
     description:
       name: device_info
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.2"
+    version: "2.0.3"
   device_info_platform_interface:
     dependency: transitive
     description:
@@ -70,14 +70,14 @@ packages:
       name: fake_async
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.2.0"
+    version: "1.3.0"
   ffi:
     dependency: transitive
     description:
       name: ffi
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.1.2"
+    version: "2.0.1"
   file:
     dependency: transitive
     description:
@@ -101,14 +101,14 @@ packages:
       name: flutter_redux
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.8.2"
+    version: "0.10.0"
   flutter_screenutil:
     dependency: "direct main"
     description:
       name: flutter_screenutil
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "4.0.4+1"
+    version: "5.5.3+2"
   flutter_test:
     dependency: "direct dev"
     description: flutter
@@ -132,70 +132,77 @@ packages:
       name: js
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.6.3"
+    version: "0.6.4"
   matcher:
     dependency: transitive
     description:
       name: matcher
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.12.10"
+    version: "0.12.11"
+  material_color_utilities:
+    dependency: transitive
+    description:
+      name: material_color_utilities
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "0.1.4"
   meta:
     dependency: transitive
     description:
       name: meta
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.3.0"
+    version: "1.7.0"
   path:
     dependency: transitive
     description:
       name: path
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.8.0"
+    version: "1.8.1"
   path_provider_linux:
     dependency: transitive
     description:
       name: path_provider_linux
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.2"
+    version: "2.1.7"
   path_provider_platform_interface:
     dependency: transitive
     description:
       name: path_provider_platform_interface
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.1"
+    version: "2.0.4"
   path_provider_windows:
     dependency: transitive
     description:
       name: path_provider_windows
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.3"
+    version: "2.1.2"
   platform:
     dependency: transitive
     description:
       name: platform
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "3.0.2"
+    version: "3.1.0"
   plugin_platform_interface:
     dependency: transitive
     description:
       name: plugin_platform_interface
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.1"
+    version: "2.1.2"
   process:
     dependency: transitive
     description:
       name: process
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "4.2.3"
+    version: "4.2.4"
   redux:
     dependency: transitive
     description:
@@ -216,21 +223,35 @@ packages:
       name: shared_preferences
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.6"
+    version: "2.0.15"
+  shared_preferences_android:
+    dependency: transitive
+    description:
+      name: shared_preferences_android
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "2.0.12"
+  shared_preferences_ios:
+    dependency: transitive
+    description:
+      name: shared_preferences_ios
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "2.1.1"
   shared_preferences_linux:
     dependency: transitive
     description:
       name: shared_preferences_linux
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.2"
+    version: "2.1.1"
   shared_preferences_macos:
     dependency: transitive
     description:
       name: shared_preferences_macos
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.2"
+    version: "2.0.4"
   shared_preferences_platform_interface:
     dependency: transitive
     description:
@@ -244,14 +265,14 @@ packages:
       name: shared_preferences_web
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.1"
+    version: "2.0.4"
   shared_preferences_windows:
     dependency: transitive
     description:
       name: shared_preferences_windows
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.2"
+    version: "2.1.1"
   sky_engine:
     dependency: transitive
     description: flutter
@@ -263,7 +284,7 @@ packages:
       name: source_span
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.8.0"
+    version: "1.8.2"
   stack_trace:
     dependency: transitive
     description:
@@ -298,35 +319,28 @@ packages:
       name: test_api
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.2.19"
-  typed_data:
-    dependency: transitive
-    description:
-      name: typed_data
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.3.0"
+    version: "0.4.9"
   vector_math:
     dependency: transitive
     description:
       name: vector_math
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.1.0"
+    version: "2.1.2"
   win32:
     dependency: transitive
     description:
       name: win32
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.5"
+    version: "2.7.0"
   xdg_directories:
     dependency: transitive
     description:
       name: xdg_directories
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.2.0"
+    version: "0.2.0+1"
 sdks:
-  dart: ">=2.12.0 <3.0.0"
-  flutter: ">=2.0.0"
+  dart: ">=2.17.6 <3.0.0"
+  flutter: ">=3.0.0"

+ 6 - 6
pubspec.yaml

@@ -3,7 +3,7 @@ description: 2048 game.
 version: 1.0.0+1
 
 environment:
-  sdk: ">=2.7.0 <3.0.0"
+  sdk: ">=2.17.6 <3.0.0"
 
 dependencies:
   flutter:
@@ -12,12 +12,12 @@ dependencies:
   flutter_localizations: # 国际化
     sdk: flutter
   intl: ^0.17.0
-  cupertino_icons: ^1.0.3 # ios风格图标
-  flutter_screenutil: ^4.0.3+2 # 屏幕工具
-  device_info: ^2.0.2
-  flutter_redux: ^0.8.2 # 状态管理
+  cupertino_icons: ^1.0.5 # ios风格图标
+  flutter_screenutil: ^5.5.3+2 # 屏幕工具
+  device_info: ^2.0.3
+  flutter_redux: ^0.10.0 # 状态管理
   redux_thunk: ^0.4.0
-  shared_preferences: ^2.0.7
+  shared_preferences: ^2.0.15
 
 dev_dependencies:
   flutter_test: