Просмотр исходного кода

feat: 幸运礼物 (#1)

* feat: 背景资源

* feat: 幸运礼物

* feat: 幸运礼物

* feat: 私信页面支持幸运礼物弹窗、横幅,规则页返回

* feat: 规则页多语言

* feat: 私聊场景幸运礼物

* feat: 私聊场景幸运礼物

* feat: 阿语资源

* feat: 避免房间和私聊送礼用同一个livedata

* feat: 规则页多语言

* feat: 幸运礼物bugFix

* feat: 礼物面板deeplink跳转、幸运礼物横幅支持上滑

* feat: 幸运礼物横幅支持上滑

* feat: 选中幸运礼物默认数量为1
WilliumP 8 месяцев назад
Родитель
Сommit
bfcb6bc8a4
53 измененных файлов с 584 добавлено и 131 удалено
  1. 6 0
      app/src/main/java/com/adealink/weparty/module/gift/Router.kt
  2. 3 2
      app/src/main/java/com/adealink/weparty/module/gift/data/GiftData.kt
  3. 21 0
      app/src/main/java/com/adealink/weparty/module/gift/effect/luckygift/LuckyGiftBigRewardEffectEntity.kt
  4. 79 0
      app/src/main/java/com/adealink/weparty/module/gift/effect/luckygift/LuckyGiftBigRewardEffectView.kt
  5. 3 3
      app/src/main/java/com/adealink/weparty/module/gift/header/RoomGiftHeaderData.kt
  6. 12 58
      app/src/main/java/com/adealink/weparty/module/gift/header/viewbinder/LuckyGiftHeaderViewBinder.kt
  7. 1 0
      app/src/main/java/com/adealink/weparty/module/gift/viewmodel/IGiftViewModel.kt
  8. 23 0
      app/src/main/java/com/adealink/weparty/util/DeepLinkPreProcessor.kt
  9. BIN
      app/src/main/res/drawable-ldrtl-xhdpi/lucky_gift_header_bg.webp
  10. BIN
      app/src/main/res/drawable-ldrtl-xhdpi/room_lucky_gift_big_reward_bg.webp
  11. BIN
      app/src/main/res/drawable-ldrtl-xhdpi/room_lucky_gift_reward_bg.webp
  12. BIN
      app/src/main/res/drawable-xhdpi/lucky_gift_header_bg.webp
  13. BIN
      app/src/main/res/drawable-xhdpi/room_lucky_gift_big_reward_bg.webp
  14. BIN
      app/src/main/res/drawable-xhdpi/room_lucky_gift_reward_bg.webp
  15. 10 0
      app/src/main/res/drawable/gift_header_right_btn_bg.xml
  16. 51 0
      app/src/main/res/layout/item_lucky_gift_header.xml
  17. 67 0
      app/src/main/res/layout/layout_lucky_gift_big_reward.xml
  18. 7 5
      app/src/main/res/layout/layout_lucky_gift_reward.xml
  19. 4 0
      app/src/main/res/values/colors.xml
  20. 3 0
      module/gift/src/main/AndroidManifest.xml
  21. 11 4
      module/gift/src/main/java/com/adealink/weparty/gift/GiftPageFragment.kt
  22. 1 2
      module/gift/src/main/java/com/adealink/weparty/gift/GiftPanelFragment.kt
  23. 25 0
      module/gift/src/main/java/com/adealink/weparty/gift/LuckyGiftRuleActivity.kt
  24. 11 1
      module/gift/src/main/java/com/adealink/weparty/gift/components/GiftPanelBottomOperateComp.kt
  25. 8 0
      module/gift/src/main/java/com/adealink/weparty/gift/data/GiftData.kt
  26. 2 0
      module/gift/src/main/java/com/adealink/weparty/gift/listener/IGiftListener.kt
  27. 5 10
      module/gift/src/main/java/com/adealink/weparty/gift/luckygift/dialog/LuckGiftRewardDialog.kt
  28. 19 0
      module/gift/src/main/java/com/adealink/weparty/gift/manager/GiftManager.kt
  29. 5 0
      module/gift/src/main/java/com/adealink/weparty/gift/viewmodel/GiftViewModel.kt
  30. BIN
      module/gift/src/main/res/drawable-xhdpi/gift_luck_gift_reward_coin_101_300.webp
  31. BIN
      module/gift/src/main/res/drawable-xhdpi/gift_luck_gift_reward_coin_1_100.webp
  32. BIN
      module/gift/src/main/res/drawable-xhdpi/gift_luck_gift_reward_coin_300.webp
  33. BIN
      module/gift/src/main/res/drawable-xhdpi/gift_lucky_gift_reward_coin.webp
  34. BIN
      module/gift/src/main/res/drawable-xhdpi/lucky_gift_bg.webp
  35. BIN
      module/gift/src/main/res/drawable-xhdpi/lucky_gift_desc_bg.webp
  36. BIN
      module/gift/src/main/res/drawable-xhdpi/lucky_gift_reward_bg.webp
  37. BIN
      module/gift/src/main/res/drawable-xhdpi/lucky_gift_rule_border.9.png
  38. BIN
      module/gift/src/main/res/drawable-xhdpi/lucky_gift_rule_left_ic.webp
  39. BIN
      module/gift/src/main/res/drawable-xhdpi/lucky_gift_rule_right_ic.webp
  40. BIN
      module/gift/src/main/res/drawable-xhdpi/lucky_gift_title.webp
  41. 109 0
      module/gift/src/main/res/layout/activity_lucky_gift_rule.xml
  42. 32 32
      module/gift/src/main/res/layout/fragment_lucky_gift_reward.xml
  43. 2 2
      module/gift/src/main/res/layout/item_normal_gift.xml
  44. 2 0
      module/gift/src/main/res/values-ar/strings.xml
  45. 2 0
      module/gift/src/main/res/values-zh/strings.xml
  46. 2 0
      module/gift/src/main/res/values/strings.xml
  47. 6 1
      module/headline/src/main/java/com/adealink/weparty/headline/view/CommonGlobalHeadline.kt
  48. 1 0
      module/headline/src/main/res/layout/layout_common_global_headline.xml
  49. 42 0
      module/message/src/main/java/com/adealink/weparty/message/conversation/comp/ChatGiftComp.kt
  50. 0 2
      module/message/src/main/java/com/adealink/weparty/message/conversation/extension/inputpanel/ConversationInputPanelFragment.kt
  51. 3 3
      module/message/src/main/java/com/adealink/weparty/message/conversation/provider/BaseNotificationMessageItemProvider.kt
  52. 3 3
      module/room/src/main/java/com/adealink/weparty/room/chatroom/page/chat/ChatRoomDynamicFactory.kt
  53. 3 3
      module/room/src/main/java/com/adealink/weparty/room/gift/view/RoomGiftComp.kt

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

@@ -58,4 +58,10 @@ interface Gift {
         }
     }
 
+    interface LuckyGiftRule {
+        companion object {
+            const val PATH = "/gift/lucky_gift_rule"
+        }
+    }
+
 }

+ 3 - 2
app/src/main/java/com/adealink/weparty/module/gift/data/GiftData.kt

@@ -656,7 +656,8 @@ enum class GiftPageType(val type: Int) {
     CUSTOMIZE(3),
     FLAG(4),
     EXCLUSIVE(5),
-    BACKPACK(6);
+    BACKPACK(6),
+    LUCKY(7);
 
     companion object {
         fun map(type: Int?): GiftPageType {
@@ -771,7 +772,7 @@ data class LuckyGiftLotteryNotify(
     @SerializedName("giftInfo")
     val giftInfo: GiftInfo, //送出的礼物信息
     @SerializedName("lotteryRatio")
-    val lotteryRatio: Int, //中奖倍数
+    val lotteryRatio: Int, //中奖倍数, 1-100公屏,100-300房间横幅,300以上全服横幅
     @SerializedName("lotteryCoins")
     val lotteryCoins: Int, //中奖金币数
     @SerializedName("showPlace")

+ 21 - 0
app/src/main/java/com/adealink/weparty/module/gift/effect/luckygift/LuckyGiftBigRewardEffectEntity.kt

@@ -0,0 +1,21 @@
+package com.adealink.weparty.module.gift.effect.luckygift
+
+import android.content.Context
+import android.util.AttributeSet
+import com.adealink.frame.effect.data.IEffectEntity
+import com.adealink.weparty.module.gift.data.LuckyGiftLotteryNotify
+
+class LuckyGiftBigRewardEffectEntity(
+    override val path: String,
+    val rewardNotify: LuckyGiftLotteryNotify,
+) : IEffectEntity<LuckyGiftBigRewardEffectView>() {
+
+    override fun createEffectView(
+        ctx: Context,
+        attrs: AttributeSet?,
+        defStyleAttr: Int,
+    ): LuckyGiftBigRewardEffectView {
+        return LuckyGiftBigRewardEffectView(ctx, attrs, defStyleAttr)
+    }
+
+}

+ 79 - 0
app/src/main/java/com/adealink/weparty/module/gift/effect/luckygift/LuckyGiftBigRewardEffectView.kt

@@ -0,0 +1,79 @@
+package com.adealink.weparty.module.gift.effect.luckygift
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.effect.data.ERROR_ENTITY_NULL
+import com.adealink.frame.effect.data.IEffectEntity
+import com.adealink.frame.effect.listener.IPlayListener
+import com.adealink.frame.effect.view.IEffectView
+import com.adealink.frame.util.DisplayUtil
+import com.adealink.weparty.databinding.LayoutLuckyGiftBigRewardBinding
+import com.adealink.weparty.R as APP_R
+
+class LuckyGiftBigRewardEffectView @JvmOverloads constructor(
+    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0,
+) : FrameLayout(context, attrs, defStyleAttr), IEffectView {
+
+    private val binding =
+        LayoutLuckyGiftBigRewardBinding.inflate(LayoutInflater.from(context), this, true)
+
+    override fun addToParent(parent: ViewGroup, params: ViewGroup.LayoutParams) {
+        parent.addView(this, params)
+    }
+
+    override fun removeFromParent(parent: ViewGroup) {
+        parent.removeView(this)
+    }
+
+    override fun setVisibility(visibility: Boolean) {
+        this.visibility = if (visibility) View.VISIBLE else View.GONE
+    }
+
+    override fun isVisibility(): Boolean {
+        return visibility == View.VISIBLE
+    }
+
+    override fun play(entity: IEffectEntity<out IEffectView>?, l: IPlayListener?) {
+        val rewardEffectEntity = entity as? LuckyGiftBigRewardEffectEntity
+        if (rewardEffectEntity == null) {
+            l?.onError(ERROR_ENTITY_NULL)
+            return
+        }
+        val userName = rewardEffectEntity.rewardNotify.userInfo.name?:""
+        binding.ivAvatar.setImageUrl(rewardEffectEntity.rewardNotify.userInfo.url)
+
+        binding.tvName.text = userName
+        binding.tvReward.text =
+            getCompatString(APP_R.string.common_lucky_congratulations_gift_reward,
+                userName,
+                rewardEffectEntity.rewardNotify.giftInfo.name,
+                rewardEffectEntity.rewardNotify.lotteryRatio)
+        val screenWidth = DisplayUtil.getScreenWidth()
+        val transX = when (DisplayUtil.isRtlLayout()) {
+            true -> -screenWidth.toFloat()
+            else -> screenWidth.toFloat()
+        }
+        binding.root.translationX = transX
+        binding.root.animate().translationX(0f).setDuration(300).withEndAction {
+            binding.root.animate().setDuration(5000).withEndAction {
+                binding.root.animate().translationX(-transX).setDuration(300).withEndAction {
+                    l?.onComplete()
+                }.start()
+            }.start()
+        }.start()
+    }
+
+    override fun pause() {
+
+    }
+
+    override fun stop() {
+
+    }
+
+}

+ 3 - 3
app/src/main/java/com/adealink/weparty/module/gift/header/RoomGiftHeaderData.kt

@@ -10,11 +10,11 @@ import com.adealink.weparty.module.gift.data.RoomGiftHeaderType
  */
 sealed class RoomGiftHeaderData(val type: RoomGiftHeaderType) : BaseListItemData {
 
-    class CPGiftHeaderData() : RoomGiftHeaderData(RoomGiftHeaderType.CPGift)
+    class CPGiftHeaderData: RoomGiftHeaderData(RoomGiftHeaderType.CPGift)
 
-    class LuckyGiftHeaderData() : RoomGiftHeaderData(RoomGiftHeaderType.LuckyGift)
+    class LuckyGiftHeaderData: RoomGiftHeaderData(RoomGiftHeaderType.LuckyGift)
 
-    class TreasureGiftHeaderData() : RoomGiftHeaderData(RoomGiftHeaderType.TreasureGift)
+    class TreasureGiftHeaderData: RoomGiftHeaderData(RoomGiftHeaderType.TreasureGift)
 
     class CustomGiftHeaderData(val customGiftConfig: CustomGiftConfig? = null) : RoomGiftHeaderData(RoomGiftHeaderType.CustomGift)
 }

+ 12 - 58
app/src/main/java/com/adealink/weparty/module/gift/header/viewbinder/LuckyGiftHeaderViewBinder.kt

@@ -1,84 +1,38 @@
 package com.adealink.weparty.module.gift.header.viewbinder
 
 import android.view.LayoutInflater
-import android.view.View
 import android.view.ViewGroup
-import androidx.annotation.DrawableRes
-import com.adealink.frame.aab.util.getCompatColor
 import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.router.Router
-import com.adealink.frame.util.DisplayUtil
-import com.adealink.weparty.App
 import com.adealink.weparty.R
-import com.adealink.weparty.commonui.drawabletoolbox.DrawableBuilder
 import com.adealink.weparty.commonui.recycleview.adapter.BindingViewHolder
 import com.adealink.weparty.commonui.recycleview.adapter.multitype.ItemViewBinder
-import com.adealink.weparty.databinding.GiftFragmentCommonHeaderBinding
+import com.adealink.weparty.databinding.ItemLuckyGiftHeaderBinding
+import com.adealink.weparty.module.gift.Gift
 import com.adealink.weparty.module.gift.header.RoomGiftHeaderData
-import com.adealink.weparty.module.webview.Web
-import com.adealink.weparty.url.H5Page
-import com.adealink.weparty.url.urlConfigService
 
 /**
- * Created by XiaoDongLin.
- * Date: 2025/5/14
+ * Created by PengWuliang
+ * Date: 2025/7/9
  */
 class LuckyGiftHeaderViewBinder :
-    ItemViewBinder<RoomGiftHeaderData.LuckyGiftHeaderData, BindingViewHolder<GiftFragmentCommonHeaderBinding>>() {
-
-    private val LUCKY_GIFT_HEADLINE_BAR_ICON =
-        App.instance.ossService.getUrlByPath("/big_img/lucky_gift/headline_bar_icon.svga")
+    ItemViewBinder<RoomGiftHeaderData.LuckyGiftHeaderData, BindingViewHolder<ItemLuckyGiftHeaderBinding>>() {
 
     override fun onCreateViewHolder(
         inflater: LayoutInflater, parent: ViewGroup
-    ): BindingViewHolder<GiftFragmentCommonHeaderBinding> {
-        val binding = GiftFragmentCommonHeaderBinding.inflate(inflater, parent, false)
+    ): BindingViewHolder<ItemLuckyGiftHeaderBinding> {
+        val binding = ItemLuckyGiftHeaderBinding.inflate(inflater, parent, false)
         return BindingViewHolder(binding)
     }
 
     override fun onBindViewHolder(
-        holder: BindingViewHolder<GiftFragmentCommonHeaderBinding>,
+        holder: BindingViewHolder<ItemLuckyGiftHeaderBinding>,
         item: RoomGiftHeaderData.LuckyGiftHeaderData
     ) {
-        holder.apply {
-            showLeftSvga(binding, LUCKY_GIFT_HEADLINE_BAR_ICON)
-            val content = getCompatString(R.string.gift_lucky_gift_tip)
-            binding.tvContent.text = content
-            binding.rightButton.text = getCompatString(R.string.common_check)
-            binding.rightButton.visibility = View.VISIBLE
-            binding.rightButton.setTextColor(getCompatColor(R.color.white))
-            val bg = DrawableBuilder()
-                .rectangle()
-                .cornerRadius(DisplayUtil.dp2px(10f))
-                .solidColor(getCompatColor(R.color.color_FF03B190))
-                .build()
-            binding.rightButton.background = bg
-            binding.rightButton.setOnClickListener {
-                val activity = binding.root.context ?: return@setOnClickListener
-                Router.build(activity, Web.FullScreen.PATH)
-                    .putExtra(
-                        Web.Common.EXTRA_URL,
-                        urlConfigService.getH5Url(H5Page.LUCKY_GIFT_RULE)
-                    )
-                    .start()
-            }
-
+        holder.binding.tvContent.text = getCompatString(R.string.gift_lucky_gift_tip)
+        holder.binding.rightButton.setOnClickListener {
+            val activity = it.context ?: return@setOnClickListener
+            Router.build(activity, Gift.LuckyGiftRule.PATH).start()
         }
     }
-
-    private fun showLeftSvga(binding: GiftFragmentCommonHeaderBinding, url: String) {
-        binding.ivLeft.visibility = View.GONE
-        binding.flLeft.visibility = View.GONE
-        binding.svgaLeft.visibility = View.VISIBLE
-        binding.svgaLeft.setUrl(url)
-    }
-
-    private fun showLeftIcon(
-        binding: GiftFragmentCommonHeaderBinding, @DrawableRes drawableId: Int
-    ) {
-        binding.ivLeft.visibility = View.VISIBLE
-        binding.flLeft.visibility = View.GONE
-        binding.svgaLeft.visibility = View.GONE
-        binding.ivLeft.setImageResource(drawableId)
-    }
 }

+ 1 - 0
app/src/main/java/com/adealink/weparty/module/gift/viewmodel/IGiftViewModel.kt

@@ -45,6 +45,7 @@ interface IGiftViewModel {
     val selectedGiftPageType: ExtLiveData<GiftPageType>
     val sendUidSetLD: ExtLiveData<Set<Long>>
     val luckyGiftRewardNotifyLD: ExtLiveData<LuckyGiftLotteryNotify>
+    val chatLuckyGiftRewardNotifyLD: ExtLiveData<LuckyGiftLotteryNotify>
     val giftBackpackItemSelectLD: ExtLiveData<UserPackageInfo>
     val sendBackpackItemNotifyLD: ExtLiveData<SendBackpackItemNotify>
     val timeLimitGiftUntilExpiredLD: ExtLiveData<Long>

+ 23 - 0
app/src/main/java/com/adealink/weparty/util/DeepLinkPreProcessor.kt

@@ -7,7 +7,9 @@ import com.adealink.frame.base.AppBaseInfo
 import com.adealink.frame.router.Router
 import com.adealink.frame.util.AppUtil
 import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
+import com.adealink.weparty.module.anchor.data.FromScene
 import com.adealink.weparty.module.operation.Operation
+import com.adealink.weparty.module.room.Room
 import com.adealink.weparty.module.wallet.Wallet
 import com.adealink.weparty.module.wallet.WalletModule
 import com.adealink.weparty.module.wallet.data.Currency
@@ -54,6 +56,27 @@ object DeepLinkPreProcessor {
                 true
             }
 
+            Room.SendGiftPanel.PATH -> {
+                val uid = uri.getQueryParameter(Room.Common.EXTRA_UID)?.toLong() ?: 0L
+                val dialog = Router.getRouterInstance<BaseDialogFragment>(Room.SendGiftPanel.PATH)?.apply {
+                    arguments = Bundle().apply {
+                        putInt(
+                            Room.SendGiftPanel.EXTRA_FROM_SCENE,
+                            FromScene.COMMON_IM.scene
+                        )
+                        putLongArray(
+                            Room.SendGiftPanel.EXTRA_UIDS,
+                            longArrayOf(uid)
+                        )
+                    }
+                }
+                AppUtil.currentActivity?.let {
+                    if (it is FragmentActivity) {
+                        dialog?.show(it.supportFragmentManager)
+                    }
+                }
+                true
+            }
             else -> {
                 false
             }

BIN
app/src/main/res/drawable-ldrtl-xhdpi/lucky_gift_header_bg.webp


BIN
app/src/main/res/drawable-ldrtl-xhdpi/room_lucky_gift_big_reward_bg.webp


BIN
app/src/main/res/drawable-ldrtl-xhdpi/room_lucky_gift_reward_bg.webp


BIN
app/src/main/res/drawable-xhdpi/lucky_gift_header_bg.webp


BIN
app/src/main/res/drawable-xhdpi/room_lucky_gift_big_reward_bg.webp


BIN
app/src/main/res/drawable-xhdpi/room_lucky_gift_reward_bg.webp


+ 10 - 0
app/src/main/res/drawable/gift_header_right_btn_bg.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <gradient
+        android:angle="180"
+        android:type="linear"
+        android:startColor="#FFE083"
+        android:endColor="#FFF6CC"/>
+    <corners android:radius="14dp" />
+</shape>

+ 51 - 0
app/src/main/res/layout/item_lucky_gift_header.xml

@@ -0,0 +1,51 @@
+<?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="44dp"
+    android:layout_marginHorizontal="12dp"
+    android:background="@drawable/lucky_gift_header_bg">
+
+    <Space
+        android:id="@+id/space"
+        android:layout_width="44dp"
+        android:layout_height="44dp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.adealink.weparty.commonui.widget.AutoMarqueeTextView
+        android:id="@+id/tv_content"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp"
+        android:layout_marginEnd="8dp"
+        android:ellipsize="end"
+        android:gravity="start|center_vertical"
+        android:textColor="@color/white"
+        android:textSize="12sp"
+        android:singleLine="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/right_button"
+        app:layout_constraintStart_toEndOf="@id/space"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/right_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="10dp"
+        android:background="@drawable/gift_header_right_btn_bg"
+        android:gravity="center"
+        android:paddingHorizontal="5dp"
+        android:paddingVertical="2dp"
+        android:text="@string/common_go"
+        android:textStyle="bold"
+        android:textColor="@color/color_FF6F1B28"
+        android:textSize="12sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 67 - 0
app/src/main/res/layout/layout_lucky_gift_big_reward.xml

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.adealink.weparty.commonui.widget.floatview.view.SwipeToTopConstraintLayout
+    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"
+    tools:layout_width="375dp"
+    android:layout_marginTop="85dp">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_bg"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginHorizontal="10dp"
+        android:scaleType="fitXY"
+        android:src="@drawable/room_lucky_gift_big_reward_bg"
+        app:layout_constraintDimensionRatio="708:196"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+
+    <com.adealink.weparty.commonui.imageview.AvatarView
+        android:id="@+id/iv_avatar"
+        android:layout_width="38dp"
+        android:layout_height="38dp"
+        android:layout_marginStart="25dp"
+        android:layout_marginTop="4dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="@id/iv_bg"
+        app:layout_constraintTop_toTopOf="parent"
+        app:placeholderImage="@drawable/common_default_avatar_ic"
+        app:roundAsCircle="true"
+        app:roundingBorderColor="@color/color_FFFFE3A5"
+        app:roundingBorderWidth="1dp" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="6dp"
+        android:textColor="@color/color_FFFFE900"
+        android:textSize="12sp"
+        app:layout_constraintStart_toEndOf="@id/iv_avatar"
+        app:layout_constraintTop_toTopOf="@id/iv_avatar"
+        tools:text="UserName" />
+
+    <com.adealink.weparty.commonui.widget.AutoMarqueeTextView
+        android:id="@+id/tv_reward"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="2dp"
+        android:layout_marginEnd="30dp"
+        android:ellipsize="marquee"
+        android:focusable="false"
+        android:focusableInTouchMode="false"
+        android:marqueeRepeatLimit="marquee_forever"
+        android:scrollHorizontally="true"
+        android:singleLine="true"
+        android:textColor="@color/white"
+        android:textSize="12sp"
+        app:layout_constraintEnd_toEndOf="@id/iv_bg"
+        app:layout_constraintStart_toStartOf="@id/tv_name"
+        app:layout_constraintTop_toBottomOf="@id/tv_name" />
+
+</com.adealink.weparty.commonui.widget.floatview.view.SwipeToTopConstraintLayout>

+ 7 - 5
app/src/main/res/layout/layout_lucky_gift_reward.xml

@@ -1,11 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.adealink.weparty.commonui.widget.floatview.view.SwipeToTopConstraintLayout
+    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="wrap_content">
+    android:layout_height="wrap_content"
+    android:layout_marginTop="120dp">
 
     <androidx.appcompat.widget.AppCompatImageView
-        android:layout_width="333dp"
+        android:layout_width="330dp"
         android:layout_height="43dp"
         android:scaleType="fitXY"
         android:src="@drawable/room_lucky_gift_reward_bg"
@@ -25,7 +27,7 @@
             android:id="@+id/iv_avatar"
             android:layout_width="24dp"
             android:layout_height="24dp"
-            android:layout_marginStart="1dp"
+            android:layout_marginStart="5.5dp"
             app:roundAsCircle="true"
             app:placeholderImage="@drawable/common_default_avatar_ic"
             app:layout_constraintBottom_toBottomOf="parent"
@@ -55,4 +57,4 @@
 
     </androidx.constraintlayout.widget.ConstraintLayout>
 
-</androidx.constraintlayout.widget.ConstraintLayout>
+</com.adealink.weparty.commonui.widget.floatview.view.SwipeToTopConstraintLayout>

+ 4 - 0
app/src/main/res/values/colors.xml

@@ -1070,4 +1070,8 @@
     <color name="color_E1E3E6">#E1E3E6</color>
     <color name="color_FF6150">#FF6150</color>
     <color name="color_FF8700">#FF8700</color>
+    <color name="color_FF6F1B28">#FF6F1B28</color>
+    <color name="color_FF541BFF">#FF541BFF</color>
+    <color name="color_FF462E90">#FF462E90</color>
+    <color name="color_FFA052E5">#FFA052E5</color>
 </resources>

+ 3 - 0
module/gift/src/main/AndroidManifest.xml

@@ -18,5 +18,8 @@
             android:name=".CustomGiftActivity"
             android:screenOrientation="portrait"
             android:theme="@style/AppTheme" />
+        <activity android:name=".LuckyGiftRuleActivity"
+            android:screenOrientation="portrait"
+            android:theme="@style/AppTheme"/>
     </application>
 </manifest>

+ 11 - 4
module/gift/src/main/java/com/adealink/weparty/gift/GiftPageFragment.kt

@@ -6,7 +6,6 @@ import androidx.recyclerview.widget.GridLayoutManager
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.base.fastLazy
 import com.adealink.frame.ext.isViewBindingValid
-import com.adealink.frame.log.Log
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.router.Router
 import com.adealink.frame.router.annotation.BindExtra
@@ -15,6 +14,7 @@ import com.adealink.weparty.commonui.recycleview.diffutil.BaseListDiffUtil
 import com.adealink.weparty.commonui.recycleview.diffutil.BaseListItemData
 import com.adealink.weparty.gift.adapter.NormalGiftItemViewBinder
 import com.adealink.weparty.gift.adapter.TimeLimitGiftItemViewBinder
+import com.adealink.weparty.gift.data.GiftItemData
 import com.adealink.weparty.gift.data.NormalGiftListItemData
 import com.adealink.weparty.gift.data.TimeLimitGiftItemData
 import com.adealink.weparty.gift.databinding.FragmentGiftPageBinding
@@ -42,6 +42,7 @@ class GiftPageFragment : BaseGiftPageFragment(R.layout.fragment_gift_page),
 
         private const val TIME_LIMIT_GIFT_INDEX = 0 //限时礼物固定在第0位
         private const val FREE_GIFT_INDEX = 7 //免费礼物固定在第8位
+        private const val LUCKY_GIFT_INDEX = 2 //幸运礼物固定在第2、3位
 
         fun newInstance(giftPageType: GiftPageType): GiftPageFragment {
             return GiftPageFragment().apply {
@@ -61,7 +62,7 @@ class GiftPageFragment : BaseGiftPageFragment(R.layout.fragment_gift_page),
 
     private val adapter by fastLazy { MultiTypeListAdapter(BaseListDiffUtil()) }
 
-    private var giftDataList: MutableList<BaseListItemData> = mutableListOf()
+    private var giftDataList: MutableList<GiftItemData> = mutableListOf()
 
     private val comboCreator by fastLazy {
         ComboCreator()
@@ -171,15 +172,18 @@ class GiftPageFragment : BaseGiftPageFragment(R.layout.fragment_gift_page),
 
 
     private fun onGetGifts(gifts: List<GiftInfo>) {
-        val giftItemList = mutableListOf<BaseListItemData>()
+        val giftItemList = mutableListOf<GiftItemData>()
+        val luckyGiftList = mutableListOf<GiftItemData>()
         var timeLimitGiftItemData: TimeLimitGiftItemData? = null
         var freeGiftItemData: NormalGiftListItemData? = null
         if (pageType == GiftPageType.NORMAL) {
-            var timeLimitGift: GiftInfo? = null
+            val timeLimitGift: GiftInfo? = null
             var freeGift: GiftInfo? = null
             gifts.forEachIndexed { _, giftInfo ->
                 if (giftInfo.isFreeGift()) {
                     freeGift = giftInfo
+                } else if(giftInfo.isLuckyGift()) {
+                    luckyGiftList.add(NormalGiftListItemData(giftInfo))
                 } else {
                     giftItemList.add(NormalGiftListItemData(giftInfo))
                 }
@@ -196,6 +200,9 @@ class GiftPageFragment : BaseGiftPageFragment(R.layout.fragment_gift_page),
                 giftItemList.add(min(FREE_GIFT_INDEX, giftItemList.size), itemData)
                 freeGiftItemData = itemData
             }
+            if (luckyGiftList.isNotEmpty()) { //将幸运礼物的位置调整到第2、3位
+                giftItemList.addAll(min(LUCKY_GIFT_INDEX, giftItemList.size), luckyGiftList)
+            }
         } else {
             giftItemList.addAll(gifts.map { NormalGiftListItemData(it) })
         }

+ 1 - 2
module/gift/src/main/java/com/adealink/weparty/gift/GiftPanelFragment.kt

@@ -9,7 +9,6 @@ import com.adealink.frame.base.fastLazy
 import com.adealink.frame.ext.parseInt
 import com.adealink.frame.log.Log
 import com.adealink.frame.mvvm.view.viewBinding
-import com.adealink.frame.router.annotation.BindExtra
 import com.adealink.weparty.commonui.BaseFragment
 import com.adealink.weparty.commonui.viewpager.Tab
 import com.adealink.weparty.commonui.viewpager.TabsPagerAdapter
@@ -17,7 +16,6 @@ import com.adealink.weparty.gift.backpack.GiftBackpackFragment
 import com.adealink.weparty.gift.data.TAG_GIFT
 import com.adealink.weparty.gift.databinding.FragmentGiftPanelBinding
 import com.adealink.weparty.gift.databinding.ItemGiftTabBinding
-import com.adealink.weparty.gift.panel.ActivityGiftPageFragment
 import com.adealink.weparty.gift.panel.BaseGiftPageFragment
 import com.adealink.weparty.gift.stat.GiftPanelStatEvent
 import com.adealink.weparty.gift.viewmodel.GiftPanelViewModel
@@ -173,6 +171,7 @@ class GiftPanelFragment : BaseFragment(R.layout.fragment_gift_panel), IGiftPanel
             GiftPageType.UN_KNOW,
             GiftPageType.ACTIVITY,
             GiftPageType.VIP,
+            GiftPageType.LUCKY,
             GiftPageType.CUSTOMIZE -> {
                 null
             }

+ 25 - 0
module/gift/src/main/java/com/adealink/weparty/gift/LuckyGiftRuleActivity.kt

@@ -0,0 +1,25 @@
+package com.adealink.weparty.gift
+
+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.weparty.commonui.BaseActivity
+import com.adealink.weparty.gift.databinding.ActivityLuckyGiftRuleBinding
+import com.adealink.weparty.module.gift.Gift
+import com.qmuiteam.qmui.widget.util.QMUIStatusBarHelper
+
+@RouterUri(path = [Gift.LuckyGiftRule.PATH], desc = "幸运礼物规则页")
+class LuckyGiftRuleActivity: BaseActivity() {
+    private val binding by viewBinding(ActivityLuckyGiftRuleBinding::inflate)
+
+    override fun initViews() {
+        setContentView(binding.root)
+        binding.ivBack.updateLayoutParams<ConstraintLayout.LayoutParams> {
+            topMargin = QMUIStatusBarHelper.getStatusbarHeight(this@LuckyGiftRuleActivity)
+        }
+        binding.ivBack.setOnClickListener {
+            finish()
+        }
+    }
+}

+ 11 - 1
module/gift/src/main/java/com/adealink/weparty/gift/components/GiftPanelBottomOperateComp.kt

@@ -40,8 +40,12 @@ class GiftPanelBottomOperateComp(
     private val fromScene: Int,
 ) : BaseViewComponent(lifecycleOwner) {
 
+    companion object {
+        private val giftCountList: List<Int> = arrayListOf(777, 77, 17, 7, 3, 1)
+        private val luckyGiftCountList: List<Int> = arrayListOf(777, 77, 17, 7, 1)
+    }
     var selectCount: Int = 1
-    private val selectItems: List<Int> = arrayListOf(777, 77, 17, 7, 3, 1)
+    private var selectItems = giftCountList
     private val walletViewModel by fastLazy { WalletModule.getWalletViewModel(requireActivity()) }
     private val giftViewModel by activityViewModels<GiftViewModel> { GiftViewModelFactory() }
 
@@ -71,7 +75,13 @@ class GiftPanelBottomOperateComp(
                 updateSelectCount(1)
                 binding.selectCount.isEnabled = false
                 binding.selectArrow.hide()
+            } else if (giftInfo.isLuckyGift()) {
+                updateSelectCount(1)
+                selectItems = luckyGiftCountList
+                binding.selectCount.isEnabled = true
+                binding.selectArrow.show()
             } else {
+                selectItems = giftCountList
                 binding.selectCount.isEnabled = true
                 binding.selectArrow.show()
             }

+ 8 - 0
module/gift/src/main/java/com/adealink/weparty/gift/data/GiftData.kt

@@ -70,6 +70,14 @@ data class RechargeGiftItemData(val rechargeConfig: RechargePackageConfig) : Gif
     }
 }
 
+data class LuckyGiftItemData(val giftInfo: GiftInfo, var isSelected: Boolean = false) :
+        GiftItemData() {
+
+    override fun areItemsTheSame(newItem: Any): Boolean {
+        return newItem is LuckyGiftItemData && giftInfo.id == newItem.giftInfo.id
+    }
+}
+
 data class TimeLimitGiftItemData(val giftInfo: GiftInfo, var isSelected: Boolean = false) :
     GiftItemData() {
 

+ 2 - 0
module/gift/src/main/java/com/adealink/weparty/gift/listener/IGiftListener.kt

@@ -28,6 +28,8 @@ interface IGiftListener : IListener {
 
     fun onLuckyGiftRewardNotify(notify: LuckyGiftLotteryNotify)
 
+    fun onChatLuckyGiftRewardNotify(notify: LuckyGiftLotteryNotify)
+
     fun onSendBackpackItemNotify(notify: SendBackpackItemNotify)
 
     fun onPersonalBackpackItemNotify(notify: SendBackpackItemNotify)

+ 5 - 10
module/gift/src/main/java/com/adealink/weparty/gift/luckygift/dialog/LuckGiftRewardDialog.kt

@@ -7,17 +7,17 @@ import android.view.Gravity
 import android.view.Window
 import android.view.WindowManager
 import com.adealink.frame.aab.util.getCompatString
-import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
-import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.router.Router
 import com.adealink.frame.router.annotation.BindExtra
 import com.adealink.frame.router.annotation.RouterUri
 import com.adealink.frame.util.DisplayUtil
-import com.adealink.weparty.module.gift.Gift
+import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
+import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.weparty.gift.R
-import com.adealink.weparty.module.gift.data.LuckyGiftLotteryNotify
 import com.adealink.weparty.gift.databinding.FragmentLuckyGiftRewardBinding
+import com.adealink.weparty.module.gift.Gift
+import com.adealink.weparty.module.gift.data.LuckyGiftLotteryNotify
 import com.adealink.weparty.R as APP_R
 
 @RouterUri(path = [Gift.LuckyGiftReward.PATH], desc = "超级幸运礼物中奖弹窗")
@@ -53,17 +53,12 @@ class LuckGiftRewardDialog : BaseDialogFragment(R.layout.fragment_lucky_gift_rew
             binding.tvRewardTimes.text = getCompatString(APP_R.string.common_times, it.lotteryRatio)
             binding.tvGetReward.text = getCompatString(APP_R.string.common_get_coin,
                 "${it.giftInfo.price}*${it.lotteryRatio}")
-            binding.ivRewardImg.setImageResource(when(it.lotteryRatio) {
-                in 1..100 -> R.drawable.gift_luck_gift_reward_coin_1_100
-                in 101..300 -> R.drawable.gift_luck_gift_reward_coin_101_300
-                else -> R.drawable.gift_luck_gift_reward_coin_300
-            })
         }
     }
 
     override fun resetWindowAttributes(window: Window) {
         super.resetWindowAttributes(window)
-        window.setLayout(DisplayUtil.dp2px(303f), WindowManager.LayoutParams.WRAP_CONTENT)
+        window.setLayout(DisplayUtil.dp2px(300f), WindowManager.LayoutParams.WRAP_CONTENT)
         window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
         val attr = window.attributes
         attr.gravity = Gravity.CENTER

+ 19 - 0
module/gift/src/main/java/com/adealink/weparty/gift/manager/GiftManager.kt

@@ -142,7 +142,19 @@ class GiftManager : BaseFrame<IGiftListener>(), IGiftManager, IRoomListener {
         override fun onNotify(data: LuckyGiftLotteryNotify) {
             handleLuckyGiftRewardNotify(data)
         }
+    }
+
+    private val chatLuckyGiftRewardNotify = object : ISocketNotify<LuckyGiftLotteryNotify> {
+
+        override val uri: String = "LUCKYGIFT_LOTTERY_NOTIFY_PRIVATE"
+
+        override fun needHandle(data: LuckyGiftLotteryNotify?): Boolean {
+            return data != null
+        }
 
+        override fun onNotify(data: LuckyGiftLotteryNotify) {
+            handleChatLuckyGiftRewardNotify(data)
+        }
     }
 
     private val sendBackpackItemNotify = object : ISocketNotify<SendBackpackItemNotify> {
@@ -204,6 +216,7 @@ class GiftManager : BaseFrame<IGiftListener>(), IGiftManager, IRoomListener {
         App.instance.networkService.subscribeNotify(sendGiftNotify)
         App.instance.networkService.subscribeNotify(newerSendGiftNotify)
         App.instance.networkService.subscribeNotify(luckyGiftRewardNotify)
+        App.instance.networkService.subscribeNotify(chatLuckyGiftRewardNotify)
         App.instance.networkService.subscribeNotify(sendBackpackItemNotify)
         App.instance.networkService.subscribeNotify(sendPersonalBackpackItemNotify)
         App.instance.networkService.subscribeNotify(chatSendGiftNotify)
@@ -1041,6 +1054,12 @@ class GiftManager : BaseFrame<IGiftListener>(), IGiftManager, IRoomListener {
         }
     }
 
+    private fun handleChatLuckyGiftRewardNotify(notify: LuckyGiftLotteryNotify) {
+        dispatch {
+            it.onChatLuckyGiftRewardNotify(notify)
+        }
+    }
+
     private fun handleSendBackpackItemNotify(notify: SendBackpackItemNotify) {
         Log.d(TAG_GIFT_SEND, "handleSendBackpackItemNotify, $notify")
         dispatch {

+ 5 - 0
module/gift/src/main/java/com/adealink/weparty/gift/viewmodel/GiftViewModel.kt

@@ -86,6 +86,7 @@ class GiftViewModel : BaseViewModel(), IGiftViewModel, IGiftListener {
     override val selectedGiftPageType: ExtLiveData<GiftPageType> = ExtMutableLiveData()
     override val sendUidSetLD: ExtLiveData<Set<Long>> = ExtMutableLiveData()
     override val luckyGiftRewardNotifyLD: ExtLiveData<LuckyGiftLotteryNotify> = ExtMutableLiveData()
+    override val chatLuckyGiftRewardNotifyLD: ExtLiveData<LuckyGiftLotteryNotify> = ExtMutableLiveData()
     override val giftBackpackItemSelectLD: ExtLiveData<UserPackageInfo> = ExtMutableLiveData()
     override val sendBackpackItemNotifyLD: ExtLiveData<SendBackpackItemNotify> = ExtMutableLiveData()
     override val timeLimitGiftUntilExpiredLD: ExtLiveData<Long> = ExtMutableLiveData()
@@ -544,6 +545,10 @@ class GiftViewModel : BaseViewModel(), IGiftViewModel, IGiftListener {
         luckyGiftRewardNotifyLD.send(notify, false)
     }
 
+    override fun onChatLuckyGiftRewardNotify(notify: LuckyGiftLotteryNotify) {
+        chatLuckyGiftRewardNotifyLD.send(notify, false)
+    }
+
     override fun onSendBackpackItemNotify(notify: SendBackpackItemNotify) {
         sendBackpackItemNotifyLD.send(notify, false)
     }

BIN
module/gift/src/main/res/drawable-xhdpi/gift_luck_gift_reward_coin_101_300.webp


BIN
module/gift/src/main/res/drawable-xhdpi/gift_luck_gift_reward_coin_1_100.webp


BIN
module/gift/src/main/res/drawable-xhdpi/gift_luck_gift_reward_coin_300.webp


BIN
module/gift/src/main/res/drawable-xhdpi/gift_lucky_gift_reward_coin.webp


BIN
module/gift/src/main/res/drawable-xhdpi/lucky_gift_bg.webp


BIN
module/gift/src/main/res/drawable-xhdpi/lucky_gift_desc_bg.webp


BIN
module/gift/src/main/res/drawable-xhdpi/lucky_gift_reward_bg.webp


BIN
module/gift/src/main/res/drawable-xhdpi/lucky_gift_rule_border.9.png


BIN
module/gift/src/main/res/drawable-xhdpi/lucky_gift_rule_left_ic.webp


BIN
module/gift/src/main/res/drawable-xhdpi/lucky_gift_rule_right_ic.webp


BIN
module/gift/src/main/res/drawable-xhdpi/lucky_gift_title.webp


+ 109 - 0
module/gift/src/main/res/layout/activity_lucky_gift_rule.xml

@@ -0,0 +1,109 @@
+<?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/color_FFA052E5"
+    android:fitsSystemWindows="false"
+    tools:layout_height="858dp">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_header"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:layout_constraintDimensionRatio="750:858"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/lucky_gift_bg" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_back"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_marginStart="16dp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/common_back_white_56_ic" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_title"
+        android:layout_width="300dp"
+        android:layout_height="66dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/iv_back"
+        app:srcCompat="@drawable/lucky_gift_title" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_desc"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="13dp"
+        android:background="@drawable/lucky_gift_desc_bg"
+        android:gravity="center"
+        android:maxLines="2"
+        android:paddingHorizontal="50dp"
+        android:text="@string/gift_lucky_gift_reward_desc"
+        android:textColor="@color/white"
+        android:textSize="14sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_bias="0.45" />
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/rule_container"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginHorizontal="12dp"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="30dp"
+        android:background="@drawable/lucky_gift_rule_border"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_desc">
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:layout_width="11dp"
+            android:layout_height="17dp"
+            android:layout_marginEnd="8dp"
+            app:srcCompat="@drawable/lucky_gift_rule_left_ic"
+            app:layout_constraintBottom_toBottomOf="@id/tv_rule_title"
+            app:layout_constraintEnd_toStartOf="@id/tv_rule_title"
+            app:layout_constraintTop_toTopOf="@id/tv_rule_title" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_rule_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="12dp"
+            android:text="@string/common_rule"
+            android:textColor="@color/color_FF541BFF"
+            android:textSize="18sp"
+            android:textStyle="bold"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:layout_width="11dp"
+            android:layout_height="17dp"
+            android:layout_marginStart="8dp"
+            app:srcCompat="@drawable/lucky_gift_rule_right_ic"
+            app:layout_constraintBottom_toBottomOf="@id/tv_rule_title"
+            app:layout_constraintStart_toEndOf="@id/tv_rule_title"
+            app:layout_constraintTop_toTopOf="@id/tv_rule_title" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_rule_desc"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="12dp"
+            android:layout_marginTop="10dp"
+            android:textColor="@color/color_FF462E90"
+            android:textSize="13sp"
+            android:text="@string/gift_lucky_gift_rule_desc"
+            android:lineSpacingMultiplier="1.4"
+            app:layout_constraintTop_toBottomOf="@id/tv_rule_title" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 32 - 32
module/gift/src/main/res/layout/fragment_lucky_gift_reward.xml

@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<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="wrap_content"
-    android:background="@drawable/commonui_dialog_bg"
-    android:padding="24dp">
+    android:layout_height="400dp"
+    android:background="@drawable/lucky_gift_reward_bg"
+    android:padding="38dp">
 
     <androidx.appcompat.widget.AppCompatTextView
         android:id="@+id/tv_congratulations"
@@ -12,41 +13,41 @@
         android:layout_height="wrap_content"
         android:gravity="center"
         android:text="@string/common_congratulations"
-        android:textColor="@color/color_222222"
-        android:textSize="18sp"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <androidx.appcompat.widget.AppCompatImageView
-        android:id="@+id/iv_reward_img"
-        android:layout_width="220dp"
-        android:layout_height="220dp"
-        android:layout_marginTop="34dp"
-        android:scaleType="fitXY"
-        android:src="@drawable/gift_luck_gift_reward_coin_1_100"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
+        android:textColor="@color/white"
+        android:textSize="25sp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintVertical_bias="0.2"/>
 
     <androidx.appcompat.widget.AppCompatTextView
         android:id="@+id/tv_reward_desc"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
+        android:layout_marginTop="12dp"
         android:gravity="center"
-        android:textColor="@color/color_222222"
-        android:textSize="16sp"
+        android:textColor="@color/white"
+        android:textSize="14sp"
         app:layout_constraintTop_toBottomOf="@id/tv_congratulations" />
 
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_reward_img"
+        android:layout_width="175dp"
+        android:layout_height="175dp"
+        android:layout_marginTop="15dp"
+        android:scaleType="fitXY"
+        android:src="@drawable/gift_lucky_gift_reward_coin"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_congratulations"/>
+
     <androidx.appcompat.widget.AppCompatTextView
         android:id="@+id/tv_reward_times"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:gravity="center"
-        android:textColor="@color/color_FFF5A623"
-        android:textSize="19sp"
-        android:textStyle="bold"
-        android:layout_marginTop="186dp"
-        app:layout_constraintTop_toTopOf="@id/iv_reward_img" />
+        android:textColor="@color/white"
+        android:textSize="17sp"
+        app:layout_constraintBottom_toTopOf="@id/tv_get_reward" />
 
     <androidx.appcompat.widget.AppCompatTextView
         android:id="@+id/tv_get_reward"
@@ -54,10 +55,9 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="8dp"
         android:gravity="center"
-        android:textColor="@color/color_FFF5A623"
-        android:textSize="12sp"
-        android:textStyle="bold"
-        app:layout_constraintTop_toBottomOf="@id/tv_reward_times" />
+        android:textColor="@color/white"
+        android:textSize="17sp"
+        app:layout_constraintBottom_toBottomOf="@id/iv_reward_img"/>
 
     <com.adealink.weparty.commonui.widget.CommonButton
         android:id="@+id/btn_confirm"
@@ -70,7 +70,7 @@
         app:is_strong="true"
         android:textSize="16sp"
         android:textStyle="bold"
-        app:button_radius="22dp"
-        app:layout_constraintTop_toBottomOf="@id/tv_get_reward" />
+        app:button_radius="35dp"
+        app:layout_constraintTop_toBottomOf="@id/iv_reward_img" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 2 - 2
module/gift/src/main/res/layout/item_normal_gift.xml

@@ -46,8 +46,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingHorizontal="2dp"
-            android:text="Lv20"
-            android:textSize="9dp"
+            tools:text="Lv20"
+            android:textSize="9sp"
             android:visibility="gone"
             android:background="@drawable/gift_intimacy_level_bg"
             android:textColor="@color/white"

+ 2 - 0
module/gift/src/main/res/values-ar/strings.xml

@@ -32,4 +32,6 @@
    <string name="gift_custom_upload_tips">هناك %1$s فرص تعديل مجانية كل شهر. التعديلات بعد استنفادها تتطلب عملات ذهبية إضافية.</string>
    <string name="gift_send_gift_error">اختار المستخدمين لإرسال الهدايا</string>
    <string name="gift_bottom_first_recharge">الشحنه الأولى</string>
+   <string name="gift_lucky_gift_rule_desc">١. أرسل هدايا الحظ لأصدقائك لفرصة ربح ما يصل إلى ١٨٨٨ ضعف الجائزة الذهبية؛\n٢. كلما زادت الهدايا المرسلة دفعة واحدة، زادت فرص الفوز وزاد المضاعف؛\n٣. يعتمد مضاعف المكافأة على قيمة الهدايا المرسلة؛\n٤. سيُخصص ٨٠٪ من قيمة الهدايا المحظوظة المستلمة لسحب يانصيب الهدايا المحظوظة، بينما يذهب الباقي إلى متلقي الهدية؛\n٥. المكافآت التي يتم الحصول عليها من لعبة الهدايا المحظوظة صالحة للاستخدام على منصة Yoki فقط، ولا يمكن استخدامها في أي أنشطة ربحية.\nالتفسير النهائي لهذه اللعبة يعود إلى Yoki.</string>
+   <string name="gift_lucky_gift_reward_desc">أرسل هدايا محظوظة لديك فرصة للحصول على 1800 ضعف جائزة العملة الذهبية</string>
 </resources>

+ 2 - 0
module/gift/src/main/res/values-zh/strings.xml

@@ -31,4 +31,6 @@
    <string name="gift_custom_upload_tips">每个月有%1$s次免费修改的机会,耗尽后再修改需要支付额外金币</string>
    <string name="gift_send_gift_error">需选择用户才能送礼</string>
    <string name="gift_bottom_first_recharge">首充</string>
+   <string name="gift_lucky_gift_rule_desc">1. 发送幸运礼物给好友,有机会赢取高达1888倍金币奖金;\n2. 一次性发送的礼物越多,中奖几率越高,倍数越大;\n3. 奖励倍数以发送的礼物价值为准;\n4. 收到的幸运礼物价值的80%将进入幸运礼物抽奖池,剩余部分归收礼人所有;\n5. 幸运礼物玩法所获得的奖励仅限在Yoki平台消费,不得用于任何形式的盈利活动。\n本玩法最终解释权归Yoki所有。</string>
+   <string name="gift_lucky_gift_reward_desc">送幸运礼物有机会获得1800倍金币大奖</string>
 </resources>

+ 2 - 0
module/gift/src/main/res/values/strings.xml

@@ -33,4 +33,6 @@
    <string name="gift_custom_upload_tips">There are %1$s free modification opportunities every month. Modifications after exhaustion require additional gold coins.</string>
    <string name="gift_send_gift_error">chose users to send gifts</string>
    <string name="gift_bottom_first_recharge">1st Recharge</string>
+   <string name="gift_lucky_gift_rule_desc">1. Send lucky gifts to friends for a chance to win up to 1888 times the gold prize;\n2. The more gifts sent at once, the higher the chance of winning and the greater the multiplier;\n3. The reward multiplier is based on the value of the gifts sent;\n4. 80% of the value of the lucky gifts received will go into the lucky gift lottery pool, with the remainder going to the gift recipient;\n5. Rewards obtained from the lucky gift gameplay are only valid for consumption on the Yoki platform and cannot be used for any form of profit-making activities.\nThe final interpretation of this gameplay is reserved by Yoki.</string>
+   <string name="gift_lucky_gift_reward_desc">Send lucky gifts have a chance to get 1800 Times the gold coin prize</string>
 </resources>

+ 6 - 1
module/headline/src/main/java/com/adealink/weparty/headline/view/CommonGlobalHeadline.kt

@@ -89,7 +89,12 @@ class CommonGlobalHeadline @JvmOverloads constructor(
         }
         binding.tvDesc.text = originContentSb
         //右边图标
-        binding.ivRightIcon.setImageUrl(notify.activityIconUrl)
+        if(notify.activityIconUrl.isEmpty()) {
+            binding.ivRightIcon.visibility = View.GONE
+        } else {
+            binding.ivRightIcon.visibility = View.VISIBLE
+            binding.ivRightIcon.setImageUrl(notify.activityIconUrl)
+        }
         //右边按钮
         val button = notify.button
         if (button == null) {

+ 1 - 0
module/headline/src/main/res/layout/layout_common_global_headline.xml

@@ -115,6 +115,7 @@
             android:layout_height="60dp"
             android:layout_marginTop="15dp"
             android:layout_marginEnd="4dp"
+            android:visibility="gone"
             app:layout_constraintEnd_toStartOf="@id/btn_play"
             app:layout_constraintTop_toTopOf="parent" />
 

+ 42 - 0
module/message/src/main/java/com/adealink/weparty/message/conversation/comp/ChatGiftComp.kt

@@ -2,9 +2,11 @@ package com.adealink.weparty.message.conversation.comp
 
 import android.content.Intent
 import android.graphics.PointF
+import android.os.Bundle
 import android.view.View
 import android.widget.ImageView
 import androidx.lifecycle.LifecycleOwner
+import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.base.fastLazy
 import com.adealink.frame.effect.svga.data.PathType
@@ -12,10 +14,13 @@ import com.adealink.frame.effect.svga.data.SVGAEffectEntity
 import com.adealink.frame.effect.video.data.VideoEffectEntity
 import com.adealink.frame.effect.view.EffectView
 import com.adealink.frame.mvvm.view.ViewComponent
+import com.adealink.frame.router.Router
 import com.adealink.frame.tceffect.effect.data.TCEffectEntity
 import com.adealink.frame.util.getCenterLocationInWindow
 import com.adealink.frame.util.getLocationInWindow
+import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
 import com.adealink.weparty.commonui.ext.dp
+import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.weparty.effect.EffectAnimType
 import com.adealink.weparty.effect.EffectSaveResource
 import com.adealink.weparty.message.constant.MESSAGE_FROM_USER_AVATAR_KEY
@@ -26,11 +31,13 @@ import com.adealink.weparty.message.effect.GiftEffectListener
 import com.adealink.weparty.message.effect.SendStaticGiftEffectEntity
 import com.adealink.weparty.message.effect.StaticGiftEffectLayout
 import com.adealink.weparty.module.anchor.data.FromScene
+import com.adealink.weparty.module.gift.Gift
 import com.adealink.weparty.module.gift.GiftModule
 import com.adealink.weparty.module.gift.data.DEFAULT_GIFT_EFFECT_TIMEOUT_MS
 import com.adealink.weparty.module.gift.data.DynamicEntityType
 import com.adealink.weparty.module.gift.data.GiftDynamicEntity
 import com.adealink.weparty.module.gift.data.GiftInfo
+import com.adealink.weparty.module.gift.data.LuckyGiftLotteryNotify
 import com.adealink.weparty.module.gift.data.SendBackpackItemNotify
 import com.adealink.weparty.module.gift.data.SendGiftNotify
 import com.adealink.weparty.module.gift.data.getSVGAGiftDynamicEntity
@@ -39,10 +46,13 @@ import com.adealink.weparty.module.gift.data.getVapFetchResource
 import com.adealink.weparty.module.gift.data.toSendGiftItems
 import com.adealink.weparty.module.gift.effect.CommonGiftEffectEntity
 import com.adealink.weparty.module.gift.effect.SendGiftNoticeLayout
+import com.adealink.weparty.module.gift.effect.luckygift.LuckyGiftBigRewardEffectEntity
+import com.adealink.weparty.module.gift.effect.luckygift.LuckyGiftRewardEffectEntity
 import com.adealink.weparty.module.profile.ProfileModule
 import com.adealink.weparty.module.profile.data.UserInfo
 import com.adealink.weparty.module.room.ring.RingEffectEntity
 import com.adealink.weparty.module.store.data.StoreGoodType
+import com.adealink.weparty.module.wallet.WalletModule
 import com.qmuiteam.qmui.widget.util.QMUIDisplayHelper
 
 class ChatGiftComp(
@@ -89,6 +99,38 @@ class ChatGiftComp(
                 handleSendBackItemNotify(notify)
             }
         }
+        giftViewModel?.chatLuckyGiftRewardNotifyLD?.observeWithoutCache(viewLifecycleOwner) { notify ->
+            handleLuckGiftRewardNotify(notify)
+        }
+    }
+
+
+    private fun handleLuckGiftRewardNotify(notify: LuckyGiftLotteryNotify) {
+        if (notify.userInfo.uid == ProfileModule.getMyUid()) {
+            if (notify.giftInfo.isComboGift == 1) {
+                //幸运礼物combo弹toast提醒
+                showToast(
+                    getCompatString(
+                        com.adealink.weparty.R.string.common_lucky_gift_reward, notify.giftInfo.name,
+                        notify.lotteryRatio
+                    )
+                )
+            } else {
+                Router.getRouterInstance<BaseDialogFragment>(Gift.LuckyGiftReward.PATH)?.apply {
+                    this.arguments = Bundle().apply {
+                        putParcelable(Gift.LuckyGiftReward.EXTRA_LUCKY_GIFT_REWARD, notify)
+                    }
+                }?.show(fragmentManager)
+            }
+            WalletModule.getWalletViewModel(requireActivity())?.getMyCoinCount()
+        }
+        if (notify.showPlace == 1) {
+            if(notify.lotteryRatio >= 300) {
+                giftEffectView.add(LuckyGiftBigRewardEffectEntity("", notify))
+            } else {
+                giftEffectView.add(LuckyGiftRewardEffectEntity("", notify))
+            }
+        }
     }
 
     private fun handleSendGiftNotify(

+ 0 - 2
module/message/src/main/java/com/adealink/weparty/message/conversation/extension/inputpanel/ConversationInputPanelFragment.kt

@@ -60,7 +60,6 @@ import com.adealink.weparty.module.anchor.data.FromScene
 import com.adealink.weparty.module.call.Call
 import com.adealink.weparty.module.couple.data.IntimacyPrivilegeType
 import com.adealink.weparty.module.couple.util.dialogIntimacyPrivilegeLimitedTips
-import com.adealink.weparty.module.gift.Gift
 import com.adealink.weparty.module.message.Message
 import com.adealink.weparty.module.message.conversation.extension.InputMode
 import com.adealink.weparty.module.message.data.ChatButtonStatus
@@ -73,7 +72,6 @@ import com.adealink.weparty.module.room.Room
 import com.adealink.weparty.permission.PermissionUtils
 import com.adealink.weparty.stat.SendIMStatEvent
 import io.rong.imlib.model.Conversation.ConversationType
-import io.rong.imlib.model.ConversationIdentifier
 import io.rong.message.TextMessage
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch

+ 3 - 3
module/message/src/main/java/com/adealink/weparty/message/conversation/provider/BaseNotificationMessageItemProvider.kt

@@ -11,11 +11,8 @@ import androidx.appcompat.widget.AppCompatTextView
 import com.adealink.frame.aab.util.getCompatColor
 import com.adealink.frame.aab.util.getCompatDrawable
 import com.adealink.frame.data.json.froJsonErrorNull
-import com.adealink.weparty.message.data.UiMessage
-import com.adealink.weparty.message.util.IMDateUtils
 import com.adealink.frame.imkit.widget.adapter.IViewProviderListener
 import com.adealink.frame.imkit.widget.adapter.ViewHolder
-import com.adealink.weparty.message.R
 import com.adealink.frame.log.Log
 import com.adealink.frame.util.AppUtil
 import com.adealink.weparty.commonui.drawabletoolbox.DrawableBuilder
@@ -24,9 +21,12 @@ import com.adealink.weparty.commonui.text.DataBindingSpanHelper
 import com.adealink.weparty.commonui.text.span.DataBindingSpan
 import com.adealink.weparty.commonui.text.span.ImageDataBindingSpan
 import com.adealink.weparty.commonui.text.span.LinkDataBindingSpan
+import com.adealink.weparty.message.R
 import com.adealink.weparty.message.constant.TAG_IM_MSG_PROVIDER
 import com.adealink.weparty.message.conversation.data.InfoMessageExtraConfig
 import com.adealink.weparty.message.conversation.message.TargetInfoMessage
+import com.adealink.weparty.message.data.UiMessage
+import com.adealink.weparty.message.util.IMDateUtils
 import com.adealink.weparty.util.goLocalLinkPage
 import io.rong.imlib.model.Message
 import io.rong.imlib.model.MessageContent

+ 3 - 3
module/room/src/main/java/com/adealink/weparty/room/chatroom/page/chat/ChatRoomDynamicFactory.kt

@@ -187,9 +187,9 @@ class ChatRoomBaseLayerFactory : IDynamicViewFactory<ConstraintLayout.LayoutPara
             }
 
             R.id.id_chat_room_gift_banner_view -> {
-                ConstraintLayout.LayoutParams(0, 36.dp()).apply {
-                    topMargin = 9.dp()
+                ConstraintLayout.LayoutParams(0, 0).apply {
                     topToTop = ConstraintLayout.LayoutParams.PARENT_ID
+                    bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
                     startToStart = ConstraintLayout.LayoutParams.PARENT_ID
                     endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
                 }
@@ -245,7 +245,7 @@ class ChatRoomBaseLayerFactory : IDynamicViewFactory<ConstraintLayout.LayoutPara
                     topToTop = ConstraintLayout.LayoutParams.PARENT_ID
                     startToStart = ConstraintLayout.LayoutParams.PARENT_ID
                     endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
-                    topMargin = 32.dp()
+                    topMargin = 48.dp()
                 }
             }
 

+ 3 - 3
module/room/src/main/java/com/adealink/weparty/room/gift/view/RoomGiftComp.kt

@@ -55,11 +55,13 @@ import com.adealink.weparty.module.gift.data.toSendGiftItems
 import com.adealink.weparty.module.gift.datasource.local.GiftExportLocalService
 import com.adealink.weparty.module.gift.effect.CommonGiftEffectEntity
 import com.adealink.weparty.module.gift.effect.SendGiftNoticeLayout
+import com.adealink.weparty.module.gift.effect.luckygift.LuckyGiftRewardEffectEntity
 import com.adealink.weparty.module.gift.view.EdgeFlashEffectView
 import com.adealink.weparty.module.gift.view.GiftFallingLayout
 import com.adealink.weparty.module.profile.ProfileModule
 import com.adealink.weparty.module.profile.data.UserInfo
 import com.adealink.weparty.module.room.Room
+import com.adealink.weparty.module.room.base.BaseRoomComp
 import com.adealink.weparty.module.room.chat.data.GiftTreasureSendMsgContent
 import com.adealink.weparty.module.room.chat.data.LuckyGiftRewardMsgContent
 import com.adealink.weparty.module.room.chat.data.Message
@@ -73,7 +75,6 @@ import com.adealink.weparty.module.store.data.StoreGoodType
 import com.adealink.weparty.module.wallet.WalletModule
 import com.adealink.weparty.room.R
 import com.adealink.weparty.room.attr.viewmodel.RoomAttrViewModel
-import com.adealink.weparty.module.room.base.BaseRoomComp
 import com.adealink.weparty.room.chat.viewmodel.ChatMessageViewModel
 import com.adealink.weparty.room.databinding.LayoutGiftFallingViewBinding
 import com.adealink.weparty.room.device.viewmodel.RoomDeviceViewModel
@@ -84,7 +85,6 @@ import com.adealink.weparty.room.gift.widget.SendStaticGiftEffectEntity
 import com.adealink.weparty.room.gift.widget.StaticGiftEffectLayout
 import com.adealink.weparty.room.member.viewmodel.RoomMemberViewModel
 import com.adealink.weparty.room.operate.RoomBottomOperateFragment
-import com.adealink.weparty.module.gift.effect.luckygift.LuckyGiftRewardEffectEntity
 import com.adealink.weparty.room.sdk.service.roomService
 import com.adealink.weparty.room.viewmodel.RoomViewModelFactory
 import com.qmuiteam.qmui.widget.util.QMUIDisplayHelper
@@ -716,7 +716,7 @@ class RoomGiftComp(
             }
             walletViewModel?.getMyCoinCount()
         }
-        if (notify.showPlace == 1) {
+        if (notify.showPlace == 1 && notify.lotteryRatio in 100..299) {
             bannerEffectView.view {
                 it.add(LuckyGiftRewardEffectEntity("", notify))
             }