From 5ef9be75d2ed06664909b2f305e540acff93ea96 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 26 Oct 2023 20:17:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=88=9D=E6=AD=A5=E6=90=AD=E5=BB=BA?= =?UTF-8?q?=E6=96=B0=E6=88=BF=E9=97=B4=E6=A1=86=E6=9E=B6=20feat:=E5=88=9D?= =?UTF-8?q?=E6=AD=A5=E6=90=AD=E5=BB=BA=E7=BA=A2=E5=8C=85=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=99=A8=E4=B8=8E=E7=BB=84=E4=BB=B6=E7=AD=89=EF=BC=88=E6=9C=AA?= =?UTF-8?q?=E5=AE=8C=E6=88=90=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../erban/avroom/activity/AVRoomActivity.java | 52 +++++--- .../erban/avroom/core/AudioRoomContext.kt | 19 +++ .../erban/avroom/fragment/BaseRoomFragment.kt | 37 +++++- .../fragment/HomePartyRoomFragment.java | 10 +- .../avroom/presenter/AvRoomPresenter.java | 4 + .../avroom/redpackage/RedPackageHandler.kt | 90 ++++++++++++++ .../avroom/redpackage/RedPackageWidget.kt | 98 ++++++++++++++-- .../com/yizhuan/erban/base/BaseActivity.java | 3 +- .../erban/ui/setting/SettingActivity.kt | 27 ++++- .../manager/IMNetEaseManager.java | 6 + .../im/custom/bean/CustomAttachment.java | 1 + .../im/custom/bean/RedPackageAttachment.java | 2 +- .../manager/AvRoomDataManager.java | 5 + .../redpackage/RedEnvelopeVO.kt | 44 ++++--- .../redpackage/RedPackageModel.kt | 51 ++++++-- .../redpackage/RedPackageNotifyInfo.kt | 78 +++++++----- .../room/core/RoomDataService.kt | 10 ++ .../support/room/RoomAbility.kt | 98 ++++++++++++++++ .../support/room/RoomContext.kt | 111 ++++++++++++++++++ .../support/room/RoomHandler.kt | 8 ++ .../support/room/RoomService.kt | 10 ++ .../support/room/RoomView.kt | 23 ++++ .../support/room/RoomWidget.kt | 20 ++++ .../lifecycle/RoomFullLifecycleObserver.kt | 34 ++++++ .../support/room/lifecycle/RoomLifecycle.kt | 35 ++++++ .../room/lifecycle/RoomLifecycleObserver.kt | 18 +++ .../room/lifecycle/RoomLifecycleOwner.kt | 9 ++ .../room/lifecycle/RoomLifecycleRegistry.kt | 62 ++++++++++ .../lifecycle/rx/RoomRxLifecycleEvent.java | 11 ++ .../java/com/chuhai/utils/ICleared.kt | 14 +++ .../com/chuhai/utils/log/AndroidLogPrinter.kt | 13 ++ .../java/com/chuhai/utils/log/ILog.kt | 61 ++++++++++ .../java/com/chuhai/utils/log/LogPrinter.kt | 14 +++ .../java/com/chuhai/utils/log/LogUtil.kt | 101 ++++++++++++++++ 34 files changed, 1086 insertions(+), 93 deletions(-) create mode 100644 app/src/main/java/com/yizhuan/erban/avroom/core/AudioRoomContext.kt create mode 100644 app/src/main/java/com/yizhuan/erban/avroom/redpackage/RedPackageHandler.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/room/core/RoomDataService.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomAbility.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomContext.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomHandler.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomService.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomView.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomWidget.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomFullLifecycleObserver.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycle.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleObserver.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleOwner.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleRegistry.kt create mode 100644 core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/rx/RoomRxLifecycleEvent.java create mode 100644 library/src/module_utils/java/com/chuhai/utils/ICleared.kt create mode 100644 library/src/module_utils/java/com/chuhai/utils/log/AndroidLogPrinter.kt create mode 100644 library/src/module_utils/java/com/chuhai/utils/log/ILog.kt create mode 100644 library/src/module_utils/java/com/chuhai/utils/log/LogPrinter.kt create mode 100644 library/src/module_utils/java/com/chuhai/utils/log/LogUtil.kt diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/AVRoomActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/AVRoomActivity.java index ba0854c1a..682c3113f 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/activity/AVRoomActivity.java +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/AVRoomActivity.java @@ -16,6 +16,7 @@ import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUS import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_ROOM_PK_NOTIFY; import android.annotation.SuppressLint; +import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.Intent; @@ -38,6 +39,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; +import androidx.lifecycle.LifecycleOwner; import androidx.viewpager2.widget.ViewPager2; import com.alibaba.fastjson.JSON; @@ -140,6 +142,8 @@ import com.yizhuan.xchat_android_core.room.event.RoomTaskTipsEvent; import com.yizhuan.xchat_android_core.room.pk.event.PKStateEvent; import com.yizhuan.xchat_android_core.super_admin.util.SAdminOptUtil; import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.support.room.RoomContext; +import com.yizhuan.xchat_android_core.support.room.RoomView; import com.yizhuan.xchat_android_core.treasurefairy.FairyMsgInfoBean; import com.yizhuan.xchat_android_core.user.UserModel; import com.yizhuan.xchat_android_core.user.bean.FirstChargeInfo; @@ -163,7 +167,6 @@ import java.net.URL; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -180,7 +183,7 @@ import io.reactivex.disposables.Disposable; */ @CreatePresenter(AvRoomPresenter.class) public class AVRoomActivity extends BaseMvpActivity - implements View.OnClickListener, IAvRoomView { + implements View.OnClickListener, IAvRoomView, RoomView { public static final int FROM_TYPE_NORMAL = 0; public static final int FROM_TYPE_RECOMMEND = 1; @@ -718,18 +721,18 @@ public class AVRoomActivity extends BaseMvpActivity redMap = DemoCache.readRedPackage(); - RedPackageModel.INSTANCE.getRedPackage(roomInfo.getUid()) - .compose(bindToLifecycle()) - .doFinally(() -> { - if (inRoomNotifyInfo != null && (redMap == null || !redMap.containsKey(inRoomNotifyInfo.getRedEnvelopeId()))) { - showRedPackageOpenDialog(inRoomNotifyInfo); - } - }) - .filter(notifyInfo -> inRoomNotifyInfo == null || !notifyInfo.getRedEnvelopeId().equals(inRoomNotifyInfo.getRedEnvelopeId())) - .subscribe(this::showRedPackageOpenDialog); +// if (roomInfo == null) return; +// RedPackageNotifyInfo inRoomNotifyInfo = (RedPackageNotifyInfo) getIntent().getSerializableExtra("notifyInfo"); +// Map redMap = DemoCache.readRedPackage(); +// RedPackageModel.INSTANCE.getRedPackage(roomInfo.getUid()) +// .compose(bindToLifecycle()) +// .doFinally(() -> { +// if (inRoomNotifyInfo != null && (redMap == null || !redMap.containsKey(inRoomNotifyInfo.getRedEnvelopeId()))) { +// showRedPackageOpenDialog(inRoomNotifyInfo); +// } +// }) +// .filter(notifyInfo -> inRoomNotifyInfo == null || !notifyInfo.getRedEnvelopeId().equals(inRoomNotifyInfo.getRedEnvelopeId())) +// .subscribe(this::showRedPackageOpenDialog); } private void showRedPackageOpenDialog(RedPackageNotifyInfo notifyInfo) { @@ -1062,6 +1065,8 @@ public class AVRoomActivity extends BaseMvpActivity { private WeakReference mReference; @@ -1433,5 +1456,4 @@ public class AVRoomActivity extends BaseMvpActivity) { + super.loadAbility(list) + // 红包处理器 + list[RedPackageHandler::class.java.simpleName] = RedPackageHandler() + } +} \ No newline at end of file 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 1232071d2..2e35f06e5 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 @@ -21,6 +21,8 @@ import android.widget.RelativeLayout import android.widget.TextView import androidx.annotation.CallSuper import androidx.core.content.ContextCompat +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.chad.library.adapter.base.BaseQuickAdapter @@ -105,6 +107,8 @@ import com.yizhuan.xchat_android_core.share.bean.SessionType import com.yizhuan.xchat_android_core.super_admin.SaConstant import com.yizhuan.xchat_android_core.super_admin.model.SuperAdminModel import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil +import com.yizhuan.xchat_android_core.support.room.RoomView +import com.yizhuan.xchat_android_core.support.room.RoomWidget import com.yizhuan.xchat_android_core.user.UserModel import com.yizhuan.xchat_android_core.user.bean.BaseInfo import com.yizhuan.xchat_android_core.user.bean.UserInfo @@ -131,7 +135,8 @@ import org.greenrobot.eventbus.ThreadMode */ open class BaseRoomFragment?> : BaseMvpFragment(), - View.OnClickListener, OnGiftDialogBtnClickListener, IBaseRoomView, OnMicroItemClickListener { + View.OnClickListener, OnGiftDialogBtnClickListener, IBaseRoomView, OnMicroItemClickListener, + RoomView { private var myUid: Long = 0 protected lateinit var messageView: MessageView protected lateinit var bottomView: BottomView @@ -180,6 +185,8 @@ open class BaseRoomFragment?> : private var atProxy: AtProxy? = null + // 房间小组件 + private var widgets: HashMap = HashMap() @CallSuper override fun onFindViews() { @@ -239,6 +246,7 @@ open class BaseRoomFragment?> : @SuppressLint("CheckResult") @CallSuper override fun initiate() { + initWidget() //如果不需要開麥,並且還沒有權限的情況下,重置狀態為需要去打開麥克風 myUid = AuthModel.get().currentUid isCloseScreen = AvRoomDataManager.get().isCloseScreen @@ -638,6 +646,7 @@ open class BaseRoomFragment?> : override fun onDestroyView() { super.onDestroyView() releaseView() + unregisterWidgets() } override fun onDestroy() { @@ -1300,4 +1309,30 @@ open class BaseRoomFragment?> : RoomMsgActivity.start(mContext) } } + + /** + * 注册组件 + */ + protected fun registerWidget(name: String, widget: RoomWidget) { + widgets.put(name, widget) + widget.onStart(this) + } + + /** + * 取消注册组件 + */ + protected fun unregisterWidgets() { + widgets.values.forEach { + it.onStop() + } + widgets.clear() + } + + override fun getLifecycleOwner(): LifecycleOwner { + return this + } + + open fun initWidget() { + + } } \ No newline at end of file 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 e80d0732b..d56032978 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 @@ -26,6 +26,7 @@ import com.yizhuan.erban.avroom.dialog.PKScoreBoardDialog; import com.yizhuan.erban.avroom.firstcharge.FirstChargePrizeDialog; import com.yizhuan.erban.avroom.giftvalue.GiftValueDialogUiHelper; import com.yizhuan.erban.avroom.presenter.HomePartyPresenter; +import com.yizhuan.erban.avroom.redpackage.RedPackageWidget; import com.yizhuan.erban.avroom.view.IHomePartyView; import com.yizhuan.erban.avroom.widget.PKBoardView; import com.yizhuan.erban.base.BaseMvpActivity; @@ -125,9 +126,6 @@ public class HomePartyRoomFragment extends BaseRoomFragment { .subscribe(roomQueueInfoSparseArray -> { long uid = AuthModel.get().getCurrentUid(); AudioEngineManager.get().startRtcEngine(uid, roomInfo.getAudioSdkType()); + // TODO 临时方案:后续逐步完善整个房间的RoomContext替换计划 + new AudioRoomContext(roomInfo.getUid()).run(); if (getMvpView() != null) { getMvpView().enterRoomSuccess(); } diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/RedPackageHandler.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/RedPackageHandler.kt new file mode 100644 index 000000000..8faa4915d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/RedPackageHandler.kt @@ -0,0 +1,90 @@ +package com.yizhuan.erban.avroom.redpackage + +import androidx.lifecycle.MutableLiveData +import com.yizhuan.erban.avroom.redpackage.open.RedPackageOpenDialog2 +import com.yizhuan.xchat_android_core.im.custom.bean.RedPackageAttachment +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager +import com.yizhuan.xchat_android_core.manager.RoomEvent +import com.yizhuan.xchat_android_core.redpackage.RedPackageModel +import com.yizhuan.xchat_android_core.redpackage.RedPackageNotifyInfo +import com.yizhuan.xchat_android_core.support.room.RoomContext +import com.yizhuan.xchat_android_core.support.room.RoomHandler + +/** + * Created by Max on 2023/10/26 11:26 + * Desc:红包处理器 + **/ +class RedPackageHandler : RoomHandler() { + + // 入口图标-数据 + val iconLiveData: MutableLiveData = MutableLiveData() + + override fun onStart(context: RoomContext) { + super.onStart(context) + registerSignaling() + requestLatestRoomRedPackage() + } + + /** + * 监听房间信令 + */ + private fun registerSignaling() { + // TODO 临时方案:不应在这里直接监听IM,后续会统一分发出口 + // 信令来源:新/旧版的厅内红包,非全服红包 + IMNetEaseManager.get().chatRoomEventObservable + .compose(bindToLifecycle()) + .filter { + it?.event == RoomEvent.RECEIVE_RED_PACKAGE && it?.chatRoomMessage?.attachment is RedPackageAttachment + }.map { + (it.chatRoomMessage.attachment as RedPackageAttachment).getRedPackageNotifyInfo() + } + .subscribe { data: RedPackageNotifyInfo -> + handleRoomRedPackage(data) + } + } + + /** + * 查找最新的厅内红包(新/旧版的厅内红包,非全服红包) + */ + private fun requestLatestRoomRedPackage() { + logD("requestLatestRoomRedPackage()") + val roomId = roomContext?.roomId ?: return + logD("requestLatestRoomRedPackage() roomId:$roomId") + RedPackageModel.getLatestRoomRedPackage(roomId) + .compose(bindToLifecycle()) + .subscribe { data -> + logD("requestLatestRoomRedPackage() data:$data") + handleRoomRedPackage(data) + } + } + + /** + * 处理厅内红包,非全服红包 + */ + private fun handleRoomRedPackage(data: RedPackageNotifyInfo) { + if (data.kind == 0 || (data.kind == 1 && data.validityType == 0)) { + //【旧版本-厅内红包:kind=0】、【新版本-厅内无门槛-立即生效红包:kind=1&validityType=0】 + tryShowOpenDialog(data) + } + updateIcon(data) + } + + /** + * 更新红包入口图标 + */ + private fun updateIcon(data: RedPackageNotifyInfo) { + iconLiveData.postValue(data) + } + + /** + * 尝试展示红包领取弹窗 + */ + private fun tryShowOpenDialog(data: RedPackageNotifyInfo) { + val activity = roomView?.getActivity() ?: return + if (activity.isFinishing) { + return + } + logD("tryShowOpenDialog() data:$data") + RedPackageOpenDialog2().show(activity) + } +} \ No newline at end of file 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 3491f2b63..dccf7c49b 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 @@ -7,22 +7,27 @@ import android.view.LayoutInflater import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible +import androidx.lifecycle.Observer +import com.chuhai.utils.ServiceTime import com.yizhuan.erban.R import com.yizhuan.xchat_android_core.redpackage.RedPackageNotifyInfo -import com.yizhuan.xchat_android_core.utils.LogUtils +import com.yizhuan.xchat_android_core.support.room.RoomContext +import com.yizhuan.xchat_android_core.support.room.RoomView +import com.yizhuan.xchat_android_core.support.room.RoomWidget import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable +import java.lang.RuntimeException import java.text.SimpleDateFormat import java.util.TimeZone import java.util.concurrent.TimeUnit -import kotlin.random.Random /** * Created by Max on 2023/10/24 16:37 * Desc:房间内的红包入口 **/ -class RedPackageWidget : ConstraintLayout { +class RedPackageWidget : ConstraintLayout, RoomWidget { + private var roomView: RoomView? = null private var textView: TextView? = null private var countDownDisposable: Disposable? = null @@ -33,6 +38,19 @@ class RedPackageWidget : ConstraintLayout { } } + // 为了获取到RoomContext + private val contextObserver = object : Observer { + override fun onChanged(value: RoomContext?) { + if (value != null) { + RoomContext.contextLiveData.removeObserver(this) + val view = this@RedPackageWidget.roomView + if (view != null) { + init(view) + } + } + } + } + constructor(context: Context) : super(context) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( @@ -49,26 +67,38 @@ class RedPackageWidget : ConstraintLayout { ) : super(context, attrs, defStyleAttr, defStyleRes) init { + // 默认不可见 + this.isVisible = false 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?) { - this.isVisible = true - switchUI(true) - val time = System.currentTimeMillis() + Random.nextLong(1000, 1000 * 100) - val count = time - System.currentTimeMillis() + /** + * 开始倒计时 + * @param time 开抢时间 + */ + private fun startCountDown(time: Long) { + val count = time - ServiceTime.time + if (count <= 0) { + switchUI(false) + return + } + logD("startCountDown() count:$count") countDownDisposable = Observable.intervalRange(0, count, 0, 500L, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { - val gap = time - System.currentTimeMillis() + val gap = time - ServiceTime.time if (gap >= 0) { textView?.text = mmssFormat.format(gap) + } else { + switchUI(false) + throw RuntimeException("状态已更新") } } .doOnComplete { + logD("doOnComplete()") switchUI(false) } .subscribe() @@ -85,10 +115,58 @@ class RedPackageWidget : ConstraintLayout { } else { textView?.setBackgroundResource(R.drawable.red_package_widget_bg_text) textView?.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 9f) + textView?.setText(R.string.red_package_widget_get) } } - fun onStop() { + override fun onStart(roomView: RoomView) { + this.roomView = roomView + // TODO #临时方案 因为目前View的生命周期比RoomContext还早,暂时这样拿到Context + val context = RoomContext.contextLiveData.value + if (context == null) { + RoomContext.contextLiveData.observeForever(contextObserver) + } else { + init(roomView) + } + } + + private fun init(roomView: RoomView) { + val context = roomView.getRoomContext() + val lifecycleOwner = roomView.getLifecycleOwner() + val handler = + context?.findAbility(RedPackageHandler::class.java.simpleName) + handler?.iconLiveData?.observe(lifecycleOwner) { + loadData(it) + } + } + + /** + * 更新数据 + */ + private fun loadData(data: RedPackageNotifyInfo?) { + stopCountDown() + if (data != null) { + if (data.validityType == 1) { + // 限时生效 + switchUI(true) + startCountDown(data.beginTime) + } else { + // 立即生效 + switchUI(false) + } + this.isVisible = true + } else { + this.isVisible = false + } + } + + override fun onStop() { + RoomContext.contextLiveData.removeObserver(contextObserver) + stopCountDown() + this.roomView = null + } + + private fun stopCountDown() { if (countDownDisposable?.isDisposed == false) { countDownDisposable?.dispose() } diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseActivity.java b/app/src/main/java/com/yizhuan/erban/base/BaseActivity.java index 50111e60a..f12bf2f7b 100644 --- a/app/src/main/java/com/yizhuan/erban/base/BaseActivity.java +++ b/app/src/main/java/com/yizhuan/erban/base/BaseActivity.java @@ -35,7 +35,6 @@ import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.StyleSpan; -import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; @@ -51,6 +50,7 @@ import androidx.fragment.app.FragmentManager; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.chuhai.utils.log.ILog; import com.google.gson.Gson; import com.netease.nim.uikit.common.util.log.LogUtil; import com.netease.nimlib.sdk.NIMSDK; @@ -103,7 +103,6 @@ import com.yizhuan.xchat_android_core.UriProvider; import com.yizhuan.xchat_android_core.bean.BaseProtocol; import com.yizhuan.xchat_android_core.gift.bean.LuckyBagNoticeInfo; import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; -import com.yizhuan.xchat_android_core.im.custom.bean.NotifyH5Attachment; import com.yizhuan.xchat_android_core.im.custom.bean.NotifyH5Info; import com.yizhuan.xchat_android_core.im.custom.bean.PlayEffectInfo; import com.yizhuan.xchat_android_core.im.custom.bean.RoomBoxPrizeInfo; 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 cc3475517..942853677 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 @@ -6,13 +6,12 @@ import android.os.Build import android.os.Environment import android.text.SpannableString import android.view.View +import com.chuhai.utils.log.ILog import com.netease.nim.uikit.StatusBarUtil import com.tongdaxing.erban.upgrade.AppUpgradeHelper import com.yizhuan.erban.BuildConfig import com.yizhuan.erban.R import com.yizhuan.erban.UIHelper -import com.yizhuan.erban.avroom.redpackage.open.RedPackageOpenDialog2 -import com.yizhuan.erban.avroom.redpackage.send.RedPackageSendDialog2 import com.yizhuan.erban.base.BaseViewBindingActivity import com.yizhuan.erban.common.widget.dialog.DialogManager.OkCancelDialogListener import com.yizhuan.erban.databinding.ActivitySettingBinding @@ -43,7 +42,7 @@ import java.io.File * 设置页 * Created by wushaocheng on 2023/2/1. */ -class SettingActivity : BaseViewBindingActivity(), View.OnClickListener { +class SettingActivity : BaseViewBindingActivity(), View.OnClickListener,ILog { override fun init() { EventBus.getDefault().register(this) initWhiteTitleBar(ResUtil.getString(R.string.ui_setting_settingactivity_01)) @@ -80,7 +79,7 @@ class SettingActivity : BaseViewBindingActivity(), View. if (BuildConfig.DEBUG) { binding.titleBar.setOnTitleClickListener { - RedPackageOpenDialog2().show(this) + debug() } } } @@ -112,6 +111,7 @@ class SettingActivity : BaseViewBindingActivity(), View. BindPhoneActivity.start(this) } } + R.id.rly_contact_us -> UIHelper.openContactUs(this) R.id.rly_help -> UIHelper.showUsinghelp(this) R.id.rly_update -> startActivity(Intent(applicationContext, AboutActivity::class.java)) @@ -124,9 +124,14 @@ class SettingActivity : BaseViewBindingActivity(), View. } ModifyPwdActivity.start(this, ModifyPwdActivity.PAY_PWD) } + R.id.btn_login_out -> { val cacheLoginUserInfo = UserModel.get().cacheLoginUserInfo ?: return - if (!cacheLoginUserInfo.isBindPasswd && !SPUtils.getBoolean(SpConstants.SET_PASSWORD, false)) { + if (!cacheLoginUserInfo.isBindPasswd && !SPUtils.getBoolean( + SpConstants.SET_PASSWORD, + false + ) + ) { dialogManager.showOkCancelWithTitleDialog(ResUtil.getString(R.string.set_login_password), SpannableString(ResUtil.getString(R.string.set_login_password_tip)), ResUtil.getString(R.string.login_fragment_adduserinfofragment_04), @@ -135,7 +140,10 @@ class SettingActivity : BaseViewBindingActivity(), View. override fun onCancel() {} override fun onOk() { SPUtils.putBoolean(SpConstants.SET_PASSWORD, true) - ModifyPwdActivity.start(this@SettingActivity, ModifyPwdActivity.LOGIN_PWD) + ModifyPwdActivity.start( + this@SettingActivity, + ModifyPwdActivity.LOGIN_PWD + ) } }) } else { @@ -143,10 +151,12 @@ class SettingActivity : BaseViewBindingActivity(), View. LogoutHelper.logout() } } + R.id.tv_community_norms -> CommonWebViewActivity.start( this, UriProvider.getCommnunityNorms() ) + R.id.rly_clear_cache -> dialogManager.showOkCancelWithTitleDialog(ResUtil.getString(R.string.ui_setting_settingactivity_07), SpannableString(ResUtil.getString(R.string.ui_setting_settingactivity_08)), ResUtil.getString(R.string.ui_setting_settingactivity_09), @@ -157,6 +167,7 @@ class SettingActivity : BaseViewBindingActivity(), View. clearCache() } }) + R.id.tv_notice_setting -> NoticeSettingActivity.start(context) R.id.tv_shield_manager -> ShieldManageActivity.start(context) R.id.rly_permission -> PermissionGuideActivity.start(context) @@ -203,4 +214,8 @@ class SettingActivity : BaseViewBindingActivity(), View. dialogManager.dismissDialog() EventBus.getDefault().unregister(this) } + + private fun debug() { +// RedPackageOpenDialog2().show(this) + } } \ No newline at end of file diff --git a/core/src/diff_src_erban/java/com/yizhuan/xchat_android_core/manager/IMNetEaseManager.java b/core/src/diff_src_erban/java/com/yizhuan/xchat_android_core/manager/IMNetEaseManager.java index fe9dd00ca..c9c4bfc33 100644 --- a/core/src/diff_src_erban/java/com/yizhuan/xchat_android_core/manager/IMNetEaseManager.java +++ b/core/src/diff_src_erban/java/com/yizhuan/xchat_android_core/manager/IMNetEaseManager.java @@ -99,6 +99,7 @@ import com.yizhuan.xchat_android_core.im.custom.bean.MonsterHuntingResultAttachm import com.yizhuan.xchat_android_core.im.custom.bean.MonsterStatusAttachment; import com.yizhuan.xchat_android_core.im.custom.bean.MultiGiftAttachment; import com.yizhuan.xchat_android_core.im.custom.bean.NobleAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RedPackageAttachment; import com.yizhuan.xchat_android_core.im.custom.bean.RoomBoxPrizeAttachment; import com.yizhuan.xchat_android_core.im.custom.bean.RoomFreeGiftAttachment; import com.yizhuan.xchat_android_core.im.custom.bean.RoomFreeGiftMsgBean; @@ -1148,12 +1149,17 @@ public final class IMNetEaseManager { case CustomAttachment.CUSTOM_MSG_RED_PACKAGE: switch (second) { + // 老版本厅内红包(2.2.0之前) case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND: noticeRoomEvent(msg, RoomEvent.RECEIVE_RED_PACKAGE); break; case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_MSG: addMessages(msg); break; + // 新版厅内红包(>=2.2.0版本) + case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND2: + noticeRoomEvent(msg, RoomEvent.RECEIVE_RED_PACKAGE); + break; } break; diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/CustomAttachment.java b/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/CustomAttachment.java index ded3ced58..eb0253bf7 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/CustomAttachment.java +++ b/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/CustomAttachment.java @@ -317,6 +317,7 @@ public class CustomAttachment implements MsgAttachment { public static final int CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND = 602; public static final int CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ALL_DIAMOND = 604;//全服红包 public static final int CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_MSG = 605; + public static final int CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND2 = 606;//新版本-厅内红包 //开福袋飘屏 public static final int CUSTOM_MSG_LUCKY_GIFT = 61; public static final int CUSTOM_MSG_LUCKY_GIFT_ROOM_NOTIFY = 610;// 福袋礼物房间飘屏通知 diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/RedPackageAttachment.java b/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/RedPackageAttachment.java index 69bfbb912..e48be6a34 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/RedPackageAttachment.java +++ b/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/RedPackageAttachment.java @@ -14,7 +14,7 @@ import lombok.EqualsAndHashCode; @Data public class RedPackageAttachment extends CustomAttachment { - private RedPackageNotifyInfo redPackageNotifyInfo; + public RedPackageNotifyInfo redPackageNotifyInfo; public RedPackageAttachment(int second) { super(CUSTOM_MSG_RED_PACKAGE, second); diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/manager/AvRoomDataManager.java b/core/src/main/java/com/yizhuan/xchat_android_core/manager/AvRoomDataManager.java index 164e4be89..97ac90106 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/manager/AvRoomDataManager.java +++ b/core/src/main/java/com/yizhuan/xchat_android_core/manager/AvRoomDataManager.java @@ -39,6 +39,7 @@ import com.yizhuan.xchat_android_core.room.game.GameStatus; import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; import com.yizhuan.xchat_android_core.super_admin.SuperAdminDataMrg; import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.support.room.RoomContext; import com.yizhuan.xchat_android_core.user.UserModel; import com.yizhuan.xchat_android_core.utils.CurrentTimeUtils; import com.yizhuan.xchat_android_core.utils.LogUtils; @@ -261,6 +262,10 @@ public final class AvRoomDataManager { kickOutRoomUids.clear(); kickOutRoomUids = null; } + RoomContext context = RoomContext.Companion.get(); + if (context != null) { + context.performStop(); + } LogUtils.d(ResUtil.getString(R.string.xchat_android_core_manager_avroomdatamanager_05)); } diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedEnvelopeVO.kt b/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedEnvelopeVO.kt index e0f6ba12c..c1ecbe5a0 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedEnvelopeVO.kt +++ b/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedEnvelopeVO.kt @@ -4,20 +4,32 @@ import com.yizhuan.xchat_android_core.community.UserVo data class RedEnvelopeVO( - var beginTime: Long = 0, - var createTime: Long = 0, - var endTime: Long = 0, - var id: String, - var message: String, - var redEnvelopeAmount: Double = 0.0, - var roomUId: Long = 0, - /** - * 红包类型 1:房间水晶红包 2:全服水晶红包 3:房间礼物红包 4:全服礼物红包 - */ - var type: Int = 0, - var updateTime: Long = 0, - var userId: Long = 0, - var totalNum: String = "", - var pickNum: String = "", - var userVO: UserVo? = null + var beginTime: Long = 0, + var createTime: Long = 0, + var endTime: Long = 0, + var id: String, + var message: String, + var redEnvelopeAmount: Double = 0.0, + var roomUId: Long = 0, + /** + * 红包类型 1:房间水晶红包 2:全服水晶红包 3:房间礼物红包 4:全服礼物红包 + */ + var type: Int = 0, + var updateTime: Long = 0, + var userId: Long = 0, + var totalNum: Long = 0, + var pickNum: Long = 0, + var userVO: UserVo? = null, + /** + * 红包种类 0 旧版本 1 无门槛红包 2 关注红包 3 分享红包 4 弹幕红包 + */ + var kind: Int = 0, + /** + * 生效类型 0 立即生效 1 限时生效 + */ + var validityType: Int = 0, + /** + * 红包状态 1 开抢中 2 过时 3 抢光了 4 抢到了 5 将要开始 6 超时已退还 + */ + var state: Int? ) \ 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 f375f927a..bf3e7e67d 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 @@ -44,20 +44,49 @@ object RedPackageModel { } fun getRedPackage(uid: Long): Observable { - return api.getRedPackage(uid) + return api.getRedPackage(true, uid) .io2main() .handleBeanData() .toObservable() .flatMap { Observable.fromIterable(it) } .map { RedPackageNotifyInfo( - it.id, - it.type, - it.message, - it.userVO?.avatar ?: "", - it.userVO?.nick ?: "", - it.roomUId, - "" + redEnvelopeId = it.id, + redEnvelopeType = it.type, + redEnvelopeMessage = it.message, + sendUserAvatar = it.userVO?.avatar ?: "", + sendUserNick = it.userVO?.nick ?: "", + roomUid = it.roomUId, + roomTitle = "", + kind = it.kind, + beginTime = it.beginTime, + redEnvelopeNum = it.totalNum, + validityType = it.validityType + ) + } + } + + /** + * 获取房间最新可用红包 + */ + fun getLatestRoomRedPackage(uid: Long): Observable { + return api.getRedPackage(true, uid) + .io2main() + .handleBeanData() + .toObservable().map { + val item = it.last() + RedPackageNotifyInfo( + redEnvelopeId = item.id, + redEnvelopeType = item.type, + redEnvelopeMessage = item.message, + sendUserAvatar = item.userVO?.avatar ?: "", + sendUserNick = item.userVO?.nick ?: "", + roomUid = item.roomUId, + roomTitle = "", + kind = item.kind, + beginTime = item.beginTime, + redEnvelopeNum = item.totalNum, + validityType = item.validityType ) } } @@ -104,7 +133,10 @@ object RedPackageModel { * @return */ @GET("/room/red-envelop") - fun getRedPackage(@Query("uid") uid: Long): Single>> + fun getRedPackage( + @Query("isShowKind") isShowKind: Boolean, + @Query("uid") uid: Long + ): Single>> /** @@ -114,6 +146,5 @@ object RedPackageModel { fun setRedPackageSwitch(@Path("roomUid") uid: Long): Single> } - } diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedPackageNotifyInfo.kt b/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedPackageNotifyInfo.kt index 7ce2d7a4b..b71239dae 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedPackageNotifyInfo.kt +++ b/core/src/main/java/com/yizhuan/xchat_android_core/redpackage/RedPackageNotifyInfo.kt @@ -4,38 +4,58 @@ import java.io.Serializable data class RedPackageNotifyInfo( - /** - * 红包 id - */ - var redEnvelopeId: String = "", + /** + * 红包 id + */ + var redEnvelopeId: String = "", - /** - * 红包类型 - */ - var redEnvelopeType: Int = 0, + /** + * 红包类型 1:房间水晶红包 2:全服水晶红包 3:房间礼物红包 4:全服礼物红包 + */ + var redEnvelopeType: Int = 0, - /** - * 红包消息 - */ - var redEnvelopeMessage: String = "", + /** + * 红包消息 + */ + var redEnvelopeMessage: String = "", - /** - * 红包发送者头像 - */ - var sendUserAvatar: String = "", + /** + * 红包发送者头像 + */ + var sendUserAvatar: String = "", - /** - * 红包发送者昵称 - */ - var sendUserNick: String = "", - /** - * 房间uid - */ - var roomUid: Long = 0, + /** + * 红包发送者昵称 + */ + var sendUserNick: String = "", + /** + * 房间uid + */ + var roomUid: Long = 0, - /** - * 房间名称 - */ - var roomTitle: String = "" + /** + * 房间名称 + */ + var roomTitle: String = "", -) : Serializable \ No newline at end of file + /** + * 红包种类 0 旧版本 1 无门槛红包 2 关注红包 3 分享红包 4 弹幕红包 + */ + var kind: Int = 0, + + /** + * 红包可领取时间 + */ + var beginTime: Long = 0, + + /** + * 红包数量 + */ + var redEnvelopeNum: Long = 0, + + /** + * 生效类型 0 立即生效 1 限时生效 + */ + var validityType: Int?, + + ) : Serializable \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/room/core/RoomDataService.kt b/core/src/main/java/com/yizhuan/xchat_android_core/room/core/RoomDataService.kt new file mode 100644 index 000000000..63a323cf5 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/room/core/RoomDataService.kt @@ -0,0 +1,10 @@ +package com.yizhuan.xchat_android_core.room.core + +import com.yizhuan.xchat_android_core.support.room.RoomService + +/** + * Created by Max on 2023/10/26 12:36 + * Desc:房间数据服务 + **/ +class RoomDataService : RoomService() { +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomAbility.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomAbility.kt new file mode 100644 index 000000000..1005423a1 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomAbility.kt @@ -0,0 +1,98 @@ +package com.yizhuan.xchat_android_core.support.room + +import androidx.annotation.CallSuper +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.LifecycleOwner +import com.chuhai.utils.log.ILog +import com.trello.rxlifecycle3.LifecycleProvider +import com.trello.rxlifecycle3.LifecycleTransformer +import com.trello.rxlifecycle3.OutsideLifecycleException +import com.trello.rxlifecycle3.RxLifecycle +import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomFullLifecycleObserver +import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomLifecycle +import io.reactivex.Observable +import io.reactivex.functions.Function +import io.reactivex.subjects.BehaviorSubject + +/** + * Created by Max on 2023/10/26 11:03 + * Desc:房间-基础能力组件 + **/ +abstract class RoomAbility : LifecycleEventObserver, ILog, RoomFullLifecycleObserver, + LifecycleProvider { + + protected var roomContext: RoomContext? = null + + protected var roomView: RoomView? = null + + // 自定义RxLifeCycle(临时方案:后续替换为Flow) + private val lifecycleSubject = BehaviorSubject.create() + + /** + * 被RoomContext激活 + */ + @CallSuper + open fun onAttach(context: RoomContext) { + this.roomContext = context + context.roomLifecycle.addObserver(this) + } + + /** + * View附加状态 + * @param view + */ + @CallSuper + open fun onViewAttach(view: RoomView) { + roomView?.getLifecycleOwner()?.lifecycle?.removeObserver(this) + roomView = view + view.getLifecycleOwner().lifecycle.addObserver(this) + } + + @CallSuper + override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { + if (event == Lifecycle.Event.ON_DESTROY) { + roomView?.getLifecycleOwner()?.lifecycle?.removeObserver(this) + roomView = null + } + } + + override fun onStateChanged(context: RoomContext, event: RoomLifecycle.Event) { + super.onStateChanged(context, event) + // 同步更新事件 + lifecycleSubject.onNext(event) + if (event == RoomLifecycle.Event.STOP) { + roomContext?.roomLifecycle?.removeObserver(this) + roomContext = null + } + } + + + + + + + /** + * 下面为RxLifeCycle相关(临时方案,后续替换Flow) + */ + override fun lifecycle(): Observable { + return lifecycleSubject.hide() + } + + override fun bindUntilEvent(event: RoomLifecycle.Event): LifecycleTransformer { + return RxLifecycle.bindUntilEvent(lifecycleSubject, event) + } + + override fun bindToLifecycle(): LifecycleTransformer { + return RxLifecycle.bind(lifecycleSubject, ROOM_LIFECYCLE) + } + + private val ROOM_LIFECYCLE: Function = + Function { lastEvent -> + when (lastEvent) { + RoomLifecycle.Event.START -> RoomLifecycle.Event.STOP + RoomLifecycle.Event.STOP -> throw OutsideLifecycleException("Cannot bind to Room lifecycle when outside of it.") + else -> throw UnsupportedOperationException("Binding to $lastEvent not yet implemented") + } + } +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomContext.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomContext.kt new file mode 100644 index 000000000..5ff404352 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomContext.kt @@ -0,0 +1,111 @@ +package com.yizhuan.xchat_android_core.support.room + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.chuhai.utils.log.ILog +import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomLifecycle +import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomLifecycleRegistry + +/** + * Created by Max on 2023/10/26 11:50 + * Desc:一个房间 + **/ +abstract class RoomContext(val roomId: Long) : ILog { + + /** + * 临时维护在这里,后续逐步改动 + */ + companion object { + private var context: RoomContext? = null + + // TODO:#临时方案 目前房间的生命周期有点出乎意料,未成功进房时,View层都已初始化完毕,所以临时开放这个LiveData供View层获取到Context + private val _contextLiveData = MutableLiveData() + val contextLiveData: LiveData get() = _contextLiveData + fun get(): RoomContext? { + return context + } + + fun set(context: RoomContext?) { + this.context = context + _contextLiveData.postValue(context) + } + } + + /** + * 生命周期处理 + */ + val roomLifecycle: RoomLifecycleRegistry = RoomLifecycleRegistry() + + /** + * 所有能力组件 + */ + private val abilityList = LinkedHashMap() + + init { + initAbility() + } + + /** + * 启动(进入房间) + */ + fun performStart() { + logI("performStart()", filePrinter = true) + roomLifecycle.handleLifecycleEvent(this, RoomLifecycle.Event.START) + } + + /** + * 停止(退出房间) + */ + fun performStop() { + logI("performStop()", filePrinter = true) + roomLifecycle.handleLifecycleEvent(this, RoomLifecycle.Event.STOP) + onCleared() + } + + /** + * 初始化Ability + */ + private fun initAbility() { + loadAbility(abilityList) + abilityList.keys.forEach { + abilityList[it]?.onAttach(this) + } + } + + /** + * 装载能力组件 + */ + open fun loadAbility(list: MutableMap) { + } + + /** + * 查找组件 + */ + fun findAbility(key: String): T? { + return abilityList[key] as? T + } + + /** + * 附加上视图了 + */ + @Deprecated("临时方案:后续逐步完善RoomContext替换计划,到时候不会在这里实现该逻辑") + fun onViewAttach(view: RoomView) { + abilityList.keys.forEach { + abilityList[it]?.onViewAttach(view) + } + } + + /** + * 激活房间(进入房间后) + */ + @Deprecated("临时方案:后续逐步完善RoomContext替换计划,到时候不会在这里实现该逻辑") + fun run() { + set(this) + performStart() + } + + private fun onCleared() { + abilityList.clear() + set(null) + } +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomHandler.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomHandler.kt new file mode 100644 index 000000000..c8cfbc7d5 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomHandler.kt @@ -0,0 +1,8 @@ +package com.yizhuan.xchat_android_core.support.room + +/** + * Created by Max on 2023/10/26 11:02 + * Desc:房间内的业务处理器 + **/ +open class RoomHandler : RoomAbility() { +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomService.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomService.kt new file mode 100644 index 000000000..ef9ef505c --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomService.kt @@ -0,0 +1,10 @@ +package com.yizhuan.xchat_android_core.support.room + +/** + * Created by Max on 2023/10/26 12:31 + * Desc:房间-基础服务组件 + * PS:基于[RoomContext],提供整个房间的基础服务能力。(服务之间可相互提供能力,也可向下提供能力。) + * + **/ +abstract class RoomService : RoomAbility() { +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomView.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomView.kt new file mode 100644 index 000000000..8223a8ca8 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomView.kt @@ -0,0 +1,23 @@ +package com.yizhuan.xchat_android_core.support.room + +import android.app.Activity +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner + +/** + * Created by Max on 2023/10/26 15:05 + * Desc:房间视图层 + * TODO:目前Activity和子Fragment都实现该接口,感觉有些奇怪,PS:还没熟悉现阶段的房间视图层级关系,后续梳理后整体优化 + **/ +interface RoomView { + fun getLifecycleOwner(): LifecycleOwner + + fun getActivity(): Activity? + + /** + * 获取房间上下文 + */ + fun getRoomContext(): RoomContext? { + return RoomContext.get() + } +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomWidget.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomWidget.kt new file mode 100644 index 000000000..67410f18e --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/RoomWidget.kt @@ -0,0 +1,20 @@ +package com.yizhuan.xchat_android_core.support.room + +import com.chuhai.utils.log.ILog + +/** + * Created by Max on 2023/10/26 17:12 + * Desc:房间UI组件 + **/ +interface RoomWidget : ILog { + + /** + * 组件激活 + */ + fun onStart(roomView: RoomView) + + /** + * 组件停止 + */ + fun onStop() +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomFullLifecycleObserver.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomFullLifecycleObserver.kt new file mode 100644 index 000000000..7f21d1a93 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomFullLifecycleObserver.kt @@ -0,0 +1,34 @@ +package com.yizhuan.xchat_android_core.support.room.lifecycle + +import com.yizhuan.xchat_android_core.support.room.RoomContext + + +/** + * Created by Max on 2023/10/26 11:50 + * Desc:房间生命周期事件观察者(完整) + **/ +interface RoomFullLifecycleObserver : RoomLifecycleObserver { + + override fun onStateChanged(context: RoomContext, event: RoomLifecycle.Event) { + when (event) { + RoomLifecycle.Event.START -> { + onStart(context) + } + RoomLifecycle.Event.STOP -> { + onStop(context) + } + } + } + + /** + * 启动房间 + * PS:只会执行一次,相当于Activity的onCreate。 + */ + fun onStart(context: RoomContext) {} + + /** + * 退出房间 + * PS:只会执行一次,相当于Activity的onDestroy。 + */ + fun onStop(context: RoomContext) {} +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycle.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycle.kt new file mode 100644 index 000000000..e2d3de2eb --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycle.kt @@ -0,0 +1,35 @@ +package com.yizhuan.xchat_android_core.support.room.lifecycle + +import com.chuhai.utils.ICleared + +/** + * Created by Max on 2023/10/26 11:50 + * Desc:房间生命周期 + **/ +abstract class RoomLifecycle : ICleared { + + /** + * 添加生命周期监听 + * PS:目前是及时事件分发,对于已发生状态事件不会补充分发。 + */ + abstract fun addObserver(observer: RoomLifecycleObserver) + + /** + * 移除生命周期监听 + */ + abstract fun removeObserver(observer: RoomLifecycleObserver) + + enum class Event { + /** + * 启动房间 + * PS:只会执行一次,相当于Activity的onCreate。 + */ + START, + + /** + * 退出房间 + * PS:只会执行一次,相当于Activity的onDestroy。 + */ + STOP; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleObserver.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleObserver.kt new file mode 100644 index 000000000..27ac33f92 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleObserver.kt @@ -0,0 +1,18 @@ +package com.yizhuan.xchat_android_core.support.room.lifecycle + +import com.yizhuan.xchat_android_core.support.room.RoomContext + + +/** + * Created by Max on 2023/10/26 11:50 + * Desc:房间生命周期事件观察者 + **/ +interface RoomLifecycleObserver { + + /** + * 状态改变 + * @param event 新事件 + */ + fun onStateChanged(context: RoomContext, event: RoomLifecycle.Event) + +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleOwner.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleOwner.kt new file mode 100644 index 000000000..a8a5c007b --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleOwner.kt @@ -0,0 +1,9 @@ +package com.yizhuan.xchat_android_core.support.room.lifecycle + +/** + * Created by Max on 2023/10/26 11:50 + * Desc:房间生命周期持有者 + **/ +interface RoomLifecycleOwner { + fun getLifecycle(): RoomLifecycle +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleRegistry.kt b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleRegistry.kt new file mode 100644 index 000000000..5663a4747 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/RoomLifecycleRegistry.kt @@ -0,0 +1,62 @@ +package com.yizhuan.xchat_android_core.support.room.lifecycle + +import com.chuhai.utils.log.ILog +import com.yizhuan.xchat_android_core.support.room.RoomContext +import java.util.concurrent.CopyOnWriteArrayList + +/** + * Created by Max on 2023/10/26 11:50 + * Desc:房间生命周期简单实现 + * PS:目前是及时事件分发,对于已发生状态事件不会补充分发。 + **/ +class RoomLifecycleRegistry : RoomLifecycle(), ILog { + /** + * 生命周期监听 + */ + private val observers: CopyOnWriteArrayList = CopyOnWriteArrayList() + + /** + * 当前事件 + */ + private var event: Event? = null + + override fun addObserver(observer: RoomLifecycleObserver) { + observers.add(observer) + } + + override fun removeObserver(observer: RoomLifecycleObserver) { + observers.remove(observer) + } + + /** + * 设置最新的事件 + */ + fun handleLifecycleEvent(context: RoomContext, event: Event) { + logI("handleLifecycleEvent() event:$event", filePrinter = true) + if (this.event == Event.STOP) { + // 停止状态 + logI("handleLifecycleEvent() 停止状态", filePrinter = true) + return + } + if (this.event == event) { + // 状态未改变 + return + } + dispatchEvent(context, event) + } + + /** + * 分发事件 + */ + private fun dispatchEvent(context: RoomContext, event: Event) { + logI("dispatchEvent() event:$event", filePrinter = true) + this.event = event + observers.forEach { + it.onStateChanged(context, event) + } + if (event == Event.STOP) { + // 停止后,主动清空下 + observers.clear() + } + } +} \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/rx/RoomRxLifecycleEvent.java b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/rx/RoomRxLifecycleEvent.java new file mode 100644 index 000000000..10fb6b7f3 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/support/room/lifecycle/rx/RoomRxLifecycleEvent.java @@ -0,0 +1,11 @@ +package com.yizhuan.xchat_android_core.support.room.lifecycle.rx; + + +/** + * Created by Max on 2023/10/26 11:50 + * Desc:RxLifecycle 房间生命周期 + **/ +public enum RoomRxLifecycleEvent { + START, + STOP +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/ICleared.kt b/library/src/module_utils/java/com/chuhai/utils/ICleared.kt new file mode 100644 index 000000000..63273e7fc --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/ICleared.kt @@ -0,0 +1,14 @@ +package com.chuhai.utils + + +/** + * Created by Max on 2023/10/26 11:50 + * Desc:清除释放统一接口 + **/ +interface ICleared { + + /** + * 清除/释放 + */ + fun onCleared() {} +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/log/AndroidLogPrinter.kt b/library/src/module_utils/java/com/chuhai/utils/log/AndroidLogPrinter.kt new file mode 100644 index 000000000..9a027de2c --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/log/AndroidLogPrinter.kt @@ -0,0 +1,13 @@ +package com.chuhai.utils.log + +import android.util.Log + +/** + * Created by Max on 2023/10/26 10:29 + * Desc:Android日志 + */ +class AndroidLogPrinter : LogPrinter { + override fun println(level: Int, tag: String, message: String) { + Log.println(level, tag, message) + } +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/log/ILog.kt b/library/src/module_utils/java/com/chuhai/utils/log/ILog.kt new file mode 100644 index 000000000..8f748390d --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/log/ILog.kt @@ -0,0 +1,61 @@ +package com.chuhai.utils.log + +/** + * Created by Max on 2023/10/26 10:29 + * Desc:日志快捷使用接口 + */ +interface ILog { + + companion object { + /** + * 清理(退出APP时调用) + */ + fun onCleared() { + + } + } + + /** + * 默认日志Tag + */ + fun getLogTag(): String { + return this::class.java.simpleName + } + + fun logI(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) { + LogUtil.i(tag, message, filePrinter) + } + + fun logV(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) { + LogUtil.v(tag, message, filePrinter) + } + + fun logW(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) { + LogUtil.w(tag, message, filePrinter) + } + + fun logD(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) { + LogUtil.d(tag, message, filePrinter) + } + + fun logE(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) { + LogUtil.e(tag, message, filePrinter) + } + + fun logE( + throwable: Throwable, + tag: String = getLogTag(), + filePrinter: Boolean = false + ) { + LogUtil.e(tag, throwable, filePrinter) + } + + fun logE( + message: String, + throwable: Throwable, + tag: String = getLogTag(), + filePrinter: Boolean = false + ) { + LogUtil.e(tag, message, throwable, filePrinter) + } +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/log/LogPrinter.kt b/library/src/module_utils/java/com/chuhai/utils/log/LogPrinter.kt new file mode 100644 index 000000000..86f231c74 --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/log/LogPrinter.kt @@ -0,0 +1,14 @@ +package com.chuhai.utils.log + + +/** + * Created by Max on 2023/10/26 10:29 + * Desc: 日志打印 + */ +interface LogPrinter { + /** + * 打印 + * @param level 级别 [android.util.Log] + */ + fun println(level: Int, tag: String, message: String) +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/log/LogUtil.kt b/library/src/module_utils/java/com/chuhai/utils/log/LogUtil.kt new file mode 100644 index 000000000..a3ce5e7b7 --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/log/LogUtil.kt @@ -0,0 +1,101 @@ +package com.chuhai.utils.log + +import android.util.Log + +/** + * Created by Max on 2023/10/26 10:29 + * Desc:日志工具 + */ +object LogUtil { + + private var consolePrinter: LogPrinter? = AndroidLogPrinter() + + private var filePrinter: LogPrinter? = null + + // 是否启动控制台打印 + var consolePrinterEnabled: Boolean = true + + // 是否启动文件打印 + var filePrinterEnabled: Boolean = true + + /** + * 设置文件打印 + */ + fun setFilePrinter(filePrinter: LogPrinter) { + this.filePrinter = filePrinter + } + + fun e(tag: String, message: String, filePrinter: Boolean = false) { + log(Log.ERROR, tag, message, filePrinter) + } + + fun e(tag: String, throwable: Throwable, filePrinter: Boolean = false) { + val cause = Log.getStackTraceString(throwable) + if (cause.isEmpty()) { + return + } + e(tag, cause, filePrinter) + } + + fun e(tag: String, message: String?, throwable: Throwable, filePrinter: Boolean = false) { + val cause = Log.getStackTraceString(throwable) + if (message == null && cause.isEmpty()) { + return + } + e(tag, message + "\t\t" + cause, filePrinter) + } + + fun d(tag: String, message: String, filePrinter: Boolean = false) { + log(Log.DEBUG, tag, message, filePrinter) + } + + fun i(tag: String, message: String, filePrinter: Boolean = false) { + log(Log.INFO, tag, message, filePrinter) + } + + fun v(tag: String, message: String, filePrinter: Boolean = false) { + log(Log.VERBOSE, tag, message, filePrinter) + } + + fun w(tag: String, message: String, filePrinter: Boolean = false) { + log(Log.WARN, tag, message, filePrinter) + } + + /** + * 输出日志 + */ + fun log(level: Int = Log.INFO, tag: String?, message: String?, filePrinter: Boolean = false) { + if (tag.isNullOrEmpty()) { + return + } + if (message.isNullOrEmpty()) { + return + } + // 输出控制台 + logConsole(level, tag, message) + // 输出文件 + if (filePrinter) { + logFile(level, tag, message) + } + } + + /** + * 输出到控制台 + */ + fun logConsole(level: Int = Log.INFO, tag: String, message: String) { + if (!consolePrinterEnabled) { + return + } + consolePrinter?.println(level, tag, message) + } + + /** + * 输出到文件 + */ + fun logFile(level: Int = Log.INFO, tag: String, message: String) { + if (!filePrinterEnabled) { + return + } + filePrinter?.println(level, tag, message) + } +} \ No newline at end of file