DoggyZhang 4 сар өмнө
parent
commit
3d6ff40e06
44 өөрчлөгдсөн 1081 нэмэгдсэн , 103 устгасан
  1. 1 1
      app/src/main/java/com/adealink/weparty/debug/DebugPrefs.kt
  2. 6 0
      app/src/main/java/com/adealink/weparty/module/im/Router.kt
  3. 2 1
      app/src/main/java/com/adealink/weparty/network/NetworkEnv.kt
  4. 22 0
      app/src/main/java/com/adealink/weparty/permission/PermissionPerf.kt
  5. 35 23
      app/src/main/java/com/adealink/weparty/push/NotificationUtil.kt
  6. 2 2
      app/src/main/java/com/adealink/weparty/ui/main/tab/MainTab.kt
  7. BIN
      app/src/main/res/drawable-xhdpi/common_app_clean_message_ic.png
  8. BIN
      app/src/main/res/drawable-xhdpi/common_app_language_ic.png
  9. BIN
      app/src/main/res/drawable-xhdpi/common_app_profile_ic.png
  10. BIN
      app/src/main/res/drawable-xhdpi/common_app_search_ic.png
  11. BIN
      app/src/main/res/drawable-xhdpi/common_close_ic.png
  12. 1 4
      app/src/main/res/drawable/common_red_dot_normal_bg.xml
  13. 1 4
      app/src/main/res/drawable/common_red_dot_text_bg.xml
  14. 4 0
      frame/tuikit/TUIConversation/tuiconversation/src/main/java/com/tencent/qcloud/tuikit/tuiconversation/presenter/ConversationPresenter.java
  15. 0 5
      module/im/src/main/AndroidManifest.xml
  16. 62 0
      module/im/src/main/java/com/adealink/weparty/im/SessionHomeListFragment.kt
  17. 0 35
      module/im/src/main/java/com/adealink/weparty/im/SessionListActivity.kt
  18. 149 0
      module/im/src/main/java/com/adealink/weparty/im/SessionListFragment.kt
  19. 59 0
      module/im/src/main/java/com/adealink/weparty/im/adapter/SessionListAdapter.kt
  20. 4 0
      module/im/src/main/java/com/adealink/weparty/im/adapter/data/BaseSessionData.kt
  21. 8 0
      module/im/src/main/java/com/adealink/weparty/im/adapter/data/SessionListData.kt
  22. 60 0
      module/im/src/main/java/com/adealink/weparty/im/comp/SessionPermissionComp.kt
  23. 1 3
      module/im/src/main/java/com/adealink/weparty/im/manager/IMLoginManager.kt
  24. 22 0
      module/im/src/main/java/com/adealink/weparty/im/viewmodel/IMViewModelFactory.kt
  25. 11 0
      module/im/src/main/java/com/adealink/weparty/im/viewmodel/SessionListViewModel.kt
  26. BIN
      module/im/src/main/res/drawable-xhdpi/im_official_avatar_ic.png
  27. 8 0
      module/im/src/main/res/drawable/im_open_notification_bg.xml
  28. 12 0
      module/im/src/main/res/drawable/im_turn_on_notification_bg.xml
  29. 0 24
      module/im/src/main/res/layout/activity_session_list.xml
  30. 79 0
      module/im/src/main/res/layout/fragment_session_home_list.xml
  31. 53 0
      module/im/src/main/res/layout/fragment_session_list.xml
  32. 84 0
      module/im/src/main/res/layout/layout_session_list_item.xml
  33. 85 0
      module/im/src/main/res/layout/layout_session_list_system_item.xml
  34. 73 0
      module/im/src/main/res/layout/layout_session_open_notification.xml
  35. 4 1
      module/im/src/main/res/values/strings.xml
  36. 4 0
      module/profile/src/main/AndroidManifest.xml
  37. 53 0
      module/profile/src/main/java/com/adealink/weparty/profile/search/SearchActivity.kt
  38. 30 0
      module/profile/src/main/java/com/adealink/weparty/profile/search/adapter/SearchItemViewBinder.kt
  39. 12 0
      module/profile/src/main/java/com/adealink/weparty/profile/search/data/SearchData.kt
  40. BIN
      module/profile/src/main/res/drawable-xhdpi/profile_search_input_ic.png
  41. 8 0
      module/profile/src/main/res/drawable/profile_search_input_bg.xml
  42. 92 0
      module/profile/src/main/res/layout/activity_user_search.xml
  43. 33 0
      module/profile/src/main/res/layout/layout_profile_search_item.xml
  44. 1 0
      module/profile/src/main/res/values/strings.xml

+ 1 - 1
app/src/main/java/com/adealink/weparty/debug/DebugPrefs.kt

@@ -15,7 +15,7 @@ object DebugPrefs : TypeDelegationPrefs(
     }
 ) {
 
-    var httpUrl: String by PrefKey("key_http_url", "http://${getLocalHost()}/")
+    var httpUrl: String by PrefKey("key_http_url", "https://${getLocalHost()}/")
     //没有socket长连接
 //    var socketUrl: String by PrefKey("key_socket_url", "ws://${getLocalHost()}/websocket")
 

+ 6 - 0
app/src/main/java/com/adealink/weparty/module/im/Router.kt

@@ -8,6 +8,12 @@ interface IM {
         }
     }
 
+    interface HomeList {
+        companion object {
+            const val PATH = "${Common.PATH}/home_list"
+        }
+    }
+
     interface SessionList {
         companion object {
             const val PATH = "${Common.PATH}/session_list"

+ 2 - 1
app/src/main/java/com/adealink/weparty/network/NetworkEnv.kt

@@ -7,7 +7,8 @@ import com.adealink.frame.base.AppBase
 val RELEASE_HOSTS = emptyList<String>() //listOf("api.yoki.chat") //主域名,优先访问
 val BACKUP_HOSTS = emptyList<String>() //listOf("yokiback.wenext.website") //备用域名,主域名访问不通时使用
 const val CDN_HOST = "yoki-user-cf.wenext.media"
-const val DEBUG_HOST_CN = "test-api.lanu.live"
+const val DEBUG_HOST_CN = "test-api.gami.vip"
+
 val WEB_PRIMARY_DOMAINS = listOf(
     "wenext.love",
     "appmisu.com",

+ 22 - 0
app/src/main/java/com/adealink/weparty/permission/PermissionPerf.kt

@@ -0,0 +1,22 @@
+package com.adealink.weparty.permission
+
+import android.content.Context
+import com.adealink.frame.storage.sp.TypeDelegationPrefs
+import com.adealink.frame.util.AppUtil
+import com.adealink.weparty.module.profile.ProfileModule
+
+object PermissionPerf : TypeDelegationPrefs(
+    prefs = {
+        AppUtil.appContext.getSharedPreferences("pref_permission", Context.MODE_PRIVATE)
+    },
+    userId = {
+        ProfileModule.getMyUid()
+    }
+) {
+
+    /**
+     * 下一次检查时间
+     */
+    var checkNotificationTs: Long by PrefUserKey("key_check_notification_ts", 0)
+
+}

+ 35 - 23
app/src/main/java/com/adealink/weparty/push/NotificationUtil.kt

@@ -1,5 +1,6 @@
 package com.adealink.weparty.push
 
+import android.Manifest
 import android.annotation.SuppressLint
 import android.app.ActivityOptions
 import android.app.Notification
@@ -34,6 +35,8 @@ import com.adealink.frame.util.PackageUtil
 import com.adealink.weparty.AppModule
 import com.adealink.weparty.R
 import com.adealink.weparty.commonui.imageview.CircleDrawable
+import com.adealink.weparty.commonui.widget.CommonDialog
+import com.adealink.weparty.permission.PermissionUtils
 import com.adealink.weparty.push.data.JiehePushMessage
 import com.adealink.weparty.push.data.PushMessageType
 import kotlinx.coroutines.CoroutineScope
@@ -227,32 +230,41 @@ object NotificationUtil {
         }
     }
 
+    fun isNotificationPermissionGranted(activity: FragmentActivity): Boolean {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+            return true
+        }
 
+        if (PermissionUtils.hasPermissions(activity, Manifest.permission.POST_NOTIFICATIONS)) {
+            return true
+        }
+        return false
+    }
 
     @SuppressLint("CheckResult")
     fun requestPostNotificationPermission(activity: FragmentActivity) {
-//        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
-//            return
-//        }
-//
-//        if (PermissionUtils.hasPermissions(activity, Manifest.permission.POST_NOTIFICATIONS)) {
-//            return
-//        }
-//
-//        PermissionUtils.getRxPermissions(activity)
-//            .request(Manifest.permission.POST_NOTIFICATIONS).subscribe { granted ->
-//                if (!granted) {
-//                    CommonDialog.Builder()
-//                        .message(getCompatString(R.string.common_open_notification_tip))
-//                        .onPositive {
-//                            PermissionUtils.goNotificationSettingActivity(activity)
-//                        }
-//                        .positiveText(getCompatString(R.string.common_open))
-//                        .setShowDefaultCancel(true)
-//                        .dismissAfterClick(true)
-//                        .build()
-//                        .show(activity.supportFragmentManager, "POST_NOTIFICATIONS_PERMISSION_NO_GRANT")
-//                }
-//            }
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+            return
+        }
+
+        if (PermissionUtils.hasPermissions(activity, Manifest.permission.POST_NOTIFICATIONS)) {
+            return
+        }
+
+        PermissionUtils.getRxPermissions(activity)
+            .request(Manifest.permission.POST_NOTIFICATIONS).subscribe { granted ->
+                if (!granted) {
+                    CommonDialog.Builder()
+                        .message(getCompatString(R.string.common_open_notification_tip))
+                        .onPositive {
+                            PermissionUtils.goNotificationSettingActivity(activity)
+                        }
+                        .positiveText(getCompatString(R.string.common_open))
+                        .setShowDefaultCancel(true)
+                        .dismissAfterClick(true)
+                        .build()
+                        .show(activity.supportFragmentManager, "POST_NOTIFICATIONS_PERMISSION_NO_GRANT")
+                }
+            }
     }
 }

+ 2 - 2
app/src/main/java/com/adealink/weparty/ui/main/tab/MainTab.kt

@@ -6,9 +6,9 @@ import com.adealink.frame.router.Router
 import com.adealink.weparty.R
 import com.adealink.weparty.commonui.BaseFragment
 import com.adealink.weparty.commonui.widget.EmptyFragment
+import com.adealink.weparty.module.im.IM
 import com.adealink.weparty.module.profile.Profile
 import com.adealink.weparty.ui.home.HomeFragment
-import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page.TUIConversationMinimalistFragment
 
 enum class MainTab(val tab: String, val number: Int) {
     /**
@@ -56,7 +56,7 @@ val MESSAGE_TAB = Tab(
         getCompatString(R.string.common_main_message_tab)
     },
     fragmentBuilder = {
-        TUIConversationMinimalistFragment()
+        Router.getRouterInstance<BaseFragment>(IM.HomeList.PATH) ?: EmptyFragment()
     }
 )
 

BIN
app/src/main/res/drawable-xhdpi/common_app_clean_message_ic.png


BIN
app/src/main/res/drawable-xhdpi/common_app_language_ic.png


BIN
app/src/main/res/drawable-xhdpi/common_app_profile_ic.png


BIN
app/src/main/res/drawable-xhdpi/common_app_search_ic.png


BIN
app/src/main/res/drawable-xhdpi/common_close_ic.png


+ 1 - 4
app/src/main/res/drawable/common_red_dot_normal_bg.xml

@@ -1,8 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="oval">
-    <stroke
-        android:width="1dp"
-        android:color="@color/white" />
-    <solid android:color="#FF6150" />
+    <solid android:color="#F23051" />
 </shape>

+ 1 - 4
app/src/main/res/drawable/common_red_dot_text_bg.xml

@@ -1,9 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <stroke
-        android:width="1dp"
-        android:color="@color/white" />
     <corners android:radius="16dp" />
-    <solid android:color="#FF6150" />
+    <solid android:color="#F23051" />
 </shape>

+ 4 - 0
frame/tuikit/TUIConversation/tuiconversation/src/main/java/com/tencent/qcloud/tuikit/tuiconversation/presenter/ConversationPresenter.java

@@ -4,7 +4,9 @@ import android.content.Context;
 import android.content.Intent;
 import android.text.TextUtils;
 import android.util.Pair;
+
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
 import com.tencent.imsdk.v2.V2TIMConversation;
 import com.tencent.imsdk.v2.V2TIMConversationListFilter;
 import com.tencent.imsdk.v2.V2TIMUserStatus;
@@ -31,6 +33,7 @@ import com.tencent.qcloud.tuikit.tuiconversation.config.TUIConversationConfig;
 import com.tencent.qcloud.tuikit.tuiconversation.interfaces.ConversationEventListener;
 import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
 import com.tencent.qcloud.tuikit.tuiconversation.model.ConversationProvider;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -124,6 +127,7 @@ public class ConversationPresenter {
 
             @Override
             public void onNewConversation(List<ConversationInfo> conversationList) {
+                TUIConversationLog.i(TAG, "onNewConversation: " + conversationList.size());
                 ConversationPresenter.this.onNewConversation(conversationList, false);
                 if (updateMarkedUnreadAndHiddenList(conversationList)) {
                     refreshUnreadCount();

+ 0 - 5
module/im/src/main/AndroidManifest.xml

@@ -20,11 +20,6 @@
 
     <application>
 
-        <activity
-            android:name=".SessionListActivity"
-            android:screenOrientation="portrait"
-            android:theme="@style/AppTheme" />
-
     </application>
 
 </manifest>

+ 62 - 0
module/im/src/main/java/com/adealink/weparty/im/SessionHomeListFragment.kt

@@ -0,0 +1,62 @@
+package com.adealink.weparty.im
+
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.view.updateLayoutParams
+import androidx.fragment.app.viewModels
+import com.adealink.frame.mvvm.view.viewBinding
+import com.adealink.frame.router.Router
+import com.adealink.frame.router.annotation.RouterUri
+import com.adealink.frame.util.DisplayUtil.getStatusBarHeight
+import com.adealink.frame.util.onClick
+import com.adealink.weparty.commonui.BaseFragment
+import com.adealink.weparty.im.databinding.FragmentSessionHomeListBinding
+import com.adealink.weparty.im.viewmodel.IMViewModelFactory
+import com.adealink.weparty.im.viewmodel.SessionListViewModel
+import com.adealink.weparty.module.im.IM
+import com.adealink.weparty.module.profile.Profile
+
+
+@RouterUri(
+    path = [IM.HomeList.PATH],
+    desc = "IM首页会话列表"
+)
+class SessionHomeListFragment : BaseFragment(R.layout.fragment_session_home_list) {
+
+    private val binding by viewBinding(FragmentSessionHomeListBinding::bind)
+
+    private val viewModel by viewModels<SessionListViewModel> { IMViewModelFactory() }
+
+    override fun initViews() {
+        super.initViews()
+        binding.clTopBar.updateLayoutParams<ConstraintLayout.LayoutParams> {
+            topMargin = activity?.let { act ->
+                getStatusBarHeight(act)
+            } ?: 0
+        }
+        binding.ivSearch.onClick {
+            goSearch()
+        }
+        binding.ivClearMessage.onClick {
+            clearMessage()
+        }
+
+        //val fragment = TUIConversationMinimalistFragment()
+        val fragment = SessionListFragment()
+        childFragmentManager
+            .beginTransaction()
+            .add(R.id.fl_content, fragment)
+            .commitAllowingStateLoss()
+
+    }
+
+    private fun goSearch() {
+        activity?.let { act ->
+            Router.build(act, Profile.Search.PATH).start()
+        }
+    }
+
+    private fun clearMessage() {
+        viewModel.clearMessage()
+    }
+
+}

+ 0 - 35
module/im/src/main/java/com/adealink/weparty/im/SessionListActivity.kt

@@ -1,35 +0,0 @@
-package com.adealink.weparty.im
-
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.core.view.updateLayoutParams
-import com.adealink.frame.mvvm.view.viewBinding
-import com.adealink.frame.router.annotation.RouterUri
-import com.adealink.frame.util.DisplayUtil.getStatusBarHeight
-import com.adealink.weparty.commonui.BaseActivity
-import com.adealink.weparty.im.databinding.ActivitySessionListBinding
-import com.adealink.weparty.module.im.IM
-import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page.TUIConversationMinimalistFragment
-
-
-@RouterUri(
-    path = [IM.SessionList.PATH],
-    desc = "IM会话列表"
-)
-class SessionListActivity : BaseActivity() {
-
-    private val binding by viewBinding(ActivitySessionListBinding::inflate)
-    override fun initViews() {
-        super.initViews()
-        setContentView(binding.root)
-        binding.topBar.updateLayoutParams<ConstraintLayout.LayoutParams> {
-            topMargin = getStatusBarHeight(this@SessionListActivity)
-        }
-        val fragment = TUIConversationMinimalistFragment()
-        supportFragmentManager
-            .beginTransaction()
-            .add(R.id.fl_content, fragment)
-            .commitAllowingStateLoss()
-
-    }
-
-}

+ 149 - 0
module/im/src/main/java/com/adealink/weparty/im/SessionListFragment.kt

@@ -0,0 +1,149 @@
+package com.adealink.weparty.im
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.view.View
+import androidx.fragment.app.viewModels
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.adealink.frame.base.fastLazy
+import com.adealink.frame.mvvm.view.viewBinding
+import com.adealink.frame.router.annotation.RouterUri
+import com.adealink.frame.util.AppUtil
+import com.adealink.weparty.commonui.BaseFragment
+import com.adealink.weparty.im.comp.SessionPermissionComp
+import com.adealink.weparty.im.databinding.FragmentSessionListBinding
+import com.adealink.weparty.im.viewmodel.IMViewModelFactory
+import com.adealink.weparty.im.viewmodel.SessionListViewModel
+import com.adealink.weparty.module.im.IM
+import com.tencent.qcloud.tuicore.TUIConstants
+import com.tencent.qcloud.tuikit.timcommon.component.swipe.Attributes
+import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo
+import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter
+import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.OnConversationAdapterListener
+import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.util.TUIConversationUtils
+import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationListAdapter
+import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter
+
+
+@RouterUri(
+    path = [IM.SessionList.PATH],
+    desc = "IM会话列表"
+)
+class SessionListFragment : BaseFragment(R.layout.fragment_session_list) {
+
+    private val binding by viewBinding(FragmentSessionListBinding::bind)
+
+    private val viewModel by viewModels<SessionListViewModel> { IMViewModelFactory() }
+    private val presenter: ConversationPresenter by fastLazy { ConversationPresenter() }
+    private val sessionAdapter: IConversationListAdapter by fastLazy { ConversationListAdapter().apply {
+        mode = Attributes.Mode.Single
+    } }
+    private lateinit var unreadCountReceiver: BroadcastReceiver
+
+    override fun initViews() {
+        super.initViews()
+        initSessionList()
+        initUnreadCountReceiver()
+    }
+
+    override fun initComponents() {
+        super.initComponents()
+        SessionPermissionComp(this, binding.vOpenNotification).attach()
+    }
+
+    private fun initSessionList() {
+        binding.conversationLayout.layoutManager =
+            LinearLayoutManager(context, RecyclerView.VERTICAL, false)
+
+        presenter.setAdapter(sessionAdapter)
+        presenter.setConversationListener()
+        presenter.setShowType(ConversationPresenter.SHOW_TYPE_CONVERSATION_LIST_WITH_FOLD)
+        binding.conversationLayout.setAdapter(sessionAdapter)
+        binding.conversationLayout.setPresenter(presenter)
+
+        binding.conversationLayout.setOnConversationAdapterListener(object :
+            OnConversationAdapterListener {
+            override fun onItemClick(
+                view: View?,
+                viewType: Int,
+                conversationInfo: ConversationInfo?
+            ) {
+                TUIConversationUtils.startChatActivity(conversationInfo)
+            }
+
+            override fun onItemLongClick(
+                view: View?,
+                conversationInfo: ConversationInfo?
+            ) {
+            }
+
+            override fun onConversationChanged(dataSource: List<ConversationInfo?>?) {
+            }
+
+            override fun onMarkConversationUnread(
+                view: View?,
+                conversationInfo: ConversationInfo?,
+                markUnread: Boolean
+            ) {
+            }
+
+            override fun onMarkConversationHidden(
+                view: View?,
+                conversationInfo: ConversationInfo?
+            ) {
+            }
+
+            override fun onClickMoreView(
+                view: View?,
+                conversationInfo: ConversationInfo?
+            ) {
+            }
+
+            override fun onSwipeConversationChanged(conversationInfo: ConversationInfo?) {
+            }
+        })
+    }
+
+    private fun initUnreadCountReceiver() {
+        unreadCountReceiver = object : BroadcastReceiver() {
+            override fun onReceive(context: Context?, intent: Intent) {
+                val unreadCount = intent.getLongExtra(TUIConstants.UNREAD_COUNT_EXTRA, 0)
+                if (unreadCount > 0) {
+                    // TODO: 更新未读数
+//                    isShowReadAllButton = true
+                } else {
+//                    isShowReadAllButton = false
+                }
+            }
+        }
+        val unreadCountFilter = IntentFilter()
+        unreadCountFilter.addAction(TUIConstants.CONVERSATION_UNREAD_COUNT_ACTION)
+        LocalBroadcastManager.getInstance(AppUtil.appContext)
+            .registerReceiver(unreadCountReceiver, unreadCountFilter)
+    }
+
+    override fun loadData() {
+        super.loadData()
+//        binding.conversationLayout.loadConversation()
+//        binding.conversationLayout.loadMarkedConversation()
+    }
+
+    override fun onResume() {
+        super.onResume()
+        binding.conversationLayout.loadConversation()
+        binding.conversationLayout.loadMarkedConversation()
+    }
+
+    override fun onDestroyView() {
+        super.onDestroyView()
+        unreadCountReceiver?.let { receiver ->
+            LocalBroadcastManager.getInstance(AppUtil.appContext).unregisterReceiver(receiver)
+        }
+        presenter.destroy()
+    }
+
+}

+ 59 - 0
module/im/src/main/java/com/adealink/weparty/im/adapter/SessionListAdapter.kt

@@ -0,0 +1,59 @@
+package com.adealink.weparty.im.adapter
+
+import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
+import com.adealink.weparty.im.adapter.data.SessionListItem
+import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo
+import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter
+import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.OnConversationAdapterListener
+import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationListAdapter
+
+/**
+ * 参考 ConversationListAdapter, 抽象出业务逻辑
+ */
+class SessionListAdapter : MultiTypeListAdapter<SessionListItem>(), IConversationListAdapter {
+
+    private var mIsLoading = false
+    private var mOnConversationAdapterListener: OnConversationAdapterListener? = null
+
+    fun setOnConversationAdapterListener(listener: OnConversationAdapterListener?) {
+        this.mOnConversationAdapterListener = listener
+    }
+
+    override fun onLoadingStateChanged(isLoading: Boolean) {
+        this.mIsLoading = isLoading
+        notifyItemChanged(itemCount - 1)
+    }
+
+    override fun onDataSourceChanged(conversationInfoList: List<ConversationInfo?>?) {
+        items = conversationInfoList?.mapNotNull { it } ?: emptyList()
+    }
+
+    override fun onViewNeedRefresh() {
+        notifyDataSetChanged()
+    }
+
+    override fun onItemRemoved(position: Int) {
+        notifyItemRemoved(position)
+    }
+
+    private fun getItemIndexInAdapter(index: Int): Int {
+        val itemIndex: Int = index + ConversationListAdapter.HEADER_COUNT
+        return itemIndex
+    }
+
+    override fun onItemInserted(position: Int) {
+        notifyItemInserted(position)
+    }
+
+    override fun onItemChanged(position: Int) {
+        notifyItemChanged(position)
+    }
+
+    override fun onItemRangeChanged(startPosition: Int, count: Int) {
+        notifyItemRangeChanged(startPosition, count)
+    }
+
+    override fun onConversationChanged(conversationInfoList: List<ConversationInfo?>?) {
+        mOnConversationAdapterListener?.onConversationChanged(conversationInfoList);
+    }
+}

+ 4 - 0
module/im/src/main/java/com/adealink/weparty/im/adapter/data/BaseSessionData.kt

@@ -0,0 +1,4 @@
+package com.adealink.weparty.im.adapter.data
+
+class BaseSessionData {
+}

+ 8 - 0
module/im/src/main/java/com/adealink/weparty/im/adapter/data/SessionListData.kt

@@ -0,0 +1,8 @@
+package com.adealink.weparty.im.adapter.data
+
+import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
+import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo
+
+sealed class SessionListItem :
+    ConversationInfo(),
+    BaseListItemData

+ 60 - 0
module/im/src/main/java/com/adealink/weparty/im/comp/SessionPermissionComp.kt

@@ -0,0 +1,60 @@
+package com.adealink.weparty.im.comp
+
+import androidx.lifecycle.LifecycleOwner
+import com.adealink.frame.mvvm.view.ViewComponent
+import com.adealink.frame.util.onClick
+import com.adealink.weparty.commonui.ext.gone
+import com.adealink.weparty.commonui.ext.show
+import com.adealink.weparty.im.databinding.LayoutSessionOpenNotificationBinding
+import com.adealink.weparty.push.NotificationUtil
+
+class SessionPermissionComp(
+    lifecycleOwner: LifecycleOwner,
+    val notificationBinding: LayoutSessionOpenNotificationBinding
+) : ViewComponent(lifecycleOwner) {
+
+    override fun onCreate() {
+        super.onCreate()
+        initView()
+    }
+
+    private fun initView() {
+        notificationBinding.ivClose.onClick {
+            ignoreNotificationPermission()
+        }
+        notificationBinding.btnTurnOn.onClick {
+            requestNotificationPermission()
+        }
+    }
+
+    override fun onResume() {
+        super.onResume()
+        checkPermission()
+    }
+
+    private fun checkPermission() {
+        checkNotification()
+    }
+
+    /**
+     * 检查通知权限是否打开
+     */
+    private fun checkNotification() {
+        val activity = activity ?: return
+        if (NotificationUtil.isNotificationPermissionGranted(activity)) {
+            notificationBinding.root.gone()
+            return
+        }
+        notificationBinding.root.show()
+    }
+
+    private fun ignoreNotificationPermission() {
+        notificationBinding.root.gone()
+    }
+
+    private fun requestNotificationPermission() {
+        val activity = activity ?: return
+        NotificationUtil.requestPostNotificationPermission(activity)
+    }
+
+}

+ 1 - 3
module/im/src/main/java/com/adealink/weparty/im/manager/IMLoginManager.kt

@@ -9,7 +9,6 @@ import com.adealink.weparty.call.manager.ICallLoginManager
 import com.adealink.weparty.im.constant.TAG_IM_LOGIN
 import com.adealink.weparty.im.service.TIMAppService
 import com.adealink.weparty.im.util.TUIUtils
-import com.adealink.weparty.module.account.AccountLocalService
 import com.adealink.weparty.module.account.AccountModule
 import com.adealink.weparty.module.account.ILoginListener
 import com.adealink.weparty.module.im.IMConfig
@@ -57,8 +56,7 @@ class IMLoginManager : BaseFrame<ICallLoginListener>(),
             Log.d(TAG_IM_LOGIN, "login return, TUILogin.isUserLogined")
             return
         }
-        //val uid = AccountModule.uid
-        val uid = AccountLocalService.testAccount
+        val uid = AccountModule.uid
         if (uid.isEmpty()) {
             Log.e(TAG_IM_LOGIN, "handleLogin fail, for $uid is invalid.")
             return

+ 22 - 0
module/im/src/main/java/com/adealink/weparty/im/viewmodel/IMViewModelFactory.kt

@@ -0,0 +1,22 @@
+package com.adealink.weparty.im.viewmodel
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+
+@Suppress("UNCHECKED_CAST")
+class IMViewModelFactory : ViewModelProvider.NewInstanceFactory() {
+
+    override fun <T : ViewModel> create(modelClass: Class<T>): T {
+        return with(modelClass) {
+            when {
+                isAssignableFrom(SessionListViewModel::class.java) ->
+                    SessionListViewModel()
+
+
+                else ->
+                    throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
+            } as T
+        }
+    }
+
+}

+ 11 - 0
module/im/src/main/java/com/adealink/weparty/im/viewmodel/SessionListViewModel.kt

@@ -0,0 +1,11 @@
+package com.adealink.weparty.im.viewmodel
+
+import com.adealink.frame.mvvm.viewmodel.BaseViewModel
+
+class SessionListViewModel: BaseViewModel() {
+
+    fun clearMessage(){
+
+    }
+
+}

BIN
module/im/src/main/res/drawable-xhdpi/im_official_avatar_ic.png


+ 8 - 0
module/im/src/main/res/drawable/im_open_notification_bg.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <solid android:color="@color/white" />
+    <corners android:radius="12dp" />
+
+</shape>

+ 12 - 0
module/im/src/main/res/drawable/im_turn_on_notification_bg.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <corners android:radius="30dp" />
+
+    <gradient
+        android:endColor="#B1EF5D"
+        android:startColor="#4ED2FF"
+        android:type="linear" />
+
+</shape>

+ 0 - 24
module/im/src/main/res/layout/activity_session_list.xml

@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <com.adealink.weparty.commonui.widget.CommonTopBar
-        android:id="@+id/top_bar"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/common_top_bar_height"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <androidx.fragment.app.FragmentContainerView
-        android:id="@+id/fl_content"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/top_bar" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 79 - 0
module/im/src/main/res/layout/fragment_session_home_list.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/color_FFF1F2F5">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintDimensionRatio="375:173"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/common_app_top_bg_ic" />
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_top_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingHorizontal="16dp"
+        android:paddingTop="16dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:layout_width="42dp"
+            android:layout_height="22dp"
+            app:layout_constraintBottom_toBottomOf="@id/tv_title"
+            app:layout_constraintEnd_toEndOf="@id/tv_title"
+            app:layout_constraintStart_toStartOf="@id/tv_title"
+            app:layout_constraintTop_toTopOf="@id/tv_title"
+            app:srcCompat="@drawable/common_home_main_tab_selected_ic" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@font/poppins_semibold"
+            android:includeFontPadding="false"
+            android:text="@string/im_session_list_title"
+            android:textColor="@color/color_FF4E5969"
+            android:textSize="24sp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_search"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:layout_marginEnd="14dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/iv_clear_message"
+            app:layout_constraintTop_toTopOf="parent"
+            app:srcCompat="@drawable/common_app_search_ic" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_clear_message"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:srcCompat="@drawable/common_app_clean_message_ic" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.fragment.app.FragmentContainerView
+        android:id="@+id/fl_content"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/cl_top_bar" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 53 - 0
module/im/src/main/res/layout/fragment_session_list.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.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"
+    tools:background="@color/color_FFF1F2F5">
+
+    <include
+        android:id="@+id/v_open_notification"
+        layout="@layout/layout_session_open_notification"
+        android:layout_width="match_parent"
+        android:layout_height="50dp"
+        android:layout_marginHorizontal="16dp"
+        android:visibility="gone"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:visibility="visible" />
+
+    <com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationListLayout
+        android:id="@+id/conversation_layout"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_marginTop="15dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/v_open_notification"
+        app:layout_goneMarginTop="0dp"
+        tools:listitem="@layout/layout_session_list_item" />
+
+    <!--    <com.scwang.smart.refresh.layout.SmartRefreshLayout-->
+    <!--        android:id="@+id/refresh_layout"-->
+    <!--        android:layout_width="0dp"-->
+    <!--        android:layout_height="0dp"-->
+    <!--        android:layout_marginTop="15dp"-->
+    <!--        app:layout_constraintBottom_toBottomOf="parent"-->
+    <!--        app:layout_constraintEnd_toEndOf="parent"-->
+    <!--        app:layout_constraintStart_toStartOf="parent"-->
+    <!--        app:layout_constraintTop_toBottomOf="@id/v_open_notification"-->
+    <!--        app:layout_goneMarginTop="0dp">-->
+
+    <!--        <androidx.recyclerview.widget.RecyclerView-->
+    <!--            android:id="@+id/v_list"-->
+    <!--            android:layout_width="match_parent"-->
+    <!--            android:layout_height="match_parent"-->
+    <!--            android:clipToPadding="true"-->
+    <!--            tools:listitem="@layout/layout_session_list_item" />-->
+
+    <!--    </com.scwang.smart.refresh.layout.SmartRefreshLayout>-->
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 84 - 0
module/im/src/main/res/layout/layout_session_list_item.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.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="64dp"
+    android:paddingHorizontal="16dp">
+
+    <com.adealink.weparty.commonui.imageview.AvatarView
+        android:id="@+id/iv_close"
+        android:layout_width="46dp"
+        android:layout_height="46dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="10dp"
+        android:ellipsize="end"
+        android:fontFamily="@font/poppins_semibold"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_FF1D2129"
+        android:textSize="12sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toTopOf="@id/tv_desc"
+        app:layout_constraintEnd_toStartOf="@id/barrier_right"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/iv_close"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_chainStyle="packed"
+        tools:text="UserName, Super Beautiful Girl" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_desc"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="10dp"
+        android:layout_marginTop="5dp"
+        android:ellipsize="end"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_FF86909C"
+        android:textSize="12sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/barrier_right"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/iv_close"
+        app:layout_constraintTop_toBottomOf="@id/tv_title"
+        tools:text="@string/im_open_notification_title_desc" />
+
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/barrier_right"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:barrierDirection="top"
+        app:constraint_referenced_ids="tv_time, " />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_FF86909C"
+        android:textSize="12sp"
+        app:layout_constraintBottom_toBottomOf="@id/tv_title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/tv_title"
+        tools:text="Now" />
+
+    <com.adealink.frame.dot.DotView
+        android:id="@+id/v_dot"
+        style="@style/CommonRedDot"
+        app:layout_constraintBottom_toBottomOf="@id/tv_desc"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/tv_desc"
+        tools:text="Now" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 85 - 0
module/im/src/main/res/layout/layout_session_list_system_item.xml

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.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="64dp"
+    android:paddingHorizontal="16dp">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_close"
+        android:layout_width="46dp"
+        android:layout_height="46dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/im_official_avatar_ic" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="10dp"
+        android:ellipsize="end"
+        android:fontFamily="@font/poppins_semibold"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_FF3FBFBD"
+        android:textSize="12sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toTopOf="@id/tv_desc"
+        app:layout_constraintEnd_toStartOf="@id/barrier_right"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/iv_close"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_chainStyle="packed"
+        tools:text="UserName, Super Beautiful Girl" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_desc"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="10dp"
+        android:layout_marginTop="5dp"
+        android:ellipsize="end"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_FF86909C"
+        android:textSize="12sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/barrier_right"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/iv_close"
+        app:layout_constraintTop_toBottomOf="@id/tv_title"
+        tools:text="@string/im_open_notification_title_desc" />
+
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/barrier_right"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:barrierDirection="top"
+        app:constraint_referenced_ids="tv_time, " />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_FF86909C"
+        android:textSize="12sp"
+        app:layout_constraintBottom_toBottomOf="@id/tv_title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/tv_title"
+        tools:text="Now" />
+
+    <com.adealink.frame.dot.DotView
+        android:id="@+id/v_dot"
+        style="@style/CommonRedDot"
+        app:layout_constraintBottom_toBottomOf="@id/tv_desc"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/tv_desc"
+        tools:text="Now" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 73 - 0
module/im/src/main/res/layout/layout_session_open_notification.xml

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="50dp"
+    android:background="@drawable/im_open_notification_bg"
+    android:paddingHorizontal="10dp">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_close"
+        android:layout_width="20dp"
+        android:layout_height="20dp"
+        app:srcCompat="@drawable/common_close_ic"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="12dp"
+        android:ellipsize="end"
+        android:fontFamily="@font/poppins_semibold"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:text="@string/im_open_notification_title"
+        android:textColor="@color/color_FF1D2129"
+        android:textSize="12sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toTopOf="@id/tv_title_desc"
+        app:layout_constraintEnd_toStartOf="@id/btn_turn_on"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/iv_close"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_chainStyle="packed" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_title_desc"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="12dp"
+        android:ellipsize="end"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:text="@string/im_open_notification_title_desc"
+        android:textColor="@color/color_FF1D2129"
+        android:textSize="12sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/btn_turn_on"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/iv_close"
+        app:layout_constraintTop_toBottomOf="@id/tv_title" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/btn_turn_on"
+        android:layout_width="wrap_content"
+        android:layout_height="24dp"
+        android:layout_marginStart="12dp"
+        android:background="@drawable/im_turn_on_notification_bg"
+        android:gravity="center"
+        android:includeFontPadding="false"
+        android:paddingHorizontal="8dp"
+        android:singleLine="true"
+        android:text="@string/im_turn_on_notification"
+        android:textColor="@color/white"
+        android:textSize="12sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 4 - 1
module/im/src/main/res/values/strings.xml

@@ -1,4 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-
+    <string name="im_session_list_title">Message</string>
+    <string name="im_open_notification_title">Open notification</string>
+    <string name="im_open_notification_title_desc">Receive important information</string>
+    <string name="im_turn_on_notification">Turn on</string>
 </resources>

+ 4 - 0
module/profile/src/main/AndroidManifest.xml

@@ -24,5 +24,9 @@
             android:name=".edit.EditProfileActivity"
             android:screenOrientation="portrait"
             android:theme="@style/AppTheme" />
+        <activity
+            android:name=".search.SearchActivity"
+            android:screenOrientation="portrait"
+            android:theme="@style/AppTheme" />
     </application>
 </manifest>

+ 53 - 0
module/profile/src/main/java/com/adealink/weparty/profile/search/SearchActivity.kt

@@ -0,0 +1,53 @@
+package com.adealink.weparty.profile.search
+
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.view.updateLayoutParams
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.adealink.frame.base.fastLazy
+import com.adealink.frame.mvvm.view.viewBinding
+import com.adealink.frame.router.Router
+import com.adealink.frame.router.annotation.RouterUri
+import com.adealink.frame.util.DisplayUtil.getStatusBarHeight
+import com.adealink.weparty.commonui.BaseActivity
+import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
+import com.adealink.weparty.module.profile.Profile
+import com.adealink.weparty.profile.databinding.ActivityUserSearchBinding
+import com.adealink.weparty.profile.search.adapter.SearchItemViewBinder
+import com.adealink.weparty.profile.search.data.SearchResultItemData
+
+@RouterUri(
+    path = [Profile.Search.PATH],
+    desc = "搜索"
+)
+class SearchActivity : BaseActivity(), SearchItemViewBinder.OnResultClickListener {
+
+    private val binding by viewBinding(ActivityUserSearchBinding::inflate)
+
+    private val listAdapter by fastLazy { MultiTypeListAdapter<SearchResultItemData>() }
+
+    override fun onBeforeCreate() {
+        super.onBeforeCreate()
+        Router.bind(this)
+    }
+
+    override fun initViews() {
+        super.initViews()
+        setContentView(binding.root)
+        binding.clTop.updateLayoutParams<ConstraintLayout.LayoutParams> {
+            topMargin = getStatusBarHeight(this@SearchActivity)
+        }
+
+        listAdapter.register(SearchItemViewBinder(this))
+        binding.rvResult.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
+        binding.rvResult.adapter = listAdapter
+    }
+
+    override fun onClick(
+        item: SearchResultItemData,
+        pos: Int
+    ) {
+
+    }
+
+}

+ 30 - 0
module/profile/src/main/java/com/adealink/weparty/profile/search/adapter/SearchItemViewBinder.kt

@@ -0,0 +1,30 @@
+package com.adealink.weparty.profile.search.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import com.adealink.weparty.commonui.recycleview.adapter.BindingViewHolder
+import com.adealink.weparty.commonui.recycleview.adapter.multitype.ItemViewBinder
+import com.adealink.weparty.profile.databinding.LayoutProfileSearchItemBinding
+import com.adealink.weparty.profile.search.data.SearchResultItemData
+
+class SearchItemViewBinder(val listener: OnResultClickListener) :
+    ItemViewBinder<SearchResultItemData, BindingViewHolder<LayoutProfileSearchItemBinding>>() {
+
+    override fun onBindViewHolder(
+        holder: BindingViewHolder<LayoutProfileSearchItemBinding>,
+        item: SearchResultItemData,
+    ) {
+    }
+
+    override fun onCreateViewHolder(
+        inflater: LayoutInflater,
+        parent: ViewGroup,
+    ): BindingViewHolder<LayoutProfileSearchItemBinding> {
+        return BindingViewHolder(LayoutProfileSearchItemBinding.inflate(inflater, parent, false))
+    }
+
+    interface OnResultClickListener {
+        fun onClick(item: SearchResultItemData, pos: Int)
+    }
+
+}

+ 12 - 0
module/profile/src/main/java/com/adealink/weparty/profile/search/data/SearchData.kt

@@ -0,0 +1,12 @@
+package com.adealink.weparty.profile.search.data
+
+import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
+import com.adealink.weparty.module.profile.data.UserInfo
+
+data class SearchData(
+    val userinfo: UserInfo
+)
+
+data class SearchResultItemData(
+    val data: SearchData
+) : BaseListItemData

BIN
module/profile/src/main/res/drawable-xhdpi/profile_search_input_ic.png


+ 8 - 0
module/profile/src/main/res/drawable/profile_search_input_bg.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <corners android:radius="20dp" />
+    <solid android:color="@color/color_FFF2F3F5" />
+
+</shape>

+ 92 - 0
module/profile/src/main/res/layout/activity_user_search.xml

@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.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"
+    android:background="@color/white">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_top"
+        android:layout_width="match_parent"
+        android:layout_height="54dp"
+        android:paddingHorizontal="16dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_back"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:srcCompat="@drawable/commonui_back_black_48_ic" />
+
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:layout_width="0dp"
+            android:layout_height="36dp"
+            android:layout_marginHorizontal="12dp"
+            android:background="@drawable/profile_search_input_bg"
+            android:paddingHorizontal="10dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/tv_search"
+            app:layout_constraintStart_toEndOf="@id/iv_back"
+            app:layout_constraintTop_toTopOf="parent">
+
+            <androidx.appcompat.widget.AppCompatImageView
+                android:id="@+id/iv_search_input"
+                android:layout_width="18dp"
+                android:layout_height="18dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:srcCompat="@drawable/profile_search_input_ic" />
+
+            <androidx.appcompat.widget.AppCompatEditText
+                android:id="@+id/et_search_input"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:background="@null"
+                android:gravity="start|center_vertical"
+                android:hint="@string/profile_search_hint"
+                android:includeFontPadding="false"
+                android:textColor="@color/color_FF1D2129"
+                android:textColorHint="@color/color_FF86909C"
+                android:textSize="12sp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toEndOf="@id/iv_search_input"
+                app:layout_constraintTop_toTopOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_search"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:gravity="center"
+            android:includeFontPadding="false"
+            android:singleLine="true"
+            android:text="@string/common_search"
+            android:textColor="@color/color_FF1D2129"
+            android:textSize="14sp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/rv_result"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/cl_top"
+        tools:listitem="@layout/layout_profile_search_item" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 33 - 0
module/profile/src/main/res/layout/layout_profile_search_item.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.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="wrap_content">
+
+    <com.adealink.weparty.commonui.imageview.AvatarView
+        android:id="@+id/iv_avatar"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="10dp"
+        android:ellipsize="end"
+        android:gravity="start|center_vertical"
+        android:includeFontPadding="false"
+        android:singleLine="true"
+        android:textColor="@color/color_FF1D2129"
+        android:textSize="14sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/iv_avatar"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="text tip" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 0
module/profile/src/main/res/values/strings.xml

@@ -24,4 +24,5 @@
     <string name="toast_profile_edit_age_empty">年龄不能为空</string>
     <string name="toast_profile_edit_age_invalid">年龄输入不合法,请输入0–99以内的数字</string>
     <string name="profile_edit_avatar_upload_fail">头像更新失败</string>
+    <string name="profile_search_hint">Please enter search keywords</string>
 </resources>