feat:完成首页数据交互

This commit is contained in:
max
2024-03-01 20:14:23 +08:00
parent 038aded819
commit 9850069824
29 changed files with 637 additions and 183 deletions

View File

@@ -598,9 +598,19 @@ public class MainActivity extends BaseMvpActivity<IMainView, MainPresenter>
transaction.add(R.id.main_fragment, showFragment, null);
}
transaction.show(showFragment);
if (tempFragment != null) transaction.hide(tempFragment);
if (tempFragment != null) {
transaction.hide(tempFragment);
if (tempFragment instanceof MainTabContentView) {
((MainTabContentView) tempFragment).onVisibleStateChanged(false);
}
}
tempFragment = showFragment;
if (!isDestroyed()) transaction.commitNowAllowingStateLoss();
if (!isDestroyed()) {
transaction.commitNowAllowingStateLoss();
if (tempFragment instanceof MainTabContentView) {
((MainTabContentView) tempFragment).onVisibleStateChanged(true);
}
}
mCurrentTabType = tabType;
//每次点击我的都更新当前用户信息

View File

@@ -0,0 +1,5 @@
package com.chwl.app
interface MainTabContentView {
fun onVisibleStateChanged(showOrHide: Boolean) {}
}

View File

@@ -9,7 +9,7 @@ import java.lang.reflect.ParameterizedType
abstract class BaseViewBindingFragment<T : ViewBinding> : BaseFragment() {
private var _binding: T? = null
protected var _binding: T? = null
val binding get() = _binding!!

View File

@@ -6,11 +6,14 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.chwl.core.utils.extension.toast
import com.chwl.library.net.rxnet.exception.ExceptionHandle
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
open class BaseViewModel : ViewModel() {
private var compositeDisposable: CompositeDisposable? = null
private val _loadingLiveData by lazy { MutableLiveData<Boolean>() }
val loadingLiveData: LiveData<Boolean> = _loadingLiveData
@@ -40,5 +43,22 @@ open class BaseViewModel : ViewModel() {
}
}
private fun getCompositeDisposable(): CompositeDisposable {
var disposable = compositeDisposable
if (disposable == null) {
disposable = CompositeDisposable()
compositeDisposable = disposable
}
return disposable
}
protected fun addDisposable(disposable: Disposable) {
getCompositeDisposable().add(disposable)
}
override fun onCleared() {
super.onCleared()
compositeDisposable?.dispose()
compositeDisposable = null
}
}

View File

@@ -0,0 +1,18 @@
package com.chwl.app.star
import android.animation.Animator
import android.animation.Animator.AnimatorListener
abstract class DefAnimatorListener : AnimatorListener {
override fun onAnimationStart(animation: Animator) {
}
override fun onAnimationEnd(animation: Animator) {
}
override fun onAnimationCancel(animation: Animator) {
}
override fun onAnimationRepeat(animation: Animator) {
}
}

View File

@@ -0,0 +1,71 @@
package com.chwl.app.star
import android.content.Context
import android.os.Bundle
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.chwl.app.R
import com.chwl.app.ui.widget.dialog.BaseDialog
import com.chwl.library.common.util.SPUtils
import com.chwl.library.utils.TimeUtils
class SendGiftTipsDialog(context: Context, val message: String, var goListener: Runnable?) :
BaseDialog(context, R.style.dialog) {
private var checked = false
companion object {
/**
* 是否需要提示
*/
fun isNeedTips(): Boolean {
val time = SPUtils.getLong("star_send_gift_ignore_tips_time", 0)
return !TimeUtils.isSameDay(time, System.currentTimeMillis())
}
/**
* 忽略提示/不在提示(今天)
*/
private fun ignoreTips() {
SPUtils.putLong("star_send_gift_ignore_tips_time", System.currentTimeMillis())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.star_send_gift_dialog)
findViewById<TextView>(R.id.tv_message)?.text = message
findViewById<View>(R.id.tv_cancel)?.setOnClickListener {
dismiss()
}
findViewById<View>(R.id.tv_ok)?.setOnClickListener {
goListener?.run()
dismiss()
}
findViewById<View>(R.id.layout_ignore_today)?.setOnClickListener {
checked = !checked
loadCheckBox()
}
loadCheckBox()
}
private fun loadCheckBox() {
val view = findViewById<ImageView>(R.id.iv_ignore)
if (checked) {
view?.setImageResource(R.drawable.star_send_gift_checkbox_checked)
} else {
view?.setImageDrawable(null)
}
}
override fun dismiss() {
super.dismiss()
if (checked) {
ignoreTips()
}
goListener = null
}
}

View File

@@ -24,6 +24,5 @@ class StarAdapter : BaseQuickAdapter<StarUser, BaseViewHolder>(R.layout.star_ite
imageView.strokeColor = femaleColor
}
imageView.loadAvatar(item?.avatar)
helper.setText(R.id.tv_name, "${helper.absoluteAdapterPosition}\n#${item?.nick}")
}
}

View File

@@ -1,21 +1,35 @@
package com.chwl.app.star
import android.util.Log
import android.animation.Animator
import android.content.res.ColorStateList
import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.chwl.app.MainTabContentView
import com.chwl.app.R
import com.chwl.app.base.BaseViewBindingFragment
import com.chwl.app.databinding.StarFragmentBinding
import com.chwl.app.ui.im.avtivity.NimP2PMessageActivity
import com.chwl.app.ui.pay.ChargeActivity
import com.chwl.app.ui.utils.loadAvatar
import com.chwl.app.ui.utils.loadFromAssets
import com.chwl.app.view.layoutmanager.CenterSnapHelper
import com.chwl.app.view.layoutmanager.CircleLayoutManager
import com.chwl.app.view.layoutmanager.ScrollHelper
import com.chwl.core.gift.bean.GiftInfo
import com.chwl.core.home.bean.StarUser
import com.chwl.core.utils.net.BalanceNotEnoughExeption
import com.chwl.library.utils.ResUtil
import com.example.lib_utils.ktx.getColorById
import com.example.lib_utils.ktx.singleClick
import com.opensource.svgaplayer.SVGADrawable
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.io.File
class StarFragment : BaseViewBindingFragment<StarFragmentBinding>() {
class StarFragment : BaseViewBindingFragment<StarFragmentBinding>(), MainTabContentView {
private val viewModel: StarViewModel by activityViewModels()
@@ -23,39 +37,114 @@ class StarFragment : BaseViewBindingFragment<StarFragmentBinding>() {
private var animFile: File? = null
private var currentUser: StarUser? = null
override fun init() {
initView()
initObserve()
viewModel.refreshList()
}
private fun initView() {
initRecyclerView()
initAnimView()
binding.ivClose.setOnClickListener {
hideUserPanel()
}
binding.ivGift.setOnClickListener {
dialogManager.showProgressDialog(context)
viewModel.getGiftInfo()
}
binding.ivRefresh.singleClick {
viewModel.refresh()
dialogManager.showProgressDialog(context)
viewModel.refreshList()
}
binding.ivFollow.singleClick {
currentUser?.let {
dialogManager.showProgressDialog(context)
viewModel.follow(it)
}
}
binding.ivChat.singleClick {
currentUser?.uid?.let {
NimP2PMessageActivity.start(context, it.toString())
}
}
}
private fun initObserve() {
viewModel.starUserLiveData.observe(this) {
dialogManager.dismissDialog()
if (adapter.data.isNotEmpty() && it.isNullOrEmpty()) {
return@observe
}
adapter.setNewData(it)
}
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.giftInfoFlow.collectLatest {
val user = currentUser ?: return@collectLatest
val gift = it.data
if (it.isSuccess && gift != null) {
if (showSendGiftDialog(gift, user)) {
dialogManager.dismissDialog()
}
} else {
dialogManager.dismissDialog()
if (it.code == BalanceNotEnoughExeption.code) {
showBalanceNotEnoughDialog()
} else {
it.message?.let { msg ->
toast(msg)
}
}
}
}
}
}
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.sendGiftFlow.collectLatest {
dialogManager.dismissDialog()
if (it.isSuccess) {
toast(R.string.decoration_helper_decorationdialoghelper_010)
currentUser?.uid?.let { uid ->
NimP2PMessageActivity.start(context, uid.toString())
}
} else {
if (it.code == BalanceNotEnoughExeption.code) {
showBalanceNotEnoughDialog()
} else {
it.message?.let { msg ->
toast(msg)
}
}
}
}
}
}
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.followFlow.collectLatest { result ->
dialogManager.dismissDialog()
if (result.isSuccess) {
if (currentUser == result.data) {
currentUser?.let {
loadUserFollowState(it)
}
}
} else if (result.message != null) {
toast(result.message)
}
}
}
}
}
private fun initRecyclerView() {
@@ -70,11 +159,10 @@ class StarFragment : BaseViewBindingFragment<StarFragmentBinding>() {
val width = binding.recyclerView.width
layoutManager.radius = (width * 0.6).toInt()
layoutManager.angleInterval = 20
layoutManager.distanceToBottom = (width * 0.293f).toInt()
layoutManager.distanceToBottom = (width * 0.3f).toInt()
}
binding.recyclerView.layoutManager = layoutManager
adapter.setOnItemClickListener { adapter, view, position ->
toast("$position")
ScrollHelper.smoothScrollToTargetView(binding.recyclerView, view)
(adapter.getItem(position) as? StarUser)?.let {
showUserPanel(it)
@@ -96,33 +184,160 @@ class StarFragment : BaseViewBindingFragment<StarFragmentBinding>() {
}
private fun showUserPanel(user: StarUser) {
binding.recyclerView.disableTouchMove()
binding.recyclerView.pause()
binding.animView.stopPlay()
binding.animView.isVisible = false
binding.layoutTarget.isVisible = true
binding.layoutTargetInfo.isVisible = true
if ((binding.ivGift.drawable as? SVGADrawable) == null) {
binding.ivGift.loadFromAssets("svga/home_star_gift.svga")
currentUser = user
loadUserPanelLeft(user)
loadUserPanelRight(user)
binding.layoutUserPanelRight.translationX =
binding.layoutUserPanelRight.width.toFloat()
binding.layoutUserPanelLeft.alpha = 0f
binding.layoutUserPanelLeft.translationX = binding.layoutUserPanelLeft.width * -0.1f
binding.layoutUserPanelRight.isVisible = true
binding.layoutUserPanelLeft.isVisible = true
switchGiftAnimState(true)
binding.layoutUserPanelRight.animate().translationX(0f)
.setListener(object : DefAnimatorListener() {}).start()
binding.animView.animate().translationX(-binding.animView.width.toFloat())
.scaleX(0f).scaleY(0f).alpha(0f).setListener(object : DefAnimatorListener() {
override fun onAnimationEnd(p0: Animator) {
switchStarAnimState(false)
binding.ivRefresh.isVisible = false
binding.animView.isVisible = false
}
}).start()
binding.layoutUserPanelLeft.animate().translationX(0f).alpha(1f)
.setListener(object : DefAnimatorListener() {}).start()
}
private fun loadUserPanelRight(user: StarUser) {
binding.ivUserAvatar.loadAvatar(user.avatar)
if (user.gender == 1) {
binding.ivUserAvatar.strokeColor =
ColorStateList.valueOf(binding.ivUserAvatar.context.getColorById(R.color.color_57CDFF))
} else {
binding.ivGift.startAnimation()
binding.ivUserAvatar.strokeColor =
ColorStateList.valueOf(binding.ivUserAvatar.context.getColorById(R.color.color_D667FF))
}
}
private fun loadUserPanelLeft(user: StarUser) {
binding.tvUserName.text = user.nick
binding.tvUserDesc.text = user.userDesc
loadUserFollowState(user)
}
private fun loadUserFollowState(user: StarUser) {
if (user.hasLike == true) {
binding.ivFollow.setImageResource(R.drawable.star_ic_followed)
} else {
binding.ivFollow.setImageResource(R.drawable.star_ic_unfollowed)
}
}
private fun hideUserPanel() {
binding.ivGift.pauseAnimation()
binding.recyclerView.enableTouchMove()
binding.recyclerView.start()
currentUser = null
binding.ivRefresh.isVisible = true
binding.animView.isVisible = true
animFile?.let {
binding.animView.startPlay(it)
switchStarAnimState(true)
binding.animView.animate().alpha(1f).translationX(0f).scaleX(1f).scaleY(1f)
.setListener(object : DefAnimatorListener() {}).start()
binding.layoutUserPanelRight.animate()
.translationX(binding.layoutUserPanelRight.width.toFloat())
.setListener(object : DefAnimatorListener() {
override fun onAnimationEnd(p0: Animator) {
switchGiftAnimState(false)
binding.layoutUserPanelRight.isVisible = false
}
}).start()
binding.layoutUserPanelLeft.animate()
.translationX(binding.layoutUserPanelLeft.width * -0.1f)
.alpha(0f).setListener(object : DefAnimatorListener() {
override fun onAnimationEnd(p0: Animator) {
binding.layoutUserPanelLeft.isVisible = false
}
}).start()
}
private fun showSendGiftDialog(gift: GiftInfo, user: StarUser): Boolean {
val next = {
dialogManager.showProgressDialog(context)
viewModel.sendGift(user.uid ?: 0)
}
if (SendGiftTipsDialog.isNeedTips()) {
val message = "确认赠送 ${gift.giftName} (${gift.goldPrice})\n${user.nick} 吗?"
SendGiftTipsDialog(requireContext(), message) {
next.invoke()
}.show()
return true
} else {
next.invoke()
return false
}
binding.layoutTarget.isVisible = false
binding.layoutTargetInfo.isVisible = false
}
private fun playStarAnim() {
private fun showBalanceNotEnoughDialog() {
dialogManager.showOkCancelDialog(
"钻石余额不足",
ResUtil.getString(R.string.treasure_to_charge)
) {
ChargeActivity.start(context)
}
}
private fun pauseStarAnim() {
private fun switchStarAnimState(play: Boolean) {
if (play) {
animFile?.let {
binding.animView.startPlay(it)
}
} else {
binding.animView.stopPlay()
}
}
private fun switchGiftAnimState(play: Boolean) {
if (play) {
if ((binding.ivGift.drawable as? SVGADrawable) == null) {
binding.ivGift.loadFromAssets("svga/home_star_gift.svga")
} else {
binding.ivGift.startAnimation()
}
} else {
binding.ivGift.pauseAnimation()
}
}
override fun onStart() {
super.onStart()
onVisibleStateChanged(true)
}
override fun onStop() {
super.onStop()
onVisibleStateChanged(false)
}
override fun onVisibleStateChanged(showOrHide: Boolean) {
if (_binding == null) {
return
}
if (showOrHide) {
if (binding.ivGift.isVisible) {
switchGiftAnimState(true)
}
if (binding.animView.isVisible) {
switchStarAnimState(true)
}
if (!binding.layoutUserPanelRight.isVisible) {
binding.recyclerView.start()
}
} else {
binding.recyclerView.pause()
switchStarAnimState(false)
switchGiftAnimState(false)
}
}
}

View File

@@ -2,32 +2,53 @@ package com.chwl.app.star
import android.content.Context
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.chwl.app.base.BaseViewModel
import com.chwl.core.bean.response.BeanResult
import com.chwl.core.gift.GiftModel
import com.chwl.core.gift.bean.GiftInfo
import com.chwl.core.home.bean.StarUser
import com.chwl.core.home.model.HomeModel
import com.chwl.core.praise.PraiseModel
import com.chwl.core.utils.extension.toast
import com.chwl.library.common.file.FileHelper
import com.example.lib_utils.AppUtils
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import java.io.File
class StarViewModel : BaseViewModel() {
private var starUserPage = 1
private var starUserListPage = 1
val starUserLiveData = MutableLiveData<List<StarUser>>(listOf(StarUser()))
val starUserLiveData = MutableLiveData<List<StarUser>>(listOf())
fun refresh() {
getStarUser(starUserPage)
}
val followFlow = MutableSharedFlow<BeanResult<StarUser>>()
private fun getStarUser(pageNum: Int) {
val giftInfoFlow = MutableSharedFlow<BeanResult<GiftInfo>>()
val sendGiftFlow = MutableSharedFlow<BeanResult<Any>>()
fun refreshList() {
safeLaunch(
onError = {
starUserLiveData.value = emptyList()
it.message.toast()
},
block = {
val result = HomeModel.getStarUserList(pageNum, 20)
starUserLiveData.value = result ?: emptyList()
val pageSize = 20
val result = HomeModel.getStarUserList(starUserListPage, pageSize)
if (!result.isNullOrEmpty()) {
if (result.size < pageSize) {
starUserListPage = 1
} else {
starUserListPage++
}
starUserLiveData.value = result ?: emptyList()
} else {
starUserListPage = 1
starUserLiveData.value = emptyList()
}
}
)
}
@@ -57,4 +78,44 @@ class StarViewModel : BaseViewModel() {
}
return dir
}
fun follow(starUser: StarUser) {
val like = !(starUser.hasLike ?: false)
addDisposable(
PraiseModel.get().praise(starUser.uid ?: 0, !(starUser.hasLike ?: false)).subscribe({
viewModelScope.launch {
starUser.hasLike = like
followFlow.emit(BeanResult.success(starUser))
}
}, {
viewModelScope.launch {
followFlow.emit(BeanResult.failed(it))
}
})
)
}
fun getGiftInfo() {
addDisposable(GiftModel.get().specialGift.subscribe({
viewModelScope.launch {
giftInfoFlow.emit(BeanResult.success(it))
}
}, {
viewModelScope.launch {
giftInfoFlow.emit(BeanResult.failed(it))
}
}))
}
fun sendGift(uid: Long) {
addDisposable(GiftModel.get().sendSpecialGift(uid).subscribe({
viewModelScope.launch {
sendGiftFlow.emit(BeanResult.success(it))
}
}, {
viewModelScope.launch {
sendGiftFlow.emit(BeanResult.failed(it))
}
}))
}
}

View File

@@ -17,6 +17,9 @@ import com.chwl.app.R;
public class AutoPlayRecyclerView extends RecyclerView {
private AutoPlaySnapHelper autoPlaySnapHelper;
public boolean autoPlayEnabled = true;
public boolean touchMoveEnabled = true;
public AutoPlayRecyclerView(Context context) {
this(context, null);
}
@@ -37,6 +40,9 @@ public class AutoPlayRecyclerView extends RecyclerView {
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_MOVE && !touchMoveEnabled) {
return false;
}
boolean result = super.dispatchTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
@@ -45,18 +51,32 @@ public class AutoPlayRecyclerView extends RecyclerView {
}
break;
case MotionEvent.ACTION_UP:
if (autoPlaySnapHelper != null) {
if (autoPlaySnapHelper != null && autoPlayEnabled) {
autoPlaySnapHelper.start();
}
}
return result;
}
public void disableTouchMove() {
touchMoveEnabled = false;
}
public void enableTouchMove() {
touchMoveEnabled = true;
}
public boolean isAutoPlayEnabled() {
return autoPlayEnabled;
}
public void start() {
autoPlayEnabled = true;
autoPlaySnapHelper.start();
}
public void pause() {
autoPlayEnabled = false;
autoPlaySnapHelper.pause();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="@dimen/dp_1"
android:color="#9D9FA3"/>
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#718CFF" />
</shape>

View File

@@ -8,8 +8,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/shape_white_corner_8dp"
tools:background="@color/black_transparent_10"
android:orientation="vertical">
android:orientation="vertical"
tools:background="@color/black_transparent_10">
<View
android:layout_width="0dp"
@@ -17,31 +17,31 @@
<TextView
android:id="@+id/tv_title"
tools:visibility="visible"
android:textSize="@dimen/text_size_18"
android:textColor="@color/color_1F1B4F"
android:textStyle="bold"
tools:text="@string/layout_layout_common_ok_cancel_dialog_01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginStart="39dp"
android:layout_marginEnd="39dp"
android:maxLines="2"
android:layout_marginBottom="@dimen/dp_14"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:maxLines="2"
android:textColor="@color/color_1F1B4F"
android:textSize="@dimen/text_size_18"
android:textStyle="bold"
tools:text="@string/layout_layout_common_ok_cancel_dialog_01"
tools:visibility="visible" />
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginStart="39dp"
android:layout_marginEnd="39dp"
android:layout_marginBottom="@dimen/dp_32"
android:layout_weight="1"
android:gravity="center_horizontal"
android:textColor="@color/color_1F1B4F"
android:textSize="@dimen/text_size_15"
android:layout_marginBottom="@dimen/dp_32"
android:gravity="center_horizontal"
tools:text="@string/layout_layout_common_ok_cancel_dialog_02" />
<include

View File

@@ -49,7 +49,7 @@
app:layout_constraintTop_toTopOf="@id/recyclerView" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_target_info"
android:id="@+id/layout_user_panel_left"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_10"
@@ -81,7 +81,7 @@
android:layout_marginTop="@dimen/dp_10"
android:background="@drawable/star_bg_btn"
android:scaleType="centerInside"
android:src="@drawable/star_ic_follow"
android:src="@drawable/star_ic_unfollowed"
app:layout_constraintDimensionRatio="72:48"
app:layout_constraintEnd_toStartOf="@id/iv_chat"
app:layout_constraintStart_toStartOf="parent"
@@ -118,7 +118,7 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_target"
android:id="@+id/layout_user_panel_right"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/star_bg_target"
@@ -152,7 +152,7 @@
app:layout_constraintGuide_percent="0.19" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/iv_user"
android:id="@+id/iv_user_avatar"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="1dp"

View File

@@ -14,12 +14,4 @@
app:strokeColor="#FFD667FF"
app:strokeWidth="@dimen/dp_2" />
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="-"
android:textColor="@color/black"
android:textSize="16sp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,83 @@
<?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="@dimen/dp_319"
android:background="@drawable/shape_white_20dp_round"
android:layout_height="wrap_content"
android:layout_gravity="center">
<TextView
android:id="@+id/tv_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_50"
android:layout_marginTop="@dimen/dp_46"
android:gravity="center_horizontal"
android:minHeight="@dimen/dp_40"
android:textColor="#1F1B4F"
android:textSize="@dimen/dp_16"
app:layout_constraintTop_toTopOf="parent"
tools:text="Message" />
<TextView
android:id="@+id/tv_cancel"
android:layout_width="@dimen/dp_124"
android:layout_height="@dimen/dp_42"
android:layout_marginTop="@dimen/dp_24"
android:layout_marginEnd="@dimen/dp_15"
android:background="@drawable/base_shape_negative_26dp"
android:gravity="center"
android:text="@string/cancel"
android:textColor="@color/base_color_negative_text"
app:layout_constraintEnd_toStartOf="@id/tv_ok"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_message" />
<TextView
android:id="@+id/tv_ok"
android:layout_width="@dimen/dp_124"
android:layout_height="@dimen/dp_42"
android:background="@drawable/base_shape_positive_26dp"
android:gravity="center"
android:text="@string/login_fragment_adduserinfofragment_04"
android:textColor="@color/base_color_positive_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_cancel"
app:layout_constraintTop_toTopOf="@id/tv_cancel" />
<LinearLayout
android:id="@+id/layout_ignore_today"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_11"
android:layout_marginBottom="@dimen/dp_10"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_10"
android:paddingVertical="@dimen/dp_5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_cancel">
<ImageView
android:id="@+id/iv_ignore"
android:layout_width="@dimen/dp_12"
android:layout_height="@dimen/dp_12"
android:background="@drawable/star_send_gift_checkbox_bg"
android:padding="@dimen/dp_2"
android:src="@drawable/star_send_gift_checkbox_checked" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_8"
android:text="今日不再提示"
android:textColor="#9D9FA3"
android:textSize="@dimen/dp_12" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -60,6 +60,7 @@ import com.chwl.library.common.util.SPUtils;
import com.chwl.library.net.rxnet.RxNet;
import com.chwl.library.utils.ListUtils;
import com.chwl.library.utils.SingleToastUtil;
import com.netease.nimlib.sdk.msg.model.IMMessage;
import org.greenrobot.eventbus.EventBus;
@@ -69,6 +70,7 @@ import java.util.List;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
@@ -513,46 +515,6 @@ public class GiftModel extends BaseModel implements IGiftModel {
isKnap ? GiftSource.BACKPACK : GiftSource.COMMON, msg, isKnap, false, null);
}
/**
* 在公聊大厅界面送礼物给某个人
* 后台规定要传 type 为 5方便后端进行数据的统计
*
* @param giftId -
* @param targetUid -
* @param giftNum -
* @return -
*/
@Override
public Single<ServiceResult<GiftMultiReceiverInfo>> sendPersonalGiftInPublicChatHall(final int giftId,
final String targetUid, final int giftNum,
String msg, boolean isKnap) {
List<Long> targetUids = new ArrayList<>();
targetUids.add(Long.parseLong(targetUid));
return sendGift(giftId, giftNum, targetUids, GiftSendType.TYPE_PUBLIC_CHAT_HALL,
isKnap ? GiftSource.BACKPACK : GiftSource.COMMON, msg, isKnap, false, null);
}
/**
* 能不能送该礼物
*
* @param giftInfo -
* @return -
*/
@Override
public boolean canUseNobleGiftOrNot(GiftInfo giftInfo) {
if (giftInfo == null) return false;
SimpleVipInfo simpleVipInfo = giftInfo.getGiftVipInfo();
if (simpleVipInfo == null || simpleVipInfo.getVipLevel() == 0) return true;
UserInfo userInfo = UserModel.get().getCacheLoginUserInfo();
if (userInfo == null) {
return false;
}
UserVipInfo userVipInfo = userInfo.getUserVipInfoVO();
int level = userVipInfo == null ? 0 : userVipInfo.getVipLevel();
return level >= simpleVipInfo.getVipLevel();
}
@Override
public void addNewGift(GiftInfo giftInfo) {
//兼容旧版写的,已经不需要了
@@ -614,14 +576,6 @@ public class GiftModel extends BaseModel implements IGiftModel {
return null;
}
@Override
public Single<ServiceResult<GiftMultiReceiverInfo>> sendTeamGift(int giftId, String targetUid, int giftNum, String msg, boolean isKnap, String chatSessionId) {
List<Long> targetUids = new ArrayList<>();
targetUids.add(Long.parseLong(targetUid));
return sendGift(giftId, giftNum, targetUids, GiftSendType.TYPE_TEAM,
isKnap ? GiftSource.BACKPACK : GiftSource.COMMON, msg, isKnap, false, chatSessionId);
}
@Override
public Single<ServiceResult<GiftMultiReceiverInfo>> sendFansTeamGift(int giftId, String targetUid) {
return api.sendJoinFansGift(AuthModel.get().getCurrentUid(),
@@ -695,26 +649,18 @@ public class GiftModel extends BaseModel implements IGiftModel {
countDownTimer.cancel();
}
}
/**
* 获取免费礼物数据
*
* @return
*/
@Override
public GiftFreeInfo getFreeGiftInfo() {
if (giftFreeInfo != null) {
return giftFreeInfo;
} else {
return null;
}
public Single<GiftInfo> getSpecialGift() {
return api.getSpecialGift().compose(RxHelper.handleBeanData2())
.compose(RxHelper.handleSchedulers());
}
@Override
public Single<List<LuckyBagNoticeInfo>> getLuckyGiftMsgList() {
return api.getLuckyGiftMsgList()
.compose(RxHelper.handleBeanData())
.compose(RxHelper.handleSchAndExce());
public Single<Object> sendSpecialGift(long uid) {
return api.sendSpecialGift(uid).compose(RxHelper.handleBeanData2())
.compose(RxHelper.handleSchedulers()).flatMap((Function<GiftMultiReceiverInfo, SingleSource<IMMessage>>) giftMultiReceiverInfo -> {
return GiftToolbox.sendGiftPrivateChatMessage(giftMultiReceiverInfo);
});
}
private interface Api {
@@ -785,13 +731,23 @@ public class GiftModel extends BaseModel implements IGiftModel {
Single<ServiceResult<GiftFreeInfo>> getFreeGift();
/**
* 福袋最近20条全服记录
* 特殊礼物信息
*
* @return
*/
@GET("/luckybag/getBannerList")
Single<ServiceResult<List<LuckyBagNoticeInfo>>> getLuckyGiftMsgList();
@GET("special/gift/get")
Single<ServiceResult<GiftInfo>> getSpecialGift();
/**
* 特殊-送礼物
*
* @return
*/
@POST("special/gift/send")
@FormUrlEncoded
Single<ServiceResult<GiftMultiReceiverInfo>> sendSpecialGift(
@Field("targetId") long uid);
}
private static class UiHandler extends Handler {

View File

@@ -132,28 +132,6 @@ public interface IGiftModel {
String msg,
boolean isKnap);
/**
* 在公聊大厅界面送礼物给某个人
*
* @param giftId -
* @param targetUid -
* @param giftNum -
* @return -
*/
Single<ServiceResult<GiftMultiReceiverInfo>> sendPersonalGiftInPublicChatHall(final int giftId,
final String targetUid,
final int giftNum,
String msg,
boolean isKnap);
/**
* 判断是否能用贵族礼物
*
* @param giftInfo
* @return
*/
boolean canUseNobleGiftOrNot(GiftInfo giftInfo);
/**
* 往内存的缓存中添加新的礼物数据
*
@@ -177,19 +155,6 @@ public interface IGiftModel {
*/
GiftInfo findGiftInfoByIdInKnapList(int giftId);
/**
* 在群聊界面送礼物
*
* @param giftId -
* @param targetUid -
* @param giftNum -
* @return -
*/
Single<ServiceResult<GiftMultiReceiverInfo>> sendTeamGift(int giftId,
String targetUid,
int giftNum,
String msg,
boolean isKnap, String chatSessionId);
/**
* 开通粉丝团送礼物
@@ -211,18 +176,14 @@ public interface IGiftModel {
*/
public void cancelCountDownTimer();
/**
* 从内存里取出免费礼物
*
* @return
*/
GiftFreeInfo getFreeGiftInfo();
/**
* 福袋最近20条全服记录
*
* @return -
* 获取特殊礼物
*/
Single<List<LuckyBagNoticeInfo>> getLuckyGiftMsgList( );
Single<GiftInfo> getSpecialGift();
/**
* 发送特殊礼物
*/
Single<Object> sendSpecialGift(long uid);
}

View File

@@ -7,7 +7,7 @@ import java.io.Serializable
data class StarUser(
val avatar: String? = null,
val gender: Int? = null,
val hasLike: Boolean? = null,
var hasLike: Boolean? = null,
val nick: String? = null,
val uid: Long? = null,
val userDesc: String? = null,

View File

@@ -8,12 +8,6 @@ import com.chwl.core.community.CommunityConstant
import com.chwl.core.community.bean.UnReadCountInfo
import com.chwl.core.home.bean.*
import com.chwl.core.room.bean.AnchorInfo
import com.chwl.core.room.bean.HomeLiveTopInfo
import com.chwl.core.room.bean.MeCenterInfo
import com.chwl.core.room.bean.SingleRoomSortInfo
import com.chwl.core.room.game.bean.GameInfo
import com.chwl.core.user.bean.DiamondGiveHistoryInfo
import com.chwl.core.user.bean.SearchUserInfo
import com.chwl.core.user.bean.UserInfo
import com.chwl.core.utils.net.RxHelper
import com.chwl.core.utils.net.launchRequest
@@ -328,7 +322,6 @@ object HomeModel : BaseModel() {
@Query("pageNum") pageNum: Int,
@Query("pageSize") pageSize: Int
): ServiceResult<List<StarUser>>
}
}

View File

@@ -61,6 +61,29 @@ public class RxHelper {
}
/**
* 这里简单对接口脱掉外层,不适合成功情况下没有data字段的接口使用
*
* @param <T>
* @return
*/
public static <T> SingleTransformer<ServiceResult<T>, T> handleBeanData2() {
return upstream -> upstream
.flatMap(result -> {
if (result.isSuccess()) {
if (result.getData() != null) {
return Single.just(result.getData());
} else {
Logger.e(ERROR_TIPS);
return Single.error(new Throwable(ERROR_TIPS));
}
} else {
return Single.error(new ServerException(getValidMessage(result), result.getCode()));
}
});
}
public interface NullHandle<T> {
T createT();
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="#70E9FF" android:centerColor="#AE87FF" android:endColor="#FF5CE1"/>
<corners android:radius="26dp" />
</shape>

View File

@@ -11,4 +11,7 @@
<!--负面按钮-文本色-->
<color name="base_color_negative_text">#FFFFFF</color>
<!--负面按钮-背景色-->
<color name="base_color_positive_bg">#D2D4D6</color>
</resources>