需要添加直播接口

This commit is contained in:
cbb
2026-01-12 17:52:15 +08:00
parent 83fec2617c
commit 13af9eb303
281 changed files with 313157 additions and 104 deletions

View File

@@ -0,0 +1,63 @@
package uts.sdk.modules.atomicx.kotlin
import android.graphics.BitmapFactory
import android.text.TextUtils
import com.google.gson.Gson
import com.tencent.cloud.tuikit.engine.room.TUIRoomDefine
import com.tencent.cloud.tuikit.engine.room.TUIRoomEngine
private const val TAG = "UTS-CallExperimentalApi: "
object ExperimentalApiInvoker {
private val gson = Gson()
// const data = { "api": "setTestEnvironment", "params": { "enableRoomTestEnv": true } } // 设置 IM 测试环境
// const data = { "api": "setLocalVideoMuteImage", "params": { "image": "filePath" } } // 设置垫片
// const giftData = { "api": "setCurrentLanguage", "params": { "language" : "en"} } // 礼物功能设置语言
public fun callExperimentalAPI(
jsonString: String,
callback: TUIRoomDefine.ExperimentalAPIResponseCallback?,
) {
val requestData: RequestData = gson.fromJson(jsonString, RequestData::class.java)
if (requestData.api == "setLocalVideoMuteImage") {
setLocalVideoMuteImage(requestData, callback)
return
}
TUIRoomEngine.sharedInstance().callExperimentalAPI(jsonString) { jsonData ->
// Logger.i(TAG + "${requestData.api}: onResponse: $jsonData")
callback?.onResponse(jsonData)
}
}
private fun setLocalVideoMuteImage(
data: RequestData,
callback: TUIRoomDefine.ExperimentalAPIResponseCallback?,
) {
try {
val filePath = data.params?.image
if (TextUtils.isEmpty(filePath)) {
// Logger.e(TAG + "setLocalVideoMuteImage: filePath is empty")
callback?.onResponse("setLocalVideoMuteImage: filePath is empty")
return
}
val bitmap = BitmapFactory.decodeFile(filePath)
TUIRoomEngine.sharedInstance().setLocalVideoMuteImage(bitmap)
} catch (e: Exception) {
// Logger.e(TAG + "setLocalVideoMuteImage: ${e.message}")
callback?.onResponse("setLocalVideoMuteImage: unexpected error")
}
}
}
data class RequestData(
val api: String,
val params: Params?,
)
// 不要修改数据,每个数据对应一个关键字
data class Params(
val image: String?,
)

View File

@@ -0,0 +1,82 @@
package uts.sdk.modules.atomicx.kotlin
import android.content.Context
import android.graphics.Outline
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewOutlineProvider
import androidx.constraintlayout.widget.ConstraintLayout
import io.dcloud.uts.console
import io.trtc.tuikit.atomicxcore.api.view.CoreViewType
import io.trtc.tuikit.atomicxcore.api.view.LiveCoreView
private const val TAG = "UTS-LiveRenderView: "
class LiveRenderView(context: Context, attrs: AttributeSet? = null) : ConstraintLayout(context, attrs) {
private var cornerRadius: Float = 48f // 圆角半径
private var nativeViewType = CoreViewType.PLAY_VIEW
init {
clipToOutline = true
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(0, 0, view.width, view.height, cornerRadius)
}
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
outlineProvider.getOutline(this, Outline())
invalidateOutline()
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
Log.w(TAG, "onAttachedToWindow")
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
Log.w(TAG, "onDetachedFromWindow")
}
public fun updateViewType(viewType: Any) {
if (viewType == null) {
return
}
if (viewType !is String) {
return
}
if (viewType == "PUSH_VIEW") {
nativeViewType = CoreViewType.PUSH_VIEW
}
}
public fun updateRenderView(liveID: Any) {
console.warn("StreamView, updateRenderView liveID: ", liveID, nativeViewType)
Logger.i(TAG + "updateRenderView: liveID:" + liveID + ", viewType: " + nativeViewType)
if (liveID == null) {
console.error("StreamView, updateRenderView liveID is invalid")
Logger.e(TAG + "updateRenderView: liveID is invalid")
return
}
if (liveID !is String) {
console.error("StreamView, updateRenderView liveID is not String")
Logger.e(TAG + "updateRenderView: liveID is not String")
return
}
if(liveID.isEmpty()) {
console.error("StreamView, updateRenderView liveID is empty")
Logger.e(TAG + "updateRenderView: liveID is empty")
return
}
removeAllViews()
val renderView = LiveCoreView(context, null, 0, nativeViewType)
renderView.setLiveId(liveID)
val lp = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
addView(renderView, lp)
}
}

View File

@@ -0,0 +1,79 @@
package uts.sdk.modules.atomicx.kotlin
import android.util.Log
import com.tencent.liteav.base.ContextUtils
import com.tencent.trtc.TRTCCloud
import org.json.JSONException
import org.json.JSONObject
class Logger {
companion object {
private const val API = "TuikitLog"
private const val LOG_KEY_API = "api"
private const val LOG_KEY_PARAMS = "params"
private const val LOG_KEY_PARAMS_LEVEL = "level"
private const val LOG_KEY_PARAMS_MESSAGE = "message"
private const val LOG_KEY_PARAMS_FILE = "file"
private const val LOG_KEY_PARAMS_LINE = "line"
private const val LOG_KEY_PARAMS_MODULE = "module"
private const val LOG_VALUE_PARAMS_MODULE = "call_state"
private const val LOG_LEVEL_INFO = 0
private const val LOG_LEVEL_WARNING = 1
private const val LOG_LEVEL_ERROR = 2
private const val LOG_FUNCTION_CALLER_INDEX = 5
fun i(message: String) {
log(LOG_LEVEL_INFO, message)
}
fun w(message: String) {
log(LOG_LEVEL_WARNING, message)
}
fun e(message: String) {
log(LOG_LEVEL_ERROR, message)
}
private fun log(
level: Int,
message: String,
) {
var context = ContextUtils.getApplicationContext()
if (context == null) {
ContextUtils.initContextFromNative("liteav")
context = ContextUtils.getApplicationContext()
}
if (context == null) {
return
}
try {
val paramsJson = JSONObject()
paramsJson.put(LOG_KEY_PARAMS_LEVEL, level)
paramsJson.put(LOG_KEY_PARAMS_MESSAGE, message)
paramsJson.put(LOG_KEY_PARAMS_MODULE, LOG_VALUE_PARAMS_MODULE)
paramsJson.put(LOG_KEY_PARAMS_FILE, getCallerFileName())
paramsJson.put(LOG_KEY_PARAMS_LINE, getCallerLineNumber())
val loggerJson = JSONObject()
loggerJson.put(LOG_KEY_API, API)
loggerJson.put(LOG_KEY_PARAMS, paramsJson)
TRTCCloud.sharedInstance(context).callExperimentalAPI(loggerJson.toString())
} catch (e: JSONException) {
Log.e("Logger", e.toString())
}
}
private fun getCallerFileName(): String {
val stackTrace = Thread.currentThread().stackTrace
if (stackTrace.size < LOG_FUNCTION_CALLER_INDEX + 1) return ""
return stackTrace[LOG_FUNCTION_CALLER_INDEX].fileName
}
private fun getCallerLineNumber(): Int {
val stackTrace = Thread.currentThread().stackTrace
if (stackTrace.size < LOG_FUNCTION_CALLER_INDEX + 1) return 0
return stackTrace[LOG_FUNCTION_CALLER_INDEX].lineNumber
}
}
}

View File

@@ -0,0 +1,141 @@
package uts.sdk.modules.atomicx.kotlin
import android.content.Context
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.opensource.svgaplayer.SVGACallback
import com.opensource.svgaplayer.SVGAImageView
import com.opensource.svgaplayer.SVGAParser
import com.opensource.svgaplayer.SVGAVideoEntity
import io.dcloud.uts.console
import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.InputStream
import java.net.URL
class SVGAAnimationView(context: Context) : FrameLayout(context), SVGACallback {
private val svgaParser: SVGAParser
private val svgaImageView: SVGAImageView
private var svgaCallback: SVGACallback? = null
init {
svgaImageView = SVGAImageView(context)
val lp: FrameLayout.LayoutParams =
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
addView(svgaImageView, lp)
svgaImageView.loops = 1
svgaImageView.callback = this
svgaParser = SVGAParser.shareParser()
svgaParser.init(context)
}
fun setCallback(callback: SVGACallback) {
svgaCallback = callback
}
// val playUrl = "/sdcard/Android/data/uni.app.UNIFA697C8/images/sports_car.svga"
fun startAnimation(playUrl: String) {
console.log("startAnimation playUrl: ", playUrl)
// Logger.e(TAG + "startAnimation, playUrl: $playUrl")
if (playUrl.isNullOrEmpty()) {
console.error("startAnimation, playUrl is empty")
// Logger.e(TAG + "startAnimation, playUrl is empty")
svgaCallback?.onFinished()
return
}
if (playUrl.endsWith(".svga") && isUrl(playUrl)) {
decodeFromURL(playUrl)
} else {
decodeFromInputStream(playUrl)
}
}
private fun isUrl(url: String): Boolean = url.startsWith("http") || url.startsWith("https")
fun stopAnimation() {
svgaImageView.stopAnimation(true)
}
private fun decodeFromURL(playUrl: String) {
console.log("decodeFromURL, playUrl: ", playUrl)
svgaParser.decodeFromURL(URL(playUrl), object : SVGAParser.ParseCompletion {
override fun onComplete(videoItem: SVGAVideoEntity) {
console.log("decodeFromURL onComplete, videoItem: ", videoItem)
// Logger.i(TAG + "startAnimation decodeFromURL, videoItem: $videoItem")
svgaImageView.setVisibility(View.VISIBLE)
svgaImageView.setVideoItem(videoItem)
svgaImageView.startAnimation()
}
override fun onError() {
console.log("===== decodeFromURL failed")
// Logger.e(TAG + "decodeFromURL failed, playUrl: $playUrl")
svgaCallback?.onFinished()
}
},)
}
private fun decodeFromInputStream(filePath: String) {
console.log("decodeFromInputStream, filePath: ", filePath)
val stream = openInputStream(filePath)
if (stream == null) {
console.log("decodeFromInputStream, filePath is null")
// Logger.e(TAG + "decodeFromInputStream failed, filePath is null")
return
}
svgaParser.decodeFromInputStream(stream, "", object : SVGAParser.ParseCompletion {
override fun onComplete(videoItem: SVGAVideoEntity) {
console.log("======startAnimation decodeFromInputStream start: ", videoItem)
// Logger.i(TAG + "decodeFromInputStream start: videoItem: $videoItem")
svgaImageView.setVisibility(VISIBLE)
svgaImageView.setVideoItem(videoItem)
svgaImageView.startAnimation()
}
override fun onError() {
console.log("======decodeFromInputStream parse failed: ", filePath)
// Logger.e(TAG + "decodeFromInputStream parse failed, filePath: $filePath")
svgaCallback?.onFinished()
}
}, true, null, "", )
}
override fun onFinished() {
console.log("SVGAAnimationView onFinished")
// Logger.i(TAG + "onFinished")
svgaImageView.setVisibility(View.GONE)
svgaCallback?.onFinished()
}
override fun onPause() {
}
override fun onRepeat() {
}
override fun onStep(frame: Int, percentage: Double) {
}
private fun openInputStream(path: String): InputStream? {
try {
val file = File(path)
if (file.exists()) {
return FileInputStream(file)
}
} catch (e: FileNotFoundException) {
Log.i(TAG, " " + e.localizedMessage)
}
return null
}
companion object {
private const val TAG = "UTS-SVGAAnimationView: "
}
}

View File

@@ -0,0 +1,42 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.device.AudioEffectStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object AudioEffectStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun audioEffectStoreChanged(callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
AudioEffectStore.shared().audioEffectState.isEarMonitorOpened
.collect { enable ->
callback("isEarMonitorOpened", gson.toJson(enable))
}
}
launch {
AudioEffectStore.shared().audioEffectState.earMonitorVolume
.collect { volume ->
callback("earMonitorVolume", gson.toJson(volume))
}
}
launch {
AudioEffectStore.shared().audioEffectState.audioChangerType
.collect { type ->
callback("audioChangerType", gson.toJson(type.value))
}
}
launch {
AudioEffectStore.shared().audioEffectState.audioReverbType
.collect { type ->
callback("audioReverbType", gson.toJson(type.value))
}
}
}
}
}

View File

@@ -0,0 +1,32 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.barrage.Barrage
import io.trtc.tuikit.atomicxcore.api.barrage.BarrageStore
import io.trtc.tuikit.atomicxcore.api.barrage.BarrageType
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object BarrageStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun barrageStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
BarrageStore.create(liveID).barrageState.messageList.collect { messageList ->
callback("messageList", gson.toJson(messageList))
}
}
// TODO: 底层未实现,暂时隐藏
// launch {
// BarrageStore.create(liveID).barrageState.allowSendMessage.collect { allowSendMessage ->
// callback("allowSendMessage", gson.toJson(allowSendMessage))
// }
// }
}
}
}

View File

@@ -0,0 +1,34 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.device.BaseBeautyStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object BaseBeautyStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun beautyStoreChanged(callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
BaseBeautyStore.shared().baseBeautyState.smoothLevel.collect { level ->
callback("smoothLevel", gson.toJson(level))
}
}
launch {
BaseBeautyStore.shared().baseBeautyState.whitenessLevel.collect { level ->
callback("whitenessLevel", gson.toJson(level))
}
}
launch {
BaseBeautyStore.shared().baseBeautyState.ruddyLevel.collect { level ->
callback("ruddyLevel", gson.toJson(level))
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.live.BattleStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object BattleStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun battleStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
BattleStore.create(liveID).battleState.currentBattleInfo.collect { currentBattleInfo ->
callback("currentBattleInfo", gson.toJson(currentBattleInfo))
}
}
launch {
BattleStore.create(liveID).battleState.battleUsers.collect { battleUsers ->
callback("battleUsers", gson.toJson(battleUsers))
}
}
launch {
BattleStore.create(liveID).battleState.battleScore.collect { battleScore ->
callback("battleScore", gson.toJson(battleScore))
}
}
}
}
}

View File

@@ -0,0 +1,72 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.live.CoGuestStore
import io.trtc.tuikit.atomicxcore.api.device.DeviceStatus
import io.trtc.tuikit.atomicxcore.api.live.Role
import io.trtc.tuikit.atomicxcore.api.live.SeatUserInfo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object CoGuestStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun coGuestStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
CoGuestStore.create(liveID).coGuestState.connected.collect { connected ->
val list = connected.map { convertSeatInfoToMap(it) }
callback("connected", gson.toJson(list)) // SeatUserInfo
}
}
launch {
CoGuestStore.create(liveID).coGuestState.invitees.collect { invitees ->
callback("invitees", gson.toJson(invitees)) // LiveUserInfo
}
}
launch {
CoGuestStore.create(liveID).coGuestState.applicants.collect { applicants ->
callback("applicants", gson.toJson(applicants)) // LiveUserInfo
}
}
launch {
CoGuestStore.create(liveID).coGuestState.candidates.collect { candidates ->
callback("candidates", gson.toJson(candidates)) // LiveUserInfo
}
}
}
}
private fun convertSeatInfoToMap(info: SeatUserInfo): Map<String, Any> {
val map = mutableMapOf<String, Any>()
map["userID"] = info.userID
map["userName"] = info.userName
map["avatarURL"] = info.avatarURL
map["role"] = info.role
map["liveID"] = info.liveID
map["microphoneStatus"] = convertDeviceStatus(info.microphoneStatus)
map["allowOpenMicrophone"] = info.allowOpenMicrophone
map["cameraStatus"] = convertDeviceStatus(info.cameraStatus)
map["allowOpenCamera"] = info.allowOpenCamera
return map
}
private fun convertDeviceStatus(status: DeviceStatus?): String {
if (status == DeviceStatus.ON) {
return "ON"
}
return "OFF"
}
private fun convertUserRole(role: Role?): String {
return when (role) {
Role.OWNER -> "OWNER"
Role.ADMIN -> "ADMIN"
else -> "GENERAL_USER"
}
}
}

View File

@@ -0,0 +1,45 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.live.CoHostStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object CoHostStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun coHostStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
CoHostStore.create(liveID).coHostState.coHostStatus.collect { coHostStatus ->
callback("coHostStatus", gson.toJson(coHostStatus))
}
}
launch {
CoHostStore.create(liveID).coHostState.connected.collect { connected ->
callback("connected", gson.toJson(connected))
}
}
// TODO: 底层未实现,暂时隐藏
// launch {
// CoHostStore.create(liveID).coHostState.candidates.collect { candidates ->
// callback("candidates", gson.toJson(candidates))
// }
// }
launch {
CoHostStore.create(liveID).coHostState.invitees.collect { invitees ->
callback("invitees", gson.toJson(invitees))
}
}
launch {
CoHostStore.create(liveID).coHostState.applicant.collect { applicant ->
callback("applicant", gson.toJson(applicant))
}
}
}
}
}

View File

@@ -0,0 +1,87 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.device.DeviceStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object DeviceStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun deviceStoreChanged(callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
DeviceStore.shared().deviceState.microphoneStatus.collect { status ->
callback("microphoneStatus", gson.toJson(status.value))
}
}
launch {
DeviceStore.shared().deviceState.microphoneLastError.collect { deviceError ->
callback("microphoneLastError", gson.toJson(deviceError.value))
}
}
launch {
DeviceStore.shared().deviceState.captureVolume.collect { volume ->
callback("captureVolume", gson.toJson(volume))
}
}
launch {
DeviceStore.shared().deviceState.currentMicVolume.collect { volume ->
callback("currentMicVolume", gson.toJson(volume))
}
}
launch {
DeviceStore.shared().deviceState.outputVolume.collect { volume ->
callback("outputVolume", gson.toJson(volume))
}
}
launch {
DeviceStore.shared().deviceState.cameraStatus.collect { cameraStatus ->
callback("cameraStatus", gson.toJson(cameraStatus.value))
}
}
launch {
DeviceStore.shared().deviceState.cameraLastError.collect { deviceError ->
callback("cameraLastError", gson.toJson(deviceError.value))
}
}
launch {
DeviceStore.shared().deviceState.isFrontCamera.collect { isFrontCamera ->
callback("isFrontCamera", gson.toJson(isFrontCamera))
}
}
launch {
DeviceStore.shared().deviceState.localMirrorType.collect { localMirrorType ->
callback("localMirrorType", gson.toJson(localMirrorType))
}
}
launch {
DeviceStore.shared().deviceState.localVideoQuality.collect { quality ->
callback("localVideoQuality", gson.toJson(quality))
}
}
launch {
DeviceStore.shared().deviceState.currentAudioRoute.collect { audioRoute ->
callback("currentAudioRoute", gson.toJson(audioRoute.value))
}
}
launch {
DeviceStore.shared().deviceState.screenStatus.collect { screenStatus ->
callback("screenStatus", gson.toJson(screenStatus.value))
}
}
launch {
DeviceStore.shared().deviceState.networkInfo.collect { networkInfo ->
callback("networkInfo", gson.toJson(networkInfo))
}
}
}
}
}

View File

@@ -0,0 +1,24 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.gift.GiftStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object GiftStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun giftStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
GiftStore.create(liveID).giftState.usableGifts.collect { usableGifts ->
callback("usableGifts", gson.toJson(usableGifts))
}
}
}
}
}

View File

@@ -0,0 +1,24 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.live.LikeStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object LikeStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun likeStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
LikeStore.create(liveID).likeState.totalLikeCount.collect { count ->
callback("totalLikeCount", gson.toJson(count))
}
}
}
}
}

View File

@@ -0,0 +1,31 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.live.LiveAudienceStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object LiveAudienceStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun liveAudienceStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
LiveAudienceStore.create(liveID).liveAudienceState.audienceList.collect { audienceList ->
callback("audienceList", gson.toJson(audienceList))
}
}
launch {
LiveAudienceStore.create(liveID).liveAudienceState.audienceCount.collect { audienceCount ->
callback("audienceCount", gson.toJson(audienceCount))
}
}
}
}
}

View File

@@ -0,0 +1,35 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.live.LiveListStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object LiveListStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun liveStoreChanged(callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
LiveListStore.shared().liveState.liveList.collect { liveList ->
callback("liveList", gson.toJson(liveList))
}
}
launch {
LiveListStore.shared().liveState.liveListCursor.collect { cursor ->
callback("liveListCursor", gson.toJson(cursor))
}
}
launch {
LiveListStore.shared().liveState.currentLive.collect { liveInfo ->
callback("currentLive", gson.toJson(liveInfo))
}
}
}
}
}

View File

@@ -0,0 +1,39 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.live.LiveSeatStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import uts.sdk.modules.atomicx.kotlin.Logger
import io.dcloud.uts.console
object LiveSeatStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun liveSeatStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
LiveSeatStore.create(liveID).liveSeatState.seatList.collect { seatList ->
val list = gson.toJson(seatList)
console.info("UTS-Live: liveSeatStoreChanged, seatList: ", list)
Logger.i("UTS-Live: " + "liveSeatStoreChanged, seatList: "+ list);
callback("seatList", gson.toJson(seatList))
}
}
launch {
LiveSeatStore.create(liveID).liveSeatState.canvas.collect { canvas ->
callback("canvas", gson.toJson(canvas))
}
}
launch {
LiveSeatStore.create(liveID).liveSeatState.speakingUsers.collect { speakingUsers ->
callback("speakingUsers", gson.toJson(speakingUsers))
}
}
}
}
}

View File

@@ -0,0 +1,23 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import io.trtc.tuikit.atomicxcore.api.live.LiveSummaryStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object LiveSummaryStoreObserver {
private val gson = Gson()
private var bindDataJob: Job? = null
fun liveSummaryStoreChanged(liveID: String, callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
LiveSummaryStore.create(liveID).liveSummaryState.summaryData.collect { data ->
callback("summaryData", gson.toJson(data))
}
}
}
}
}

View File

@@ -0,0 +1,32 @@
package uts.sdk.modules.atomicx.observer
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import io.trtc.tuikit.atomicxcore.api.login.LoginStatus
import io.trtc.tuikit.atomicxcore.api.login.LoginStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object LoginStoreObserver {
private val gson = GsonBuilder().serializeNulls().create()
private var bindDataJob: Job? = null
fun loginStoreChanged(callback: (String, String) -> Unit) {
bindDataJob?.cancel()
bindDataJob = CoroutineScope(Dispatchers.Main).launch {
launch {
LoginStore.shared.loginState.loginUserInfo.collect { userInfo ->
callback("loginUserInfo", gson.toJson(userInfo))
}
}
launch {
LoginStore.shared.loginState.loginStatus.collect { loginStatus ->
// UNLOGIN \ LOGINED
callback("loginStatus", gson.toJson(loginStatus))
}
}
}
}
}