Primroses 3 лет назад
Родитель
Сommit
1a4fed4ae7
36 измененных файлов с 1497 добавлено и 639 удалено
  1. 6 0
      lib/bean/message.dart
  2. 6 1
      lib/bean/post.dart
  3. 58 0
      lib/bean/share_info.dart
  4. 12 3
      lib/bean/sport_index.dart
  5. 6 1
      lib/bean/user.dart
  6. 101 11
      lib/db/message_db.dart
  7. 14 0
      lib/pages/home/home_info_page.dart
  8. 12 2
      lib/pages/home/sport_detail_page.dart
  9. 1 1
      lib/pages/home_page.dart
  10. 1 1
      lib/pages/my/my_page.dart
  11. 3 2
      lib/pages/my/user_info_page.dart
  12. 164 61
      lib/pages/social/chat_page.dart
  13. 363 0
      lib/pages/social/message_list_subpage.dart
  14. 6 303
      lib/pages/social/message_page.dart
  15. 50 1
      lib/pages/social/post_detail_page.dart
  16. 95 10
      lib/pages/social/post_page.dart
  17. 93 31
      lib/pages/social/post_share_page.dart
  18. 53 0
      lib/pages/social/post_widget.dart
  19. 13 7
      lib/pages/social/search_page.dart
  20. 18 8
      lib/pages/social/share_achievement.dart
  21. 46 42
      lib/pages/social/share_webview.dart
  22. 4 4
      lib/pages/social/user_friend_add_page.dart
  23. 3 1
      lib/pages/social/user_friend_page.dart
  24. 15 2
      lib/provider/message_model.dart
  25. 8 1
      lib/provider/sport_index_model.dart
  26. 5 0
      lib/services/Converter.dart
  27. 11 2
      lib/services/api/rest_client.dart
  28. 51 6
      lib/services/api/rest_client.g.dart
  29. 4 0
      lib/sharesdk/tencent.dart
  30. 21 3
      lib/sharesdk/wechat.dart
  31. 30 11
      lib/widgets/button_primary.dart
  32. 3 1
      lib/widgets/dialog/request_dialog.dart
  33. 33 22
      lib/widgets/dialog/share_popup.dart
  34. 118 76
      lib/widgets/menu_bar.dart
  35. 69 24
      lib/widgets/menu_share_bottom.dart
  36. 1 1
      pubspec.yaml

+ 6 - 0
lib/bean/message.dart

@@ -1,3 +1,5 @@
+import 'package:sport/bean/share_info.dart';
+
 class MessageInstance {
   int fromId;
   int toId;
@@ -68,6 +70,7 @@ class MessageData {
   MessagePostUser user;
   MessageForum forum;
   MessageSubject subject;
+  Share share;
 
   MessageData({
     this.text,
@@ -76,6 +79,7 @@ class MessageData {
     this.user,
     this.forum,
     this.subject,
+    this.share
   });
 
   MessageData.fromJson(Map<String, dynamic> json) {
@@ -87,6 +91,7 @@ class MessageData {
     subject = json['subject'] != null
         ? MessageSubject.fromJson(json["subject"])
         : null;
+    share = json['share'] != null ? Share.fromJson(json['share']):null;
   }
 
   Map<String, dynamic> toJson() {
@@ -97,6 +102,7 @@ class MessageData {
     map['user'] = this.user;
     map['forum'] = this.forum;
     map['subject'] = this.subject;
+    map["share"] = this.share;
     return map;
   }
 }

+ 6 - 1
lib/bean/post.dart

@@ -30,6 +30,7 @@ class Post {
   Post quoteSubject;
   List<String> tags;
   String followStatus;
+  String quoteData;
 
   Post(
       {this.id,
@@ -46,7 +47,9 @@ class Post {
       this.nickname,
       this.avatar,
       this.createTime,
-      this.isLiked});
+      this.isLiked,
+      this.quoteData,
+      });
 
   Post.fromJson(Map<String, dynamic> json) {
     id = json['id'];
@@ -99,6 +102,7 @@ class Post {
       }
     }
     followStatus = json['follow_status'];
+    quoteData = json['quote_data'];
   }
 
   Map<String, dynamic> toJson() {
@@ -126,6 +130,7 @@ class Post {
     if (this.quoteSubject != null) {
       data['quoteSubject'] = this.quoteSubject.toJson();
     }
+    data['quote_data'] = this.quoteData;
     return data;
   }
 

+ 58 - 0
lib/bean/share_info.dart

@@ -0,0 +1,58 @@
+import 'package:sport/services/Converter.dart';
+
+class ShareInfo {
+  int id;
+  String hash;
+
+  ShareInfo.fromJson(Map<String, dynamic> json) {
+    id = Converter.toInt(json['id']);
+    hash = json['hash'];
+  }
+
+  Map<String, dynamic> toJson() {
+    final Map<String, dynamic> data = new Map<String, dynamic>();
+    data['id'] = this.id;
+    data["share"] = this.hash;
+    return data;
+  }
+}
+
+class Share {
+  int id;
+  String hash;
+  int consume;
+  double defeat;
+  int duration;
+  String period;
+  double weight;
+  Share(
+      {this.id,
+      this.hash,
+      this.consume,
+      this.defeat,
+      this.duration,
+      this.period,
+      this.weight});
+
+  Share.fromJson(Map<String, dynamic> json) {
+    id = Converter.toInt(json['id']);
+    hash = json["hash"];
+    consume = json['consume'];
+    defeat = json['defeat'];
+    duration = json['duration'];
+    period = json['period'];
+    weight = json['weight'];
+  }
+
+  Map<String, dynamic> toJson() {
+    final Map<String, dynamic> data = new Map<String, dynamic>();
+    data['id'] = this.id;
+    data["hash"] = this.hash;
+    data["consume"] = this.consume;
+    data['defeat'] = this.defeat;
+    data['duration'] = this.duration;
+    data['period'] = this.period;
+    data['weight'] = this.weight;
+    return data;
+  }
+}

+ 12 - 3
lib/bean/sport_index.dart

@@ -1,6 +1,6 @@
 
-import 'package:sport/bean/rank_game_info.dart';
 import 'package:sport/bean/user.dart';
+//import 'package:sport/bean/user.dart';
 
 import 'game.dart' as game;
 
@@ -14,9 +14,10 @@ class SportIndex{
   game.GameInfoData lastGame;
   List<game.GameInfoData> games;
   RankInfo rank;
+  List<Achievement> achievement;
 
   SportIndex(
-      {this.duration, this.durationTarget, this.consume, this.beyond, this.inspire, this.lastGame});
+      {this.duration, this.durationTarget, this.consume, this.beyond, this.inspire, this.lastGame,this.achievement});
 
   SportIndex.fromJson(Map<String, dynamic> json) {
     duration = json['duration'];
@@ -34,6 +35,13 @@ class SportIndex{
         games.add(new game.GameInfoData.fromJson(v));
       });
     }
+
+    if(json['new_achievements'] != null){
+      achievement = new List<Achievement>();
+      json['new_achievements'].forEach((v) {
+        achievement.add(new Achievement.fromJson(v));
+      });
+    }
   }
 
   Map<String, dynamic> toJson() {
@@ -46,6 +54,7 @@ class SportIndex{
     if (this.lastGame != null) {
       data['last_game'] = this.lastGame.toJson();
     }
+    data["new_achievements"] = this.achievement;
     return data;
   }
 }
@@ -129,4 +138,4 @@ class Rank {
     data['rate_end'] = this.rateEnd;
     return data;
   }
-}
+}

+ 6 - 1
lib/bean/user.dart

@@ -120,6 +120,7 @@ class Achievement {
   String createdAt;
   String conditionDetail;
   String conditionMeasure;
+  int userCount;
 
   Achievement(
       {this.id,
@@ -132,7 +133,9 @@ class Achievement {
         this.conditionProgress,
         this.createdAt,
         this.conditionDetail,
-        this.conditionMeasure});
+        this.conditionMeasure,
+        this.userCount
+      });
 
   Achievement.fromJson(Map<String, dynamic> json) {
     id = json['id'];
@@ -147,6 +150,7 @@ class Achievement {
     createdAt = json['created_at'] == null ? "" : json['created_at'] ;
     conditionDetail = json['condition_detail'];
     conditionMeasure = json['condition_measure'];
+    userCount = json['user_count'];
   }
 
   Map<String, dynamic> toJson() {
@@ -163,6 +167,7 @@ class Achievement {
     data['created_at'] = this.createdAt;
     data['condition_detail'] = this.conditionDetail;
     data['condition_measure'] = this.conditionMeasure;
+    data['user_count'] = this.userCount;
     return data;
   }
 }

+ 101 - 11
lib/db/message_db.dart

@@ -2,6 +2,7 @@ import 'dart:async';
 import 'dart:convert';
 
 import 'package:path/path.dart';
+import 'package:sport/bean/login.dart';
 import 'package:sport/bean/message.dart';
 import 'package:sqflite/sqflite.dart';
 
@@ -12,13 +13,24 @@ class MessageItem {
   int userId;
   int unReadCount; //未读数量...
   int messageId;
-  MessageItem(
-      {this.message,
-      this.status,
-      this.curId,
-      this.userId,
-      this.unReadCount,
-      this.messageId});
+  int isTop;
+  // 时间
+  int day;
+  int time;
+  String messageType;
+  String dateTime;
+  MessageItem({
+    this.message,
+    this.status,
+    this.curId,
+    this.userId,
+    this.unReadCount,
+    this.messageId,
+    this.messageType,
+    this.day,
+    this.time,
+    this.dateTime,
+  });
 
   Map<String, dynamic> toJson() {
     final Map<String, dynamic> data = new Map<String, dynamic>();
@@ -26,6 +38,7 @@ class MessageItem {
     data['status'] = this.status;
     data['curId'] = this.curId;
     data['userId'] = this.userId;
+    data['messageId'] = this.messageId;
 //    data['unReadCount'] = this.unReadCount;
 //    data["messageId"] = this.messageId;
     return data;
@@ -33,14 +46,38 @@ class MessageItem {
 
   MessageItem.fromJson(Map<String, dynamic> map) {
     message = MessageInstance.fromJson(json.decode(map['message']));
+    if (message != null && message.createdAt.isNotEmpty == true) {
+      var t = DateTime.parse(message.createdAt);
+      day = t.day;
+      time = t.millisecondsSinceEpoch;
+    }
     status = map['status'];
     curId = map['curId'];
     userId = map['userId'];
+    messageId = map['messageId'];
 //    unReadCount = map['unReadCount'];
 //    messageId = map['messageId'];
   }
 }
 
+class UserTableInfo {
+  int userId;
+  int isTop;
+
+  UserTableInfo({this.userId, this.isTop});
+
+  UserTableInfo.fromJson(Map<String, dynamic> map) {
+    userId = map['userId'];
+    isTop = map['isTop'];
+  }
+  Map<String, dynamic> toJson() {
+    final Map<String, dynamic> data = new Map<String, dynamic>();
+    data['userId'] = this.userId;
+    data['isTop'] = this.isTop;
+    return data;
+  }
+}
+
 class MessageDB {
   static final MessageDB _instance = new MessageDB.internal();
 
@@ -60,6 +97,7 @@ class MessageDB {
   }
 
   final String TABLE = 'Message';
+  final String USERTABLE = "user";
 
   initDb() async {
     String databasesPath = await getDatabasesPath();
@@ -74,9 +112,13 @@ class MessageDB {
   // @message   信息
   // @userId    跟谁聊天的信息 跟谁 跟谁 跟谁 跟谁 ...
   FutureOr<void> _onCreate(Database db, int version) async {
-    print("Create Table");
+    // 表1: message表
     await db.execute(
         'CREATE TABLE $TABLE(messageId INTEGER PRIMARY KEY, status INTEGER ,message TEXT, curId INTEGER,userId INTEGER)');
+
+    // 表2: 用户表
+    await db.execute(
+        'CREATE TABLE $USERTABLE(userId INTEGER PRIMARY KEY, isTop INTEGER)');
   }
 
   Future<int> insert(MessageItem item) async {
@@ -85,6 +127,12 @@ class MessageDB {
     return result;
   }
 
+  Future<int> insertUser(UserTableInfo item) async {
+    var dbClient = await db;
+    var result = await dbClient.insert(USERTABLE, item.toJson());
+    return result;
+  }
+
   Future insertAll(List<MessageItem> items) async {
     var dbClient = await db;
     var batch = dbClient.batch();
@@ -109,6 +157,18 @@ class MessageDB {
     );
   }
 
+  Future<List<Map<String, dynamic>>> findHasUserId(int userId) async {
+    var dbClient = await db;
+    return await dbClient
+        .rawQuery("SELECT * FROM $USERTABLE where userId = $userId");
+  }
+
+  Future<List<Map<String, dynamic>>> findAllUser() async {
+    var dbClient = await db;
+    return await dbClient
+        .rawQuery("SELECT * FROM $USERTABLE ORDER BY userId DESC");
+  }
+
   // 更新状态...
   Future<List<Map<String, dynamic>>> updateStatus(int userId) async {
     var dbClient = await db;
@@ -124,6 +184,20 @@ class MessageDB {
     );
   }
 
+  // 更新状态...
+  Future<List<Map<String, dynamic>>> updateIsTop(int userId, int isTop) async {
+    var dbClient = await db;
+    // status = 0 表示 没有置顶  ... 1:已经置顶
+    await dbClient.update(
+      USERTABLE,
+      {"isTop": isTop},
+      // Ensure that the Dog has a matching id.
+      where: "userId = ?",
+      // Pass the Dog's id as a whereArg to prevent SQL injection.
+      whereArgs: [userId],
+    );
+  }
+
   Future<List<Map<String, dynamic>>> getMessageList() async {
     var dbClient = await db;
     return await dbClient.rawQuery(
@@ -146,10 +220,14 @@ class MessageDB {
   // 获取还有多少未读的数量
   Future<List<Map<String, dynamic>>> getMessageUnRead() async {
     var dbClient = await db;
+//    return await dbClient.rawQuery(
+//      "select c.*, ccc.cout from $TABLE c, (select userId, max(messageId) mid FROM $TABLE group by userId) cc, " +
+//          "(select userId, sum(status) cout  FROM $TABLE group by userId) ccc where c.messageId = cc.mid order by messageId desc;",
+//    );
     return await dbClient.rawQuery(
-      "select c.*, ccc.cout from $TABLE c, (select userId, max(messageId) mid FROM $TABLE group by userId) cc, " +
-          "(select userId, sum(status) cout  FROM $TABLE group by userId) ccc where c.messageId = cc.mid order by messageId desc;",
-    );
+        "select u.isTop, c.*, ccc.cout from $TABLE c, (select userId, max(messageId) mid FROM $TABLE group by userId) cc,"
+        "(select userId, sum(status) cout  FROM $TABLE group by userId) ccc, "
+        "$USERTABLE u where c.messageId = cc.mid and cc.userId = ccc.userId and u.userId = cc.userId order by u.isTop desc, messageId desc;");
   }
 
   // 删除数据库
@@ -166,6 +244,18 @@ class MessageDB {
         .delete("$TABLE", where: "messageId = ?", whereArgs: [messageId]);
   }
 
+  Future<int> deleteUserIdMessage(int userId) async {
+    var dbClient = await db;
+    return await dbClient
+        .delete("$TABLE", where: "userId=?", whereArgs: [userId]);
+  }
+
+  Future<int> deleteMessageIdMessage(int messageId) async {
+    var dbClient = await db;
+    return await dbClient
+        .delete("$TABLE", where: "messageId=?", whereArgs: [messageId]);
+  }
+
 //  Future<int> delete(int time) async {
 //    var dbClient = await db;
 //    return await dbClient.delete(TABLE, where: "time <= ?", whereArgs: [time]);

+ 14 - 0
lib/pages/home/home_info_page.dart

@@ -10,6 +10,7 @@ import 'package:sport/bean/game.dart' as game;
 import 'package:sport/bean/sport_index.dart';
 import 'package:sport/bean/user.dart';
 import 'package:sport/constant/ui.dart' show ui_padding, ui_margin_list;
+import 'package:sport/pages/game/detail_bottom.dart';
 import 'package:sport/pages/game/game_info.dart';
 import 'package:sport/pages/home/guide_page.dart';
 import 'package:sport/provider/bluetooth.dart';
@@ -24,6 +25,7 @@ import 'package:sport/widgets/button_primary.dart';
 import 'package:sport/widgets/decoration.dart';
 import 'package:sport/widgets/dialog/request_dialog.dart';
 import 'package:sport/widgets/dialog/search_device.dart';
+import 'package:sport/widgets/dialog/share_popup.dart';
 import 'package:sport/widgets/image.dart';
 import 'package:sport/widgets/loading.dart';
 import 'package:sport/widgets/misc.dart';
@@ -44,6 +46,8 @@ class _PageState extends ViewStateLifecycle<HomeInfoPage, SportIndexModel> with
   void initState() {
     super.initState();
     loadSetting();
+    initList();
+
   }
 
   void loadSetting() async {
@@ -60,6 +64,16 @@ class _PageState extends ViewStateLifecycle<HomeInfoPage, SportIndexModel> with
     model.refresh();
   }
 
+  initList(){
+    model.valueNotifier.addListener(() {
+      print("list--------------------------${model.valueNotifier.value}");
+      if(model.valueNotifier.value.length > 0){
+        Navigator.push( context, new PopRoute(child: sharePopup(model.valueNotifier.value)));
+      }
+    });
+
+  }
+
   @override
   Widget build(BuildContext context) {
     super.build(context);

+ 12 - 2
lib/pages/home/sport_detail_page.dart

@@ -10,6 +10,7 @@ import 'package:flutter_easyrefresh/easy_refresh.dart';
 import 'package:provider/provider.dart';
 import 'package:sport/bean/feed_back.dart';
 import 'package:sport/bean/game.dart';
+import 'package:sport/bean/share_info.dart';
 import 'package:sport/bean/sport_detail.dart';
 import 'package:sport/bean/sport_target.dart';
 import 'package:sport/bean/sport_target_today.dart';
@@ -145,12 +146,21 @@ class _PageState extends State<SportDetailPage> with TickerProviderStateMixin, I
                                   }
                                 });
                                 if (group != null) {
+                                  print("[group:]---------------------------$group");
                                   NavigatorUtil.goPage(context, (context) => FeedbackDetailPage(group));
                                 }
                                 break;
                               case "share":
-//                                ToastUtil.show("分享什么东西~");
-                                  NavigatorUtil.goPage(context, (context)=> WebViewSharePage("www.baidu.com"));
+                                  String hash;
+                                  print("------------------------------------------------------------");
+                                  await request(context, () async {
+                                    ShareInfo _info = (await api.getshareCreateSport("year",50.0)).data;
+                                    hash = _info.hash;
+                                    print("[hash:]---------------------------${_info.hash}");
+                                  });
+                                  if(hash != null){
+                                    NavigatorUtil.goPage(context, (context)=> WebViewSharePage("http://shoes-web.hiyd.com/share",hash: hash,));
+                                  }
                                 break;
                             }
                           },

+ 1 - 1
lib/pages/home_page.dart

@@ -120,7 +120,7 @@ class _HomePageState extends LifecycleState<HomePage> with ConfigInject {
                 _pageController.jumpToPage(index);
                 _valueNotifierIndex.value = index;
                 // 这里得轮询解决
-//                  Navigator.push( context, new PopRoute(child: sharePopup()));
+//
               },
             ),
           ),

+ 1 - 1
lib/pages/my/my_page.dart

@@ -98,7 +98,7 @@ class _MyPageState extends State<MyPage> with InjectApi {
                                               children: <Widget>[
                                                 Row(
                                                   children: <Widget>[
-                                                    Image.asset("lib/assets/img/mine_icon_${model.user.gender == 1 ? "manl" : "girl"}_white.png"),
+                                                    Image.asset("lib/assets/img/mine_icon_${model.user.gender == 1 ? "man" : "girl"}_gray.png"),
                                                     Space(
                                                       width: 4,
                                                     ),

+ 3 - 2
lib/pages/my/user_info_page.dart

@@ -70,7 +70,8 @@ class _PageState extends State<UserInfoPage> with InjectLoginApi {
                       Text("头像"),
                       Consumer<UserModel>(
                         builder: (_, model, __) {
-                          return Container(
+                          // 没有头像就为空...
+                          return  model.user.avatar != null ? Container(
                             width: 40.0,
                             height: 40.0,
                             child: CircleAvatar(
@@ -81,7 +82,7 @@ class _PageState extends State<UserInfoPage> with InjectLoginApi {
                                       _lastCropped,
                                     ),
                             ),
-                          );
+                          ):Container();
                         },
                       )
                     ],

+ 164 - 61
lib/pages/social/chat_page.dart

@@ -5,8 +5,11 @@ import 'dart:math';
 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/scheduler.dart';
 import 'package:flutter/services.dart';
 import 'package:shared_preferences/shared_preferences.dart';
+import 'package:sport/bean/image.dart' as photo;
 import 'package:sport/bean/message.dart';
 import 'package:sport/bean/post.dart';
 import 'package:sport/bean/post_user.dart';
@@ -22,6 +25,7 @@ import 'package:sport/router/navigator_util.dart';
 import 'package:sport/services/api/inject_api.dart';
 import 'package:sport/services/api/resp.dart';
 import 'package:sport/services/userid.dart';
+import 'package:sport/utils/DateFormat.dart';
 import 'package:sport/utils/print_map.dart';
 import 'package:sport/utils/toast.dart';
 import 'package:sport/widgets/appbar.dart';
@@ -32,6 +36,8 @@ import 'package:sport/widgets/space.dart';
 import 'package:sport/widgets/dialog/popupmenu.dart' as menu;
 import 'package:provider/provider.dart';
 
+import 'gallery_photo_view.dart';
+
 final List<String> avatarList = [
   "https://wx3.sinaimg.cn/mw1024/a6bdcd78gy1gfna8yznv5j20m90m9tbz.jpg",
   "https://wx2.sinaimg.cn/mw1024/a6bdcd78gy1gfna8x3nbzj20m90m943a.jpg",
@@ -48,9 +54,10 @@ final List<String> avatarList = [
 
 class ChatPage extends StatefulWidget {
   final UserInfo user;
-  final Post post;
-
-  ChatPage(this.user, {this.post});
+  final Post post; // 分享来的帖子
+  final String hash; // 分享来的link
+  final String image; // 分享来的图片 ...
+  ChatPage(this.user, {this.post, this.hash, this.image});
 
   @override
   State<StatefulWidget> createState() => _ChatPageState();
@@ -60,11 +67,12 @@ class ChatPage extends StatefulWidget {
 class _ChatPageState extends State<ChatPage>
     with InjectLoginApi, InjectApi, UserId, WidgetsBindingObserver {
   GetMenuController _menuController = new GetMenuController();
-
+//  ScrollController scrollMenuController = new ScrollController();
   StreamSubscription _streamSubscription;
   List<MessageItem> messageList = [];
 //  String othersAvatarUrl = "";
   GlobalKey SCROLLVIEW = new GlobalKey();
+  double emptyHeight;
 
   dispose() {
     super.dispose();
@@ -79,21 +87,32 @@ class _ChatPageState extends State<ChatPage>
     addPost(); // 这里是分享过来的 ...
 //    initScrollBottom();
 //    print("${Provider.of<UserModel>(context, listen: false).user.toJson()}");
+//    _menuController.scroll();
   }
 
   // 这个是初始化 聊天列表的...
   initMessageList() async {
+//   await Future.delayed(Duration(milliseconds: 1000));
 //    List<MessageItem> messageList = [];
     List<MessageItem> data = [];
     var list = await MessageDB().getMessageForUserId(widget.user.id);
+    int day = -1;
     for (var item in list) {
       MessageItem _item = MessageItem.fromJson(item);
+      if (_item.day != day) {
+        day = _item.day;
+        data.add(new MessageItem(
+            messageType: "time",
+            dateTime:
+                DateFormat.format(DateTime.parse(_item.message.createdAt))));
+      }
       data.add(_item);
     }
     // 读过就操作一手...
     await MessageDB().updateStatus(widget.user.id);
 
 //    messageList.addAll(data);
+    int cout = 0;
     data.forEach((element) {
       messageList.insert(0, element);
     });
@@ -102,9 +121,17 @@ class _ChatPageState extends State<ChatPage>
     setState(() {
       messageList = messageList;
     });
+//    SchedulerBinding.instance.addPostFrameCallback((_) {
+////here the sublist is already build
+//      scrollMenuController.jumpTo(scrollMenuController.position.maxScrollExtent);
+//      print("2222222222222222222222222");
+//      print("${scrollMenuController.position.minScrollExtent} - ${scrollMenuController.position.maxScrollExtent}");
+//    });
+    _menuController.scroll();
   }
 
   Future addPost() async {
+    // 这里是拿到了 帖子
     if (widget.post != null) {
       // 拿到后还得 存
       MessageInstance _instance = (await api.shareForwardSubject(
@@ -116,6 +143,25 @@ class _ChatPageState extends State<ChatPage>
 
       addMessageToPage(_instance);
     }
+    // 也可能是拿到了 link
+    else if (widget.hash != null) {
+      MessageInstance _instance =
+          (await api.getshareForwardSport(widget.hash, widget.user.id)).data;
+
+      await MessageDB().insert(new MessageItem(
+          message: _instance, status: 0, curId: 0, userId: widget.user.id));
+
+      addMessageToPage(_instance);
+    } else if (widget.image != null) {
+      MessageInstance _instance = (await api.postChatSend(
+              widget.user.id, "image", '{"url":"${widget.image}"}'))
+          .data;
+
+      await MessageDB().insert(new MessageItem(
+          message: _instance, status: 0, curId: 0, userId: widget.user.id));
+
+      addMessageToPage(_instance);
+    }
   }
 
   // 在本页中如果收到了就 ...
@@ -151,9 +197,9 @@ class _ChatPageState extends State<ChatPage>
   // 各种来自别的地方收到的消息 输出到 页面上
   addMessageToPage(MessageInstance _instance) {
     MessageItem item = instanceToItem(_instance);
-    messageList.insert(0, item);
+//    messageList.insert(0, item);
 //    messageList.add(item);
-//    messageList.insert(0, item); // 到头插...
+    messageList.insert(0, item); // 到头插...
     setState(() {
       messageList = messageList;
     });
@@ -165,6 +211,17 @@ class _ChatPageState extends State<ChatPage>
 // @type 聊天的类型 可能是通过分享过来的那种 ? 游戏 或者是 别的 社区 或者是 链接 ?
 
   Widget _buildChatItem(MessageItem item) {
+    // type 是时间 还是 消息...
+    print("${item.toJson()}----------------------------------");
+    if (item.messageType != null) {
+      return Padding(
+        padding: EdgeInsets.symmetric(vertical: 5.0),
+        child: Center(
+          child: Text("${item.dateTime}"),
+        ),
+      );
+    }
+
     GlobalKey anchorKey = GlobalKey();
 
     MessageInstance data = item.message;
@@ -177,6 +234,8 @@ class _ChatPageState extends State<ChatPage>
     String userAvatar = data.fromUser.avatar;
 
     Widget chatItemOfType(String type) {
+      List<photo.Image> images = [];
+      images.add(photo.Image(id: "1", src: data.data.url));
       // 文本或者是图片...
       if (type == "text" || type == "image") {
         return Column(
@@ -191,26 +250,31 @@ class _ChatPageState extends State<ChatPage>
                 key: anchorKey,
               ),
             if (data.data.url != null)
-              CachedNetworkImage(imageUrl: data.data.url)
-//            SizedBox(
-//              height: 10.0,
-//            ),
-//          if (imageUrls?.length != null)
-//            GridView.count(
-//                physics: new NeverScrollableScrollPhysics(),
-//                shrinkWrap: true,
-//                padding: EdgeInsets.zero,
-//                crossAxisSpacing: 10.0,
-//                crossAxisCount: imageUrls.length > 3 ? 3 : imageUrls.length,
-//                mainAxisSpacing: 10.0,
-//                children: imageUrls
-//                    .asMap()
-//                    .keys
-//                    .map((i) => CachedNetworkImage(
-//                          imageUrl: imageUrls[i],
-//                          fit: BoxFit.cover,
-//                        ))
-//                    .toList())
+              InkWell(
+                child: Container(
+                  constraints: BoxConstraints(
+                    maxHeight: MediaQuery.of(context).size.height,
+                    maxWidth: MediaQuery.of(context).size.width,
+                  ),
+                  child: CachedNetworkImage(imageUrl: data.data.url),
+                ),
+                onTap: () {
+                  Navigator.push(
+                    context,
+                    FadeRoute(
+                      page: GalleryPhotoViewWrapper(
+                        galleryItems: images,
+                        backgroundDecoration: const BoxDecoration(
+                          color: Colors.black,
+                        ),
+                        initialIndex: 1,
+                        scrollDirection: Axis.horizontal,
+                        loadingBuilder: (_, __) => RequestLoadingWidget(),
+                      ),
+                    ),
+                  );
+                },
+              )
           ],
           crossAxisAlignment: CrossAxisAlignment.start,
         );
@@ -292,13 +356,14 @@ class _ChatPageState extends State<ChatPage>
         );
       }
       // 链接..
-      if (type == "link") {
+      if (type == "share") {
+        print("${data.toJson()}--------------------------------------");
         return InkWell(
           child: Row(
               crossAxisAlignment: CrossAxisAlignment.start,
               children: <Widget>[
                 CachedNetworkImage(
-                  imageUrl: data.data.logo,
+                  imageUrl: avatarList[9],
                   width: 60.0,
                   height: 60.0,
                 ),
@@ -309,13 +374,13 @@ class _ChatPageState extends State<ChatPage>
                   child: RichText(
                     text: TextSpan(children: [
                       TextSpan(
-                          text: data.data.user.name,
+                          text: data.fromUser.name,
                           style: Theme.of(context)
                               .textTheme
                               .headline6
                               .copyWith(color: Color(0xFFFFC400))),
                       TextSpan(
-                          text: data.data.text,
+                          text: "分享了他的运动记录,快来围观吧~",
                           style: Theme.of(context).textTheme.subtitle1),
                     ]),
                   ),
@@ -323,7 +388,11 @@ class _ChatPageState extends State<ChatPage>
               ]),
           onTap: () async {
             await NavigatorUtil.goPage(
-                context, (context) => WebViewSharePage(data.data.url));
+                context,
+                (context) => WebViewSharePage(
+                      data.data.url,
+                      hash: data.data.share.hash,
+                    ));
           },
         );
       }
@@ -339,6 +408,7 @@ class _ChatPageState extends State<ChatPage>
                   ? EdgeInsets.fromLTRB(12, 6, 20, 8)
                   : EdgeInsets.fromLTRB(20, 6, 12, 8),
               child: GestureDetector(
+                  behavior: HitTestBehavior.opaque,
                   onLongPressStart: (e) {
                     RenderBox renderBox =
                         anchorKey.currentContext.findRenderObject();
@@ -395,10 +465,27 @@ class _ChatPageState extends State<ChatPage>
                               who == 1
                                   ? menuItem(
                                       imgUrl: "linkpop_icon_del.png",
-                                      text: "删除")
+                                      text: "删除",
+                                      callBack: () async {
+                                        await MessageDB()
+                                            .deleteMessageIdMessage(
+                                                item.messageId);
+                                        messageList.remove(item);
+                                        setState(() {
+                                          messageList = messageList;
+                                        });
+                                      },
+                                    )
                                   : menuItem(
                                       imgUrl: "linkpop_icon_modify_1.png",
-                                      text: "举报"),
+                                      text: "举报",
+                                      callBack: () async {
+                                        await api.postForumReport(
+                                            userId: item.userId,
+                                            content:
+                                                "该用户涉嫌发送不良消息内容为:${item.message.data.text}");
+                                        ToastUtil.show("举报已受理...");
+                                      }),
                               menuItem(
                                   imgUrl: "linkpop_icon_cancel.png", text: "取消")
                             ],
@@ -415,8 +502,12 @@ class _ChatPageState extends State<ChatPage>
     );
 
     String avatarUrl = data.fromUser?.id == int.parse(selfId)
-        ? Provider.of<UserModel>(context, listen: false).user.avatar
-        : widget.user.avatar;
+        ? Provider.of<UserModel>(context, listen: false).user?.avatar == null
+            ? avatarList[4]
+            : Provider.of<UserModel>(context, listen: false).user?.avatar
+        : widget.user?.avatar == null
+            ? data.fromUser.avatar
+            : widget.user?.avatar;
 
     Widget avatar = InkWell(
       onTap: () async {
@@ -457,33 +548,45 @@ class _ChatPageState extends State<ChatPage>
           ),
           leading: buildBackButton(context),
         ),
-        resizeToAvoidBottomInset: false, // 透传MediaQuery 的高度?
-        body: MenuBar(
-          CustomScrollView(
-            key: SCROLLVIEW,
-            reverse: true,
-            controller: _menuController.scrollMenuController,
-            slivers: <Widget>[
-              if (messageList?.length == 0)
-                SliverToBoxAdapter(
-                  child: Container(),
-                ),
-              if (messageList?.length != 0)
-                SliverList(
-                  delegate: SliverChildBuilderDelegate((content, index) {
+//        resizeToAvoidBottomInset: false, // 透传MediaQuery 的高度?
+        body: WillPopScope(
+            onWillPop: () async {
+              // 这是分享.... 只能一步一步pop 出去
+              if(widget.post != null || widget.hash != null || widget.image != null){
+                print("${widget.post}=============");
+                Navigator.pop(context,true);
+                return false;
+              }
+              return true;
+            },
+            child: MenuBar(
+              CustomScrollView(
+                key: SCROLLVIEW,
+                shrinkWrap: true,
+                reverse: true,
+                controller: _menuController.scrollMenuController,
+//              controller: scrollMenuController,
+                slivers: <Widget>[
+                  if (messageList?.length == 0)
+                    SliverToBoxAdapter(
+                      child: Container(),
+                    ),
+                  if (messageList?.length != 0)
+                    SliverList(
+                      delegate: SliverChildBuilderDelegate((content, index) {
 //                    MessageInstance data = messageList[index];
-                    return _buildChatItem(messageList[index]);
-                  }, childCount: messageList.length),
-                ),
-            ],
-          ),
-          menuIdentity:
-              new MenuIdentity(menuScene: "chat", userId: widget.user.id),
-          inputField: "",
-//          scrollToBottom: _menuController.scrollToBottom, // 暂时可以废弃...
-          sendCallBack: addMessageToPage,
-          globalkey: SCROLLVIEW,
-        ));
+                        return _buildChatItem(messageList[index]);
+                      }, childCount: messageList.length),
+                    ),
+                ],
+              ),
+              menuIdentity:
+                  new MenuIdentity(menuScene: "chat", userId: widget.user.id),
+              inputField: "",
+              scrollToBottom: _menuController.scroll, // 暂时可以废弃...
+              sendCallBack: addMessageToPage,
+              globalkey: SCROLLVIEW,
+            )));
   }
 }
 

+ 363 - 0
lib/pages/social/message_list_subpage.dart

@@ -0,0 +1,363 @@
+import 'dart:async';
+
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:sport/bean/message.dart';
+import 'package:sport/bean/user_info.dart';
+import 'package:sport/db/message_db.dart';
+import 'package:sport/pages/social/chat_page.dart';
+import 'package:sport/provider/message_model.dart';
+import 'package:sport/router/navigator_util.dart';
+import 'package:sport/services/api/inject_api.dart';
+import 'package:sport/services/userid.dart';
+import 'package:sport/utils/DateFormat.dart';
+import 'package:sport/utils/toast.dart';
+import 'package:sport/widgets/dialog/alert_dialog.dart';
+import 'package:sport/widgets/dialog/popupmenu.dart' as menu;
+import 'package:sport/widgets/error.dart';
+import 'package:sport/widgets/image.dart';
+import 'package:sport/widgets/loading.dart';
+
+class MessageListSubPage extends StatefulWidget {
+  @override
+  State<StatefulWidget> createState() {
+    // TODO: implement createState
+    return _MessageListSubPageState();
+  }
+}
+
+class _MessageListSubPageState extends State<MessageListSubPage>
+    with InjectApi, UserId {
+  List<MessageItem> messageList;
+  StreamSubscription _streamSubscription;
+  bool isLoading = true;
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+    getChatIndex().then((value){
+      setState(() {
+        isLoading = false;
+        messageList = messageList;
+      });
+    });
+    initListen();
+  }
+
+  // MessageInstance 类型是 服务器请求回来的类型 MessageItem 是本地 存储后的类型...
+  Future getChatIndex() async {
+    //    List<ChatMessageInstance> list = (await api.getChatIndex()).results;
+//    var list = await MessageDB().getMessageList();
+    messageList = [];
+    var unReadList = await MessageDB().getMessageUnRead();
+
+    print("[unReadList]:$unReadList---------------------------------------");
+
+    if (unReadList != null && unReadList.length > 0) {
+      List<int> ids = [];
+      for (var item in unReadList) {
+        ids.add(MessageItem.fromJson(item).userId);
+      }
+
+      List<ChatOnlineInfo> chatInfo = (await api.getChatUserInfo(ids)).results;
+
+      // 这不是是个骚的?
+      for (int i = 0; i < unReadList.length; i++) {
+        MessageItem item = MessageItem.fromJson(unReadList[i]);
+        for (int j = 0; j < chatInfo.length; j++) {
+          if (item.userId == chatInfo[j].userId) {
+            if (item.message.fromUser.id == int.parse(selfId)) {
+              item.message.toUser.online = chatInfo[i].online;
+            } else {
+              item.message.fromUser.online = chatInfo[i].online;
+            }
+//            print("[online:]${chatInfo[i].online}------------------------");
+            item.message.relate = chatInfo[i].relate;
+            item.unReadCount = unReadList[i]['cout'];
+            item.isTop = unReadList[i]['isTop'];
+          }
+        }
+        messageList.add(item);
+      }
+    }
+//    return messageList;
+  }
+
+  // 在本页中如果收到了就 ...
+  initListen() {
+    Stream<List<MessageInstance>> queryStream =
+        Provider.of<MessageModel>(context, listen: false).queryStream;
+    _streamSubscription = queryStream.listen((List<MessageInstance> list) {
+      print("[receive:message]:$list-----------------------------");
+      getChatIndex();
+    });
+  }
+
+  void dispose() {
+    super.dispose();
+    _streamSubscription?.cancel();
+  }
+
+  Widget messageWidget(
+      BuildContext context, api, id, online, avatar, name, messageList, index) {
+    GlobalKey messageKey = new GlobalKey();
+    return GestureDetector(
+      behavior: HitTestBehavior.opaque,
+      key: messageKey,
+      onTap: () async {
+        UserInfo info = (await api.getUserInfo("$id")).data;
+        await NavigatorUtil.goPage(context, (context) => ChatPage(info));
+        getChatIndex().then((value){
+          setState(() {
+            isLoading = false;
+            messageList = messageList;
+          });
+        }); // 原来是为了更新那个红点的...
+      },
+      onLongPressStart: (e) async {
+        RenderBox renderBox = messageKey.currentContext.findRenderObject();
+        var offset =
+            renderBox.localToGlobal(Offset(0.0, renderBox.size.height));
+        final RelativeRect position = RelativeRect.fromLTRB(
+            e.globalPosition.dx, //取点击位置坐弹出x坐标
+            offset.dy, //取text高度做弹出y坐标(这样弹出就不会遮挡文本)
+            e.globalPosition.dx,
+            offset.dy);
+
+        PopupMenuEntry menuItem(
+                {String imgUrl, String text, dynamic callBack}) =>
+            menu.PopupMenuItem(
+              value: callBack,
+              child: Row(
+                mainAxisSize: MainAxisSize.min,
+                children: <Widget>[
+                  if (imgUrl != null)
+                    Image.asset(
+                      "lib/assets/img/$imgUrl",
+                      width: 24,
+                    ),
+                  SizedBox(
+                    width: 4,
+                  ),
+                  Text(
+                    text,
+                  )
+                ],
+              ),
+            );
+
+        var d = await showMenu(
+          context: context,
+          position: position,
+          items: <PopupMenuEntry>[
+            PopupMenuItem(
+                child: Container(
+              child: Column(
+                children: <Widget>[
+                  menuItem(
+                      text: messageList[index].isTop == 1 ? "取消置顶" : "置顶",
+                      callBack: 1),
+                  menuItem(text: "删除聊天", callBack: 2)
+                ],
+              ),
+            ))
+          ],
+        );
+        if (d == 1) {
+//        Navigator.of(context).pop(1);
+          await MessageDB()
+              .updateIsTop(id, messageList[index].isTop == 1 ? 0 : 1);
+          ToastUtil.show("${messageList[index].isTop}");
+        } else if (d == 2) {
+          bool flag = await showDialog(
+              context: context,
+              builder: (context) => CustomAlertDialog(
+                  title: '是否删除聊天记录',
+                  ok: () => Navigator.of(context).pop(true)));
+
+          if (flag) {
+            await MessageDB().deleteUserIdMessage(id);
+            getChatIndex();
+            ToastUtil.show("删除成功");
+          }
+        }
+      },
+      child: Padding(
+        padding: const EdgeInsets.all(12.0),
+        child: Column(
+          children: <Widget>[
+            Padding(
+                padding: const EdgeInsets.all(12.0),
+                child: Row(
+                  children: <Widget>[
+                    !online
+                        ? ColorFiltered(
+                            colorFilter:
+                                ColorFilter.mode(Colors.white, BlendMode.color),
+                            child: CircleAvatar(
+                              backgroundImage: userAvatarProvider(avatar),
+                              radius: 22,
+                            ),
+                          )
+                        : CircleAvatar(
+                            backgroundImage: userAvatarProvider(avatar),
+                            radius: 22,
+                          ),
+                    SizedBox(
+                      width: 8,
+                    ),
+                    Expanded(
+                      flex: 3,
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: <Widget>[
+                          Row(
+                            children: <Widget>[
+                              Expanded(
+                                child: Text(
+                                  "$name",
+                                  style: Theme.of(context).textTheme.headline3,
+                                  maxLines: 1,
+                                  overflow: TextOverflow.ellipsis,
+                                ),
+                              ),
+                              SizedBox(
+                                width: 4.0,
+                              ),
+                              messageList[index].message.relate != 'friends'
+                                  ? Container(
+                                      padding:
+                                          EdgeInsets.symmetric(horizontal: 5.0),
+                                      decoration: BoxDecoration(
+                                          border: Border.all(
+                                              color: Color(0xffffc400)),
+                                          borderRadius: BorderRadius.all(
+                                              Radius.circular(8.0))),
+                                      child: Text(
+                                        "未关注",
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .bodyText1
+                                            .copyWith(color: Color(0xffffc400)),
+                                      ))
+                                  : Container()
+                            ],
+                          ),
+                          SizedBox(
+                            height: 4,
+                          ),
+                          if (messageList[index].message.type == "text")
+                            Text(
+                              "${messageList[index].message.data.text}",
+                              style: Theme.of(context).textTheme.bodyText1,
+                              maxLines: 1,
+                              overflow: TextOverflow.ellipsis,
+                            ),
+                          if (messageList[index].message.type ==
+                              "forum-forward")
+                            Text(
+                              "${messageList[index].message.data.subject.content}",
+                              style: Theme.of(context).textTheme.bodyText1,
+                              maxLines: 1,
+                              overflow: TextOverflow.ellipsis,
+                            ),
+                          if (messageList[index].message.type == "image")
+                            Text(
+                              "分享图片",
+                              style: Theme.of(context).textTheme.bodyText1,
+                              maxLines: 1,
+                              overflow: TextOverflow.ellipsis,
+                            ),
+                          if (messageList[index].message.type == "share")
+                            Text(
+                              "分享链接",
+                              style: Theme.of(context).textTheme.bodyText1,
+                              maxLines: 1,
+                              overflow: TextOverflow.ellipsis,
+                            )
+                        ],
+                      ),
+                    ),
+                    SizedBox(
+                      width: 8,
+                    ),
+                    Expanded(
+                      flex: 1,
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.end,
+                        mainAxisAlignment: MainAxisAlignment.center,
+                        children: <Widget>[
+                          Text(
+                            "${DateFormat.format(DateTime.parse(messageList[index].message.createdAt))}",
+                            style: Theme.of(context).textTheme.bodyText1,
+                          ),
+                          SizedBox(
+                            height: 3,
+                          ),
+                          if (messageList[index].unReadCount > 0)
+                            ClipOval(
+                                child: Container(
+                              width: 21.0,
+                              height: 21.0,
+                              color: Color(0xffff5B1D),
+                              child: Center(
+                                child: Text(
+                                  '${messageList[index].unReadCount}',
+                                  style: TextStyle(
+                                      color: Colors.white, fontSize: 12.0),
+                                ),
+                              ),
+                            ))
+                        ],
+                      ),
+                    )
+                  ],
+                )),
+          ],
+        ),
+      ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    if (isLoading) return LoadingWidget();
+    // TODO: implement build
+    return messageList.length <= 0
+        ? Center(
+            child: RequestErrorWidget(
+              null,
+              msg: "暂无消息",
+              assets: RequestErrorWidget.ASSETS_NO_COMMENT,
+            ),
+          )
+        : ListView.separated(
+            padding: EdgeInsets.zero,
+            separatorBuilder: (context, index) => Divider(
+                  height: 1,
+                ),
+            itemCount: messageList?.length ?? 0,
+            itemBuilder: (context, index) {
+              // 这里可能有得后续看看怎么写比较好 ... 判断是否是自己 ...
+              // 这里拿的时候得判断一手 是自己还是别人发的...
+              int id;
+              String name;
+              String avatar;
+              bool online;
+              if (messageList[index].message.fromUser.id == int.parse(selfId)) {
+                id = messageList[index].message.toUser.id;
+                name = messageList[index].message.toUser.name;
+                avatar = messageList[index].message.toUser.avatar;
+                online = messageList[index].message.toUser.online;
+              } else {
+                id = messageList[index].message.fromUser.id;
+                name = messageList[index].message.fromUser.name;
+                avatar = messageList[index].message.fromUser.avatar;
+                online = messageList[index].message.fromUser.online;
+              }
+              return messageWidget(
+                  context, api, id, online, avatar, name, messageList, index);
+            });
+  }
+}

+ 6 - 303
lib/pages/social/message_page.dart

@@ -23,11 +23,14 @@ import 'package:sport/services/userid.dart';
 import 'package:sport/utils/DateFormat.dart';
 import 'package:sport/utils/toast.dart';
 import 'package:sport/widgets/appbar.dart';
+import 'package:sport/widgets/dialog/alert_dialog.dart';
 import 'package:sport/widgets/error.dart';
 import 'package:sport/widgets/image.dart';
 import 'package:sport/widgets/loading.dart';
 import 'package:sport/widgets/misc.dart';
 import 'package:sport/widgets/persistent_header.dart';
+import 'package:sport/widgets/dialog/popupmenu.dart' as menu;
+import 'package:sport/pages/social/message_list_subpage.dart';
 
 class MessagePage extends StatefulWidget {
   @override
@@ -39,8 +42,6 @@ class _PageState extends State<MessagePage>
   TabController _controller;
   Future<List<Notice>> _future;
 
-  StreamSubscription _streamSubscription;
-  List<MessageItem> messageList;
   final List<String> avatarList = [
     "https://wx3.sinaimg.cn/mw1024/a6bdcd78gy1gfna8yznv5j20m90m9tbz.jpg",
     "https://wx2.sinaimg.cn/mw1024/a6bdcd78gy1gfna8x3nbzj20m90m943a.jpg",
@@ -61,8 +62,6 @@ class _PageState extends State<MessagePage>
     super.initState();
     _controller = TabController(length: 2, vsync: this);
     _future = _getNotice();
-    getChatIndex(); // 初始化chat...
-    initListen();
   }
 
   Future<List<Notice>> _getNotice() async {
@@ -74,65 +73,10 @@ class _PageState extends State<MessagePage>
     return items;
   }
 
-  // MessageInstance 类型是 服务器请求回来的类型 MessageItem 是本地 存储后的类型...
-  void getChatIndex() async {
-    //    List<ChatMessageInstance> list = (await api.getChatIndex()).results;
-//    var list = await MessageDB().getMessageList();
-    messageList = [];
-    var unReadList = await MessageDB().getMessageUnRead();
-
-//    print("[unReadList]:$unReadList---------------------------------------");
-
-    if (unReadList != null && unReadList.length > 0) {
-      List<int> ids = [];
-      for (var item in unReadList) {
-        ids.add(MessageItem.fromJson(item).userId);
-      }
-
-      List<ChatOnlineInfo> chatInfo = (await api.getChatUserInfo(ids)).results;
-
-      // 这不是是个骚的?
-      for (int i = 0; i < unReadList.length; i++) {
-        MessageItem item = MessageItem.fromJson(unReadList[i]);
-        for (int j = 0; j < chatInfo.length; j++) {
-          if (item.userId == chatInfo[j].userId) {
-            if (item.message.fromUser.id == int.parse(selfId)) {
-              item.message.toUser.online = chatInfo[i].online;
-            } else {
-              item.message.fromUser.online = chatInfo[i].online;
-            }
-//            print("[online:]${chatInfo[i].online}------------------------");
-            item.message.relate = chatInfo[i].relate;
-            item.unReadCount = unReadList[i]['cout'];
-          }
-        }
-        messageList.add(item);
-      }
-    }
-    setState(() {
-      messageList = messageList;
-    });
-//    return messageList;
-  }
-
-  // 在本页中如果收到了就 ...
-  initListen() {
-    Stream<List<MessageInstance>> queryStream =
-        Provider.of<MessageModel>(context, listen: false).queryStream;
-    _streamSubscription = queryStream.listen((List<MessageInstance> list) {
-//      for (MessageInstance item in list) {
-//        addMessageToPage(item);
-//      }
-      print("[receive:message]:$list-----------------------------");
-      getChatIndex();
-    });
-  }
-
   @override
   void dispose() {
     _controller?.dispose();
     super.dispose();
-    _streamSubscription?.cancel();
   }
 
   @override
@@ -239,10 +183,10 @@ class _PageState extends State<MessagePage>
                                     indicatorPadding:
                                         EdgeInsets.symmetric(horizontal: 6),
                                     tabs: <Widget>[
-                                      Tab(text: '消息'),
                                       Tab(
                                         text: '聊天',
                                       ),
+                                      Tab(text: '消息'),
                                       Tab(text: '通知')
                                     ],
                                   ),
@@ -263,6 +207,8 @@ class _PageState extends State<MessagePage>
             },
             body: TabBarView(children: [
               NestedScrollViewInnerScrollPositionKeyWidget(
+                  const Key('Tab0'), Container(child: MessageListSubPage())),
+              NestedScrollViewInnerScrollPositionKeyWidget(
                   const Key('Tab0'),
                   ListView.separated(
                     padding: EdgeInsets.zero,
@@ -389,250 +335,7 @@ class _PageState extends State<MessagePage>
                     ),
                     itemCount: 3,
                   )),
-              NestedScrollViewInnerScrollPositionKeyWidget(
-                  const Key('Tab0'),
-                  Container(
-                      child: messageList == null
-                          ? RequestLoadingWidget()
-                          : messageList.length == 0
-                              ? Center(
-                                  child: RequestErrorWidget(
-                                    null,
-                                    msg: "暂无消息",
-                                    assets:
-                                        RequestErrorWidget.ASSETS_NO_COMMENT,
-                                  ),
-                                )
-                              : ListView.separated(
-                                  padding: EdgeInsets.zero,
-                                  separatorBuilder: (context, index) => Divider(
-                                        height: 1,
-                                      ),
-                                  itemCount: messageList?.length ?? 0 + 1,
-                                  itemBuilder: (context, index) {
-                                    // 这里可能有得后续看看怎么写比较好 ... 判断是否是自己 ...
-                                    // 这里拿的时候得判断一手 是自己还是别人发的...
-                                    int id;
-                                    String name;
-                                    String avatar;
-                                    bool online;
-                                    if (messageList[index]
-                                            .message
-                                            .fromUser
-                                            .id ==
-                                        int.parse(selfId)) {
-                                      id = messageList[index].message.toUser.id;
-                                      name = messageList[index]
-                                          .message
-                                          .toUser
-                                          .name;
-                                      avatar = messageList[index]
-                                          .message
-                                          .toUser
-                                          .avatar;
-                                      online = messageList[index]
-                                          .message
-                                          .toUser
-                                          .online;
-                                    } else {
-                                      id = messageList[index]
-                                          .message
-                                          .fromUser
-                                          .id;
-                                      name = messageList[index]
-                                          .message
-                                          .fromUser
-                                          .name;
-                                      avatar = messageList[index]
-                                          .message
-                                          .fromUser
-                                          .avatar;
-                                      online = messageList[index]
-                                          .message
-                                          .fromUser
-                                          .online;
-                                    }
 
-                                    return InkWell(
-                                      onTap: () async {
-                                        UserInfo info = (await api.getUserInfo("$id")).data;
-                                        await NavigatorUtil.goPage(context,
-                                            (context) => ChatPage(info));
-                                        getChatIndex();
-                                      },
-                                      child: Padding(
-                                        padding: const EdgeInsets.all(12.0),
-                                        child: Column(
-                                          children: <Widget>[
-                                            Padding(
-                                                padding:
-                                                    const EdgeInsets.all(12.0),
-                                                child: Row(
-                                                  children: <Widget>[
-                                                    !online
-                                                        ? ColorFiltered(
-                                                            colorFilter:
-                                                                ColorFilter.mode(
-                                                                    Colors
-                                                                        .white,
-                                                                    BlendMode
-                                                                        .color),
-                                                            child: CircleAvatar(
-                                                              backgroundImage:
-                                                                  userAvatarProvider(
-                                                                      avatar),
-                                                              radius: 22,
-                                                            ),
-                                                          )
-                                                        : CircleAvatar(
-                                                            backgroundImage:
-                                                                userAvatarProvider(
-                                                                    avatar),
-                                                            radius: 22,
-                                                          ),
-                                                    SizedBox(
-                                                      width: 8,
-                                                    ),
-                                                    Expanded(
-                                                      flex: 3,
-                                                      child: Column(
-                                                        crossAxisAlignment:
-                                                            CrossAxisAlignment
-                                                                .start,
-                                                        children: <Widget>[
-                                                          Row(
-                                                            children: <Widget>[
-                                                              Expanded(
-                                                                child: Text(
-                                                                  "$name",
-                                                                  style: Theme.of(
-                                                                          context)
-                                                                      .textTheme
-                                                                      .headline3,
-                                                                  maxLines: 1,
-                                                                  overflow:
-                                                                      TextOverflow
-                                                                          .ellipsis,
-                                                                ),
-                                                              ),
-                                                              SizedBox(
-                                                                width: 4.0,
-                                                              ),
-                                                              messageList[index]
-                                                                          .message
-                                                                          .relate !=
-                                                                      'friends'
-                                                                  ? Container(
-                                                                      padding: EdgeInsets.symmetric(
-                                                                          horizontal:
-                                                                              5.0),
-                                                                      decoration: BoxDecoration(
-                                                                          border: Border.all(
-                                                                              color: Color(
-                                                                                  0xffffc400)),
-                                                                          borderRadius: BorderRadius.all(Radius.circular(
-                                                                              8.0))),
-                                                                      child:
-                                                                          Text(
-                                                                        "未关注",
-                                                                        style: Theme.of(context)
-                                                                            .textTheme
-                                                                            .bodyText1
-                                                                            .copyWith(color: Color(0xffffc400)),
-                                                                      ))
-                                                                  : Container()
-                                                            ],
-                                                          ),
-                                                          SizedBox(
-                                                            height: 4,
-                                                          ),
-                                                          if (messageList[index]
-                                                                  .message
-                                                                  .type ==
-                                                              "text")
-                                                            Text(
-                                                              "${messageList[index].message.data.text}",
-                                                              style: Theme.of(
-                                                                      context)
-                                                                  .textTheme
-                                                                  .bodyText1,
-                                                              maxLines: 1,
-                                                              overflow:
-                                                                  TextOverflow
-                                                                      .ellipsis,
-                                                            ),
-                                                          if (messageList[index]
-                                                                  .message
-                                                                  .type ==
-                                                              "forum-forward")
-                                                            Text(
-                                                              "${messageList[index].message.data.subject.content}",
-                                                              style: Theme.of(
-                                                                      context)
-                                                                  .textTheme
-                                                                  .bodyText1,
-                                                              maxLines: 1,
-                                                              overflow:
-                                                                  TextOverflow
-                                                                      .ellipsis,
-                                                            ),
-                                                        ],
-                                                      ),
-                                                    ),
-                                                    SizedBox(
-                                                      width: 8,
-                                                    ),
-                                                    Expanded(
-                                                      flex: 1,
-                                                      child: Column(
-                                                        crossAxisAlignment:
-                                                            CrossAxisAlignment
-                                                                .end,
-                                                        mainAxisAlignment:
-                                                            MainAxisAlignment
-                                                                .center,
-                                                        children: <Widget>[
-                                                          Text(
-                                                            "${DateFormat.format(DateTime.parse(messageList[index].message.createdAt))}",
-                                                            style: Theme.of(
-                                                                    context)
-                                                                .textTheme
-                                                                .bodyText1,
-                                                          ),
-                                                          SizedBox(
-                                                            height: 3,
-                                                          ),
-                                                          if (messageList[index]
-                                                                  .unReadCount >
-                                                              0)
-                                                            ClipOval(
-                                                                child:
-                                                                    Container(
-                                                              width: 21.0,
-                                                              height: 21.0,
-                                                              color: Color(
-                                                                  0xffff5B1D),
-                                                              child: Center(
-                                                                child: Text(
-                                                                  '${messageList[index].unReadCount}',
-                                                                  style: TextStyle(
-                                                                      color: Colors
-                                                                          .white,
-                                                                      fontSize:
-                                                                          12.0),
-                                                                ),
-                                                              ),
-                                                            ))
-                                                        ],
-                                                      ),
-                                                    )
-                                                  ],
-                                                )),
-                                          ],
-                                        ),
-                                      ),
-                                    );
-                                  }))),
               NestedScrollViewInnerScrollPositionKeyWidget(
                   const Key('Tab0'),
                   Container(

+ 50 - 1
lib/pages/social/post_detail_page.dart

@@ -1,3 +1,4 @@
+import 'dart:convert';
 import 'dart:math';
 
 import 'package:cached_network_image/cached_network_image.dart';
@@ -12,6 +13,7 @@ import 'package:sport/pages/social/gallery_photo_view.dart';
 import 'package:sport/pages/social/notification.dart';
 import 'package:sport/pages/social/post_comment.dart';
 import 'package:sport/pages/social/post_share_page.dart';
+import 'package:sport/pages/social/share_webview.dart';
 import 'package:sport/provider/lib/provider_widget.dart';
 import 'package:sport/provider/lib/view_state_lifecycle.dart';
 import 'package:sport/provider/post_detail_model.dart';
@@ -35,6 +37,8 @@ import 'package:sport/widgets/popmenu_bg.dart';
 import 'package:sport/widgets/space.dart';
 import 'package:sport/widgets/text_input.dart' as input;
 
+import 'chat_page.dart';
+
 class PostDetailPage extends StatefulWidget {
   final List posts;
   final Post post;
@@ -164,6 +168,7 @@ class _PageState extends ViewStateLifecycle<PostDetailPage, PostDetailModel> wit
   }
 
   Widget _postWidget(Post post) {
+    print(post.quoteData);
     double width = MediaQuery.of(context).size.width - 24 - 22;
     return Column(
       crossAxisAlignment: CrossAxisAlignment.start,
@@ -251,6 +256,34 @@ class _PageState extends ViewStateLifecycle<PostDetailPage, PostDetailModel> wit
       ],
     );
   }
+  Widget _postLink(String quote){
+    var data = json.decode(quote);
+    return Container(
+        color: Theme.of(context).scaffoldBackgroundColor,
+      child: Row(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          mainAxisSize: MainAxisSize.max,
+          children: <Widget>[
+            CachedNetworkImage(
+              imageUrl: avatarList[4],
+              width: 60.0,
+              height: 60.0,
+            ),
+            Space(
+              width: 5.0,
+            ),
+            Expanded(
+              child: RichText(
+                maxLines: 3,
+                overflow: TextOverflow.ellipsis,
+                text: TextSpan(style: Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 16), children: <InlineSpan>[
+                  TextSpan(text: '${data["username"]["value"]}:', style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)),
+                  TextSpan(text: '分享了他的运动记录,快来围观吧~', style: Theme.of(context).textTheme.subtitle1),
+                ]),
+              ),
+            ),]),
+    );
+  }
 
   Widget _buildPostDetailWidget(Post post) {
     double width = MediaQuery.of(context).size.width - 24;
@@ -480,6 +513,22 @@ class _PageState extends ViewStateLifecycle<PostDetailPage, PostDetailModel> wit
                     child: _postWidget(post.quoteSubject),
                   ),
                 ),
+              if(post.quoteData != null)
+                GestureDetector(
+                  behavior: HitTestBehavior.opaque,
+                  onTap: () {
+                    Navigator.push(context, MaterialPageRoute(builder: (context) {
+                      return WebViewSharePage(json.decode(post.quoteData)["url"]["value"],hash:json.decode(post.quoteData)["hash"]["value"] ,);
+                    }));
+                  },
+                  child: Container(
+                    padding: EdgeInsets.all(11.0),
+                    margin: EdgeInsets.symmetric(vertical: 5.0),
+                    decoration: BoxDecoration(
+                        shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(10)), color: Theme.of(context).scaffoldBackgroundColor),
+                    child: _postLink(post.quoteData),
+                  ),
+                ),
               Space(
                 height: 10,
               ),
@@ -661,7 +710,7 @@ class _PageState extends ViewStateLifecycle<PostDetailPage, PostDetailModel> wit
                               children: <Widget>[
                                 InkWell(
                                   onTap: () {
-                                    NavigatorUtil.goPage(context, (context) => PostSharePage(_post));
+                                    NavigatorUtil.goPage(context, (context) => PostSharePage(post:_post));
                                   },
                                   child: Row(
                                     children: <Widget>[

+ 95 - 10
lib/pages/social/post_page.dart

@@ -2,15 +2,19 @@ import 'dart:io';
 import 'dart:math';
 
 import 'package:cached_network_image/cached_network_image.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:multi_image_picker/multi_image_picker.dart';
 import 'package:path_provider/path_provider.dart';
+import 'package:provider/provider.dart';
 import 'package:sport/bean/forum.dart';
 import 'package:sport/bean/image.dart' as photo;
 import 'package:sport/bean/post.dart';
+import 'package:sport/bean/user.dart';
 import 'package:sport/pages/social/gallery_photo_view.dart';
 import 'package:sport/pages/social/social_detail_page.dart';
+import 'package:sport/provider/user_model.dart';
 import 'package:sport/router/navigator_util.dart';
 import 'package:sport/services/api/inject_api.dart';
 import 'package:sport/utils/toast.dart';
@@ -20,12 +24,16 @@ import 'package:sport/widgets/dialog/alert_dialog.dart';
 import 'package:sport/widgets/dialog/bindphone_dialog.dart';
 import 'package:sport/widgets/space.dart';
 
+import 'chat_page.dart';
+
 class PostPage extends StatefulWidget {
   final String id;
   final Forum forum;
   final Post post;
-
-  const PostPage(this.id, {this.post, this.forum});
+  final String url;
+  final String hash;
+  final String image;
+  const PostPage(this.id, {this.post, this.forum,this.url,this.hash,this.image});
 
   @override
   State<StatefulWidget> createState() => _PageState();
@@ -42,6 +50,9 @@ class _PageState extends State<PostPage> {
     super.initState();
     _focusNode = FocusNode();
     _controller = TextEditingController()..addListener(() {});
+    //...
+    if(widget.post != null) _controller.text = "转发帖子";
+    _valueNotifier.value ="转发帖子";
   }
 
   @override
@@ -95,7 +106,7 @@ class _PageState extends State<PostPage> {
                     barrierDismissible: false,
                     builder: (context) => SimpleDialog(
                           children: <Widget>[
-                            PostAction(widget.id, postValue, imageList, widget.post?.quoteSubjectId == '0' ? widget.post?.id : widget.post?.quoteSubjectId)
+                            PostAction(widget.id, postValue, imageList, widget.post?.quoteSubjectId == '0' ? widget.post?.id : widget.post?.quoteSubjectId,widget.url,widget.hash,widget.image)
                           ],
                         ));
                 if (result == true) {
@@ -162,15 +173,14 @@ class _PageState extends State<PostPage> {
                       child: Text("$currentLength/$maxLength"),
                     ));
                   },
-                  decoration: InputDecoration(hintText: widget.post == null ? '发表你的看法...' : '分享文字...', border: InputBorder.none,
+                  decoration: InputDecoration(hintText: widget.post == null ?  '发表你的看法...' : "", border: InputBorder.none,
                   contentPadding: EdgeInsets.symmetric(horizontal: 6),
                   hintStyle: TextStyle(color: Color(0xff999999))),
                 ),
                 Space(
                   height: 16,
                 ),
-                widget.post == null
-                    ? GridView.builder(
+                widget.post == null? widget.url != null ? _postLink() : widget.image != null ? _postSharePoster(widget.image) :GridView.builder(
                         padding: EdgeInsets.zero,
                         shrinkWrap: true,
                         physics: NeverScrollableScrollPhysics(),
@@ -202,6 +212,8 @@ class _PageState extends State<PostPage> {
                             shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(10)), color: Theme.of(context).scaffoldBackgroundColor),
                         child: _postWidget(),
                       ),
+//                if(widget.url != null)
+//                  _postLink(),
               ],
             ),
           ),
@@ -296,6 +308,59 @@ class _PageState extends State<PostPage> {
                                 ],
                               ))))
                   .toList()),
+        if(post.quoteData != null)
+          _postLink(),
+
+      ],
+    );
+  }
+
+  Widget _postLink(){
+    return  Container(
+      padding: EdgeInsets.all(12.0),
+        color: Colors.white,
+      child: Row(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          mainAxisSize: MainAxisSize.max,
+          children: <Widget>[
+            CachedNetworkImage(
+              imageUrl: avatarList[4],
+              width: 60.0,
+              height: 60.0,
+            ),
+            Space(
+              width: 5.0,
+            ),
+            Expanded(
+              child: RichText(
+                maxLines: 3,
+                overflow: TextOverflow.ellipsis,
+                text: TextSpan(style: Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 16), children: <InlineSpan>[
+                  TextSpan(text: '${Provider.of<UserModel>(context).user.name}:', style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)),
+                  TextSpan(text: '分享了他的运动记录,快来围观吧~', style: Theme.of(context).textTheme.subtitle1),
+                ]),
+              ),
+            ),]),
+    );
+  }
+
+  Widget _postSharePoster(String image){
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: <Widget>[
+        Container(
+          constraints: BoxConstraints(
+            maxWidth: 100,
+            maxHeight: 200,
+          ),
+          child: ClipRRect(
+              borderRadius: BorderRadius.circular(6),
+              child:Image.asset(
+                image,
+                fit: BoxFit.cover,
+              )
+          ),
+        )
       ],
     );
   }
@@ -348,8 +413,11 @@ class PostAction extends StatefulWidget {
   final String content;
   final List<Asset> imageList;
   final String quoteSubjectId;
+  final String url;
+  final String hash;
+  final String image;
 
-  const PostAction(this.forumId, this.content, this.imageList, this.quoteSubjectId);
+  const PostAction(this.forumId, this.content, this.imageList, this.quoteSubjectId,this.url,this.hash,this.image);
 
   @override
   State<StatefulWidget> createState() => PostActionState();
@@ -378,7 +446,15 @@ class PostActionState extends State<PostAction> with InjectApi {
   }
 
   void post() async {
-    List<Asset> imageList = widget.imageList;
+    List<Asset> imageList = [];
+    if(widget.imageList?.isNotEmpty == true){
+      imageList.addAll(widget.imageList);
+    }
+
+    if(widget.image != null){
+      imageList.add(Asset(Uri.file(widget.image).toString() ,"", 0, 0));
+    }
+
     if (imageList != null && imageList.isNotEmpty) {
       Directory tempDir = await getTemporaryDirectory();
       Directory directory = new Directory('${tempDir.path}/upload');
@@ -408,8 +484,17 @@ class PostActionState extends State<PostAction> with InjectApi {
     _msg.value = "发布中...";
     // await Future.delayed(Duration(seconds: 3));
     if (_disposed) return;
-    var data =
-        await api.postForum(widget.forumId, widget.content, images: upload.values.map((e) => e.id).toList().join(","), quoteSubjectId: widget.quoteSubjectId);
+    var data;
+    // 这里我也没办法知道它之前的名字叫什么吧...
+    if(widget.url != null){
+      data =
+      await api.postForum(widget.forumId, widget.content, images: upload.values.map((e) => e.id).toList().join(","), quoteSubjectId: widget.quoteSubjectId,
+          quoteData: '{"username":{"value":"${Provider.of<UserModel>(context,listen: false).user.name}","from":"user#${Provider.of<UserModel>(context,listen: false).user.id}"},"url":{"value":"${widget.url}"},"hash":{"value":"${widget.hash}"}}');
+    }else{
+       data =
+      await api.postForum(widget.forumId, widget.content, images: upload.values.map((e) => e.id).toList().join(","), quoteSubjectId: widget.quoteSubjectId);
+    }
+
     if (data != null && data.code == 0) {
       Navigator.of(context).pop(true);
     } else {

+ 93 - 31
lib/pages/social/post_share_page.dart

@@ -1,10 +1,12 @@
 import 'package:cached_network_image/cached_network_image.dart';
 import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
 import 'package:sport/bean/forum.dart';
 import 'package:sport/bean/post.dart';
 import 'package:sport/bean/user_friend.dart';
 import 'package:sport/pages/social/chat_page.dart';
 import 'package:sport/pages/social/post_page.dart';
+import 'package:sport/provider/user_model.dart';
 import 'package:sport/router/navigator_util.dart';
 import 'package:sport/services/api/inject_api.dart';
 import 'package:sport/services/api/resp.dart';
@@ -15,10 +17,15 @@ import 'package:sport/widgets/image.dart';
 import 'package:sport/widgets/loading.dart';
 import 'package:sport/widgets/space.dart';
 
+// 简单判断吧 post 就是转发 帖子类型     link 就是 链接类型 ...
 class PostSharePage extends StatefulWidget {
   final Post post;
-
-  const PostSharePage(this.post);
+  // link 需要hash 和 url 要分开操作的是...
+  final String url;
+  final String hash;
+  // Img
+  final String image;
+  const PostSharePage({this.post,this.url,this.hash,this.image});
 
   @override
   State<StatefulWidget> createState() => _PageState();
@@ -76,6 +83,9 @@ class _PageState extends State<PostSharePage> with InjectApi {
                           list[index].forumId,
                           post: widget.post,
                           forum: list[index],
+                          url: widget.url,
+                          hash: widget.hash,
+                          image:widget.image,
                         ));
                 if (result == true) {
                   Navigator.of(context).pop(true);
@@ -93,9 +103,10 @@ class _PageState extends State<PostSharePage> with InjectApi {
 }
 
 class PostShareFriendsPage extends StatefulWidget {
-  final Post post;
-
-  const PostShareFriendsPage(this.post);
+  final Post post; // 应该是二选一...
+  final String hash; // 二选一 ...
+  final String image;
+  const PostShareFriendsPage({this.post, this.hash,this.image});
 
   @override
   State<StatefulWidget> createState() => _PostShareFriendsPageState();
@@ -173,7 +184,7 @@ class _PostShareFriendsPageState extends State<PostShareFriendsPage>
                             Space(
                               height: 8.0,
                             ),
-                            _buildPostWidget(context, widget.post)
+                            _buildPostWidget(context, widget.post, widget.hash,widget.image)
                           ],
                         ),
                         textOk: "分享",
@@ -183,9 +194,12 @@ class _PostShareFriendsPageState extends State<PostShareFriendsPage>
                               (context) => ChatPage(
                                     list[index].socialInfo,
                                     post: widget.post,
+                                    hash: widget.hash,
+                                  image:widget.image
                                   ));
                           if (result == true) {
                             Navigator.of(context).pop(true);
+                            Navigator.of(context).pop(true);
                           }
                         }));
               },
@@ -200,7 +214,78 @@ class _PostShareFriendsPageState extends State<PostShareFriendsPage>
   }
 }
 
-Widget _buildPostWidget(BuildContext context, Post post) {
+Widget _buildPostWidget(BuildContext context, Post post, String hash,String image) {
+  Widget imageWidget(String image) {
+    return ClipRRect(
+        child: CachedNetworkImage(
+          imageUrl: image,
+          fit: BoxFit.cover,
+          width: 50,
+          height: 50,
+        ),
+        // 也可控件一边圆角大小
+        borderRadius: new BorderRadius.all(Radius.circular(6.0)));
+  }
+
+  Widget contentWidget(String content) {
+    return Expanded(
+      child: Container(
+        margin: const EdgeInsets.all(5.0),
+        child: Text(content,
+            maxLines: 1,
+            overflow: TextOverflow.ellipsis,
+            style: Theme.of(context).textTheme.subtitle1),
+      ),
+    );
+  }
+
+  Widget contentMoreWidget(){
+    return Expanded(
+      child: Container(
+        margin: const EdgeInsets.all(5.0),
+        child:RichText(
+          text: TextSpan(
+            children: [
+              TextSpan(text: Provider.of<UserModel>(context, listen: false).user.name,style: Theme.of(context).textTheme.headline6.copyWith(color: Color(0xffffc400))),
+              TextSpan(text:"分享了他的运动记录,快来围观吧~",style: Theme.of(context).textTheme.subtitle1)
+            ]
+          ),
+        ),
+      ),
+    );
+  }
+
+  Widget sharePostWidget() {
+    if (post != null) {
+      return Row(
+        children: <Widget>[
+          if(post?.images != null && post.images.isNotEmpty)
+          imageWidget(post?.images[0].src),
+          contentWidget(post.content),
+        ],
+      );
+    } else if (hash != null) {
+      return Row(
+        children: <Widget>[
+          imageWidget(avatarList[4]),
+          contentMoreWidget(),
+        ],
+      );
+    } else if(image != null){
+      return Container(
+        constraints: BoxConstraints(
+          maxHeight: 300,
+          maxWidth: 200
+        ),
+        child: CachedNetworkImage(
+          imageUrl: image,
+        ),
+      );
+    }else {
+      return Container();
+    }
+  }
+
   return Container(
       margin: const EdgeInsets.symmetric(horizontal: 8.0),
       padding: const EdgeInsets.symmetric(vertical: 7.0, horizontal: 8.0),
@@ -208,28 +293,5 @@ Widget _buildPostWidget(BuildContext context, Post post) {
         color: Color(0xfff1f1f1), // 底色
         borderRadius: new BorderRadius.all(Radius.circular(10.0)),
       ),
-      child: Row(
-        children: <Widget>[
-          if (post.images != null && post.images.isNotEmpty)
-            ClipRRect(
-              child: CachedNetworkImage(
-                imageUrl: post.images[0].src,
-                fit: BoxFit.cover,
-                width: 50,
-                height: 50,
-              ),
-              // 也可控件一边圆角大小
-              borderRadius: new BorderRadius.all(Radius.circular(6.0)),
-            ),
-          Expanded(
-            child: Container(
-              margin: const EdgeInsets.all(5.0),
-              child: Text(post.content,
-                  maxLines: 1,
-                  overflow: TextOverflow.ellipsis,
-                  style: Theme.of(context).textTheme.subtitle1),
-            ),
-          )
-        ],
-      ));
+      child: sharePostWidget());
 }

+ 53 - 0
lib/pages/social/post_widget.dart

@@ -1,14 +1,17 @@
+import 'dart:convert';
 import 'dart:math';
 
 import 'package:cached_network_image/cached_network_image.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
+import 'package:provider/provider.dart';
 import 'package:sport/bean/post.dart';
 import 'package:sport/bean/post_user.dart';
 import 'package:sport/pages/social/gallery_photo_view.dart';
 import 'package:sport/pages/social/post_detail_page.dart';
 import 'package:sport/pages/social/post_share_page.dart';
+import 'package:sport/pages/social/share_webview.dart';
 import 'package:sport/provider/social_detail_model.dart';
 import 'package:sport/router/navigator_util.dart';
 import 'package:sport/services/api/inject_api.dart';
@@ -23,6 +26,8 @@ import 'package:sport/widgets/menu_share_bottom.dart';
 import 'package:sport/widgets/misc.dart';
 import 'package:sport/widgets/space.dart';
 
+import 'chat_page.dart';
+
 class PostWidget extends StatefulWidget {
   final SocialDetailModel model;
   final Post post;
@@ -97,6 +102,7 @@ class _PostWidgetState extends State<PostWidget> with InjectApi {
 
   Widget _postWidget(Post post) {
     double width = MediaQuery.of(context).size.width - 24 - 22;
+    if(post.quoteData != null) print("[post:]${post.toJson()}-------------------------");
     return Column(
       crossAxisAlignment: CrossAxisAlignment.start,
       children: <Widget>[
@@ -180,10 +186,42 @@ class _PostWidgetState extends State<PostWidget> with InjectApi {
                                 ],
                               ))))
                   .toList()),
+        if(post.quoteData != null)
+          _postLink(post.quoteData,color: Colors.white),
       ],
     );
   }
 
+  Widget _postLink(String quote,{Color color}){
+    var data = json.decode(quote);
+    return Container(
+      padding: EdgeInsets.all(8.0),
+        color:color !=null? color:Color(0xfff5f5f5),
+      child: Row(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          mainAxisSize: MainAxisSize.max,
+          children: <Widget>[
+            CachedNetworkImage(
+              imageUrl: avatarList[4],
+              width: 60.0,
+              height: 60.0,
+            ),
+            Space(
+              width: 5.0,
+            ),
+            Expanded(
+              child: RichText(
+                maxLines: 3,
+                overflow: TextOverflow.ellipsis,
+                text: TextSpan(style: Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 16), children: <InlineSpan>[
+                  TextSpan(text: '${data["username"]["value"]}:', style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)),
+                  TextSpan(text: '分享了他的运动记录,快来围观吧~', style: Theme.of(context).textTheme.subtitle1),
+                ]),
+              ),
+            ),]),
+    );
+  }
+
   _delete(SocialDetailModel model, Post post) {
     model.list.removeWhere((element) => element.id == post.id);
     setState(() {
@@ -498,6 +536,21 @@ class _PostWidgetState extends State<PostWidget> with InjectApi {
                       child: _postWidget(post.quoteSubject),
                     ),
                   ),
+                if(post.quoteData != null)
+                  GestureDetector(
+                    behavior: HitTestBehavior.opaque,
+                    onTap: () {
+                        var data = json.decode(post.quoteData);
+                        print("$data------------------------------");
+                      NavigatorUtil.goPage(context, (context) => WebViewSharePage(data['url']["value"],hash: data['hash']["value"],));
+                    },
+                    child: Container(
+                      padding: EdgeInsets.all(11.0),
+                      margin: EdgeInsets.symmetric(horizontal: 12.0, vertical: 5.0),
+                      decoration: BoxDecoration(shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(10)), color: Color(0xfff5f5f5)),
+                      child: _postLink(post.quoteData),
+                    ),
+                  ),
                 Space(
                   height: 10,
                 ),

+ 13 - 7
lib/pages/social/search_page.dart

@@ -17,6 +17,7 @@ import 'package:sport/router/navigator_util.dart';
 import 'package:sport/services/api/inject_api.dart';
 import 'package:sport/services/api/resp.dart';
 import 'package:sport/services/userid.dart';
+import 'package:sport/utils/click.dart';
 import 'package:sport/utils/toast.dart';
 import 'package:sport/widgets/appbar.dart';
 import 'package:sport/widgets/dialog/request_dialog.dart';
@@ -53,7 +54,7 @@ class _PageState extends State<SearchPage> with UserId, InjectApi {
       ..getHot();
     _searchModel = SocialDetailModel("0", 100);
     simpleModel = new SimpleModel((page) async {
-      var list = (await api.userSearch(kw: _model.searchValue, page: page))
+      var list = (await api.userSearch(kw: _controller.text, page: page))
           .pageResult
           .results;
       return list;
@@ -69,10 +70,11 @@ class _PageState extends State<SearchPage> with UserId, InjectApi {
   }
 
   _submitValue(String value) {
-    _controller.text = value;
-    _searchModel.setKeyword(value);
+//    _controller.text = value;
     _model.queryValue(value);
-    _focusNode?.unfocus();
+    _searchModel.setKeyword(value);
+    simpleModel.loadData();
+//    _focusNode?.unfocus();
   }
 
   @override
@@ -130,10 +132,14 @@ class _PageState extends State<SearchPage> with UserId, InjectApi {
                               vertical: 11.0, horizontal: 16.0),
                           border: InputBorder.none,
                           hintStyle: TextStyle(color: Color(0xff999999))),
-                      onChanged: (value) {
+                      onChanged: debounceValueChanged((value) {
+                        if(value != ""){
+                          _submitValue(value);
+                        }
+                        _model.queryValue(value);
                         Provider.of<SearchModel>(context, listen: false)
                             .updateSearchValue(value);
-                      },
+                      }),
                       onSubmitted: (value) {
                         _submitValue(value);
                         // _searchModel.setKeyword(value);
@@ -413,7 +419,7 @@ class _PageState extends State<SearchPage> with UserId, InjectApi {
                   autoDispose: false,
                   builder: (_, model, __) {
                     return EasyRefresh.custom(
-                      firstRefresh: true,
+//                      firstRefresh: true,
                       controller: model.refreshController,
                       enableControlFinishRefresh: true,
                       enableControlFinishLoad: true,

+ 18 - 8
lib/pages/social/share_achievement.dart

@@ -5,6 +5,7 @@ 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:sport/bean/user.dart';
 
 import 'package:sport/widgets/appbar.dart';
 import 'package:sport/widgets/menu_share_bottom.dart';
@@ -14,7 +15,8 @@ import 'chat_page.dart';
 
 class ShareAchievementPage extends StatelessWidget {
   final GlobalKey poster = new GlobalKey();
-
+  final Achievement achievement;
+  ShareAchievementPage(this.achievement);
   @override
   Widget build(BuildContext context) {
 //    print("${DateTime.now().millisecondsSinceEpoch}");
@@ -70,14 +72,14 @@ class ShareAchievementPage extends StatelessWidget {
                                 height: 5.0,
                               ),
                               Text(
-                                "您是第100位获得者",
+                                "您是第${achievement.userCount}位获得者",
                                 style: Theme.of(context).textTheme.bodyText1,
                               ),
                               Space(
                                 height: 16.0,
                               ),
                               CachedNetworkImage(
-                                imageUrl: avatarList[Random().nextInt(10) % 11],
+                                imageUrl: achievement.logo,
                                 width: 120.0,
                                 height: 120.0,
                               ),
@@ -85,14 +87,14 @@ class ShareAchievementPage extends StatelessWidget {
                                 height: 8.0,
                               ),
                               Text(
-                                "燃脂达人Ⅱ",
+                                "${achievement.name}",
                                 style: Theme.of(context).textTheme.headline1,
                               ),
                               Space(
                                 height: 16.0,
                               ),
                               Text(
-                                "使用智能鞋运动消耗1000kal",
+                                "使用智能鞋运动${achievement.conditionDetail}",
                                 style: Theme.of(context).textTheme.bodyText1,
                               ),
                               Space(
@@ -101,10 +103,18 @@ class ShareAchievementPage extends StatelessWidget {
                               Container(
                                 height: 25.0,
                                 width: MediaQuery.of(context).size.width * 0.6,
-                                color: Color(0xffFFC400).withOpacity(0.3),
+//                                color: Color(0xffFFC400).withOpacity(0.3),
                                 alignment: Alignment.center,
+                                decoration: BoxDecoration(
+                                  gradient: new RadialGradient(
+                                      radius: 4,
+                                      colors: [
+                                        Color.fromRGBO(255, 196, 0, 1).withAlpha(80),
+                                        Color(0x00ffffff),
+                                      ]),
+                                ),
                                 child: Text(
-                                  "经验值+5  积分+1",
+                                  "经验值+${achievement.rewardExp}  积分+${achievement.rewardScore}",
                                   style: Theme.of(context)
                                       .textTheme
                                       .subtitle2
@@ -125,7 +135,7 @@ class ShareAchievementPage extends StatelessWidget {
                                     ),
                                   ),
                                   Text(
-                                    "2020.07.14",
+                                    "${achievement.createdAt}",
                                     style:
                                         Theme.of(context).textTheme.bodyText1,
                                   ),

+ 46 - 42
lib/pages/social/share_webview.dart

@@ -6,12 +6,14 @@
 
 import 'dart:async';
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'package:sport/widgets/menu_share_bottom.dart';
 import 'package:webview_flutter/webview_flutter.dart';
 
 class WebViewSharePage extends StatefulWidget {
   final String url;
-  WebViewSharePage(this.url);
+  final String hash;
+  WebViewSharePage(this.url, {this.hash});
   @override
   _WebViewSharePageState createState() => _WebViewSharePageState();
 }
@@ -22,18 +24,20 @@ class _WebViewSharePageState extends State<WebViewSharePage> {
 
   @override
   Widget build(BuildContext context) {
-    return Scaffold(
-        // We're using a Builder here so we have a context that is below the Scaffold
-        // to allow calling Scaffold.of(context) so we can show a snackbar.
-        body: SafeArea(
-      child: Stack(
-        children: <Widget>[
-          Container(
-            child: SingleChildScrollView(
-              child: Container(
+    return AnnotatedRegion<SystemUiOverlayStyle>(
+        value: SystemUiOverlayStyle.dark,
+        child: Scaffold(
+            backgroundColor: Color(0xff241d19),
+            // We're using a Builder here so we have a context that is below the Scaffold
+            // to allow calling Scaffold.of(context) so we can show a snackbar.
+            body: SafeArea(
+          child: Stack(
+            children: <Widget>[
+              Container(
                 height: MediaQuery.of(context).size.height * 1,
                 child: WebView(
-                  initialUrl: 'https://www.baidu.com',
+                  initialUrl:
+                      'http://shoes-web.hiyd.com/share?h=${widget.hash}',
                   javascriptMode: JavascriptMode.unrestricted,
                   onWebViewCreated: (WebViewController webViewController) {
                     _controller.complete(webViewController);
@@ -51,42 +55,42 @@ class _WebViewSharePageState extends State<WebViewSharePage> {
                   gestureNavigationEnabled: true,
                 ),
               ),
-              // 要不要取消回弹...
-//              physics: new ClampingScrollPhysics(),
-            ),
-          ),
-          Positioned(
-            left: 12.0,
-            top: 11.0,
-            child: Container(
-              child: InkWell(
-                child: Image.asset("lib/assets/img/topbar_return_white.png"),
-                onTap: () {
-                  Navigator.pop(context);
-                },
-              ),
+              Positioned(
+                left: 12.0,
+                top: 11.0,
+                child: Container(
+                  child: InkWell(
+                    child:
+                        Image.asset("lib/assets/img/topbar_return_white.png"),
+                    onTap: () {
+                      Navigator.pop(context);
+                    },
+                  ),
 //                color: Colors.red,
-            ),
-          ),
-          Positioned(
-            right: 12.0,
-            top: 11.0,
-            child: Container(
-              child: InkWell(
-                child: Image.asset("lib/assets/img/bbs_icon_share_white.png"),
-                onTap: () {
-                  menuShareBottom(context, "Link",
-                      url: "http://106.52.104.134:4000/", hasDownload: false);
-                },
+                ),
               ),
+              Positioned(
+                right: 12.0,
+                top: 11.0,
+                child: Container(
+                  child: InkWell(
+                    child:
+                        Image.asset("lib/assets/img/bbs_icon_share_white.png"),
+                    onTap: () {
+                      menuShareBottom(context, "Link",
+                          url: "http://shoes-web.hiyd.com/share",
+                          hasDownload: false,
+                          hash: widget.hash);
+                    },
+                  ),
 //                color: Colors.red,
-            ),
+                ),
+              ),
+            ],
           ),
-        ],
-      ),
-    )
+        )
 //      floatingActionButton: favoriteButton(),
-        );
+            ));
   }
 
   JavascriptChannel _toasterJavascriptChannel(BuildContext context) {

+ 4 - 4
lib/pages/social/user_friend_add_page.dart

@@ -207,12 +207,12 @@ class _PageState extends ViewStateLifecycle<UserFriendAddPage, SimpleModel>
                     child: RequestLoadingWidget(),
                   ),
                 if (model.isEmpty || model.isError)
-                  SliverToBoxAdapter(
-                    child: RequestErrorWidget(
+                  _searchValue.value != "" ? SliverToBoxAdapter(
+                  child: RequestErrorWidget(
                       null,
-                      msg: _searchValue.value == "" ? "请输入搜索的关键字" : "暂无相关用户~",
+                      msg:  "暂无相关用户~",
                     ),
-                  ),
+                  ):SliverToBoxAdapter(),
                 if (model.isIdle)
                   SliverList(
                     delegate: SliverChildBuilderDelegate(

+ 3 - 1
lib/pages/social/user_friend_page.dart

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart' hide NestedScrollView;
 import 'package:flutter_easyrefresh/easy_refresh.dart';
 import 'package:sport/bean/post_user.dart';
 import 'package:sport/bean/user_friend.dart';
+import 'package:sport/pages/social/chat_page.dart';
 import 'package:sport/pages/social/user_detail_page.dart';
 import 'package:sport/pages/social/user_friend_add_page.dart';
 import 'package:sport/provider/lib/provider_widget.dart';
@@ -440,7 +441,8 @@ class _PageDetailState extends ViewStateLifecycle<_PageDetailPage, UserFriendMod
           padding: const EdgeInsets.all(12.0),
           child: InkWell(
               onTap: () async {
-                await NavigatorUtil.goPage(
+                if(widget.type == 0)  await NavigatorUtil.goPage(context, (context) => ChatPage(user?.socialInfo));
+                else await NavigatorUtil.goPage(
                     context,
                     (context) => UserDetailPage(PostUser(id: "${user?.socialInfo?.id}", name: user?.socialInfo?.name, avatar: user?.socialInfo?.avatar),
                         userFriends: model.list));

+ 15 - 2
lib/provider/message_model.dart

@@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
 import 'package:sport/bean/message.dart';
 import 'package:sport/db/message_db.dart';
 import 'package:sport/services/api/inject_api.dart';
+import 'package:sport/utils/print_map.dart';
 
 class MessageModel extends ChangeNotifier with InjectApi {
 //  Message _message;
@@ -33,10 +34,12 @@ class MessageModel extends ChangeNotifier with InjectApi {
       // curId 这里一定是接口返回的 本地存 sqlite的 curId 全部都是 0
       _curId = data.curId;
       _messages = data.messages;
-//
-//      await MessageDB().deleteMessage(15);
+
 //      var list = await MessageDB().findAll(); // 清空数字
 //      print("[list]:$list--------------------------");
+
+      var userList = await MessageDB().findAllUser();
+      print("[list]:$userList--------------------------");
 //      MessageDB().deleteTable(); //
       // 这里本来是做了去重操作的 现在不用了 ...
 //      if (_messages.length > 0) {
@@ -66,8 +69,18 @@ class MessageModel extends ChangeNotifier with InjectApi {
           curId: curId,
           status: 1,
           userId: _instance.fromUser.id));
+      var list = await MessageDB().findHasUserId(_instance.fromUser.id);
+//      print("[user:]$list-------------------------------");
+//
+//      printWell("list", list);
+
+      if (list.length == 0) {
+        await MessageDB().insertUser(
+            new UserTableInfo(userId: _instance.fromUser.id, isTop: 0));
+      }
     }
     await MessageDB().insertAll(_items);
+
     // 这里就是 广播?
     get(messages);
 //    print("[items]:$_items----------------------------------------------");

+ 8 - 1
lib/provider/sport_index_model.dart

@@ -1,6 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 import 'package:sport/bean/sport_index.dart';
+import 'package:sport/bean/user.dart';
 import 'package:sport/provider/lib/view_state_refresh_list_model.dart';
 import 'package:sport/provider/user_model.dart';
 import 'package:sport/services/api/inject_api.dart';
@@ -10,9 +11,11 @@ class SportIndexModel extends ViewStateRefreshListModel with InjectApi {
   SportIndex data;
   int gameId;
   int provinceId, cityId, districtId;
-
   BuildContext context;
 
+
+  ValueNotifier< List<Achievement>> valueNotifier = ValueNotifier([]);
+
   SportIndexModel(this.context);
 
   @override
@@ -21,6 +24,10 @@ class SportIndexModel extends ViewStateRefreshListModel with InjectApi {
     if (data != null) {
       gameId = data.games?.first?.id;
       Provider.of<UserModel>(context, listen: false).durationTarget.value = data.durationTarget;
+//      achievementList.add(data.achievement);
+      if(data.achievement != null){
+        valueNotifier.value = data.achievement;
+      }
       return [data];
     } else {
       return [];

+ 5 - 0
lib/services/Converter.dart

@@ -10,6 +10,7 @@ import 'package:sport/bean/post.dart';
 import 'package:sport/bean/post_user.dart';
 import 'package:sport/bean/rank_game_info.dart';
 import 'package:sport/bean/rank_info.dart';
+import 'package:sport/bean/share_info.dart';
 import 'package:sport/bean/sport_detail.dart';
 import 'package:sport/bean/sport_index.dart';
 import 'package:sport/bean/sport_step.dart';
@@ -79,6 +80,10 @@ class Converter {
         return MessageUser.fromJson(json) as T;
       case "MessagePostUser":
         return MessagePostUser.fromJson(json) as T;
+      case "ShareInfo":
+        return ShareInfo.fromJson(json) as T;
+      case "Share":
+        return Share.fromJson(json) as T;
     }
     return json as T;
   }

+ 11 - 2
lib/services/api/rest_client.dart

@@ -13,6 +13,7 @@ import 'package:sport/bean/notice.dart';
 import 'package:sport/bean/post.dart';
 import 'package:sport/bean/rank_game_info.dart';
 import 'package:sport/bean/rank_info.dart';
+import 'package:sport/bean/share_info.dart';
 import 'package:sport/bean/sport_detail.dart';
 import 'package:sport/bean/sport_index.dart';
 import 'package:sport/bean/sport_step.dart';
@@ -152,7 +153,7 @@ abstract class RestClient {
   Future<RespData<String>> postDelComment(@Query("commentId") String commentId);
 
   @POST("/forum/report")
-  Future<RespData<String>> postForumReport({@Query("subjectId") String subjectId, @Query("commentId") String commentId, @Query("content") String content});
+  Future<RespData<String>> postForumReport({@Query("subjectId") String subjectId, @Query("commentId") String commentId, @Query("content") String content,@Query("userId") int userId});
 
   @POST("/forum/blockUser")
   Future<RespList<int>> postForumBlockUser(@Query("uid") String uid);
@@ -175,6 +176,7 @@ abstract class RestClient {
       {@Query("images") String images,
       @Query("quoteSubjectId") String quoteSubjectId,
       @Query("quoteCommentId") String quoteCommentId,
+        @Query("quoteData") String quoteData,
       CancelToken cancelToken});
 
   @POST("/forum/setUserTopSubjects")
@@ -249,12 +251,19 @@ abstract class RestClient {
   @Headers(<String, dynamic>{
     "content-type": "multipart/form-data",
   })
-  Future<RespData<String>> postChatUpload(@Part(name: "media") File file,);
+  Future<RespData> postChatUpload(@Part(name: "file") File file,);
 
   @POST("/chat/info")
   Future<RespList<ChatOnlineInfo>> getChatUserInfo(@Query("user_ids")  List<int> userIds,);
 
+  // ********************** 分享相关 *****************************
 
+  @POST("/share/createSport")
+  Future<RespData<ShareInfo>> getshareCreateSport(@Query("period")  String period,@Query("weight")  double weight);
+
+
+  @POST("/share/forwardSport")
+  Future<RespData<MessageInstance>> getshareForwardSport(@Query("h")  String hash,@Query("user_id")  int userId);
   // ********************** 公告相关 *****************************
   @GET("/inform/list")
   Future<RespPage<Notice>> getInformList({@Query("p") int page});

+ 51 - 6
lib/services/api/rest_client.g.dart

@@ -781,12 +781,13 @@ class _RestClient implements RestClient {
   }
 
   @override
-  postForumReport({subjectId, commentId, content}) async {
+  postForumReport({subjectId, commentId, content, userId}) async {
     const _extra = <String, dynamic>{};
     final queryParameters = <String, dynamic>{
       r'subjectId': subjectId,
       r'commentId': commentId,
-      r'content': content
+      r'content': content,
+      r'userId': userId
     };
     queryParameters.removeWhere((k, v) => v == null);
     final _data = <String, dynamic>{};
@@ -910,7 +911,7 @@ class _RestClient implements RestClient {
 
   @override
   postForum(forumId, content,
-      {images, quoteSubjectId, quoteCommentId, cancelToken}) async {
+      {images, quoteSubjectId, quoteCommentId, quoteData, cancelToken}) async {
     ArgumentError.checkNotNull(forumId, 'forumId');
     ArgumentError.checkNotNull(content, 'content');
     const _extra = <String, dynamic>{};
@@ -919,7 +920,8 @@ class _RestClient implements RestClient {
       r'content': content,
       r'images': images,
       r'quoteSubjectId': quoteSubjectId,
-      r'quoteCommentId': quoteCommentId
+      r'quoteCommentId': quoteCommentId,
+      r'quoteData': quoteData
     };
     queryParameters.removeWhere((k, v) => v == null);
     final _data = <String, dynamic>{};
@@ -1386,7 +1388,7 @@ class _RestClient implements RestClient {
     final queryParameters = <String, dynamic>{};
     final _data = FormData();
     _data.files.add(MapEntry(
-        'media',
+        'file',
         MultipartFile.fromFileSync(file.path,
             filename: file.path.split(Platform.pathSeparator).last)));
     final Response<Map<String, dynamic>> _result = await _dio.request(
@@ -1399,7 +1401,7 @@ class _RestClient implements RestClient {
             contentType: 'multipart/form-data',
             baseUrl: baseUrl),
         data: _data);
-    final value = RespData<String>.fromJson(_result.data);
+    final value = RespData<dynamic>.fromJson(_result.data);
     return value;
   }
 
@@ -1423,6 +1425,49 @@ class _RestClient implements RestClient {
   }
 
   @override
+  getshareCreateSport(period, weight) async {
+    ArgumentError.checkNotNull(period, 'period');
+    ArgumentError.checkNotNull(weight, 'weight');
+    const _extra = <String, dynamic>{};
+    final queryParameters = <String, dynamic>{
+      r'period': period,
+      r'weight': weight
+    };
+    final _data = <String, dynamic>{};
+    final Response<Map<String, dynamic>> _result = await _dio.request(
+        '/share/createSport',
+        queryParameters: queryParameters,
+        options: RequestOptions(
+            method: 'POST',
+            headers: <String, dynamic>{},
+            extra: _extra,
+            baseUrl: baseUrl),
+        data: _data);
+    final value = RespData<ShareInfo>.fromJson(_result.data);
+    return value;
+  }
+
+  @override
+  getshareForwardSport(hash, userId) async {
+    ArgumentError.checkNotNull(hash, 'hash');
+    ArgumentError.checkNotNull(userId, 'userId');
+    const _extra = <String, dynamic>{};
+    final queryParameters = <String, dynamic>{r'h': hash, r'user_id': userId};
+    final _data = <String, dynamic>{};
+    final Response<Map<String, dynamic>> _result = await _dio.request(
+        '/share/forwardSport',
+        queryParameters: queryParameters,
+        options: RequestOptions(
+            method: 'POST',
+            headers: <String, dynamic>{},
+            extra: _extra,
+            baseUrl: baseUrl),
+        data: _data);
+    final value = RespData<MessageInstance>.fromJson(_result.data);
+    return value;
+  }
+
+  @override
   getInformList({page}) async {
     const _extra = <String, dynamic>{};
     final queryParameters = <String, dynamic>{r'p': page};

+ 4 - 0
lib/sharesdk/tencent.dart

@@ -56,6 +56,10 @@ mixin TencentMixin<T extends StatefulWidget> on State<T> {
     );
   }
 
+  void qqShareLink(String url) async{
+    await _tencent.shareWebpage(scene: TencentScene.SCENE_QQ, title: "分享页面" ,targetUrl: url);
+  }
+
   void _listenLogin(TencentLoginResp resp) async {
     _loginResp = resp;
     if (_loginResp != null &&

+ 21 - 3
lib/sharesdk/wechat.dart

@@ -86,18 +86,36 @@ mixin WechatMixin<T extends StatefulWidget> on State<T> {
 //    await _wechat.shareImage(scene: WechatScene.SESSION, imageData: File(path).readAsBytesSync());
 //  }
 
-  void wechatShareImage(String path,String type) async {
-    if(type == "chat"){
+  void wechatShareImage(String path, String type) async {
+    if (type == "chat") {
       // 这是 聊天
       await _wechat.shareImage(
           scene: WechatScene.SESSION, imageData: File(path).readAsBytesSync());
-    }else if(type == "friend"){
+    } else if (type == "friend") {
       // 这是朋友圈
       await _wechat.shareImage(
           scene: WechatScene.TIMELINE, imageData: File(path).readAsBytesSync());
     }
   }
 
+  void wechatShareLink(String url, String type, String username) async {
+    if (type == "chat") {
+      _wechat.shareWebpage(
+          scene: WechatScene.SESSION,
+          webpageUrl: url,
+          title: "$username分享了他的运动记录,快来围观吧~",
+          description: "$username分享了他的运动记录,快来围观吧~"
+      );
+    } else if (type == "friend") {
+      _wechat.shareWebpage(
+          scene: WechatScene.TIMELINE,
+          webpageUrl: url,
+          title: "$username分享了他的运动记录,快来围观吧~",
+          description: "$username分享了他的运动记录,快来围观吧~"
+      );
+    }
+  }
+
   void dispose() {
     _auth?.cancel();
     _auth = null;

+ 30 - 11
lib/widgets/button_primary.dart

@@ -10,6 +10,7 @@ class PrimaryButton extends StatelessWidget {
   final Widget child;
   final bool shadow;
   final bool bold;
+  final Color buttonColor;
 
   PrimaryButton({
     @required this.callback,
@@ -20,6 +21,7 @@ class PrimaryButton extends StatelessWidget {
     this.fontSize = 28,
     this.shadow = true,
     this.bold = false,
+    this.buttonColor,
   });
 
   @override
@@ -41,27 +43,44 @@ class PrimaryButton extends StatelessWidget {
                 ? BoxDecoration(
                     shape: BoxShape.rectangle,
                     borderRadius: BorderRadius.all(Radius.circular(height / 2)),
-                    boxShadow: [BoxShadow(offset: Offset(0.0, 3), blurRadius: 3, spreadRadius: 0, color: Color(0x82FF9100))],
+                    boxShadow: [
+                      BoxShadow(
+                          offset: Offset(0.0, 3),
+                          blurRadius: 3,
+                          spreadRadius: 0,
+                          color: Color(0x82FF9100))
+                    ],
                     gradient: LinearGradient(
                       begin: Alignment.topCenter,
                       end: Alignment.bottomCenter,
                       colors: <Color>[Color(0xffFFC400), Color(0xffFFAA00)],
                     ),
                   )
-                : BoxDecoration(
-                    shape: BoxShape.rectangle,
-                    borderRadius: BorderRadius.all(Radius.circular(height / 2)),
-                    gradient: LinearGradient(
-                      begin: Alignment.topCenter,
-                      end: Alignment.bottomCenter,
-                      colors: <Color>[Color(0xffFFC400), Color(0xffFFAA00)],
-                    ),
-                  ),
+                : buttonColor != null
+                    ? BoxDecoration(
+                        color: buttonColor,
+                        shape: BoxShape.rectangle,
+                        borderRadius:
+                            BorderRadius.all(Radius.circular(height / 2)),
+                      )
+                    : BoxDecoration(
+                        shape: BoxShape.rectangle,
+                        borderRadius:
+                            BorderRadius.all(Radius.circular(height / 2)),
+                        gradient: LinearGradient(
+                          begin: Alignment.topCenter,
+                          end: Alignment.bottomCenter,
+                          colors: <Color>[Color(0xffFFC400), Color(0xffFFAA00)],
+                        ),
+                      ),
         child: content?.isNotEmpty == true
             ? Text(
                 content,
                 style: TextStyle(
-                    color: Colors.white, fontSize: height > 40 ? callback == null ? 14.0 : 16.0 : 14.0, fontWeight: bold ? FontWeight.w600 : FontWeight.normal),
+                    color: Colors.white,
+                    fontSize:
+                        height > 40 ? callback == null ? 14.0 : 16.0 : 14.0,
+                    fontWeight: bold ? FontWeight.w600 : FontWeight.normal),
                 strutStyle: fixedLine,
               )
             : child,

+ 3 - 1
lib/widgets/dialog/request_dialog.dart

@@ -39,7 +39,9 @@ Future request(BuildContext context, ApiCall api) async {
                   ],
                 )),
           )));
-  var data = await api.call().catchError((onError) {});
+  var data = await api.call().catchError((onError) {
+    print("[onError]:$onError");
+  });
   if (!pop) Navigator.of(context).pop();
   return data;
 }

+ 33 - 22
lib/widgets/dialog/share_popup.dart

@@ -3,6 +3,7 @@ import 'dart:math';
 import 'package:cached_network_image/cached_network_image.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
+import 'package:sport/bean/user.dart';
 import 'package:sport/pages/social/chat_page.dart';
 import 'package:sport/pages/social/share_achievement.dart';
 import 'package:sport/router/navigator_util.dart';
@@ -46,6 +47,8 @@ import '../space.dart';
 
 // 换成这种 自定义PopRoute
 class sharePopup extends StatefulWidget {
+  List<Achievement> list;
+  sharePopup(this.list);
   @override
   State<StatefulWidget> createState() {
     // TODO: implement createState
@@ -54,9 +57,8 @@ class sharePopup extends StatefulWidget {
 }
 
 class _sharePopupState extends State<sharePopup> {
-  List<int> data = [0, 1, 2, 3];
   bool showCloseButton = true;
-  Widget content(int e) {
+  Widget content(Achievement e) {
     return Container(
 //      width: MediaQuery.of(context).size.width * 1,
       child: Column(
@@ -84,14 +86,14 @@ class _sharePopupState extends State<sharePopup> {
                   height: 5.0,
                 ),
                 Text(
-                  "您是第$e位获得者",
+                  "您是第${e.userCount}位获得者",
                   style: Theme.of(context).textTheme.bodyText1,
                 ),
                 Space(
                   height: 16.0,
                 ),
                 CachedNetworkImage(
-                  imageUrl: avatarList[Random().nextInt(10) % 11],
+                  imageUrl: e.logo,
                   width: 120.0,
                   height: 120.0,
                 ),
@@ -99,14 +101,14 @@ class _sharePopupState extends State<sharePopup> {
                   height: 8.0,
                 ),
                 Text(
-                  "燃脂达人Ⅱ",
+                  "${e.name}",
                   style: Theme.of(context).textTheme.headline1,
                 ),
                 Space(
                   height: 16.0,
                 ),
                 Text(
-                  "使用智能鞋运动消耗1000kal",
+                  "${e.conditionDetail}",
                   style: Theme.of(context).textTheme.bodyText1,
                 ),
                 Space(
@@ -115,10 +117,18 @@ class _sharePopupState extends State<sharePopup> {
                 Container(
                   height: 25.0,
                   width: MediaQuery.of(context).size.width * 0.6,
-                  color: Color(0xffFFC400).withOpacity(0.3),
+//                  color: Color(0xffFFC400).withOpacity(0.3),
                   alignment: Alignment.center,
+                  decoration: BoxDecoration(
+                    gradient: new RadialGradient(
+                      radius: 4,
+                        colors: [
+                          Color.fromRGBO(255, 196, 0, 1).withAlpha(80),
+                          Color(0x00ffffff),
+                        ]),
+                  ),
                   child: Text(
-                    "经验值+5  积分+1",
+                    "经验值+${e.rewardExp}  积分+${e.rewardScore}",
                     style: Theme.of(context)
                         .textTheme
                         .subtitle2
@@ -137,8 +147,8 @@ class _sharePopupState extends State<sharePopup> {
                     border: new Border.all(
                         width: 1, color: Theme.of(context).accentColor),
                     gradient: new LinearGradient(
-                        begin: Alignment.topCenter,
-                        end: Alignment.bottomCenter,
+                        begin: Alignment.centerLeft,
+                        end: Alignment.centerRight,
                         colors: [
                           Color.fromRGBO(255, 196, 0, 1),
                           Color.fromRGBO(255, 170, 0, 1),
@@ -150,15 +160,16 @@ class _sharePopupState extends State<sharePopup> {
                       style: Theme.of(context).textTheme.headline6,
                     ),
                     onTap: () {
-                      if (data.length != 1) {
+                      if (widget.list.length != 1) {
                         setState(() {
-                          data = data.sublist(0, data.length - 1);
+                          widget.list =
+                              widget.list.sublist(0, widget.list.length - 1);
                         });
                       } else {
                         Navigator.pop(context);
                       }
                       NavigatorUtil.goPage(
-                          context, (context) => ShareAchievementPage());
+                          context, (context) => ShareAchievementPage(e));
                     },
                   ),
                 ),
@@ -175,7 +186,7 @@ class _sharePopupState extends State<sharePopup> {
                       ),
                     ),
                     Text(
-                      "2020.07.14",
+                      "${e.createdAt}",
                       style: Theme.of(context).textTheme.bodyText1,
                     ),
                     Expanded(
@@ -192,14 +203,14 @@ class _sharePopupState extends State<sharePopup> {
           ),
           Padding(
             padding: EdgeInsets.only(top: 20.0),
-            child: data.length > 0 && 0 == data.indexOf(e)
+            child: widget.list.length > 0 && 0 == widget.list.indexOf(e)
                 ? InkWell(
                     child: Image.asset("lib/assets/img/pop_share_chose.png"),
                     onTap: () {
-                      if (data.length != 1) {
-                        data.removeAt(0);
+                      if (widget.list.length != 1) {
+                        widget.list.removeAt(0);
                         setState(() {
-                          data = data;
+                          widget.list = widget.list;
                         });
                       } else {
                         Navigator.of(context).pop();
@@ -218,7 +229,7 @@ class _sharePopupState extends State<sharePopup> {
 
   @override
   Widget build(BuildContext context) {
-    print(data);
+    print(widget.list);
     // TODO: implement build
     return Material(
       color: Colors.black.withOpacity(0.5),
@@ -229,10 +240,10 @@ class _sharePopupState extends State<sharePopup> {
             child: Center(
               // stack 需要一个高度进行搞一搞
               child: Stack(
-                children: data.reversed.map((e) {
+                children: widget.list.reversed.map((e) {
                   return Transform.translate(
-                      offset: Offset((data.indexOf(e) + 1) * 5.0,
-                          -(data.indexOf(e)) * 5.0),
+                      offset: Offset((widget.list.indexOf(e) + 1) * 5.0,
+                          -(widget.list.indexOf(e)) * 5.0),
 //                      padding: EdgeInsets.only(
 //                          right: (data.indexOf(e)) * 10.0,
 //                          top: (data.indexOf(e)) * 10.0),

+ 118 - 76
lib/widgets/menu_bar.dart

@@ -5,13 +5,16 @@ import 'dart:math';
 
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter/scheduler.dart';
 import 'package:flutter/services.dart';
 import 'package:image_picker/image_picker.dart';
 import 'package:multi_image_picker/multi_image_picker.dart';
+import 'package:path_provider/path_provider.dart';
 import 'package:sport/bean/message.dart';
 import 'package:sport/db/message_db.dart';
 import 'package:sport/pages/social/chat_page.dart';
 import 'package:sport/services/api/inject_api.dart';
+import 'package:sport/utils/toast.dart';
 import 'package:sport/widgets/button_primary.dart';
 import 'package:sport/widgets/decoration.dart';
 
@@ -67,22 +70,25 @@ class _MenuBarState extends State<MenuBar>
 
   Timer _timer;
 
+  @override
+  void didUpdateWidget(MenuBar oldWidget) {
+    super.didUpdateWidget(oldWidget);
+    widget.scrollToBottom();
+  }
+
   void initState() {
     super.initState();
 
     initEmoji();
 
     _controller = TextEditingController();
-
 //    _focusNode.addListener(() {
 //      if (_focusNode.hasFocus) {
-//        widget.scrollToBottom(keyBoardHeight: keyBoardHeight);
-//        setState(() {
-//          isShowMenuBottomIndex = 1;
-//        });
+////        setState(() {
+////          isShowExtMenu = false;
+////        });
 //      }
 //    });
-//    WidgetsBinding.instance.addObserver(this);
   }
 
   // 直接进来就请求了 不要 搞这些骚的....
@@ -103,21 +109,21 @@ class _MenuBarState extends State<MenuBar>
     _timer?.cancel();
   }
 
-  @override
-//  void didChangeMetrics() {
-//    super.didChangeMetrics();
-//    WidgetsBinding.instance.addPostFrameCallback((_) {
-//      // 当前是安卓系统并且在焦点聚焦的情况下
-////      if (Platform.isAndroid && _focusNode.hasFocus) {
-////        widget.scrollToBottom(context, widget.globalkey, false);
-////      }
-//    });
-//  }
-
+  // 这里 插库 + 渲染更新...
   Future add(MessageInstance message) async {
     // 聊天的时候 是没有返回 curId的 本地存储的时候 就得自己构造一个? 或者是不存?
     await MessageDB().insert(new MessageItem(
         message: message, status: 0, userId: message.toUser.id, curId: 0));
+
+    var list = await MessageDB().findHasUserId(message.toUser.id);
+
+    if (list.length == 0) {
+      await MessageDB()
+          .insertUser(new UserTableInfo(userId: message.toUser.id, isTop: 0));
+    }
+
+    // view 上setstate 渲染的...
+    widget.sendCallBack(message); // 添加完 在 callBack...
   }
 
   Widget extMenuItem(
@@ -144,6 +150,38 @@ class _MenuBarState extends State<MenuBar>
               selectionTextColor: "#ffffff",
               selectionCharacter: "✓",
             ));
+        List<String> urls = [];
+        if (resultList != null) {
+          Directory tempDir = await getTemporaryDirectory();
+          Directory directory = new Directory('${tempDir.path}/upload');
+          if (!directory.existsSync()) {
+            directory.createSync();
+            print('文档初始化成功,文件保存路径为 ${directory.path}');
+          }
+
+          for (var i = 0; i < resultList.length; i++) {
+            Asset asset = resultList[i];
+            ByteData byteData = await asset.getByteData(quality: 85);
+            File file = File(
+                '${directory.path}/${DateTime.now().millisecondsSinceEpoch}_$i.jpg');
+            List<int> bytes = byteData.buffer.asUint8List().toList();
+            print('临时文件 ${file.path} ${bytes.length}');
+            file.writeAsBytesSync(bytes);
+            String url = (await api.postChatUpload(file)).data["url"];
+            urls.add(url);
+            file.delete();
+          }
+        }
+        if (urls.length > 0) {
+          for (int i = 0; i < urls.length; i++) {
+            MessageInstance message = (await api.postChatSend(
+                    widget.menuIdentity.userId,
+                    "image",
+                    '{"url":"${urls[i]}"}'))
+                .data;
+            add(message);
+          }
+        }
       } on Exception catch (e) {
         error = e.toString();
       }
@@ -163,7 +201,6 @@ class _MenuBarState extends State<MenuBar>
                   "image",
                   '{ "data":{ "url":"$url" }}'))
               .data;
-//          print("$message -------------------------------");
           add(message);
         }
       } on Exception catch (e) {
@@ -288,25 +325,31 @@ class _MenuBarState extends State<MenuBar>
 
     return Column(
       children: <Widget>[
-//        GestureDetector(
-//          onTap: () {
-//            setState(() {
-//              isShowMenuBottomIndex = 0;
-//            });
-//            _focusNode.unfocus();
-//          },
-//          // 列表在这里...
-//          child: ,
-//        ),
         Expanded(
-          child: widget.messageList,
+          child: Column(
+            children: <Widget>[
+              Flexible(
+                  child: GestureDetector(
+                    onTap: () {
+                      setState(() {
+                        isShowMenuBottomIndex = 0;
+                      });
+                      _focusNode.unfocus();
+                    },
+                    child: widget.messageList,
+                  )),
+            ],
+          ),
         ),
+//        Expanded(
+//          child: Container(),
+//        ),
         ConstrainedBox(
             key: _myKey,
             constraints: BoxConstraints(maxHeight: 150, minHeight: 50),
             child: Container(
                 padding:
-                    const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
+                const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
                 decoration: shadowTop(),
                 child: Column(
                   mainAxisSize: MainAxisSize.min,
@@ -358,21 +401,22 @@ class _MenuBarState extends State<MenuBar>
                               minLines: 1,
                               maxLines: 3,
 //                              maxLength: 200,
-//                              onChanged: (value) {
-//                                setState(() {
+                              onChanged: (value) {
+                                setState(() {
 //                                  _textFieldValue = value;
-//                                });
-//                              },
+                                });
+                              },
                               onTap: () {
                                 setState(() {
                                   isShowMenuBottomIndex = 1;
                                 });
+                                widget.scrollToBottom();
                               },
                               decoration: InputDecoration(
                                   counterText: "",
                                   hintText: "${widget.inputField}",
                                   contentPadding:
-                                      EdgeInsets.symmetric(vertical: 16.0),
+                                  EdgeInsets.symmetric(vertical: 16.0),
                                   border: InputBorder.none),
                             ),
                           ),
@@ -380,49 +424,36 @@ class _MenuBarState extends State<MenuBar>
                         Expanded(
                           flex: 3,
                           child: PrimaryButton(
-                              content: "发送",
-                              callback: () async {
-                                if (widget.menuIdentity.menuScene == "chat") {
-//                                  MessageInstance message =
-//                                      (await api.postChatSend(
-//                                              widget.menuIdentity.userId,
-//                                              "text",
-//                                              '{"text":"${_controller.text}"}'))
-//                                          .data;
-
-                                  MessageInstance message = new MessageInstance(
-                                    type: "link",
-                                    data: new MessageData(
-                                        logo: avatarList[
-                                            Random().nextInt(10) % 13],
-                                        url: "www.baidu.com",
-                                        text: "饭粒猫与包子鸭呀...",
-                                        user: new MessagePostUser(
-                                            name: "饭粒猫...")),
-                                    toUser: new MessageUser(
-                                        id: 10,
-                                        avatar:
-                                            "https://wxt.sinaimg.cn/thumb300/a6bdcd78gy1gfna8wnwquj20lr0lradp.jpg?tags=%5B%5D"),
-                                    fromUser: new MessageUser(
-                                        id: 10,
-                                        avatar:
-                                            "https://wxt.sinaimg.cn/thumb300/a6bdcd78gy1gfna8wnwquj20lr0lradp.jpg?tags=%5B%5D"),
-                                  );
-
-//                                  await add(
-//                                      message); // await 是等待的标志 我等待完 在做后面的init 的事?
-//                                  _controller.text = "";
-
-                                  // view 上setstate 渲染的...
-                                  widget.sendCallBack(
-                                      message); // 添加完 在 callBack...
-
-                                  // 调整高度...
+                            content: "发送",
+                            callback: () async {
+                              if (_controller.text.length <= 0) {
+                                ToastUtil.show("请输入正确的内容");
+                                return;
+                              }
+
+                              if (widget.menuIdentity.menuScene == "chat") {
+                                MessageInstance message =
+                                    (await api.postChatSend(
+                                        widget.menuIdentity.userId,
+                                        "text",
+                                        '{"text":"${_controller.text}"}'))
+                                        .data;
+
+                                await add(
+                                    message); // await 是等待的标志 我等待完 在做后面的init 的事?
+                                _controller.text = "";
+
+                                // 调整高度...
 //                                  widget.scrollToBottom(context,
 //                                      widget.globalkey, false); //发完还得 调整一手 ...
-                                }
-                                // 这里可能传不了 callback 所有需要的值都在menu bar里面 只能通过传 不同的 场景 进行 不同的操作
-                              }),
+                              }
+                              // 这里可能传不了 callback 所有需要的值都在menu bar里面 只能通过传 不同的 场景 进行 不同的操作
+                            },
+                            shadow: _controller.text.length <= 0 ? false : true,
+                            buttonColor: _controller.text == ""
+                                ? Color(0xffd2d2d2)
+                                : null,
+                          ),
                         ),
                       ],
                     ),
@@ -482,6 +513,17 @@ class GetMenuController {
       });
     }
   }
+
+  // 后续修改为用这个...
+  void scroll() {
+//    SchedulerBinding.instance.addPostFrameCallback((_) {
+////here the sublist is already build
+//      scrollMenuController
+//          .jumpTo(scrollMenuController.position.maxScrollExtent);
+//      print(
+//          "${scrollMenuController.position.minScrollExtent} - ${scrollMenuController.position.maxScrollExtent}");
+//    });
+  }
 }
 
 // 自己内部传的 bean 用来鉴别 是什么 场景使用的 menuBar

+ 69 - 24
lib/widgets/menu_share_bottom.dart

@@ -5,9 +5,12 @@ import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/services.dart';
 import 'package:image_gallery_saver/image_gallery_saver.dart';
+import 'package:provider/provider.dart';
 import 'package:sport/bean/post.dart';
 import 'package:sport/pages/social/post_share_page.dart';
+import 'package:sport/provider/user_model.dart';
 import 'package:sport/router/navigator_util.dart';
+import 'package:sport/services/api/inject_api.dart';
 import 'package:sport/utils/toast.dart';
 import 'package:path_provider/path_provider.dart';
 import 'package:sport/sharesdk/tencent.dart';
@@ -16,24 +19,30 @@ import 'dart:io';
 import 'dart:typed_data';
 
 class MenuShareBottomContent extends StatefulWidget {
-  final String url;
-  final bool hasDownload;
-  final GlobalKey poster;
-  final String shareType;
-  final Post post;
-
-  MenuShareBottomContent(this.shareType,
-      {this.post, this.url = "", this.hasDownload = false, this.poster});
+  final String url; // 复制的那个链接
+  final bool hasDownload; // 有些又download 有些没download
+  final GlobalKey poster; // 下载海报...
+  final String shareType; // 什么类型 Img social Link
+  final Post post; // social 连带的 post
+  final String hash; // 分享 link 连带的hash
+  MenuShareBottomContent(
+    this.shareType, {
+    this.post,
+    this.url = "",
+    this.hasDownload = false,
+    this.poster,
+    this.hash,
+  });
   @override
   State<StatefulWidget> createState() {
     // TODO: implement createState
     return _MenuShareBottomContentState();
   }
 }
-// shareType : Img / Link / Social
 
+// shareType : Img / Link / Social
 class _MenuShareBottomContentState extends State<MenuShareBottomContent>
-    with TencentMixin, WechatMixin {
+    with TencentMixin, WechatMixin, InjectApi {
   List<Map<String, dynamic>> map;
   Uint8List postInstance;
   @override
@@ -48,8 +57,9 @@ class _MenuShareBottomContentState extends State<MenuShareBottomContent>
           if (widget.shareType == "Img") {
             String path = await initFile();
             wechatShareImage(path, "chat");
-          } else {
-            print("-----");
+          } else if (widget.shareType == "Link") {
+            wechatShareLink(widget.url + "?h=${widget.hash}", "chat",
+                Provider.of<UserModel>(context, listen: false).user.name);
           }
         }
       },
@@ -60,8 +70,9 @@ class _MenuShareBottomContentState extends State<MenuShareBottomContent>
           if (widget.shareType == "Img") {
             String path = await initFile();
             wechatShareImage(path, "friend");
-          } else {
-            print("-----");
+          } else if (widget.shareType == "Link") {
+            wechatShareLink(widget.url + "?h=${widget.hash}", "friend",
+                Provider.of<UserModel>(context, listen: false).user.name);
           }
         }
       },
@@ -72,29 +83,59 @@ class _MenuShareBottomContentState extends State<MenuShareBottomContent>
           if (widget.shareType == "Img") {
             String path = await initFile();
             qqShare(path);
-          } else {
-            print("-----");
+          } else if (widget.shareType == "Link") {
+            qqShareLink(widget.url);
           }
         }
       },
       {
         "value": "社区",
         "url": "share_icon_community",
-        "callBack": () {
+        "callBack": () async {
           if (widget.shareType == "social") {
-            NavigatorUtil.goPage(
-                context, (context) => PostSharePage(widget.post));
+            await NavigatorUtil.goPage(
+                context, (context) => PostSharePage(post: widget.post));
+          } else if (widget.shareType == "Link") {
+            await NavigatorUtil.goPage(
+                context,
+                (context) => PostSharePage(
+                      url: "http://shoes-web.hiyd.com/share",
+                      hash: widget.hash,
+                    ));
+          } else if (widget.shareType == "Img") {
+            String path = await initFile();
+
+            await NavigatorUtil.goPage(
+                context, (context) => PostSharePage(image: path));
           }
+          Navigator.pop(context,true);
         }
       },
       {
         "value": "社区好友",
         "url": "share_icon_friends",
-        "callBack": () {
+        "callBack": () async {
           if (widget.shareType == "social") {
-            NavigatorUtil.goPage(
-                context, (context) => PostShareFriendsPage(widget.post));
+            await NavigatorUtil.goPage(
+                context,
+                (context) => PostShareFriendsPage(
+                      post: widget.post,
+                    ));
+
+          } else if (widget.shareType == "Link") {
+            // 这里可能得组装一手 link 的 数据 ...
+            await NavigatorUtil.goPage(
+                context, (context) => PostShareFriendsPage(hash: widget.hash));
+          } else if (widget.shareType == "Img") {
+            String path = await initFile();
+            String url = (await api.postChatUpload(File(path))).data["url"];
+            await NavigatorUtil.goPage(
+                context,
+                (context) => PostShareFriendsPage(
+                      image: url,
+                    ));
           }
+          Navigator.pop(context,true);
         }
       },
       {
@@ -239,12 +280,16 @@ class _MenuShareBottomContentState extends State<MenuShareBottomContent>
 }
 
 Future<bool> menuShareBottom(BuildContext context, String shareType,
-    {Post post, String url, bool hasDownload, GlobalKey poster}) {
+    {Post post, String url, bool hasDownload, GlobalKey poster, String hash}) {
   return showModalBottomSheet(
     context: context,
     builder: (context) {
       return MenuShareBottomContent(shareType,
-          post: post, url: url, hasDownload: hasDownload, poster: poster);
+          post: post,
+          url: url,
+          hasDownload: hasDownload,
+          poster: poster,
+          hash: hash);
     },
     backgroundColor: Colors.white,
     elevation: 10,

+ 1 - 1
pubspec.yaml

@@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
 # Read more about iOS versioning at
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
-version: 1.0.2+1
+version: 1.0.3+1
 
 environment:
   sdk: ">=2.7.0 <3.0.0"