x1ongzhu 6 éve
szülő
commit
b1e0c9721b

+ 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 27
+    compileSdkVersion 28
 
     lintOptions {
         disable 'InvalidPackage'
@@ -34,7 +34,7 @@ android {
     defaultConfig {
         applicationId "com.izouma.mobilecybergames"
         minSdkVersion 19
-        targetSdkVersion 27
+        targetSdkVersion 28
         versionCode flutterVersionCode.toInteger()
         versionName flutterVersionName
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

+ 5 - 4
android/app/src/main/AndroidManifest.xml

@@ -18,10 +18,11 @@
         android:name="io.flutter.app.FlutterApplication"
         android:icon="@mipmap/ic_launcher"
         android:label="全民电竞">
-        <service
-            android:name=".ScreenStreamService"
-            android:enabled="true"
-            android:exported="true"></service>
+        
+        <activity
+            android:name="com.yalantis.ucrop.UCropActivity"
+            android:screenOrientation="portrait"
+            android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
 
         <activity
             android:name=".MainActivity"

+ 2 - 0
android/gradle.properties

@@ -1 +1,3 @@
 org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true

+ 28 - 19
lib/net/HttpManager.dart

@@ -15,36 +15,45 @@ class HttpManager {
     return Dio(options);
   }
 
-  static Future<Result> post(String url, {Map<String, dynamic> data}) {
-    return Future(() async {
+  static Future<Result> post(String url, {Map<String, dynamic> data}) async {
+    Result result = Result.empty();
+    try {
       FormData formData = FormData.from(data ?? {});
       Response response = await _createDio().post(url, data: formData);
       print(response);
       if (response.statusCode != 200) {
-        return Future.error("httpCode" + response.statusCode.toString());
+        result.success = false;
+        result.error = "httpCode" + response.statusCode.toString();
+        return result;
       }
-      Result result = Result.fromJson(response.data);
+      result = Result.fromJson(response.data);
       return result;
-    });
+    } catch (e) {
+      result.success = false;
+      result.error = e.toString();
+    }
+    return result;
   }
 
-  static Future<Result> get(String url, {Map<String, dynamic> data}) {
-    return Future(() async {
-      Response response =
-          await _createDio().get(url, queryParameters: data ?? {});
+  static Future<Result> get(String url, {Map<String, dynamic> data}) async {
+    Result result = Result.empty();
+    try {
+      Response response = await _createDio().get(url, queryParameters: data ?? {});
       if (response.statusCode != 200) {
-        return Future.error("httpCode" + response.statusCode.toString());
+        result.success = false;
+        result.error = "httpCode" + response.statusCode.toString();
+        return result;
       }
-      Result result = Result.fromJson(response.data);
+      result = Result.fromJson(response.data);
       return result;
-    });
+    } catch (e) {
+      result.success = false;
+      result.error = e.toString();
+    }
+    return result;
   }
 }
 
-
-
-String readTimestamp(int timestamp,String _timeType) {
-   
-
-    return DateFormat(_timeType).format(DateTime.fromMillisecondsSinceEpoch(timestamp));
-  }
+String readTimestamp(int timestamp, String _timeType) {
+  return DateFormat(_timeType).format(DateTime.fromMillisecondsSinceEpoch(timestamp));
+}

+ 55 - 53
lib/pages/UserChange.dart

@@ -4,17 +4,13 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:dio/dio.dart';
 import 'package:intl/intl.dart';
-import 'package:jpush_flutter/jpush_flutter.dart';
 import 'package:package_info/package_info.dart';
-import 'package:shared_preferences/shared_preferences.dart';
 import '../styles/colors.dart';
 import 'dart:io';
 import 'dart:async';
-import 'dart:convert';
 import 'dart:ui';
 import '../styles/totast.dart';
-import 'ChangeUserInfo.dart'; //修改信息页面
-import 'loginFirst.dart'; //登录
+import 'ChangeUserInfo.dart';
 import 'package:redux/redux.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 import '../redux/AppState.dart';
@@ -22,6 +18,7 @@ import '../model/UserInfo.dart';
 import '../net/HttpManager.dart';
 import '../net/Result.dart';
 import '../redux/UserRedux.dart';
+import 'package:image_cropper/image_cropper.dart';
 
 class UserChange extends StatefulWidget {
   @override
@@ -32,22 +29,6 @@ class UserChangeState extends State<UserChange> {
   String version = "";
   bool receiveMsg = false;
 
-  void getFilePath() async {
-    String filePath = await FilePicker.getFilePath(type: FileType.IMAGE);
-    if (filePath == null) {
-      return;
-    }
-    File _file = File(filePath);
-    Toast.show(context, '加载中', -1, 'loading');
-    Result res = await HttpManager.post("assets/uploadFile", data: {
-      "file": UploadFileInfo(_file, filePath),
-    });
-    Toast.hide();
-    if (res.success) {
-      updateUserInfo(StoreProvider.of<AppState>(context).state.userInfo, res.data[0], 'icon');
-    } else {}
-  }
-
   @override
   void initState() {
     super.initState();
@@ -92,19 +73,31 @@ class UserChangeState extends State<UserChange> {
                               _sectionDivier(),
                               _section([
                                 _cell(
-                                    '头像',
-                                    ClipOval(
-                                      child: Image.network(userInfo.icon, width: 36, height: 36),
-                                    ), onTap: () {
-                                  getFilePath();
-                                }),
-                                _cell('昵称', userInfo.nickname, placeholder: '请填写昵称', onTap: () {
-                                  Navigator.push(
-                                      context, new CupertinoPageRoute(builder: (context) => new ChangeUserInfo(title: '昵称', val: userInfo.nickname)));
-                                }),
-                                _cell('性别', userInfo.sex, placeholder: '请添加性别信息', onTap: () {
-                                  _chooseSex(context);
-                                }),
+                                  '头像',
+                                  ClipOval(
+                                    child: Image.network(userInfo.icon, width: 36, height: 36),
+                                  ),
+                                  onTap: () {
+                                    _chooseImage();
+                                  },
+                                ),
+                                _cell(
+                                  '昵称',
+                                  userInfo.nickname,
+                                  placeholder: '请填写昵称',
+                                  onTap: () {
+                                    Navigator.push(
+                                        context, new CupertinoPageRoute(builder: (context) => new ChangeUserInfo(title: '昵称', val: userInfo.nickname)));
+                                  },
+                                ),
+                                _cell(
+                                  '性别',
+                                  userInfo.sex,
+                                  placeholder: '请添加性别信息',
+                                  onTap: () {
+                                    _chooseSex(context);
+                                  },
+                                ),
                                 _cell(
                                   '生日',
                                   DateFormat('yyyy-MM-dd').format(
@@ -119,7 +112,6 @@ class UserChangeState extends State<UserChange> {
                                   Navigator.push(context, new CupertinoPageRoute(builder: (context) => new ChangeUserInfo(title: '手机号', val: userInfo.phone)));
                                 })
                               ]),
-                             
                             ],
                           ),
                         ),
@@ -200,15 +192,14 @@ class UserChangeState extends State<UserChange> {
                 onPressed: () {
                   Navigator.pop(context, '女');
                 },
-              ),
-              CupertinoDialogAction(
-                child: const Text('取消'),
-                isDestructiveAction: true,
-                onPressed: () {
-                  Navigator.pop(context);
-                },
               )
             ],
+            cancelButton: CupertinoDialogAction(
+              child: const Text('取消'),
+              onPressed: () {
+                Navigator.pop(context);
+              },
+            ),
           );
         });
     if (sex != null) {
@@ -295,19 +286,30 @@ class UserChangeState extends State<UserChange> {
     }
   }
 
-  _chooseImage(BuildContext context) async {
-    UserInfo userInfo = StoreProvider.of<AppState>(context).state.userInfo;
-    var image = await FilePicker.getFilePath(type: FileType.IMAGE);
+  _chooseImage() async {
+    String path = await FilePicker.getFilePath(type: FileType.IMAGE);
+    if (path == null) {
+      return;
+    }
+    File croppedFile = await ImageCropper.cropImage(
+      sourcePath: path,
+      ratioX: 1.0,
+      ratioY: 1.0,
+      maxWidth: 512,
+      maxHeight: 512,
+      toolbarColor: PRIMARY_COLOR,
+    );
+    if (croppedFile == null) {
+      return;
+    }
     Toast.show(context, '加载中', -1, 'loading');
-    File _image = File(image);
-    _image.readAsBytes().then((bytes) async {
-      String encoded1 = 'data:image/jpeg;base64,' + base64Encode(bytes);
-      FormData formData = new FormData.from({"base64": encoded1});
-      Result res = await HttpManager.post('assets/uploadImg', data: formData);
-      if (res.success) {
-        updateUserInfo(userInfo, res.data, 'icon');
-      }
+    Result res = await HttpManager.post("assets/uploadFile", data: {
+      "file": UploadFileInfo(croppedFile, croppedFile.path),
     });
+    Toast.hide();
+    if (res.success) {
+      updateUserInfo(StoreProvider.of<AppState>(context).state.userInfo, res.data[0], 'icon');
+    }
   }
 
   Widget _sectionDivier() {

+ 31 - 89
lib/pages/openRoom.dart

@@ -27,30 +27,26 @@ class OpenRoom extends StatefulWidget {
 
 class OpenRoomState extends State<OpenRoom> {
   TextStyle titleStyle = TextStyle(color: Colors.white, fontSize: 14);
-  TextStyle valStyle =
-      TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.w500);
+  TextStyle valStyle = TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.w500);
 
-  Map<String, dynamic> editRoomInfo = {
-    "gameId": 1,
-    "houseLevel": 1,
-    "maxNumber": 10
-  };
+  Map<String, dynamic> editRoomInfo = {"gameId": 1, "houseLevel": 1, "maxNumber": 10};
   List<GameInfo> gameList = [];
   List<HouseLevel> levelList = [];
 
   void getFilePath() async {
-    String filePath = await FilePicker.getFilePath(type: FileType.ANY);
-    File _file = File(filePath);
+    File file = await FilePicker.getFile(type: FileType.ANY);
+    if (file == null) return;
+    print(file.statSync());
     Toast.show(context, '加载中', -1, 'loading');
     Result res = await HttpManager.post("assets/uploadFile", data: {
-      "file": UploadFileInfo(_file, filePath),
+      "file": UploadFileInfo(file, file.path),
     });
     Toast.hide();
     if (res.success) {
       setState(() {
         editRoomInfo['video'] = res.data[0];
       });
-    } else {}
+    }
   }
 
   void saveInfo() async {
@@ -66,15 +62,11 @@ class OpenRoomState extends State<OpenRoom> {
       Toast.show(context, '请选择房间等级', 1500, 'info');
       return;
     }
-    if (editRoomInfo['houseType'] == '1' &&
-        (editRoomInfo['gameHouseId'] == null ||
-            editRoomInfo['gameHouseId'] == '')) {
+    if (editRoomInfo['houseType'] == '1' && (editRoomInfo['gameHouseId'] == null || editRoomInfo['gameHouseId'] == '')) {
       Toast.show(context, '请录入游戏房间号', 1500, 'info');
       return;
     }
-    if (editRoomInfo['houseType'] == '1' &&
-        (editRoomInfo['gameHousePassword'] == null ||
-            editRoomInfo['gameHousePassword'] == '')) {
+    if (editRoomInfo['houseType'] == '1' && (editRoomInfo['gameHousePassword'] == null || editRoomInfo['gameHousePassword'] == '')) {
       Toast.show(context, '请录入游戏房间密码', 1500, 'info');
       return;
     }
@@ -85,8 +77,7 @@ class OpenRoomState extends State<OpenRoom> {
           chooseLevelInfo = item;
         }
       }
-      if (StoreProvider.of<AppState>(context).state.userInfo.moneyCoin <
-          chooseLevelInfo.entryCoin) {
+      if (StoreProvider.of<AppState>(context).state.userInfo.moneyCoin < chooseLevelInfo.entryCoin) {
         return;
       }
     } else {
@@ -114,23 +105,15 @@ class OpenRoomState extends State<OpenRoom> {
       );
       return;
     }
-    editRoomInfo['createUser'] =
-        StoreProvider.of<AppState>(context).state.userInfo.id;
+    editRoomInfo['createUser'] = StoreProvider.of<AppState>(context).state.userInfo.id;
     Toast.show(context, '加载中', -1, 'loading');
     Result res = await HttpManager.post("houseInfo/save", data: editRoomInfo);
     Toast.hide();
     if (res.success) {
-      HttpManager.post("houseInfo/join", data: {
-        "houseId": res.data,
-        "userId": StoreProvider.of<AppState>(context).state.userInfo.id
-      });
+      HttpManager.post("houseInfo/join", data: {"houseId": res.data, "userId": StoreProvider.of<AppState>(context).state.userInfo.id});
       Toast.show(context, '创建成功', 1500, 'success');
       Future.delayed(Duration(milliseconds: 1500), () {
-        Navigator.pushReplacement(
-            context,
-            new CupertinoPageRoute(
-                builder: (context) =>
-                    new RoomInfo(roomId: res.data.toString())));
+        Navigator.pushReplacement(context, new CupertinoPageRoute(builder: (context) => new RoomInfo(roomId: res.data.toString())));
       });
     } else {}
   }
@@ -147,11 +130,7 @@ class OpenRoomState extends State<OpenRoom> {
         gameList = _list;
         if (res.data.length > 0) {
           editRoomInfo['gameId'] = res.data[0]['id'];
-          editRoomInfo['houseName'] =
-              StoreProvider.of<AppState>(context).state.userInfo.nickname +
-                  '的' +
-                  res.data[0]['shortName'] +
-                  '房间';
+          editRoomInfo['houseName'] = StoreProvider.of<AppState>(context).state.userInfo.nickname + '的' + res.data[0]['shortName'] + '房间';
           editRoomInfo['houseAbstract'] = res.data[0]['profile'] ?? '';
         }
       });
@@ -212,8 +191,7 @@ class OpenRoomState extends State<OpenRoom> {
                 child: FlatButton(
                   highlightColor: PRIMARY_COLOR,
                   padding: EdgeInsets.only(right: 0),
-                  child: Text('规则',
-                      style: TextStyle(color: Colors.white, fontSize: 13)),
+                  child: Text('规则', style: TextStyle(color: Colors.white, fontSize: 13)),
                   onPressed: () {},
                 ),
               )
@@ -274,11 +252,8 @@ class OpenRoomState extends State<OpenRoom> {
                           Padding(
                             padding: EdgeInsets.only(top: 12),
                             child: Text(
-                              editRoomInfo.containsKey('video')
-                                  ? '已选择'
-                                  : '不上传则自动使用官方默认视频',
-                              style: TextStyle(
-                                  color: Color(0xFF9BA0AE), fontSize: 13),
+                              editRoomInfo.containsKey('video') ? '已选择' : '不上传则自动使用官方默认视频',
+                              style: TextStyle(color: Color(0xFF9BA0AE), fontSize: 13),
                             ),
                           )
                         ],
@@ -388,24 +363,17 @@ class OpenRoomState extends State<OpenRoom> {
                           children: <Widget>[
                             Padding(
                               padding: EdgeInsets.only(right: 6),
-                              child: Image.asset('images/icon_jinbi_da_bai.png',
-                                  width: 20),
+                              child: Image.asset('images/icon_jinbi_da_bai.png', width: 20),
                             ),
                             Text(
                               '×' + (chooseLevelInfo.entryCoin ?? 0).toString(),
-                              style: TextStyle(
-                                  color: Colors.white,
-                                  fontSize: 16,
-                                  fontWeight: FontWeight.w500),
+                              style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500),
                             ),
                             Padding(
                               padding: EdgeInsets.only(left: 20),
                               child: Text(
                                 '创建房间',
-                                style: TextStyle(
-                                    color: Colors.white,
-                                    fontSize: 16,
-                                    fontWeight: FontWeight.w500),
+                                style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500),
                               ),
                             )
                           ],
@@ -502,19 +470,14 @@ class OpenRoomState extends State<OpenRoom> {
     new Picker(
         confirmText: '确定',
         cancelText: "取消",
-        adapter: PickerDataAdapter<String>(
-            pickerdata: new JsonDecoder().convert(PickerData)),
+        adapter: PickerDataAdapter<String>(pickerdata: new JsonDecoder().convert(PickerData)),
         changeToFirst: true,
         textAlign: TextAlign.left,
         columnPadding: const EdgeInsets.all(8.0),
         onConfirm: (Picker picker, List value) {
           setState(() {
             editRoomInfo['gameId'] = gameList[value[0]].id;
-            editRoomInfo['houseName'] =
-                StoreProvider.of<AppState>(context).state.userInfo.nickname +
-                    '的' +
-                    gameList[value[0]].shortName +
-                    '房间';
+            editRoomInfo['houseName'] = StoreProvider.of<AppState>(context).state.userInfo.nickname + '的' + gameList[value[0]].shortName + '房间';
             editRoomInfo['houseAbstract'] = gameList[value[0]].profile ?? '';
           });
         }).showModal(this.context);
@@ -530,8 +493,7 @@ class OpenRoomState extends State<OpenRoom> {
     new Picker(
         confirmText: '确定',
         cancelText: "取消",
-        adapter: PickerDataAdapter<String>(
-            pickerdata: new JsonDecoder().convert(PickerData)),
+        adapter: PickerDataAdapter<String>(pickerdata: new JsonDecoder().convert(PickerData)),
         changeToFirst: true,
         textAlign: TextAlign.left,
         columnPadding: const EdgeInsets.all(8.0),
@@ -551,8 +513,7 @@ class OpenRoomState extends State<OpenRoom> {
     new Picker(
         confirmText: '确定',
         cancelText: "取消",
-        adapter: PickerDataAdapter<String>(
-            pickerdata: new JsonDecoder().convert(PickerData)),
+        adapter: PickerDataAdapter<String>(pickerdata: new JsonDecoder().convert(PickerData)),
         changeToFirst: true,
         textAlign: TextAlign.left,
         columnPadding: const EdgeInsets.all(8.0),
@@ -568,14 +529,7 @@ typedef int OnTapHomeMenu();
 typedef ValueChanged<T> = void Function(T value);
 
 class ChooseContent extends StatelessWidget {
-  ChooseContent(
-      {Key key,
-      this.title,
-      this.val,
-      this.chooseLevelInfo,
-      this.isLevel = false,
-      this.onTapHomeMenu})
-      : super(key: key);
+  ChooseContent({Key key, this.title, this.val, this.chooseLevelInfo, this.isLevel = false, this.onTapHomeMenu}) : super(key: key);
   final String title;
   final String val;
   final OnTapHomeMenu onTapHomeMenu;
@@ -610,24 +564,15 @@ class ChooseContent extends StatelessWidget {
                         ),
                         Padding(
                           padding: EdgeInsets.only(left: 20, right: 2),
-                          child: Image.asset('images/icon_jinbi_da_bai.png',
-                              width: 20),
+                          child: Image.asset('images/icon_jinbi_da_bai.png', width: 20),
                         ),
                         Text(
                           '×' + (chooseLevelInfo.entryCoin ?? 0).toString(),
-                          style: TextStyle(
-                              color: Colors.white,
-                              fontSize: 15,
-                              fontWeight: FontWeight.w500),
+                          style: TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.w500),
                         )
                       ],
                     )
-                  : Text(val ?? '',
-                      style: TextStyle(
-                          fontSize: 15,
-                          color: Colors.white,
-                          fontWeight: FontWeight.w500),
-                      textAlign: TextAlign.right),
+                  : Text(val ?? '', style: TextStyle(fontSize: 15, color: Colors.white, fontWeight: FontWeight.w500), textAlign: TextAlign.right),
             ),
             Image.asset('images/icon_inter.png', width: 24)
           ],
@@ -639,8 +584,7 @@ class ChooseContent extends StatelessWidget {
 }
 
 class InputContent extends StatefulWidget {
-  InputContent({Key key, this.title, this.value, this.onTextChange})
-      : super(key: key);
+  InputContent({Key key, this.title, this.value, this.onTextChange}) : super(key: key);
   final String title;
   final String value;
   final ValueChanged onTextChange;
@@ -673,16 +617,14 @@ class InputContentState extends State<InputContent> {
       child: TextField(
         controller: _controller,
         textAlign: TextAlign.end,
-        style: TextStyle(
-            fontSize: 15, color: Colors.white, fontWeight: FontWeight.w500),
+        style: TextStyle(fontSize: 15, color: Colors.white, fontWeight: FontWeight.w500),
         maxLength: 10,
         decoration: InputDecoration(
             hintText: "请输入" + widget.title,
             hintStyle: TextStyle(color: Color(0xFF727785), fontSize: 13),
             prefixIcon: Padding(
               padding: EdgeInsets.symmetric(vertical: 12),
-              child: Text(widget.title,
-                  style: TextStyle(fontSize: 14, color: Colors.white)),
+              child: Text(widget.title, style: TextStyle(fontSize: 14, color: Colors.white)),
             ),
             border: InputBorder.none,
             counterStyle: TextStyle(fontSize: 0)),

+ 1 - 38
lib/pages/setting.dart

@@ -1,20 +1,14 @@
 import 'package:flutter/material.dart';
-import 'package:file_picker/file_picker.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
-import 'package:dio/dio.dart';
-import 'package:intl/intl.dart';
 import 'package:jpush_flutter/jpush_flutter.dart';
 import 'package:package_info/package_info.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import '../styles/colors.dart';
-import 'dart:io';
 import 'dart:async';
-import 'dart:convert';
 import 'dart:ui';
 import '../styles/totast.dart';
-import 'ChangeUserInfo.dart'; //修改信息页面
-import 'loginFirst.dart'; //登录
+import 'loginFirst.dart';
 import 'package:redux/redux.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 import '../redux/AppState.dart';
@@ -33,22 +27,6 @@ class SettingState extends State<Setting> {
   String version = "";
   bool receiveMsg = false;
 
-  void getFilePath() async {
-    String filePath = await FilePicker.getFilePath(type: FileType.IMAGE);
-    if (filePath == null) {
-      return;
-    }
-    File _file = File(filePath);
-    Toast.show(context, '加载中', -1, 'loading');
-    Result res = await HttpManager.post("assets/uploadFile", data: {
-      "file": UploadFileInfo(_file, filePath),
-    });
-    Toast.hide();
-    if (res.success) {
-      updateUserInfo(StoreProvider.of<AppState>(context).state.userInfo, res.data[0], 'icon');
-    } else {}
-  }
-
   @override
   void initState() {
     super.initState();
@@ -291,21 +269,6 @@ class SettingState extends State<Setting> {
     }
   }
 
-  _chooseImage(BuildContext context) async {
-    UserInfo userInfo = StoreProvider.of<AppState>(context).state.userInfo;
-    var image = await FilePicker.getFilePath(type: FileType.IMAGE);
-    Toast.show(context, '加载中', -1, 'loading');
-    File _image = File(image);
-    _image.readAsBytes().then((bytes) async {
-      String encoded1 = 'data:image/jpeg;base64,' + base64Encode(bytes);
-      FormData formData = new FormData.from({"base64": encoded1});
-      Result res = await HttpManager.post('assets/uploadImg', data: formData);
-      if (res.success) {
-        updateUserInfo(userInfo, res.data, 'icon');
-      }
-    });
-  }
-
   Widget _sectionDivier() {
     return SizedBox(height: 10);
   }

+ 3 - 3
pubspec.yaml

@@ -18,20 +18,20 @@ dependencies:
   pull_to_refresh: ^1.1.6
   dio: ^2.0.10
   flutter_swiper: ^1.0.6
-  image_picker: ^0.4.10
   redux: ^3.0.0
   flutter_redux: ^0.5.2
   redux_persist: ^0.8.0
   redux_persist_flutter: ^0.8.0
-  flutter_picker: ^1.0.7
+  flutter_picker: ^1.0.9
   intl: "^0.15.6"
-  file_picker: ^1.1.1
+  file_picker: ^1.3.1
   json_serializable: ^2.0.2
   shared_preferences: ^0.5.1
   package_info: ^0.4.0
   video_player: ^0.10.0
   url_launcher: ^5.0.1
   jpush_flutter: ^0.0.11
+  image_cropper: ^1.0.0
 
 dev_dependencies:
   build_runner: ^1.1.1