From c72af689e5fd00fcf6fbae96d0a7228114dbbbe4 Mon Sep 17 00:00:00 2001 From: max Date: Tue, 28 May 2024 19:34:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E8=B4=AD=E4=B9=B0=E6=B8=B8=E6=88=8F=E6=8E=A5=E5=8F=A3=EF=BC=88?= =?UTF-8?q?=E5=BE=85=E5=AE=8C=E6=95=B4=E8=81=94=E8=B0=83=EF=BC=89=20feat?= =?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84=E6=B8=B8=E6=88=8F=E6=88=BFUI=20feat?= =?UTF-8?q?=EF=BC=9A=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=E6=B8=B8=E6=88=8F?= =?UTF-8?q?=E5=BC=95=E6=93=8E=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/avroom/activity/AVRoomActivity.java | 19 ++ .../app/avroom/fragment/BaseRoomFragment.kt | 10 + .../com/chwl/app/avroom/game/AppConfig.java | 6 +- .../chwl/app/game/core/BaseGameActivity.kt | 93 ++++++++ .../chwl/app/game/core/GameStateAbility.kt | 4 +- .../game/core/engine/GameEngineViewModel.kt | 206 ++++++++++++++++++ .../chwl/app/game/core/engine/GameSudFSMMG.kt | 48 ++++ .../app/game/core/engine/GameSudFSTAPP.kt | 37 ++++ .../core/engine/model/GameStateResponse.kt | 25 +++ .../core/engine/model/GameViewInfoModel.java | 47 ++++ .../game/data/{GameModel.kt => GameModel2.kt} | 20 +- .../chwl/app/game/data/bean/GameModeBean.kt | 2 + .../com/chwl/app/game/ui/buy/GameBuyDialog.kt | 110 +++++++++- .../com/chwl/app/game/ui/game/GameActivity.kt | 74 +++++-- .../app/game/ui/game/GameEngineViewModel.kt | 10 - .../com/chwl/app/game/ui/game/GameIntent.kt | 2 +- .../chwl/app/game/ui/game/GameViewModel.kt | 7 +- .../ui/game/input/GameMessageInputDialog.kt | 74 +++++++ .../game/widgets/bottom/GameBottomWidget.kt | 43 ++++ .../chwl/app/game/ui/home/GameHomeFragment.kt | 29 ++- .../app/game/ui/home/GameHomeViewModel.kt | 20 +- .../module_game/res/layout/game_activity.xml | 42 ++-- .../res/layout/game_bottom_widget.xml | 29 +++ .../res/layout/game_buy_dialog.xml | 6 +- .../res/layout/game_message_input_dialog.xml | 37 ++++ .../res/layout/game_queue_widget.xml | 37 ++-- app/src/module_game/res/values-ar/strings.xml | 2 + .../module_game/res/values-zh-rTW/strings.xml | 4 +- app/src/module_game/res/values/strings.xml | 2 + .../app/public_chat/core/ChatRoomClient.kt | 21 +- .../support/room/FrameLayoutRoomWidget.kt | 5 +- .../com/chwl/core/support/room/RoomView.kt | 7 + .../chwl/library/utils/json/JsonUtils.java | 7 +- 33 files changed, 977 insertions(+), 108 deletions(-) create mode 100644 app/src/module_game/java/com/chwl/app/game/core/BaseGameActivity.kt create mode 100644 app/src/module_game/java/com/chwl/app/game/core/engine/GameEngineViewModel.kt create mode 100644 app/src/module_game/java/com/chwl/app/game/core/engine/GameSudFSMMG.kt create mode 100644 app/src/module_game/java/com/chwl/app/game/core/engine/GameSudFSTAPP.kt create mode 100644 app/src/module_game/java/com/chwl/app/game/core/engine/model/GameStateResponse.kt create mode 100644 app/src/module_game/java/com/chwl/app/game/core/engine/model/GameViewInfoModel.java rename app/src/module_game/java/com/chwl/app/game/data/{GameModel.kt => GameModel2.kt} (65%) delete mode 100644 app/src/module_game/java/com/chwl/app/game/ui/game/GameEngineViewModel.kt create mode 100644 app/src/module_game/java/com/chwl/app/game/ui/game/input/GameMessageInputDialog.kt create mode 100644 app/src/module_game/java/com/chwl/app/game/ui/game/widgets/bottom/GameBottomWidget.kt create mode 100644 app/src/module_game/res/layout/game_bottom_widget.xml create mode 100644 app/src/module_game/res/layout/game_message_input_dialog.xml diff --git a/app/src/main/java/com/chwl/app/avroom/activity/AVRoomActivity.java b/app/src/main/java/com/chwl/app/avroom/activity/AVRoomActivity.java index 1c7188117..d8f6d8cf8 100644 --- a/app/src/main/java/com/chwl/app/avroom/activity/AVRoomActivity.java +++ b/app/src/main/java/com/chwl/app/avroom/activity/AVRoomActivity.java @@ -11,6 +11,7 @@ import static com.chwl.core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_ROOM_ import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; +import android.app.FragmentManager; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; @@ -33,6 +34,7 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LiveData; import androidx.viewpager2.widget.ViewPager2; import com.alibaba.fastjson.JSON; @@ -1357,18 +1359,35 @@ public class AVRoomActivity extends BaseMvpActivity getRoomContextLiveData() { + return AudioRoomContext.Companion.getContextLiveData(); + } + @NonNull @Override public LifecycleOwner getLifecycleOwner() { return this; } + @NonNull + @Override + public androidx.fragment.app.FragmentManager getViewFragmentManager() { + return getSupportFragmentManager(); + } + @Nullable @Override public RoomWidget findWidget(@NonNull String name) { diff --git a/app/src/main/java/com/chwl/app/avroom/fragment/BaseRoomFragment.kt b/app/src/main/java/com/chwl/app/avroom/fragment/BaseRoomFragment.kt index 6bbb4cfe0..e3982c216 100644 --- a/app/src/main/java/com/chwl/app/avroom/fragment/BaseRoomFragment.kt +++ b/app/src/main/java/com/chwl/app/avroom/fragment/BaseRoomFragment.kt @@ -23,8 +23,10 @@ import android.widget.TextView import androidx.annotation.CallSuper import androidx.core.content.ContextCompat import androidx.core.view.isVisible +import androidx.fragment.app.FragmentManager import androidx.fragment.app.activityViewModels import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData import androidx.lifecycle.lifecycleScope import androidx.lifecycle.withResumed import androidx.recyclerview.widget.RecyclerView @@ -1460,6 +1462,10 @@ open class BaseRoomFragment?> : return this } + override fun getViewFragmentManager(): FragmentManager { + return activity?.supportFragmentManager ?: childFragmentManager + } + override fun findWidget(name: String): RoomWidget? { return widgets[name] } @@ -1468,6 +1474,10 @@ open class BaseRoomFragment?> : return AudioRoomContext.get() } + override fun getRoomContextLiveData(): LiveData { + return AudioRoomContext.contextLiveData + } + open fun initWidget() { publicChatMessageWidget?.let { registerWidget(PublicChatRoomMessageWidget::class.java.simpleName, it) diff --git a/app/src/main/java/com/chwl/app/avroom/game/AppConfig.java b/app/src/main/java/com/chwl/app/avroom/game/AppConfig.java index 3d4941b1f..36d1bd0d6 100644 --- a/app/src/main/java/com/chwl/app/avroom/game/AppConfig.java +++ b/app/src/main/java/com/chwl/app/avroom/game/AppConfig.java @@ -9,8 +9,8 @@ import com.chwl.app.BuildConfig; public class AppConfig { - protected static final String APP_ID = "1578948593831571457"; - protected static final String APP_KEY = "J9lHOXvFWkAZiTfl4SK7IGt0wDnW3fWd"; - protected static boolean isTestEnv = BuildConfig.DEBUG; + public static final String APP_ID = "1578948593831571457"; + public static final String APP_KEY = "J9lHOXvFWkAZiTfl4SK7IGt0wDnW3fWd"; + public static boolean isTestEnv = BuildConfig.DEBUG; } diff --git a/app/src/module_game/java/com/chwl/app/game/core/BaseGameActivity.kt b/app/src/module_game/java/com/chwl/app/game/core/BaseGameActivity.kt new file mode 100644 index 000000000..1c85e5993 --- /dev/null +++ b/app/src/module_game/java/com/chwl/app/game/core/BaseGameActivity.kt @@ -0,0 +1,93 @@ +package com.chwl.app.game.core + +import android.app.Activity +import androidx.activity.viewModels +import androidx.fragment.app.FragmentManager +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData +import androidx.viewbinding.ViewBinding +import com.chwl.app.base.BaseViewBindingActivity +import com.chwl.app.game.core.engine.GameEngineViewModel +import com.chwl.app.game.ui.game.GameViewModel +import com.chwl.core.support.room.RoomContext +import com.chwl.core.support.room.RoomView +import com.chwl.core.support.room.RoomWidget +import com.netease.nim.uikit.StatusBarUtil + +abstract class BaseGameActivity : BaseViewBindingActivity(), RoomView { + + protected val viewModel: GameViewModel by viewModels() + protected val gameViewModel: GameEngineViewModel by viewModels() + protected var widgets: HashMap = HashMap() + + override fun init() { + initView() + initEvent() + initObserver() + initWidgets() + } + + protected open fun initView() { + } + + protected open fun initEvent() { + } + + protected open fun initObserver() { + } + + protected open fun initWidgets() { + } + + /** + * 注册组件 + */ + protected open fun registerWidget(name: String, widget: RoomWidget) { + widgets.put(name, widget) + widget.onStart(this) + } + + /** + * 取消注册组件 + */ + protected open fun unregisterWidgets() { + widgets.values.forEach { + it.onStop() + } + widgets.clear() + } + + override fun needSteepStateBar(): Boolean { + return true + } + + override fun setStatusBar() { + super.setStatusBar() + StatusBarUtil.transparencyBar(this) + } + + override fun getLifecycleOwner(): LifecycleOwner { + return this + } + + override fun getActivity(): Activity? { + return this + } + + override fun getRoomContext(): RoomContext? { + return viewModel.gameContextLiveData.value + } + + override fun getViewFragmentManager(): FragmentManager { + return supportFragmentManager + } + + override fun getRoomContextLiveData(): LiveData { + return viewModel.gameContextLiveData + } + + override fun findWidget(name: String): RoomWidget? { + return widgets[name] + } + +} \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/core/GameStateAbility.kt b/app/src/module_game/java/com/chwl/app/game/core/GameStateAbility.kt index 2e6090806..d85bfb9d2 100644 --- a/app/src/module_game/java/com/chwl/app/game/core/GameStateAbility.kt +++ b/app/src/module_game/java/com/chwl/app/game/core/GameStateAbility.kt @@ -1,6 +1,6 @@ package com.chwl.app.game.core -import com.chwl.app.game.data.GameModel +import com.chwl.app.game.data.GameModel2 import com.chwl.core.support.room.RoomAbility import kotlinx.coroutines.flow.MutableStateFlow @@ -10,7 +10,7 @@ class GameStateAbility : RoomAbility() { fun requestRoomInfo() { safeLaunch { - val info = GameModel.getGameRoomInfo() + val info = GameModel2.getGameRoomInfo() } } } \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/core/engine/GameEngineViewModel.kt b/app/src/module_game/java/com/chwl/app/game/core/engine/GameEngineViewModel.kt new file mode 100644 index 000000000..d8c2151fc --- /dev/null +++ b/app/src/module_game/java/com/chwl/app/game/core/engine/GameEngineViewModel.kt @@ -0,0 +1,206 @@ +package com.chwl.app.game.core.engine + +import android.annotation.SuppressLint +import android.app.Activity +import android.view.View +import android.view.ViewTreeObserver +import android.widget.FrameLayout +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.LifecycleOwner +import com.chwl.app.R +import com.chwl.app.avroom.game.AppConfig +import com.chwl.app.base.BaseViewModel +import com.chwl.app.game.core.engine.model.GameStateResponse +import com.chwl.app.game.core.engine.model.GameViewInfoModel +import com.chwl.app.game.core.engine.model.GameViewInfoModel.GameViewRectModel +import com.chwl.core.auth.AuthModel +import com.chwl.core.room.game.GameModel +import com.chwl.core.room.game.bean.GameCfg +import com.chwl.library.language.LanguageHelper +import com.chwl.library.utils.SingleToastUtil +import com.chwl.library.utils.json.JsonUtils +import com.example.lib_utils.log.ILog +import tech.sud.mgp.core.ISudFSMStateHandle +import tech.sud.mgp.core.ISudListenerInitSDK +import tech.sud.mgp.core.SudMGP +import java.lang.IllegalStateException + +@SuppressLint("StaticFieldLeak") +open class GameEngineViewModel : BaseViewModel(), ILog, LifecycleEventObserver { + + private var isRunning = true + + private val gameFSMMG = GameSudFSMMG(this) + + private val gameFSTAPP = GameSudFSTAPP(this) + + private var lifecycle: Lifecycle? = null + private var gameLayout: FrameLayout? = null + private var gameViewRect: GameViewRectModel = GameViewRectModel() + private var roomId: String = "" + + fun init(lifecycle: Lifecycle, gameLayout: FrameLayout) { + this.lifecycle = lifecycle + this.gameLayout = gameLayout + lifecycle.addObserver(this) + } + + fun loadGame(activity: Activity, roomId: String, gameId: Long) { + if (!this.isRunning) { + return + } + if (lifecycle == null) { + throw IllegalStateException("未初始化") + } + this.roomId = roomId + getGameCode({ + initSDK(activity, gameId, it) + }, { + toast(it.message) + }) + } + + private fun initSDK(activity: Activity, gameId: Long, code: String) { + SudMGP.initSDK( + activity, + getAppId(), + getAppKey(), + isTestEnv(), + object : ISudListenerInitSDK { + override fun onSuccess() { + loadGameSDK(activity, gameId, code) + } + + override fun onFailure(code: Int, errInfo: String) { + val msg = + activity.getString(R.string.game_failed_tips).format("$code-${errInfo}") + toast(msg) + } + }) + } + + private fun loadGameSDK(activity: Activity, gameId: Long, code: String) { + if (!isRunning) { + return + } + val userId = AuthModel.get().currentUid.toString() + gameFSTAPP.destroyMG() + val iSudFSTAPP = + SudMGP.loadMG(activity, userId, getRoomId(), code, gameId, getGameLanguage(), gameFSMMG) + gameFSTAPP.updateSudFSTAPP(iSudFSTAPP) + updateGameView(iSudFSTAPP.gameView) + } + + private fun updateGameView(view: View?) { + gameLayout?.removeAllViews() + if (view != null) { + gameLayout?.addView(view) + } + } + + fun setGameViewRect(rect: GameViewRectModel) { + this.gameViewRect = rect + } + + private fun getGameCode(onSuccess: (String) -> Unit, onFailed: (Throwable) -> Unit) { + addDisposable( + GameModel.getGameCode() + .subscribe({ + onSuccess.invoke(it.code) + }, { + onFailed.invoke(it) + }) + ) + } + + private fun toast(message: String?) { + if (!message.isNullOrEmpty()) { + SingleToastUtil.showToast(message) + } + } + + fun onExpireCode(handle: ISudFSMStateHandle) { + getGameCode({ + handle.success(GameStateResponse.success().toJson()) + gameFSTAPP.updateCode(it, null) + }, { + logE(it) + }) + } + + fun onGetGameCfg(handle: ISudFSMStateHandle) { + handle.success(JsonUtils.toJson(GameCfg())) + } + + fun onGetGameViewInfo(handle: ISudFSMStateHandle) { + val gameLayout = gameLayout + if (gameLayout == null) { + handle.failure("gameLayout is NULL") + return + } + val gameViewWidth = gameLayout.measuredWidth + val gameViewHeight = gameLayout.measuredHeight + if (gameViewWidth > 0 && gameViewHeight > 0) { + notifyGameViewInfo(handle, gameViewWidth, gameViewHeight) + return + } + gameLayout.viewTreeObserver.addOnGlobalLayoutListener(object : + ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + gameLayout.viewTreeObserver.removeOnGlobalLayoutListener(this) + notifyGameViewInfo(handle, gameLayout.measuredWidth, gameLayout.measuredHeight) + } + }) + } + + private fun notifyGameViewInfo(handle: ISudFSMStateHandle, width: Int, height: Int) { + val response = GameViewInfoModel() + response.ret_code = 0 + response.view_size.width = width + response.view_size.height = height + response.view_game_rect = gameViewRect + handle.success(JsonUtils.toJson(response)) + } + + override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { + if (event == Lifecycle.Event.ON_DESTROY) { + onViewDestroy() + } + } + + private fun getRoomId() = roomId + + private fun getAppId() = AppConfig.APP_ID + + private fun getAppKey() = AppConfig.APP_KEY + + private fun isTestEnv() = AppConfig.isTestEnv + + private fun getGameLanguage(): String { + return when (LanguageHelper.getCurrentLanguageType()) { + LanguageHelper.ZH -> { + "zh-TW" + } + + LanguageHelper.AR -> { + "ar-SA" + } + + else -> { + "en-US" + } + } + } + + override fun onCleared() { + super.onCleared() + onViewDestroy() + } + + private fun onViewDestroy() { + isRunning = false + lifecycle?.removeObserver(this) + lifecycle = null + } +} \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/core/engine/GameSudFSMMG.kt b/app/src/module_game/java/com/chwl/app/game/core/engine/GameSudFSMMG.kt new file mode 100644 index 000000000..8e2c32dca --- /dev/null +++ b/app/src/module_game/java/com/chwl/app/game/core/engine/GameSudFSMMG.kt @@ -0,0 +1,48 @@ +package com.chwl.app.game.core.engine + +import com.chwl.app.game.core.engine.model.GameStateResponse +import com.example.lib_utils.log.ILog +import tech.sud.mgp.core.ISudFSMMG +import tech.sud.mgp.core.ISudFSMStateHandle + +class GameSudFSMMG(private val engineViewModel: GameEngineViewModel) : ISudFSMMG, ILog { + override fun onGameLog(p0: String?) { + if (p0 != null) { + logD(p0) + } + } + + override fun onGameLoadingProgress(p0: Int, p1: Int, p2: Int) { + } + + override fun onGameStarted() { + } + + override fun onGameDestroyed() { + } + + override fun onExpireCode(p0: ISudFSMStateHandle, p1: String?) { + engineViewModel.onExpireCode(p0) + } + + override fun onGetGameViewInfo(p0: ISudFSMStateHandle, p1: String?) { + engineViewModel.onGetGameViewInfo(p0) + } + + override fun onGetGameCfg(p0: ISudFSMStateHandle, p1: String?) { + engineViewModel.onGetGameCfg(p0) + } + + override fun onGameStateChange(p0: ISudFSMStateHandle, p1: String?, p2: String?) { + p0.success(GameStateResponse.success().toJson()) + } + + override fun onPlayerStateChange( + p0: ISudFSMStateHandle, + p1: String?, + p2: String?, + p3: String? + ) { + p0.success(GameStateResponse.success().toJson()) + } +} \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/core/engine/GameSudFSTAPP.kt b/app/src/module_game/java/com/chwl/app/game/core/engine/GameSudFSTAPP.kt new file mode 100644 index 000000000..806a62c57 --- /dev/null +++ b/app/src/module_game/java/com/chwl/app/game/core/engine/GameSudFSTAPP.kt @@ -0,0 +1,37 @@ +package com.chwl.app.game.core.engine + +import tech.sud.mgp.core.ISudFSTAPP +import tech.sud.mgp.core.ISudListenerNotifyStateChange + +class GameSudFSTAPP(private val engineViewModel: GameEngineViewModel) { + private var sudFSTAPP: ISudFSTAPP? = null + + fun updateSudFSTAPP(iSudFSTAPP: ISudFSTAPP) { + this.sudFSTAPP = iSudFSTAPP + } + + fun updateCode(code: String, listener: ISudListenerNotifyStateChange?) { + this.sudFSTAPP?.updateCode(code, listener) + } + + fun startMG() { + this.sudFSTAPP?.startMG() + } + + fun playMG() { + this.sudFSTAPP?.playMG() + } + + fun pauseMG() { + this.sudFSTAPP?.pauseMG() + } + + fun stopMG() { + this.sudFSTAPP?.stopMG() + } + + fun destroyMG() { + sudFSTAPP?.destroyMG() + sudFSTAPP = null + } +} \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/core/engine/model/GameStateResponse.kt b/app/src/module_game/java/com/chwl/app/game/core/engine/model/GameStateResponse.kt new file mode 100644 index 000000000..0e7b91391 --- /dev/null +++ b/app/src/module_game/java/com/chwl/app/game/core/engine/model/GameStateResponse.kt @@ -0,0 +1,25 @@ +package com.chwl.app.game.core.engine.model + +import androidx.annotation.Keep +import com.chwl.library.utils.json.JsonUtils +import java.io.Serializable + +@Keep +data class GameStateResponse( + var ret_code: Int = CODE_SUCCESS, // 返回码 + var ret_msg: String? = null // 返回消息 +) : Serializable { + + fun toJson(): String { + return JsonUtils.toJson(this) + } + + // 返回码,成功 + companion object { + val CODE_SUCCESS = 0 + + fun success(): GameStateResponse { + return GameStateResponse(CODE_SUCCESS, "success") + } + } +} \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/core/engine/model/GameViewInfoModel.java b/app/src/module_game/java/com/chwl/app/game/core/engine/model/GameViewInfoModel.java new file mode 100644 index 000000000..236012c5e --- /dev/null +++ b/app/src/module_game/java/com/chwl/app/game/core/engine/model/GameViewInfoModel.java @@ -0,0 +1,47 @@ +/* + * Copyright © Sud.Tech + * https://sud.tech + */ + +package com.chwl.app.game.core.engine.model; + +import androidx.annotation.Keep; + +/** + * 游戏视图 + * 参考文档:https://docs.sud.tech/zh-CN/app/Client/API/ISudFSMMG/onGetGameViewInfo.html + */ +@Keep +public class GameViewInfoModel { + // 返回码 + public int ret_code; + + // 返回消息 + public String ret_msg; + + // 游戏View的大小 + public GameViewSizeModel view_size = new GameViewSizeModel(); + + // 游戏安全操作区域 + public GameViewRectModel view_game_rect = new GameViewRectModel(); + @Keep + public static class GameViewSizeModel { + // 游戏View的宽 (单位像素) + public int width; + + // 游戏View的高 (单位像素) + public int height; + } + @Keep + public static class GameViewRectModel { + // 相对于view_size左边框偏移(单位像素) + public int left; + // 相对于view_size上边框偏移(单位像素) + public int top; + // 相对于view_size右边框偏移(单位像素) + public int right; + // 相对于view_size下边框偏移(单位像素) + public int bottom; + } + +} diff --git a/app/src/module_game/java/com/chwl/app/game/data/GameModel.kt b/app/src/module_game/java/com/chwl/app/game/data/GameModel2.kt similarity index 65% rename from app/src/module_game/java/com/chwl/app/game/data/GameModel.kt rename to app/src/module_game/java/com/chwl/app/game/data/GameModel2.kt index e9cfebe9a..d3cbd474a 100644 --- a/app/src/module_game/java/com/chwl/app/game/data/GameModel.kt +++ b/app/src/module_game/java/com/chwl/app/game/data/GameModel2.kt @@ -7,9 +7,12 @@ import com.chwl.core.bean.response.ServiceResult import com.chwl.core.home.bean.* import com.chwl.core.utils.net.launchRequest import com.chwl.library.net.rxnet.RxNet +import retrofit2.http.Field +import retrofit2.http.FormUrlEncoded import retrofit2.http.GET +import retrofit2.http.POST -object GameModel : BaseModel() { +object GameModel2 : BaseModel() { private val api = RxNet.create(Api::class.java) @@ -23,6 +26,11 @@ object GameModel : BaseModel() { api.getGameRoomInfo() } + suspend fun startGame(gameId: String, gameMode: Int): String? = + launchRequest { + api.startGame(gameId, gameMode) + } + private interface Api { /** * 游戏房信息 @@ -37,6 +45,16 @@ object GameModel : BaseModel() { */ @GET("miniGame/nav/config") suspend fun getHomeGameConfig(): ServiceResult + + /** + * 开始游戏 + */ + @POST("/miniGame/nav/start") + @FormUrlEncoded + suspend fun startGame( + @Field("mgId") mgId: String, + @Field("gameMode") gameMode: Int + ): ServiceResult } } \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/data/bean/GameModeBean.kt b/app/src/module_game/java/com/chwl/app/game/data/bean/GameModeBean.kt index b98f19274..55dd8877f 100644 --- a/app/src/module_game/java/com/chwl/app/game/data/bean/GameModeBean.kt +++ b/app/src/module_game/java/com/chwl/app/game/data/bean/GameModeBean.kt @@ -9,4 +9,6 @@ class GameModeBean : Serializable { val modeIcon: String? = null val gameMode: Int? = null val scores: List? = null + val ruleUrl: String? = null + val modeName: String? = null } \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/ui/buy/GameBuyDialog.kt b/app/src/module_game/java/com/chwl/app/game/ui/buy/GameBuyDialog.kt index 3e7807077..8577bf6d0 100644 --- a/app/src/module_game/java/com/chwl/app/game/ui/buy/GameBuyDialog.kt +++ b/app/src/module_game/java/com/chwl/app/game/ui/buy/GameBuyDialog.kt @@ -1,9 +1,115 @@ package com.chwl.app.game.ui.buy +import android.app.Dialog +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.chwl.app.R +import com.chwl.app.common.widget.dialog.DialogManager import com.chwl.app.databinding.GameBuyDialogBinding -import com.chwl.library.common.base.BaseDialogFragment +import com.chwl.app.game.data.bean.GameConfigBean +import com.chwl.app.game.data.bean.GameModeBean +import com.chwl.app.game.ui.game.GameActivity +import com.chwl.app.game.ui.game.GameIntent +import com.chwl.app.game.ui.home.GameHomeViewModel +import com.chwl.app.ui.pay.ChargeActivity +import com.chwl.app.ui.webview.DialogWebViewActivity +import com.chwl.core.utils.net.BalanceNotEnoughExeption +import com.chwl.library.utils.ResUtil +import com.chwl.library.utils.SingleToastUtil +import com.example.lib_utils.ktx.singleClick +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch -class GameBuyDialog : BaseDialogFragment() { +class GameBuyDialog(private val gameConfig: GameConfigBean, private val gameMode: GameModeBean) : + BottomSheetDialogFragment() { + private var binding: GameBuyDialogBinding? = null + private val viewModel: GameHomeViewModel by activityViewModels() + + private var dialogManager: DialogManager? = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + dialogManager = DialogManager(requireContext()) + initView() + initObserver() + } + + private fun initView() { + binding?.tvTitle?.text = context?.getString(R.string.game_ticket_format, gameMode.modeName) + binding?.tvCoins?.text = gameMode.ticket?.toString() + binding?.ivHelp?.singleClick { + DialogWebViewActivity.start(context, gameMode.ruleUrl ?: "", true) + } + binding?.tvStart?.singleClick { + dialogManager?.showProgressDialog(requireContext()) + viewModel.startGame(gameConfig.mgIdStr ?: "", gameMode.gameMode ?: -1) + } + } + + private fun initObserver() { + viewLifecycleOwner.lifecycleScope.launch { + lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.startGameFlow.collectLatest { + dialogManager?.dismissDialog() + if (it.isSuccess) { + dismissAllowingStateLoss() + val intent = + GameIntent(1, gameConfig.mgId ?: 0L, gameMode.gameMode ?: -1) + GameActivity.start(requireContext(), intent) + } else { + if (it.code == BalanceNotEnoughExeption.code) { + showBalanceNotEnoughDialog() + } else { + it.message?.let { msg -> + SingleToastUtil.showToast(msg) + } + } + } + } + } + } + } + + private fun showBalanceNotEnoughDialog() { + dialogManager?.showOkCancelDialog( + ResUtil.getString(R.string.star_send_gift_balance), + ResUtil.getString(R.string.treasure_to_charge) + ) { + ChargeActivity.start(context) + } + } + + override fun onDestroyView() { + super.onDestroyView() + dialogManager?.dismissDialog() + dialogManager = null + } + + override fun getTheme(): Int { + return R.style.ErbanBottomSheetDialog + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = GameBuyDialogBinding.inflate(LayoutInflater.from(context)) + return binding?.root + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + return super.onCreateDialog(savedInstanceState).apply { + this.setCanceledOnTouchOutside(true) + } + } } \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/ui/game/GameActivity.kt b/app/src/module_game/java/com/chwl/app/game/ui/game/GameActivity.kt index 0625c6fbb..63b345926 100644 --- a/app/src/module_game/java/com/chwl/app/game/ui/game/GameActivity.kt +++ b/app/src/module_game/java/com/chwl/app/game/ui/game/GameActivity.kt @@ -2,17 +2,19 @@ package com.chwl.app.game.ui.game import android.content.Context import android.content.Intent -import androidx.activity.viewModels import com.chwl.app.R -import com.chwl.app.base.BaseViewBindingActivity +import com.chwl.app.common.widget.dialog.DialogManager.OkCancelDialogListener import com.chwl.app.databinding.GameActivityBinding +import com.chwl.app.game.core.BaseGameActivity +import com.chwl.app.game.core.engine.model.GameViewInfoModel.GameViewRectModel +import com.chwl.app.game.ui.game.widgets.bottom.GameBottomWidget +import com.chwl.app.game.ui.game.widgets.message.GameMessageWidget +import com.chwl.app.game.ui.game.widgets.queue.GameQueueWidget +import com.chwl.core.support.room.RoomView import com.example.lib_utils.ktx.singleClick -import com.netease.nim.uikit.StatusBarUtil +import com.example.lib_utils.log.ILog -class GameActivity : BaseViewBindingActivity() { - - private val viewModel: GameViewModel by viewModels() - private val gameViewModel: GameEngineViewModel by viewModels() +class GameActivity : BaseGameActivity(), RoomView, ILog { companion object { fun start(context: Context, intent: GameIntent) { @@ -29,36 +31,60 @@ class GameActivity : BaseViewBindingActivity() { finish() return } - initView() - initEvent() - initObserver() + super.init() viewModel.init(intentData) + initGameEngine(intentData) } - private fun initView() { - + private fun initGameEngine(intentData: GameIntent) { + gameViewModel.init(lifecycle, binding.layoutGame) + binding.spaceGameRect.post { + val rect = GameViewRectModel().apply { + top = binding.spaceGameRect.top + bottom = binding.root.height - binding.spaceGameRect.bottom + } + logD("initGameEngine() height:${binding.root.height}") + logD("initGameEngine() top:${rect.top} bottom:${rect.bottom}") + gameViewModel.setGameViewRect(rect) + gameViewModel.loadGame(this, intentData.roomId.toString(), intentData.gameId) + } } - private fun initEvent() { + override fun initEvent() { + super.initEvent() binding.ivClose.singleClick { - toast("close") - finish() + onBackPressed() } } - private fun initObserver() { - gameViewModel.gameViewLiveData.observe(this) { - - } + override fun initObserver() { + super.initObserver() } - override fun needSteepStateBar(): Boolean { - return true + override fun initWidgets() { + super.initWidgets() + registerWidget(GameMessageWidget::class.java.simpleName, binding.messageWidget) + registerWidget(GameQueueWidget::class.java.simpleName, binding.queueWidget) + registerWidget(GameBottomWidget::class.java.simpleName, binding.bottomWidget) } - override fun setStatusBar() { - super.setStatusBar() - StatusBarUtil.transparencyBar(this) + override fun onBackPressed() { +// super.onBackPressed() + showExitTips() } + private fun showExitTips() { + dialogManager.showOkCancelDialog( + getString(R.string.game_exit_tips), + getString(R.string.layout_dialog_game_exit_04), + getString(R.string.exit_text), object : OkCancelDialogListener { + override fun onOk() { + } + + override fun onCancel() { + super.onCancel() + this@GameActivity.finish() + } + }) + } } \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/ui/game/GameEngineViewModel.kt b/app/src/module_game/java/com/chwl/app/game/ui/game/GameEngineViewModel.kt deleted file mode 100644 index ba0655415..000000000 --- a/app/src/module_game/java/com/chwl/app/game/ui/game/GameEngineViewModel.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.chwl.app.game.ui.game - -import android.view.View -import androidx.lifecycle.MutableLiveData -import com.chwl.app.base.BaseViewModel - -class GameEngineViewModel : BaseViewModel() { - - val gameViewLiveData = MutableLiveData() -} \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/ui/game/GameIntent.kt b/app/src/module_game/java/com/chwl/app/game/ui/game/GameIntent.kt index 25bfe3c02..57ab66096 100644 --- a/app/src/module_game/java/com/chwl/app/game/ui/game/GameIntent.kt +++ b/app/src/module_game/java/com/chwl/app/game/ui/game/GameIntent.kt @@ -4,5 +4,5 @@ import androidx.annotation.Keep import java.io.Serializable @Keep -data class GameIntent(val roomId: Long, val gameId: String, val gameMode: String) : Serializable { +data class GameIntent(val roomId: Long, val gameId: Long, val gameMode: Int) : Serializable { } \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/ui/game/GameViewModel.kt b/app/src/module_game/java/com/chwl/app/game/ui/game/GameViewModel.kt index 88b2629a2..b922f1eca 100644 --- a/app/src/module_game/java/com/chwl/app/game/ui/game/GameViewModel.kt +++ b/app/src/module_game/java/com/chwl/app/game/ui/game/GameViewModel.kt @@ -1,13 +1,16 @@ package com.chwl.app.game.ui.game +import androidx.lifecycle.MutableLiveData import com.chwl.app.base.BaseViewModel import com.chwl.app.game.core.GameContext +import com.chwl.core.support.room.RoomContext class GameViewModel : BaseViewModel() { - private var roomContext: GameContext? = null + val gameContextLiveData = MutableLiveData() fun init(intent: GameIntent) { - roomContext = GameContext(intent.roomId) + val gameContext = GameContext(intent.roomId) + gameContextLiveData.value = gameContext } } \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/ui/game/input/GameMessageInputDialog.kt b/app/src/module_game/java/com/chwl/app/game/ui/game/input/GameMessageInputDialog.kt new file mode 100644 index 000000000..8dcb83dba --- /dev/null +++ b/app/src/module_game/java/com/chwl/app/game/ui/game/input/GameMessageInputDialog.kt @@ -0,0 +1,74 @@ +package com.chwl.app.game.ui.game.input + +import android.app.Dialog +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.chwl.app.R +import com.chwl.app.common.widget.dialog.DialogManager +import com.chwl.app.databinding.GameMessageInputDialogBinding +import com.chwl.library.utils.SingleToastUtil +import com.chwl.library.utils.keyboard.KeyboardUtil +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import kotlinx.coroutines.launch + +class GameMessageInputDialog : + BottomSheetDialogFragment() { + + private var binding: GameMessageInputDialogBinding? = null + + private var dialogManager: DialogManager? = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + dialogManager = DialogManager(requireContext()) + initView() + initObserver() + } + + private fun initView() { + binding?.inputEdit?.let { + KeyboardUtil.showKeyboardInDialog(this.dialog, it) + } + binding?.inputSend?.setOnClickListener { + SingleToastUtil.showToast("SEND") + } + } + + private fun initObserver() { + viewLifecycleOwner.lifecycleScope.launch { + lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { + + } + } + } + + override fun onDestroyView() { + super.onDestroyView() + dialogManager?.dismissDialog() + dialogManager = null + } + + override fun getTheme(): Int { + return R.style.ErbanBottomSheetDialogDimFalse + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = GameMessageInputDialogBinding.inflate(LayoutInflater.from(context)) + return binding?.root + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + return super.onCreateDialog(savedInstanceState).apply { + this.setCanceledOnTouchOutside(true) + } + } +} \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/ui/game/widgets/bottom/GameBottomWidget.kt b/app/src/module_game/java/com/chwl/app/game/ui/game/widgets/bottom/GameBottomWidget.kt new file mode 100644 index 000000000..70e72bdbf --- /dev/null +++ b/app/src/module_game/java/com/chwl/app/game/ui/game/widgets/bottom/GameBottomWidget.kt @@ -0,0 +1,43 @@ +package com.chwl.app.game.ui.game.widgets.bottom + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import androidx.databinding.DataBindingUtil +import com.chwl.app.R +import com.chwl.app.databinding.GameBottomWidgetBinding +import com.chwl.app.game.ui.game.input.GameMessageInputDialog +import com.chwl.core.support.room.FrameLayoutRoomWidget + +class GameBottomWidget : FrameLayoutRoomWidget { + + private val binding: GameBottomWidgetBinding = + DataBindingUtil.inflate( + LayoutInflater.from( + context + ), R.layout.game_bottom_widget, this, true + ) + + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) + + constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, + defStyleRes: Int + ) : super(context, attrs, defStyleAttr, defStyleRes) + + init { + binding.tvInput.setOnClickListener { + roomView?.let { + GameMessageInputDialog().show(it.getViewFragmentManager(), "MESSAGE_INPUT") + } + } + } +} \ No newline at end of file diff --git a/app/src/module_game/java/com/chwl/app/game/ui/home/GameHomeFragment.kt b/app/src/module_game/java/com/chwl/app/game/ui/home/GameHomeFragment.kt index bc4c76e61..dbca790cd 100644 --- a/app/src/module_game/java/com/chwl/app/game/ui/home/GameHomeFragment.kt +++ b/app/src/module_game/java/com/chwl/app/game/ui/home/GameHomeFragment.kt @@ -6,8 +6,7 @@ import com.chwl.app.base.BaseViewBindingFragment import com.chwl.app.databinding.GameHomeFragmentBinding import com.chwl.app.game.data.bean.GameConfigBean import com.chwl.app.game.ui.buy.GameBuyDialog -import com.chwl.app.game.ui.game.GameActivity -import com.chwl.app.game.ui.game.GameIntent +import com.chwl.app.support.FragmentVisibleStateHelper import com.chwl.app.ui.pay.ChargeActivity import com.chwl.app.ui.utils.load import com.chwl.app.ui.utils.loadAvatar @@ -32,6 +31,9 @@ class GameHomeFragment : BaseViewBindingFragment(), Mai initView() initEvent() initObserver() + FragmentVisibleStateHelper(this) { + onVisibleChanged(it) + } PayModel.get().refreshWalletInfo(true) refreshWalletInfo() refreshUserInfo() @@ -54,16 +56,22 @@ class GameHomeFragment : BaseViewBindingFragment(), Mai } binding.ivRank.singleClick { toast("RANK") - GameActivity.start(requireContext(), GameIntent(111,"2","2")) } - adapter.setOnItemClickListener { adapter, view, position -> - toast("$position") - GameBuyDialog().show(childFragmentManager,"GAME_BUY") + adapter.setOnItemClickListener { _, view, position -> + val config = viewModel.gameConfigLiveData.value?.data + val gameMode = adapter.getItem(position) + if (config == null || gameMode == null) { + return@setOnItemClickListener + } + GameBuyDialog(config, gameMode).show(childFragmentManager, "GAME_BUY") } } private fun initObserver() { viewModel.gameConfigLiveData.observe(this) { + if (it == null) { + return@observe + } val configData = it.data if (it.isSuccess && configData != null) { loadGameInfo(configData) @@ -71,7 +79,14 @@ class GameHomeFragment : BaseViewBindingFragment(), Mai toast(it.message) } } - viewModel.getGameList() + } + + private fun onVisibleChanged(isVisible: Boolean) { + if (isVisible) { + if (viewModel.gameConfigLiveData.value?.isSuccess != true) { + viewModel.getGameList() + } + } } private fun loadGameInfo(config: GameConfigBean) { diff --git a/app/src/module_game/java/com/chwl/app/game/ui/home/GameHomeViewModel.kt b/app/src/module_game/java/com/chwl/app/game/ui/home/GameHomeViewModel.kt index c7da8fcee..9cd3420f4 100644 --- a/app/src/module_game/java/com/chwl/app/game/ui/home/GameHomeViewModel.kt +++ b/app/src/module_game/java/com/chwl/app/game/ui/home/GameHomeViewModel.kt @@ -2,19 +2,33 @@ package com.chwl.app.game.ui.home import androidx.lifecycle.MutableLiveData import com.chwl.app.base.BaseViewModel -import com.chwl.app.game.data.GameModel +import com.chwl.app.game.data.GameModel2 import com.chwl.app.game.data.bean.GameConfigBean import com.chwl.core.bean.response.BeanResult +import com.chwl.core.pay.PayModel +import kotlinx.coroutines.flow.MutableSharedFlow class GameHomeViewModel : BaseViewModel() { - val gameConfigLiveData = MutableLiveData>() + val gameConfigLiveData = MutableLiveData?>() + + val startGameFlow = MutableSharedFlow>() fun getGameList() { safeLaunch(onError = { gameConfigLiveData.postValue(BeanResult.Companion.failed(it)) }) { - val configBean = GameModel.getHomeGameConfig() + val configBean = GameModel2.getHomeGameConfig() gameConfigLiveData.postValue(BeanResult.success(configBean)) } } + + fun startGame(gameId: String, gameMode: Int) { + safeLaunch(onError = { + startGameFlow.emit(BeanResult.Companion.failed(it)) + }) { + PayModel.get().refreshWalletInfo(true) + val value = GameModel2.startGame(gameId, gameMode) + startGameFlow.emit(BeanResult.success(value)) + } + } } \ No newline at end of file diff --git a/app/src/module_game/res/layout/game_activity.xml b/app/src/module_game/res/layout/game_activity.xml index 8e510b74a..713e08b89 100644 --- a/app/src/module_game/res/layout/game_activity.xml +++ b/app/src/module_game/res/layout/game_activity.xml @@ -49,18 +49,19 @@ android:id="@+id/queue_widget" android:layout_width="match_parent" android:layout_height="wrap_content" - app:layout_constraintTop_toBottomOf="@id/space_title_bar" /> + android:layout_marginTop="@dimen/dp_13" + app:layout_constraintTop_toTopOf="@id/space_title_bar" /> - - + android:layout_height="wrap_content" + app:layout_constraintBottom_toBottomOf="parent" /> - - - + \ No newline at end of file diff --git a/app/src/module_game/res/layout/game_bottom_widget.xml b/app/src/module_game/res/layout/game_bottom_widget.xml new file mode 100644 index 000000000..894bd2f5f --- /dev/null +++ b/app/src/module_game/res/layout/game_bottom_widget.xml @@ -0,0 +1,29 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_game/res/layout/game_buy_dialog.xml b/app/src/module_game/res/layout/game_buy_dialog.xml index 2a381eddc..d9865d019 100644 --- a/app/src/module_game/res/layout/game_buy_dialog.xml +++ b/app/src/module_game/res/layout/game_buy_dialog.xml @@ -25,12 +25,13 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.13" - tools:text="Name" /> + tools:text="@string/game_ticket_format" /> + + + + + + + + + + + diff --git a/app/src/module_game/res/layout/game_queue_widget.xml b/app/src/module_game/res/layout/game_queue_widget.xml index 50ecaecb5..12e496116 100644 --- a/app/src/module_game/res/layout/game_queue_widget.xml +++ b/app/src/module_game/res/layout/game_queue_widget.xml @@ -18,6 +18,20 @@ app:layout_constraintTop_toTopOf="parent" tools:text="@string/matchmaking" /> + + + app:layout_constraintWidth_percent="0.152" /> - - - + app:layout_constraintWidth_percent="0.152" /> \ No newline at end of file diff --git a/app/src/module_game/res/values-ar/strings.xml b/app/src/module_game/res/values-ar/strings.xml index 5510e3eec..1a7db2b34 100644 --- a/app/src/module_game/res/values-ar/strings.xml +++ b/app/src/module_game/res/values-ar/strings.xml @@ -3,4 +3,6 @@ 匹配中 獲勝獎勵%s金幣 开始 + 入场费(%s) + 遊戲已經開始,退出房間將默認遊戲失敗,確認退出房間? \ No newline at end of file diff --git a/app/src/module_game/res/values-zh-rTW/strings.xml b/app/src/module_game/res/values-zh-rTW/strings.xml index 4cb8080af..aa13bfd44 100644 --- a/app/src/module_game/res/values-zh-rTW/strings.xml +++ b/app/src/module_game/res/values-zh-rTW/strings.xml @@ -3,5 +3,7 @@ 匹配中 獲勝獎勵%s金幣 - 开始 + 開始 + 入场费(%s) + 遊戲已經開始,退出房間將默認遊戲失敗,確認退出房間? \ No newline at end of file diff --git a/app/src/module_game/res/values/strings.xml b/app/src/module_game/res/values/strings.xml index 5510e3eec..1a7db2b34 100644 --- a/app/src/module_game/res/values/strings.xml +++ b/app/src/module_game/res/values/strings.xml @@ -3,4 +3,6 @@ 匹配中 獲勝獎勵%s金幣 开始 + 入场费(%s) + 遊戲已經開始,退出房間將默認遊戲失敗,確認退出房間? \ No newline at end of file diff --git a/app/src/module_public_chat/java/com/chwl/app/public_chat/core/ChatRoomClient.kt b/app/src/module_public_chat/java/com/chwl/app/public_chat/core/ChatRoomClient.kt index 67e15a3d0..eca5f9b5d 100644 --- a/app/src/module_public_chat/java/com/chwl/app/public_chat/core/ChatRoomClient.kt +++ b/app/src/module_public_chat/java/com/chwl/app/public_chat/core/ChatRoomClient.kt @@ -27,9 +27,15 @@ import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import io.reactivex.subjects.PublishSubject +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch +import java.lang.Exception open class ChatRoomClient(val sessionId: String) : ICleared, ILog { + private val clientScope = MainScope() private var isLogin = false private var loginData: EnterChatRoomResultData? = null private val messagePublishSubject: PublishSubject> = @@ -39,6 +45,7 @@ open class ChatRoomClient(val sessionId: String) : ICleared, ILog { .toObservable() .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) + val stateFlow = MutableStateFlow(StatusCode.INVALID) private val receiveMessageObserver = Observer> { val list = it.filter { item -> @@ -55,6 +62,9 @@ open class ChatRoomClient(val sessionId: String) : ICleared, ILog { } else { isLogin = false } + clientScope.launch { + stateFlow.emit(it.status) + } } init { @@ -126,8 +136,8 @@ open class ChatRoomClient(val sessionId: String) : ICleared, ILog { }.compose(RxHelper.handleSchedulers()) } - fun exitChatRoom(sessionId: String) { - logD("exitChatRoom() sessionId:${sessionId}") + fun exitChatRoom() { + logD("exitChatRoom()") NIMChatRoomSDK.getChatRoomService().exitChatRoom(sessionId) } @@ -208,6 +218,11 @@ open class ChatRoomClient(val sessionId: String) : ICleared, ILog { ChatRoomClientManager.onClientCleared(this) registerReceiveMessage(false) registerOnlineStatus(false) - exitChatRoom(sessionId) + exitChatRoom() + try { + clientScope.cancel() + } catch (e: Exception) { + e.printStackTrace() + } } } \ No newline at end of file diff --git a/core/src/main/java/com/chwl/core/support/room/FrameLayoutRoomWidget.kt b/core/src/main/java/com/chwl/core/support/room/FrameLayoutRoomWidget.kt index 8836697d8..f13f7839e 100644 --- a/core/src/main/java/com/chwl/core/support/room/FrameLayoutRoomWidget.kt +++ b/core/src/main/java/com/chwl/core/support/room/FrameLayoutRoomWidget.kt @@ -5,7 +5,6 @@ import android.util.AttributeSet import android.widget.FrameLayout import androidx.annotation.CallSuper import androidx.lifecycle.Observer -import androidx.lifecycle.viewModelScope import com.chwl.core.utils.extension.toast import com.chwl.library.net.rxnet.exception.ExceptionHandle import io.reactivex.disposables.CompositeDisposable @@ -64,13 +63,13 @@ abstract class FrameLayoutRoomWidget : FrameLayout, RoomWidget { @CallSuper override fun onStart(roomView: RoomView) { this.roomView = roomView - AudioRoomContext.contextLiveData.observeForever(contextObserver) + roomView.getRoomContextLiveData().observeForever(contextObserver) } @CallSuper override fun onStop() { // 注销监听 - AudioRoomContext.contextLiveData.removeObserver(contextObserver) + roomView?.getRoomContextLiveData()?.removeObserver(contextObserver) // 解绑 onUnbindContext() this.roomView = null diff --git a/core/src/main/java/com/chwl/core/support/room/RoomView.kt b/core/src/main/java/com/chwl/core/support/room/RoomView.kt index eea2b27b9..e5ae730a7 100644 --- a/core/src/main/java/com/chwl/core/support/room/RoomView.kt +++ b/core/src/main/java/com/chwl/core/support/room/RoomView.kt @@ -1,7 +1,10 @@ package com.chwl.core.support.room import android.app.Activity +import androidx.fragment.app.FragmentManager import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData +import androidx.room.Room /** * Created by Max on 2023/10/26 15:05 @@ -13,6 +16,10 @@ interface RoomView { fun getActivity(): Activity? + fun getViewFragmentManager(): FragmentManager + + fun getRoomContextLiveData(): LiveData + /** * 获取房间上下文 */ diff --git a/library/src/main/java/com/chwl/library/utils/json/JsonUtils.java b/library/src/main/java/com/chwl/library/utils/json/JsonUtils.java index f84c404b8..ca7f4d90d 100644 --- a/library/src/main/java/com/chwl/library/utils/json/JsonUtils.java +++ b/library/src/main/java/com/chwl/library/utils/json/JsonUtils.java @@ -7,11 +7,16 @@ import com.google.gson.Gson; */ public class JsonUtils { + public static Gson gson; + public static String toJson(Object object) { + if (gson == null) { + gson = new Gson(); + } String result = null; try { if (object != null) { - result = new Gson().toJson(object); + result = gson.toJson(object); } } catch (Exception ex) { ex.printStackTrace();