Fenix Wang 8 år sedan
förälder
incheckning
cf835e4be3
79 ändrade filer med 4127 tillägg och 336 borttagningar
  1. 13 1
      app/AndroidManifest.xml
  2. 7 7
      app/app.iml
  3. BIN
      app/res/drawable-xhdpi/icon_new_follow.png
  4. 17 0
      app/res/layout/activity_be_followed.xml
  5. 167 0
      app/res/layout/activity_forget.xml
  6. 1 0
      app/res/layout/area_group_create_group.xml
  7. 2 2
      app/res/layout/circle_new_tweeting.xml
  8. 11 0
      app/res/layout/content_be_followed.xml
  9. 11 0
      app/res/layout/content_forget.xml
  10. 2 2
      app/res/layout/login_and_reg_login_layout.xml
  11. 10 8
      app/res/layout/mine_about_webview_activity.xml
  12. 51 0
      app/res/layout/mine_fragment.xml
  13. 2 0
      app/res/values/strings.xml
  14. 50 13
      app/src/com/sheishuo/app/cache/SocialInfoCache.java
  15. 31 0
      app/src/com/sheishuo/app/common/beans/BeFollowedBean.java
  16. 9 9
      app/src/com/sheishuo/app/common/beans/CircleBean.java
  17. 3 3
      app/src/com/sheishuo/app/common/beans/CircleUserLikedBean.java
  18. 88 0
      app/src/com/sheishuo/app/common/beans/RequestBean.java
  19. 9 0
      app/src/com/sheishuo/app/common/beans/SocialInfoBean.java
  20. 52 0
      app/src/com/sheishuo/app/common/util/date/DateUtil.java
  21. 15 0
      app/src/com/sheishuo/app/common/util/img/ImgUtil.java
  22. 18 2
      app/src/com/sheishuo/app/common/util/net/INet.java
  23. 303 6
      app/src/com/sheishuo/app/common/util/net/NetImpl.java
  24. 17 4
      app/src/com/sheishuo/app/common/util/net/NetInfo.java
  25. 7 3
      app/src/com/sheishuo/app/common/views/BaseToolbar.java
  26. 8 8
      app/src/com/sheishuo/app/core_module/circle/activity/CircleDetailsActivity.java
  27. 17 12
      app/src/com/sheishuo/app/core_module/circle/activity/CirclePersonActivity.java
  28. 16 2
      app/src/com/sheishuo/app/core_module/circle/activity/NewCommentActivity.java
  29. 165 51
      app/src/com/sheishuo/app/core_module/circle/activity/NewTweetingActivity.java
  30. 34 0
      app/src/com/sheishuo/app/core_module/circle/model/NewTweetModel.java
  31. 9 0
      app/src/com/sheishuo/app/core_module/circle/presenter/NewTweetPresenter.java
  32. 120 0
      app/src/com/sheishuo/app/core_module/friends/activity/BeFollowedActivity.java
  33. 64 4
      app/src/com/sheishuo/app/core_module/friends/activity/ContactsListActivity.java
  34. 528 0
      app/src/com/sheishuo/app/core_module/friends/activity/FollowSelectActivity.java
  35. 470 0
      app/src/com/sheishuo/app/core_module/friends/fragment/BeFollowedListFragment.java
  36. 479 0
      app/src/com/sheishuo/app/core_module/friends/fragment/FollowListFragment.java
  37. 18 0
      app/src/com/sheishuo/app/core_module/friends/item/FollowItem.java
  38. 45 0
      app/src/com/sheishuo/app/core_module/friends/model/FollowDataAdapter.java
  39. 65 0
      app/src/com/sheishuo/app/core_module/friends/provider/BeFollowedDataProvider.java
  40. 74 0
      app/src/com/sheishuo/app/core_module/friends/provider/FollowDataProvider.java
  41. 24 0
      app/src/com/sheishuo/app/core_module/friends/viewholder/FollowContactHolder.java
  42. 1 1
      app/src/com/sheishuo/app/core_module/mine/view/ui/activity/HobbySelectActivity.java
  43. 17 12
      app/src/com/sheishuo/app/core_module/mine/view/ui/activity/PersonalSettingsActivity.java
  44. 3 0
      app/src/com/sheishuo/app/core_module/mine/view/ui/activity/UserInfoDetailActivity.java
  45. 16 15
      app/src/com/sheishuo/app/core_module/mine/view/ui/activity/UserInfoSettingActivity.java
  46. 75 5
      app/src/com/sheishuo/app/core_module/sheishuo/view/ui/TeamSettingsActivity.java
  47. 36 0
      app/src/com/sheishuo/app/core_module/trade/model/TradeModel.java
  48. 25 3
      app/src/com/sheishuo/app/core_module/trade/presenter/TradePresenter.java
  49. 208 78
      app/src/com/sheishuo/app/core_module/trade/view/ui/activity/TradePublishActivity.java
  50. 42 7
      app/src/com/sheishuo/app/impl/SheishuoTeamMessageActivity.java
  51. 7 0
      app/src/com/sheishuo/app/login/LoginActivity.java
  52. 181 0
      app/src/com/sheishuo/app/main/activity/ForgetActivity.java
  53. 3 2
      app/src/com/sheishuo/app/main/activity/GlobalSearchActivity.java
  54. 2 1
      app/src/com/sheishuo/app/main/activity/MainActivity.java
  55. 122 5
      app/src/com/sheishuo/app/main/activity/SystemMessageActivity.java
  56. 29 12
      app/src/com/sheishuo/app/main/adapter/CircleListAdapter.java
  57. 24 2
      app/src/com/sheishuo/app/main/fragment/CircleOfFriendsFragment.java
  58. 40 3
      app/src/com/sheishuo/app/main/fragment/HomeFragment.java
  59. 100 8
      app/src/com/sheishuo/app/main/fragment/MineFragment.java
  60. 76 3
      app/src/com/sheishuo/app/main/fragment/SessionListFragment.java
  61. 15 12
      app/src/com/sheishuo/app/main/helper/MessageHelper.java
  62. 0 1
      app/src/com/sheishuo/app/main/model/MainTab.java
  63. 1 1
      app/src/com/sheishuo/app/session/SessionHelper.java
  64. BIN
      uikit/res/drawable-hdpi/nim_message_right_blue_bg.9.png
  65. BIN
      uikit/res/drawable-hdpi/nim_message_right_blue_bg_pressed.9.png
  66. 0 4
      uikit/res/layout/gift_panel.xml
  67. 1 1
      uikit/res/layout/nim_message_activity_bottom_layout.xml
  68. 26 3
      uikit/src/com/netease/nim/uikit/cache/NimUserInfoCache.java
  69. 1 1
      uikit/src/com/netease/nim/uikit/contact/ContactsFragment.java
  70. 1 0
      uikit/src/com/netease/nim/uikit/contact/ait/AitContactsDataChangeListener.java
  71. 7 0
      uikit/src/com/netease/nim/uikit/contact/ait/AitedContacts.java
  72. 2 0
      uikit/src/com/netease/nim/uikit/contact/core/item/ItemTypes.java
  73. 5 5
      uikit/src/com/netease/nim/uikit/contact/core/model/ContactDataAdapter.java
  74. 5 0
      uikit/src/com/netease/nim/uikit/contact/core/model/IContact.java
  75. 3 1
      uikit/src/com/netease/nim/uikit/contact/core/provider/ContactSearch.java
  76. 1 1
      uikit/src/com/netease/nim/uikit/contact/core/viewholder/ContactHolder.java
  77. 1 1
      uikit/src/com/netease/nim/uikit/contact_selector/viewholder/ContactsSelectHolder.java
  78. 5 4
      uikit/src/com/netease/nim/uikit/session/activity/WatchPictureActivity.java
  79. 14 7
      uikit/src/com/netease/nim/uikit/session/module/input/InputPanel.java

+ 13 - 1
app/AndroidManifest.xml

@@ -593,7 +593,19 @@
             android:name=".core_module.circle.activity.CirclePersonActivity"
             android:label="@string/title_activity_circle_person"
             android:theme="@style/AppTheme.NoActionBar" />
-        <activity android:name=".impl.SheishuoP2PMessageActivity"></activity>
+        <activity android:name=".impl.SheishuoP2PMessageActivity" />
+        <activity
+            android:name=".core_module.friends.activity.BeFollowedActivity"
+            android:label="@string/title_activity_be_followed"
+            android:theme="@style/AppTheme.NoActionBar" />
+        <activity
+            android:name=".main.activity.ForgetActivity"
+            android:label="@string/title_activity_forget"
+            android:theme="@style/AppTheme.NoActionBar"></activity>
+        <activity
+            android:name=".core_module.friends.activity.FollowSelectActivity"
+            android:label="@string/title_activity_forget"
+            android:theme="@style/AppTheme.NoActionBar"></activity>
     </application>
 
 </manifest>

+ 7 - 7
app/app.iml

@@ -59,13 +59,6 @@
       <sourceFolder url="file://$MODULE_DIR$/assets" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
@@ -73,6 +66,13 @@
       <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />

BIN
app/res/drawable-xhdpi/icon_new_follow.png


+ 17 - 0
app/res/layout/activity_be_followed.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.sheishuo.app.common.views.BaseToolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="@style/fullToolbarStyle"/>
+    <LinearLayout
+        android:id="@+id/recent_contacts_list_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</LinearLayout>

+ 167 - 0
app/res/layout/activity_forget.xml

@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <android.support.design.widget.AppBarLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:theme="@style/AppTheme.NoActionBar.AppBarOverlay">
+
+        <com.sheishuo.app.common.views.BaseToolbar
+            android:id="@+id/toolbar"
+            style="@style/fullToolbarStyle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    </android.support.design.widget.AppBarLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="15dp">
+
+            <TextView
+                android:layout_width="80dp"
+                android:layout_height="wrap_content"
+                android:text="手机号"
+                android:textColor="@color/black"
+                android:textSize="18sp" />
+
+            <EditText
+                android:id="@+id/mobile_txt"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="90dp"
+                android:background="@null"
+                android:ems="10"
+                android:hint="输入手机号"
+                android:inputType="phone" />
+
+        </RelativeLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/grey_light" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:padding="15dp">
+
+            <TextView
+                android:layout_width="80dp"
+                android:layout_height="wrap_content"
+                android:text="验证码"
+                android:textColor="@color/black"
+                android:textSize="18sp" />
+
+            <EditText
+                android:id="@+id/code_txt"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="90dp"
+                android:layout_marginRight="110dp"
+                android:background="@null"
+                android:ems="10"
+                android:hint="输入验证码"
+                android:inputType="number" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="right"
+                android:orientation="horizontal">
+
+                <View
+                    android:id="@+id/view3"
+                    android:layout_width="1dp"
+                    android:layout_height="18dp"
+                    android:background="@color/grey_light" />
+
+                <Button
+                    android:id="@+id/send_code_btn"
+                    android:layout_width="100dp"
+                    android:layout_height="20dp"
+                    android:background="@null"
+                    android:text="获取验证码"
+                    android:textColor="@color/color_green_00ae8c"
+                    android:textSize="16sp" />
+
+            </LinearLayout>
+
+        </RelativeLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/grey_light" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:padding="15dp">
+
+            <TextView
+                android:layout_width="80dp"
+                android:layout_height="wrap_content"
+                android:text="密码"
+                android:textColor="@color/black"
+                android:textSize="18sp" />
+
+            <EditText
+                android:id="@+id/pwd_txt"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="90dp"
+                android:background="@null"
+                android:ems="10"
+                android:hint="输入8至12位新密码"
+                android:inputType="textPassword" />
+
+        </RelativeLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/grey_light" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:padding="15dp">
+
+            <TextView
+                android:layout_width="80dp"
+                android:layout_height="wrap_content"
+                android:text="确认密码"
+                android:textColor="@color/black"
+                android:textSize="18sp" />
+
+            <EditText
+                android:id="@+id/confirm_txt"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="90dp"
+                android:background="@null"
+                android:ems="10"
+                android:hint="再输一次密码"
+                android:inputType="textPassword" />
+
+        </RelativeLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/grey_light" />
+
+    </LinearLayout>
+
+</LinearLayout>

+ 1 - 0
app/res/layout/area_group_create_group.xml

@@ -80,6 +80,7 @@
                 android:id="@+id/create_group_members_layout"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent">
+
                 <com.netease.nim.uikit.common.ui.imageview.HeadImageView
                     android:id="@+id/create_group_add_member"
                     android:layout_width="wrap_content"

+ 2 - 2
app/res/layout/circle_new_tweeting.xml

@@ -59,8 +59,8 @@
 
             <ImageView
                 android:id="@+id/new_tweet_add_imgs"
-                android:layout_width="128dp"
-                android:layout_height="128dp"
+                android:layout_width="60dp"
+                android:layout_height="60dp"
                 android:src="@drawable/circle_new_tweet_img" />
         </LinearLayout>
     </HorizontalScrollView>

+ 11 - 0
app/res/layout/content_be_followed.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    app:layout_behavior="@string/appbar_scrolling_view_behavior"
+    tools:context="com.sheishuo.app.core_module.friends.activity.BeFollowedActivity"
+    tools:showIn="@layout/activity_be_followed">
+
+</android.support.constraint.ConstraintLayout>

+ 11 - 0
app/res/layout/content_forget.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    app:layout_behavior="@string/appbar_scrolling_view_behavior"
+    tools:context="com.sheishuo.app.main.activity.ForgetActivity"
+    tools:showIn="@layout/activity_forget">
+
+</android.support.constraint.ConstraintLayout>

+ 2 - 2
app/res/layout/login_and_reg_login_layout.xml

@@ -68,6 +68,7 @@
             android:layout_marginTop="30dp"
             android:background="@android:drawable/editbox_background"
             android:hint="@string/please_input_tel_num"
+            android:inputType="phone"
             android:maxLines="1"
             android:padding="15dp"
             app:layout_constraintHorizontal_bias="0.117"
@@ -100,7 +101,6 @@
             android:layout_marginRight="15dp"
             android:layout_marginTop="9dp"
             android:text="忘记密码?"
-            android:visibility="gone"
             android:textColor="@color/grey_light"
             app:layout_constraintRight_toRightOf="@+id/login_password"
             app:layout_constraintTop_toBottomOf="@+id/login_password" />
@@ -112,7 +112,7 @@
             android:layout_height="wrap_content"
             android:layout_marginLeft="15dp"
             android:layout_marginRight="15dp"
-            android:layout_marginTop="20dp"
+            android:layout_marginTop="15dp"
             android:text="@string/login"
             app:layout_constraintHorizontal_bias="0.0"
             app:layout_constraintLeft_toLeftOf="@+id/login_password"

+ 10 - 8
app/res/layout/mine_about_webview_activity.xml

@@ -28,24 +28,26 @@
         android:layout_height="wrap_content"
         android:orientation="horizontal"
         android:visibility="gone">
+
         <Button
             android:id="@+id/mine_about_webview_agree"
-            android:layout_weight="1"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:text="同意"
-            android:textColor="@color/white"
+            android:layout_margin="8dp"
+            android:layout_weight="1"
             android:background="@drawable/btn1_selector"
-            android:layout_margin="8dp"/>
+            android:text="取消"
+            android:textColor="@color/white" />
+
         <Button
             android:id="@+id/mine_about_webview_reject"
-            android:layout_weight="1"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:text="拒绝"
-            android:textColor="@color/white"
+            android:layout_margin="8dp"
+            android:layout_weight="1"
             android:background="@drawable/btn1_selector"
-            android:layout_margin="8dp"/>
+            android:text="实名认证"
+            android:textColor="@color/white" />
     </LinearLayout>
 
 </LinearLayout>

+ 51 - 0
app/res/layout/mine_fragment.xml

@@ -107,6 +107,57 @@
                 android:columnCount="4"/>
 
 
+            <TextView
+                android:id="@+id/textView8"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="8dp"
+                android:layout_marginStart="8dp"
+                android:paddingBottom="8dp"
+                android:paddingTop="8dp"
+                android:text="动态"
+                android:textSize="16sp" />
+
+            <RelativeLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+                <LinearLayout
+                    android:id="@+id/mine_fragment_detail_circle"
+                    android:layout_width="match_parent"
+                    android:layout_height="80dp"
+                    android:background="#00000000"
+                    android:gravity="right"
+                    android:orientation="horizontal">
+
+                    <LinearLayout
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:gravity="right|center"
+                        android:paddingLeft="200dp"
+                        android:paddingRight="20dp">
+
+                        <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:layout_weight="1"
+                            android:text="..." />
+
+                        <ImageView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:layout_weight="1"
+                            app:srcCompat="@drawable/nim_arrow_right" />
+                    </LinearLayout>
+                </LinearLayout>
+
+                <GridLayout
+                    android:id="@+id/mine_fragment_details_tweet_photos_layout"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:columnCount="4"></GridLayout>
+
+            </RelativeLayout>
 
             <LinearLayout
                 android:id="@+id/mine_fragment_options_layout"

+ 2 - 0
app/res/values/strings.xml

@@ -391,6 +391,8 @@
     <string name="contacts">通讯录</string>
     <string name="add_friends">添加朋友</string>
     <string name="title_activity_circle_person">个人动态</string>
+    <string name="title_activity_be_followed">BeFollowedActivity</string>
+    <string name="title_activity_forget">ForgetActivity</string>
 
 
 </resources>

+ 50 - 13
app/src/com/sheishuo/app/cache/SocialInfoCache.java

@@ -1,16 +1,12 @@
 package com.sheishuo.app.cache;
 
+import com.netease.nim.uikit.cache.NimUserInfoCache;
 import com.netease.nimlib.sdk.NIMClient;
-import com.netease.nimlib.sdk.friend.FriendService;
-import com.netease.nimlib.sdk.friend.model.Friend;
-import com.netease.nimlib.sdk.uinfo.UserInfoProvider;
 import com.netease.nimlib.sdk.uinfo.UserService;
 import com.netease.nimlib.sdk.uinfo.model.NimUserInfo;
 import com.sheishuo.app.common.beans.SocialInfoBean;
-import com.sheishuo.app.common.util.net.INet;
-import com.sheishuo.app.common.util.net.NetImpl;
-import com.sheishuo.app.common.util.net.ResponseCallback;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -19,11 +15,11 @@ import java.util.Map;
  */
 
 public class SocialInfoCache {
-    private static INet net = new NetImpl();
     private static Map<String,SocialInfoBean> socialInfoMap = new HashMap<>();
+    private static Map<String, String> followCache;
 
-
-    public static void put(String id,SocialInfoBean info){
+    public static void put(String id, SocialInfoBean info){
+        NimUserInfoCache.getInstance().setAlias(id, info.getAlias());
         socialInfoMap.put(id,info);
     }
 
@@ -36,14 +32,14 @@ public class SocialInfoCache {
 
     public static String getNick(String id)
     {
-        Friend friend = NIMClient.getService(FriendService.class).getFriendByAccount(id);
-        if(friend != null && friend.getAlias() != null && friend.getAlias().length() > 0)
+        SocialInfoBean bean = get(id);
+        if(bean != null && bean.getAlias() != null && bean.getAlias().length() > 0)
         {
-            return friend.getAlias();
+            return bean.getAlias();
         }
 
         NimUserInfo user = NIMClient.getService(UserService.class).getUserInfo(id);
-        if (user.getName() != null && user.getName().length() > 0)
+        if (user != null && user.getName() != null && user.getName().length() > 0)
         {
             return user.getName();
         }
@@ -58,5 +54,46 @@ public class SocialInfoCache {
         return id;
     }
 
+    public static Collection<String> followList()
+    {
+        if(followCache == null)
+            return null;
+
+        return followCache.values();
+    }
+
+    public static void initFollowList(Collection<String> list)
+    {
+        followCache = new HashMap<String, String>();
+        for(String userId : list)
+        {
+            setFollow(userId, true);
+        }
+    }
+
+    public static void setFollow(String userId, Boolean value)
+    {
+        if(followCache == null)
+            return;
+
+        if(!value)
+        {
+            followCache.remove(userId);
+        }
+        else if(!followCache.containsKey(userId))
+        {
+            followCache.put(userId, userId);
+        }
+    }
+
+    public static void setAlias(String userId, String alias)
+    {
+        SocialInfoBean bean = SocialInfoCache.get(userId);
+        NimUserInfoCache.getInstance().setAlias(userId, alias);
+        if(bean != null)
+            bean.setAlias(alias);
+    }
+
+
 }
 

+ 31 - 0
app/src/com/sheishuo/app/common/beans/BeFollowedBean.java

@@ -0,0 +1,31 @@
+package com.sheishuo.app.common.beans;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Created by KN on 2017/7/18.
+ */
+
+public class BeFollowedBean implements Serializable{
+
+    private int c;
+    private List<String> d;
+
+    public int getC() {
+        return c;
+    }
+
+    public void setC(int c) {
+        this.c = c;
+    }
+
+    public List<String> getD() {
+        return d;
+    }
+
+    public void setD(List<String> d) {
+        this.d = d;
+    }
+
+}

+ 9 - 9
app/src/com/sheishuo/app/common/beans/CircleBean.java

@@ -69,9 +69,9 @@ public class CircleBean implements Serializable{
             private String local;
             private String msg;
             private String pic;
-            private String views;
-            private String likes;
-            private String comments;
+            private int views;
+            private int likes;
+            private int comments;
             private String longitude;
             private String latitude;
             private String inputtime;
@@ -121,27 +121,27 @@ public class CircleBean implements Serializable{
                 this.pic = pic;
             }
 
-            public String getViews() {
+            public int getViews() {
                 return views;
             }
 
-            public void setViews(String views) {
+            public void setViews(int views) {
                 this.views = views;
             }
 
-            public String getLikes() {
+            public int getLikes() {
                 return likes;
             }
 
-            public void setLikes(String likes) {
+            public void setLikes(int likes) {
                 this.likes = likes;
             }
 
-            public String getComments() {
+            public int getComments() {
                 return comments;
             }
 
-            public void setComments(String comments) {
+            public void setComments(int comments) {
                 this.comments = comments;
             }
 

+ 3 - 3
app/src/com/sheishuo/app/common/beans/CircleUserLikedBean.java

@@ -40,15 +40,15 @@ public class CircleUserLikedBean {
          * like_users : ["200028","200030"]
          */
 
-        private String likes;
+        private int likes;
         private String social_id;
         private List<String> like_users;
 
-        public String getLikes() {
+        public int getLikes() {
             return likes;
         }
 
-        public void setLikes(String likes) {
+        public void setLikes(int likes) {
             this.likes = likes;
         }
 

+ 88 - 0
app/src/com/sheishuo/app/common/beans/RequestBean.java

@@ -0,0 +1,88 @@
+package com.sheishuo.app.common.beans;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Created by KN on 2017/7/18.
+ */
+
+public class RequestBean implements Serializable{
+
+    private int c;
+    private List<ListBean> d;
+
+    public int getC() {
+        return c;
+    }
+
+    public void setC(int c) {
+        this.c = c;
+    }
+
+    public List<ListBean> getD() {
+        return d;
+    }
+
+    public void setD(List<ListBean> d) {
+        this.d = d;
+    }
+
+    public class ListBean implements Serializable{
+
+        private String id;
+        private String user_id;
+        private String target_id;
+        private String msg;
+        private String state;
+        private String inputtime;
+
+        public String getId() {
+            return id;
+        }
+
+        public void setId(String id) {
+            this.id = id;
+        }
+
+        public String getUser_id() {
+            return user_id;
+        }
+
+        public void setUser_id(String user_id) {
+            this.user_id = user_id;
+        }
+
+        public String getTarget_id() {
+            return target_id;
+        }
+
+        public void setTarget_id(String target_id) {
+            this.target_id = target_id;
+        }
+
+        public String getMsg() {
+            return msg;
+        }
+
+        public void setMsg(String msg) {
+            this.msg = msg;
+        }
+
+        public String getState() {
+            return state;
+        }
+
+        public void setState(String state) {
+            this.state = state;
+        }
+
+        public String getInputtime() {
+            return inputtime;
+        }
+
+        public void setInputtime(String inputtime) {
+            this.inputtime = inputtime;
+        }
+    }
+}

+ 9 - 0
app/src/com/sheishuo/app/common/beans/SocialInfoBean.java

@@ -44,6 +44,7 @@ public class SocialInfoBean {
     private String ssid;
     private String pwd;
     private String nick;
+    private String alias;
     private String mobile;
     private String coin;
     private String room_id;
@@ -99,6 +100,14 @@ public class SocialInfoBean {
         this.nick = nick;
     }
 
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
     public String getMobile() {
         return mobile;
     }

+ 52 - 0
app/src/com/sheishuo/app/common/util/date/DateUtil.java

@@ -0,0 +1,52 @@
+package com.sheishuo.app.common.util.date;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Created by fenix on 2017/9/17.
+ */
+
+public class DateUtil {
+
+    // string类型转换为date类型
+    // strTime要转换的string类型的时间,formatType要转换的格式yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日
+    // HH时mm分ss秒,
+    // strTime的时间格式必须要与formatType的时间格式相同
+    public static Date stringToDate(String strTime, String formatType)
+            throws ParseException {
+        SimpleDateFormat formatter = new SimpleDateFormat(formatType);
+        Date date = null;
+        date = formatter.parse(strTime);
+        return date;
+    }
+
+    // string类型转换为long类型
+    // strTime要转换的String类型的时间
+    // formatType时间格式
+    // strTime的时间格式和formatType的时间格式必须相同
+    public static long stringToLong(String strTime, String formatType){
+
+        try {
+            Date date = stringToDate(strTime, formatType); // String类型转成date类型
+            if (date == null) {
+                return 0;
+            } else {
+                long currentTime = dateToLong(date); // date类型转成long类型
+                return currentTime;
+            }
+        }
+        catch (Exception e)
+        {
+
+        }
+        return 0;
+    }
+
+    // date类型转换为long类型
+    // date要转换的date类型的时间
+    public static long dateToLong(Date date) {
+        return date.getTime();
+    }
+}

+ 15 - 0
app/src/com/sheishuo/app/common/util/img/ImgUtil.java

@@ -109,6 +109,21 @@ public class ImgUtil {
         return outputFile;
     }
 
+    public static File compressImage(Bitmap bitmap, String targetPath, int quality)  {
+        File outputFile = new File(targetPath);
+        try {
+            if (!outputFile.exists()) {
+                outputFile.getParentFile().mkdirs();
+                //outputFile.createNewFile();
+            }else{
+                outputFile.delete();
+            }
+            FileOutputStream out = new FileOutputStream(outputFile);
+            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out);
+        }catch (Exception e){}
+        return outputFile;
+    }
+
     /**
      * 根据路径获得图片信息并按比例压缩,返回bitmap
      */

+ 18 - 2
app/src/com/sheishuo/app/common/util/net/INet.java

@@ -1,5 +1,6 @@
 package com.sheishuo.app.common.util.net;
 
+import android.graphics.Bitmap;
 import android.support.annotation.Nullable;
 
 import com.sheishuo.app.common.beans.SocialInfoBean;
@@ -20,7 +21,7 @@ public interface INet {
     void post(String url, RequestBody body,ResponseCallback callback);
     void updateLatitudeAndLongitude(double longitude, double latitude, ResponseCallback callback);
     void updateLocation(String province,String city,String district,ResponseCallback callback);
-    void loginQuery(String mobile,String pwd,ResponseCallback callback);
+
     void getVerificationCode(String mobile,ResponseCallback callback);
     void changePwd(String pwd,String newPwd,ResponseCallback callback);
     void getGiftList(ResponseCallback callback);
@@ -42,10 +43,25 @@ public interface INet {
     void updateBanner(String filePath,ResponseCallback callback);
     void getPhoneContactRelationship(String phoneListStr,ResponseCallback callback);
     void sendAddFriendRequest(String targetId,String msg);
-    void followOrUnfollow(String targetId);
     void updateSocialInfo(SocialInfoBean bean,ResponseCallback callback);
     void getHobbyList(ResponseCallback callback);
     void sendInviteMsg(String phoneNum);
     void submitComplaint(String targetId,String type,String reason);
     void alipay(String money,ResponseCallback callback);
+
+    //account
+    void loginQuery(String mobile,String pwd,ResponseCallback callback);
+    void forgetPassword(String mobile, String code, String pwd, ResponseCallback callback);
+    void updateAlias(String targetId, String alias, ResponseCallback callback);
+    void fetchAlias(String targetIds, ResponseCallback callback);
+
+    //follow
+    void followOrUnfollow(String targetId);
+    void followList(ResponseCallback callback);
+    void befollowedList(ResponseCallback callback);
+
+    //friend request
+    void requestList(ResponseCallback callback);
+    void requestDelete(String requestId, ResponseCallback callback);
+    void addFriend(String requestId,  ResponseCallback callback);
 }

+ 303 - 6
app/src/com/sheishuo/app/common/util/net/NetImpl.java

@@ -1,18 +1,22 @@
 package com.sheishuo.app.common.util.net;
 
+import android.graphics.Bitmap;
 import android.support.annotation.Nullable;
 import android.util.Log;
 
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
+import com.netease.nim.uikit.cache.NimUserInfoCache;
 import com.sheishuo.app.SheishuoApplication;
 import com.sheishuo.app.cache.AccountCache;
 import com.sheishuo.app.cache.HobbyCache;
 import com.sheishuo.app.cache.SocialInfoCache;
+import com.sheishuo.app.common.beans.BeFollowedBean;
 import com.sheishuo.app.common.beans.CircleBean;
 import com.sheishuo.app.common.beans.CircleUserLikedBean;
 import com.sheishuo.app.common.beans.ContactRelationshipBean;
 import com.sheishuo.app.common.beans.GiftBean;
+import com.sheishuo.app.common.beans.RequestBean;
 import com.sheishuo.app.common.beans.SocialInfoBean;
 import com.sheishuo.app.common.beans.SocialPhoto;
 import com.sheishuo.app.common.beans.TradeBean;
@@ -26,6 +30,7 @@ import org.json.JSONObject;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -217,7 +222,7 @@ public class NetImpl implements INet {
                 //创建FormBody
                 Request request = new Request.Builder()
                         .post(body)
-                        .url(NetInfo.INDEX + NetInfo.LOGIN_URL)
+                        .url(LOGIN_URL)
                         .build();
 
 
@@ -283,6 +288,117 @@ public class NetImpl implements INet {
     }
 
     @Override
+    public void forgetPassword(final String mobile, final String code, final String pwd, final ResponseCallback callback) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try{
+                    FormBody body = new FormBody.Builder()
+                            .add("mobile", mobile)
+                            .add("pwd", pwd)
+                            .add("code",code)
+                            .build();
+
+                    Request request = new Request.Builder()
+                            .post(body)
+                            .url(FORGET_URL)
+                            .build();
+
+                    Response response = client.newCall(request).execute();
+                    if (200 == response.code()){
+                        callback.onSuccess(null);
+                    }else {
+                        callback.onFailed();
+                    }
+
+                }catch (Exception e){
+                    e.printStackTrace();
+                    callback.onFailed();
+                }
+
+
+            }
+        }).start();
+    }
+
+    @Override
+    public void updateAlias(final String targetId, final String alias, final ResponseCallback callback) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try{
+                    FormBody body = new FormBody.Builder()
+                            .add("user_id", AccountCache.getAccount().getId())
+                            .add("target_id", targetId)
+                            .add("alias", alias)
+                            .build();
+
+                    Request request = new Request.Builder()
+                            .post(body)
+                            .url(ALIAS_URL)
+                            .build();
+
+                    Response response = client.newCall(request).execute();
+                    if (200 == response.code()){
+                        callback.onSuccess(null);
+                    }else {
+                        callback.onFailed();
+                    }
+
+                }catch (Exception e){
+                    e.printStackTrace();
+                    callback.onFailed();
+                }
+
+
+            }
+        }).start();
+    }
+
+    @Override
+    public void fetchAlias(final String targetIds, final ResponseCallback callback) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try{
+                    FormBody body = new FormBody.Builder()
+                            .add("user_id", AccountCache.getAccount().getId())
+                            .add("target_ids", targetIds)
+                            .build();
+
+                    Request request = new Request.Builder()
+                            .post(body)
+                            .url(FETCH_ALIAS_URL)
+                            .build();
+
+                    Response response = client.newCall(request).execute();
+                    if (200 == response.code()){
+                        String resultStr = response.body().string();
+                        JSONArray list = new JSONObject(resultStr).getJSONObject("d").getJSONArray("list");
+                        for(int i=0; i<list.length(); i++)
+                        {
+                            JSONObject data = list.getJSONObject(i);
+                            String targetId = data.getString("target_id");
+                            String alias = data.getString("alias");
+                            NimUserInfoCache.getInstance().setAlias(targetId, alias);
+                        }
+                        callback.onSuccess(null);
+                    }
+                    else
+                    {
+                        callback.onFailed();
+                    }
+                }catch (Exception e){
+                    e.printStackTrace();
+                    callback.onFailed();
+                }
+
+
+            }
+        }).start();
+    }
+
+    @Override
     public void changePwd(final String pwd, final String newPwd, final ResponseCallback callback) {
         new Thread(new Runnable() {
             @Override
@@ -403,6 +519,7 @@ public class NetImpl implements INet {
         });
     }
 
+
     @Override
     public void uploadSocialPhoto(String filePath, final ResponseCallback callback) {
         File file = new File(filePath);
@@ -713,7 +830,9 @@ public class NetImpl implements INet {
                 try{
                     Response response = client.newCall(request).execute();
                     if (200 ==  response.code()){
-                        CircleBean bean = new Gson().fromJson(response.body().string(),CircleBean.class);
+                        String result = response.body().string();
+                        Log.e("getCircleList", result);
+                        CircleBean bean = new Gson().fromJson(result, CircleBean.class);
                         callback.onSuccess(bean);
                     }else {
                         callback.onFailed();
@@ -900,9 +1019,13 @@ public class NetImpl implements INet {
                     if (200 == response.code()){
                         String resultStr = response.body().string();
                         Log.e("resultStr",resultStr);
-                        int code = new JSONObject(resultStr).getInt("c");
+                        JSONObject result = new JSONObject(resultStr);
+                        int code = result.getInt("c");
+                        JSONObject data = result.getJSONObject("d");
                         if (0 == code){
-                            callback.onSuccess(code);
+                            String dataStr = data.toString();
+                            CircleBean.DBean.ListBean.Comment comment = gson.fromJson(dataStr, CircleBean.DBean.ListBean.Comment.class);
+                            callback.onSuccess(comment);
                         }else {
                             callback.onFailed();
                         }
@@ -1045,10 +1168,94 @@ public class NetImpl implements INet {
                 Response response = null;
                 try {
                     response = client.newCall(request).execute();
-
-                    Log.e("follow",response.body().string());
+                    String resultStr = response.body().string();
+                    Log.e("follow", resultStr);
+                    JSONObject json = new JSONObject(resultStr);
+                    JSONObject data = json.getJSONObject("d");
+                    int follow = data.getInt("follow");
+                    SocialInfoCache.setFollow(targetId, follow > 0);
                 } catch (IOException e) {
                     e.printStackTrace();
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+            }
+        }).start();
+    }
+
+    @Override
+    public void followList(final ResponseCallback callback) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+                Collection<String> followList = SocialInfoCache.followList();
+                if(followList != null)
+                {
+                    callback.onSuccess(followList);
+                    return;
+                }
+
+                FormBody body = new FormBody.Builder()
+                        .add("user_id",AccountCache.getAccount().getId())
+                        .build();
+
+                Request request = new Request.Builder()
+                        .post(body)
+                        .url(FOLLOW_LIST)
+                        .build();
+                try {
+                    Response response = client.newCall(request).execute();
+                    if (200 == response.code()) {
+                        String resultStr = response.body().string();
+                        Log.e("follow list", resultStr);
+                        JSONArray array = new JSONObject(resultStr).getJSONArray("d");
+                        Collection<String> list = new ArrayList<String>();
+                        for(int i=0; i<array.length(); i++)
+                        {
+                            String userId = array.getString(i);
+                            list.add(userId);
+                        }
+                        SocialInfoCache.initFollowList(list);
+                        callback.onSuccess(SocialInfoCache.followList());
+                    } else {
+                        callback.onFailed();
+                    }
+                }catch (Exception e){
+                    e.printStackTrace();
+                    callback.onFailed();
+                }
+            }
+        }).start();
+    }
+
+    @Override
+    public void befollowedList(final ResponseCallback callback) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+                FormBody body = new FormBody.Builder()
+                        .add("user_id",AccountCache.getAccount().getId())
+                        .build();
+
+                Request request = new Request.Builder()
+                        .post(body)
+                        .url(BEFOLLOWED_LIST)
+                        .build();
+                try {
+                    Response response = client.newCall(request).execute();
+                    if (200 == response.code()) {
+                        String resultStr = response.body().string();
+                        Log.e("befollowed list", resultStr);
+                        BeFollowedBean bean = gson.fromJson(resultStr, BeFollowedBean.class);
+                        callback.onSuccess(bean);
+                    } else {
+                        callback.onFailed();
+                    }
+                }catch (Exception e){
+                    e.printStackTrace();
+                    callback.onFailed();
                 }
             }
         }).start();
@@ -1252,4 +1459,94 @@ public class NetImpl implements INet {
     }
 
 
+    @Override
+    public void requestList(final ResponseCallback callback) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try{
+                    FormBody body = new FormBody.Builder()
+                            .add("user_id",AccountCache.getAccount().getId())
+                            .build();
+
+                    Request request = new Request.Builder()
+                            .post(body)
+                            .url(REQUEST_LIST)
+                            .build();
+
+                    Response response = client.newCall(request).execute();
+                    if (200 == response.code()){
+                        RequestBean bean = gson.fromJson(response.body().string(), RequestBean.class);
+                        callback.onSuccess(bean);
+                    }else {
+                        callback.onFailed();
+                    }
+
+                }catch (Exception e){
+                    e.printStackTrace();
+                    callback.onFailed();
+                }
+            }
+        }).start();
+    }
+
+    @Override
+    public void requestDelete(final String id, final ResponseCallback callback) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try{
+                    FormBody body = new FormBody.Builder()
+                            .add("id", id)
+                            .build();
+
+                    Request request = new Request.Builder()
+                            .post(body)
+                            .url(REQUEST_DELETE)
+                            .build();
+
+                    Response response = client.newCall(request).execute();
+                    if (200 == response.code()){
+                        callback.onSuccess(null);
+                    }else {
+                        callback.onFailed();
+                    }
+
+                }catch (Exception e){
+                    e.printStackTrace();
+                    callback.onFailed();
+                }
+            }
+        }).start();
+    }
+
+    @Override
+    public void addFriend(final String requestId, final ResponseCallback callback) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try{
+                    FormBody body = new FormBody.Builder()
+                            .add("id", requestId)
+                            .build();
+
+                    Request request = new Request.Builder()
+                            .post(body)
+                            .url(ADD_FRIEND)
+                            .build();
+
+                    Response response = client.newCall(request).execute();
+                    if (200 == response.code()){
+                        callback.onSuccess(null);
+                    }else {
+                        callback.onFailed();
+                    }
+
+                }catch (Exception e){
+                    e.printStackTrace();
+                    callback.onFailed();
+                }
+            }
+        }).start();
+    }
 }

+ 17 - 4
app/src/com/sheishuo/app/common/util/net/NetInfo.java

@@ -5,9 +5,8 @@ package com.sheishuo.app.common.util.net;
  */
 
 public class NetInfo {
-    public final static String INDEX = "http://whosay.dashgame.com/index.php/";
-    public final static String LOGIN_URL = INDEX + "?m=who&c=index&a=login";
-    public final static String REG_URL = INDEX + "?m=who&c=index&a=register";
+    public final static String INDEX = "http://118.31.11.27/index.php";
+
     public final static String CHANGE_PWD = INDEX + "?m=who&c=index&a=pwd_update";
     public final static String GET_NEARBY_GROUP = INDEX + "?m=who&c=index&a=near_room";
     public final static String CIRCLE_LIST = INDEX + "?m=who&c=social&a=lists";
@@ -35,14 +34,28 @@ public class NetInfo {
     public final static String TRADE_SEARCH = INDEX + "?m=who&c=trade&a=search";
     public final static String CIRCLE_COMMENT = INDEX + "?m=who&c=social&a=comment";
     public final static String UPDATE_BANNER = INDEX + "?m=who&c=social&a=banner_upload";
+    public final static String REQUEST_LIST = INDEX + "?m=who&c=social&a=request_list";
+    public final static String REQUEST_DELETE = INDEX + "?m=who&c=social&a=delete_request";
+    public final static String ADD_FRIEND = INDEX + "?m=who&c=social&a=add_friend";
     public final static String REQUEST_FRIEND = INDEX + "?m=who&c=social&a=request_friend";
-    public final static String FOLLOW_OR_UNFOLLOW_USER = INDEX + "?m=who&c=social&a=follow";
+
     public final static String UPDATE_SOCIAL_INFO = INDEX + "?m=who&c=social&a=update_info";
     public final static String GET_HOBBY = INDEX + "?m=who&c=index&a=hobby_list";
     public final static String SEND_INVITE_MSG = INDEX + "?m=who&c=index&a=send_msg";
     public final static String SUBMIT_COMPLAINT = INDEX + "?m=who&c=index&a=complain";
     public final static String ALIPAY_URL = INDEX + "?m=who&c=index&a=alipay_order";
 
+    //account
+    public final static String LOGIN_URL = INDEX + "?m=who&c=index&a=login";
+    public final static String REG_URL = INDEX + "?m=who&c=index&a=register";
+    public final static String FORGET_URL = INDEX + "?m=who&c=index&a=forget";
+    public final static String ALIAS_URL = INDEX + "?m=who&c=social&a=update_alias";
+    public final static String FETCH_ALIAS_URL = INDEX + "?m=who&c=social&a=fetch_alias";
+
+    //follow
+    public final static String FOLLOW_OR_UNFOLLOW_USER = INDEX + "?m=who&c=social&a=follow";
+    public final static String FOLLOW_LIST = INDEX + "?m=who&c=social&a=follows";
+    public final static String BEFOLLOWED_LIST = INDEX + "?m=who&c=social&a=befollowed";
 
 
     //about URL

+ 7 - 3
app/src/com/sheishuo/app/common/views/BaseToolbar.java

@@ -149,7 +149,9 @@ public class BaseToolbar extends Toolbar {
             if(view instanceof ImageView)
             {
                 ImageView imageView = (ImageView) view;
-                imageView.setLayoutParams(new ViewGroup.LayoutParams(ScreenUtil.dip2px(28), ScreenUtil.dip2px(28)));
+                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ScreenUtil.dip2px(28), ScreenUtil.dip2px(28));
+                layoutParams.setMargins(ScreenUtil.dip2px(10), 0, 0, 0);
+                imageView.setLayoutParams(layoutParams);
                 imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
             }
             else if(view instanceof TextView)
@@ -157,11 +159,13 @@ public class BaseToolbar extends Toolbar {
                 TextView txtView = (TextView) view;
                 txtView.setTextColor(Color.WHITE);
                 txtView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
-                txtView.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+                layoutParams.setMargins(ScreenUtil.dip2px(10), 0, 0, 0);
+                txtView.setLayoutParams(new ViewGroup.LayoutParams(layoutParams));
             }
             else
             {
-                view.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+                //view.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
             }
             rightLayout.addView(view);
         }

+ 8 - 8
app/src/com/sheishuo/app/core_module/circle/activity/CircleDetailsActivity.java

@@ -84,7 +84,6 @@ public class CircleDetailsActivity extends SheishuoUI {
         init();
     }
 
-
     void findViews(){
 
         toolbar = findView(R.id.toolbar);
@@ -143,7 +142,7 @@ public class CircleDetailsActivity extends SheishuoUI {
         dateTV.setText(bean.getInputtime());
 
         //显示阅读量
-        readNumTV.setText(bean.getViews());
+        readNumTV.setText(""+bean.getViews());
 
         if(bean.getUser_id().equals(AccountCache.getAccount().getId())) {
             deleteTV.setVisibility(View.VISIBLE);
@@ -167,8 +166,8 @@ public class CircleDetailsActivity extends SheishuoUI {
             @Override
             public void onClick(View v) {
                 Intent intent = new Intent(context,NewCommentActivity.class);
-                intent.putExtra(NewCommentActivity.SOCIAL_ID,bean.getId());
-                startActivity(intent);
+                intent.putExtra(NewCommentActivity.SOCIAL_ID, bean);
+                startActivityForResult(intent, 0);
             }
         });
 
@@ -274,7 +273,7 @@ public class CircleDetailsActivity extends SheishuoUI {
         }
 
         //显示点赞数
-        likedNumTV.setText(bean.getLikes());
+        likedNumTV.setText(""+bean.getLikes());
         likedNum2TV.setText(bean.getLikes()+"人已赞");
     }
 
@@ -303,12 +302,13 @@ public class CircleDetailsActivity extends SheishuoUI {
         getHandler().post(new Runnable() {
             @Override
             public void run() {
+                commentsLayout.removeAllViews();
                 for(int i=0; i<commentList.size(); i++)
                 {
                     CircleBean.DBean.ListBean.Comment comment = commentList.get(i);
-                    int id = Integer.parseInt(comment.getId());
-                    if(id > lastId)
-                        lastId = id;
+//                    int id = Integer.parseInt(comment.getId());
+//                    if(id > lastId)
+//                        lastId = id;
                     commentsLayout.addView(createComment(comment));
                 }
             }

+ 17 - 12
app/src/com/sheishuo/app/core_module/circle/activity/CirclePersonActivity.java

@@ -42,7 +42,6 @@ public class CirclePersonActivity extends SheishuoUI {
 
     private String TAG = this.getClass().getSimpleName();
     public final static int REFRESH_CIRCLE = 10000;
-    private boolean isLoaded = true;
 
     private Context context = this;
     private CirclePresenter presenter = new CirclePresenter(this);
@@ -57,7 +56,7 @@ public class CirclePersonActivity extends SheishuoUI {
 
     private LinearLayoutManager layoutManager = new LinearLayoutManager(context);
 
-    private Handler handler = getHandler();
+    private Handler handler;
 
     private Toast toast = null;
     private long lastTime = System.currentTimeMillis();
@@ -74,6 +73,7 @@ public class CirclePersonActivity extends SheishuoUI {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        handler = getHandler();
         setContentView(R.layout.circle_of_person_activity);
         targetId = (String) getIntent().getSerializableExtra(EXTRA_DATA_USER_ID);
 
@@ -94,8 +94,6 @@ public class CirclePersonActivity extends SheishuoUI {
                 .into(backgroundImg);
 
         username.setText(user.getName());
-
-        isLoaded = true;
     }
 
 
@@ -139,8 +137,6 @@ public class CirclePersonActivity extends SheishuoUI {
 
     public void onCircleListLoaded(final CircleBean bean){
 
-        isLoaded = true;
-
         handler.post(new Runnable() {
             @Override
             public void run() {
@@ -188,13 +184,8 @@ public class CirclePersonActivity extends SheishuoUI {
      * @param lastId
      */
     public void loadCircleListMore(String lastId){
-
-        if(isLoaded)
-            return;
-
-        isLoaded = false;
         presenter.loadCircleList(AccountCache.getAccount().getId(), lastId, targetId);
-        showToast("正在加载更多内容...");
+        //showToast("正在加载更多内容...");
     }
 
     /**
@@ -221,6 +212,20 @@ public class CirclePersonActivity extends SheishuoUI {
             case REFRESH_CIRCLE:
                 refreshCircle();
                 break;
+            case CircleOfFriendsFragment.DELETE_CIRCLE:
+                Bundle bundle = data.getExtras();
+                String id = bundle.getString(CircleOfFriendsFragment.DELETE_ID);
+                adapter.onDelete(id);
+                break;
+            case NewCommentActivity.NEW_COMMENT:
+                adapter.addComment((CircleBean.DBean.ListBean.Comment)data.getSerializableExtra(NewCommentActivity.NEW_COMMENT_DATA));
+                getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        adapter.notifyDataSetChanged();
+                    }
+                });
+                break;
         }
     }
 }

+ 16 - 2
app/src/com/sheishuo/app/core_module/circle/activity/NewCommentActivity.java

@@ -1,6 +1,8 @@
 package com.sheishuo.app.core_module.circle.activity;
 
+import android.app.Activity;
 import android.content.Context;
+import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
@@ -9,6 +11,7 @@ import android.widget.ImageView;
 import android.widget.LinearLayout;
 
 import com.sheishuo.app.R;
+import com.sheishuo.app.common.beans.CircleBean;
 import com.sheishuo.app.common.util.net.INet;
 import com.sheishuo.app.common.util.net.NetImpl;
 import com.sheishuo.app.common.util.net.ResponseCallback;
@@ -20,7 +23,8 @@ import com.sheishuo.app.impl.SheishuoUI;
 
 public class NewCommentActivity extends SheishuoUI{
 
-
+    public static final int NEW_COMMENT = 10002;
+    public static final String NEW_COMMENT_DATA = "newCommentData";
 
     public static final String SOCIAL_ID = "social_id";
     public static final String REPLY_ID = "reply_id";
@@ -35,11 +39,15 @@ public class NewCommentActivity extends SheishuoUI{
     private ImageView replyBtn;
 
     private INet net = new NetImpl();
+    private CircleBean.DBean.ListBean bean;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.circle_new_comment);
-        String socialIdStr = getIntent().getStringExtra(SOCIAL_ID);
+        bean = (CircleBean.DBean.ListBean) getIntent().getSerializableExtra(SOCIAL_ID);
+        Log.e("Comment", "receive "+bean.hashCode());
+        String socialIdStr = bean.getId();
         if (socialIdStr != null)
             socialId = Integer.parseInt(socialIdStr);
 
@@ -74,6 +82,12 @@ public class NewCommentActivity extends SheishuoUI{
                 net.newComment(socialId, replyId, replyET.getText().toString(), new ResponseCallback() {
                     @Override
                     public void onSuccess(Object object) {
+                        CircleBean.DBean.ListBean.Comment comment = (CircleBean.DBean.ListBean.Comment)object;
+
+                        Intent intent = new Intent();
+                        intent.putExtra(NEW_COMMENT_DATA, comment);
+                        setResult(NEW_COMMENT, intent);
+
                         showToast(context,"评论成功");
                         finish();
                     }

+ 165 - 51
app/src/com/sheishuo/app/core_module/circle/activity/NewTweetingActivity.java

@@ -4,8 +4,12 @@ import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.util.Log;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -15,12 +19,17 @@ import android.widget.Toast;
 import com.bumptech.glide.Glide;
 import com.netease.nim.uikit.common.media.picker.PickImageHelper;
 import com.netease.nim.uikit.common.media.picker.model.PhotoInfo;
+import com.netease.nim.uikit.common.ui.dialog.DialogMaker;
+import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialog;
+import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialogHelper;
+import com.netease.nim.uikit.session.constant.Extras;
 import com.sheishuo.app.R;
 import com.sheishuo.app.cache.AccountCache;
 import com.sheishuo.app.core_module.circle.presenter.NewTweetPresenter;
 import com.sheishuo.app.common.util.img.ImgUtil;
 import com.sheishuo.app.common.util.net.NetStatus;
 import com.sheishuo.app.common.views.BaseToolbar;
+import com.sheishuo.app.core_module.trade.view.ui.activity.TradePublishActivity;
 import com.sheishuo.app.main.activity.MainActivity;
 import com.sheishuo.app.main.fragment.CircleOfFriendsFragment;
 import com.sheishuo.app.impl.SheishuoUI;
@@ -49,6 +58,8 @@ public class NewTweetingActivity extends SheishuoUI {
     private Toast toast = null;
 //    private static MainActivity activity;
 
+    private int maxNumImages = 9;
+
     public static void start(Context context) {
         start(context, null);
     }
@@ -112,17 +123,7 @@ public class NewTweetingActivity extends SheishuoUI {
         rightTxt.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                if (NetStatus.IS_BUSY){
-                    showToast("内容发布中,请稍后...");
-                }else {
-                    showToast("内容发布中...");
-                    getHandler().postDelayed(new Runnable() {
-                        @Override
-                        public void run() {
-                            presenter.publishNewTweeting(tweetContent.getText().toString(),photoIds);
-                        }
-                    },1000);
-                }
+                publish();
             }
         });
         toolbar.setRightItems(new View[]{rightTxt});
@@ -160,44 +161,16 @@ public class NewTweetingActivity extends SheishuoUI {
             }
 
             Bundle result = data.getExtras();
-            if (!result.getBoolean("from_local")) {
+            if (!result.getBoolean(Extras.EXTRA_FROM_LOCAL)) {
                 //照相机
-                String filePath = result.getString("file_path");
-                //移除添加图片按钮
-                imgsLayout.removeAllViews();
-
-                ImageView imageView = new ImageView(this);
-                imageView.setAdjustViewBounds(true);
-                int toDp = (int) ImgUtil.convertDpToPixel(128, context);
-                imageView.setLayoutParams(new LinearLayout.LayoutParams(toDp, toDp));
-                Glide.with(context).load(filePath)
-                        .centerCrop()
-                        .bitmapTransform(new ColorFilterTransformation(context, 0x7900CCCC))
-                        .into(imageView);
-                imgsLayout.addView(imageView);
-                selectedPhotoPathList.add(filePath);
-                presenter.uploadPhoto(filePath);
+                String filePath = result.getString(Extras.EXTRA_FILE_PATH);
+                createImageView(filePath);
             } else {
                 //相册
-
-                //移除添加图片按钮
-                imgsLayout.removeAllViews();
-
                 List<PhotoInfo> photoInfoList = (List<PhotoInfo>) result.getSerializable("photo_list");
                 for (PhotoInfo info : photoInfoList) {
-                    ImageView imageView = new ImageView(this);
-                    imageView.setAdjustViewBounds(true);
-                    int toDp = (int) ImgUtil.convertDpToPixel(128, context);
-                    imageView.setLayoutParams(new LinearLayout.LayoutParams(toDp, toDp));
-                    Glide.with(context).load(info.getFilePath())
-                            .centerCrop()
-                            .bitmapTransform(new ColorFilterTransformation(context, 0x7900CCCC))
-                            .into(imageView);
-                    imgsLayout.addView(imageView);
-                    selectedPhotoPathList.add(info.getAbsolutePath());
+                    createImageView(info.getAbsolutePath());
                 }
-
-                presenter.uploadPhoto(selectedPhotoPathList);
             }
 
         }
@@ -228,6 +201,82 @@ public class NewTweetingActivity extends SheishuoUI {
     }
 
 
+    private ImageView createImageView(String filePath)
+    {
+        int imgSize = (int) ImgUtil.convertDpToPixel(60, context);
+        selectedPhotoPathList.add(filePath);
+
+        final ImageView imageView = new ImageView(this);
+        imageView.setAdjustViewBounds(true);
+        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+        imageView.setLayoutParams(new ViewGroup.LayoutParams(imgSize, imgSize));
+        imageView.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() {
+
+                    @Override
+                    public void doCancelAction() {
+                    }
+
+                    @Override
+                    public void doOkAction() {
+                        for(int i=0; i<imgsLayout.getChildCount(); i++)
+                        {
+                            if(imgsLayout.getChildAt(i).equals(imageView))
+                            {
+                                imgsLayout.removeViewAt(i);
+                                selectedPhotoPathList.remove(i-1);
+                                break;
+                            }
+                        }
+                        checkAddImg();
+                    }
+                };
+
+                EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(NewTweetingActivity.this, null, "是否删除该图片", true, listener);
+                dialog.show();
+                return false;
+            }
+        });
+
+        Glide.with(context).load(filePath)
+                .into(imageView);
+        imgsLayout.addView(imageView);
+        checkAddImg();
+        return imageView;
+    }
+
+    private void checkAddImg()
+    {
+        if(imgsLayout.getChildCount() >= maxNumImages + 1)
+            addImg.setVisibility(View.GONE);
+        else
+            addImg.setVisibility(View.VISIBLE);
+    }
+
+    public void publish()
+    {
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                DialogMaker.showProgressDialog(NewTweetingActivity.this, "");
+
+                photoIds.clear();
+                presenter.uploadPhoto(selectedPhotoPathList, 0);
+            }
+        });
+    }
+
+    private void sendPublish()
+    {
+        getHandler().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                presenter.publishNewTweeting(tweetContent.getText().toString(), photoIds);
+            }
+        },100);
+    }
 
     public void onTweetSuccess() {
         showToast("发布成功");
@@ -241,10 +290,6 @@ public class NewTweetingActivity extends SheishuoUI {
         getHandler().post(new Runnable() {
             @Override
             public void run() {
-                ImageView imageView = (ImageView) imgsLayout.getChildAt(index);
-                String filePath = selectedPhotoPathList.get(index);
-                Glide.with(context).load(filePath).into(imageView);
-                Collections.synchronizedList(photoIds);
                 photoIds.add(photoId);
 
             }
@@ -252,20 +297,89 @@ public class NewTweetingActivity extends SheishuoUI {
 
     }
 
-
-    //全部照片上传完成
-    public void onAllPhotosUploaded(){
+    public void onPhotoUploadFailed(final int index)
+    {
         getHandler().post(new Runnable() {
             @Override
             public void run() {
-                //toolbar.getRightTV().setEnabled(true);
+                EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() {
+
+                    @Override
+                    public void doCancelAction() {
+                        DialogMaker.dismissProgressDialog();
+                    }
+
+                    @Override
+                    public void doOkAction() {
+                        presenter.uploadPhoto(selectedPhotoPathList, index);
+                    }
+                };
+
+                EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(NewTweetingActivity.this, null, "图片上传失败,是否重试?", true, listener);
+                dialog.show();
             }
         });
+
     }
 
+    //全部照片上传完成
+    public void onAllPhotosUploaded(){
+        sendPublish();
+    }
 
 
 
 
 
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+
+            // 获得当前得到焦点的View,一般情况下就是EditText(特殊情况就是轨迹求或者实体案件会移动焦点)
+            View v = getCurrentFocus();
+
+            if (isShouldHideInput(v, ev)) {
+                hideSoftInput(v.getWindowToken());
+            }
+        }
+        return super.dispatchTouchEvent(ev);
+    }
+
+    /**
+     * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时没必要隐藏
+     *
+     * @param v
+     * @param event
+     * @return
+     */
+    private boolean isShouldHideInput(View v, MotionEvent event) {
+        if (v != null && (v instanceof EditText)) {
+            int[] l = { 0, 0 };
+            v.getLocationInWindow(l);
+            int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left
+                    + v.getWidth();
+            if (event.getX() > left && event.getX() < right
+                    && event.getY() > top && event.getY() < bottom) {
+                // 点击EditText的事件,忽略它。
+                return false;
+            } else {
+                return true;
+            }
+        }
+        // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditView上,和用户用轨迹球选择其他的焦点
+        return false;
+    }
+
+    /**
+     * 多种隐藏软件盘方法的其中一种
+     *
+     * @param token
+     */
+    private void hideSoftInput(IBinder token) {
+        if (token != null) {
+            InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+            im.hideSoftInputFromWindow(token,
+                    InputMethodManager.HIDE_NOT_ALWAYS);
+        }
+    }
 }

+ 34 - 0
app/src/com/sheishuo/app/core_module/circle/model/NewTweetModel.java

@@ -80,6 +80,37 @@ public class NewTweetModel {
 
     }
 
+    public void uploadPhoto(final List<String> filesPathList, final int index)
+    {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+                if(index >= filesPathList.size()) {
+                    presenter.onAllPhotoUploaded();
+                    return;
+                }
+
+                net.uploadImgs(filesPathList.get(index), new ResponseCallback() {
+                    @Override
+                    public void onSuccess(Object object) {
+                        //Log.e("object", (String) object);
+                        presenter.showToast("第" + (index + 1) + "张照片上传完毕");
+                        presenter.onOnePhotoUploaded(index, (int) object);
+                        uploadPhoto(filesPathList, index+1);
+                    }
+
+                    @Override
+                    public void onFailed() {
+                        presenter.showToast("第" + (index + 1) + "张照片上传失败");
+                        presenter.onPhotoUploadFailed(index);
+                    }
+                });
+            }
+
+        }).start();
+    }
+
     public void publishNewTweeting(final String content,final List<Integer> photoIds){
         NetStatus.IS_BUSY = true;
         new Thread(new Runnable() {
@@ -103,6 +134,9 @@ public class NewTweetModel {
                         .add("id",accuont.getId())
                         .add("msg",content)
                         .add("local",accuont.getCity() + accuont.getDistrict())
+                        .add("province", accuont.getProvince())
+                        .add("city", accuont.getCity())
+                        .add("district", accuont.getDistrict())
                         .add("latitude",accuont.getLatitude())
                         .add("longitude",accuont.getLongitude())
                         .add("pic",pics)

+ 9 - 0
app/src/com/sheishuo/app/core_module/circle/presenter/NewTweetPresenter.java

@@ -30,6 +30,10 @@ public class NewTweetPresenter {
         model.uploadPhoto(filesPath);
     }
 
+    public void uploadPhoto(List<String> filesPath, int index){
+        model.uploadPhoto(filesPath, index);
+    }
+
     public void onOnePhotoUploaded(int index,int photoId){
         activity.onOnePhotoUploaded(index,photoId);
     }
@@ -42,6 +46,11 @@ public class NewTweetPresenter {
         model.publishNewTweeting(content,ids);
     }
 
+    public void onPhotoUploadFailed(int index)
+    {
+        activity.onPhotoUploadFailed(index);
+    }
+
     public void onPublishSuccess(){
         activity.onTweetSuccess();
     }

+ 120 - 0
app/src/com/sheishuo/app/core_module/friends/activity/BeFollowedActivity.java

@@ -0,0 +1,120 @@
+package com.sheishuo.app.core_module.friends.activity;
+
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.netease.nim.uikit.common.activity.UI;
+import com.netease.nim.uikit.contact.ContactsCustomization;
+import com.netease.nim.uikit.contact.core.item.AbsContactItem;
+import com.netease.nim.uikit.contact.core.viewholder.AbsContactViewHolder;
+import com.sheishuo.app.R;
+import com.sheishuo.app.common.beans.BeFollowedBean;
+import com.sheishuo.app.common.beans.RequestBean;
+import com.sheishuo.app.common.util.net.INet;
+import com.sheishuo.app.common.util.net.NetImpl;
+import com.sheishuo.app.common.util.net.ResponseCallback;
+import com.sheishuo.app.common.views.BaseToolbar;
+import com.sheishuo.app.core_module.friends.fragment.BeFollowedListFragment;
+import com.sheishuo.app.core_module.friends.fragment.FollowListFragment;
+import com.sheishuo.app.impl.SheishuoUI;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BeFollowedActivity extends SheishuoUI {
+
+    private LinearLayout layout;
+    private FragmentManager manager = getSupportFragmentManager();
+    private FragmentTransaction transaction;
+    private BaseToolbar toolbar;
+    private BeFollowedListFragment fragment;
+    public static BeFollowedBean beFollowedBean;
+    private INet net = new NetImpl();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_be_followed);
+        findViews();
+        init();
+    }
+
+    private void findViews() {
+        toolbar = findView(R.id.toolbar);
+        layout = findView(R.id.recent_contacts_list_layout);
+    }
+
+
+    private void init() {
+        beFollowedBean = null;
+        initToolbar();
+        addContactFragment();
+        fetchBeFollowBean();
+    }
+
+    private void initToolbar() {
+        toolbar.setTitle("我的粉丝");
+        toolbar.setBackOnClickListener(new View.OnClickListener(){
+            @Override
+            public void onClick(View view)
+            {
+                finish();
+            }
+        });
+    }
+
+    private void fetchBeFollowBean()
+    {
+        net.befollowedList(new ResponseCallback() {
+            @Override
+            public void onSuccess(Object object) {
+                beFollowedBean = (BeFollowedBean) object;
+                getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        fragment.followListUpdate();
+                    }
+                });
+            }
+
+            @Override
+            public void onFailed() {
+
+            }
+        });
+    }
+
+    private void addContactFragment() {
+        fragment = new BeFollowedListFragment();
+        fragment.setContainerId(R.id.recent_contacts_list_layout);
+
+        UI activity = this;
+
+        // 如果是activity从堆栈恢复,FM中已经存在恢复而来的fragment,此时会使用恢复来的,而new出来这个会被丢弃掉
+        fragment = (BeFollowedListFragment) activity.addFragment(fragment);
+
+        // 功能项定制
+        fragment.setContactsCustomization(new ContactsCustomization() {
+            @Override
+            public Class<? extends AbsContactViewHolder<? extends AbsContactItem>> onGetFuncViewHolderClass() {
+                return ContactsListActivity.FuncItem.FuncViewHolder.class;
+            }
+
+            @Override
+            public List<AbsContactItem> onGetFuncItems() {
+                return new ArrayList<AbsContactItem>();
+            }
+
+            @Override
+            public void onFuncItemClick(AbsContactItem item) {
+            }
+        });
+    }
+}

+ 64 - 4
app/src/com/sheishuo/app/core_module/friends/activity/ContactsListActivity.java

@@ -10,18 +10,30 @@ import android.view.View;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
+import android.widget.Toast;
 
+import com.netease.nim.uikit.NimUIKit;
 import com.netease.nim.uikit.common.activity.UI;
 import com.netease.nim.uikit.contact.ContactsCustomization;
 import com.netease.nim.uikit.contact.ContactsFragment;
 import com.netease.nim.uikit.contact.core.item.AbsContactItem;
 import com.netease.nim.uikit.contact.core.item.ItemTypes;
 import com.netease.nim.uikit.contact.core.model.ContactDataAdapter;
+import com.netease.nim.uikit.contact.core.model.IContact;
 import com.netease.nim.uikit.contact.core.viewholder.AbsContactViewHolder;
+import com.netease.nimlib.sdk.NIMClient;
+import com.netease.nimlib.sdk.msg.SystemMessageService;
+import com.netease.nimlib.sdk.uinfo.UserInfoProvider;
 import com.sheishuo.app.R;
 import com.sheishuo.app.cache.AccountCache;
+import com.sheishuo.app.cache.SocialInfoCache;
+import com.sheishuo.app.common.beans.RequestBean;
+import com.sheishuo.app.common.util.net.INet;
+import com.sheishuo.app.common.util.net.NetImpl;
+import com.sheishuo.app.common.util.net.ResponseCallback;
 import com.sheishuo.app.common.views.BaseToolbar;
 import com.sheishuo.app.contact.activity.BlackListActivity;
+import com.sheishuo.app.core_module.friends.fragment.FollowListFragment;
 import com.sheishuo.app.main.activity.RobotListActivity;
 import com.sheishuo.app.main.activity.SystemMessageActivity;
 import com.sheishuo.app.main.activity.TeamListActivity;
@@ -37,11 +49,15 @@ import java.util.List;
 
 public class ContactsListActivity extends SheishuoUI {
 
+    public final static String FRIEND_REQUEST = "friendRequest";
+
     private LinearLayout layout;
     private FragmentManager manager = getSupportFragmentManager();
     private FragmentTransaction transaction;
     private BaseToolbar toolbar;
-    private ContactsFragment fragment;
+    private FollowListFragment fragment;
+    public static RequestBean requestBean;
+    private INet net = new NetImpl();
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -49,6 +65,7 @@ public class ContactsListActivity extends SheishuoUI {
         setContentView(R.layout.contacts_list_activity);
         findViews();
         init();
+
     }
 
     private void findViews() {
@@ -62,6 +79,11 @@ public class ContactsListActivity extends SheishuoUI {
         addContactFragment();
     }
 
+    @Override
+    protected void onResume() {
+        super.onResume();
+        fetchFollowList();
+    }
 
     private void initToolbar() {
         toolbar.setTitle("通讯录");
@@ -74,14 +96,35 @@ public class ContactsListActivity extends SheishuoUI {
         });
     }
 
+    private void fetchFollowList()
+    {
+        net.followList(new ResponseCallback() {
+            @Override
+            public void onSuccess(Object object) {
+                getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        fragment.followListUpdate();
+                    }
+                });
+
+            }
+
+            @Override
+            public void onFailed() {
+
+            }
+        });
+    }
+
     private void addContactFragment() {
-        fragment = new ContactsFragment();
+        fragment = new FollowListFragment();
         fragment.setContainerId(R.id.recent_contacts_list_layout);
 
         UI activity = this;
 
         // 如果是activity从堆栈恢复,FM中已经存在恢复而来的fragment,此时会使用恢复来的,而new出来这个会被丢弃掉
-        fragment = (ContactsFragment) activity.addFragment(fragment);
+        fragment = (FollowListFragment) activity.addFragment(fragment);
 
         // 功能项定制
         fragment.setContactsCustomization(new ContactsCustomization() {
@@ -111,6 +154,7 @@ public class ContactsListActivity extends SheishuoUI {
         static final FuncItem BLACK_LIST = new FuncItem();
         static final FuncItem MY_COMPUTER = new FuncItem();
         static final FuncItem PHONE_CONTACTS = new FuncItem();
+        static final FuncItem BEFOLLOWED = new FuncItem();
 
         @Override
         public int getItemType() {
@@ -142,11 +186,20 @@ public class ContactsListActivity extends SheishuoUI {
                     funcName.setText("新的朋友");
                     image.setImageResource(R.drawable.icon_new_friends);
                     image.setScaleType(ImageView.ScaleType.FIT_XY);
+                    if(ContactsListActivity.requestBean != null)
+                    {
+                        int count = NIMClient.getService(SystemMessageService.class).querySystemMessageUnreadCountBlock() + ContactsListActivity.requestBean.getD().size();
+                        updateUnreadNum(count);
+                    }
                 }
 //                else if (item == NORMAL_TEAM) {
 //                    funcName.setText("讨论组");
 //                    image.setImageResource(R.drawable.ic_secretary);
 //                }
+                else if (item == BEFOLLOWED) {
+                    funcName.setText("我的粉丝");
+                    image.setImageResource(R.drawable.icon_new_follow);
+                }
                 else if (item == ADVANCED_TEAM) {
                     funcName.setText("群组");
                     image.setImageResource(R.drawable.icon_groups);
@@ -171,7 +224,7 @@ public class ContactsListActivity extends SheishuoUI {
 
             private void updateUnreadNum(int unreadCount) {
                 // 2.*版本viewholder复用问题
-                if (unreadCount > 0 && funcName.getText().toString().equals("验证提醒")) {
+                if (unreadCount > 0 && funcName.getText().toString().equals("新的朋友")) {
                     unreadNum.setVisibility(View.VISIBLE);
                     unreadNum.setText("" + unreadCount);
                 } else {
@@ -183,6 +236,7 @@ public class ContactsListActivity extends SheishuoUI {
         static List<AbsContactItem> provide() {
             List<AbsContactItem> items = new ArrayList<AbsContactItem>();
             items.add(VERIFY);
+            items.add(BEFOLLOWED);
 //            items.add(ROBOT);
 //            items.add(NORMAL_TEAM);
             items.add(ADVANCED_TEAM);
@@ -196,6 +250,8 @@ public class ContactsListActivity extends SheishuoUI {
         static void handle(Context context, AbsContactItem item) {
             if (item == VERIFY) {
                 SystemMessageActivity.start(context);
+            } else if (item == BEFOLLOWED){
+                context.startActivity(new Intent(context, BeFollowedActivity.class));
             } else if (item == ROBOT) {
                 RobotListActivity.start(context);
             } else if (item == NORMAL_TEAM) {
@@ -211,4 +267,8 @@ public class ContactsListActivity extends SheishuoUI {
             }
         }
     }
+
+
+
+
 }

+ 528 - 0
app/src/com/sheishuo/app/core_module/friends/activity/FollowSelectActivity.java

@@ -0,0 +1,528 @@
+package com.sheishuo.app.core_module.friends.activity;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.SearchView;
+import android.text.TextUtils;
+import android.util.TypedValue;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.GridView;
+import android.widget.HorizontalScrollView;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.netease.nim.uikit.R;
+import com.netease.nim.uikit.common.activity.UI;
+import com.netease.nim.uikit.common.ui.liv.LetterIndexView;
+import com.netease.nim.uikit.common.ui.liv.LivIndex;
+import com.netease.nim.uikit.contact.core.item.AbsContactItem;
+import com.netease.nim.uikit.contact.core.item.ContactItem;
+import com.netease.nim.uikit.contact.core.item.ContactItemFilter;
+import com.netease.nim.uikit.contact.core.item.ItemTypes;
+import com.netease.nim.uikit.contact.core.model.ContactGroupStrategy;
+import com.netease.nim.uikit.contact.core.model.IContact;
+import com.netease.nim.uikit.contact.core.provider.ContactDataProvider;
+import com.netease.nim.uikit.contact.core.provider.TeamMemberDataProvider;
+import com.netease.nim.uikit.contact.core.query.IContactDataProvider;
+import com.netease.nim.uikit.contact.core.query.TextQuery;
+import com.netease.nim.uikit.contact.core.viewholder.LabelHolder;
+import com.netease.nim.uikit.contact_selector.activity.ContactSelectActivity;
+import com.netease.nim.uikit.contact_selector.adapter.ContactSelectAdapter;
+import com.netease.nim.uikit.contact_selector.adapter.ContactSelectAvatarAdapter;
+import com.netease.nim.uikit.contact_selector.viewholder.ContactsMultiSelectHolder;
+import com.netease.nim.uikit.contact_selector.viewholder.ContactsSelectHolder;
+import com.netease.nim.uikit.model.ToolBarOptions;
+import com.sheishuo.app.core_module.friends.provider.FollowDataProvider;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 联系人选择器
+ * <p/>
+ * Created by huangjun on 2015/3/3.
+ */
+public class FollowSelectActivity extends UI implements View.OnClickListener, SearchView.OnQueryTextListener {
+
+    public static final String EXTRA_DATA = "EXTRA_DATA"; // 请求数据:Option
+    public static final String RESULT_DATA = "RESULT_DATA"; // 返回结果
+
+    // adapter
+
+    private ContactSelectAdapter contactAdapter;
+
+    private ContactSelectAvatarAdapter contactSelectedAdapter;
+
+    // view
+
+    private ListView listView;
+
+    private LivIndex livIndex;
+
+    private RelativeLayout bottomPanel;
+
+    private HorizontalScrollView scrollViewSelected;
+
+    private GridView imageSelectedGridView;
+
+    private Button btnSelect;
+
+    private SearchView searchView;
+
+    // other
+
+    private String queryText;
+
+    private ContactSelectActivity.Option option;
+
+    // class
+
+    private static class ContactsSelectGroupStrategy extends ContactGroupStrategy {
+        public ContactsSelectGroupStrategy() {
+            add(ContactGroupStrategy.GROUP_NULL, -1, "");
+            addABC(0);
+        }
+    }
+
+    public static void startActivityForResult(Context context, ContactSelectActivity.Option option, int requestCode) {
+        Intent intent = new Intent();
+        intent.putExtra(EXTRA_DATA, option);
+        intent.setClass(context, FollowSelectActivity.class);
+
+        ((Activity) context).startActivityForResult(intent, requestCode);
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (searchView != null) {
+            searchView.setQuery("", true);
+            searchView.setIconified(true);
+        }
+        showKeyboard(false);
+        finish();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(android.view.Menu menu) {
+        // search view
+        getMenuInflater().inflate(R.menu.contacts_search_menu, menu);
+        MenuItem item = menu.findItem(R.id.action_search);
+        if (!option.searchVisible) {
+            item.setVisible(false);
+            return true;
+        }
+
+        MenuItemCompat.setOnActionExpandListener(item, new MenuItemCompat.OnActionExpandListener() {
+
+            @Override
+            public boolean onMenuItemActionExpand(MenuItem menuItem) {
+                return true;
+            }
+
+            @Override
+            public boolean onMenuItemActionCollapse(MenuItem menuItem) {
+                finish();
+                return false;
+            }
+        });
+        SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
+        this.searchView = searchView;
+        this.searchView.setVisibility(option.searchVisible ? View.VISIBLE : View.GONE);
+        searchView.setOnQueryTextListener(this);
+        return true;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.nim_contacts_select);
+
+        ToolBarOptions options = new ToolBarOptions();
+        setToolBar(R.id.toolbar, options);
+
+        parseIntentData();
+        initAdapter();
+        initListView();
+        initContactSelectArea();
+
+        loadData();
+    }
+
+    private void parseIntentData() {
+        this.option = (ContactSelectActivity.Option) getIntent().getSerializableExtra(EXTRA_DATA);
+        if (TextUtils.isEmpty(option.maxSelectedTip)) {
+            option.maxSelectedTip = "最多选择" + option.maxSelectNum + "人";
+        }
+        if (TextUtils.isEmpty(option.minSelectedTip)) {
+            option.minSelectedTip = "至少选择" + option.minSelectNum + "人";
+        }
+        setTitle(option.title);
+    }
+
+    private class ContactDataProviderEx extends ContactDataProvider {
+        private String teamId;
+
+        private boolean loadedTeamMember = false;
+
+        public ContactDataProviderEx(String teamId, int... itemTypes) {
+            super(itemTypes);
+            this.teamId = teamId;
+        }
+
+        @Override
+        public List<AbsContactItem> provide(TextQuery query) {
+            List<AbsContactItem> data = new ArrayList<>();
+            // 异步加载
+            if (!loadedTeamMember) {
+                TeamMemberDataProvider.loadTeamMemberDataAsync(teamId, new TeamMemberDataProvider.LoadTeamMemberCallback() {
+                    @Override
+                    public void onResult(boolean success) {
+                        if (success) {
+                            loadedTeamMember = true;
+                            // 列表重新加载数据
+                            loadData();
+                        }
+                    }
+                });
+            } else {
+                data = TeamMemberDataProvider.provide(query, teamId);
+            }
+            return data;
+        }
+    }
+
+    private void initAdapter() {
+        IContactDataProvider dataProvider = new FollowDataProvider();
+
+        // contact adapter
+        contactAdapter = new ContactSelectAdapter(FollowSelectActivity.this, new ContactsSelectGroupStrategy(),
+                dataProvider) {
+            boolean isEmptyContacts = false;
+
+            @Override
+            protected List<AbsContactItem> onNonDataItems() {
+                return null;
+            }
+
+            @Override
+            protected void onPostLoad(boolean empty, String queryText, boolean all) {
+                if (empty) {
+                    if (TextUtils.isEmpty(queryText)) {
+                        isEmptyContacts = true;
+                    }
+                    updateEmptyView(queryText);
+                } else {
+                    setSearchViewVisible(true);
+                }
+            }
+
+            private void updateEmptyView(String queryText) {
+                if (!isEmptyContacts && !TextUtils.isEmpty(queryText)) {
+                    setSearchViewVisible(true);
+                } else {
+                    setSearchViewVisible(false);
+                }
+            }
+
+            private void setSearchViewVisible(boolean visible) {
+                option.searchVisible = visible;
+                if (searchView != null) {
+                    searchView.setVisibility(option.searchVisible ? View.VISIBLE : View.GONE);
+                }
+            }
+        };
+
+        Class c = option.multi ? ContactsMultiSelectHolder.class : ContactsSelectHolder.class;
+        contactAdapter.addViewHolder(ItemTypes.LABEL, LabelHolder.class);
+        contactAdapter.addViewHolder(ItemTypes.FRIEND, c);
+        contactAdapter.addViewHolder(ItemTypes.TEAM_MEMBER, c);
+        contactAdapter.addViewHolder(ItemTypes.TEAM, c);
+        contactAdapter.addViewHolder(ItemTypes.FOLLOW, c);
+
+        contactAdapter.setFilter(option.itemFilter);
+        contactAdapter.setDisableFilter(option.itemDisableFilter);
+
+        // contact select adapter
+        contactSelectedAdapter = new ContactSelectAvatarAdapter(this);
+    }
+
+    private void initListView() {
+        listView = findView(R.id.contact_list_view);
+        listView.setAdapter(contactAdapter);
+        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+                showKeyboard(false);
+            }
+
+            @Override
+            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+
+            }
+        });
+        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                position = position - listView.getHeaderViewsCount();
+                AbsContactItem item = (AbsContactItem) contactAdapter.getItem(position);
+
+                if (item == null) {
+                    return;
+                }
+
+                if (option.multi) {
+                    if (!contactAdapter.isEnabled(position)) {
+                        return;
+                    }
+                    IContact contact = null;
+                    if (item instanceof ContactItem) {
+                        contact = ((ContactItem) item).getContact();
+                    }
+                    if (contactAdapter.isSelected(position)) {
+                        contactAdapter.cancelItem(position);
+                        if (contact != null) {
+                            contactSelectedAdapter.removeContact(contact);
+                        }
+                    } else {
+                        if (contactSelectedAdapter.getCount() <= option.maxSelectNum) {
+                            contactAdapter.selectItem(position);
+                            if (contact != null) {
+                                contactSelectedAdapter.addContact(contact);
+                            }
+                        } else {
+                            Toast.makeText(FollowSelectActivity.this, option.maxSelectedTip, Toast.LENGTH_SHORT).show();
+                        }
+
+                        if (!TextUtils.isEmpty(queryText) && searchView != null) {
+                            searchView.setQuery("", true);
+                            searchView.setIconified(true);
+                            showKeyboard(false);
+                        }
+                    }
+                    arrangeSelected();
+                } else {
+                    if (item instanceof ContactItem) {
+                        final IContact contact = ((ContactItem) item).getContact();
+                        ArrayList<String> selectedIds = new ArrayList<>();
+                        selectedIds.add(contact.getContactId());
+                        onSelected(selectedIds);
+                    }
+
+                    arrangeSelected();
+                }
+            }
+        });
+
+        // 字母导航
+        TextView letterHit = (TextView) findViewById(R.id.tv_hit_letter);
+        LetterIndexView idxView = (LetterIndexView) findViewById(R.id.liv_index);
+        idxView.setLetters(getResources().getStringArray(R.array.letter_list2));
+        ImageView imgBackLetter = (ImageView) findViewById(R.id.img_hit_letter);
+        if (option.type != ContactSelectActivity.ContactSelectType.TEAM) {
+            livIndex = contactAdapter.createLivIndex(listView, idxView, letterHit, imgBackLetter);
+            livIndex.show();
+        } else {
+            idxView.setVisibility(View.GONE);
+        }
+    }
+
+    private void initContactSelectArea() {
+        btnSelect = (Button) findViewById(R.id.btnSelect);
+        if (!option.allowSelectEmpty) {
+            btnSelect.setEnabled(false);
+        } else {
+            btnSelect.setEnabled(true);
+        }
+        btnSelect.setOnClickListener(this);
+        bottomPanel = (RelativeLayout) findViewById(R.id.rlCtrl);
+        scrollViewSelected = (HorizontalScrollView) findViewById(R.id.contact_select_area);
+        if (option.multi) {
+            bottomPanel.setVisibility(View.VISIBLE);
+            if (option.showContactSelectArea) {
+                scrollViewSelected.setVisibility(View.VISIBLE);
+                btnSelect.setVisibility(View.VISIBLE);
+            } else {
+                scrollViewSelected.setVisibility(View.GONE);
+                btnSelect.setVisibility(View.GONE);
+            }
+            btnSelect.setText(getOKBtnText(0));
+        } else {
+            bottomPanel.setVisibility(View.GONE);
+        }
+
+        // selected contact image banner
+        imageSelectedGridView = (GridView) findViewById(R.id.contact_select_area_grid);
+        imageSelectedGridView.setAdapter(contactSelectedAdapter);
+        notifySelectAreaDataSetChanged();
+        imageSelectedGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                try {
+                    if (contactSelectedAdapter.getItem(position) == null) {
+                        return;
+                    }
+
+                    IContact iContact = contactSelectedAdapter.remove(position);
+                    if (iContact != null) {
+                        contactAdapter.cancelItem(iContact);
+                    }
+                    arrangeSelected();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+
+        // init already selected items
+        List<String> selectedUids = option.alreadySelectedAccounts;
+        if (selectedUids != null && !selectedUids.isEmpty()) {
+            contactAdapter.setAlreadySelectedAccounts(selectedUids);
+            List<ContactItem> selectedItems = contactAdapter.getSelectedItem();
+            for (ContactItem item : selectedItems) {
+                contactSelectedAdapter.addContact(item.getContact());
+            }
+            arrangeSelected();
+        }
+    }
+
+    private void loadData() {
+        contactAdapter.load(true);
+    }
+
+    private void arrangeSelected() {
+        this.contactAdapter.notifyDataSetChanged();
+        if (option.multi) {
+            int count = contactSelectedAdapter.getCount();
+            if (!option.allowSelectEmpty) {
+                btnSelect.setEnabled(count > 1);
+            } else {
+                btnSelect.setEnabled(true);
+            }
+            btnSelect.setText(getOKBtnText(count));
+            notifySelectAreaDataSetChanged();
+        }
+    }
+
+    private void notifySelectAreaDataSetChanged() {
+        int converViewWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 46, this.getResources()
+                .getDisplayMetrics()));
+        ViewGroup.LayoutParams layoutParams = imageSelectedGridView.getLayoutParams();
+        layoutParams.width = converViewWidth * contactSelectedAdapter.getCount();
+        layoutParams.height = converViewWidth;
+        imageSelectedGridView.setLayoutParams(layoutParams);
+        imageSelectedGridView.setNumColumns(contactSelectedAdapter.getCount());
+
+        try {
+            final int x = layoutParams.width;
+            final int y = layoutParams.height;
+            new Handler().post(new Runnable() {
+                @Override
+                public void run() {
+                    scrollViewSelected.scrollTo(x, y);
+                }
+            });
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        contactSelectedAdapter.notifyDataSetChanged();
+    }
+
+    private String getOKBtnText(int count) {
+        String caption = getString(R.string.ok);
+        int showCount = (count < 1 ? 0 : (count - 1));
+        StringBuilder sb = new StringBuilder(caption);
+        sb.append(" (");
+        sb.append(showCount);
+        if (option.maxSelectNumVisible) {
+            sb.append("/");
+            sb.append(option.maxSelectNum);
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+
+    /**
+     * ************************** select ************************
+     */
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.btnSelect) {
+            List<IContact> contacts = contactSelectedAdapter
+                    .getSelectedContacts();
+            if (option.allowSelectEmpty || checkMinMaxSelection(contacts.size())) {
+                ArrayList<String> selectedAccounts = new ArrayList<>();
+                for (IContact c : contacts) {
+                    selectedAccounts.add(c.getContactId());
+                }
+                onSelected(selectedAccounts);
+            }
+
+        }
+    }
+
+    private boolean checkMinMaxSelection(int selected) {
+        if (option.minSelectNum > selected) {
+            return showMaxMinSelectTip(true);
+        } else if (option.maxSelectNum < selected) {
+            return showMaxMinSelectTip(false);
+        }
+        return true;
+    }
+
+    private boolean showMaxMinSelectTip(boolean min) {
+        if (min) {
+            Toast.makeText(this, option.minSelectedTip, Toast.LENGTH_SHORT).show();
+        } else {
+            Toast.makeText(this, option.maxSelectedTip, Toast.LENGTH_SHORT).show();
+        }
+        return false;
+    }
+
+    public void onSelected(ArrayList<String> selects) {
+        Intent intent = new Intent();
+        intent.putStringArrayListExtra(RESULT_DATA, selects);
+        setResult(Activity.RESULT_OK, intent);
+        this.finish();
+    }
+
+    /**
+     * ************************* search ******************************
+     */
+
+    @Override
+    public boolean onQueryTextChange(String query) {
+        queryText = query;
+        if (TextUtils.isEmpty(query)) {
+            this.contactAdapter.load(true);
+        } else {
+            this.contactAdapter.query(query);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onQueryTextSubmit(String arg0) {
+        return false;
+    }
+
+    @Override
+    public void finish() {
+        showKeyboard(false);
+        super.finish();
+    }
+}

+ 470 - 0
app/src/com/sheishuo/app/core_module/friends/fragment/BeFollowedListFragment.java

@@ -0,0 +1,470 @@
+package com.sheishuo.app.core_module.friends.fragment;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.netease.nim.uikit.LoginSyncDataStatusObserver;
+import com.netease.nim.uikit.NimUIKit;
+import com.netease.nim.uikit.OnlineStateChangeListener;
+import com.netease.nim.uikit.R;
+import com.netease.nim.uikit.UIKitLogTag;
+import com.netease.nim.uikit.cache.FriendDataCache;
+import com.netease.nim.uikit.common.fragment.TFragment;
+import com.netease.nim.uikit.common.ui.liv.LetterIndexView;
+import com.netease.nim.uikit.common.ui.liv.LivIndex;
+import com.netease.nim.uikit.common.util.log.LogUtil;
+import com.netease.nim.uikit.contact.ContactsCustomization;
+import com.netease.nim.uikit.contact.core.item.AbsContactItem;
+import com.netease.nim.uikit.contact.core.item.ContactItem;
+import com.netease.nim.uikit.contact.core.item.ItemTypes;
+import com.netease.nim.uikit.contact.core.model.ContactDataAdapter;
+import com.netease.nim.uikit.contact.core.model.ContactGroupStrategy;
+import com.netease.nim.uikit.contact.core.query.IContactDataProvider;
+import com.netease.nim.uikit.contact.core.viewholder.LabelHolder;
+import com.netease.nim.uikit.contact.core.viewholder.OnlineStateContactHolder;
+import com.netease.nim.uikit.uinfo.UserInfoHelper;
+import com.netease.nim.uikit.uinfo.UserInfoObservable;
+import com.netease.nimlib.sdk.Observer;
+import com.sheishuo.app.core_module.friends.item.FollowItem;
+import com.sheishuo.app.core_module.friends.provider.BeFollowedDataProvider;
+import com.sheishuo.app.core_module.friends.provider.FollowDataProvider;
+import com.sheishuo.app.core_module.friends.viewholder.FollowContactHolder;
+import com.sheishuo.app.core_module.mine.view.ui.activity.UserInfoDetailActivity;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
+
+
+/**
+ * 通讯录Fragment
+ * <p/>
+ * Created by huangjun on 2015/9/7.
+ */
+public class BeFollowedListFragment extends TFragment {
+
+    private ContactDataAdapter adapter;
+
+    private ListView listView;
+
+    private TextView countText;
+
+    private LivIndex litterIdx;
+
+    private View loadingFrame;
+
+    private ContactsCustomization customization;
+
+    private ReloadFrequencyControl reloadControl = new ReloadFrequencyControl();
+
+    public void setContactsCustomization(ContactsCustomization customization) {
+        this.customization = customization;
+    }
+
+    private static final class ContactsGroupStrategy extends ContactGroupStrategy {
+        public ContactsGroupStrategy() {
+            add(ContactGroupStrategy.GROUP_NULL, -1, "");
+            addABC(0);
+        }
+    }
+
+    /**
+     * ***************************************** 生命周期 *****************************************
+     */
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.nim_contacts, container, false);
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        // 界面初始化
+        initAdapter();
+        findViews();
+        buildLitterIdx(getView());
+
+        // 注册观察者
+        registerObserver(true);
+        registerOnlineStateChangeListener(true);
+        // 加载本地数据
+        reload(false);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        registerObserver(false);
+        registerOnlineStateChangeListener(false);
+    }
+
+    public void followListUpdate()
+    {
+        reload(false);
+    }
+
+    private void initAdapter() {
+        IContactDataProvider dataProvider = new BeFollowedDataProvider();
+
+        adapter = new ContactDataAdapter(getActivity(), new ContactsGroupStrategy(), dataProvider) {
+            @Override
+            protected List<AbsContactItem> onNonDataItems() {
+                if (customization != null) {
+                    return customization.onGetFuncItems();
+                }
+
+                return new ArrayList<>();
+            }
+
+            @Override
+            protected void onPreReady() {
+                loadingFrame.setVisibility(View.VISIBLE);
+            }
+
+            @Override
+            protected void onPostLoad(boolean empty, String queryText, boolean all) {
+                loadingFrame.setVisibility(View.GONE);
+//                int userCount = SocialInfoCache.followList().size();
+//                countText.setText("共关注谁说用户" + userCount + "名");
+                countText.setText("");
+                onReloadCompleted();
+            }
+        };
+
+        adapter.addViewHolder(ItemTypes.LABEL, LabelHolder.class);
+        if (customization != null) {
+            adapter.addViewHolder(ItemTypes.FUNC, customization.onGetFuncViewHolderClass());
+        }
+        adapter.addViewHolder(ItemTypes.FRIEND, OnlineStateContactHolder.class);
+        adapter.addViewHolder(ItemTypes.FOLLOW, FollowContactHolder.class);
+
+    }
+
+    private void findViews() {
+        // loading
+        loadingFrame = findView(R.id.contact_loading_frame);
+
+        // count
+        View countLayout = View.inflate(getView().getContext(), R.layout.nim_contacts_count_item, null);
+        countLayout.setClickable(false);
+        countText = (TextView) countLayout.findViewById(R.id.contactCountText);
+
+        // ListView
+        listView = findView(R.id.contact_list_view);
+        listView.addFooterView(countLayout); // 注意:addFooter要放在setAdapter之前,否则旧版本手机可能会add不上
+        listView.setAdapter(adapter);
+        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
+
+            @Override
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+
+            }
+
+            @Override
+            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+
+            }
+        });
+
+        ContactItemClickListener listener = new ContactItemClickListener();
+        listView.setOnItemClickListener(listener);
+        listView.setOnItemLongClickListener(listener);
+
+        // ios style
+        OverScrollDecoratorHelper.setUpOverScroll(listView);
+    }
+
+    private void buildLitterIdx(View view) {
+        LetterIndexView livIndex = (LetterIndexView) view.findViewById(R.id.liv_index);
+        livIndex.setNormalColor(getResources().getColor(R.color.contacts_letters_color));
+        ImageView imgBackLetter = (ImageView) view.findViewById(R.id.img_hit_letter);
+        TextView litterHit = (TextView) view.findViewById(R.id.tv_hit_letter);
+        litterIdx = adapter.createLivIndex(listView, livIndex, litterHit, imgBackLetter);
+
+        litterIdx.show();
+    }
+
+    private final class ContactItemClickListener implements OnItemClickListener, OnItemLongClickListener {
+
+        @Override
+        public void onItemClick(AdapterView<?> parent, View view, int position,
+                                long id) {
+            AbsContactItem item = (AbsContactItem) adapter.getItem(position);
+            if (item == null) {
+                return;
+            }
+
+            int type = item.getItemType();
+
+            if (type == ItemTypes.FUNC && customization != null) {
+                customization.onFuncItemClick(item);
+                return;
+            }
+
+            if (type == ItemTypes.FRIEND && item instanceof ContactItem && NimUIKit.getContactEventListener() != null) {
+                NimUIKit.getContactEventListener().onItemClick(getActivity(), (((ContactItem) item).getContact()).getContactId());
+            }
+
+            if (type == ItemTypes.FOLLOW)
+            {
+                UserInfoDetailActivity.start(getContext(), ((FollowItem)item).getContact().getContactId());
+            }
+        }
+
+        @Override
+        public boolean onItemLongClick(AdapterView<?> parent, View view,
+                                       int position, long id) {
+            AbsContactItem item = (AbsContactItem) adapter.getItem(position);
+            if (item == null) {
+                return false;
+            }
+
+            if (item instanceof ContactItem && NimUIKit.getContactEventListener() != null) {
+                NimUIKit.getContactEventListener().onItemLongClick(getActivity(), (((ContactItem) item).getContact()).getContactId());
+            }
+
+            return true;
+        }
+    }
+
+    public void scrollToTop() {
+        if (listView != null) {
+            int top = listView.getFirstVisiblePosition();
+            int bottom = listView.getLastVisiblePosition();
+            if (top >= (bottom - top)) {
+                listView.setSelection(bottom - top);
+                listView.smoothScrollToPosition(0);
+            } else {
+                listView.smoothScrollToPosition(0);
+            }
+        }
+    }
+
+    /**
+     * *********************************** 通讯录加载控制 *******************************
+     */
+
+    /**
+     * 加载通讯录数据并刷新
+     *
+     * @param reload true则重新加载数据;false则判断当前数据源是否空,若空则重新加载,不空则不加载
+     */
+    private void reload(boolean reload) {
+        if (!reloadControl.canDoReload(reload)) {
+            return;
+        }
+
+        if (adapter == null) {
+            if (getActivity() == null) {
+                return;
+            }
+
+            initAdapter();
+        }
+
+        // 开始加载
+        if (!adapter.load(reload)) {
+            // 如果不需要加载,则直接当完成处理
+            onReloadCompleted();
+        }
+    }
+
+    private void onReloadCompleted() {
+        if (reloadControl.continueDoReloadWhenCompleted()) {
+            // 计划下次加载,稍有延迟
+            getHandler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    boolean reloadParam = reloadControl.getReloadParam();
+                    Log.i(UIKitLogTag.CONTACT, "continue reload " + reloadParam);
+                    reloadControl.resetStatus();
+                    reload(reloadParam);
+                }
+            }, 50);
+        } else {
+            // 本次加载完成
+            reloadControl.resetStatus();
+        }
+
+        LogUtil.i(UIKitLogTag.CONTACT, "contact load completed");
+    }
+
+    /**
+     * 通讯录加载频率控制
+     */
+    class ReloadFrequencyControl {
+        boolean isReloading = false;
+        boolean needReload = false;
+        boolean reloadParam = false;
+
+        boolean canDoReload(boolean param) {
+            if (isReloading) {
+                // 正在加载,那么计划加载完后重载
+                needReload = true;
+                if (param) {
+                    // 如果加载过程中又有多次reload请求,多次参数只要有true,那么下次加载就是reload(true);
+                    reloadParam = true;
+                }
+                LogUtil.i(UIKitLogTag.CONTACT, "pending reload task");
+
+                return false;
+            } else {
+                // 如果当前空闲,那么立即开始加载
+                isReloading = true;
+                return true;
+            }
+        }
+
+        boolean continueDoReloadWhenCompleted() {
+            return needReload;
+        }
+
+        void resetStatus() {
+            isReloading = false;
+            needReload = false;
+            reloadParam = false;
+        }
+
+        boolean getReloadParam() {
+            return reloadParam;
+        }
+    }
+
+    /**
+     * *********************************** 用户资料、好友关系变更、登录数据同步完成观察者 *******************************
+     */
+
+    private void registerObserver(boolean register) {
+        if (register) {
+            UserInfoHelper.registerObserver(userInfoObserver);
+        } else {
+            UserInfoHelper.unregisterObserver(userInfoObserver);
+        }
+
+        FriendDataCache.getInstance().registerFriendDataChangedObserver(friendDataChangedObserver, register);
+
+        LoginSyncDataStatusObserver.getInstance().observeSyncDataCompletedEvent(loginSyncCompletedObserver);
+    }
+
+    FriendDataCache.FriendDataChangedObserver friendDataChangedObserver = new FriendDataCache.FriendDataChangedObserver() {
+        @Override
+        public void onAddedOrUpdatedFriends(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onAddedOrUpdatedFriends", true);
+        }
+
+        @Override
+        public void onDeletedFriends(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onDeletedFriends", true);
+        }
+
+        @Override
+        public void onAddUserToBlackList(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onAddUserToBlackList", true);
+        }
+
+        @Override
+        public void onRemoveUserFromBlackList(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onRemoveUserFromBlackList", true);
+        }
+    };
+
+    private UserInfoObservable.UserInfoObserver userInfoObserver = new UserInfoObservable.UserInfoObserver() {
+        @Override
+        public void onUserInfoChanged(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onUserInfoChanged", true, false); // 非好友资料变更,不用刷新界面
+        }
+    };
+
+    private Observer<Void> loginSyncCompletedObserver = new Observer<Void>() {
+        @Override
+        public void onEvent(Void aVoid) {
+            getHandler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    reloadWhenDataChanged(null, "onLoginSyncCompleted", false);
+                }
+            }, 50);
+        }
+    };
+
+    private void reloadWhenDataChanged(List<String> accounts, String reason, boolean reload) {
+        reloadWhenDataChanged(accounts, reason, reload, true);
+    }
+
+    private void reloadWhenDataChanged(List<String> accounts, String reason, boolean reload, boolean force) {
+        if (accounts == null || accounts.isEmpty()) {
+            return;
+        }
+
+        boolean needReload = false;
+        if (!force) {
+            // 非force:与通讯录无关的(非好友)变更通知,去掉
+            for (String account : accounts) {
+                if (FriendDataCache.getInstance().isMyFriend(account)) {
+                    needReload = true;
+                    break;
+                }
+            }
+        } else {
+            needReload = true;
+        }
+
+        if (!needReload) {
+            Log.d(UIKitLogTag.CONTACT, "no need to reload contact");
+            return;
+        }
+
+        // log
+        StringBuilder sb = new StringBuilder();
+        sb.append("ContactFragment received data changed as [" + reason + "] : ");
+        if (accounts != null && !accounts.isEmpty()) {
+            for (String account : accounts) {
+                sb.append(account);
+                sb.append(" ");
+            }
+            sb.append(", changed size=" + accounts.size());
+        }
+        Log.i(UIKitLogTag.CONTACT, sb.toString());
+
+        // reload
+        reload(reload);
+    }
+
+    /**
+     * *********************************** 在线状态 *******************************
+     */
+
+    OnlineStateChangeListener onlineStateChangeListener = new OnlineStateChangeListener() {
+        @Override
+        public void onlineStateChange(Set<String> accounts) {
+            // 更新
+            adapter.notifyDataSetChanged();
+        }
+    };
+
+    private void registerOnlineStateChangeListener(boolean register) {
+        if (!NimUIKit.enableOnlineState()) {
+            return;
+        }
+        if (register) {
+            NimUIKit.addOnlineStateChangeListeners(onlineStateChangeListener);
+        } else {
+            NimUIKit.removeOnlineStateChangeListeners(onlineStateChangeListener);
+        }
+    }
+}

+ 479 - 0
app/src/com/sheishuo/app/core_module/friends/fragment/FollowListFragment.java

@@ -0,0 +1,479 @@
+package com.sheishuo.app.core_module.friends.fragment;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.netease.nim.uikit.LoginSyncDataStatusObserver;
+import com.netease.nim.uikit.NimUIKit;
+import com.netease.nim.uikit.OnlineStateChangeListener;
+import com.netease.nim.uikit.R;
+import com.netease.nim.uikit.UIKitLogTag;
+import com.netease.nim.uikit.cache.FriendDataCache;
+import com.netease.nim.uikit.common.fragment.TFragment;
+import com.netease.nim.uikit.common.ui.liv.LetterIndexView;
+import com.netease.nim.uikit.common.ui.liv.LivIndex;
+import com.netease.nim.uikit.common.util.log.LogUtil;
+import com.netease.nim.uikit.contact.ContactsCustomization;
+import com.netease.nim.uikit.contact.core.item.AbsContactItem;
+import com.netease.nim.uikit.contact.core.item.ContactItem;
+import com.netease.nim.uikit.contact.core.item.ItemTypes;
+import com.netease.nim.uikit.contact.core.model.ContactDataAdapter;
+import com.netease.nim.uikit.contact.core.model.ContactGroupStrategy;
+import com.netease.nim.uikit.contact.core.provider.ContactDataProvider;
+import com.netease.nim.uikit.contact.core.query.IContactDataProvider;
+import com.netease.nim.uikit.contact.core.viewholder.LabelHolder;
+import com.netease.nim.uikit.contact.core.viewholder.OnlineStateContactHolder;
+import com.netease.nim.uikit.uinfo.UserInfoHelper;
+import com.netease.nim.uikit.uinfo.UserInfoObservable;
+import com.netease.nimlib.sdk.Observer;
+import com.sheishuo.app.cache.SocialInfoCache;
+import com.sheishuo.app.common.beans.RequestBean;
+import com.sheishuo.app.core_module.friends.item.FollowItem;
+import com.sheishuo.app.core_module.friends.provider.FollowDataProvider;
+import com.sheishuo.app.core_module.friends.viewholder.FollowContactHolder;
+import com.sheishuo.app.core_module.mine.view.ui.activity.UserInfoDetailActivity;
+import com.sheishuo.app.session.SessionHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
+
+
+/**
+ * 通讯录Fragment
+ * <p/>
+ * Created by huangjun on 2015/9/7.
+ */
+public class FollowListFragment extends TFragment {
+
+    private ContactDataAdapter adapter;
+
+    private ListView listView;
+
+    private TextView countText;
+
+    private LivIndex litterIdx;
+
+    private View loadingFrame;
+
+    private ContactsCustomization customization;
+
+    private ReloadFrequencyControl reloadControl = new ReloadFrequencyControl();
+
+    public void setContactsCustomization(ContactsCustomization customization) {
+        this.customization = customization;
+    }
+
+    private static final class ContactsGroupStrategy extends ContactGroupStrategy {
+        public ContactsGroupStrategy() {
+            add(ContactGroupStrategy.GROUP_NULL, -1, "");
+            addABC(0);
+        }
+    }
+
+    /**
+     * ***************************************** 生命周期 *****************************************
+     */
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.nim_contacts, container, false);
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        // 界面初始化
+        initAdapter();
+        findViews();
+        buildLitterIdx(getView());
+
+        // 注册观察者
+        registerObserver(true);
+        registerOnlineStateChangeListener(true);
+        // 加载本地数据
+        reload(false);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        registerObserver(false);
+        registerOnlineStateChangeListener(false);
+    }
+
+    public void followListUpdate()
+    {
+        reload(false);
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                adapter.notifyDataSetChanged();
+            }
+        });
+    }
+
+    private void initAdapter() {
+        IContactDataProvider dataProvider = new FollowDataProvider();
+
+        adapter = new ContactDataAdapter(getActivity(), new ContactsGroupStrategy(), dataProvider) {
+            @Override
+            protected List<AbsContactItem> onNonDataItems() {
+                if (customization != null) {
+                    return customization.onGetFuncItems();
+                }
+
+                return new ArrayList<>();
+            }
+
+            @Override
+            protected void onPreReady() {
+                loadingFrame.setVisibility(View.VISIBLE);
+            }
+
+            @Override
+            protected void onPostLoad(boolean empty, String queryText, boolean all) {
+                loadingFrame.setVisibility(View.GONE);
+//                int userCount = SocialInfoCache.followList().size();
+//                countText.setText("共关注谁说用户" + userCount + "名");
+                countText.setText("");
+                onReloadCompleted();
+            }
+        };
+
+        adapter.addViewHolder(ItemTypes.LABEL, LabelHolder.class);
+        if (customization != null) {
+            adapter.addViewHolder(ItemTypes.FUNC, customization.onGetFuncViewHolderClass());
+        }
+        adapter.addViewHolder(ItemTypes.FRIEND, OnlineStateContactHolder.class);
+        adapter.addViewHolder(ItemTypes.FOLLOW, FollowContactHolder.class);
+
+    }
+
+    private void findViews() {
+        // loading
+        loadingFrame = findView(R.id.contact_loading_frame);
+
+        // count
+        View countLayout = View.inflate(getView().getContext(), R.layout.nim_contacts_count_item, null);
+        countLayout.setClickable(false);
+        countText = (TextView) countLayout.findViewById(R.id.contactCountText);
+
+        // ListView
+        listView = findView(R.id.contact_list_view);
+        listView.addFooterView(countLayout); // 注意:addFooter要放在setAdapter之前,否则旧版本手机可能会add不上
+        listView.setAdapter(adapter);
+        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
+
+            @Override
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+
+            }
+
+            @Override
+            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+
+            }
+        });
+
+        ContactItemClickListener listener = new ContactItemClickListener();
+        listView.setOnItemClickListener(listener);
+        listView.setOnItemLongClickListener(listener);
+
+        // ios style
+        OverScrollDecoratorHelper.setUpOverScroll(listView);
+    }
+
+    private void buildLitterIdx(View view) {
+        LetterIndexView livIndex = (LetterIndexView) view.findViewById(R.id.liv_index);
+        livIndex.setNormalColor(getResources().getColor(R.color.contacts_letters_color));
+        ImageView imgBackLetter = (ImageView) view.findViewById(R.id.img_hit_letter);
+        TextView litterHit = (TextView) view.findViewById(R.id.tv_hit_letter);
+        litterIdx = adapter.createLivIndex(listView, livIndex, litterHit, imgBackLetter);
+
+        litterIdx.show();
+    }
+
+    private final class ContactItemClickListener implements OnItemClickListener, OnItemLongClickListener {
+
+        @Override
+        public void onItemClick(AdapterView<?> parent, View view, int position,
+                                long id) {
+            AbsContactItem item = (AbsContactItem) adapter.getItem(position);
+            if (item == null) {
+                return;
+            }
+
+            int type = item.getItemType();
+
+            if (type == ItemTypes.FUNC && customization != null) {
+                customization.onFuncItemClick(item);
+                return;
+            }
+
+            if (type == ItemTypes.FRIEND && item instanceof ContactItem && NimUIKit.getContactEventListener() != null) {
+                NimUIKit.getContactEventListener().onItemClick(getActivity(), (((ContactItem) item).getContact()).getContactId());
+            }
+
+            if (type == ItemTypes.FOLLOW)
+            {
+                UserInfoDetailActivity.start(getContext(), ((FollowItem)item).getContact().getContactId());
+            }
+        }
+
+        @Override
+        public boolean onItemLongClick(AdapterView<?> parent, View view,
+                                       int position, long id) {
+            AbsContactItem item = (AbsContactItem) adapter.getItem(position);
+            if (item == null) {
+                return false;
+            }
+
+            if (item instanceof ContactItem && NimUIKit.getContactEventListener() != null) {
+                NimUIKit.getContactEventListener().onItemLongClick(getActivity(), (((ContactItem) item).getContact()).getContactId());
+            }
+
+            return true;
+        }
+    }
+
+    public void scrollToTop() {
+        if (listView != null) {
+            int top = listView.getFirstVisiblePosition();
+            int bottom = listView.getLastVisiblePosition();
+            if (top >= (bottom - top)) {
+                listView.setSelection(bottom - top);
+                listView.smoothScrollToPosition(0);
+            } else {
+                listView.smoothScrollToPosition(0);
+            }
+        }
+    }
+
+    /**
+     * *********************************** 通讯录加载控制 *******************************
+     */
+
+    /**
+     * 加载通讯录数据并刷新
+     *
+     * @param reload true则重新加载数据;false则判断当前数据源是否空,若空则重新加载,不空则不加载
+     */
+    private void reload(boolean reload) {
+        if (!reloadControl.canDoReload(reload)) {
+            return;
+        }
+
+        if (adapter == null) {
+            if (getActivity() == null) {
+                return;
+            }
+
+            initAdapter();
+        }
+
+        // 开始加载
+        if (!adapter.load(reload)) {
+            // 如果不需要加载,则直接当完成处理
+            onReloadCompleted();
+        }
+    }
+
+    private void onReloadCompleted() {
+        if (reloadControl.continueDoReloadWhenCompleted()) {
+            // 计划下次加载,稍有延迟
+            getHandler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    boolean reloadParam = reloadControl.getReloadParam();
+                    Log.i(UIKitLogTag.CONTACT, "continue reload " + reloadParam);
+                    reloadControl.resetStatus();
+                    reload(reloadParam);
+                }
+            }, 50);
+        } else {
+            // 本次加载完成
+            reloadControl.resetStatus();
+        }
+
+        LogUtil.i(UIKitLogTag.CONTACT, "contact load completed");
+    }
+
+    /**
+     * 通讯录加载频率控制
+     */
+    class ReloadFrequencyControl {
+        boolean isReloading = false;
+        boolean needReload = false;
+        boolean reloadParam = false;
+
+        boolean canDoReload(boolean param) {
+            if (isReloading) {
+                // 正在加载,那么计划加载完后重载
+                needReload = true;
+                if (param) {
+                    // 如果加载过程中又有多次reload请求,多次参数只要有true,那么下次加载就是reload(true);
+                    reloadParam = true;
+                }
+                LogUtil.i(UIKitLogTag.CONTACT, "pending reload task");
+
+                return false;
+            } else {
+                // 如果当前空闲,那么立即开始加载
+                isReloading = true;
+                return true;
+            }
+        }
+
+        boolean continueDoReloadWhenCompleted() {
+            return needReload;
+        }
+
+        void resetStatus() {
+            isReloading = false;
+            needReload = false;
+            reloadParam = false;
+        }
+
+        boolean getReloadParam() {
+            return reloadParam;
+        }
+    }
+
+    /**
+     * *********************************** 用户资料、好友关系变更、登录数据同步完成观察者 *******************************
+     */
+
+    private void registerObserver(boolean register) {
+        if (register) {
+            UserInfoHelper.registerObserver(userInfoObserver);
+        } else {
+            UserInfoHelper.unregisterObserver(userInfoObserver);
+        }
+
+        FriendDataCache.getInstance().registerFriendDataChangedObserver(friendDataChangedObserver, register);
+
+        LoginSyncDataStatusObserver.getInstance().observeSyncDataCompletedEvent(loginSyncCompletedObserver);
+    }
+
+    FriendDataCache.FriendDataChangedObserver friendDataChangedObserver = new FriendDataCache.FriendDataChangedObserver() {
+        @Override
+        public void onAddedOrUpdatedFriends(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onAddedOrUpdatedFriends", true);
+        }
+
+        @Override
+        public void onDeletedFriends(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onDeletedFriends", true);
+        }
+
+        @Override
+        public void onAddUserToBlackList(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onAddUserToBlackList", true);
+        }
+
+        @Override
+        public void onRemoveUserFromBlackList(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onRemoveUserFromBlackList", true);
+        }
+    };
+
+    private UserInfoObservable.UserInfoObserver userInfoObserver = new UserInfoObservable.UserInfoObserver() {
+        @Override
+        public void onUserInfoChanged(List<String> accounts) {
+            reloadWhenDataChanged(accounts, "onUserInfoChanged", true, false); // 非好友资料变更,不用刷新界面
+        }
+    };
+
+    private Observer<Void> loginSyncCompletedObserver = new Observer<Void>() {
+        @Override
+        public void onEvent(Void aVoid) {
+            getHandler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    reloadWhenDataChanged(null, "onLoginSyncCompleted", false);
+                }
+            }, 50);
+        }
+    };
+
+    private void reloadWhenDataChanged(List<String> accounts, String reason, boolean reload) {
+        reloadWhenDataChanged(accounts, reason, reload, true);
+    }
+
+    private void reloadWhenDataChanged(List<String> accounts, String reason, boolean reload, boolean force) {
+        if (accounts == null || accounts.isEmpty()) {
+            return;
+        }
+
+        boolean needReload = false;
+        if (!force) {
+            // 非force:与通讯录无关的(非好友)变更通知,去掉
+            for (String account : accounts) {
+                if (FriendDataCache.getInstance().isMyFriend(account)) {
+                    needReload = true;
+                    break;
+                }
+            }
+        } else {
+            needReload = true;
+        }
+
+        if (!needReload) {
+            Log.d(UIKitLogTag.CONTACT, "no need to reload contact");
+            return;
+        }
+
+        // log
+        StringBuilder sb = new StringBuilder();
+        sb.append("ContactFragment received data changed as [" + reason + "] : ");
+        if (accounts != null && !accounts.isEmpty()) {
+            for (String account : accounts) {
+                sb.append(account);
+                sb.append(" ");
+            }
+            sb.append(", changed size=" + accounts.size());
+        }
+        Log.i(UIKitLogTag.CONTACT, sb.toString());
+
+        // reload
+        reload(reload);
+    }
+
+    /**
+     * *********************************** 在线状态 *******************************
+     */
+
+    OnlineStateChangeListener onlineStateChangeListener = new OnlineStateChangeListener() {
+        @Override
+        public void onlineStateChange(Set<String> accounts) {
+            // 更新
+            adapter.notifyDataSetChanged();
+        }
+    };
+
+    private void registerOnlineStateChangeListener(boolean register) {
+        if (!NimUIKit.enableOnlineState()) {
+            return;
+        }
+        if (register) {
+            NimUIKit.addOnlineStateChangeListeners(onlineStateChangeListener);
+        } else {
+            NimUIKit.removeOnlineStateChangeListeners(onlineStateChangeListener);
+        }
+    }
+}

+ 18 - 0
app/src/com/sheishuo/app/core_module/friends/item/FollowItem.java

@@ -0,0 +1,18 @@
+package com.sheishuo.app.core_module.friends.item;
+
+import android.text.TextUtils;
+
+import com.netease.nim.uikit.contact.core.item.AbsContactItem;
+import com.netease.nim.uikit.contact.core.item.ContactItem;
+import com.netease.nim.uikit.contact.core.item.ItemTypes;
+import com.netease.nim.uikit.contact.core.model.ContactGroupStrategy;
+import com.netease.nim.uikit.contact.core.model.IContact;
+import com.netease.nim.uikit.contact.core.query.TextComparator;
+
+public class FollowItem extends ContactItem {
+
+	public FollowItem(IContact contact) {
+		super(contact, ItemTypes.FOLLOW);
+	}
+
+}

+ 45 - 0
app/src/com/sheishuo/app/core_module/friends/model/FollowDataAdapter.java

@@ -0,0 +1,45 @@
+package com.sheishuo.app.core_module.friends.model;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.netease.nim.uikit.UIKitLogTag;
+import com.netease.nim.uikit.common.ui.liv.LetterIndexView;
+import com.netease.nim.uikit.common.ui.liv.LivIndex;
+import com.netease.nim.uikit.common.util.log.LogUtil;
+import com.netease.nim.uikit.contact.core.item.AbsContactItem;
+import com.netease.nim.uikit.contact.core.item.ContactItemFilter;
+import com.netease.nim.uikit.contact.core.model.AbsContactDataList;
+import com.netease.nim.uikit.contact.core.model.ContactDataAdapter;
+import com.netease.nim.uikit.contact.core.model.ContactDataList;
+import com.netease.nim.uikit.contact.core.model.ContactDataTask;
+import com.netease.nim.uikit.contact.core.model.ContactDataTask.Host;
+import com.netease.nim.uikit.contact.core.model.ContactGroupStrategy;
+import com.netease.nim.uikit.contact.core.query.IContactDataProvider;
+import com.netease.nim.uikit.contact.core.query.TextQuery;
+import com.netease.nim.uikit.contact.core.viewholder.AbsContactViewHolder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 通讯录数据适配器
+ * <p/>
+ * Created by huangjun on 2015/2/10.
+ */
+public class FollowDataAdapter extends ContactDataAdapter {
+
+    public FollowDataAdapter(Context context, ContactGroupStrategy groupStrategy, IContactDataProvider dataProvider) {
+        super(context, groupStrategy, dataProvider);
+    }
+
+}

+ 65 - 0
app/src/com/sheishuo/app/core_module/friends/provider/BeFollowedDataProvider.java

@@ -0,0 +1,65 @@
+package com.sheishuo.app.core_module.friends.provider;
+
+import com.netease.nim.uikit.UIKitLogTag;
+import com.netease.nim.uikit.common.util.log.LogUtil;
+import com.netease.nim.uikit.contact.core.item.AbsContactItem;
+import com.netease.nim.uikit.contact.core.model.IContact;
+import com.netease.nim.uikit.contact.core.query.IContactDataProvider;
+import com.netease.nim.uikit.contact.core.query.TextQuery;
+import com.sheishuo.app.cache.SocialInfoCache;
+import com.sheishuo.app.core_module.friends.activity.BeFollowedActivity;
+import com.sheishuo.app.core_module.friends.item.FollowItem;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public final class BeFollowedDataProvider implements IContactDataProvider {
+
+    public BeFollowedDataProvider() {
+
+    }
+
+    @Override
+    public List<AbsContactItem> provide(TextQuery query) {
+        List<AbsContactItem> data = new ArrayList<>();
+
+        data.addAll(getProvide(query));
+
+        return data;
+    }
+
+    private static final List<AbsContactItem> getProvide(TextQuery query) {
+        List<AbsContactItem> items = new ArrayList<>();
+
+        if(BeFollowedActivity.beFollowedBean != null) {
+            List<String> follows = BeFollowedActivity.beFollowedBean.getD();
+            if (follows != null) {
+                for (String userId : follows) {
+                    items.add(new FollowItem(makeFollowContactFromUserId(userId)));
+                }
+            }
+        }
+        LogUtil.i(UIKitLogTag.CONTACT, "contact provide data size =" + items.size());
+        return items;
+    }
+
+    public static IContact makeFollowContactFromUserId(final String userId) {
+        return new IContact() {
+            @Override
+            public String getContactId() {
+                return userId;
+            }
+
+            @Override
+            public int getContactType() {
+                return Type.Follow;
+            }
+
+            @Override
+            public String getDisplayName() {
+                return SocialInfoCache.getNick(userId);
+            }
+        };
+    }
+}

+ 74 - 0
app/src/com/sheishuo/app/core_module/friends/provider/FollowDataProvider.java

@@ -0,0 +1,74 @@
+package com.sheishuo.app.core_module.friends.provider;
+
+import com.netease.nim.uikit.NimUIKit;
+import com.netease.nim.uikit.UIKitLogTag;
+import com.netease.nim.uikit.cache.FriendDataCache;
+import com.netease.nim.uikit.common.util.log.LogUtil;
+import com.netease.nim.uikit.contact.core.item.AbsContactItem;
+import com.netease.nim.uikit.contact.core.item.ContactItem;
+import com.netease.nim.uikit.contact.core.item.ItemTypes;
+import com.netease.nim.uikit.contact.core.model.IContact;
+import com.netease.nim.uikit.contact.core.provider.ContactSearch;
+import com.netease.nim.uikit.contact.core.provider.MsgDataProvider;
+import com.netease.nim.uikit.contact.core.provider.TeamDataProvider;
+import com.netease.nim.uikit.contact.core.provider.UserDataProvider;
+import com.netease.nim.uikit.contact.core.query.IContactDataProvider;
+import com.netease.nim.uikit.contact.core.query.TextQuery;
+import com.netease.nim.uikit.contact.core.util.ContactHelper;
+import com.netease.nimlib.sdk.friend.model.Friend;
+import com.netease.nimlib.sdk.uinfo.UserInfoProvider;
+import com.sheishuo.app.cache.SocialInfoCache;
+import com.sheishuo.app.core_module.friends.item.FollowItem;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+public final class FollowDataProvider implements IContactDataProvider {
+
+    public FollowDataProvider() {
+
+    }
+
+    @Override
+    public List<AbsContactItem> provide(TextQuery query) {
+        List<AbsContactItem> data = new ArrayList<>();
+
+        data.addAll(getProvide(query));
+
+        return data;
+    }
+
+    private static final List<AbsContactItem> getProvide(TextQuery query) {
+        List<AbsContactItem> items = new ArrayList<>();
+
+        Collection<String> follows = SocialInfoCache.followList();
+        if(follows != null) {
+            for (String userId : follows) {
+                items.add(new FollowItem(makeFollowContactFromUserId(userId)));
+            }
+        }
+        LogUtil.i(UIKitLogTag.CONTACT, "contact provide data size =" + items.size());
+        return items;
+    }
+
+    public static IContact makeFollowContactFromUserId(final String userId) {
+        return new IContact() {
+            @Override
+            public String getContactId() {
+                return userId;
+            }
+
+            @Override
+            public int getContactType() {
+                return Type.Follow;
+            }
+
+            @Override
+            public String getDisplayName() {
+                return SocialInfoCache.getNick(userId);
+            }
+        };
+    }
+}

+ 24 - 0
app/src/com/sheishuo/app/core_module/friends/viewholder/FollowContactHolder.java

@@ -0,0 +1,24 @@
+package com.sheishuo.app.core_module.friends.viewholder;
+
+import android.text.TextUtils;
+import android.view.View;
+
+import com.netease.nim.uikit.NimUIKit;
+import com.netease.nim.uikit.contact.core.item.ContactItem;
+import com.netease.nim.uikit.contact.core.model.ContactDataAdapter;
+import com.netease.nim.uikit.contact.core.model.IContact;
+import com.netease.nim.uikit.contact.core.viewholder.ContactHolder;
+
+/**
+ * Created by hzchenkang on 2017/4/6.
+ */
+
+public class FollowContactHolder extends ContactHolder{
+
+    @Override
+    public void refresh(ContactDataAdapter adapter, int position, ContactItem item) {
+        super.refresh(adapter, position, item);
+        IContact contact = item.getContact();
+        desc.setVisibility(View.GONE);
+    }
+}

+ 1 - 1
app/src/com/sheishuo/app/core_module/mine/view/ui/activity/HobbySelectActivity.java

@@ -85,7 +85,7 @@ public class HobbySelectActivity extends SheishuoUI {
             public void onClick(View v) {
                 Intent intent = new Intent();
                 String hobbySelect = TextUtils.join(",", hobbySelectList);
-                intent.putExtra(RESULT_HOBBY,hobbySelect.substring(0,hobbySelect.length() - 1));
+                intent.putExtra(RESULT_HOBBY, hobbySelect);
                 setResult(HOBBY_RESULT_CODE,intent);
                 finish();
             }

+ 17 - 12
app/src/com/sheishuo/app/core_module/mine/view/ui/activity/PersonalSettingsActivity.java

@@ -208,17 +208,7 @@ public class PersonalSettingsActivity extends SheishuoUI {
 
         if (!bean.getAge().isEmpty()) ageTV.setText(bean.getAge());
 
-        if (!bean.getHobby().isEmpty())
-        {
-            if(bean.getHobby().length() > 6)
-                hobbyTV.setText(bean.getHobby().substring(0, 6));
-            else
-                hobbyTV.setText(bean.getHobby());
-        }
-        else
-        {
-            hobbyTV.setText("");
-        }
+        updateHobby(bean.getHobby());
 
 
         //隐藏真实姓名
@@ -335,6 +325,21 @@ public class PersonalSettingsActivity extends SheishuoUI {
         PickImageHelper.pickImage(this, requestCode, option);
     }
 
+    private void updateHobby(String hobbys)
+    {
+        if (hobbys != null && !hobbys.isEmpty())
+        {
+            if(hobbys.length() > 6)
+                hobbyTV.setText(hobbys.substring(0, 6)+"...");
+            else
+                hobbyTV.setText(hobbys);
+        }
+        else
+        {
+            hobbyTV.setText("");
+        }
+    }
+
     private void updateRealName()
     {
         if (!bean.getReal_name().isEmpty()){
@@ -416,7 +421,7 @@ public class PersonalSettingsActivity extends SheishuoUI {
 
         } else if (HobbySelectActivity.HOBBY_RESULT_CODE == resultCode) {
             String hobby = data.getStringExtra(HobbySelectActivity.RESULT_HOBBY);
-            hobbyTV.setText(hobby);
+            updateHobby(hobby);
             bean.setHobby(hobby);
 
             net.updateSocialInfo(bean, new ResponseCallback() {

+ 3 - 0
app/src/com/sheishuo/app/core_module/mine/view/ui/activity/UserInfoDetailActivity.java

@@ -228,6 +228,8 @@ public class UserInfoDetailActivity extends SheishuoUI {
                 thumbUrl.add(info.getPhotos().get(i).getThumb());
             }
 
+            personalPhotosLayout.removeAllViewsInLayout();
+
             int widthAndHeight = ImgUtil.getScreenWidth(context) / 4;
             for (int i = 0;i < info.getPhotos().size() && i < 4;i++){
                 String url = info.getPhotos().get(i).getThumb();
@@ -269,6 +271,7 @@ public class UserInfoDetailActivity extends SheishuoUI {
                     public void run() {
                         if (circlePhotosThumb.size() > 0) {
                             tweetPhotosLayout.setVisibility(View.VISIBLE);
+                            tweetPhotosLayout.removeAllViewsInLayout();
                             int widthAndHeight = ImgUtil.getScreenWidth(context) / 4;
                             for (int i = 0; i < 3 && i < circlePhotosThumb.size(); i++) {
 

+ 16 - 15
app/src/com/sheishuo/app/core_module/mine/view/ui/activity/UserInfoSettingActivity.java

@@ -15,6 +15,7 @@ import android.widget.Switch;
 import android.widget.TextView;
 
 import com.netease.nim.uikit.cache.FriendDataCache;
+import com.netease.nim.uikit.cache.NimUserInfoCache;
 import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog;
 import com.netease.nim.uikit.common.ui.dialog.DialogMaker;
 import com.netease.nim.uikit.common.ui.dialog.EasyEditDialog;
@@ -27,6 +28,10 @@ import com.netease.nimlib.sdk.msg.MsgService;
 import com.netease.nimlib.sdk.uinfo.UserService;
 import com.netease.nimlib.sdk.uinfo.constant.UserInfoFieldEnum;
 import com.sheishuo.app.R;
+import com.sheishuo.app.cache.SocialInfoCache;
+import com.sheishuo.app.common.util.net.INet;
+import com.sheishuo.app.common.util.net.NetImpl;
+import com.sheishuo.app.common.util.net.ResponseCallback;
 import com.sheishuo.app.common.views.BaseToolbar;
 import com.sheishuo.app.impl.SheishuoUI;
 
@@ -101,7 +106,7 @@ public class UserInfoSettingActivity extends SheishuoUI {
         muteSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
             @Override
             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                NIMClient.getService(FriendService.class).setMessageNotify(userId,isChecked);
+                NIMClient.getService(FriendService.class).setMessageNotify(userId, !isChecked);
             }
         });
 
@@ -139,9 +144,10 @@ public class UserInfoSettingActivity extends SheishuoUI {
 
     private void refreshAlias()
     {
-        Friend friend = FriendDataCache.getInstance().getFriendByAccount(userId);
-        if (friend != null && !TextUtils.isEmpty(friend.getAlias())) {
-            remarkTV.setText(friend.getAlias());
+        String alias = NimUserInfoCache.getInstance().getAlias(userId);
+//        Friend friend = FriendDataCache.getInstance().getFriendByAccount(userId);
+        if (alias != null && !TextUtils.isEmpty(alias)) {
+            remarkTV.setText(alias);
         } else {
             remarkTV.setHint("请输入备注名...");
         }
@@ -183,23 +189,18 @@ public class UserInfoSettingActivity extends SheishuoUI {
     {
         if(data.length() > 0) {
             DialogMaker.showProgressDialog(this, null, true);
-            Map<FriendFieldEnum, Object> map = new HashMap<>();
-            map.put(FriendFieldEnum.ALIAS, data);
-            NIMClient.getService(FriendService.class).updateFriendFields(userId, map).setCallback(new RequestCallback<Void>() {
+            INet net = new NetImpl();
+            net.updateAlias(userId, data, new ResponseCallback() {
                 @Override
-                public void onSuccess(Void aVoid) {
+                public void onSuccess(Object object) {
+                    SocialInfoCache.setAlias(userId, data);
+                    NimUserInfoCache.getInstance().setAlias(userId, data);
                     remarkTV.setText(data);
                     DialogMaker.dismissProgressDialog();
                 }
 
                 @Override
-                public void onFailed(int i) {
-                    showToast(getBaseContext(), "设置备注名失败");
-                    DialogMaker.dismissProgressDialog();
-                }
-
-                @Override
-                public void onException(Throwable throwable) {
+                public void onFailed() {
                     showToast(getBaseContext(), "设置备注名失败");
                     DialogMaker.dismissProgressDialog();
                 }

+ 75 - 5
app/src/com/sheishuo/app/core_module/sheishuo/view/ui/TeamSettingsActivity.java

@@ -14,13 +14,20 @@ import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.Switch;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import com.bumptech.glide.Glide;
+import com.netease.nim.uikit.NimUIKit;
+import com.netease.nim.uikit.common.ui.imageview.HeadImageView;
+import com.netease.nim.uikit.contact_selector.activity.ContactSelectActivity;
 import com.netease.nim.uikit.recent.RecentContactsFragment;
 import com.netease.nim.uikit.session.helper.MessageListPanelHelper;
+import com.netease.nim.uikit.team.activity.AdvancedTeamInfoActivity;
 import com.netease.nim.uikit.team.activity.AdvancedTeamMemberActivity;
+import com.netease.nim.uikit.team.helper.TeamHelper;
 import com.netease.nimlib.sdk.NIMClient;
 import com.netease.nimlib.sdk.RequestCallback;
+import com.netease.nimlib.sdk.ResponseCode;
 import com.netease.nimlib.sdk.msg.MsgService;
 import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
 import com.netease.nimlib.sdk.msg.model.RecentContact;
@@ -31,8 +38,10 @@ import com.netease.nimlib.sdk.team.model.TeamMember;
 import com.netease.nimlib.sdk.uinfo.UserService;
 import com.netease.nimlib.sdk.uinfo.model.NimUserInfo;
 import com.sheishuo.app.R;
+import com.sheishuo.app.cache.AccountCache;
 import com.sheishuo.app.common.util.img.ImgUtil;
 import com.sheishuo.app.common.views.BaseToolbar;
+import com.sheishuo.app.core_module.friends.activity.FollowSelectActivity;
 import com.sheishuo.app.core_module.mine.view.ui.activity.UserInfoDetailActivity;
 import com.sheishuo.app.impl.SheishuoUI;
 import com.sheishuo.app.session.activity.MessageHistoryActivity;
@@ -52,6 +61,8 @@ public class TeamSettingsActivity extends SheishuoUI implements View.OnClickList
     public final static int INTRODUCTION_REQUEST_CODE = 1102;
     public final static int MEMBER_REQUEST_CODE = 1103;
 
+    private static final int REQUEST_CODE_CONTACT_SELECT = 103;
+
     private String TAG = this.getClass().getSimpleName();
     private Context context = this;
 
@@ -326,19 +337,70 @@ public class TeamSettingsActivity extends SheishuoUI implements View.OnClickList
             }
         }
 
+        if (resultCode == Activity.RESULT_OK) {
+            switch (requestCode) {
+                case REQUEST_CODE_CONTACT_SELECT:
+                    final ArrayList<String> selected = data.getStringArrayListExtra(ContactSelectActivity.RESULT_DATA);
+                    if (selected != null && !selected.isEmpty()) {
+                        inviteMembers(selected);
+                    }
+                    break;
+            }
+        }
     }
 
 
+    private void inviteMembers(ArrayList<String> accounts) {
+        NIMClient.getService(TeamService.class).addMembers(team.getId(), accounts).setCallback(new RequestCallback<Void>() {
+            @Override
+            public void onSuccess(Void param) {
+                Toast.makeText(TeamSettingsActivity.this, "添加群成员成功", Toast.LENGTH_SHORT).show();
+            }
+
+            @Override
+            public void onFailed(int code) {
+                if (code == ResponseCode.RES_TEAM_INVITE_SUCCESS) {
+                    Toast.makeText(TeamSettingsActivity.this, com.netease.nim.uikit.R.string.team_invite_members_success, Toast.LENGTH_SHORT).show();
+                } else {
+                    Toast.makeText(TeamSettingsActivity.this, "invite members failed, code=" + code, Toast.LENGTH_SHORT).show();
+                    Log.e(TAG, "invite members failed, code=" + code);
+                }
+            }
+
+            @Override
+            public void onException(Throwable exception) {
+
+            }
+        });
+    }
+
     //加载群成员资料和头像
-    private void updateMembersInfo(List<String> memberIds) {
+    private void updateMembersInfo(final List<String> memberIds) {
         NIMClient.getService(UserService.class).fetchUserInfo(memberIds).setCallback(new RequestCallback<List<NimUserInfo>>() {
             @Override
             public void onSuccess(List<NimUserInfo> nimUserInfos) {
+
+                final int imageSize = HeadImageView.DEFAULT_AVATAR_NOTIFICATION_ICON_SIZE;
+
+                if(team.getCreator().equals(AccountCache.getAccount().getId())) {
+                    HeadImageView addBtn = new HeadImageView(context);
+                    addBtn.setMaxWidth(imageSize);
+                    addBtn.setMaxHeight(imageSize);
+                    addBtn.setImageResource(R.drawable.add_group_members);
+
+                    addBtn.setOnClickListener(new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            ContactSelectActivity.Option option = TeamHelper.getContactSelectOption(memberIds);
+                            FollowSelectActivity.startActivityForResult(TeamSettingsActivity.this, option, REQUEST_CODE_CONTACT_SELECT);
+                        }
+                    });
+                    teamMemberAvatarLayout.addView(addBtn);
+                }
+
+                int count = 0;
                 for (final NimUserInfo info : nimUserInfos) {
-                    ImageView avatar = new ImageView(context);
-                    avatar.setAdjustViewBounds(true);
-                    avatar.setMaxWidth((int) ImgUtil.convertDpToPixel(48, context));
-                    avatar.setMaxHeight((int) ImgUtil.convertDpToPixel(48, context));
+                    HeadImageView avatar = new HeadImageView(context);
 
                     avatar.setOnClickListener(new View.OnClickListener() {
                         @Override
@@ -349,19 +411,27 @@ public class TeamSettingsActivity extends SheishuoUI implements View.OnClickList
                         }
                     });
 
+
                     if (info.getAvatar() == null) {
                         Glide.with(context)
                                 .load(R.drawable.nim_avatar_default)
                                 .bitmapTransform(new CropCircleTransformation(context))
+                                .centerCrop()
+                                .override(imageSize, imageSize)
                                 .into(avatar);
                     } else {
                         Glide.with(context)
                                 .load(info.getAvatar())
                                 .bitmapTransform(new CropCircleTransformation(context))
+                                .centerCrop()
+                                .override(imageSize, imageSize)
                                 .into(avatar);
                     }
 
                     teamMemberAvatarLayout.addView(avatar);
+                    count++;
+                    if(count > 6)
+                        break;
                 }
             }
 

+ 36 - 0
app/src/com/sheishuo/app/core_module/trade/model/TradeModel.java

@@ -1,8 +1,11 @@
 package com.sheishuo.app.core_module.trade.model;
 
+import android.graphics.Bitmap;
 import android.util.Log;
 
 import com.google.gson.Gson;
+import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialog;
+import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialogHelper;
 import com.sheishuo.app.cache.AccountCache;
 import com.sheishuo.app.common.beans.TradeBean;
 import com.sheishuo.app.common.util.net.INet;
@@ -205,9 +208,42 @@ public class TradeModel {
             }).start();
 
         }
+    }
+
+    public void uploadPhoto(final List<String> filesPathList, final int index)
+    {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+
+                if(index >= filesPathList.size()) {
+                    presenter.onAllPhotoUploaded();
+                    return;
+                }
+
+                net.uploadImgs(filesPathList.get(index), new ResponseCallback() {
+                    @Override
+                    public void onSuccess(Object object) {
+                        //Log.e("object", (String) object);
+                        presenter.showToast("第" + (index + 1) + "张照片上传完毕");
+                        presenter.onOnePhotoUploaded(index, (int) object);
+                        uploadPhoto(filesPathList, index+1);
+                    }
 
+                    @Override
+                    public void onFailed() {
+                        presenter.showToast("第" + (index + 1) + "张照片上传失败");
+                        presenter.onPhotoUploadFailed(index);
+                    }
+                });
+            }
+
+        }).start();
     }
 
+
+
+
     public void editTrade(final String id, final String priority)
     {
         final FormBody body = new FormBody.Builder()

+ 25 - 3
app/src/com/sheishuo/app/core_module/trade/presenter/TradePresenter.java

@@ -2,6 +2,7 @@ package com.sheishuo.app.core_module.trade.presenter;
 
 import android.content.Context;
 import android.content.DialogInterface;
+import android.graphics.Bitmap;
 import android.support.v7.app.AlertDialog;
 
 import com.netease.nim.uikit.session.helper.MessageListPanelHelper;
@@ -49,6 +50,20 @@ public class TradePresenter {
         model = new TradeModel(this);
     }
 
+    public Context getContext()
+    {
+        Context context = null;
+        if(fragment != null)
+            context = fragment.getContext();
+        else if(mineTradeActivity != null)
+            context = mineTradeActivity;
+        else if(activity != null)
+            context = activity;
+        else if(detailsActivity != null)
+            context = detailsActivity;
+
+        return context;
+    }
 
     public void loadTradeList(int type,int page){
         model.loadTradeList(type,page);
@@ -89,17 +104,24 @@ public class TradePresenter {
         model.uploadPhoto(filePaths);
     }
 
+    public void uploadPhoto(List<String> filePaths, int index)
+    {
+        model.uploadPhoto(filePaths, index);
+    }
 
     public void onOnePhotoUploaded(int index,int photoId){
         activity.onOnePhotoUploaded(index,photoId);
     }
 
-
     public void onAllPhotoUploaded(){
-        activity.onAllPhotosUploaded();
+        if(activity != null)
+            activity.onAllPhotosUploaded();
     }
 
-
+    public void onPhotoUploadFailed(int index){
+        if(activity != null)
+            activity.onPhotoUploadFailed(index);
+    }
 
     public void updatePriority(String tradeId, String priority)
     {

+ 208 - 78
app/src/com/sheishuo/app/core_module/trade/view/ui/activity/TradePublishActivity.java

@@ -3,10 +3,15 @@ package com.sheishuo.app.core_module.trade.view.ui.activity;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Bitmap;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.support.v7.widget.RecyclerView;
 import android.util.Log;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
@@ -23,6 +28,10 @@ import com.bumptech.glide.Glide;
 import com.netease.nim.uikit.activity.GiftRechargeActivity;
 import com.netease.nim.uikit.common.media.picker.PickImageHelper;
 import com.netease.nim.uikit.common.media.picker.model.PhotoInfo;
+import com.netease.nim.uikit.common.ui.dialog.DialogMaker;
+import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialog;
+import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialogHelper;
+import com.netease.nim.uikit.session.constant.Extras;
 import com.sheishuo.app.R;
 import com.sheishuo.app.cache.AccountCache;
 import com.sheishuo.app.cache.SocialInfoCache;
@@ -84,13 +93,15 @@ public class TradePublishActivity extends SheishuoUI {
     private ArrayAdapter<String> adapter;
 
 
-
     //FLAGS
     private String teamId = "";
     private String PRIORITY_TYPE = TradeItemAdapter.PRIORITY_COUNTRY;
     private int TRADE_TYPE = TradeModel.TYPE_SELL;
     private int RADIO_CHECKED;
 
+    private int imgSize;
+    private ImageView addImg;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -121,6 +132,8 @@ public class TradePublishActivity extends SheishuoUI {
 
     void init() {
 
+        imgSize = ImgUtil.getScreenWidth(context) / 9;
+
         //设置父Layout
         parentLayout.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -228,57 +241,25 @@ public class TradePublishActivity extends SheishuoUI {
         publishBtn.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                publishBtn.setEnabled(false);
-                for (int i = 0;i < photoIds.size() ; i ++){
-                    if (i == photoIds.size() - 1){
-                        photosStr += photoIds.get(i);
-                    }else {
-                        photosStr += photoIds.get(i) + ",";
-                    }
-                }
-
-                Log.e(TAG,photosStr);
-
-                new NetImpl().publishTrade(TRADE_TYPE
-                        , tradeContentET.getText().toString()
-                        , photosStr
-                        , Integer.valueOf(priorityTV.getText().toString())
-                        , Integer.valueOf(PRIORITY_TYPE)
-                        , teamId
-                        , new ResponseCallback() {
-                            @Override
-                            public void onSuccess(Object object) {
-                                try {
-                                    int code = new JSONObject((String) object).getInt("c");
-                                    if (1 == code){
-                                        showToast(context,new JSONObject((String) object).getString("d"));
-                                    }else {
-                                        showToast(context,"发布成功");
-                                    }
-                                    finish();
-
-                                } catch (JSONException e) {
-                                    e.printStackTrace();
-                                }
-                            }
-
-                            @Override
-                            public void onFailed() {
-                                showToast(context,"发布失败");
-                            }
-                        });
+                publish();
             }
         });
 
 
         //初始化photosLayout
-        photosLayout.setOnClickListener(new View.OnClickListener() {
+        addImg = new ImageView(this);
+        addImg.setAdjustViewBounds(true);
+        addImg.setImageResource(R.drawable.add_group_members);
+        addImg.setLayoutParams(new ViewGroup.LayoutParams(imgSize, imgSize));
+        addImg.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 PickImageHelper.PickImageOption option = new PickImageHelper.PickImageOption();
+                option.multiSelectMaxCount = 10 - photosLayout.getChildCount();
                 PickImageHelper.pickImage(context, 0, option);
             }
         });
+        photosLayout.addView(addImg);
 
     }
 
@@ -292,57 +273,130 @@ public class TradePublishActivity extends SheishuoUI {
             }
 
             Bundle result = data.getExtras();
-            if (!result.getBoolean("from_local")) {
+            if (!result.getBoolean(Extras.EXTRA_FROM_LOCAL)) {
                 //照相机
-                String filePath = result.getString("file_path");
-                //移除添加图片按钮
-                photosLayout.removeAllViews();
-
-                ImageView imageView = new ImageView(this);
-                imageView.setAdjustViewBounds(true);
-                int toDp = (int) ImgUtil.convertDpToPixel(128, context);
-                imageView.setLayoutParams(new LinearLayout.LayoutParams(toDp, toDp));
-                Glide.with(context).load(filePath)
-                        .centerCrop()
-                        .bitmapTransform(new ColorFilterTransformation(context, 0x7900CCCC))
-                        .into(imageView);
-                photosLayout.addView(imageView);
-                selectedPhotoPathList.add(filePath);
-                presenter.uploadPhoto(filePath);
+                String filePath = result.getString(Extras.EXTRA_FILE_PATH);
+                createImageView(filePath);
             } else {
                 //相册
 
-                //移除添加图片按钮
-                photosLayout.removeAllViews();
-
                 List<PhotoInfo> photoInfoList = (List<PhotoInfo>) result.getSerializable("photo_list");
                 for (PhotoInfo info : photoInfoList) {
-                    ImageView imageView = new ImageView(this);
-                    imageView.setAdjustViewBounds(true);
-                    int toDp = (int) ImgUtil.convertDpToPixel(128, context);
-                    imageView.setLayoutParams(new LinearLayout.LayoutParams(toDp, toDp));
-                    Glide.with(context).load(info.getFilePath())
-                            .centerCrop()
-                            .bitmapTransform(new ColorFilterTransformation(context, 0x7900CCCC))
-                            .into(imageView);
-                    photosLayout.addView(imageView);
-                    selectedPhotoPathList.add(info.getAbsolutePath());
+                    createImageView(info.getAbsolutePath());
                 }
+            }
+        }
+    }
 
-                presenter.uploadPhoto(selectedPhotoPathList);
 
+    private ImageView createImageView(String filePath)
+    {
+        selectedPhotoPathList.add(filePath);
 
+        final ImageView imageView = new ImageView(this);
+        imageView.setAdjustViewBounds(true);
+        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+        imageView.setLayoutParams(new ViewGroup.LayoutParams(imgSize, imgSize));
+        imageView.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() {
 
+                    @Override
+                    public void doCancelAction() {
+                    }
+
+                    @Override
+                    public void doOkAction() {
+                        for(int i=0; i<photosLayout.getChildCount(); i++)
+                        {
+                            if(photosLayout.getChildAt(i).equals(imageView))
+                            {
+                                photosLayout.removeViewAt(i);
+                                selectedPhotoPathList.remove(i-1);
+                                break;
+                            }
+                        }
+                        checkAddImg();
+                    }
+                };
+
+                EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(TradePublishActivity.this, null, "是否删除该图片", true, listener);
+                dialog.show();
+                return false;
             }
+        });
 
-        }
+        Glide.with(context).load(filePath)
+                .into(imageView);
+        photosLayout.addView(imageView);
+        checkAddImg();
+        return imageView;
     }
 
+    private void checkAddImg()
+    {
+        if(photosLayout.getChildCount() >= 9 + 1)
+            addImg.setVisibility(View.GONE);
+        else
+            addImg.setVisibility(View.VISIBLE);
+    }
 
     /**
      * 开放调用方法
      */
 
+    public void publish()
+    {
+        DialogMaker.showProgressDialog(TradePublishActivity.this, "");
+
+        photoIds.clear();
+        presenter.uploadPhoto(selectedPhotoPathList, 0);
+    }
+
+    private void sendPublish()
+    {
+        for (int i = 0;i < photoIds.size() ; i ++){
+            if (i == photoIds.size() - 1){
+                photosStr += photoIds.get(i);
+            }else {
+                photosStr += photoIds.get(i) + ",";
+            }
+        }
+
+        Log.e(TAG,photosStr);
+
+        new NetImpl().publishTrade(TRADE_TYPE
+                , tradeContentET.getText().toString()
+                , photosStr
+                , Integer.valueOf(priorityTV.getText().toString())
+                , Integer.valueOf(PRIORITY_TYPE)
+                , teamId
+                , new ResponseCallback() {
+                    @Override
+                    public void onSuccess(Object object) {
+                        try {
+                            int code = new JSONObject((String) object).getInt("c");
+                            if (1 == code){
+                                showToast(context,new JSONObject((String) object).getString("d"));
+                            }else {
+                                showToast(context,"发布成功");
+                            }
+                            DialogMaker.dismissProgressDialog();
+                            finish();
+
+                        } catch (JSONException e) {
+                            e.printStackTrace();
+                        }
+                    }
+
+                    @Override
+                    public void onFailed() {
+                        DialogMaker.dismissProgressDialog();
+                        showToast(context,"发布失败");
+                    }
+                });
+    }
 
 
     //当一张照片上传完成后回调
@@ -350,21 +404,44 @@ public class TradePublishActivity extends SheishuoUI {
         getHandler().post(new Runnable() {
             @Override
             public void run() {
-                ImageView imageView = (ImageView) photosLayout.getChildAt(index);
-                String filePath = selectedPhotoPathList.get(index);
-                Glide.with(context).load(filePath).into(imageView);
-                Collections.synchronizedList(photoIds);
                 photoIds.add(String.valueOf(photoId));
+            }
+        });
+    }
 
+    public void onPhotoUploadFailed(final int index)
+    {
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() {
+
+                    @Override
+                    public void doCancelAction() {
+                        DialogMaker.dismissProgressDialog();
+                    }
+
+                    @Override
+                    public void doOkAction() {
+                        presenter.uploadPhoto(selectedPhotoPathList, index);
+                    }
+                };
+
+                EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(TradePublishActivity.this, null, "图片上传失败,是否重试?", true, listener);
+                dialog.show();
             }
         });
 
     }
 
-
     //全部照片上传完成
     public void onAllPhotosUploaded(){
-        publishBtn.setEnabled(true);
+        getHandler().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                sendPublish();
+            }
+        }, 100);
     }
 
 
@@ -390,4 +467,57 @@ public class TradePublishActivity extends SheishuoUI {
         startActivity(intent);
         finish();
     }
+
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+
+            // 获得当前得到焦点的View,一般情况下就是EditText(特殊情况就是轨迹求或者实体案件会移动焦点)
+            View v = getCurrentFocus();
+
+            if (isShouldHideInput(v, ev)) {
+                hideSoftInput(v.getWindowToken());
+            }
+        }
+        return super.dispatchTouchEvent(ev);
+    }
+
+    /**
+     * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时没必要隐藏
+     *
+     * @param v
+     * @param event
+     * @return
+     */
+    private boolean isShouldHideInput(View v, MotionEvent event) {
+        if (v != null && (v instanceof EditText)) {
+            int[] l = { 0, 0 };
+            v.getLocationInWindow(l);
+            int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left
+                    + v.getWidth();
+            if (event.getX() > left && event.getX() < right
+                    && event.getY() > top && event.getY() < bottom) {
+                // 点击EditText的事件,忽略它。
+                return false;
+            } else {
+                return true;
+            }
+        }
+        // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditView上,和用户用轨迹球选择其他的焦点
+        return false;
+    }
+
+    /**
+     * 多种隐藏软件盘方法的其中一种
+     *
+     * @param token
+     */
+    private void hideSoftInput(IBinder token) {
+        if (token != null) {
+            InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+            im.hideSoftInputFromWindow(token,
+                    InputMethodManager.HIDE_NOT_ALWAYS);
+        }
+    }
 }

+ 42 - 7
app/src/com/sheishuo/app/impl/SheishuoTeamMessageActivity.java

@@ -7,6 +7,7 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.support.v4.view.MenuItemCompat;
 import android.support.v7.app.AlertDialog;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -25,6 +26,7 @@ import com.netease.nim.uikit.session.constant.Extras;
 import com.netease.nim.uikit.session.fragment.MessageFragment;
 import com.netease.nim.uikit.session.helper.MessageListPanelHelper;
 import com.netease.nimlib.sdk.NIMClient;
+import com.netease.nimlib.sdk.RequestCallback;
 import com.netease.nimlib.sdk.msg.MsgService;
 import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
 import com.netease.nimlib.sdk.msg.model.IMMessage;
@@ -33,10 +35,14 @@ import com.netease.nimlib.sdk.team.constant.TeamTypeEnum;
 import com.netease.nimlib.sdk.team.model.Team;
 import com.netease.nimlib.sdk.team.model.TeamMember;
 import com.sheishuo.app.R;
+import com.sheishuo.app.common.util.net.INet;
+import com.sheishuo.app.common.util.net.NetImpl;
+import com.sheishuo.app.common.util.net.ResponseCallback;
 import com.sheishuo.app.common.views.BaseToolbar;
 import com.sheishuo.app.core_module.sheishuo.view.ui.TeamSettingsActivity;
 import com.sheishuo.app.session.search.SearchMessageActivity;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -63,6 +69,8 @@ public class SheishuoTeamMessageActivity extends TeamMessageActivity {
 
     protected Class<? extends Activity> backToClass;
 
+    protected INet net = new NetImpl();
+
     public static void start(Context context, String tid, SessionCustomization customization,
                              Class<? extends Activity> backToClass, IMMessage anchor) {
         Intent intent = new Intent();
@@ -246,6 +254,38 @@ public class SheishuoTeamMessageActivity extends TeamMessageActivity {
                 }
             });
         }
+
+        NIMClient.getService(TeamService.class).queryMemberList(sessionId).setCallback(new RequestCallback<List<TeamMember>>() {
+            @Override
+            public void onSuccess(List<TeamMember> teamMembers) {
+                List<String> memberIds = new ArrayList<>();
+                for (TeamMember member : teamMembers) {
+                    memberIds.add(member.getAccount());
+                }
+                net.fetchAlias(TextUtils.join(",", memberIds), new ResponseCallback() {
+                    @Override
+                    public void onSuccess(Object object) {
+                        fragment.refreshMessageList();
+                    }
+
+                    @Override
+                    public void onFailed() {
+
+                    }
+                });
+            }
+
+            @Override
+            public void onFailed(int i) {
+
+            }
+
+            @Override
+            public void onException(Throwable throwable) {
+
+            }
+        });
+
     }
 
     protected void onRequestTeamInfoFailed() {
@@ -404,13 +444,8 @@ public class SheishuoTeamMessageActivity extends TeamMessageActivity {
 
 
     public boolean isSystemTeam(Team team){
-        if (team.getName().contains("国家")
-                ||team.getName().contains("省")
-                ||team.getName().contains("市")
-                ||team.getName().contains("区")
-                ||team.getName().contains("县")
-                ||team.getName().contains("自治")
-                ||team.getName().contains("特别行政区")){
+        if (Integer.parseInt(team.getCreator()) < 20000)
+        {
             return true;
         }
 

+ 7 - 0
app/src/com/sheishuo/app/login/LoginActivity.java

@@ -31,6 +31,7 @@ import com.sheishuo.app.login.beans.LoginBean;
 import com.sheishuo.app.login.helper.LoginHelper;
 import com.sheishuo.app.impl.SheishuoToolbarOptions;
 import com.sheishuo.app.impl.SheishuoUI;
+import com.sheishuo.app.main.activity.ForgetActivity;
 
 /**
  * Created by KN on 2017/7/11.
@@ -46,6 +47,7 @@ public class LoginActivity extends SheishuoUI implements View.OnClickListener{
     private Button loginBtn;
     private TextView toRegisterTxt;
     private TextView toAgreeTxt;
+    private TextView forgetTxt;
     private RadioButton agreeRadio;
     private boolean isAgree = true;
 
@@ -96,6 +98,9 @@ public class LoginActivity extends SheishuoUI implements View.OnClickListener{
                 intent.putExtra(AboutWebViewActivity.URL, NetInfo.AGREEMENT_URL);
                 startActivity(intent);
                 break;
+            case R.id.forgot_password:
+                startActivity(new Intent(context, ForgetActivity.class));
+                break;
         }
     }
 
@@ -107,11 +112,13 @@ public class LoginActivity extends SheishuoUI implements View.OnClickListener{
         toRegisterTxt = findView(R.id.register_txt);
         toAgreeTxt = findView(R.id.agree_txt);
         agreeRadio = findView(R.id.agree_radio);
+        forgetTxt = findView(R.id.forgot_password);
 
         loginBtn.setOnClickListener(this);
         toRegisterTxt.setOnClickListener(this);
         toAgreeTxt.setOnClickListener(this);
         agreeRadio.setOnClickListener(this);
+        forgetTxt.setOnClickListener(this);
     }
 
 

+ 181 - 0
app/src/com/sheishuo/app/main/activity/ForgetActivity.java

@@ -0,0 +1,181 @@
+package com.sheishuo.app.main.activity;
+
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.netease.nim.uikit.common.ui.dialog.DialogMaker;
+import com.sheishuo.app.R;
+import com.sheishuo.app.cache.AccountCache;
+import com.sheishuo.app.common.util.net.INet;
+import com.sheishuo.app.common.util.net.NetImpl;
+import com.sheishuo.app.common.util.net.ResponseCallback;
+import com.sheishuo.app.common.views.BaseToolbar;
+import com.sheishuo.app.impl.SheishuoUI;
+
+public class ForgetActivity extends SheishuoUI {
+
+
+    private BaseToolbar toolbar;
+    private EditText mobileTxt;
+    private EditText codeTxt;
+    private EditText pwdTxt;
+    private EditText confirmTxt;
+    private Button sendCodeBtn;
+
+    private INet net = new NetImpl();
+    private Handler handler;
+    private int countDown = 60;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_forget);
+        findViews();
+        init();
+    }
+
+    private void findViews()
+    {
+        toolbar = findView(R.id.toolbar);
+        mobileTxt = findView(R.id.mobile_txt);
+        codeTxt = findView(R.id.code_txt);
+        pwdTxt = findView(R.id.pwd_txt);
+        confirmTxt = findView(R.id.confirm_txt);
+        sendCodeBtn = findView(R.id.send_code_btn);
+    }
+
+    private void init()
+    {
+        toolbar.setTitle("忘记密码");
+        toolbar.setBackOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                finish();
+            }
+        });
+
+        TextView rightTxt = new TextView(getBaseContext());
+        rightTxt.setText("发送");
+        rightTxt.setTextColor(Color.WHITE);
+        rightTxt.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                submit();
+            }
+        });
+        toolbar.setRightItems(new View[]{rightTxt});
+
+
+        sendCodeBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                getCode();
+            }
+        });
+
+        handler = new Handler(){
+            @Override
+            public void handleMessage(Message msg) {
+                super.handleMessage(msg);
+                switch (msg.what){
+                    case 0:
+                        countDown--;
+                        if (countDown > 0) {
+                            sendCodeBtn.setText(countDown + "秒后重发");
+                            msg = handler.obtainMessage();
+                            msg.what = 0;
+                            handler.sendMessageDelayed(msg,1000);
+                        }else {
+                            countDown = 60;
+                            sendCodeBtn.setEnabled(true);
+                            sendCodeBtn.setText("获取验证码");
+                            sendCodeBtn.setTextColor(Color.parseColor("#00ae8c"));
+                        }
+                        break;
+                }
+            }
+        };
+    }
+
+    private void getCode()
+    {
+        sendCodeBtn.setEnabled(false);
+        handler.sendEmptyMessage(0);
+
+        String mobile = mobileTxt.getText().toString().trim();
+        net.getVerificationCode(mobile, new ResponseCallback() {
+            @Override
+            public void onSuccess(Object object) {
+
+            }
+
+            @Override
+            public void onFailed() {
+
+            }
+        });
+    }
+
+    private void submit()
+    {
+        String mobile = mobileTxt.getText().toString().trim();
+        String code = codeTxt.getText().toString().trim();
+        String pwd = pwdTxt.getText().toString().trim();
+        String confirm = confirmTxt.getText().toString().trim();
+
+        if(pwd.length() < AccountCache.PasswordMinLength || pwd.length() > 12)
+        {
+            Toast.makeText(getBaseContext(), "密码长度不正确", Toast.LENGTH_SHORT).show();
+        }
+        else if(!pwd.equals(confirm))
+        {
+            Toast.makeText(getBaseContext(), "密码与确认密码不一致", Toast.LENGTH_SHORT).show();
+        }
+
+        DialogMaker.showProgressDialog(this, "");
+
+        net.forgetPassword(mobile, code, pwd, new ResponseCallback() {
+            @Override
+            public void onSuccess(Object object) {
+                DialogMaker.dismissProgressDialog();
+                reset();
+                showToast("密码重置成功");
+            }
+
+            @Override
+            public void onFailed() {
+                DialogMaker.dismissProgressDialog();
+                showToast("密码重置失败");
+            }
+        });
+    }
+
+    private void reset()
+    {
+        mobileTxt.setText("");
+        codeTxt.setText("");
+        pwdTxt.setText("");
+        confirmTxt.setText("");
+    }
+
+    private void showToast(final String content)
+    {
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                Toast.makeText(getBaseContext(), content, Toast.LENGTH_SHORT).show();
+            }
+        });
+    }
+}

+ 3 - 2
app/src/com/sheishuo/app/main/activity/GlobalSearchActivity.java

@@ -16,6 +16,7 @@ import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ListView;
 
+import com.sheishuo.app.impl.SheishuoUIKit;
 import com.sheishuo.app.session.SessionHelper;
 import com.sheishuo.app.session.search.DisplayMessageActivity;
 import com.sheishuo.app.R;
@@ -189,12 +190,12 @@ public class GlobalSearchActivity extends UI implements OnItemClickListener {
         AbsContactItem item = (AbsContactItem) adapter.getItem(position);
         switch (item.getItemType()) {
             case ItemTypes.TEAM: {
-                SessionHelper.startTeamSession(this, ((ContactItem) item).getContact().getContactId());
+                SheishuoUIKit.startTeamSession(this, ((ContactItem) item).getContact().getContactId());
                 break;
             }
 
             case ItemTypes.FRIEND: {
-                SessionHelper.startP2PSession(this, ((ContactItem) item).getContact().getContactId());
+                SheishuoUIKit.startP2PSession(this, ((ContactItem) item).getContact().getContactId());
                 break;
             }
 

+ 2 - 1
app/src/com/sheishuo/app/main/activity/MainActivity.java

@@ -32,6 +32,7 @@ import com.sheishuo.app.avchat.activity.AVChatActivity;
 import com.sheishuo.app.chatroom.helper.ChatRoomHelper;
 import com.sheishuo.app.common.views.BaseToolbar;
 import com.sheishuo.app.config.preference.UserPreferences;
+import com.sheishuo.app.core_module.circle.activity.NewCommentActivity;
 import com.sheishuo.app.core_module.location.LocationSelectActivity;
 import com.sheishuo.app.core_module.mine.view.ui.activity.MineUploadPhotoActivity;
 import com.sheishuo.app.core_module.trade.view.ui.activity.TradeChangePriorityActivity;
@@ -290,7 +291,7 @@ public class MainActivity extends SheishuoUI {
                 final ArrayList<String> selected = data.getStringArrayListExtra(ContactSelectActivity.RESULT_DATA);
                 TeamCreateHelper.createAdvancedTeam(MainActivity.this, selected);
             }
-        }else if(resultCode == REFRESH_CIRCLE || resultCode == DELETE_CIRCLE){
+        }else if(resultCode == REFRESH_CIRCLE || resultCode == DELETE_CIRCLE || resultCode == NewCommentActivity.NEW_COMMENT){
             mainFragment.onActivityResult(requestCode,resultCode,data);
         }
 

+ 122 - 5
app/src/com/sheishuo/app/main/activity/SystemMessageActivity.java

@@ -12,8 +12,14 @@ import android.view.View;
 import android.widget.Toast;
 
 import com.sheishuo.app.cache.AccountCache;
+import com.sheishuo.app.cache.SocialInfoCache;
+import com.sheishuo.app.common.beans.RequestBean;
+import com.sheishuo.app.common.util.date.DateUtil;
+import com.sheishuo.app.common.util.net.INet;
 import com.sheishuo.app.common.util.net.NetImpl;
+import com.sheishuo.app.common.util.net.ResponseCallback;
 import com.sheishuo.app.common.views.BaseToolbar;
+import com.sheishuo.app.core_module.friends.activity.ContactsListActivity;
 import com.sheishuo.app.main.adapter.SystemMessageAdapter;
 import com.sheishuo.app.main.viewholder.SystemMessageViewHolder;
 import com.sheishuo.app.R;
@@ -54,9 +60,10 @@ import java.util.Set;
 public class SystemMessageActivity extends UI implements TAdapterDelegate,
         AutoRefreshListView.OnRefreshListener, SystemMessageViewHolder.SystemMessageListener {
 
-    private static final boolean MERGE_ADD_FRIEND_VERIFY = false; // 是否要合并好友申请,同一个用户仅保留最近一条申请内容(默认不合并)
+    private static final boolean MERGE_ADD_FRIEND_VERIFY = true; // 是否要合并好友申请,同一个用户仅保留最近一条申请内容(默认不合并)
 
     private static final int LOAD_MESSAGE_COUNT = 10;
+    public static final String SHEI_SHUO_INVITE = "Sheishuoinvite";
 
     // view
     private MessageListView listView;
@@ -69,6 +76,9 @@ public class SystemMessageActivity extends UI implements TAdapterDelegate,
     // db
     private boolean firstLoad = true;
 
+    private INet net = new NetImpl();
+    private RequestBean requestBean;
+
     public static void start(Context context) {
         start(context, null, true);
     }
@@ -115,6 +125,9 @@ public class SystemMessageActivity extends UI implements TAdapterDelegate,
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        Bundle bundle = getIntent().getExtras();
+        requestBean = ContactsListActivity.requestBean;
+
         setContentView(R.layout.system_notification_message_activity);
 
         BaseToolbar toolbar = (BaseToolbar) findViewById(R.id.toolbar);
@@ -132,6 +145,8 @@ public class SystemMessageActivity extends UI implements TAdapterDelegate,
 
         loadMessages(); // load old data
         registerSystemObserver(true);
+
+        addSheiShuoInvite();
     }
 
     @Override
@@ -193,6 +208,24 @@ public class SystemMessageActivity extends UI implements TAdapterDelegate,
     }
 
 
+    private void addSheiShuoInvite()
+    {
+        for(RequestBean.ListBean bean : requestBean.getD())
+        {
+            SystemMessage msg = new SystemMessage();
+            msg.setMessageId(Long.parseLong(bean.getId()));
+            msg.setAttachObject(bean);
+            msg.setType(SystemMessageType.AddFriend.getValue());
+            msg.setFromAccount(bean.getUser_id());
+            msg.setTargetId(bean.getTarget_id());
+            msg.setContent(bean.getMsg());
+            msg.setTime(DateUtil.stringToLong(bean.getInputtime(), "yyyy-MM-dd HH:mm:ss"));
+            msg.setStatus(SystemMessageStatus.init);
+            items.add(msg);
+        }
+    }
+
+
     private int loadOffset = 0;
     private Set<String> addFriendVerifyRequestAccounts = new HashSet<>(); // 发送过好友申请的账号(好友申请合并用)
 
@@ -263,12 +296,16 @@ public class SystemMessageActivity extends UI implements TAdapterDelegate,
         collectAndRequestUnknownUserInfo(messageFromAccounts);
     }
 
+
     /**
      * 新消息到来
      */
     private void onIncomingMessage(final SystemMessage message) {
         // 同一个账号的好友申请仅保留最近一条
         if (addFriendVerifyFilter(message)) {
+            if(true)
+                return;
+
             SystemMessage del = null;
             for (SystemMessage m : items) {
                 if (m.getFromAccount().equals(message.getFromAccount()) && m.getType() == SystemMessageType.AddFriend) {
@@ -317,6 +354,10 @@ public class SystemMessageActivity extends UI implements TAdapterDelegate,
             return false; // 不过滤
         }
 
+        //谁说不需要好友功能
+        if(true)
+            return true;
+
         AddFriendNotify attachData = (AddFriendNotify) msg.getAttachObject();
         if (attachData == null) {
             return true; // 过滤
@@ -397,7 +438,48 @@ public class SystemMessageActivity extends UI implements TAdapterDelegate,
                 NIMClient.getService(TeamService.class).rejectApply(message.getTargetId(), message.getFromAccount(), "").setCallback(callback);
             }
         } else if (message.getType() == SystemMessageType.AddFriend) {
-            NIMClient.getService(FriendService.class).ackAddFriendRequest(message.getFromAccount(), pass).setCallback(callback);
+            //NIMClient.getService(FriendService.class).ackAddFriendRequest(message.getFromAccount(), pass).setCallback(callback);
+            onSheishuoInviteDeal(message, pass);
+        }
+    }
+
+    private void onSheishuoInviteDeal(final SystemMessage message, final boolean pass)
+    {
+        final RequestBean.ListBean bean = (RequestBean.ListBean)message.getAttachObject();
+        if(bean == null)
+            return;
+
+        if(pass)
+        {
+            net.addFriend(bean.getId(), new ResponseCallback() {
+                @Override
+                public void onSuccess(Object object) {
+                    SocialInfoCache.setFollow(bean.getUser_id(), true);
+                    items.remove(message);
+                    deleteRequest(bean);
+                    getHandler().post(new Runnable() {
+                        @Override
+                        public void run() {
+                            Toast.makeText(SystemMessageActivity.this, "添加好友成功", Toast.LENGTH_SHORT).show();
+                        }
+                    });
+                }
+
+                @Override
+                public void onFailed() {
+                    getHandler().post(new Runnable() {
+                        @Override
+                        public void run() {
+                            Toast.makeText(SystemMessageActivity.this, "添加好友失败", Toast.LENGTH_SHORT).show();
+                        }
+                    });
+                }
+            });
+        }
+        else
+        {
+            items.remove(message);
+            deleteRequest(bean);
         }
     }
 
@@ -512,9 +594,44 @@ public class SystemMessageActivity extends UI implements TAdapterDelegate,
     }
 
     private void deleteSystemMessage(final SystemMessage message) {
-        NIMClient.getService(SystemMessageService.class).deleteSystemMessage(message.getMessageId());
-        items.remove(message);
+        if(message.getType() == SystemMessageType.AddFriend) {
+            items.remove(message);
+            deleteRequest((RequestBean.ListBean)message.getAttachObject());
+        }
+        else
+        {
+            NIMClient.getService(SystemMessageService.class).deleteSystemMessage(message.getMessageId());
+            items.remove(message);
+            refresh();
+            Toast.makeText(SystemMessageActivity.this, R.string.delete_success, Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    private void deleteRequest(final RequestBean.ListBean bean)
+    {
+        if(bean == null)
+            return;
+
+        net.requestDelete(bean.getId(), new ResponseCallback() {
+            @Override
+            public void onSuccess(Object object) {
+                removeFromRequestBean(bean);
+            }
+
+            @Override
+            public void onFailed() {
+
+            }
+        });
+    }
+
+    private void removeFromRequestBean(RequestBean.ListBean bean)
+    {
+        if(requestBean == null)
+            return;
+
+        requestBean.getD().remove(bean);
+
         refresh();
-        Toast.makeText(SystemMessageActivity.this, R.string.delete_success, Toast.LENGTH_SHORT).show();
     }
 }

+ 29 - 12
app/src/com/sheishuo/app/main/adapter/CircleListAdapter.java

@@ -1,5 +1,6 @@
 package com.sheishuo.app.main.adapter;
 
+import android.app.Activity;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -60,7 +61,7 @@ public class CircleListAdapter  extends RecyclerView.Adapter<CircleListAdapter.C
 
     private List<CircleBean.DBean.ListBean> data;
     private OnCircleItemClickListener listener;
-    private Context context;
+    private Activity context;
     private CircleOfFriendsFragment circleFragment;
     private CirclePersonActivity circleActivity;
     private Boolean FLAGS_ALL_LOADED = false;
@@ -96,8 +97,8 @@ public class CircleListAdapter  extends RecyclerView.Adapter<CircleListAdapter.C
         holder.contentTV.setVisibility(bean.getMsg().length() > 0 ? View.VISIBLE : View.GONE);
         holder.locationTV.setText(bean.getLocal());
         holder.dateTV.setText(bean.getInputtime());
-        holder.likesNumTV.setText(bean.getLikes());
-        holder.visitNumTv.setText(bean.getViews());
+        holder.likesNumTV.setText(""+bean.getLikes());
+        holder.visitNumTv.setText(""+bean.getViews());
         holder.usernameTV.setText(getUserName(bean.getUser_id()));
         holder.usernameTV.setOnClickListener(this);
         holder.usernameTV.setTag(bean);
@@ -116,8 +117,8 @@ public class CircleListAdapter  extends RecyclerView.Adapter<CircleListAdapter.C
             public void onClick(View v) {
                 Log.e("socialId",bean.getId());
                 Intent intent = new Intent(context, NewCommentActivity.class);
-                intent.putExtra(NewCommentActivity.SOCIAL_ID,bean.getId());
-                context.startActivity(intent);
+                intent.putExtra(NewCommentActivity.SOCIAL_ID, bean);
+                context.startActivityForResult(intent, 0);
             }
         });
 
@@ -172,7 +173,7 @@ public class CircleListAdapter  extends RecyclerView.Adapter<CircleListAdapter.C
 
                     //修改本地缓存
                     num++;
-                    bean.setLikes(String.valueOf(num));
+                    bean.setLikes(num);
                     bean.setLiked("1");
 
 
@@ -193,7 +194,10 @@ public class CircleListAdapter  extends RecyclerView.Adapter<CircleListAdapter.C
                 HeadImageView imageView = (HeadImageView) commentView.findViewById(R.id.circle_comment_preview_item_img);
                 TextView textView = (TextView) commentView.findViewById(circle_comment_preview_item_tv);
 
-                String avatarUrl = NIMClient.getService(UserService.class).getUserInfo(comment.getUser_id()).getAvatar();
+                String avatarUrl = "";
+                NimUserInfo userInfo = NIMClient.getService(UserService.class).getUserInfo(comment.getUser_id());
+                if(userInfo != null )
+                    avatarUrl = userInfo.getAvatar();
                 if (avatarUrl.equals("")){
                     Glide.with(context).load(R.drawable.user_account_icon).into(imageView);
                 }else {
@@ -213,9 +217,9 @@ public class CircleListAdapter  extends RecyclerView.Adapter<CircleListAdapter.C
                     @Override
                     public void onClick(View v) {
                         Intent intent = new Intent(context, NewCommentActivity.class);
-                        intent.putExtra(NewCommentActivity.SOCIAL_ID,bean.getId());
-                        intent.putExtra(NewCommentActivity.REPLY_ID,comment.getUser_id());
-                        context.startActivity(intent);
+                        intent.putExtra(NewCommentActivity.SOCIAL_ID, bean);
+                        intent.putExtra(NewCommentActivity.REPLY_ID, comment.getUser_id());
+                        context.startActivityForResult(intent, 0);
                     }
                 });
 
@@ -237,8 +241,8 @@ public class CircleListAdapter  extends RecyclerView.Adapter<CircleListAdapter.C
         //判断标志为缓存的Holder小于两个且最底部的Item
         if (position > data.size() - 2 && !FLAGS_ALL_LOADED) {
             Log.e("LOAED_ALL", String.valueOf(FLAGS_ALL_LOADED));
-            if(circleFragment != null) circleFragment.loadCircleListMore(data.get(data.size() - 1).getId());
-            if(circleActivity != null) circleActivity.loadCircleListMore(data.get(data.size() - 1).getId());
+            if(circleFragment != null) circleFragment.loadCircleListMore(data.get(0).getId());
+            if(circleActivity != null) circleActivity.loadCircleListMore(data.get(0).getId());
         }else if (FLAGS_ALL_LOADED){
             if(circleFragment != null) circleFragment.showToast("已无更多内容");
             if(circleActivity != null) circleActivity.showToast("已无更多内容");
@@ -391,6 +395,19 @@ public class CircleListAdapter  extends RecyclerView.Adapter<CircleListAdapter.C
 
     }
 
+    public void addComment(CircleBean.DBean.ListBean.Comment comment)
+    {
+        for(CircleBean.DBean.ListBean listBean : data)
+        {
+            if(listBean.getId().equals(comment.getSocial_id()))
+            {
+                listBean.getComments_list().add(comment);
+                listBean.setComments(listBean.getComments()+1);
+                break;
+            }
+        }
+    }
+
     //清空数据
     public void clearAll(){
         data.clear();

+ 24 - 2
app/src/com/sheishuo/app/main/fragment/CircleOfFriendsFragment.java

@@ -39,6 +39,7 @@ import com.sheishuo.app.common.util.net.NetStatus;
 import com.sheishuo.app.common.util.net.ResponseCallback;
 import com.sheishuo.app.common.views.ImgGridView;
 import com.sheishuo.app.core_module.circle.activity.CircleDetailsActivity;
+import com.sheishuo.app.core_module.circle.activity.NewCommentActivity;
 import com.sheishuo.app.core_module.circle.activity.NewTweetingActivity;
 import com.sheishuo.app.common.beans.CircleBean;
 import com.sheishuo.app.common.views.BaseToolbar;
@@ -136,8 +137,18 @@ public class CircleOfFriendsFragment extends MainTabFragment{
                 option.multiSelectMaxCount, true, false, 0, 0);
     }
 
+    @Override
+    public void onResume() {
+        super.onResume();
 
-
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                if(adapter != null)
+                    adapter.notifyDataSetChanged();
+            }
+        });
+    }
 
     void findViews(){
         parent = (MainActivity) getActivity();
@@ -271,7 +282,7 @@ public class CircleOfFriendsFragment extends MainTabFragment{
      * @param lastId
      */
     public void loadCircleListMore(String lastId){
-        showToast("正在加载更多内容...");
+        //showToast("正在加载更多内容...");
         presenter.loadCircleList(AccountCache.getAccount().getId(),lastId, null);
     }
 
@@ -308,9 +319,20 @@ public class CircleOfFriendsFragment extends MainTabFragment{
             case Activity.RESULT_OK:
                 UpdateBanner(requestCode, data);
                 break;
+            case NewCommentActivity.NEW_COMMENT:
+                adapter.addComment((CircleBean.DBean.ListBean.Comment)data.getSerializableExtra(NewCommentActivity.NEW_COMMENT_DATA));
+                getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        adapter.notifyDataSetChanged();
+                    }
+                });
+                break;
         }
     }
 
+
+
     private void UpdateBanner(int requestCode, Intent data)
     {
         Bundle result = data.getExtras();

+ 40 - 3
app/src/com/sheishuo/app/main/fragment/HomeFragment.java

@@ -28,12 +28,15 @@ import com.netease.nim.uikit.common.ui.drop.DropFake;
 import com.netease.nim.uikit.common.ui.drop.DropManager;
 import com.netease.nim.uikit.common.util.log.LogUtil;
 import com.netease.nim.uikit.contact_selector.activity.ContactSelectActivity;
+import com.netease.nim.uikit.recent.TeamMemberAitHelper;
 import com.netease.nimlib.sdk.NIMClient;
 import com.netease.nimlib.sdk.Observer;
 import com.netease.nimlib.sdk.msg.MsgService;
+import com.netease.nimlib.sdk.msg.MsgServiceObserve;
 import com.netease.nimlib.sdk.msg.SystemMessageObserver;
 import com.netease.nimlib.sdk.msg.SystemMessageService;
 import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
+import com.netease.nimlib.sdk.msg.model.IMMessage;
 import com.netease.nimlib.sdk.msg.model.RecentContact;
 import com.netease.nimlib.sdk.team.TeamService;
 import com.sheishuo.app.R;
@@ -41,6 +44,7 @@ import com.sheishuo.app.cache.AccountCache;
 import com.sheishuo.app.common.ui.viewpager.FadeInOutPageTransformer;
 import com.sheishuo.app.common.ui.viewpager.PagerSlidingTabStrip;
 import com.sheishuo.app.common.views.BottomNavigationViewEx;
+import com.sheishuo.app.core_module.circle.activity.NewCommentActivity;
 import com.sheishuo.app.core_module.location.LocationSelectActivity;
 import com.sheishuo.app.core_module.mine.view.ui.activity.MineUploadPhotoActivity;
 import com.sheishuo.app.core_module.trade.view.ui.activity.TradeChangePriorityActivity;
@@ -49,12 +53,15 @@ import com.sheishuo.app.main.activity.MainActivity;
 import com.sheishuo.app.main.adapter.MainTabPagerAdapter;
 import com.sheishuo.app.main.helper.SystemMessageUnreadManager;
 import com.sheishuo.app.main.model.MainTab;
+import com.sheishuo.app.main.reminder.ReminderId;
 import com.sheishuo.app.main.reminder.ReminderItem;
 import com.sheishuo.app.main.reminder.ReminderManager;
 import com.sheishuo.app.team.TeamCreateHelper;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Created by KN on 2017/7/17.
@@ -162,7 +169,7 @@ public class HomeFragment extends TFragment implements OnPageChangeListener, Rem
         {
             ViewGroup itemLayout = (ViewGroup) bottomTabContainer.getChildAt(i);
             int drawable = 0;
-            int color = i == index ? Color.parseColor("#FFFBAB08") : Color.parseColor("lightgrey");
+            int color = i == index ? Color.parseColor("#FFFBAB08") : Color.parseColor("#FF979797");
             switch(i)
             {
                 case 0:
@@ -259,9 +266,10 @@ public class HomeFragment extends TFragment implements OnPageChangeListener, Rem
         enableMsgNotification(false);
         //quitOtherActivities();
 //        for (Fragment fragment : getFragmentManager().getFragments()) {
-//            if (fragment instanceof SessionListFragment)
+//            if (fragment instanceof MineFragment)
 //                fragment.setUserVisibleHint(true);
 //        }
+
     }
 
     @Override
@@ -327,17 +335,40 @@ public class HomeFragment extends TFragment implements OnPageChangeListener, Rem
     private void registerMsgUnreadInfoObserver(boolean register) {
         if (register) {
             ReminderManager.getInstance().registerUnreadNumChangedCallback(this);
+            MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class);
+            service.observeReceiveMessage(messageReceiverObserver, register);
         } else {
             ReminderManager.getInstance().unregisterUnreadNumChangedCallback(this);
+            MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class);
+            service.observeReceiveMessage(messageReceiverObserver, register);
         }
     }
 
+    private Observer<List<IMMessage>> messageReceiverObserver = new Observer<List<IMMessage>>() {
+        @Override
+        public void onEvent(List<IMMessage> imMessages) {
+            if (imMessages != null) {
+                //延迟一点时间,未读数量才会更新
+                getHandler().postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount();
+                        ReminderManager.getInstance().updateSessionUnreadNum(unreadNum);
+                    }
+                }, 100);
+            }
+        }
+    };
+
     /**
      * 未读消息数量观察者实现
      */
     @Override
     public void onUnreadNumChanged(ReminderItem item) {
-        MainTab tab = MainTab.fromReminderId(item.getId());
+        int itemId = item.getId();
+        if(itemId == ReminderId.CONTACT)
+            itemId = ReminderId.SESSION;
+        MainTab tab = MainTab.fromReminderId(itemId);
 //        if (tab != null) {
 //            tabs.updateTab(tab.tabIndex, item);
 //        }
@@ -478,7 +509,13 @@ public class HomeFragment extends TFragment implements OnPageChangeListener, Rem
                         fragment.onActivityResult(requestCode, resultCode, data);
 
                 }
+
                 break;
+            case NewCommentActivity.NEW_COMMENT:
+                for (Fragment fragment : getFragmentManager().getFragments()) {
+                    if (fragment instanceof CircleOfFriendsFragment)
+                        fragment.onActivityResult(requestCode, resultCode, data);
+                }
 
             //位置选择
             case LocationSelectActivity.LOCATION_SELECTED_RESULT_CODE:

+ 100 - 8
app/src/com/sheishuo/app/main/fragment/MineFragment.java

@@ -25,6 +25,7 @@ import com.netease.nim.uikit.common.ui.dialog.DialogMaker;
 import com.netease.nim.uikit.common.util.log.LogUtil;
 import com.netease.nim.uikit.common.util.media.ImageUtil;
 import com.netease.nim.uikit.session.actions.PickImageAction;
+import com.netease.nim.uikit.session.activity.WatchPictureActivity;
 import com.netease.nimlib.sdk.AbortableFuture;
 import com.netease.nimlib.sdk.NIMClient;
 import com.netease.nimlib.sdk.RequestCallback;
@@ -40,6 +41,7 @@ import com.sheishuo.app.R;
 import com.sheishuo.app.cache.AccountCache;
 import com.sheishuo.app.cache.MineSocialCache;
 import com.sheishuo.app.cache.SocialInfoCache;
+import com.sheishuo.app.common.beans.CircleBean;
 import com.sheishuo.app.common.beans.SocialInfoBean;
 import com.sheishuo.app.common.beans.SocialPhoto;
 import com.sheishuo.app.common.util.img.ImgUtil;
@@ -48,6 +50,7 @@ import com.sheishuo.app.common.util.net.NetImpl;
 import com.sheishuo.app.common.util.net.ResponseCallback;
 import com.sheishuo.app.common.views.BaseToolbar;
 import com.sheishuo.app.contact.helper.UserUpdateHelper;
+import com.sheishuo.app.core_module.circle.activity.CirclePersonActivity;
 import com.sheishuo.app.core_module.mine.view.ui.activity.MineTradeActivity;
 import com.sheishuo.app.core_module.mine.view.ui.activity.MineUploadPhotoActivity;
 import com.sheishuo.app.core_module.mine.view.ui.activity.NearbyPeopleActivity;
@@ -76,8 +79,8 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
     private ScrollView layout;
     private ImageView avatarImg,settingsImg,bannerImg,editPhotoImg,genderImg;
     private TextView usernameTV,userIdTV;
-    private LinearLayout neabyPeopleOption,mineTradeOption,settingsOptions;
-    private GridLayout photosLayout;
+    private LinearLayout neabyPeopleOption,mineTradeOption,settingsOptions, socialContainer;
+    private GridLayout photosLayout, socialPicLayout;
     private Toast toast = null;
     private INet net = new NetImpl();
 
@@ -92,7 +95,6 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         onCurrent();
-
     }
 
     @Override
@@ -101,6 +103,17 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
         init();
     }
 
+    @Override
+    public void onCurrent() {
+        super.onCurrent();
+        fetchCircleList();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateHead();
+    }
 
     private void findViews(){
         parent = (MainActivity) getActivity();
@@ -117,6 +130,9 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
         photosLayout = findView(R.id.mine_fragment_photos_layout);
         genderImg = findView(R.id.mine_fragment_gender);
 
+        socialContainer = findView(R.id.mine_fragment_detail_circle);
+        socialPicLayout = findView(R.id.mine_fragment_details_tweet_photos_layout);
+
         avatarImg.setOnClickListener(this);
         bannerImg.setOnClickListener(this);
         settingsImg.setOnClickListener(this);
@@ -130,11 +146,12 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
         initToolbar();
         fetchSocialInfo();
 
-
-
-
         mineId = AccountCache.getAccount().getId();
+        socialContainer.setOnClickListener(this);
+    }
 
+    private void updateHead()
+    {
         NimUserInfo user = NIMClient.getService(UserService.class).getUserInfo(AccountCache.getAccount().getId());
         if (user.getAvatar() != null)
             Glide.with(getActivity()).load(user.getAvatar()).into(avatarImg);
@@ -150,7 +167,6 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
 
         usernameTV.setText(SocialInfoCache.getNick(mineId));
         userIdTV.setText("ID:" + SocialInfoCache.getSsid(mineId));
-
     }
 
 
@@ -177,7 +193,8 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
     public void onClick(View v) {
         switch (v.getId()){
             case R.id.mine_fragment_avatar:
-                pickImage(MineFragment.AVATAR_SELECTED);
+                //pickImage(MineFragment.AVATAR_SELECTED);
+                showAvatarImage();
                 break;
             case R.id.mine_fragment_banner:
                 pickImage(MineFragment.BANNER_SELECTED);
@@ -199,6 +216,9 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
                 break;
             case R.id.mine_fragment_photos_layout:
                 break;
+            case R.id.mine_fragment_detail_circle:
+                CirclePersonActivity.start(context, AccountCache.getAccount().getId());
+                break;
         }
     }
 
@@ -479,4 +499,76 @@ public class MineFragment extends MainTabFragment implements View.OnClickListene
         DialogMaker.dismissProgressDialog();
     }
 
+
+
+    private void fetchCircleList(){
+        //展示动态照片
+        net.getCircleList(AccountCache.getAccount().getId(), "", new ResponseCallback() {
+            @Override
+            public void onSuccess(Object object) {
+                final CircleBean bean = (CircleBean) object;
+
+                getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        fillCircle(bean);
+                    }
+                });
+            }
+
+            @Override
+            public void onFailed() {
+                showToast("加载动态失败");
+            }
+        });
+    }
+
+    private void fillCircle(CircleBean bean)
+    {
+        final List<String> circlePhotosThumb = new ArrayList<>();
+        final List<String> circlePhotos = new ArrayList<>();
+        for (CircleBean.DBean.ListBean listItem : bean.getD().getList()) {
+            circlePhotosThumb.addAll(listItem.getThumbs());
+            circlePhotos.addAll(listItem.getPics());
+        }
+
+        socialPicLayout.removeAllViewsInLayout();
+
+        if (circlePhotosThumb.size() > 0) {
+            int widthAndHeight = ImgUtil.getScreenWidth(getContext()) / 4;
+            for (int i = 0; i < 3 && i < circlePhotosThumb.size(); i++) {
+                ImageView imageView = ImgUtil.getImageFromNet(context,circlePhotosThumb.get(i));
+                imageView.setAdjustViewBounds(true);
+                GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
+                layoutParams.width = widthAndHeight;
+                layoutParams.height = widthAndHeight;
+                imageView.setLayoutParams(layoutParams);
+
+                final int finalI = i;
+                imageView.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        WatchPictureActivity.start(context, circlePhotos, circlePhotosThumb, finalI);
+                    }
+                });
+
+                socialPicLayout.addView(imageView);
+            }
+        }
+    }
+
+    private void showAvatarImage()
+    {
+        NimUserInfo userInfo = NIMClient.getService(UserService.class).getUserInfo(AccountCache.getAccount().getId());
+        if(userInfo != null && userInfo.getAvatar() != null)
+        {
+            List<String> imgList = new ArrayList<String>();
+            imgList.add(userInfo.getAvatar());
+
+            List<String> thumbList = new ArrayList<String>();
+            thumbList.add("");
+
+            WatchPictureActivity.start(context, imgList, thumbList, 0);
+        }
+    }
 }

+ 76 - 3
app/src/com/sheishuo/app/main/fragment/SessionListFragment.java

@@ -2,16 +2,24 @@ package com.sheishuo.app.main.fragment;
 
 import android.app.FragmentTransaction;
 import android.content.Intent;
+import android.graphics.Color;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
+import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 import android.widget.Toast;
 
 import com.netease.nim.uikit.common.activity.UI;
+import com.netease.nim.uikit.common.ui.drop.DropFake;
 import com.netease.nim.uikit.common.util.log.LogUtil;
+import com.netease.nim.uikit.common.util.sys.ScreenUtil;
 import com.netease.nim.uikit.recent.RecentContactsCallback;
 import com.netease.nim.uikit.recent.RecentContactsFragment;
 import com.netease.nim.uikit.session.extension.GiftAttachment;
@@ -29,6 +37,10 @@ import com.netease.nimlib.sdk.msg.model.RecentContact;
 import com.netease.nimlib.sdk.team.TeamService;
 import com.netease.nimlib.sdk.team.model.Team;
 import com.sheishuo.app.R;
+import com.sheishuo.app.common.beans.RequestBean;
+import com.sheishuo.app.common.util.net.INet;
+import com.sheishuo.app.common.util.net.NetImpl;
+import com.sheishuo.app.common.util.net.ResponseCallback;
 import com.sheishuo.app.common.views.BaseToolbar;
 import com.sheishuo.app.config.preference.Preferences;
 import com.sheishuo.app.core_module.friends.activity.AddNewFriendActivity;
@@ -71,6 +83,9 @@ public class SessionListFragment extends MainTabFragment {
     private MainActivity parent;
 
     private TextView searchTV;
+    private DropFake dropFake;
+
+    private INet net = new NetImpl();
 
     public SessionListFragment() {
         this.setContainerId(MainTab.RECENT_CONTACTS.fragmentId);
@@ -128,6 +143,7 @@ public class SessionListFragment extends MainTabFragment {
         });
 
         removeNotJoinTeamConversation();
+        fetchRequestBean();
     }
 
     @Override
@@ -135,6 +151,7 @@ public class SessionListFragment extends MainTabFragment {
     {
         super.onResume();
         removeNotJoinTeamConversation();
+        updateRequestBadge();
     }
 
     private void removeNotJoinTeamConversation()
@@ -154,6 +171,37 @@ public class SessionListFragment extends MainTabFragment {
         }
     }
 
+    private void fetchRequestBean()
+    {
+        net.requestList(new ResponseCallback() {
+            @Override
+            public void onSuccess(Object object) {
+                ContactsListActivity.requestBean = (RequestBean)object;
+                getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        updateRequestBadge();
+                    }
+                });
+            }
+
+            @Override
+            public void onFailed() {
+
+            }
+        });
+    }
+
+    private void updateRequestBadge()
+    {
+        if(ContactsListActivity.requestBean == null)
+            return;
+
+        int count = ContactsListActivity.requestBean.getD().size();
+        dropFake.setText(""+count);
+        dropFake.setVisibility(count>0?View.VISIBLE:View.GONE);
+    }
+
     private void registerObservers(boolean register) {
         NIMClient.getService(AuthServiceObserver.class).observeOtherClients(clientsObserver, register);
         NIMClient.getService(AuthServiceObserver.class).observeOnlineStatus(userStatusObserver, register);
@@ -185,15 +233,40 @@ public class SessionListFragment extends MainTabFragment {
             toolbar.setVisibility(View.VISIBLE);
             toolbar.setTitle("朋友");
 
+            RelativeLayout relativeLayout = new RelativeLayout(getContext());
+            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ScreenUtil.dip2px(48), ScreenUtil.dip2px(48));
+            relativeLayout.setLayoutParams(layoutParams);
+
             ImageView listIcon = new ImageView(getContext());
             listIcon.setImageResource(R.drawable.friends_contacts_list_ico);
-            listIcon.setOnClickListener(new View.OnClickListener() {
+            LinearLayout.LayoutParams iconLayoutParams = new LinearLayout.LayoutParams(ScreenUtil.dip2px(28), ScreenUtil.dip2px(28));
+            iconLayoutParams.setMargins(ScreenUtil.dip2px(10), ScreenUtil.dip2px(10), ScreenUtil.dip2px(10), ScreenUtil.dip2px(10));
+            listIcon.setLayoutParams(iconLayoutParams);
+            listIcon.setEnabled(false);
+            relativeLayout.addView(listIcon);
+
+            dropFake = new DropFake(getContext(), null);
+            LinearLayout.LayoutParams dropFakeLayoutParams = new LinearLayout.LayoutParams(ScreenUtil.dip2px(28), ScreenUtil.dip2px(28));
+            dropFakeLayoutParams.setMargins(ScreenUtil.dip2px(20), ScreenUtil.dip2px(0), ScreenUtil.dip2px(0), ScreenUtil.dip2px(10));
+            dropFake.setLayoutParams(dropFakeLayoutParams);
+            dropFake.setVisibility(View.GONE);
+            dropFake.setEnabled(false);
+
+            relativeLayout.addView(dropFake);
+
+            Button overlayBtn = new Button(getContext());
+            overlayBtn.setBackgroundColor(Color.parseColor("#00000000"));
+            overlayBtn.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+            overlayBtn.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
                     startActivity(new Intent(getActivity(),ContactsListActivity.class));
-
                 }
             });
+            relativeLayout.addView(overlayBtn);
+
+
+
 
             ImageView addIcon = new ImageView(getContext());
             addIcon.setImageResource(R.drawable.friends_add_ico);
@@ -204,7 +277,7 @@ public class SessionListFragment extends MainTabFragment {
                 }
             });
 
-            toolbar.setRightItems(new View[]{listIcon, addIcon});
+            toolbar.setRightItems(new View[]{relativeLayout, addIcon});
             toolbar.setLeftItems(new View[0]);
 
             parent.setSupportActionBar(toolbar);

+ 15 - 12
app/src/com/sheishuo/app/main/helper/MessageHelper.java

@@ -42,18 +42,19 @@ public class MessageHelper {
         } else if (message.getType() == SystemMessageType.RejectTeamApply) {
             sb.append(fromAccount).append("拒绝了你加入群 ").append(teamName).append("的申请");
         } else if (message.getType() == SystemMessageType.AddFriend) {
-            AddFriendNotify attachData = (AddFriendNotify) message.getAttachObject();
-            if (attachData != null) {
-                if (attachData.getEvent() == AddFriendNotify.Event.RECV_ADD_FRIEND_DIRECT) {
-                    sb.append("已添加你为好友");
-                } else if (attachData.getEvent() == AddFriendNotify.Event.RECV_AGREE_ADD_FRIEND) {
-                    sb.append("通过了你的好友请求");
-                } else if (attachData.getEvent() == AddFriendNotify.Event.RECV_REJECT_ADD_FRIEND) {
-                    sb.append("拒绝了你的好友请求");
-                } else if (attachData.getEvent() == AddFriendNotify.Event.RECV_ADD_FRIEND_VERIFY_REQUEST) {
-                    sb.append("请求添加好友" + (TextUtils.isEmpty(message.getContent()) ? "" : ":" + message.getContent()));
-                }
-            }
+            sb.append("" + (TextUtils.isEmpty(message.getContent()) ? "" : ":" + message.getContent()));
+//            AddFriendNotify attachData = (AddFriendNotify) message.getAttachObject();
+//            if (attachData != null) {
+//                if (attachData.getEvent() == AddFriendNotify.Event.RECV_ADD_FRIEND_DIRECT) {
+//                    sb.append("已添加你为好友");
+//                } else if (attachData.getEvent() == AddFriendNotify.Event.RECV_AGREE_ADD_FRIEND) {
+//                    sb.append("通过了你的好友请求");
+//                } else if (attachData.getEvent() == AddFriendNotify.Event.RECV_REJECT_ADD_FRIEND) {
+//                    sb.append("拒绝了你的好友请求");
+//                } else if (attachData.getEvent() == AddFriendNotify.Event.RECV_ADD_FRIEND_VERIFY_REQUEST) {
+//                    sb.append("请求添加好友" + (TextUtils.isEmpty(message.getContent()) ? "" : ":" + message.getContent()));
+//                }
+//            }
         }
 
         return sb.toString();
@@ -64,6 +65,8 @@ public class MessageHelper {
      */
     public static boolean isVerifyMessageNeedDeal(SystemMessage message) {
         if (message.getType() == SystemMessageType.AddFriend) {
+            if(true)
+                return true;
             if (message.getAttachObject() != null) {
                 AddFriendNotify attachData = (AddFriendNotify) message.getAttachObject();
                 if (attachData.getEvent() == AddFriendNotify.Event.RECV_ADD_FRIEND_DIRECT ||

+ 0 - 1
app/src/com/sheishuo/app/main/model/MainTab.java

@@ -45,7 +45,6 @@ public enum MainTab {
                 return value;
             }
         }
-
         return null;
     }
 

+ 1 - 1
app/src/com/sheishuo/app/session/SessionHelper.java

@@ -439,7 +439,7 @@ public class SessionHelper {
                         .setCallback(new RequestCallback<TeamMember>() {
                             @Override
                             public void onSuccess(TeamMember teamMember) {
-                                AitedContacts.getInstance().aitTeamMember(teamMember);
+                                AitedContacts.getInstance().aitTeamMemberForce(teamMember);
                             }
 
                             @Override

BIN
uikit/res/drawable-hdpi/nim_message_right_blue_bg.9.png


BIN
uikit/res/drawable-hdpi/nim_message_right_blue_bg_pressed.9.png


+ 0 - 4
uikit/res/layout/gift_panel.xml

@@ -175,10 +175,6 @@
                 android:layout_height="wrap_content"
                 android:orientation="horizontal">
 
-                <ImageView
-                    android:layout_width="48dp"
-                    android:layout_height="48dp"
-                    android:src="@drawable/nim_team_member_add_normal" />
             </LinearLayout>
         </HorizontalScrollView>
     </LinearLayout>

+ 1 - 1
uikit/res/layout/nim_message_activity_bottom_layout.xml

@@ -19,5 +19,5 @@
         android:id="@+id/gift_panel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:visibility="gone"/>
+        android:visibility="gone" />
 </LinearLayout>

+ 26 - 3
uikit/src/com/netease/nim/uikit/cache/NimUserInfoCache.java

@@ -36,6 +36,8 @@ public class NimUserInfoCache {
 
     private Map<String, List<RequestCallback<NimUserInfo>>> requestUserInfoMap = new ConcurrentHashMap<>(); // 重复请求处理
 
+    private Map<String, String> aliasMap = new ConcurrentHashMap<String, String>();
+
     /**
      * 构建缓存与清理
      */
@@ -197,13 +199,34 @@ public class NimUserInfoCache {
     }
 
     public String getAlias(String account) {
-        Friend friend = FriendDataCache.getInstance().getFriendByAccount(account);
-        if (friend != null && !TextUtils.isEmpty(friend.getAlias())) {
-            return friend.getAlias();
+//        Friend friend = FriendDataCache.getInstance().getFriendByAccount(account);
+//        if (friend != null && !TextUtils.isEmpty(friend.getAlias())) {
+//            return friend.getAlias();
+//        }
+//        return null;
+        if(aliasMap.containsKey(account))
+        {
+            return aliasMap.get(account);
         }
         return null;
     }
 
+    public void setAlias(String account, String alias)
+    {
+        if(aliasMap.containsKey(account))
+        {
+            if(!aliasMap.get(account).equals(alias))
+            {
+                aliasMap.remove(account);
+                aliasMap.put(account, alias);
+            }
+        }
+        else
+        {
+            aliasMap.put(account, alias);
+        }
+    }
+
     // 获取用户原本的昵称
     public String getUserName(String account) {
         NimUserInfo userInfo = getUserInfo(account);

+ 1 - 1
uikit/src/com/netease/nim/uikit/contact/ContactsFragment.java

@@ -109,7 +109,7 @@ public class ContactsFragment extends TFragment {
     }
 
     private void initAdapter() {
-        IContactDataProvider dataProvider = new ContactDataProvider(ItemTypes.FRIEND);
+        IContactDataProvider dataProvider = new ContactDataProvider(ItemTypes.FOLLOW);
 
         adapter = new ContactDataAdapter(getActivity(), new ContactsGroupStrategy(), dataProvider) {
             @Override

+ 1 - 0
uikit/src/com/netease/nim/uikit/contact/ait/AitContactsDataChangeListener.java

@@ -9,6 +9,7 @@ import com.netease.nimlib.sdk.team.model.TeamMember;
 
 public interface AitContactsDataChangeListener {
     void onAitTeamMemberAdded(TeamMember member);
+    void onAitTeamMemberAddedForce(TeamMember member);
 
     void onAitRobotAdded(NimRobotInfo robotInfo, boolean force);
 }

+ 7 - 0
uikit/src/com/netease/nim/uikit/contact/ait/AitedContacts.java

@@ -28,6 +28,13 @@ public class AitedContacts {
         }
     }
 
+    public void aitTeamMemberForce(TeamMember member) {
+        selectedMembers.put(member.getAccount(), member);
+        if (aitContactsDataChangeListener != null) {
+            aitContactsDataChangeListener.onAitTeamMemberAddedForce(member);
+        }
+    }
+
     public void aitRobot(NimRobotInfo robotInfo) {
         selectedRobots.put(robotInfo.getAccount(), robotInfo);
         if (aitContactsDataChangeListener != null) {

+ 2 - 0
uikit/src/com/netease/nim/uikit/contact/core/item/ItemTypes.java

@@ -26,6 +26,8 @@ public interface ItemTypes {
 
     int MSG = 4; // 消息
 
+    int FOLLOW = 5; // 关注
+
     /**
      * 子类型
      */

+ 5 - 5
uikit/src/com/netease/nim/uikit/contact/core/model/ContactDataAdapter.java

@@ -37,19 +37,19 @@ public class ContactDataAdapter extends BaseAdapter {
     // COMPONENTS
     //
 
-    private final Context context;
+    protected final Context context;
 
-    private final Map<Integer, Class<? extends AbsContactViewHolder<? extends AbsContactItem>>> viewHolderMap;
+    protected final Map<Integer, Class<? extends AbsContactViewHolder<? extends AbsContactItem>>> viewHolderMap;
 
-    private final ContactGroupStrategy groupStrategy;
+    protected final ContactGroupStrategy groupStrategy;
 
-    private final IContactDataProvider dataProvider;
+    protected final IContactDataProvider dataProvider;
 
     //
     // DATAS
     //
 
-    private AbsContactDataList datas;
+    protected AbsContactDataList datas;
 
     protected final HashMap<String, Integer> indexes = new HashMap<>();
 

+ 5 - 0
uikit/src/com/netease/nim/uikit/contact/core/model/IContact.java

@@ -23,6 +23,11 @@ public interface IContact {
          * TYPE_MSG
          */
         int Msg = 0x04;
+
+        /**
+         * TYPE_MSG
+         */
+        int Follow = 0x04;
     }
 
     /**

+ 3 - 1
uikit/src/com/netease/nim/uikit/contact/core/provider/ContactSearch.java

@@ -1,5 +1,6 @@
 package com.netease.nim.uikit.contact.core.provider;
 
+import com.netease.nim.uikit.cache.NimUserInfoCache;
 import com.netease.nim.uikit.contact.core.model.IContact;
 import com.netease.nim.uikit.contact.core.provider.ContactSearch.HitInfo.Type;
 import com.netease.nim.uikit.contact.core.query.TextQuery;
@@ -42,7 +43,8 @@ public class ContactSearch {
 
     public static final boolean hitFriend(Friend friend, TextQuery query) {
         String account = friend.getAccount();
-        String alias = friend.getAlias();
+        //String alias = friend.getAlias();
+        String alias = NimUserInfoCache.getInstance().getAlias(friend.getAccount());
 
         return TextSearcher.contains(query.t9, account, query.text) || TextSearcher.contains(query.t9, alias, query.text);
     }

+ 1 - 1
uikit/src/com/netease/nim/uikit/contact/core/viewholder/ContactHolder.java

@@ -29,7 +29,7 @@ public class ContactHolder extends AbsContactViewHolder<ContactItem> {
     public void refresh(ContactDataAdapter adapter, int position, final ContactItem item) {
         // contact info
         final IContact contact = item.getContact();
-        if (contact.getContactType() == IContact.Type.Friend) {
+        if (contact.getContactType() == IContact.Type.Friend || contact.getContactType() == IContact.Type.Follow) {
             head.loadBuddyAvatar(contact.getContactId());
         } else {
             Team team = TeamDataCache.getInstance().getTeamById(contact.getContactId());

+ 1 - 1
uikit/src/com/netease/nim/uikit/contact_selector/viewholder/ContactsSelectHolder.java

@@ -58,7 +58,7 @@ public class ContactsSelectHolder extends AbsContactViewHolder<ContactItem> {
         IContact contact = item.getContact();
         this.nickname.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
         this.nickname.setText(contact.getDisplayName());
-        if (contact.getContactType() == IContact.Type.Friend || contact.getContactType() == IContact.Type.TeamMember) {
+        if (contact.getContactType() == IContact.Type.Friend || contact.getContactType() == IContact.Type.TeamMember || contact.getContactType() == IContact.Type.Follow) {
             this.nickname.setText(contact.getDisplayName());
             this.image.loadBuddyAvatar(contact.getContactId());
         } else if (contact.getContactType() == IContact.Type.Team) {

+ 5 - 4
uikit/src/com/netease/nim/uikit/session/activity/WatchPictureActivity.java

@@ -288,7 +288,7 @@ public class WatchPictureActivity extends UI {
 
     private void doSaveImage(Bitmap bitmap)
     {
-        boolean success = saveImageToGallery(getBaseContext(), bitmap);
+        boolean success = saveImageToGallery(WatchPictureActivity.this, bitmap);
 //        String msg = success ? "保存图片成功" : "保存图片失败";
 //        EasyAlertDialogHelper.showOneButtonDiolag(this, "提示", msg, "确认", false, null);
 //
@@ -319,11 +319,12 @@ public class WatchPictureActivity extends UI {
             Uri uri = Uri.fromFile(file);
             context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
             if (isSuccess) {
-                EasyAlertDialogHelper.showOneButtonDiolag(context, "提示", "图片已保存至"+uri.getPath(), "确认", false, null);
-                //Toast.makeText(context, "图片已保存至"+uri.getPath(), Toast.LENGTH_SHORT);
+                //EasyAlertDialogHelper.showOneButtonDiolag(context, "提示", "图片已保存至"+uri.getPath(), "确认", false, null);
+                Toast.makeText(context, "图片已保存至"+uri.getPath(), Toast.LENGTH_SHORT).show();
                 return true;
             } else {
-                EasyAlertDialogHelper.showOneButtonDiolag(context, "提示", "保存图片失败", "确认", false, null);
+                //EasyAlertDialogHelper.showOneButtonDiolag(context, "提示", "保存图片失败", "确认", false, null);
+                Toast.makeText(context, "保存图片失败", Toast.LENGTH_SHORT).show();
                 return false;
             }
         } catch (IOException e) {

+ 14 - 7
uikit/src/com/netease/nim/uikit/session/module/input/InputPanel.java

@@ -340,11 +340,11 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
                 sendTypingCommand();
 
                 //去除掉多余的@符号
-                if (s.toString().equals("@")){
-                    String str = messageEditText.getText().toString();
-                    str = str.substring(0,str.length() - 1);
-                    messageEditText.setText(str);
-                }
+//                if (s.toString().equals("@")){
+//                    String str = messageEditText.getText().toString();
+//                    str = str.substring(0,str.length() - 1);
+//                    messageEditText.setText(str);
+//                }
             }
         });
     }
@@ -705,6 +705,13 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
     }
 
     @Override
+    public void onAitTeamMemberAddedForce(TeamMember member) {
+        String account = "@" + member.getAccount();
+        String aitName = TeamMemberAitHelper.getAitName(member);
+        insertAitMember(account, aitName, true);
+    }
+
+    @Override
     public void onAitRobotAdded(NimRobotInfo robotInfo, boolean force) {
         String account = robotInfo.getAccount();
         if (force) {
@@ -953,8 +960,8 @@ public class InputPanel implements IEmoticonSelectedListener, IAudioRecordCallba
         int length = account.length();
         // 不是输入的@,而是插进来的
         if (!force) {
-            //start--;
-            //length++;
+            start--;
+            length++;
         }
 
         editable.setSpan(TeamMemberAitHelper.getInputAitSpan(aitName, messageEditText.getTextSize(), messageEditText.getMeasuredWidth()),