diff --git a/app/src/main/java/com/yizhuan/erban/application/XChatApplication.java b/app/src/main/java/com/yizhuan/erban/application/XChatApplication.java index 38ffa7001..255ab7505 100644 --- a/app/src/main/java/com/yizhuan/erban/application/XChatApplication.java +++ b/app/src/main/java/com/yizhuan/erban/application/XChatApplication.java @@ -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 初始化 diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/BaseRoomFragment.kt b/app/src/main/java/com/yizhuan/erban/avroom/fragment/BaseRoomFragment.kt index 49951dc4e..1232071d2 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/fragment/BaseRoomFragment.kt +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/BaseRoomFragment.kt @@ -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?> : * 是否開啟禮物值顯示 */ 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?> : override fun onMoreBtnClick() { val dialog = RoomOperationDialog(mContext) dialog.setOnActionListener { - redPackageSendDialog = RedPackageSendDialog() + redPackageSendDialog = RedPackageSendDialog2() redPackageSendDialog?.show(activity) } dialog.show() diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java index e9a43283c..e80d0732b 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java @@ -529,6 +529,11 @@ public class HomePartyRoomFragment extends BaseRoomFragment(), 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() +// } } } diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/RedPackageWidget.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/RedPackageWidget.kt index a6fffdd76..3491f2b63 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/RedPackageWidget.kt +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/RedPackageWidget.kt @@ -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?) { diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PrivateRedPackageEditorFragment.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PrivateRedPackageEditorFragment.kt index 6197ec904..a2c8944f5 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PrivateRedPackageEditorFragment.kt +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PrivateRedPackageEditorFragment.kt @@ -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() { + + 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() 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 { + 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 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 + } } \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PublicRedPackageEditorFragment.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PublicRedPackageEditorFragment.kt index 12b94ff0f..063da24db 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PublicRedPackageEditorFragment.kt +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PublicRedPackageEditorFragment.kt @@ -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() { + + 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 } } \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageSendDialog2.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageSendDialog2.kt index 9d1c5ee48..4dab83dbd 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageSendDialog2.kt +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageSendDialog2.kt @@ -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() { @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() { 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() diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageTypeItemAdapter.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageTypeItemAdapter.kt index 1d5eb05b1..60531a202 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageTypeItemAdapter.kt +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageTypeItemAdapter.kt @@ -19,7 +19,12 @@ class RedPackageTypeItemAdapter(list: List) : 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) diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseDialog.kt b/app/src/main/java/com/yizhuan/erban/base/BaseDialog.kt index ab8b29fd4..9c0afd7b9 100644 --- a/app/src/main/java/com/yizhuan/erban/base/BaseDialog.kt +++ b/app/src/main/java/com/yizhuan/erban/base/BaseDialog.kt @@ -14,6 +14,7 @@ import java.lang.reflect.ParameterizedType abstract class BaseDialog : RxDialogFragment() { + val isViewLoaded: Boolean get() = _binding != null private var _binding: T? = null private var onDismissListener: (() -> Unit)? = null val binding get() = _binding!! diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.kt b/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.kt index de0c6a8e5..cc3475517 100644 --- a/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.kt +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.kt @@ -80,7 +80,6 @@ class SettingActivity : BaseViewBindingActivity(), View. if (BuildConfig.DEBUG) { binding.titleBar.setOnTitleClickListener { -// RedPackageSendDialog2().show(this) RedPackageOpenDialog2().show(this) } } diff --git a/app/src/main/res/layout/red_package_private_fragment.xml b/app/src/main/res/layout/red_package_private_fragment.xml index a611469f0..707c0cc84 100644 --- a/app/src/main/res/layout/red_package_private_fragment.xml +++ b/app/src/main/res/layout/red_package_private_fragment.xml @@ -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" diff --git a/app/src/main/res/layout/red_package_public_fragment.xml b/app/src/main/res/layout/red_package_public_fragment.xml index 986184bc1..324223a42 100644 --- a/app/src/main/res/layout/red_package_public_fragment.xml +++ b/app/src/main/res/layout/red_package_public_fragment.xml @@ -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" /> @@ -34,9 +32,10 @@ app:layout_constraintTop_toTopOf="@id/iv_top" /> 已存入錢包,請到我的收益確認 已領取%s/%s個 抢红包 + 请输入弹幕内容 \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/interceptor/TimeSyncInterceptor.kt b/core/src/main/java/com/yizhuan/xchat_android_core/interceptor/TimeSyncInterceptor.kt new file mode 100644 index 000000000..668e30526 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/interceptor/TimeSyncInterceptor.kt @@ -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() + } + } +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedPackageModel.kt b/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedPackageModel.kt index bbaba5f67..746274cea 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedPackageModel.kt +++ b/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedPackageModel.kt @@ -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 { - 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 { + return api.sendRedPackage( + goldNum, + message, + num, + roomUId, + type, + kind, + validityType, + password + ) + .io2main() + .handleStringData() } - fun openRedPackage(redEnvelopeId: String): Single { return api.openRedPackage(redEnvelopeId) - .io2main() - .handleBeanData() + .io2main() + .handleBeanData() } fun getRedPackage(uid: Long): Observable { 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 { + fun setRedPackageSwitch(roomUid: Long): Single { 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> + 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> /** * 开红包 diff --git a/library/src/module_utils/java/com/chuhai/utils/ServiceTime.kt b/library/src/module_utils/java/com/chuhai/utils/ServiceTime.kt new file mode 100644 index 000000000..9a77a6816 --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/ServiceTime.kt @@ -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() + } +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/ShapeViewOutlineProvider.kt b/library/src/module_utils/java/com/chuhai/utils/ShapeViewOutlineProvider.kt new file mode 100644 index 000000000..5394bacba --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/ShapeViewOutlineProvider.kt @@ -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) + } + } +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/ktx/EditTextKtx.kt b/library/src/module_utils/java/com/chuhai/utils/ktx/EditTextKtx.kt new file mode 100644 index 000000000..cd01b47fb --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/ktx/EditTextKtx.kt @@ -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 +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/ktx/ViewKtx.kt b/library/src/module_utils/java/com/chuhai/utils/ktx/ViewKtx.kt new file mode 100644 index 000000000..6d2e4e15c --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/ktx/ViewKtx.kt @@ -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.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.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.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.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() + } +} +