feat:初步完成发红包接口对接

feat:增加服务器时间字段
This commit is contained in:
Max
2023-10-25 15:17:08 +08:00
parent c3dab80e71
commit 6ec57834fd
21 changed files with 852 additions and 64 deletions

View File

@@ -65,6 +65,7 @@ import com.yizhuan.xchat_android_core.im.custom.bean.OpenSignInAttachment;
import com.yizhuan.xchat_android_core.initial.InitialModel;
import com.yizhuan.xchat_android_core.interceptor.NoParamsInterceptor;
import com.yizhuan.xchat_android_core.interceptor.ParamsInterceptor;
import com.yizhuan.xchat_android_core.interceptor.TimeSyncInterceptor;
import com.yizhuan.xchat_android_core.manager.IMMessageManager;
import com.yizhuan.xchat_android_core.manager.IMSystemMsgManager;
import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel;
@@ -407,6 +408,7 @@ public class XChatApplication extends BaseApp {
.setBaseUrl(url)
.addInterceptors(new ParamsInterceptor(httpParams))
.addInterceptors(new NoParamsInterceptor())//注意:拦截器的添加顺序,请求的拦截顺序
.addInterceptors(new TimeSyncInterceptor())
.certificates()
.build();
//单例的model 初始化

View File

@@ -47,6 +47,7 @@ import com.yizhuan.erban.avroom.dialog.RoomOperationDialog
import com.yizhuan.erban.avroom.firstcharge.FirstChargeDialog
import com.yizhuan.erban.avroom.presenter.BaseRoomPresenter
import com.yizhuan.erban.avroom.redpackage.RedPackageSendDialog
import com.yizhuan.erban.avroom.redpackage.send.RedPackageSendDialog2
import com.yizhuan.erban.avroom.room_album.RoomAlbumModel
import com.yizhuan.erban.avroom.view.IBaseRoomView
import com.yizhuan.erban.avroom.widget.BottomView
@@ -162,7 +163,7 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
* 是否開啟禮物值顯示
*/
private var showGiftValue = false
private var redPackageSendDialog: RedPackageSendDialog? = null
private var redPackageSendDialog: RedPackageSendDialog2? = null
private val mOnSoftKeyBoardChangeListener: OnSoftKeyBoardChangeListener =
object : OnSoftKeyBoardChangeListener {
override fun keyBoardShow(height: Int) {
@@ -1289,7 +1290,7 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
override fun onMoreBtnClick() {
val dialog = RoomOperationDialog(mContext)
dialog.setOnActionListener {
redPackageSendDialog = RedPackageSendDialog()
redPackageSendDialog = RedPackageSendDialog2()
redPackageSendDialog?.show(activity)
}
dialog.show()

View File

@@ -529,6 +529,11 @@ public class HomePartyRoomFragment extends BaseRoomFragment<IHomePartyView, Home
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
gameBinding.redPackageWidget.onStop();
}
@Override
public void onDestroy() {

View File

@@ -28,6 +28,7 @@ import com.yizhuan.xchat_android_core.pay.PayModel
import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent
import com.yizhuan.xchat_android_core.redpackage.*
import com.yizhuan.xchat_android_core.user.UserModel
import com.yizhuan.xchat_android_core.utils.LogUtils
import com.yizhuan.xchat_android_core.utils.toIntOrDef
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
import com.yizhuan.xchat_android_library.common.util.DeviceUtil
@@ -219,23 +220,24 @@ class RedPackageSendDialog : BaseDialog<DialogRedPackageSendBinding>(), GridPass
override fun onTextChanged(psw: String) {
val password = passWordFragment?.password?.password ?: ""
if (password.length == 6) {
dialogManager.showProgressDialog(context)
RedPackageModel.sendRedPackage(binding?.editGoldNum?.text.toString(),
binding?.editRedText?.text.toString().ifEmpty { "恭喜發財,大吉大利!" },
binding?.editRedNum?.text.toString(),
AvRoomDataManager.get().mCurrentRoomInfo?.uid.toString(), getRedType(), DESUtils.DESAndBase64(password))
.doOnError {
dialogManager.dismissDialog()
SingleToastUtil.showToast(it.message)
passWordFragment?.password?.clearPassword()
}
.subscribe { _ ->
PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
dialogManager.dismissDialog()
SingleToastUtil.showToast("發送成功")
passWordFragment?.dismissAllowingStateLoss()
dismissAllowingStateLoss()
}
LogUtils.d("onTextChanged() editGoldNum:${binding?.editGoldNum?.text.toString()} NUM:${binding?.editRedNum?.text.toString()}")
// dialogManager.showProgressDialog(context)
// RedPackageModel.sendRedPackage(binding?.editGoldNum?.text.toString(),
// binding?.editRedText?.text.toString().ifEmpty { "恭喜發財,大吉大利!" },
// binding?.editRedNum?.text.toString(),
// AvRoomDataManager.get().mCurrentRoomInfo?.uid.toString(), getRedType(), DESUtils.DESAndBase64(password))
// .doOnError {
// dialogManager.dismissDialog()
// SingleToastUtil.showToast(it.message)
// passWordFragment?.password?.clearPassword()
// }
// .subscribe { _ ->
// PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
// dialogManager.dismissDialog()
// SingleToastUtil.showToast("發送成功")
// passWordFragment?.dismissAllowingStateLoss()
// dismissAllowingStateLoss()
// }
}
}

View File

@@ -9,10 +9,10 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import com.yizhuan.erban.R
import com.yizhuan.xchat_android_core.redpackage.RedPackageNotifyInfo
import com.yizhuan.xchat_android_core.utils.LogUtils
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Predicate
import java.text.SimpleDateFormat
import java.util.TimeZone
import java.util.concurrent.TimeUnit
@@ -52,6 +52,7 @@ class RedPackageWidget : ConstraintLayout {
LayoutInflater.from(context)
.inflate(R.layout.red_package_widget, this, true)
textView = findViewById(R.id.tv_text)
this.setBackgroundResource(R.drawable.red_package_widget_bg)
}
fun loadData(data: RedPackageNotifyInfo?) {

View File

@@ -2,34 +2,60 @@ package com.yizhuan.erban.avroom.redpackage.send
import android.graphics.Color
import androidx.core.view.isVisible
import com.chuhai.utils.ktx.addDisableFilter
import com.chuhai.utils.ktx.getColorById
import com.chuhai.utils.ktx.singleClick
import com.yizhuan.erban.R
import com.yizhuan.erban.base.BaseBindingFragment
import com.yizhuan.erban.databinding.RedPackagePrivateFragmentBinding
import com.yizhuan.erban.pay.password.GiveGoldPassWordFragment
import com.yizhuan.erban.pay.widget.GridPasswordNoFocusView
import com.yizhuan.erban.ui.setting.ModifyPwdActivity
import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil
import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration
import com.yizhuan.xchat_android_core.auth.AuthModel
import com.yizhuan.xchat_android_core.initial.InitialModel
import com.yizhuan.xchat_android_core.manager.AvRoomDataManager
import com.yizhuan.xchat_android_core.pay.PayModel
import com.yizhuan.xchat_android_core.redpackage.RedPackageModel
import com.yizhuan.xchat_android_core.user.UserModel
import com.yizhuan.xchat_android_core.utils.toIntOrDef
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
import com.yizhuan.xchat_android_library.utils.keyboard.KeyboardUtil
import com.yizhuan.xchat_android_library.utils.ResUtil
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
import com.yizhuan.xchat_android_library.utils.codec.DESUtils
import okhttp3.internal.toLongOrDefault
/**
* Created by Max on 2023/10/23 12:14
* Desc:
* Desc: 厅内红包
**/
@ActLayoutRes(R.layout.red_package_private_fragment)
class PrivateRedPackageEditorFragment : BaseBindingFragment<RedPackagePrivateFragmentBinding>() {
private var passWordFragment: GiveGoldPassWordFragment? = null
private var typeAdapter: RedPackageTypeItemAdapter? = null
// 生效时间类型 0 立即生效 1 限时生效
private var timeType = 0
override fun initiate() {
mBinding.etText.addDisableFilter(" ", "\n")
initTypeView()
updateTimeView(true)
}
override fun onSetListener() {
super.onSetListener()
mBinding.tvNow.setOnClickListener {
mBinding.tvNow.singleClick {
updateTimeView(true)
}
mBinding.tvDelay.setOnClickListener {
mBinding.tvDelay.singleClick {
updateTimeView(false)
}
mBinding.tvSend.singleClick {
checkSend()
}
}
private fun initTypeView() {
@@ -41,33 +67,34 @@ class PrivateRedPackageEditorFragment : BaseBindingFragment<RedPackagePrivateFra
val list = ArrayList<RedPackageTypeItemAdapter.ItemData>()
list.add(
RedPackageTypeItemAdapter.ItemData(
"UNLIMITED",
1,
R.string.red_package_type_unlimited_name,
R.string.red_package_type_unlimited_tips
)
)
list.add(
RedPackageTypeItemAdapter.ItemData(
"FOLLOW",
2,
R.string.red_package_type_follow_name,
R.string.red_package_type_follow_tips
)
)
list.add(
RedPackageTypeItemAdapter.ItemData(
"SHARE",
3,
R.string.red_package_type_share_name,
R.string.red_package_type_share_tips
)
)
list.add(
RedPackageTypeItemAdapter.ItemData(
"MSG",
4,
R.string.red_package_type_msg_name,
R.string.red_package_type_msg_tips
)
)
val adapter = RedPackageTypeItemAdapter(list)
typeAdapter = adapter
adapter.setOnItemClickListener { _, view, position ->
adapter.select(position)
updateTypeView(adapter.getSelect()?.type)
@@ -81,15 +108,15 @@ class PrivateRedPackageEditorFragment : BaseBindingFragment<RedPackagePrivateFra
/**
* 更新红包类型对应的视图
*/
private fun updateTypeView(type: String?) {
private fun updateTypeView(type: Int?) {
when (type) {
"UNLIMITED" -> {
1 -> {
mBinding.tvNow.isVisible = true
mBinding.tvDelay.isVisible = true
mBinding.etText.isVisible = false
}
"MSG" -> {
4 -> {
mBinding.tvNow.isVisible = false
mBinding.tvDelay.isVisible = false
mBinding.etText.isVisible = true
@@ -108,15 +135,128 @@ class PrivateRedPackageEditorFragment : BaseBindingFragment<RedPackagePrivateFra
*/
private fun updateTimeView(nowOrDelay: Boolean) {
if (nowOrDelay) {
timeType = 0
mBinding.tvNow.setBackgroundResource(R.drawable.red_package_bg_type_selected)
mBinding.tvDelay.setBackgroundResource(R.drawable.shape_f8f8fa_8)
mBinding.tvNow.setTextColor(mBinding.root.context.getColorById(R.color.color_FF285C))
mBinding.tvDelay.setTextColor(mBinding.root.context.getColorById(R.color.color_767585))
} else {
timeType = 1
mBinding.tvNow.setBackgroundResource(R.drawable.shape_f8f8fa_8)
mBinding.tvDelay.setBackgroundResource(R.drawable.red_package_bg_type_selected)
mBinding.tvNow.setTextColor(mBinding.root.context.getColorById(R.color.color_767585))
mBinding.tvDelay.setTextColor(mBinding.root.context.getColorById(R.color.color_FF285C))
}
}
private fun checkSend() {
val initInfo = InitialModel.get().cacheInitInfo
if (initInfo == null) {
SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_redpackage_redpackagesenddialog_01))
return
}
val typeItem = typeAdapter?.getSelect()
if (typeItem?.type == 4) {
if (mBinding.etText.text.toString().trim().isEmpty()) {
toast(R.string.red_package_msg_empty_tips)
return
}
}
val minNum = initInfo.redEnvelopeConfig.roomRedEnvelopeMinNum
val maxNum = initInfo.redEnvelopeConfig.roomRedEnvelopeMaxNum
val minGold = initInfo.redEnvelopeConfig.roomRedEnvelopeMinAmount
val maxGold = initInfo.redEnvelopeConfig.roomRedEnvelopeMaxAmount
val rate =
if (initInfo.redEnvelopeConfig.exchangeDiamondsRate == 0.0) 0.68 else initInfo.redEnvelopeConfig.exchangeDiamondsRate
val redNum = mBinding?.etNum?.text.toString().toIntOrDef()
if (redNum < minNum || redNum > maxNum) {
SingleToastUtil.showToast("紅包數量不能小於${minNum}或大於${maxNum}!")
return
}
val goldNum = mBinding?.etMoney?.text.toString().toIntOrDef()
if (goldNum % 10 != 0) {
SingleToastUtil.showToast("鉆石數必須為10的倍數!")
return
}
if (goldNum < minGold || goldNum > maxGold) {
SingleToastUtil.showToast("鉆石數量不能小於${minGold}或大於${maxGold}!")
return
}
if (goldNum.toFloat() / redNum * rate < 0.1) {//單個手氣紅包價值不低於0.1水晶
SingleToastUtil.showToast("單個紅包金額過低")
return
}
UserModel.get().cacheLoginUserInfo?.let {
if (!it.isBindPaymentPwd) {
ModifyPwdActivity.start(context, ModifyPwdActivity.PAY_PWD)
return
}
}
GiveGoldPassWordFragment.newInstance(
childFragmentManager,
mBinding?.etMoney?.text.toString()
).apply {
setListener(object : GridPasswordNoFocusView.OnPasswordChangedListener {
override fun onTextChanged(psw: String?) {
val password = passWordFragment?.password?.password ?: ""
if (password.length == 6) {
send(password)
}
}
override fun onInputFinish(psw: String?) {
}
})
passWordFragment = this
}
}
/**
* 密码输入完成
*/
private fun send(password: String) {
dialogManager.showProgressDialog(context)
val kind = typeAdapter?.getSelect()?.type ?: 1
val message = if (kind == 4) {
mBinding.etText.text.trim().toString()
} else {
""
}
val validityType = if (kind == 1) {
timeType
} else {
0
}
RedPackageModel.sendRedPackage(
goldNum = mBinding.etMoney.text.trim().toString().toLongOrDefault(0),
message = message,
num = mBinding.etNum.text.trim().toString().toLongOrDefault(0),
roomUId = AvRoomDataManager.get().mCurrentRoomInfo?.uid.toString(),
type = 1,
kind = kind,
validityType = validityType,
password = DESUtils.DESAndBase64(password)
)
.compose(bindToLifecycle())
.doOnError {
dialogManager.dismissDialog()
SingleToastUtil.showToast(it.message)
passWordFragment?.password?.clearPassword()
}
.subscribe { _ ->
PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
dialogManager.dismissDialog()
SingleToastUtil.showToast("發送成功")
passWordFragment?.dismissAllowingStateLoss()
(parentFragment as? RedPackageSendDialog2)?.dismissAllowingStateLoss()
}
}
override fun onDestroy() {
super.onDestroy()
passWordFragment?.dismissAllowingStateLoss()
passWordFragment = null
}
}

View File

@@ -1,17 +1,139 @@
package com.yizhuan.erban.avroom.redpackage.send
import com.chuhai.utils.ktx.addDisableFilter
import com.chuhai.utils.ktx.setOnInputChangedListener
import com.chuhai.utils.ktx.singleClick
import com.chuhai.utils.ktx.toStringRes
import com.yizhuan.erban.R
import com.yizhuan.erban.base.BaseBindingFragment
import com.yizhuan.erban.databinding.RedPackagePrivateFragmentBinding
import com.yizhuan.erban.databinding.RedPackagePublicFragmentBinding
import com.yizhuan.erban.pay.password.GiveGoldPassWordFragment
import com.yizhuan.erban.pay.widget.GridPasswordNoFocusView
import com.yizhuan.erban.ui.setting.ModifyPwdActivity
import com.yizhuan.xchat_android_core.auth.AuthModel
import com.yizhuan.xchat_android_core.initial.InitialModel
import com.yizhuan.xchat_android_core.initial.bean.InitInfo
import com.yizhuan.xchat_android_core.manager.AvRoomDataManager
import com.yizhuan.xchat_android_core.pay.PayModel
import com.yizhuan.xchat_android_core.redpackage.RedPackageModel
import com.yizhuan.xchat_android_core.user.UserModel
import com.yizhuan.xchat_android_core.utils.toIntOrDef
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
import com.yizhuan.xchat_android_library.utils.codec.DESUtils
import okhttp3.internal.toLongOrDefault
/**
* Created by Max on 2023/10/23 12:14
* Desc:
* Desc:全服红包
**/
@ActLayoutRes(R.layout.red_package_public_fragment)
class PublicRedPackageEditorFragment : BaseBindingFragment<RedPackagePublicFragmentBinding>() {
private var passWordFragment: GiveGoldPassWordFragment? = null
override fun initiate() {
mBinding.etText.addDisableFilter("\n")
mBinding.etText.setOnInputChangedListener {
mBinding.tvTextLength.text =
R.string.red_package_opened_count_format.toStringRes().format(this, 20)
true
}
mBinding.tvSend.singleClick {
checkSend()
}
}
private fun checkSend() {
val initInfo = InitialModel.get().cacheInitInfo ?: InitInfo()
val minNum = initInfo.redEnvelopeConfig.serverRedEnvelopeMinNum
val maxNum = initInfo.redEnvelopeConfig.serverRedEnvelopeMaxNum
val minGold = initInfo.redEnvelopeConfig.serverRedEnvelopeMinAmount
val maxGold = initInfo.redEnvelopeConfig.serverRedEnvelopeMaxAmount
val rate =
if (initInfo.redEnvelopeConfig.exchangeDiamondsRate == 0.0) 0.68 else initInfo.redEnvelopeConfig.exchangeDiamondsRate
val redNum = mBinding?.etNum?.text.toString().toIntOrDef()
if (redNum < minNum || redNum > maxNum) {
SingleToastUtil.showToast("紅包數量不能小於${minNum}或大於${maxNum}!")
return
}
val goldNum = mBinding?.etMoney?.text.toString().toIntOrDef()
if (goldNum % 100 != 0) {
SingleToastUtil.showToast("鉆石數必須為100的倍數!")
return
}
if (goldNum < minGold || goldNum > maxGold) {
SingleToastUtil.showToast("鉆石數量不能小於${minGold}或大於${maxGold}!")
return
}
if (goldNum.toFloat() / redNum * rate < 0.1) {//單個手氣紅包價值不低於0.1水晶
SingleToastUtil.showToast("單個紅包金額過低")
return
}
UserModel.get().cacheLoginUserInfo?.let {
if (!it.isBindPaymentPwd) {
ModifyPwdActivity.start(context, ModifyPwdActivity.PAY_PWD)
return
}
}
GiveGoldPassWordFragment.newInstance(
childFragmentManager,
mBinding?.etMoney?.text.toString()
).apply {
setListener(object : GridPasswordNoFocusView.OnPasswordChangedListener {
override fun onTextChanged(psw: String?) {
val password = passWordFragment?.password?.password ?: ""
if (password.length == 6) {
send(password)
}
}
override fun onInputFinish(psw: String?) {
}
})
passWordFragment = this
}
}
/**
* 密码输入完成
*/
private fun send(password: String) {
dialogManager.showProgressDialog(context)
var message = mBinding.etText.text.trim().toString()
if (message.isEmpty()) {
message = R.string.red_package_msg_def.toStringRes()
}
RedPackageModel.sendRedPackage(
goldNum = mBinding.etMoney.text.trim().toString().toLongOrDefault(0),
message = message,
num = mBinding.etNum.text.trim().toString().toLongOrDefault(0),
roomUId = AvRoomDataManager.get().mCurrentRoomInfo?.uid.toString(),
type = 2,
kind = 0,
validityType = 0,
password = DESUtils.DESAndBase64(password)
)
.compose(bindToLifecycle())
.doOnError {
dialogManager.dismissDialog()
SingleToastUtil.showToast(it.message)
passWordFragment?.password?.clearPassword()
}
.subscribe { _ ->
PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
dialogManager.dismissDialog()
SingleToastUtil.showToast("發送成功")
passWordFragment?.dismissAllowingStateLoss()
(parentFragment as? RedPackageSendDialog2)?.dismissAllowingStateLoss()
}
}
override fun onDestroy() {
super.onDestroy()
passWordFragment?.dismissAllowingStateLoss()
passWordFragment = null
}
}

View File

@@ -4,16 +4,30 @@ package com.yizhuan.erban.avroom.redpackage.send
import android.annotation.SuppressLint
import android.view.Gravity
import android.view.WindowManager
import com.bumptech.glide.manager.Lifecycle
import com.chuhai.utils.ktx.singleClick
import com.chuhai.utils.ktx.toStringRes
import com.yizhuan.erban.R
import com.yizhuan.erban.avroom.redpackage.RedPackageEvent
import com.yizhuan.erban.base.BaseDialog
import com.yizhuan.erban.common.ViewPagerAdapter
import com.yizhuan.erban.databinding.RedPackageSendDialogBinding
import com.yizhuan.erban.ui.pay.ChargeActivity
import com.yizhuan.erban.ui.webview.CommonWebViewActivity
import com.yizhuan.erban.ui.webview.DialogWebViewActivity
import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper
import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator
import com.yizhuan.xchat_android_core.Constants
import com.yizhuan.xchat_android_core.UriProvider
import com.yizhuan.xchat_android_core.initial.InitialModel
import com.yizhuan.xchat_android_core.pay.PayModel
import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent
import com.yizhuan.xchat_android_core.redpackage.*
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
import com.yizhuan.xchat_android_library.common.util.DeviceUtil
import com.yizhuan.xchat_android_library.utils.AppMetaDataUtil
import com.yizhuan.xchat_android_library.utils.ResUtil
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
@@ -35,7 +49,24 @@ class RedPackageSendDialog2 : BaseDialog<RedPackageSendDialogBinding>() {
@SuppressLint("SetTextI18n")
override fun init() {
EventBus.getDefault().register(this)
val tabTitles = arrayListOf(R.string.red_package_room.toStringRes(), R.string.red_package_public.toStringRes())
if (InitialModel.get().cacheInitInfo == null) {
InitialModel.get().init(true)
SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_redpackage_redpackagesenddialog_01))
dismissAllowingStateLoss()
return
}
initView()
initEvent()
PayModel.get().currentWalletInfo?.let {
binding.tvBalance.text = it.diamondNum.toLong().toString()
}
}
private fun initView() {
val tabTitles = arrayListOf(
R.string.red_package_room.toStringRes(),
R.string.red_package_public.toStringRes()
)
val topMagicIndicatorAdapter = TabIndicatorAdapter(context, tabTitles)
topMagicIndicatorAdapter.setOnItemSelectListener {
binding.viewPager.currentItem = it
@@ -54,11 +85,42 @@ class RedPackageSendDialog2 : BaseDialog<RedPackageSendDialogBinding>() {
ViewPagerHelper.bind(binding.tabLayout, binding.viewPager)
}
private fun initEvent() {
binding.ivHelp.singleClick {
DialogWebViewActivity.start(
context,
UriProvider.getRedPacketRule()
)
}
binding.tvBalance.singleClick {
if (AppMetaDataUtil.getChannelID() == Constants.GOOGLE) {
ChargeActivity.start(context)
} else {
CommonWebViewActivity.start(
context, UriProvider.getOfficialPay(
4,
DeviceUtil.getDeviceId(context)
)
)
}
}
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onWalletInfoUpdate(event: UpdateWalletInfoEvent?) {
if (!isViewLoaded) {
return
}
binding.tvBalance.text = PayModel.get().currentWalletInfo?.diamondNum?.toString()
?: "0"
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun handleRedPackageDialog(event: RedPackageEvent?) {
dismissAllowingStateLoss()

View File

@@ -19,7 +19,12 @@ class RedPackageTypeItemAdapter(list: List<ItemData>) :
private var selectPosition = -1
@Keep
data class ItemData(val type: String, val name: Int, val tips: Int)
data class ItemData(
/**
* 红包种类 0 旧版本 1 无门槛红包 2 关注红包 3 分享红包 4 弹幕红包
*/
val type: Int, val name: Int, val tips: Int
)
override fun convert(helper: BaseViewHolder, item: ItemData) {
helper.setText(R.id.tv_name, item.name)

View File

@@ -14,6 +14,7 @@ import java.lang.reflect.ParameterizedType
abstract class BaseDialog<T : ViewBinding> : RxDialogFragment() {
val isViewLoaded: Boolean get() = _binding != null
private var _binding: T? = null
private var onDismissListener: (() -> Unit)? = null
val binding get() = _binding!!

View File

@@ -80,7 +80,6 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
if (BuildConfig.DEBUG) {
binding.titleBar.setOnTitleClickListener {
// RedPackageSendDialog2().show(this)
RedPackageOpenDialog2().show(this)
}
}

View File

@@ -189,6 +189,7 @@
android:gravity="center"
android:hint="@string/red_package_msg_hint"
android:maxLength="10"
android:singleLine="true"
android:textColor="@color/color_322F4D"
android:textColorHint="@color/color_B3B3C3"
android:textSize="16sp"

View File

@@ -130,13 +130,14 @@
android:maxLength="20"
android:paddingHorizontal="10dp"
android:paddingVertical="10dp"
android:text="@string/red_package_msg_def"
android:hint="@string/red_package_msg_def"
android:textColorHint="@color/color_B3B3C3"
android:textColor="@color/color_322F4D"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@id/et_num" />
<TextView
android:id="@+id/tv_text_langth"
android:id="@+id/tv_text_length"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"

View File

@@ -18,8 +18,6 @@
android:id="@+id/iv_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="@drawable/red_package_send_bg"
app:layout_constraintTop_toTopOf="parent" />
@@ -34,9 +32,10 @@
app:layout_constraintTop_toTopOf="@id/iv_top" />
<ImageView
android:id="@+id/iv_help"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginTop="71dp"
android:layout_marginTop="64dp"
android:layout_marginEnd="2dp"
android:scaleType="center"
android:src="@drawable/red_package_ic_help"
@@ -47,7 +46,7 @@
android:id="@+id/tv_balance"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginBottom="10dp"
android:layout_marginBottom="8dp"
android:background="@drawable/red_package_bg_balance"
android:gravity="center"
android:paddingStart="25dp"

View File

@@ -5170,4 +5170,5 @@
<string name="red_package_opened_money_tips">已存入錢包,請到我的收益確認</string>
<string name="red_package_opened_count_format">已領取%s/%s個</string>
<string name="red_package_widget_get">抢红包</string>
<string name="red_package_msg_empty_tips">请输入弹幕内容</string>
</resources>

View File

@@ -0,0 +1,57 @@
package com.yizhuan.xchat_android_core.interceptor
import com.chuhai.utils.AppUtils
import com.chuhai.utils.ServiceTime
import com.yizhuan.xchat_android_core.utils.LogUtils
import com.yizhuan.xchat_android_library.utils.NetworkUtils
import okhttp3.Headers
import okhttp3.Interceptor
import okhttp3.Response
/**
* Created by Max on 2023/10/25 14:17 AM
* Desc:服务器时间同步器
*/
class TimeSyncInterceptor : Interceptor {
private var minResponseTime = Long.MAX_VALUE
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val startTime = System.nanoTime()
val proceed = chain.proceed(request)
val lastTime = System.nanoTime() - startTime
val headers = proceed.headers
calibration(lastTime, headers)
return proceed
}
private fun calibration(responseTime: Long, headers: Headers?) {
if (headers == null) {
return
}
//如果这一次的请求响应时间小于上一次,则更新本地维护的时间
if (responseTime >= minResponseTime) {
return
}
try {
// 网络无法使用时,不能同步时间
if (!NetworkUtils.isNetworkAvailable(AppUtils.getApp())) {
return
}
// 网络响应头包含Date字段世界时间
// 利用Interceptor记录每次请求响应时间如果本次网络操作的时间小于上一次网络操作的时间则获取Date字段转换时区后更新本地
val date = headers.getDate("Date")
LogUtils.d("TimeSyncInterceptor date:$date time:${date?.time}")
date?.let {
//客户端请求过程一般大于比收到响应时间耗时所以没有简单的除2 加上去,而是直接用该时间
ServiceTime.refreshServiceTime(it.time)
minResponseTime = responseTime
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -1,7 +1,6 @@
package com.yizhuan.xchat_android_core.redpackage
import com.yizhuan.xchat_android_core.bean.response.ServiceResult
import com.yizhuan.xchat_android_core.utils.net.handleBeanData
import com.yizhuan.xchat_android_core.utils.net.handleStringData
@@ -20,32 +19,53 @@ object RedPackageModel {
api = RxNet.create(Api::class.java)
}
fun sendRedPackage(goldNum: String, message: String, num: String, roomUId: String, type: Int, password: String): Single<String> {
return api.sendRedPackage(goldNum, message, num, roomUId, type, password)
.io2main()
.handleStringData()
fun sendRedPackage(
goldNum: Long, message: String, num: Long, roomUId: String, type: Int,
kind: Int, validityType: Int, password: String
): Single<String> {
return api.sendRedPackage(
goldNum,
message,
num,
roomUId,
type,
kind,
validityType,
password
)
.io2main()
.handleStringData()
}
fun openRedPackage(redEnvelopeId: String): Single<RedPackageInfo> {
return api.openRedPackage(redEnvelopeId)
.io2main()
.handleBeanData()
.io2main()
.handleBeanData()
}
fun getRedPackage(uid: Long): Observable<RedPackageNotifyInfo> {
return api.getRedPackage(uid)
.io2main()
.handleBeanData()
.toObservable()
.flatMap { Observable.fromIterable(it) }
.map { RedPackageNotifyInfo(it.id, it.type, it.message, it.userVO?.avatar?:"", it.userVO?.nick?:"", it.roomUId, "") }
.io2main()
.handleBeanData()
.toObservable()
.flatMap { Observable.fromIterable(it) }
.map {
RedPackageNotifyInfo(
it.id,
it.type,
it.message,
it.userVO?.avatar ?: "",
it.userVO?.nick ?: "",
it.roomUId,
""
)
}
}
fun setRedPackageSwitch(roomUid: Long):Single<Boolean> {
fun setRedPackageSwitch(roomUid: Long): Single<Boolean> {
return api.setRedPackageSwitch(roomUid)
.io2main()
.handleBeanData()
.io2main()
.handleBeanData()
}
private interface Api {
@@ -57,12 +77,16 @@ object RedPackageModel {
*/
@FormUrlEncoded
@POST("/red-envelope")
fun sendRedPackage(@Field("goldNum") goldNum: String,
@Field("message") message: String,
@Field("num") num: String,
@Field("roomUId") roomUId: String,
@Field("type") type: Int,
@Field("password") password: String): Single<ServiceResult<String>>
fun sendRedPackage(
@Field("goldNum") goldNum: Long,
@Field("message") message: String,
@Field("num") num: Long,
@Field("roomUId") roomUId: String,
@Field("type") type: Int,
@Field("kind") kind: Int,
@Field("validityType") validityType: Int,
@Field("password") password: String
): Single<ServiceResult<String>>
/**
* 开红包

View File

@@ -0,0 +1,25 @@
package com.chuhai.utils
import android.os.SystemClock
/**
* Created by Max on 3/4/21 5:00 PM
* Desc:服务器时间
*/
object ServiceTime {
// 服务器时间与系统开机时间的时差
private var serviceTimeDiff: Long? = null
val time
get() = if (serviceTimeDiff == null) System.currentTimeMillis()
else SystemClock.elapsedRealtime() + serviceTimeDiff!!
/**
* 刷新服务器时间
*/
fun refreshServiceTime(time: Long) {
//serviceTimeDiff = 服务器时间 - 此刻系统启动时间
serviceTimeDiff = time - SystemClock.elapsedRealtime()
}
}

View File

@@ -0,0 +1,42 @@
package com.chuhai.utils
import android.graphics.Outline
import android.view.View
import android.view.ViewOutlineProvider
import kotlin.math.min
/**
* Created by Max on 2/25/21 1:50 PM
* Desc:
*/
class ShapeViewOutlineProvider {
/**
* Created by Max on 2/25/21 1:48 PM
* Desc:圆角
*/
class Round(var corner: Float) : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(
0,
0,
view.width,
view.height,
corner
)
}
}
/**
* Created by Max on 2/25/21 1:48 PM
* Desc:圆形
*/
class Circle : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
val min = min(view.width, view.height)
val left = (view.width - min) / 2
val top = (view.height - min) / 2
outline.setOval(left, top, min, min)
}
}
}

View File

@@ -0,0 +1,106 @@
package com.chuhai.utils.ktx
import android.text.Editable
import android.text.InputFilter
import android.text.InputFilter.LengthFilter
import android.text.Spanned
import android.text.TextWatcher
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import android.widget.EditText
/**
* 设置editText输入监听
* @param onChanged 改变事件
* @return 是否接受此次文本的改变
*/
inline fun EditText.setOnInputChangedListener(
/**
* @param Int当前长度
* @return 是否接受此次文本的改变
*/
crossinline onChanged: (Int).() -> Boolean
) {
this.addTextChangedListener(object : TextWatcher {
var flag = false
override fun afterTextChanged(p0: Editable?) {
if (flag) {
return
}
if (!onChanged(p0?.length ?: 0)) {
flag = true
this@setOnInputChangedListener.setText(
this@setOnInputChangedListener.getTag(
1982329101
) as? String
)
this@setOnInputChangedListener.setSelection(this@setOnInputChangedListener.length())
flag = false
} else {
flag = false
}
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
this@setOnInputChangedListener.setTag(1982329101, p0?.toString())
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
})
}
/**
* 切换密码可见度
*/
fun EditText.switchPasswordVisibility(visibility: Boolean) {
transformationMethod =
if (!visibility) HideReturnsTransformationMethod.getInstance() else PasswordTransformationMethod.getInstance()
}
/**
* 设置输入功能是否启用不启用就相当于TextView
*/
fun EditText.setInputEnabled(isEnabled: Boolean) {
if (isEnabled) {
isFocusable = true
isFocusableInTouchMode = true
isClickable = true
} else {
isFocusable = false
isFocusableInTouchMode = false
isClickable = false
keyListener = null
}
}
/**
* 添加输入长度限制过滤器
*/
fun EditText.addLengthFilter(maxLength: Int) {
val newFilters = filters.copyOf(filters.size + 1)
newFilters[newFilters.size - 1] = LengthFilter(maxLength)
filters = newFilters
}
/**
* 添加禁用文本过滤器
* @param disableText 不允许输入该文本
*/
fun EditText.addDisableFilter(vararg disableText: CharSequence) {
val newFilters = filters.copyOf(filters.size + 1)
newFilters[newFilters.size - 1] = InputFilter { source, p1, p2, p3, p4, p5 ->
disableText.forEach {
if (source.equals(it)) {
return@InputFilter ""
}
}
return@InputFilter null
}
filters = newFilters
}

View File

@@ -0,0 +1,192 @@
package com.chuhai.utils.ktx
import android.graphics.*
import android.os.Build
import android.os.SystemClock
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.Checkable
import android.widget.TextView
import androidx.core.view.ScrollingView
import com.chuhai.utils.ShapeViewOutlineProvider
import com.chuhai.utils.UiUtils
/**
* 是否右-左布局
*/
fun View.isRtl(): Boolean {
return UiUtils.isRtl(this)
}
/**
* 展示or隐藏
*/
fun View.visibleOrGone(isShow: Boolean) {
visibility = if (isShow) {
View.VISIBLE
} else {
View.GONE
}
}
/**
* 展示or隐藏
*/
inline fun View.visibleOrGone(show: View.() -> Boolean = { true }) {
visibility = if (show(this)) {
View.VISIBLE
} else {
View.GONE
}
}
/**
* 展示or不可见
*/
inline fun View.visibleOrInvisible(show: View.() -> Boolean = { true }) {
visibility = if (show(this)) {
View.VISIBLE
} else {
View.INVISIBLE
}
}
/**
* 点击事件
*/
inline fun <T : View> T.singleClick(time: Long = 800, crossinline block: (T) -> Unit) {
setOnClickListener(object : View.OnClickListener {
private var lastClickTime: Long = 0L
override fun onClick(v: View?) {
val currentTimeMillis = SystemClock.elapsedRealtime()
if (currentTimeMillis - lastClickTime > time || this is Checkable) {
lastClickTime = currentTimeMillis
block(this@singleClick)
}
}
})
}
/**
* 点击事件
*/
fun <T : View> T.singleClick(onClickListener: View.OnClickListener, time: Long = 800) {
setOnClickListener(object : View.OnClickListener {
private var lastClickTime: Long = 0L
override fun onClick(v: View?) {
val currentTimeMillis = SystemClock.elapsedRealtime()
if (currentTimeMillis - lastClickTime > time || this is Checkable) {
lastClickTime = currentTimeMillis
onClickListener.onClick(v)
}
}
})
}
/**
* 设置View圆角矩形
*/
fun <T : View> T.roundCorner(corner: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (outlineProvider == null || outlineProvider !is ShapeViewOutlineProvider.Round) {
outlineProvider = ShapeViewOutlineProvider.Round(corner.toFloat())
} else if (outlineProvider != null && outlineProvider is ShapeViewOutlineProvider.Round) {
(outlineProvider as ShapeViewOutlineProvider.Round).corner = corner.toFloat()
}
clipToOutline = true
}
}
/**
* 设置View为圆形
*/
fun <T : View> T.circle() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (outlineProvider == null || outlineProvider !is ShapeViewOutlineProvider.Circle) {
outlineProvider = ShapeViewOutlineProvider.Circle()
}
clipToOutline = true
}
}
fun View.getBitmap(): Bitmap {
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.translate(scrollX.toFloat(), scrollY.toFloat())
draw(canvas)
return bitmap
}
/**
* 设置边距
*/
fun View?.setMargin(start: Int? = null, top: Int? = null, end: Int? = null, bottom: Int? = null) {
(this?.layoutParams as? ViewGroup.MarginLayoutParams)?.apply {
start?.let {
this.marginStart = start
}
top?.let {
this.topMargin = top
}
end?.let {
this.marginEnd = end
}
bottom?.let {
this.bottomMargin = bottom
}
}
}
/**
* 设置内边距
*/
fun View?.setPadding2(start: Int? = null, top: Int? = null, end: Int? = null, bottom: Int? = null) {
if (this == null) return
this.setPadding(
start ?: paddingStart, top ?: paddingTop, end ?: paddingEnd, bottom ?: paddingBottom
)
}
/**
* 描边宽度
*/
fun TextView.strokeWidth(width: Float) {
this.paint?.style = Paint.Style.FILL_AND_STROKE
this.paint?.strokeWidth = width
this.invalidate()
}
/**
* 模拟点击并取消
*/
fun ScrollingView.simulateClickAndCancel() {
val view = this as? View ?: return
val downEvent = MotionEvent.obtain(
System.currentTimeMillis(), System.currentTimeMillis(), MotionEvent.ACTION_DOWN, (view.right - view.left) / 2f, (view.bottom - view.top) / 2f, 0
)
view.dispatchTouchEvent(downEvent)
val cancelEvent = MotionEvent.obtain(
System.currentTimeMillis(), System.currentTimeMillis(), MotionEvent.ACTION_CANCEL, (view.right - view.left) / 2f, (view.bottom - view.top) / 2f, 0
)
view.dispatchTouchEvent(cancelEvent)
}
/**
* 使用灰色滤镜
*/
fun View.applyGrayFilter(isGray: Boolean) {
try {
val paint = Paint()
val colorMatrix = ColorMatrix()
colorMatrix.setSaturation(if (isGray) 0f else 1f)
paint.colorFilter = ColorMatrixColorFilter(colorMatrix)
setLayerType(View.LAYER_TYPE_HARDWARE, paint)
} catch (e: Exception) {
e.printStackTrace()
}
}