Bläddra i källkod

feat: 二维码分享

DoggyZhang 4 månader sedan
förälder
incheckning
1c020beafc
21 ändrade filer med 410 tillägg och 9 borttagningar
  1. 3 1
      app/src/main/java/com/adealink/weparty/module/playmate/data/Tags.kt
  2. 6 0
      app/src/main/java/com/adealink/weparty/module/playmate/viewmodel/IPlaymateViewModel.kt
  3. 10 0
      module/playmate/src/main/java/com/adealink/weparty/playmate/data/PlaymateData.kt
  4. 5 0
      module/playmate/src/main/java/com/adealink/weparty/playmate/datasource/remote/PlaymateHttpService.kt
  5. 3 0
      module/playmate/src/main/java/com/adealink/weparty/playmate/manager/IPlaymateManager.kt
  6. 48 0
      module/playmate/src/main/java/com/adealink/weparty/playmate/manager/PlaymateManager.kt
  7. 15 0
      module/playmate/src/main/java/com/adealink/weparty/playmate/viewmodel/PlaymateViewModel.kt
  8. 28 1
      module/profile/src/main/java/com/adealink/weparty/profile/me/MeFragment.kt
  9. BIN
      module/profile/src/main/res/drawable-xhdpi/profile_share_friends_tag_ic.png
  10. BIN
      module/profile/src/main/res/drawable-xhdpi/profile_share_qr_code_tag_ic.png
  11. 8 0
      module/profile/src/main/res/layout/fragment_me.xml
  12. 52 0
      module/share/src/main/java/com/adealink/weparty/share/qrcode/ChooseCategoryDialog.kt
  13. 17 0
      module/share/src/main/java/com/adealink/weparty/share/qrcode/CommonQRCodeFragment.kt
  14. 62 2
      module/share/src/main/java/com/adealink/weparty/share/qrcode/QRCodeShareDialog.kt
  15. 15 0
      module/share/src/main/java/com/adealink/weparty/share/qrcode/SpecialQRCodeFragment.kt
  16. 49 0
      module/share/src/main/java/com/adealink/weparty/share/qrcode/adapter/CategoryItemViewBinder.kt
  17. 15 0
      module/share/src/main/java/com/adealink/weparty/share/qrcode/viewmodel/QRCodeViewModel.kt
  18. 3 0
      module/share/src/main/java/com/adealink/weparty/share/viewmodel/ShareViewModelFactory.kt
  19. 22 0
      module/share/src/main/res/layout/dialog_choose_category.xml
  20. 9 5
      module/share/src/main/res/layout/dialog_qr_code_share.xml
  21. 40 0
      module/share/src/main/res/layout/layout_choose_category_item.xml

+ 3 - 1
app/src/main/java/com/adealink/weparty/module/playmate/data/Tags.kt

@@ -1,4 +1,6 @@
 package com.adealink.weparty.module.playmate.data
 
 const val TAG_PLAYMATE = "tag_playmate"
-const val TAG_PLAYMATE_LIST = "${TAG_PLAYMATE}_list"
+const val TAG_PLAYMATE_LIST = "${TAG_PLAYMATE}_list"
+
+const val TAG_PLAYMATE_MANAGER = "${TAG_PLAYMATE}_manager"

+ 6 - 0
app/src/main/java/com/adealink/weparty/module/playmate/viewmodel/IPlaymateViewModel.kt

@@ -1,6 +1,7 @@
 package com.adealink.weparty.module.playmate.viewmodel
 
 import androidx.lifecycle.LiveData
+import com.adealink.frame.base.Rlt
 import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
 
 interface IPlaymateViewModel {
@@ -9,4 +10,9 @@ interface IPlaymateViewModel {
 
     fun pullAllCategory()
 
+    fun getUserPlaymateCategory(
+        uid: String,
+        cache: Boolean
+    ): LiveData<Rlt<List<PlaymateCategoryData>>>
+
 }

+ 10 - 0
module/playmate/src/main/java/com/adealink/weparty/playmate/data/PlaymateData.kt

@@ -1,5 +1,6 @@
 package com.adealink.weparty.playmate.data
 
+import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
 import com.google.gson.annotations.SerializedName
 
 data class PlaymateDetailReq(
@@ -25,4 +26,13 @@ data class PlaymateDetailRes(
     @SerializedName("labels") val labels: List<String>, //标签
     @SerializedName("categoryName") val categoryName: String, //品类名称
     @SerializedName("categoryIcon") val categoryIcon: String, //品类图标
+)
+
+
+data class UserPlaymateCategoryReq(
+    @SerializedName("id") val uid: String, //用户ID
+)
+
+data class UserPlaymateCategoryRes(
+    @SerializedName("list") val list: List<PlaymateCategoryData>
 )

+ 5 - 0
module/playmate/src/main/java/com/adealink/weparty/playmate/datasource/remote/PlaymateHttpService.kt

@@ -7,6 +7,8 @@ import com.adealink.weparty.playmate.data.PlaymateDetailReq
 import com.adealink.weparty.playmate.data.PlaymateDetailRes
 import com.adealink.weparty.playmate.data.PlaymateListReq
 import com.adealink.weparty.playmate.data.PlaymateListRes
+import com.adealink.weparty.playmate.data.UserPlaymateCategoryReq
+import com.adealink.weparty.playmate.data.UserPlaymateCategoryRes
 import retrofit2.http.Body
 import retrofit2.http.POST
 
@@ -25,4 +27,7 @@ interface PlaymateHttpService {
     @POST("skill/detail")
     suspend fun getPlaymateDetail(@Body req: PlaymateDetailReq): Rlt<Res<PlaymateDetailRes>>
 
+    @POST("skill/user/goods")
+    suspend fun getUserPlaymateCategory(@Body req: UserPlaymateCategoryReq): Rlt<Res<UserPlaymateCategoryRes>>
+
 }

+ 3 - 0
module/playmate/src/main/java/com/adealink/weparty/playmate/manager/IPlaymateManager.kt

@@ -1,5 +1,6 @@
 package com.adealink.weparty.playmate.manager
 
+import com.adealink.frame.base.Rlt
 import com.adealink.frame.frame.IBaseFrame
 import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
 
@@ -7,4 +8,6 @@ interface IPlaymateManager : IBaseFrame<IPlaymateListener> {
 
     suspend fun pullAllCategory(): Map<String, PlaymateCategoryData>
 
+    suspend fun getUserPlaymateCategory(uid: String, cache: Boolean): Rlt<List<PlaymateCategoryData>>
+
 }

+ 48 - 0
module/playmate/src/main/java/com/adealink/weparty/playmate/manager/PlaymateManager.kt

@@ -1,10 +1,16 @@
 package com.adealink.weparty.playmate.manager
 
+import com.adealink.frame.base.CommonDataNullError
+import com.adealink.frame.base.CommonParamError
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.base.fastLazy
 import com.adealink.frame.frame.BaseFrame
+import com.adealink.frame.log.Log
+import com.adealink.frame.storage.cache.TimeoutLruCache
 import com.adealink.weparty.App
 import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
+import com.adealink.weparty.module.playmate.data.TAG_PLAYMATE_MANAGER
+import com.adealink.weparty.playmate.data.UserPlaymateCategoryReq
 import com.adealink.weparty.playmate.datasource.remote.PlaymateHttpService
 
 
@@ -16,6 +22,13 @@ class PlaymateManager : BaseFrame<IPlaymateListener>(), IPlaymateManager {
         App.instance.networkService.getHttpService(PlaymateHttpService::class.java)
     }
 
+    private val userPlaymateCategoryCache by lazy {
+        TimeoutLruCache<String, List<PlaymateCategoryData>>(
+            500,
+            10 * 60 * 1000
+        ) //最多缓存5000个,缓存时长10分钟
+    }
+
     override suspend fun pullAllCategory(): Map<String, PlaymateCategoryData> {
         val rlt = playmateHttpService.getAllCategory()
         when (rlt) {
@@ -34,5 +47,40 @@ class PlaymateManager : BaseFrame<IPlaymateListener>(), IPlaymateManager {
         }
     }
 
+    override suspend fun getUserPlaymateCategory(
+        uid: String,
+        cache: Boolean
+    ): Rlt<List<PlaymateCategoryData>> {
+        if (uid.isEmpty()) {
+            return Rlt.Failed(CommonParamError("uid($uid) is invalid"))
+        }
+        if (cache) {
+            val data = userPlaymateCategoryCache[uid]
+            if (data != null) {
+                return Rlt.Success(data)
+            }
+        }
+
+        Log.d(TAG_PLAYMATE_MANAGER, "PlaymateManager.getPlaymateCategory, uid:${uid}")
+        val rlt = playmateHttpService.getUserPlaymateCategory(UserPlaymateCategoryReq(uid))
+        return when (rlt) {
+            is Rlt.Failed -> {
+                rlt
+            }
+
+            is Rlt.Success -> {
+                val data = rlt.data.data ?: return Rlt.Failed(CommonDataNullError())
+                updateUserPlaymateCategory(uid, data.list)
+                return Rlt.Success(data.list)
+            }
+        }
+    }
+
+    private fun updateUserPlaymateCategory(
+        uid: String,
+        categoryList: List<PlaymateCategoryData>
+    ) {
+        userPlaymateCategoryCache.put(uid, categoryList)
+    }
 
 }

+ 15 - 0
module/playmate/src/main/java/com/adealink/weparty/playmate/viewmodel/PlaymateViewModel.kt

@@ -1,6 +1,9 @@
 package com.adealink.weparty.playmate.viewmodel
 
+import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
 import com.adealink.frame.mvvm.viewmodel.BaseViewModel
 import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
 import com.adealink.weparty.module.playmate.viewmodel.IPlaymateViewModel
@@ -17,4 +20,16 @@ class PlaymateViewModel : BaseViewModel(), IPlaymateViewModel {
         }
     }
 
+    override fun getUserPlaymateCategory(
+        uid: String,
+        cache: Boolean
+    ): LiveData<Rlt<List<PlaymateCategoryData>>> {
+        val liveData = OnceMutableLiveData<Rlt<List<PlaymateCategoryData>>>()
+        viewModelScope.launch {
+            val rlt = playmateManager.getUserPlaymateCategory(uid, cache)
+            liveData.send(rlt)
+        }
+        return liveData
+    }
+
 }

+ 28 - 1
module/profile/src/main/java/com/adealink/weparty/profile/me/MeFragment.kt

@@ -1,13 +1,19 @@
 package com.adealink.weparty.profile.me
 
+import android.text.SpannableStringBuilder
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.updateLayoutParams
+import com.adealink.frame.aab.util.getCompatDrawable
+import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.ext.findAndSetSpan
 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.BaseFragment
+import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.commonui.widget.BottomDialogFragment
+import com.adealink.weparty.commonui.widget.CenterImageSpan
 import com.adealink.weparty.module.account.AccountModule
 import com.adealink.weparty.module.profile.Profile
 import com.adealink.weparty.module.share.Share
@@ -27,10 +33,28 @@ class MeFragment : BaseFragment(R.layout.fragment_me) {
                 getStatusBarHeight(act)
             } ?: 0
         }
-
+        val qrCodeText = getCompatString(R.string.profile_generate_qr_code)
+        binding.tvQrCode.text = SpannableStringBuilder(qrCodeText).apply {
+            findAndSetSpan(
+                CenterImageSpan(getCompatDrawable(R.drawable.profile_share_qr_code_tag_ic).apply {
+                    setBounds(0, 0, 16.dp(), 16.dp())
+                }),
+                IMG_TAG
+            )
+        }
         binding.clQrCode.setOnClickListener {
             generateQRCode()
         }
+
+        val shareFriendText = getCompatString(R.string.profile_share_with_friends)
+        binding.tvShareFriend.text = SpannableStringBuilder(shareFriendText).apply {
+            findAndSetSpan(
+                CenterImageSpan(getCompatDrawable(R.drawable.profile_share_friends_tag_ic).apply {
+                    setBounds(0, 0, 16.dp(), 16.dp())
+                }),
+                IMG_TAG
+            )
+        }
         binding.clShare.setOnClickListener {
             clickShare()
         }
@@ -81,5 +105,8 @@ class MeFragment : BaseFragment(R.layout.fragment_me) {
 
     }
 
+    companion object {
+        private const val IMG_TAG = "[IMG]"
+    }
 
 }

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


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


+ 8 - 0
module/profile/src/main/res/layout/fragment_me.xml

@@ -50,6 +50,7 @@
                 app:layout_constraintTop_toBottomOf="@id/v_header">
 
                 <androidx.appcompat.widget.AppCompatTextView
+                    android:id="@+id/tv_qr_code"
                     android:layout_width="0dp"
                     android:layout_height="0dp"
                     android:layout_marginVertical="10dp"
@@ -61,6 +62,9 @@
                     android:text="@string/profile_generate_qr_code"
                     android:textColor="@color/color_FF01327B"
                     android:textSize="16sp"
+                    app:autoSizeMaxTextSize="16sp"
+                    app:autoSizeMinTextSize="8sp"
+                    app:autoSizeTextType="uniform"
                     app:layout_constraintBottom_toBottomOf="parent"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
@@ -82,6 +86,7 @@
                 app:layout_constraintTop_toBottomOf="@id/v_header">
 
                 <androidx.appcompat.widget.AppCompatTextView
+                    android:id="@+id/tv_share_friend"
                     android:layout_width="0dp"
                     android:layout_height="0dp"
                     android:layout_marginVertical="10dp"
@@ -93,6 +98,9 @@
                     android:text="@string/profile_share_with_friends"
                     android:textColor="@color/color_FF0A625F"
                     android:textSize="16sp"
+                    app:autoSizeMaxTextSize="16sp"
+                    app:autoSizeMinTextSize="8sp"
+                    app:autoSizeTextType="uniform"
                     app:layout_constraintBottom_toBottomOf="parent"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"

+ 52 - 0
module/share/src/main/java/com/adealink/weparty/share/qrcode/ChooseCategoryDialog.kt

@@ -0,0 +1,52 @@
+package com.adealink.weparty.share.qrcode
+
+import androidx.fragment.app.viewModels
+import com.adealink.frame.base.fastLazy
+import com.adealink.frame.mvvm.view.viewBinding
+import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
+import com.adealink.weparty.commonui.widget.BottomDialogFragment
+import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
+import com.adealink.weparty.share.R
+import com.adealink.weparty.share.databinding.DialogChooseCategoryBinding
+import com.adealink.weparty.share.qrcode.adapter.CategoryItem
+import com.adealink.weparty.share.qrcode.adapter.CategoryItemViewBinder
+import com.adealink.weparty.share.qrcode.viewmodel.QRCodeViewModel
+import com.adealink.weparty.share.viewmodel.ShareViewModelFactory
+import com.adealink.weparty.ui.main.tab.ITabManager
+import com.adealink.weparty.ui.main.tab.TabManager
+import kotlin.getValue
+
+class ChooseCategoryDialog : BottomDialogFragment(R.layout.dialog_choose_category),
+    ITabManager by TabManager(), CategoryItemViewBinder.CategoryChooseListener {
+
+    private val binding by viewBinding(DialogChooseCategoryBinding::bind)
+
+    private val qrCodeViewModel by viewModels<QRCodeViewModel>(ownerProducer = {
+        parentFragment ?: this
+    }, factoryProducer = { ShareViewModelFactory() })
+    private val listAdapter by fastLazy { MultiTypeListAdapter<CategoryItem>() }
+
+    private var list: List<PlaymateCategoryData> = emptyList()
+    private var selected: PlaymateCategoryData? = null
+
+    fun setCategoryList(list: List<PlaymateCategoryData>, selected: PlaymateCategoryData) {
+        this.list = list
+        this.selected = selected
+    }
+
+
+    override fun initViews() {
+        super.initViews()
+        listAdapter.register(CategoryItemViewBinder(this))
+        binding.rvCategory.adapter = listAdapter
+        listAdapter.submitList(
+            list.map { CategoryItem(it, it == selected) }
+        )
+    }
+
+    override fun onChoose(data: PlaymateCategoryData) {
+        qrCodeViewModel.selectCategory(data)
+        dismiss()
+    }
+
+}

+ 17 - 0
module/share/src/main/java/com/adealink/weparty/share/qrcode/CommonQRCodeFragment.kt

@@ -1,10 +1,27 @@
 package com.adealink.weparty.share.qrcode
 
+import androidx.fragment.app.viewModels
+import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.weparty.commonui.BaseFragment
 import com.adealink.weparty.share.R
+import com.adealink.weparty.share.databinding.DialogQrCodeShareBinding
+import com.adealink.weparty.share.databinding.DialogQrCodeShareBinding.bind
+import com.adealink.weparty.share.databinding.FragmentCommonQrCodeBinding
+import com.adealink.weparty.share.qrcode.viewmodel.QRCodeViewModel
+import com.adealink.weparty.share.viewmodel.ShareViewModelFactory
+import kotlin.getValue
 
 class CommonQRCodeFragment : BaseFragment(R.layout.fragment_common_qr_code) {
 
 
+    private val binding by viewBinding(FragmentCommonQrCodeBinding::bind)
+
+    private val qrCodeViewModel by viewModels<QRCodeViewModel>(ownerProducer = {
+        parentFragment ?: this
+    }, factoryProducer = { ShareViewModelFactory() })
+
+    override fun initViews() {
+        super.initViews()
+    }
 
 }

+ 62 - 2
module/share/src/main/java/com/adealink/weparty/share/qrcode/QRCodeShareDialog.kt

@@ -1,16 +1,26 @@
 package com.adealink.weparty.share.qrcode
 
 import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
 import com.adealink.frame.aab.util.getCompatColor
+import com.adealink.frame.base.Rlt
+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.onClick
 import com.adealink.weparty.commonui.recycleview.adapter.BaseTabFragmentStateAdapter
+import com.adealink.weparty.commonui.toast.util.showFailedToast
 import com.adealink.weparty.commonui.widget.BottomDialogFragment
 import com.adealink.weparty.commonui.widget.EmptyFragment
+import com.adealink.weparty.module.account.AccountModule
+import com.adealink.weparty.module.playmate.PlaymateModule
+import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
 import com.adealink.weparty.module.share.Share
 import com.adealink.weparty.share.R
 import com.adealink.weparty.share.databinding.DialogQrCodeShareBinding
 import com.adealink.weparty.share.databinding.LayoutQrCodeTabItemBinding
+import com.adealink.weparty.share.qrcode.viewmodel.QRCodeViewModel
+import com.adealink.weparty.share.viewmodel.ShareViewModelFactory
 import com.adealink.weparty.ui.main.tab.ITabManager
 import com.adealink.weparty.ui.main.tab.MAIN_TABS
 import com.adealink.weparty.ui.main.tab.TabManager
@@ -23,10 +33,19 @@ class QRCodeShareDialog : BottomDialogFragment(R.layout.dialog_qr_code_share),
     ITabManager by TabManager() {
 
     private val binding by viewBinding(DialogQrCodeShareBinding::bind)
+
+    private val playmateViewModel by fastLazy { PlaymateModule.getPlaymateViewModel(this) }
+    private val qrCodeViewModel by viewModels<QRCodeViewModel> { ShareViewModelFactory() }
     private lateinit var pagerAdapter: ShareOtherPageAdapter
 
+    private val myCategoryList = mutableListOf<PlaymateCategoryData>()
+
     override fun initViews() {
         super.initViews()
+        binding.clTop.onClick {
+
+        }
+
         pagerAdapter = ShareOtherPageAdapter()
         binding.vpContent.offscreenPageLimit = 1
         binding.vpContent.adapter = pagerAdapter
@@ -62,6 +81,7 @@ class QRCodeShareDialog : BottomDialogFragment(R.layout.dialog_qr_code_share),
             }
 
         })
+        binding.vpContent.currentItem = 0
     }
 
     fun updateTabView(
@@ -82,6 +102,47 @@ class QRCodeShareDialog : BottomDialogFragment(R.layout.dialog_qr_code_share),
         }
     }
 
+    override fun loadData() {
+        super.loadData()
+        playmateViewModel?.getUserPlaymateCategory(AccountModule.uid, true)
+            ?.observe(viewLifecycleOwner) { rlt ->
+                when (rlt) {
+                    is Rlt.Failed -> {
+                        showFailedToast(rlt)
+                    }
+
+                    is Rlt.Success<List<PlaymateCategoryData>> -> {
+                        updateMyCategory(rlt.data)
+                    }
+                }
+            }
+    }
+
+    override fun observeViewModel() {
+        super.observeViewModel()
+        qrCodeViewModel.currentCategoryLD.observe(viewLifecycleOwner) {
+            selectCategory(it)
+        }
+    }
+
+    private fun updateMyCategory(list: List<PlaymateCategoryData>) {
+        myCategoryList.clear()
+        myCategoryList.addAll(list)
+
+        qrCodeViewModel.selectCategory(list.firstOrNull())
+    }
+
+    private fun selectCategory(category: PlaymateCategoryData?) {
+        //更新视图
+        binding.ivCategory.setImageUrl(category?.icon)
+        binding.tvCategory.text = category?.name
+
+    }
+
+    private fun showCategoryChooseDialog() {
+
+    }
+
     internal inner class ShareOtherPageAdapter : BaseTabFragmentStateAdapter(this) {
         override fun getTabName(pos: Int): String {
             return ""
@@ -97,5 +158,4 @@ class QRCodeShareDialog : BottomDialogFragment(R.layout.dialog_qr_code_share),
         }
 
     }
-}
-
+}

+ 15 - 0
module/share/src/main/java/com/adealink/weparty/share/qrcode/SpecialQRCodeFragment.kt

@@ -1,9 +1,24 @@
 package com.adealink.weparty.share.qrcode
 
+import androidx.fragment.app.viewModels
+import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.weparty.commonui.BaseFragment
 import com.adealink.weparty.share.R
+import com.adealink.weparty.share.databinding.FragmentCommonQrCodeBinding
+import com.adealink.weparty.share.databinding.FragmentSpecialQrCodeBinding
+import com.adealink.weparty.share.qrcode.viewmodel.QRCodeViewModel
+import com.adealink.weparty.share.viewmodel.ShareViewModelFactory
 
 class SpecialQRCodeFragment : BaseFragment(R.layout.fragment_special_qr_code) {
 
+    private val binding by viewBinding(FragmentSpecialQrCodeBinding::bind)
+
+    private val qrCodeViewModel by viewModels<QRCodeViewModel>(ownerProducer = {
+        parentFragment ?: this
+    }, factoryProducer = { ShareViewModelFactory() })
+
+    override fun initViews() {
+        super.initViews()
+    }
 
 }

+ 49 - 0
module/share/src/main/java/com/adealink/weparty/share/qrcode/adapter/CategoryItemViewBinder.kt

@@ -0,0 +1,49 @@
+package com.adealink.weparty.share.qrcode.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import com.adealink.frame.util.onClick
+import com.adealink.weparty.commonui.recycleview.adapter.BindingViewHolder
+import com.adealink.weparty.commonui.recycleview.adapter.multitype.ItemViewBinder
+import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
+import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
+import com.adealink.weparty.share.databinding.LayoutChooseCategoryItemBinding
+import com.adealink.weparty.R as APP_R
+
+data class CategoryItem(
+    val data: PlaymateCategoryData,
+    var selected: Boolean,
+) : BaseListItemData
+
+class CategoryItemViewBinder(
+    val listener: CategoryChooseListener
+) :
+    ItemViewBinder<CategoryItem, BindingViewHolder<LayoutChooseCategoryItemBinding>>() {
+
+    override fun onBindViewHolder(
+        holder: BindingViewHolder<LayoutChooseCategoryItemBinding>,
+        item: CategoryItem,
+    ) {
+        holder.binding.root.onClick {
+            listener.onChoose(item.data)
+        }
+        holder.binding.ivCategory.setImageUrl(item.data.icon)
+        holder.binding.tvCategory.text = item.data.name
+        if (item.selected) {
+            holder.binding.ivSelected.setImageResource(APP_R.drawable.common_check_selected_ic)
+        } else {
+            holder.binding.ivSelected.setImageResource(APP_R.drawable.common_check_unselected_ic)
+        }
+    }
+
+    override fun onCreateViewHolder(
+        inflater: LayoutInflater,
+        parent: ViewGroup,
+    ): BindingViewHolder<LayoutChooseCategoryItemBinding> {
+        return BindingViewHolder(LayoutChooseCategoryItemBinding.inflate(inflater, parent, false))
+    }
+
+    interface CategoryChooseListener {
+        fun onChoose(data: PlaymateCategoryData)
+    }
+}

+ 15 - 0
module/share/src/main/java/com/adealink/weparty/share/qrcode/viewmodel/QRCodeViewModel.kt

@@ -0,0 +1,15 @@
+package com.adealink.weparty.share.qrcode.viewmodel
+
+import androidx.lifecycle.MutableLiveData
+import com.adealink.frame.mvvm.viewmodel.BaseViewModel
+import com.adealink.weparty.module.playmate.data.PlaymateCategoryData
+
+class QRCodeViewModel : BaseViewModel() {
+
+    val currentCategoryLD = MutableLiveData<PlaymateCategoryData?>()
+
+    fun selectCategory(category: PlaymateCategoryData?) {
+        currentCategoryLD.send(category)
+    }
+
+}

+ 3 - 0
module/share/src/main/java/com/adealink/weparty/share/viewmodel/ShareViewModelFactory.kt

@@ -2,6 +2,7 @@ package com.adealink.weparty.share.viewmodel
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
+import com.adealink.weparty.share.qrcode.viewmodel.QRCodeViewModel
 
 @Suppress("UNCHECKED_CAST")
 class ShareViewModelFactory : ViewModelProvider.NewInstanceFactory() {
@@ -11,6 +12,8 @@ class ShareViewModelFactory : ViewModelProvider.NewInstanceFactory() {
             when {
                 isAssignableFrom(ShareViewModel::class.java) ->
                     ShareViewModel()
+                isAssignableFrom(QRCodeViewModel::class.java) ->
+                    QRCodeViewModel()
 
                 else ->
                     throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")

+ 22 - 0
module/share/src/main/res/layout/dialog_choose_category.xml

@@ -0,0 +1,22 @@
+<?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"
+    android:background="@drawable/common_bottom_dialog_bg"
+    android:paddingTop="8dp"
+    android:paddingBottom="12dp">
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/rv_category"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="100dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:itemCount="4"
+        tools:listitem="@layout/layout_choose_category_item" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 9 - 5
module/share/src/main/res/layout/dialog_qr_code_share.xml

@@ -10,12 +10,16 @@
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:id="@+id/cl_top"
-        android:layout_width="match_parent"
+        android:layout_width="wrap_content"
         android:layout_height="45dp"
+        android:minWidth="100dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent">
 
         <com.adealink.frame.image.view.NetworkImageView
-            android:id="@+id/iv_play"
+            android:id="@+id/iv_category"
             android:layout_width="20dp"
             android:layout_height="20dp"
             app:layout_constraintBottom_toBottomOf="parent"
@@ -23,7 +27,7 @@
             app:layout_constraintTop_toTopOf="parent" />
 
         <androidx.appcompat.widget.AppCompatTextView
-            android:id="@+id/tv_play"
+            android:id="@+id/tv_category"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginStart="4dp"
@@ -31,7 +35,7 @@
             android:textColor="@color/color_FF1D2129"
             android:textSize="12sp"
             app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toEndOf="@id/iv_play"
+            app:layout_constraintStart_toEndOf="@id/iv_category"
             app:layout_constraintTop_toTopOf="parent"
             tools:text="Lol Mobile" />
 
@@ -40,7 +44,7 @@
             android:layout_height="16dp"
             android:layout_marginStart="16dp"
             app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toEndOf="@id/tv_play"
+            app:layout_constraintStart_toEndOf="@id/tv_category"
             app:layout_constraintTop_toTopOf="parent"
             app:srcCompat="@drawable/common_go_ic" />
 

+ 40 - 0
module/share/src/main/res/layout/layout_choose_category_item.xml

@@ -0,0 +1,40 @@
+<?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="48dp">
+
+    <com.adealink.frame.image.view.NetworkImageView
+        android:id="@+id/iv_category"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_category"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp"
+        android:includeFontPadding="false"
+        android:textColor="@color/color_FF1D2129"
+        android:textSize="14sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toEndOf="@id/iv_category"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="Lol Mobile" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_selected"
+        android:layout_width="16dp"
+        android:layout_height="16dp"
+        android:layout_marginStart="16dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/common_check_unselected_ic"
+        tools:srcCompat="@drawable/common_check_selected_ic" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>