x1ongzhu 6 年之前
父节点
当前提交
90da9d2bbf

+ 16 - 3
android/app/src/main/AndroidManifest.xml

@@ -1,4 +1,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     package="com.izouma.wanna_battle">
     package="com.izouma.wanna_battle">
 
 
     <!-- io.flutter.app.FlutterApplication is an android.app.Application that
     <!-- io.flutter.app.FlutterApplication is an android.app.Application that
@@ -6,6 +7,10 @@
          In most cases you can leave this as-is, but you if you want to provide
          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
          additional functionality it is fine to subclass or reimplement
          FlutterApplication and put your custom class here. -->
          FlutterApplication and put your custom class here. -->
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+
     <application
     <application
         android:name="com.izouma.screen_stream_plugin.MyApplication"
         android:name="com.izouma.screen_stream_plugin.MyApplication"
         android:icon="@mipmap/ic_launcher"
         android:icon="@mipmap/ic_launcher"
@@ -37,8 +42,16 @@
             </intent-filter>
             </intent-filter>
         </activity>
         </activity>
 
 
-        <meta-data
-            android:name="android.support.FILE_PROVIDER_PATHS"
-            android:resource="@xml/file_paths" />
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:authorities="com.izouma.wanna_battle.fileProvider"
+            android:exported="false"
+            android:grantUriPermissions="true"
+            tools:node="replace">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/filepaths"
+                tools:replace="android:resource" />
+        </provider>
     </application>
     </application>
 </manifest>
 </manifest>

+ 0 - 6
android/app/src/main/res/xml/file_paths.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<paths xmlns:android="http://schemas.android.com/apk/res/android">
-    <external-path
-        name="external_files"
-        path="tessdata" />
-</paths>

+ 1 - 13
android/app/src/main/res/xml/filepaths.xml

@@ -2,17 +2,5 @@
 <paths xmlns:android="http://schemas.android.com/apk/res/android">
 <paths xmlns:android="http://schemas.android.com/apk/res/android">
     <external-path
     <external-path
         name="external_files"
         name="external_files"
-        path="tessdata" />
-    <!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
-    <external-path
-        name="beta_external_path"
-        path="Download/" />
-    <!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
-    <external-path
-        name="beta_external_files_path"
-        path="Android/data/" />
-
-    <external-path
-        name="sdcard"
-        path="/" />
+        path="." />
 </paths>
 </paths>

二进制
images/2x/icon_rank.png


二进制
images/3x/icon_rank.png


二进制
images/icon_rank.png


+ 26 - 5
lib/main.dart

@@ -6,6 +6,8 @@ import 'package:redux/redux.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:shared_preferences/shared_preferences.dart';
+import 'package:flutter_bugly/flutter_bugly.dart';
+import 'package:flutter/foundation.dart';
 import './Localizations.dart';
 import './Localizations.dart';
 import 'model/UserInfo.dart';
 import 'model/UserInfo.dart';
 import 'net/HttpManager.dart';
 import 'net/HttpManager.dart';
@@ -71,17 +73,36 @@ Future<void> main() async {
   );
   );
   jpush.applyPushAuthority(NotificationSettingsIOS(sound: true, alert: true, badge: true));
   jpush.applyPushAuthority(NotificationSettingsIOS(sound: true, alert: true, badge: true));
   final prefs = await SharedPreferences.getInstance();
   final prefs = await SharedPreferences.getInstance();
-  print(prefs.getString('token'));
   HttpManager.token = prefs.getString('token') ?? '';
   HttpManager.token = prefs.getString('token') ?? '';
+
+  if (debugMode()) {
+    HttpManager.token = ''
+        'eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwOTkyZDBkMC0xN2Y3LTQ2'
+        'NzktOTY4My01YWFlY2VlZmU1YzgiLCJpc3MiOiJhZG1pbiIsImlh'
+        'dCI6MTU2MDk5NTYwNCwic3ViIjoiODQ3MDMiLCJleHAiOjE1NjM1'
+        'ODc2MDR9.WBB9F2KBb_xOv3rXnyxCVXYTC7_BiqhS1IFhMcnKvT8';
+  }
+
   Result result = await HttpManager.get('userInfo/getUserInfo');
   Result result = await HttpManager.get('userInfo/getUserInfo');
   AppState state = AppState.empty();
   AppState state = AppState.empty();
   if (result.success && result.data != null) {
   if (result.success && result.data != null) {
     UserInfo userInfo = UserInfo.fromJson(result.data);
     UserInfo userInfo = UserInfo.fromJson(result.data);
     state.userInfo = userInfo;
     state.userInfo = userInfo;
-    try {
-      // jpush.setAlias(userInfo.id.toString()).then((map) {});
-    } catch (e) {}
+    jpush.setAlias(userInfo.id.toString()).then((map) {});
   }
   }
+
   Store<AppState> store = Store<AppState>(appReducer, initialState: state);
   Store<AppState> store = Store<AppState>(appReducer, initialState: state);
-  runApp(MobileCyberGamesApp(store));
+  FlutterBugly.init(androidAppId: '5f31e941fc', iOSAppId: '');
+  FlutterBugly.postCatchedException(() {
+    runApp(MobileCyberGamesApp(store));
+  });
+}
+
+bool debugMode() {
+  if (kReleaseMode) {
+    print('release mode');
+  } else {
+    print('debug mode');
+  }
+  return !kReleaseMode;
 }
 }

+ 3 - 1
lib/model/ParticipatingInfo.dart

@@ -1,11 +1,12 @@
 import 'package:json_annotation/json_annotation.dart';
 import 'package:json_annotation/json_annotation.dart';
+import 'package:wanna_battle/model/UserInfo.dart';
 part 'ParticipatingInfo.g.dart';
 part 'ParticipatingInfo.g.dart';
 
 
 @JsonSerializable()
 @JsonSerializable()
 class ParticipatingInfo {
 class ParticipatingInfo {
   ParticipatingInfo.empty();
   ParticipatingInfo.empty();
 
 
-  ParticipatingInfo(this.userId, this.competitionId, this.points, this.bonus, this.received, this.rank, this.currentRank);
+  ParticipatingInfo(this.userId, this.competitionId, this.points, this.bonus, this.received, this.rank, this.currentRank, this.userInfo);
 
 
   factory ParticipatingInfo.fromJson(Map<String, dynamic> json) => _$ParticipatingInfoFromJson(json);
   factory ParticipatingInfo.fromJson(Map<String, dynamic> json) => _$ParticipatingInfoFromJson(json);
 
 
@@ -16,6 +17,7 @@ class ParticipatingInfo {
   int received;
   int received;
   int rank;
   int rank;
   int currentRank;
   int currentRank;
+  UserInfo userInfo;
 
 
   Map<String, dynamic> toJson() => _$ParticipatingInfoToJson(this);
   Map<String, dynamic> toJson() => _$ParticipatingInfoToJson(this);
 
 

+ 6 - 2
lib/model/ParticipatingInfo.g.dart

@@ -14,7 +14,10 @@ ParticipatingInfo _$ParticipatingInfoFromJson(Map<String, dynamic> json) {
       json['bonus'] as int,
       json['bonus'] as int,
       json['received'] as int,
       json['received'] as int,
       json['rank'] as int,
       json['rank'] as int,
-      json['currentRank'] as int);
+      json['currentRank'] as int,
+      json['userInfo'] == null
+          ? null
+          : UserInfo.fromJson(json['userInfo'] as Map<String, dynamic>));
 }
 }
 
 
 Map<String, dynamic> _$ParticipatingInfoToJson(ParticipatingInfo instance) =>
 Map<String, dynamic> _$ParticipatingInfoToJson(ParticipatingInfo instance) =>
@@ -25,5 +28,6 @@ Map<String, dynamic> _$ParticipatingInfoToJson(ParticipatingInfo instance) =>
       'bonus': instance.bonus,
       'bonus': instance.bonus,
       'received': instance.received,
       'received': instance.received,
       'rank': instance.rank,
       'rank': instance.rank,
-      'currentRank': instance.currentRank
+      'currentRank': instance.currentRank,
+      'userInfo': instance.userInfo
     };
     };

+ 0 - 1
lib/net/HttpManager.dart

@@ -20,7 +20,6 @@ class HttpManager {
     try {
     try {
       FormData formData = FormData.from(data ?? {});
       FormData formData = FormData.from(data ?? {});
       Response response = await _createDio().post(url, data: formData);
       Response response = await _createDio().post(url, data: formData);
-      print(response);
       if (response.statusCode != 200) {
       if (response.statusCode != 200) {
         result.success = false;
         result.success = false;
         result.error = 'httpCode' + response.statusCode.toString();
         result.error = 'httpCode' + response.statusCode.toString();

+ 268 - 0
lib/pages/CompetitionRank.dart

@@ -0,0 +1,268 @@
+import 'package:cached_network_image/cached_network_image.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter_redux/flutter_redux.dart';
+import 'package:wanna_battle/model/ParticipatingInfo.dart';
+import 'package:wanna_battle/redux/AppState.dart';
+import '../styles/colors.dart';
+import '../net/HttpManager.dart';
+
+class CompetitionRank extends StatefulWidget {
+  final int competitionId;
+
+  const CompetitionRank({Key key, this.competitionId}) : super(key: key);
+
+  @override
+  State<StatefulWidget> createState() {
+    return CompetitionRankState();
+  }
+}
+
+class CompetitionRankState extends State<CompetitionRank> {
+  List<ParticipatingInfo> data = [];
+  ParticipatingInfo myParticipatingInfo;
+
+  Future<void> refresh() async {
+    final res = await HttpManager.get('participatingInfo/rank', data: {'competitionId': widget.competitionId});
+    ParticipatingInfo myParticipatingInfo;
+    if (res.success) {
+      List<ParticipatingInfo> list = [];
+      for (var item in res.data) {
+        var p = ParticipatingInfo.fromJson(item);
+        list.add(p);
+        if (StoreProvider.of<AppState>(context).state.userInfo.id == p.userId) {
+          myParticipatingInfo = p;
+        }
+      }
+      setState(() {
+        data = list;
+        this.myParticipatingInfo = myParticipatingInfo;
+      });
+    }
+  }
+
+  @override
+  void initState() {
+    super.initState();
+    Future.delayed(Duration.zero, () {
+      refresh();
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        centerTitle: true,
+        elevation: 0,
+        title: Text('排行榜'),
+        actions: <Widget>[
+          CupertinoButton(
+            child: Text(
+              '奖金规则',
+              style: TextStyle(fontSize: 13, color: Color(0x80FFFFFF)),
+            ),
+            onPressed: () {},
+          )
+        ],
+      ),
+      body: Stack(
+        children: <Widget>[
+          RefreshIndicator(
+            onRefresh: () async {
+              await refresh();
+              return;
+            },
+            child: Builder(
+              builder: (context) {
+                List<Widget> list = [
+                  Container(
+                    padding: EdgeInsets.only(bottom: 10),
+                    color: SUB_COLOR,
+                    child: Row(
+                      children: <Widget>[
+                        topRank(data.length > 1 ? data[1] : null),
+                        topRank(data.length > 0 ? data[0] : null),
+                        topRank(data.length > 2 ? data[2] : null),
+                      ],
+                    ),
+                  )
+                ];
+                if (data.length > 3) {
+                  for (int i = 2; i < data.length; i++) {
+                    list.add(rankItem(data[i]));
+                  }
+                }
+                return ListView(
+                  padding: EdgeInsets.only(bottom: 48),
+                  children: list,
+                );
+              },
+            ),
+          ),
+          Align(
+            alignment: Alignment.bottomCenter,
+            child: rankItem(myParticipatingInfo, mine: true),
+          )
+        ],
+      ),
+    );
+  }
+
+  Widget topRank(ParticipatingInfo participatingInfo) {
+    if (participatingInfo == null) {
+      return Expanded(child: Container());
+    }
+    double size = participatingInfo.rank == 1 ? 80 : 70;
+    List<Color> colors = [Color(0xFFD48E00), Color(0xFFFECF01)];
+    String icon = 'images/icon_paihangbang_01.png';
+    if (participatingInfo.rank == 2) {
+      colors = [Color(0xFFC5C5C5), Color(0xFFE3E3E3)];
+      icon = 'images/icon_paihangbang_02.png';
+    } else if (participatingInfo.rank == 3) {
+      colors = [Color(0xFFE77023), Color(0xFFF89E58)];
+      icon = 'images/icon_paihangbang_03.png';
+    }
+    return Expanded(
+      child: Container(
+        margin: EdgeInsets.only(top: participatingInfo.rank == 1 ? 4 : 38),
+        child: Column(
+          children: <Widget>[
+            Stack(
+              children: <Widget>[
+                Align(
+                  alignment: Alignment.topCenter,
+                  child: Container(
+                    width: size,
+                    height: size,
+                    margin: EdgeInsets.only(top: 23),
+                    padding: EdgeInsets.all(5),
+                    decoration: BoxDecoration(
+                      borderRadius: BorderRadius.all(Radius.circular(size / 2)),
+                      gradient: LinearGradient(
+                        colors: colors,
+                        begin: Alignment.centerRight,
+                        end: Alignment.centerLeft,
+                      ),
+                    ),
+                    child: ClipOval(
+                      child: CachedNetworkImage(
+                        imageUrl: participatingInfo?.userInfo?.icon ?? '',
+                        fit: BoxFit.cover,
+                      ),
+                    ),
+                  ),
+                ),
+                Align(
+                  alignment: Alignment.topCenter,
+                  child: Image.asset(icon),
+                ),
+              ],
+            ),
+            Container(
+              margin: EdgeInsets.only(top: 6),
+              child: Text(
+                participatingInfo?.userInfo?.nickname ?? '',
+                style: TextStyle(color: PRIMARY_COLOR, fontSize: 14, fontWeight: FontWeight.bold),
+              ),
+            ),
+            Row(
+              mainAxisSize: MainAxisSize.min,
+              children: <Widget>[
+                Image.asset('images/icon_jifen_da.png', width: 20),
+                Container(
+                  margin: EdgeInsets.only(left: 2),
+                  child: Text(
+                    (participatingInfo?.points ?? 0).toString(),
+                    style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold),
+                  ),
+                )
+              ],
+            )
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget rankItem(ParticipatingInfo participatingInfo, {bool mine = false}) {
+    if (participatingInfo == null) {
+      if (mine) {
+        return Container();
+      }
+      return Container();
+    }
+    return Container(
+      height: mine ? 48 : 66,
+      decoration: BoxDecoration(
+        border: Border(
+          bottom: BorderSide(
+            width: mine ? 0 : 1,
+            color: Color(0x2E000000),
+          ),
+        ),
+        color: mine ? SUB_COLOR : Colors.transparent,
+      ),
+      padding: EdgeInsets.only(left: 15),
+      child: Row(
+        children: <Widget>[
+          Container(
+            width: 30,
+            height: 30,
+            child: Stack(
+              children: <Widget>[
+                Image.asset('images/icon_rank.png'),
+                Align(
+                  alignment: Alignment.topCenter,
+                  child: Container(
+                    margin: EdgeInsets.only(top: 11),
+                    child: Text(
+                      (participatingInfo?.rank ?? 0).toString(),
+                      style: TextStyle(color: Color(0xFF15151D), fontSize: 12, fontWeight: FontWeight.bold),
+                    ),
+                  ),
+                )
+              ],
+            ),
+          ),
+          Container(
+            width: mine ? 30 : 46,
+            height: mine ? 30 : 46,
+            margin: EdgeInsets.only(left: 10),
+            child: ClipOval(
+              child: CachedNetworkImage(
+                imageUrl: participatingInfo?.userInfo?.icon ?? '',
+                fit: BoxFit.cover,
+              ),
+            ),
+          ),
+          Expanded(
+            child: Container(
+              margin: EdgeInsets.only(left: 19),
+              child: Text(
+                participatingInfo?.userInfo?.nickname ?? '',
+                style: TextStyle(color: mine ? Colors.white : PRIMARY_COLOR, fontSize: 14),
+              ),
+            ),
+          ),
+          Container(
+            width: 113,
+            child: Row(
+              children: <Widget>[
+                Image.asset('images/icon_jifen_da.png', width: 20),
+                Container(
+                  margin: EdgeInsets.only(left: 2),
+                  child: Text(
+                    (participatingInfo?.points ?? 0).toString(),
+                    style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold),
+                  ),
+                )
+              ],
+            ),
+          )
+        ],
+      ),
+    );
+  }
+}

+ 4 - 1
lib/pages/CompetitionRooms.dart

@@ -13,6 +13,7 @@ import '../net/Result.dart';
 import './RoomInfo.dart';
 import './RoomInfo.dart';
 import '../redux/AppState.dart';
 import '../redux/AppState.dart';
 import '../plugins/ScreenStramPlugin.dart';
 import '../plugins/ScreenStramPlugin.dart';
+import './CompetitionRank.dart';
 
 
 class CompetitionRooms extends StatefulWidget {
 class CompetitionRooms extends StatefulWidget {
   CompetitionRooms(this.competitionInfo);
   CompetitionRooms(this.competitionInfo);
@@ -47,7 +48,9 @@ class _CompetitionRoomsState extends State<CompetitionRooms> {
         elevation: 0,
         elevation: 0,
         actions: <Widget>[
         actions: <Widget>[
           GestureDetector(
           GestureDetector(
-            onTap: () {},
+            onTap: () {
+              Navigator.push(context, CupertinoPageRoute(builder: (context) => CompetitionRank(competitionId: widget.competitionInfo.id)));
+            },
             child: Image.asset('images/icon_paihangbang.png'),
             child: Image.asset('images/icon_paihangbang.png'),
           )
           )
         ],
         ],

+ 1 - 2
lib/pages/Competitions.dart

@@ -18,7 +18,6 @@ class Competitions extends StatefulWidget {
 
 
 class _CompetitionState extends State<Competitions> {
 class _CompetitionState extends State<Competitions> {
   List<CompetitionInfo> competitionInfoList = [];
   List<CompetitionInfo> competitionInfoList = [];
-
   @override
   @override
   void initState() {
   void initState() {
     super.initState();
     super.initState();
@@ -148,7 +147,7 @@ class _CompetitionState extends State<Competitions> {
                                           ],
                                           ],
                                         ),
                                         ),
                                       ),
                                       ),
-                                      onTap: () {
+                                      onTap: () async {
                                         showCheckinDialog(context);
                                         showCheckinDialog(context);
                                       },
                                       },
                                     ),
                                     ),

+ 6 - 1
lib/pages/Home.dart

@@ -4,6 +4,7 @@ import './Competitions.dart';
 import '../widget/HomeDrawer.dart';
 import '../widget/HomeDrawer.dart';
 import './TipList.dart';
 import './TipList.dart';
 import './Shop.dart';
 import './Shop.dart';
+import '../widget/CheckUpgrade.dart';
 
 
 class HomePage extends StatefulWidget {
 class HomePage extends StatefulWidget {
   const HomePage({Key key}) : super(key: key);
   const HomePage({Key key}) : super(key: key);
@@ -17,12 +18,16 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
     Tab(text: 'RIGHT'),
     Tab(text: 'RIGHT'),
   ];
   ];
 
 
+  final GlobalKey<UpgradeDialogState> _dialogKey = GlobalKey();
   TabController _tabController;
   TabController _tabController;
-
+  
   @override
   @override
   void initState() {
   void initState() {
     super.initState();
     super.initState();
     _tabController = TabController(vsync: this, length: myTabs.length);
     _tabController = TabController(vsync: this, length: myTabs.length);
+    Future.delayed(Duration.zero, () {
+      checkUpgrade(context, _dialogKey);
+    });
   }
   }
 
 
   @override
   @override

+ 9 - 8
lib/pages/UserChange.dart

@@ -87,8 +87,7 @@ class UserChangeState extends State<UserChange> {
                                   userInfo.nickname,
                                   userInfo.nickname,
                                   placeholder: '请填写昵称',
                                   placeholder: '请填写昵称',
                                   onTap: () {
                                   onTap: () {
-                                    Navigator.push(
-                                        context, CupertinoPageRoute(builder: (context) => ChangeUserInfo(title: '昵称', val: userInfo.nickname)));
+                                    Navigator.push(context, CupertinoPageRoute(builder: (context) => ChangeUserInfo(title: '昵称', val: userInfo.nickname)));
                                   },
                                   },
                                 ),
                                 ),
                                 _cell(
                                 _cell(
@@ -129,7 +128,7 @@ class UserChangeState extends State<UserChange> {
                           highlightColor: Color(0xFF763434),
                           highlightColor: Color(0xFF763434),
                           child: Text(
                           child: Text(
                             '退出登录',
                             '退出登录',
-                            style: TextStyle(fontSize: 16, fontWeight:  FontWeight.normal),
+                            style: TextStyle(fontSize: 16, fontWeight: FontWeight.normal),
                           ),
                           ),
                           onPressed: () async {
                           onPressed: () async {
                             Toast.show(context, '退出成功', 1500, 'success');
                             Toast.show(context, '退出成功', 1500, 'success');
@@ -228,6 +227,7 @@ class UserChangeState extends State<UserChange> {
                       top: 0,
                       top: 0,
                       bottom: 0,
                       bottom: 0,
                       child: CupertinoButton(
                       child: CupertinoButton(
+                        padding: EdgeInsets.fromLTRB(15, 0, 0, 0),
                         child: Text(
                         child: Text(
                           '取消',
                           '取消',
                           style: TextStyle(color: PRIMARY_COLOR),
                           style: TextStyle(color: PRIMARY_COLOR),
@@ -242,6 +242,7 @@ class UserChangeState extends State<UserChange> {
                       top: 0,
                       top: 0,
                       bottom: 0,
                       bottom: 0,
                       child: CupertinoButton(
                       child: CupertinoButton(
+                        padding: EdgeInsets.fromLTRB(0, 0, 15, 0),
                         child: Text(
                         child: Text(
                           '确定',
                           '确定',
                           style: TextStyle(color: PRIMARY_COLOR),
                           style: TextStyle(color: PRIMARY_COLOR),
@@ -341,11 +342,11 @@ class UserChangeState extends State<UserChange> {
     } else {
     } else {
       secondChild = child;
       secondChild = child;
     }
     }
-    return Container(
-      height: 60,
-      padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
-      child: GestureDetector(
-        onTap: onTap,
+    return GestureDetector(
+      onTap: onTap,
+      child: Container(
+        height: 60,
+        padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
         child: Container(
         child: Container(
           decoration: BoxDecoration(
           decoration: BoxDecoration(
             border: Border(
             border: Border(

+ 1 - 5
lib/redux/UserRedux.dart

@@ -19,11 +19,7 @@ UserInfo _updateLoaded(UserInfo userInfo, action) {
   final JPush jpush = JPush();
   final JPush jpush = JPush();
   if (action.userInfo != null) {
   if (action.userInfo != null) {
     if (userInfo == null || (userInfo.id != action.userInfo.id)) {
     if (userInfo == null || (userInfo.id != action.userInfo.id)) {
-      try {
-        jpush.setAlias(action.userInfo.id.toString()).then((map) {}).catchError((error) => {});
-      } catch (e) {
-        print(e.toString());
-      }
+      jpush.setAlias(action.userInfo.id.toString());
     }
     }
   } else {
   } else {
     jpush.deleteAlias();
     jpush.deleteAlias();

+ 293 - 0
lib/widget/CheckUpgrade.dart

@@ -0,0 +1,293 @@
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_bugly/flutter_bugly.dart';
+import 'package:intl/intl.dart';
+import 'package:dio/dio.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:open_file/open_file.dart';
+import 'package:permission_handler/permission_handler.dart';
+
+Future checkUpgrade(context, key) async {
+  final upgradeInfo = await FlutterBugly.getUpgradeInfo();
+  if (upgradeInfo == null) {
+    return false;
+  }
+  return await showUpgradeDailog(context, upgradeInfo, key);
+}
+
+Future showUpgradeDailog(context, upgradeInfo, key) async {
+  return await showGeneralDialog(
+    context: context,
+    barrierDismissible: false,
+    pageBuilder: (BuildContext buildContext, Animation<double> animation, Animation<double> secondaryAnimation) {
+      return WillPopScope(
+        onWillPop: () {
+          return Future.value(false);
+        },
+        child: Center(
+          child: Material(
+            color: Colors.transparent,
+            child: UpgradeDialog(upgradeInfo, key: key),
+          ),
+        ),
+      );
+    },
+    barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
+    barrierColor: Colors.black26,
+    transitionDuration: const Duration(milliseconds: 300),
+  );
+}
+
+Future downloadApk(context, url) async {
+  return await showGeneralDialog(
+    context: context,
+    barrierDismissible: false,
+    pageBuilder: (BuildContext buildContext, Animation<double> animation, Animation<double> secondaryAnimation) {
+      return Center(
+        child: Material(
+          color: Colors.transparent,
+          child: DownloadDialog(url),
+        ),
+      );
+    },
+    barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
+    barrierColor: Colors.black26,
+    transitionDuration: const Duration(milliseconds: 300),
+  );
+}
+
+class UpgradeDialog extends StatefulWidget {
+  final UpgradeInfo upgradeInfo;
+
+  UpgradeDialog(this.upgradeInfo, {Key key}) : super(key: key);
+
+  @override
+  State<StatefulWidget> createState() {
+    return UpgradeDialogState();
+  }
+}
+
+class UpgradeDialogState extends State<UpgradeDialog> {
+  final Color primaryColor = Color(0xFF1990F8);
+  final Color bgColor = Color(0xE6293559);
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: 280,
+      padding: EdgeInsets.only(left: 20, right: 20),
+      decoration: BoxDecoration(color: bgColor, border: Border.all(width: 1, color: primaryColor)),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.stretch,
+        mainAxisSize: MainAxisSize.min,
+        children: <Widget>[
+          Container(
+            margin: EdgeInsets.only(top: 20),
+            child: Text(
+              widget.upgradeInfo.title,
+              style: TextStyle(color: primaryColor, fontSize: 16, fontWeight: FontWeight.bold),
+              textAlign: TextAlign.center,
+            ),
+          ),
+          Container(
+            margin: EdgeInsets.only(top: 15),
+            child: Text(
+              '版本:' + widget.upgradeInfo.versionName,
+              style: TextStyle(color: Colors.white),
+            ),
+          ),
+          Container(
+            margin: EdgeInsets.only(top: 10),
+            child: Text(
+              '包大小:' + (widget.upgradeInfo.fileSize / 1024 / 1024).toStringAsFixed(0) + 'MB',
+              style: TextStyle(color: Colors.white),
+            ),
+          ),
+          Container(
+            margin: EdgeInsets.only(top: 10),
+            child: Text(
+              '更新时间:' + DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.fromMicrosecondsSinceEpoch(widget.upgradeInfo.publishTime * 1000)),
+              style: TextStyle(color: Colors.white),
+            ),
+          ),
+          Container(
+            margin: EdgeInsets.only(top: 10),
+            child: Text(
+              '更新说明:',
+              style: TextStyle(color: Colors.white),
+            ),
+          ),
+          Container(
+            margin: EdgeInsets.only(top: 6),
+            child: Text(
+              widget.upgradeInfo.newFeature,
+              style: TextStyle(color: Colors.white),
+            ),
+          ),
+          Container(
+            margin: EdgeInsets.only(bottom: 20, top: 20),
+            child: Row(
+              children: <Widget>[
+                widget.upgradeInfo.upgradeType == 2
+                    ? Container()
+                    : Expanded(
+                        child: MaterialButton(
+                          elevation: 0,
+                          highlightElevation: 0,
+                          minWidth: 100,
+                          height: 36,
+                          color: Color(0xFF4F5C87),
+                          child: Text(
+                            '下次再说',
+                            style: TextStyle(color: Colors.white),
+                          ),
+                          onPressed: () {
+                            Navigator.of(context).pop();
+                          },
+                        ),
+                      ),
+                widget.upgradeInfo.upgradeType == 2 ? Container() : Container(width: 20),
+                Expanded(
+                  child: MaterialButton(
+                    elevation: 0,
+                    highlightElevation: 0,
+                    minWidth: 100,
+                    height: 36,
+                    color: primaryColor,
+                    child: Text(
+                      '立即更新',
+                      style: TextStyle(color: Colors.white),
+                    ),
+                    onPressed: () async {
+                      PermissionStatus permission = await PermissionHandler().checkPermissionStatus(PermissionGroup.storage);
+                      if (permission == PermissionStatus.denied) {
+                        Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().requestPermissions([PermissionGroup.storage]);
+                        if (permissions[PermissionGroup.storage] == PermissionStatus.denied) {
+                          showDialog(
+                              context: context,
+                              barrierDismissible: false,
+                              builder: (context) {
+                                return AlertDialog(
+                                  content: Text(
+                                    '需要获取外部存储权限来下载安装包',
+                                    style: TextStyle(color: Colors.black),
+                                  ),
+                                  actions: <Widget>[
+                                    FlatButton(
+                                      child: Text('打开设置'),
+                                      onPressed: () {
+                                        Navigator.of(context).pop();
+                                        PermissionHandler().openAppSettings();
+                                      },
+                                    ),
+                                  ],
+                                );
+                              });
+                          return;
+                        }
+                      }
+                      Navigator.of(context).pop();
+                      await downloadApk(context, widget.upgradeInfo.apkUrl);
+                    },
+                  ),
+                )
+              ],
+            ),
+          )
+        ],
+      ),
+    );
+  }
+}
+
+class DownloadDialog extends StatefulWidget {
+  final String url;
+
+  DownloadDialog(this.url, {Key key}) : super(key: key);
+
+  @override
+  State<StatefulWidget> createState() {
+    return DownloadDialogState();
+  }
+}
+
+class DownloadDialogState extends State<DownloadDialog> {
+  final Color primaryColor = Color(0xFF1990F8);
+  final Color bgColor = Color(0xE6293559);
+  Dio dio;
+  CancelToken token;
+  double progress = 0;
+
+  @override
+  void initState() {
+    super.initState();
+    Future.delayed(Duration.zero, () async {
+      final Directory tempDir = await getExternalStorageDirectory();
+      final String tempPath = tempDir.path;
+      final String savePath = '$tempPath/update.apk';
+      dio = Dio();
+      token = CancelToken();
+      final res = await dio.download(
+        widget.url,
+        savePath,
+        onReceiveProgress: (int count, int total) {
+          setState(() {
+            progress = count / total;
+          });
+        },
+        options: Options(receiveTimeout: 10 * 60 * 1000),
+        cancelToken: token,
+      ).catchError((_error) {
+        return _error;
+      });
+      if (res != null && res.statusCode == 200) {
+        OpenFile.open(savePath);
+      }
+      Navigator.of(context).pop();
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: 300,
+      height: 60,
+      padding: EdgeInsets.fromLTRB(15, 10, 15, 10),
+      decoration: BoxDecoration(color: bgColor, border: Border.all(width: 1, color: primaryColor)),
+      child: Column(
+        children: <Widget>[
+          Row(
+            children: <Widget>[
+              Expanded(
+                child: Text(
+                  '正在下载更新',
+                  style: TextStyle(color: primaryColor, fontSize: 14),
+                ),
+              ),
+              Text(
+                (progress * 100).toStringAsFixed(0) + '%',
+                style: TextStyle(color: Colors.white.withAlpha(128)),
+              )
+            ],
+          ),
+          Container(
+            margin: EdgeInsets.only(top: 10),
+            child: Align(
+              alignment: Alignment.centerLeft,
+              child: FractionallySizedBox(
+                widthFactor: progress,
+                child: Container(
+                  height: 2,
+                  color: primaryColor,
+                ),
+              ),
+            ),
+          )
+        ],
+      ),
+    );
+  }
+}

+ 8 - 7
lib/widget/HomeDrawer.dart

@@ -1,3 +1,4 @@
+import 'package:cached_network_image/cached_network_image.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:redux/redux.dart';
 import 'package:redux/redux.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 import 'package:flutter_redux/flutter_redux.dart';
@@ -52,8 +53,8 @@ class HomeDrawerState extends State<HomeDrawer> {
                     children: <Widget>[
                     children: <Widget>[
                       ClipOval(
                       ClipOval(
                         child: InkWell(
                         child: InkWell(
-                          child: Image.network(
-                            userInfo.icon,
+                          child: CachedNetworkImage(
+                            imageUrl: userInfo.icon,
                             width: 86,
                             width: 86,
                             height: 86,
                             height: 86,
                             fit: BoxFit.cover,
                             fit: BoxFit.cover,
@@ -170,11 +171,11 @@ class DrawerMenu extends StatelessWidget {
   DrawerMenu(this.icon, this.title, {this.onTap});
   DrawerMenu(this.icon, this.title, {this.onTap});
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    return Container(
-      height: 60,
-      padding: EdgeInsets.fromLTRB(30, 0, 28, 0),
-      child: GestureDetector(
-        onTap: onTap,
+    return GestureDetector(
+      onTap: onTap,
+      child: Container(
+        height: 60,
+        padding: EdgeInsets.fromLTRB(30, 0, 28, 0),
         child: Row(
         child: Row(
           children: <Widget>[
           children: <Widget>[
             Image.asset(icon),
             Image.asset(icon),

+ 74 - 0
lib/widget/UpdateDialog.dart

@@ -0,0 +1,74 @@
+import 'package:flutter/material.dart';
+
+class UpdateDialog extends StatefulWidget {
+  final key;
+  final version;
+  final Function onClickWhenDownload;
+  final Function onClickWhenNotDownload;
+
+  UpdateDialog(
+    this.key,
+    this.version,
+    this.onClickWhenDownload,
+    this.onClickWhenNotDownload,
+  );
+
+  @override
+  State<StatefulWidget> createState() => UpdateDialogState();
+}
+
+class UpdateDialogState extends State<UpdateDialog> {
+  var _downloadProgress = 0.0;
+
+  @override
+  Widget build(BuildContext context) {
+    var _textStyle = TextStyle(color: Theme.of(context).textTheme.body1.color);
+
+    return AlertDialog(
+      title: Text(
+        "有新的更新",
+        style: _textStyle,
+      ),
+      content: _downloadProgress == 0.0
+          ? Text(
+              "版本${widget.version}",
+              style: _textStyle,
+            )
+          : LinearProgressIndicator(
+              value: _downloadProgress,
+            ),
+      actions: <Widget>[
+        FlatButton(
+          child: Text(
+            '更新',
+            style: _textStyle,
+          ),
+          onPressed: () {
+            if (_downloadProgress != 0.0) {
+              widget.onClickWhenDownload("正在更新中");
+              return;
+            }
+            widget.onClickWhenNotDownload();
+//            Navigator.of(context).pop();
+          },
+        ),
+        FlatButton(
+          child: new Text('取消'),
+          onPressed: () {
+            Navigator.of(context).pop();
+          },
+        ),
+      ],
+    );
+  }
+
+  set progress(_progress) {
+    setState(() {
+      _downloadProgress = _progress;
+      if (_downloadProgress == 1) {
+        Navigator.of(context).pop();
+        _downloadProgress = 0.0;
+      }
+    });
+  }
+}

+ 28 - 0
pubspec.lock

@@ -181,6 +181,13 @@ packages:
     description: flutter
     description: flutter
     source: sdk
     source: sdk
     version: "0.0.0"
     version: "0.0.0"
+  flutter_bugly:
+    dependency: "direct main"
+    description:
+      name: flutter_bugly
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.2.2"
   flutter_cache_manager:
   flutter_cache_manager:
     dependency: transitive
     dependency: transitive
     description:
     description:
@@ -303,6 +310,13 @@ packages:
       url: "https://pub.dartlang.org"
       url: "https://pub.dartlang.org"
     source: hosted
     source: hosted
     version: "1.0.2"
     version: "1.0.2"
+  install_plugin:
+    dependency: "direct main"
+    description:
+      name: install_plugin
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.1"
   intl:
   intl:
     dependency: "direct main"
     dependency: "direct main"
     description:
     description:
@@ -380,6 +394,13 @@ packages:
       url: "https://pub.dartlang.org"
       url: "https://pub.dartlang.org"
     source: hosted
     source: hosted
     version: "0.9.6+3"
     version: "0.9.6+3"
+  open_file:
+    dependency: "direct main"
+    description:
+      name: open_file
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.3"
   package_config:
   package_config:
     dependency: transitive
     dependency: transitive
     description:
     description:
@@ -422,6 +443,13 @@ packages:
       url: "https://pub.dartlang.org"
       url: "https://pub.dartlang.org"
     source: hosted
     source: hosted
     version: "1.5.0"
     version: "1.5.0"
+  permission_handler:
+    dependency: "direct main"
+    description:
+      name: permission_handler
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "3.1.0"
   platform:
   platform:
     dependency: transitive
     dependency: transitive
     description:
     description:

+ 4 - 0
pubspec.yaml

@@ -40,6 +40,10 @@ dependencies:
   gradient_text: ^1.0.2
   gradient_text: ^1.0.2
   sprintf: ^4.0.2
   sprintf: ^4.0.2
   flutter_html: ^0.10.1+hotfix.1
   flutter_html: ^0.10.1+hotfix.1
+  flutter_bugly: ^0.2.2
+  install_plugin: ^2.0.1
+  open_file: ^2.0.3
+  permission_handler: ^3.1.0
 
 
 dev_dependencies:
 dev_dependencies:
   build_runner: ^1.1.1
   build_runner: ^1.1.1