diff --git a/app/build.gradle b/app/build.gradle
index 57addf3fe..429897ac0 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -205,6 +205,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
api 'androidx.multidex:multidex:2.0.1'
+ implementation 'androidx.gridlayout:gridlayout:1.0.0'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
@@ -270,6 +271,8 @@ dependencies {
//wheelView
implementation 'com.contrarywind:wheelview:4.1.0'
+ // 轮播组件
+ implementation 'io.github.youth5201314:banner:2.2.3'
implementation project(':modules:module_base')
if (!isolationMode && file("../modules/module_google/build.gradle").exists()) {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3b2f3073c..37ddb7bee 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -734,7 +734,10 @@
android:screenOrientation="portrait" />
+ android:screenOrientation="portrait" />
+
diff --git a/app/src/main/java/com/chwl/app/home/fragment/MeFragment.kt b/app/src/main/java/com/chwl/app/home/fragment/MeFragment.kt
index 28cc3f71b..f751d6055 100644
--- a/app/src/main/java/com/chwl/app/home/fragment/MeFragment.kt
+++ b/app/src/main/java/com/chwl/app/home/fragment/MeFragment.kt
@@ -35,6 +35,7 @@ import com.chwl.app.ui.utils.ImageLoadUtils
import com.chwl.app.ui.wallet.WalletActivity
import com.chwl.app.ui.webview.CommonWebViewActivity
import com.chwl.app.view.GenderAgeTextView
+import com.chwl.app.vip.VipCenterActivity
import com.chwl.app.vip.VipMainActivity
import com.chwl.app.vip.VipViewModel
import com.chwl.core.auth.AuthModel
@@ -353,7 +354,8 @@ class MeFragment : BaseFragment(), View.OnClickListener {
}
R.id.iv_vip -> {
- VipMainActivity.start(mContext)
+// VipMainActivity.start(mContext)
+ VipCenterActivity.start(mContext)
//进入贵族中心埋点
val goldWalletInfo = PayModel.get().currentWalletInfo
val map = HashMap(5)
diff --git a/app/src/main/java/com/chwl/app/vip/VipCenterActivity.kt b/app/src/main/java/com/chwl/app/vip/VipCenterActivity.kt
new file mode 100644
index 000000000..48feb674b
--- /dev/null
+++ b/app/src/main/java/com/chwl/app/vip/VipCenterActivity.kt
@@ -0,0 +1,403 @@
+package com.chwl.app.vip
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.TextView
+import androidx.activity.viewModels
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.view.isVisible
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.resource.bitmap.RoundedCorners
+import com.bumptech.glide.request.RequestOptions
+import com.chwl.app.R
+import com.chwl.app.base.BaseViewBindingActivity
+import com.chwl.app.base.TitleBar
+import com.chwl.app.common.EmptyViewHelper
+import com.chwl.app.databinding.ActivityVipCenterBinding
+import com.chwl.app.ui.pay.ChargeActivity
+import com.chwl.app.ui.utils.RVDelegate
+import com.chwl.app.ui.webview.CommonWebViewActivity
+import com.chwl.app.vip.adapter.VipAuthAdapter
+import com.chwl.app.vip.adapter.VipCenterBannerAdapter
+import com.chwl.app.vip.adapter.VipCenterIdentificationsAdapter
+import com.chwl.app.vip.adapter.VipMagicIndicatorAdapter
+import com.chwl.app.vip.adapter.VipRebateAdapter
+import com.chwl.app.vip.dialog.SelectPayTypeDialog
+import com.chwl.app.vip.dialog.VipAuthDetailsDialog
+import com.chwl.core.UriProvider
+import com.chwl.core.pay.PayModel
+import com.chwl.core.pay.bean.ChargeBean
+import com.chwl.core.utils.extension.toast
+import com.chwl.core.vip.bean.VipAuthInfo
+import com.chwl.core.vip.bean.VipInfo
+import com.example.module_base.support.billing.IBillingService
+import com.example.module_base.support.billing.IProductDetails
+import com.example.module_base.support.billing.IPurchase
+import com.youth.banner.Banner
+import com.youth.banner.adapter.BannerImageAdapter
+import com.youth.banner.holder.BannerImageHolder
+import com.youth.banner.indicator.CircleIndicator
+import com.youth.banner.transformer.AlphaPageTransformer
+import com.youth.banner.transformer.DepthPageTransformer
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import org.greenrobot.eventbus.EventBus
+
+
+class VipCenterActivity : BaseViewBindingActivity(),
+ VipMagicIndicatorAdapter.OnItemSelectListener, IBillingService.Listener {
+
+ private val authAdapter = VipAuthAdapter() // 用户权限
+ private val vipViewModel: VipViewModel by viewModels()
+ private var chargeList: List? = null
+ private val rebateAdapter = VipRebateAdapter()
+ private var currentChargeInfo: ChargeBean? = null
+ private lateinit var rvDelegate: RVDelegate
+ private lateinit var banner:Banner
+
+ private lateinit var recyclerView: RecyclerView
+ private lateinit var vipIdentificationsAdapter: VipCenterIdentificationsAdapter
+
+// protected var banner: Banner? = null
+
+ companion object {
+
+ @JvmStatic
+ fun start(context: Context) {
+ val starter = Intent(context, VipCenterActivity::class.java)
+ context.startActivity(starter)
+ }
+
+ private const val BIND_CODE_GOLD = 200
+ private const val TAG = "VipCenterActivity"
+ }
+
+ @SuppressLint("SetTextI18N")
+ override fun init() {
+ EventBus.getDefault().register(this)
+ initWhiteTitleBar(getString(R.string.vip_center))
+
+ initView()
+ initObserve()
+
+ handleAuthAdapter()
+ handleViewModel()
+ handleBinding()
+
+ rvDelegate = RVDelegate.Builder()
+ .setLayoutManager(GridLayoutManager(this, 3))
+ .setRecyclerView(binding.recyclerViewBottom)
+ .setEmptyView(
+ EmptyViewHelper.createEmptyTextView(
+ context,
+ getString(R.string.me_no_search_results)
+ )
+ )
+ .setAdapter(authAdapter)
+ .build()
+
+ authAdapter.setOnItemClickListener { _, _, position ->
+ authAdapter.getItem(position)?.let {
+ VipAuthDetailsDialog.newInstance(it.descPic, it.authName, it.authIntro).show(this)
+ }
+ }
+
+ requestChargeList{
+ loadChargeList(it)
+ }
+ }
+
+ private fun initView() {
+ banner = findViewById(R.id.banner_view)
+ banner.isAutoLoop(false)
+ banner.setBannerGalleryEffect(25, 25,25)
+
+ recyclerView = findViewById(R.id.recycler_view)
+ recyclerView.layoutManager = GridLayoutManager(this, 2)
+
+// val identificationTitle = findViewById(R.id.center_title)
+// identificationTitle.text = R.string.vip_center_2.toString()
+//
+// val exclusivePrivilegesTitle = findViewById(R.id.center_title_2)
+// exclusivePrivilegesTitle.text = R.string.vip_center_4.toString()
+ }
+
+ override fun initWhiteTitleBar(title: String?) {
+ mTitleBar = findViewById(R.id.title_bar)
+ if (mTitleBar != null) {
+ mTitleBar.setTitle(title)
+ mTitleBar.setImmersive(false)
+ mTitleBar.setTitleColor(resources.getColor(R.color.color_FFE3AF))
+ mTitleBar.setLeftImageResource(R.drawable.vip_center_back_button)
+ mTitleBar.setBackgroundResource(R.color.transparent)
+ mTitleBar.setLeftClickListener { onLeftClickListener() }
+ mTitleBar.addAction(object : TitleBar.ImageAction(R.drawable.vip_center_help_button) {
+ override fun performAction(view: View) {
+ CommonWebViewActivity.start(
+ this@VipCenterActivity,
+ UriProvider.getVipHelpUrl())
+ }
+ })
+ }
+ }
+
+ private fun handleAuthAdapter() {
+ authAdapter.setOnItemClickListener { _, _, position ->
+ authAdapter.getItem(position)?.let {
+ VipAuthDetailsDialog.newInstance(it.descPic, it.authName, it.authIntro).show(this)
+ }
+ }
+ }
+
+ private fun handleBinding() {
+ binding.layoutOpenVip.setOnClickListener {
+ checkBuyVip {
+ buyVip()
+ }
+ }
+
+ binding.recyclerViewBottom.isNestedScrollingEnabled = false
+ }
+
+ private fun handleViewModel() {
+ vipViewModel.getVipPageInfo()
+
+ vipViewModel.loadingLiveData.observe(this) {
+ if (it == true) {
+ dialogManager.showProgressDialog(this)
+ } else {
+ dialogManager.dismissDialog()
+ }
+ }
+
+ vipViewModel.authInfosLiveData.observe(this) {
+ // ArrayList[VipAuthInfo] // 全部特权列表
+ authAdapter.setNewData(it)
+ it?.let {
+ vipIdentificationsAdapter = VipCenterIdentificationsAdapter(this, it)
+ recyclerView.adapter = vipIdentificationsAdapter
+ }
+ }
+
+ vipViewModel.pageLiveData.observe(this) {
+ it?.let { // 当前显示的 index
+// binding.magicIndicator.onPageSelected(it)
+ // TODO 处理轮播组件 index 更新
+ }
+ }
+
+ vipViewModel.vipInfosLiveData.observe(this) {
+ it?.let { // ArrayList[VipInfo] 每个等级的 VIP 内容
+// initTitleTab(it)
+ // TODO 初始化轮播组件
+ val adapter = VipCenterBannerAdapter(this, it)
+ banner.setAdapter(adapter)
+
+// banner.setAdapter(object : BannerImageAdapter(it) {
+// override fun onBindView(holder: BannerImageHolder, data: VipInfo, position: Int, size: Int) {
+// //图片加载自己实现
+// Glide.with(holder.itemView)
+// .load(data.vipIcon)
+// .apply(RequestOptions.bitmapTransform(RoundedCorners(30)))
+// .into(holder.imageView)
+// }
+// override fun onCreateHolder(
+// parent: ViewGroup?,
+// viewType: Int
+// ): BannerImageHolder {
+// return super.onCreateHolder(parent, viewType)
+// }
+// }).addBannerLifecycleObserver(this)
+// .setIndicator(CircleIndicator(this), false)
+ }
+ }
+
+
+ vipViewModel.myVipInfoLiveData.observe(this) {
+ it?.let {
+ //TODO 处理有 VIP 的情况
+// bannerView.visibility = View.VISIBLE
+// bannerView.post {
+// binding.bannerView.setPageMargin(UIUtil.dip2px(mContext, 8.0))
+// .setScrollDuration(800)
+// .setOnPageClickListener { _: View?, position: Int ->
+// }
+// .create(it)
+// }
+ } ?: run {
+// binding.layoutLevelInfo.isVisible = false
+// binding.layoutLevelProgress.isVisible = false
+ binding.slAuth.isVisible = true
+// binding.tvNotOpen.text = getString(R.string.me_no_aristocracy_yet)
+ }
+ }
+
+ vipViewModel.currVipInfoLiveData.observe(this) {
+ it?.let { // VipInfo
+ // TODO 根据当前显示的 VIP 信息更新 UI
+ } ?: run {
+ getString(R.string.me_failed_to_get_aristocrat_data).toast()
+ }
+ }
+ }
+
+ @SuppressLint("CheckResult")
+ private fun requestChargeList(call: (List) -> Unit) {
+ PayModel.get().vipList
+ .compose(bindToLifecycle())
+ .subscribe(
+ {
+ call.invoke(it)
+ }, {
+ it.printStackTrace()
+ }
+ )
+ }
+
+ private fun initObserve(){
+ lifecycleScope.launch(Dispatchers.Main) {
+ vipViewModel.getVipRebateSuccessFlow.collect {
+ rebateAdapter.notifyItemRangeChanged(0, rebateAdapter.itemCount, true)
+ }
+ }
+ }
+
+ private fun loadChargeList(list: List) {
+ this.chargeList = list
+ refreshOpenVipState()
+ }
+
+ private fun checkBuyVip(block: () -> Unit) {
+ val myVipInfo = vipViewModel.myVipInfoLiveData.value
+ val currentVipInfo = vipViewModel.currVipInfoLiveData.value
+ if (currentVipInfo != null && myVipInfo != null && currentVipInfo.vipLevel > myVipInfo.vipLevel) {
+ val message = context.getString(R.string.vip_buy_tips).format(
+ myVipInfo.vipName,currentVipInfo.vipName
+ )
+ dialogManager.showOkCancelDialog(message,
+ context.getString(R.string.miniworld_activity_mwteamroommessageact_07),
+ context.getString(R.string.miniworld_activity_mwteamroommessageact_08),
+ true
+ ) { block.invoke() }
+ } else {
+ block.invoke()
+ }
+ }
+
+ private fun buyVip() {
+ val googleUnavailable = ((currentChargeInfo?.productDetails?.getOneTimePurchaseOfferDetails()
+ ?.getPriceAmountMicros()
+ ?: "0") == "0")
+ var text =
+ currentChargeInfo?.productDetails?.getOneTimePurchaseOfferDetails()?.getFormattedPrice()
+ if (text.isNullOrEmpty()) {
+ text = ((currentChargeInfo?.money ?: 0.0) * 1000).toInt().toString()
+ }
+ SelectPayTypeDialog.newInstance(
+ text,
+ !googleUnavailable,
+ currentChargeInfo?.getMoney() ?: 0.0
+ )
+ .apply {
+ setOnDiamondChargeClick {
+ vipViewModel.openVipWithDiamond(
+ currentChargeInfo?.getProdDesc()?.toIntOrNull() ?: -1
+ )
+ }
+ setOnGoogleChargeClick {
+ if (googleUnavailable) {
+ toast(getString(R.string.Recharge_failure))
+ return@setOnGoogleChargeClick
+ }
+ currentChargeInfo?.let { charge ->
+ buyProduct(charge.productDetails)
+ }
+ }
+ setOnChargeClick {
+ ChargeActivity.start(this@VipCenterActivity)
+ }
+ }
+ .show(context)
+ }
+
+ /*购买商品*/
+ @SuppressLint("CheckResult")
+ fun buyProduct(productDetails: IProductDetails?) {
+ if (productDetails != null) {
+ Log.d(VipCenterActivity.TAG, "BuyProduct:" + productDetails.getProductId())
+// PayModel.get().placeOrder(productDetails.getProductId())
+// .compose(bindToLifecycle())
+// .subscribe(
+// { recordId: PayRecordId ->
+// billingManager?.initiatePurchaseFlow(
+// productDetails,
+// recordId.recordId
+// )
+// }
+// ) { throwable: Throwable ->
+// SingleToastUtil.showToast(
+// throwable.message
+// )
+// }
+ } else {
+ Log.w(VipCenterActivity.TAG, "skuDetails ==null")
+ }
+ }
+
+ private fun refreshOpenVipState() {
+ val currentVipInfo = vipViewModel.currVipInfoLiveData.value
+ val myVipInfo = vipViewModel.myVipInfoLiveData.value
+ if (currentVipInfo != null) {
+ currentChargeInfo = chargeList?.firstOrNull {
+ it.prodDesc?.toIntOrNull() == currentVipInfo.vipLevel
+ }
+ if (currentChargeInfo != null && (myVipInfo == null || myVipInfo.vipLevel < currentVipInfo.vipLevel)) {
+ "${currentChargeInfo?.getMoney()} ${
+ getString(R.string.vip_buy_format).format(
+ currentVipInfo.vipName
+ )
+ }".also { binding.tvOpenVip.text = it }
+ binding.layoutOpenVip.isVisible = true
+ } else {
+ binding.layoutOpenVip.isVisible = false
+ }
+ } else {
+ currentChargeInfo = null
+// binding.layoutOpenVip.isVisible = false
+ }
+// if (binding.layoutOpenVip.isVisible && binding.layoutLevelProgress.isVisible) {
+// binding.layoutBottomPanel.setBackgroundDrawable(binding.layoutLevelProgress.background)
+// } else {
+// binding.layoutBottomPanel.setBackgroundDrawable(null)
+// }
+ }
+
+ override fun onItemSelect(position: Int, view: TextView?) {
+ TODO("Not yet implemented")
+ }
+
+ override fun onBillingClientSetupFinished() {
+ TODO("Not yet implemented")
+ }
+
+ override fun onPurchasesUpdated(purchases: List) {
+ TODO("Not yet implemented")
+ }
+
+ override fun onConsumeFinished(token: String?, result: Int) {
+ TODO("Not yet implemented")
+ }
+
+ override fun onFailedHandle(result: Int) {
+ TODO("Not yet implemented")
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/chwl/app/vip/VipMainActivity.kt b/app/src/main/java/com/chwl/app/vip/VipMainActivity.kt
index 94325809b..fd6527cc4 100644
--- a/app/src/main/java/com/chwl/app/vip/VipMainActivity.kt
+++ b/app/src/main/java/com/chwl/app/vip/VipMainActivity.kt
@@ -546,12 +546,11 @@ class VipMainActivity : BaseViewBindingActivity(),
it.prodDesc?.toIntOrNull() == currentVipInfo.vipLevel
}
if (currentChargeInfo != null && (myVipInfo == null || myVipInfo.vipLevel < currentVipInfo.vipLevel)) {
- binding.tvOpenVip.text =
- "${currentChargeInfo?.getMoney()} ${
- getString(R.string.vip_buy_format).format(
- currentVipInfo.vipName
- )
- }"
+ "${currentChargeInfo?.getMoney()} ${
+ getString(R.string.vip_buy_format).format(
+ currentVipInfo.vipName
+ )
+ }".also { binding.tvOpenVip.text = it }
binding.layoutOpenVip.isVisible = true
} else {
binding.layoutOpenVip.isVisible = false
diff --git a/app/src/main/java/com/chwl/app/vip/adapter/VipCenterBannerAdapter.kt b/app/src/main/java/com/chwl/app/vip/adapter/VipCenterBannerAdapter.kt
new file mode 100644
index 000000000..f766453d9
--- /dev/null
+++ b/app/src/main/java/com/chwl/app/vip/adapter/VipCenterBannerAdapter.kt
@@ -0,0 +1,49 @@
+package com.chwl.app.vip.adapter
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.chwl.app.R
+import com.chwl.core.vip.bean.VipInfo
+import com.youth.banner.adapter.BannerAdapter
+
+class VipCenterBannerAdapter(
+ private val context: Context,
+ private val vipInfos: List
+) : BannerAdapter(vipInfos) {
+ override fun onCreateHolder(parent: ViewGroup, viewType: Int): BannerViewHolder {
+ val view = LayoutInflater.from(context).inflate(
+ R.layout.banner_vip_center_custom,
+ parent,
+ false)
+ return BannerViewHolder(view)
+ }
+
+ override fun onBindView(holder: BannerViewHolder, data: VipInfo, position: Int, size: Int) {
+ // 加载本地背景图片
+ when(position) {
+ 1->holder.imgBackground.setImageResource(R.drawable.vip_center_level_1)
+ 2->holder.imgBackground.setImageResource(R.drawable.vip_center_level_2)
+ 3->holder.imgBackground.setImageResource(R.drawable.vip_center_level_3)
+ 4->holder.imgBackground.setImageResource(R.drawable.vip_center_level_4)
+ 5->holder.imgBackground.setImageResource(R.drawable.vip_center_level_5)
+ 6->holder.imgBackground.setImageResource(R.drawable.vip_center_level_6)
+ 7->holder.imgBackground.setImageResource(R.drawable.vip_center_level_7)
+ 8->holder.imgBackground.setImageResource(R.drawable.vip_center_level_8)
+ 9->holder.imgBackground.setImageResource(R.drawable.vip_center_level_9)
+ }
+
+ // 加载网络图片
+ Glide.with(context)
+ .load(data.vipIcon) // data 是图片的 URL
+ .into(holder.imgForeground)
+ }
+
+ inner class BannerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
+ val imgBackground: ImageView = view.findViewById(R.id.img_background)
+ val imgForeground: ImageView = view.findViewById(R.id.img_foreground)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/chwl/app/vip/adapter/VipCenterIdentificationsAdapter.kt b/app/src/main/java/com/chwl/app/vip/adapter/VipCenterIdentificationsAdapter.kt
new file mode 100644
index 000000000..b7b6e145f
--- /dev/null
+++ b/app/src/main/java/com/chwl/app/vip/adapter/VipCenterIdentificationsAdapter.kt
@@ -0,0 +1,50 @@
+package com.chwl.app.vip.adapter
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.chwl.app.R
+import com.chwl.core.vip.bean.VipAuthInfo
+
+class VipCenterIdentificationsAdapter(
+ private val context: Context,
+ private val items: List
+) : RecyclerView.Adapter() {
+ override fun onCreateViewHolder(
+ parent: ViewGroup,
+ viewType: Int
+ ): VipCenterIdentificationsAdapter.ItemViewHolder {
+ val view = LayoutInflater.from(context).inflate(R.layout.vip_center_idnetifications_layout, parent, false)
+ return ItemViewHolder(view)
+ }
+
+ override fun onBindViewHolder(
+ holder: VipCenterIdentificationsAdapter.ItemViewHolder,
+ position: Int
+ ) {
+ val item = items[position]
+
+ // 加载内容图片
+ Glide.with(context)
+ .load(item.authIcon)
+ .into(holder.contentImageView)
+
+ // 设置标题
+ holder.titleTextView.text = item.authName
+ }
+
+ override fun getItemCount(): Int {
+ return items.size
+ }
+
+ inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
+// val backgroundImageView: ImageView = view.findViewById(R.id.background_image)
+ val contentImageView: ImageView = view.findViewById(R.id.item_image)
+ val titleTextView: TextView = view.findViewById(R.id.item_title)
+ }
+}
+
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_back_button.webp b/app/src/main/res/drawable-xhdpi/vip_center_back_button.webp
new file mode 100644
index 000000000..328efd655
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_back_button.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_background.webp b/app/src/main/res/drawable-xhdpi/vip_center_background.webp
new file mode 100644
index 000000000..475c2b7d2
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_background.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_help_button.webp b/app/src/main/res/drawable-xhdpi/vip_center_help_button.webp
new file mode 100644
index 000000000..ea86902ea
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_help_button.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_identification_card.webp b/app/src/main/res/drawable-xhdpi/vip_center_identification_card.webp
new file mode 100644
index 000000000..a2d037232
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_identification_card.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_label_decorate.webp b/app/src/main/res/drawable-xhdpi/vip_center_label_decorate.webp
new file mode 100644
index 000000000..6a6a2a4b2
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_label_decorate.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_1.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_1.webp
new file mode 100644
index 000000000..5334bc328
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_1.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_2.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_2.webp
new file mode 100644
index 000000000..324b15603
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_2.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_3.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_3.webp
new file mode 100644
index 000000000..21c0eb360
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_3.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_4.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_4.webp
new file mode 100644
index 000000000..4b116928b
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_4.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_5.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_5.webp
new file mode 100644
index 000000000..7fca4b647
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_5.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_6.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_6.webp
new file mode 100644
index 000000000..4c2011fc5
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_6.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_7.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_7.webp
new file mode 100644
index 000000000..9c9decd78
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_7.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_8.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_8.webp
new file mode 100644
index 000000000..6669efa1e
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_8.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_level_9.webp b/app/src/main/res/drawable-xhdpi/vip_center_level_9.webp
new file mode 100644
index 000000000..35b92fa06
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_level_9.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_purchase_bg.webp b/app/src/main/res/drawable-xhdpi/vip_center_purchase_bg.webp
new file mode 100644
index 000000000..bd6812b00
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_purchase_bg.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_purchase_button_bg.webp b/app/src/main/res/drawable-xhdpi/vip_center_purchase_button_bg.webp
new file mode 100644
index 000000000..0a6f76699
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_purchase_button_bg.webp differ
diff --git a/app/src/main/res/drawable-xhdpi/vip_center_purchase_coin.webp b/app/src/main/res/drawable-xhdpi/vip_center_purchase_coin.webp
new file mode 100644
index 000000000..f41b19968
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/vip_center_purchase_coin.webp differ
diff --git a/app/src/main/res/layout/activity_vip_center.xml b/app/src/main/res/layout/activity_vip_center.xml
new file mode 100644
index 000000000..743700efb
--- /dev/null
+++ b/app/src/main/res/layout/activity_vip_center.xml
@@ -0,0 +1,255 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/banner_vip_center_custom.xml b/app/src/main/res/layout/banner_vip_center_custom.xml
new file mode 100644
index 000000000..8dffaca2a
--- /dev/null
+++ b/app/src/main/res/layout/banner_vip_center_custom.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/vip_center_idnetifications_layout.xml b/app/src/main/res/layout/vip_center_idnetifications_layout.xml
new file mode 100644
index 000000000..9f3d8ef32
--- /dev/null
+++ b/app/src/main/res/layout/vip_center_idnetifications_layout.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index c61e9e6be..f2a26c063 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -5343,4 +5343,11 @@
%s ساعة
تم تقديم الطلب بنجاح
+ Activate VIP
+ Due on:
+ Identification
+ Exclusive Privileges/n
+ Days
+ Expires
+ Renew
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index dacdb0735..2be7985c9 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -5283,4 +5283,13 @@
和我一起玩遊戲吧~
%s小時
下單成功~
+
+ Activate VIP
+ Due on:
+ Identification
+ Exclusive Privileges/n
+ Days
+ Expires
+ Renew
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index e1f30185f..8f51745bf 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -747,4 +747,7 @@
#002512
#3FDDAC
#0FCA81
+
+ #FFE3AF
+ #633000
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dc722b977..f05f927e5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -5323,6 +5323,14 @@ You cannot join again within 24 hours after leaving
%s Hour
successfully ordered
+ Activate VIP
+ Due on:
+ Identification
+ Exclusive Privileges/n
+ Days
+ Expires
+ Renew
+
diff --git a/app/src/module_labour_union/res/layout/activity_vip_main.xml b/app/src/module_labour_union/res/layout/activity_vip_main.xml
index 8171f94ae..77d1d2ee8 100644
--- a/app/src/module_labour_union/res/layout/activity_vip_main.xml
+++ b/app/src/module_labour_union/res/layout/activity_vip_main.xml
@@ -1,5 +1,6 @@
-