需要添加直播接口
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class AudioEffectStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
public static let shared = AudioEffectStoreObserver()
|
||||
|
||||
public func audioEffectStoreChanged(
|
||||
_ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
|
||||
AudioEffectStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \AudioEffectState.audioChangerType))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("audioChangerType", String(value.rawValue))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
AudioEffectStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \AudioEffectState.audioReverbType))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("audioReverbType", String(value.rawValue))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
AudioEffectStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \AudioEffectState.isEarMonitorOpened))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("isEarMonitorOpened", String(value))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
AudioEffectStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \AudioEffectState.earMonitorVolume))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("earMonitorVolume", String(value))
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import Foundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class BarrageStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
public static let shared = BarrageStoreObserver()
|
||||
|
||||
public func barrageStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
BarrageStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \BarrageState.messageList))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] messageList in
|
||||
guard let self = self else { return }
|
||||
let dict = messageList.map { self.convertBarrageToDic(barrage: $0) }
|
||||
if let jsonList = JsonUtil.toJson(dict) {
|
||||
callback("messageList", jsonList)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
// TODO: 底层未实现,暂时隐藏
|
||||
// BarrageStore.create(liveID: liveID)
|
||||
// .state.subscribe(StatePublisherSelector(keyPath: \BarrageState.allowSendMessage))
|
||||
// .receive(on: DispatchQueue.main)
|
||||
// .sink(receiveValue: { message in
|
||||
// callback("allowSendMessage", String(message))
|
||||
// }).store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func convertBarrageToDic(barrage: Barrage) -> [String: Any] {
|
||||
var dict: [String: Any] = [
|
||||
"liveID": barrage.liveID,
|
||||
"sender": TypeConvert.convertLiveUserInfoToDic(liveUserInfo: barrage.sender),
|
||||
"sequence": barrage.sequence,
|
||||
"timestampInSecond": barrage.timestampInSecond,
|
||||
"messageType": convertMessageType(barrage.messageType),
|
||||
"textContent": barrage.textContent,
|
||||
"extensionInfo": barrage.extensionInfo,
|
||||
"businessID": barrage.businessID,
|
||||
"data": barrage.data,
|
||||
]
|
||||
return dict
|
||||
}
|
||||
|
||||
private func convertMessageType(_ type: BarrageType) -> String {
|
||||
if type == BarrageType.custom {
|
||||
return "CUSTOM"
|
||||
}
|
||||
return "TEXT"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class BaseBeautyStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
public static let shared = BaseBeautyStoreObserver()
|
||||
|
||||
public func beautyStoreChanged(_ callback: @escaping (_ name: String, _ data: String) -> Void) {
|
||||
cancellables.removeAll()
|
||||
|
||||
BaseBeautyStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \BaseBeautyState.smoothLevel))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("smoothLevel", String(value))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
BaseBeautyStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \BaseBeautyState.whitenessLevel))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("whitenessLevel", String(value))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
BaseBeautyStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \BaseBeautyState.ruddyLevel))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("ruddyLevel", String(value))
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class BattleStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var battleEventCancellables = Set<AnyCancellable>()
|
||||
public static let shared = BattleStoreObserver()
|
||||
|
||||
public func battleStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
|
||||
BattleStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \BattleState.currentBattleInfo))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] currentBattleInfo in
|
||||
guard let self = self else { return }
|
||||
if let battleInfo = currentBattleInfo {
|
||||
if let json = JsonUtil.toJson(
|
||||
self.convertBattleInfoToDic(battleInfo: battleInfo))
|
||||
{
|
||||
callback("currentBattleInfo", json)
|
||||
}
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
BattleStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \BattleState.battleUsers))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] battleUsers in
|
||||
guard let self = self else { return }
|
||||
let userList = battleUsers.map {
|
||||
TypeConvert.convertSeatUserInfoToDic(seatUserInfo: $0)
|
||||
}
|
||||
if let json = JsonUtil.toJson(userList) {
|
||||
callback("battleUsers", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
BattleStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \BattleState.battleScore))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] battleScore in
|
||||
guard let self = self else { return }
|
||||
if let json = JsonUtil.toJson(battleScore) {
|
||||
callback("battleScore", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func convertBattleInfoToDic(battleInfo: BattleInfo) -> [String: Any] {
|
||||
return [
|
||||
"battleID": battleInfo.battleID,
|
||||
"config": convertBattleConfigToDic(config: battleInfo.config),
|
||||
"startTime": battleInfo.startTime,
|
||||
"endTime": battleInfo.endTime,
|
||||
]
|
||||
}
|
||||
|
||||
private func convertBattleConfigToDic(config: BattleConfig) -> [String: Any] {
|
||||
return [
|
||||
"duration": config.duration,
|
||||
"needResponse": config.needResponse,
|
||||
"extensionInfo": config.extensionInfo,
|
||||
]
|
||||
}
|
||||
|
||||
public func setupBattleEvent(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
battleEventCancellables.removeAll()
|
||||
BattleStore.create(liveID: liveID).battleEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onBattleStarted(let battleInfo, let inviter, let invitees):
|
||||
let dict: [String: Any] = [
|
||||
"battleInfo": self.convertBattleInfoToDic(battleInfo: battleInfo),
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
"invitees": invitees.map {
|
||||
TypeConvert.convertSeatUserInfoToDic(seatUserInfo: $0)
|
||||
},
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onBattleStarted", json)
|
||||
}
|
||||
case .onBattleEnded(let battleInfo, let reason):
|
||||
let reasonStr = reason == .allMemberExit ? "ALL_MEMBER_EXIT" : "TIME_OVER"
|
||||
let dict: [String: Any] = [
|
||||
"battleInfo": self.convertBattleInfoToDic(battleInfo: battleInfo),
|
||||
"reason": reasonStr,
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onBattleEnded", json)
|
||||
}
|
||||
case .onUserJoinBattle(let battleID, let battleUser):
|
||||
let dict: [String: Any] = [
|
||||
"battleID": battleID,
|
||||
"battleUser": TypeConvert.convertSeatUserInfoToDic(
|
||||
seatUserInfo: battleUser),
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onUserJoinBattle", json)
|
||||
}
|
||||
case .onUserExitBattle(let battleID, let battleUser):
|
||||
let dict: [String: Any] = [
|
||||
"battleID": battleID,
|
||||
"battleUser": TypeConvert.convertSeatUserInfoToDic(
|
||||
seatUserInfo: battleUser),
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onUserExitBattle", json)
|
||||
}
|
||||
case .onBattleRequestReceived(let battleID, let inviter, let invitee):
|
||||
let dict: [String: Any] = [
|
||||
"battleID": battleID,
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
"invitee": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee),
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onBattleRequestReceived", json)
|
||||
}
|
||||
case .onBattleRequestCancelled(let battleID, let inviter, let invitee):
|
||||
let dict: [String: Any] = [
|
||||
"battleID": battleID,
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
"invitee": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee),
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onBattleRequestCancelled", json)
|
||||
}
|
||||
case .onBattleRequestTimeout(let battleID, let inviter, let invitee):
|
||||
let dict: [String: Any] = [
|
||||
"battleID": battleID,
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
"invitee": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee),
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onBattleRequestTimeout", json)
|
||||
}
|
||||
case .onBattleRequestAccept(let battleID, let inviter, let invitee):
|
||||
let dict: [String: Any] = [
|
||||
"battleID": battleID,
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
"invitee": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee),
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onBattleRequestAccept", json)
|
||||
}
|
||||
case .onBattleRequestReject(let battleID, let inviter, let invitee):
|
||||
let dict: [String: Any] = [
|
||||
"battleID": battleID,
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
"invitee": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee),
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onBattleRequestReject", json)
|
||||
}
|
||||
}
|
||||
}.store(in: &battleEventCancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class CoGuestStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var hostEventCancellables = Set<AnyCancellable>()
|
||||
private var guestEventCancellables = Set<AnyCancellable>()
|
||||
public static let shared = CoGuestStoreObserver()
|
||||
|
||||
public func coGuestStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
CoGuestStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \CoGuestState.connected))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { arr in
|
||||
let dict = arr.map { TypeConvert.convertSeatUserInfoToDic(seatUserInfo: $0) }
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("connected", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
let arrayKeys: [(String, KeyPath<CoGuestState, [LiveUserInfo]>)] = [
|
||||
("invitees", \CoGuestState.invitees),
|
||||
("applicants", \CoGuestState.applicants),
|
||||
("candidates", \CoGuestState.candidates),
|
||||
]
|
||||
for (key, kp) in arrayKeys {
|
||||
CoGuestStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: kp))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { arr in
|
||||
let dict = arr.map { TypeConvert.convertLiveUserInfoToDic(liveUserInfo: $0) }
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback(key, json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
|
||||
public func setupHostEvent(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
hostEventCancellables.removeAll()
|
||||
CoGuestStore.create(liveID: liveID).hostEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onGuestApplicationReceived(let guestUser):
|
||||
let dict: [String: Any] = [
|
||||
"guestUser" : TypeConvert.convertLiveUserInfoToDic(liveUserInfo: guestUser)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onGuestApplicationReceived", json)
|
||||
}
|
||||
case .onGuestApplicationCancelled(let guestUser):
|
||||
let dict: [String: Any] = [
|
||||
"guestUser" : TypeConvert.convertLiveUserInfoToDic(liveUserInfo: guestUser)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onGuestApplicationCancelled", json)
|
||||
}
|
||||
case .onGuestApplicationProcessedByOtherHost(let guestUser, let hostUser):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["guestUser"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: guestUser)
|
||||
dict["hostUser"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: hostUser)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onGuestApplicationProcessedByOtherHost", json)
|
||||
}
|
||||
case .onHostInvitationResponded(let isAccept, let guestUser):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["isAccept"] = isAccept
|
||||
dict["guestUser"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: guestUser)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onHostInvitationResponded", json)
|
||||
}
|
||||
case .onHostInvitationNoResponse(let guestUser, let reason):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["guestUser"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: guestUser)
|
||||
dict["reason"] = convertNoResponseReason(reason)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onHostInvitationNoResponse", json)
|
||||
}
|
||||
}
|
||||
}.store(in: &hostEventCancellables)
|
||||
}
|
||||
|
||||
private func convertNoResponseReason(_ reason: NoResponseReason) -> String {
|
||||
if reason == NoResponseReason.alreadySeated {
|
||||
return "ALREADY_SEATED"
|
||||
}
|
||||
return "TIMEOUT"
|
||||
}
|
||||
|
||||
public func setupGuestEvent(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
guestEventCancellables.removeAll()
|
||||
CoGuestStore.create(liveID: liveID).guestEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onHostInvitationReceived(let hostUser):
|
||||
let dict: [String: Any] = [
|
||||
"hostUser" : TypeConvert.convertLiveUserInfoToDic(liveUserInfo: hostUser)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onHostInvitationReceived", json)
|
||||
}
|
||||
case .onHostInvitationCancelled(let hostUser):
|
||||
let dict: [String: Any] = [
|
||||
"hostUser" : TypeConvert.convertLiveUserInfoToDic(liveUserInfo: hostUser)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onHostInvitationCancelled", json)
|
||||
}
|
||||
case .onGuestApplicationResponded(let isAccept, let hostUser):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["isAccept"] = isAccept
|
||||
dict["hostUser"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: hostUser)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onGuestApplicationResponded", json)
|
||||
}
|
||||
case .onGuestApplicationNoResponse(let reason):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["reason"] = convertNoResponseReason(reason)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onGuestApplicationNoResponse", json)
|
||||
}
|
||||
case .onKickedOffSeat(let seatIndex, let hostUser):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["seatIndex"] = seatIndex
|
||||
dict["hostUser"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: hostUser)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onKickedOffSeat", json)
|
||||
}
|
||||
}
|
||||
}.store(in: &guestEventCancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class CoHostStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var coHostEventCancellables = Set<AnyCancellable>()
|
||||
public static let shared = CoHostStoreObserver()
|
||||
|
||||
public func coHostStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
|
||||
CoHostStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \CoHostState.coHostStatus))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
var coHostStatus = "DISCONNECTED"
|
||||
if value == .connected {
|
||||
coHostStatus = "CONNECTED"
|
||||
}
|
||||
if let json = JsonUtil.toJson(coHostStatus) {
|
||||
callback("coHostStatus", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
CoHostStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \CoHostState.connected))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { arr in
|
||||
let dict = arr.map { TypeConvert.convertSeatUserInfoToDic(seatUserInfo: $0) }
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("connected", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
//TODO: 底层未实现,暂时删除
|
||||
// CoHostStore.create(liveID: liveID)
|
||||
// .state.subscribe(StatePublisherSelector(keyPath: \CoHostState.candidates))
|
||||
// .receive(on: DispatchQueue.main)
|
||||
// .sink(receiveValue: { arr in
|
||||
// let dict = arr.map { TypeConvert.convertSeatUserInfoToDic(seatUserInfo: $0) }
|
||||
// if let json = JsonUtil.toJson(dict) {
|
||||
// callback("candidates", json)
|
||||
// }
|
||||
// }).store(in: &cancellables)
|
||||
|
||||
CoHostStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \CoHostState.invitees))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { arr in
|
||||
let dict = arr.map { TypeConvert.convertSeatUserInfoToDic(seatUserInfo: $0) }
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("invitees", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
CoHostStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \CoHostState.applicant))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] value in
|
||||
guard let self = self else { return }
|
||||
guard let value = value else { return }
|
||||
let userInfo = TypeConvert.convertSeatUserInfoToDic(seatUserInfo: value)
|
||||
if let json = JsonUtil.toJson(userInfo) {
|
||||
callback("applicant", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
public func setupCoHostEvent(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
coHostEventCancellables.removeAll()
|
||||
CoHostStore.create(liveID: liveID).coHostEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onCoHostRequestReceived(let inviter, let extensionInfo):
|
||||
var dict: [String: Any] = [
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
"extensionInfo": extensionInfo,
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onCoHostRequestReceived", json)
|
||||
}
|
||||
case .onCoHostRequestCancelled(let inviter, let invitee):
|
||||
var dict: [String: Any] = [
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
]
|
||||
if let invitee = invitee {
|
||||
dict["invitee"] = TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee)
|
||||
}
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onCoHostRequestCancelled", json)
|
||||
}
|
||||
case .onCoHostRequestAccepted(let invitee):
|
||||
var dict: [String: Any] = [
|
||||
"invitee": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onCoHostRequestAccepted", json)
|
||||
}
|
||||
case .onCoHostRequestRejected(let invitee):
|
||||
var dict: [String: Any] = [
|
||||
"invitee": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onCoHostRequestRejected", json)
|
||||
}
|
||||
case .onCoHostRequestTimeout(let inviter, let invitee):
|
||||
var dict: [String: Any] = [
|
||||
"inviter": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: inviter),
|
||||
"invitee": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: invitee),
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onCoHostRequestTimeout", json)
|
||||
}
|
||||
case .onCoHostUserJoined(let userInfo):
|
||||
var dict: [String: Any] = [
|
||||
"userInfo": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: userInfo)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onCoHostUserJoined", json)
|
||||
}
|
||||
case .onCoHostUserLeft(let userInfo):
|
||||
var dict: [String: Any] = [
|
||||
"userInfo": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: userInfo)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onCoHostUserLeft", json)
|
||||
}
|
||||
}
|
||||
}.store(in: &coHostEventCancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class DeviceStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
public static let shared = DeviceStoreObserver()
|
||||
|
||||
public func deviceStoreChanged(_ callback: @escaping (_ name: String, _ data: String) -> Void) {
|
||||
cancellables.removeAll()
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.microphoneStatus))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("microphoneStatus", String(value.rawValue))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.microphoneLastError))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("microphoneLastError", String(value.rawValue))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.captureVolume))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("captureVolume", String(value))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.currentMicVolume))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("currentMicVolume", String(value))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.outputVolume))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("outputVolume", String(value))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.cameraStatus))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("cameraStatus", String(value.rawValue))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.cameraLastError))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("cameraLastError", String(value.rawValue))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.isFrontCamera))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("isFrontCamera", String(value))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.localMirrorType))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] value in
|
||||
guard let self = self else { return }
|
||||
if let json = JsonUtil.toJson(convertLocalMirrorType(value)) {
|
||||
callback("localMirrorType", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.localVideoQuality))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] value in
|
||||
guard let self = self else { return }
|
||||
callback("localVideoQuality", convertVideoQuality(value))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.currentAudioRoute))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("currentAudioRoute", String(value.rawValue))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.screenStatus))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
callback("screenStatus", String(value.rawValue))
|
||||
}).store(in: &cancellables)
|
||||
|
||||
DeviceStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \DeviceState.networkInfo))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] value in
|
||||
guard let self = self else { return }
|
||||
if let json = JsonUtil.toJson(convertNetworkInfo(value)) {
|
||||
callback("networkInfo", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func convertNetworkInfo(_ info: NetworkInfo) -> [String: Any] {
|
||||
var map = [String: Any]()
|
||||
map["userID"] = info.userID ?? ""
|
||||
map["quality"] = convertNetworkQuality(info.quality)
|
||||
map["upLoss"] = info.upLoss
|
||||
map["downLoss"] = info.downLoss
|
||||
map["delay"] = info.delay
|
||||
return map
|
||||
}
|
||||
|
||||
private func convertNetworkQuality(_ quality: NetworkQuality?) -> String {
|
||||
guard let quality = quality else {
|
||||
return "UNKNOWN"
|
||||
}
|
||||
switch quality {
|
||||
case .excellent:
|
||||
return "EXCELLENT"
|
||||
case .good:
|
||||
return "GOOD"
|
||||
case .poor:
|
||||
return "POOR"
|
||||
case .veryBad:
|
||||
return "VBAD"
|
||||
case .bad:
|
||||
return "BAD"
|
||||
case .down:
|
||||
return "DOWN"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
private func convertVideoQuality(_ quality: VideoQuality) -> String {
|
||||
switch quality {
|
||||
case VideoQuality.quality540P:
|
||||
return "540P"
|
||||
case VideoQuality.quality720P:
|
||||
return "720P"
|
||||
case VideoQuality.quality1080P:
|
||||
return "1080P"
|
||||
default:
|
||||
return "360P"
|
||||
}
|
||||
}
|
||||
private func convertLocalMirrorType(_ type: MirrorType) -> String {
|
||||
switch type {
|
||||
case MirrorType.enable:
|
||||
return "ENABLE"
|
||||
case MirrorType.disable:
|
||||
return "DISABLE"
|
||||
default:
|
||||
return "AUTO"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class GiftStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var giftEventCancellables = Set<AnyCancellable>()
|
||||
public static let shared = GiftStoreObserver()
|
||||
|
||||
public func giftStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
GiftStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \GiftState.usableGifts))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] usableGifts in
|
||||
guard let self = self else { return }
|
||||
let dict = usableGifts.map { self.convertGiftCategoryToDic(giftCategory: $0) }
|
||||
if let jsonList = JsonUtil.toJson(dict) {
|
||||
callback("usableGifts", jsonList)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func convertGiftCategoryToDic(giftCategory: GiftCategory) -> [String: Any] {
|
||||
var gifts: [[String: Any]] = []
|
||||
for info in giftCategory.giftList {
|
||||
gifts.append(convertGiftToDic(gift: info))
|
||||
}
|
||||
return [
|
||||
"categoryID": giftCategory.categoryID,
|
||||
"name": giftCategory.name,
|
||||
"desc": giftCategory.desc,
|
||||
"extensionInfo": giftCategory.extensionInfo,
|
||||
"giftList": gifts,
|
||||
]
|
||||
}
|
||||
private func convertGiftToDic(gift: Gift) -> [String: Any] {
|
||||
return [
|
||||
"giftID": gift.giftID,
|
||||
"name": gift.name,
|
||||
"desc": gift.desc,
|
||||
"iconURL": gift.iconURL,
|
||||
"resourceURL": gift.resourceURL,
|
||||
"level": gift.level,
|
||||
"coins": gift.coins,
|
||||
"extensionInfo": gift.extensionInfo,
|
||||
]
|
||||
}
|
||||
|
||||
public func setupGiftEvent(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
giftEventCancellables.removeAll()
|
||||
GiftStore.create(liveID: liveID).giftEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onReceiveGift(let liveID, let gift, let count, let sender):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["liveID"] = liveID
|
||||
dict["gift"] = self.convertGiftToDic(gift: gift)
|
||||
dict["count"] = count
|
||||
dict["sender"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: sender)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onReceiveGift", json)
|
||||
}
|
||||
}
|
||||
}.store(in: &giftEventCancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class LikeStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var likeEventCancellables = Set<AnyCancellable>()
|
||||
public static let shared = LikeStoreObserver()
|
||||
|
||||
public func likeStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
LikeStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LikeState.totalLikeCount))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { totalLikeCount in
|
||||
callback("totalLikeCount", String(totalLikeCount))
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
public func setupLikeEvent(_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void) {
|
||||
likeEventCancellables.removeAll()
|
||||
LikeStore.create(liveID: liveID).likeEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onReceiveLikesMessage(liveID: let liveID, totalLikesReceived: let totalLikesReceived, sender: let sender):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["liveID"] = liveID
|
||||
dict["totalLikesReceived"] = totalLikesReceived
|
||||
dict["sender"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: sender)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onReceiveLikesMessage", json)
|
||||
}
|
||||
}
|
||||
}.store(in: &likeEventCancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class LiveAudienceStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var audienceCancellables = Set<AnyCancellable>()
|
||||
public static let shared = LiveAudienceStoreObserver()
|
||||
|
||||
public func liveAudienceStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
|
||||
LiveAudienceStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveAudienceState.audienceList))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { audienceList in
|
||||
let dict = audienceList.map {
|
||||
TypeConvert.convertLiveUserInfoToDic(liveUserInfo: $0)
|
||||
}
|
||||
if let jsonList = JsonUtil.toJson(dict) {
|
||||
callback("audienceList", jsonList)
|
||||
}
|
||||
})
|
||||
.store(in: &cancellables)
|
||||
|
||||
LiveAudienceStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveAudienceState.audienceCount))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { count in
|
||||
callback("audienceCount", String(count))
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
public func setupAudienceEvent(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
audienceCancellables.removeAll()
|
||||
LiveAudienceStore.create(liveID: liveID).liveAudienceEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onAudienceJoined(let audience):
|
||||
let dict: [String: Any] = [
|
||||
"audience" : TypeConvert.convertLiveUserInfoToDic(liveUserInfo: audience)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onAudienceJoined", json)
|
||||
}
|
||||
case .onAudienceMessageDisabled(let audience, let isDisable):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["isDisable"] = isDisable
|
||||
dict["audience"] = TypeConvert.convertLiveUserInfoToDic(liveUserInfo: audience)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onAudienceMessageDisabled", json)
|
||||
}
|
||||
case .onAudienceLeft(let audience):
|
||||
let dict: [String: Any] = [
|
||||
"audience" : TypeConvert.convertLiveUserInfoToDic(liveUserInfo: audience)
|
||||
]
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onAudienceLeft", json)
|
||||
}
|
||||
break
|
||||
}
|
||||
}.store(in: &audienceCancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import Foundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class LiveListStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var liveListEventCancellables = Set<AnyCancellable>()
|
||||
public static let shared = LiveListStoreObserver()
|
||||
|
||||
public func liveStoreChanged(_ callback: @escaping (_ name: String, _ data: String) -> Void) {
|
||||
cancellables.removeAll()
|
||||
|
||||
LiveListStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveListState.liveList))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] liveList in
|
||||
guard let self = self else { return }
|
||||
let dict = liveList.map { TypeConvert.convertLiveInfoToDic(liveInfo: $0) }
|
||||
if let jsonList = JsonUtil.toJson(dict) {
|
||||
callback("liveList", jsonList)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
LiveListStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveListState.liveListCursor))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { liveListCursor in
|
||||
if let json = JsonUtil.toJson(liveListCursor) {
|
||||
callback("liveListCursor", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
LiveListStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveListState.currentLive))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] liveInfo in
|
||||
guard let self = self else { return }
|
||||
let dict = TypeConvert.convertLiveInfoToDic(liveInfo: liveInfo)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("currentLive", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
public func setupLiveListEvent(_ callback: @escaping (_ name: String, _ data: String) -> Void) {
|
||||
liveListEventCancellables.removeAll()
|
||||
LiveListStore.shared.liveListEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onLiveEnded(let liveID, let reason, let message):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["liveID"] = liveID
|
||||
dict["reason"] = convertLiveEndedReason(reason)
|
||||
dict["message"] = message
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onLiveEnded", json)
|
||||
}
|
||||
case .onKickedOutOfLive(let liveID, let reason, let message):
|
||||
var dict: [String: Any] = [:]
|
||||
dict["liveID"] = liveID
|
||||
dict["reason"] = convertLiveKickedOutReason(reason)
|
||||
dict["message"] = message
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("onKickedOutOfLive", json)
|
||||
}
|
||||
}
|
||||
}.store(in: &liveListEventCancellables)
|
||||
}
|
||||
|
||||
private func convertLiveEndedReason(_ reason: LiveEndedReason) -> String {
|
||||
if reason == LiveEndedReason.endedByServer {
|
||||
return "ENDED_BY_SERVER"
|
||||
}
|
||||
return "ENDED_BY_HOST"
|
||||
}
|
||||
|
||||
private func convertLiveKickedOutReason(_ reason: LiveKickedOutReason) -> String {
|
||||
switch reason {
|
||||
case .byLoggedOnOtherDevice:
|
||||
return "BY_LOGGED_ON_OTHER_DEVICE"
|
||||
case .byServer:
|
||||
return "BY_SERVER"
|
||||
case .forNetworkDisconnected:
|
||||
return "FOR_NETWORK_DISCONNECTED"
|
||||
case .forJoinRoomStatusInvalidDuringOffline:
|
||||
return "FOR_JOIN_ROOM_STATUS_INVALID_DURING_OFFLINE"
|
||||
case .forCountOfJoinedRoomsExceedLimit:
|
||||
return "FOR_COUNT_OF_JOINED_ROOMS_EXCEED_LIMIT"
|
||||
default:
|
||||
return "BY_ADMIN"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import Foundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class LiveSeatStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var liveSeatEventCancellables = Set<AnyCancellable>()
|
||||
public static let shared = LiveSeatStoreObserver()
|
||||
|
||||
public func liveSeatStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
|
||||
LiveSeatStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveSeatState.seatList))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] seatList in
|
||||
guard let self = self else { return }
|
||||
let dictArray = seatList.map { self.convertSeatInfoToDic(seatInfo: $0) }
|
||||
if let jsonList = JsonUtil.toJson(dictArray) {
|
||||
callback("seatList", jsonList)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
LiveSeatStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveSeatState.canvas))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] canvas in
|
||||
guard let self = self else { return }
|
||||
let dict = self.convertCanvasToDic(canvas: canvas)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("canvas", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
LiveSeatStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveSeatState.speakingUsers))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { speakingUsers in
|
||||
if let jsonUsers = JsonUtil.toJson(speakingUsers) {
|
||||
callback("speakingUsers", jsonUsers)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func convertSeatInfoToDic(seatInfo: SeatInfo) -> [String: Any] {
|
||||
var dict: [String: Any] = [
|
||||
"index": seatInfo.index,
|
||||
"isLocked": seatInfo.isLocked,
|
||||
"userInfo": TypeConvert.convertSeatUserInfoToDic(seatUserInfo: seatInfo.userInfo),
|
||||
"region": convertRegionInfoToDic(region: seatInfo.region),
|
||||
]
|
||||
return dict
|
||||
}
|
||||
|
||||
private func convertRegionInfoToDic(region: RegionInfo) -> [String: Any] {
|
||||
return [
|
||||
"x": region.x,
|
||||
"y": region.y,
|
||||
"w": region.w,
|
||||
"h": region.h,
|
||||
"zorder": region.zorder,
|
||||
]
|
||||
}
|
||||
|
||||
private func convertCanvasToDic(canvas: LiveCanvas) -> [String: Any] {
|
||||
return [
|
||||
"templateID": canvas.templateID,
|
||||
"w": canvas.w,
|
||||
"h": canvas.h,
|
||||
]
|
||||
}
|
||||
|
||||
public func setupLiveSeatEvent(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
liveSeatEventCancellables.removeAll()
|
||||
LiveSeatStore.create(liveID: liveID).liveSeatEventPublisher
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] event in
|
||||
guard let self = self else { return }
|
||||
switch event {
|
||||
case .onLocalCameraOpenedByAdmin(let policy):
|
||||
callback("onLocalCameraOpenedByAdmin", convertDeviceControlPolicy(policy))
|
||||
case .onLocalCameraClosedByAdmin:
|
||||
callback("onLocalCameraClosedByAdmin", "")
|
||||
case .onLocalMicrophoneOpenedByAdmin(let policy):
|
||||
callback("onLocalMicrophoneOpenedByAdmin", convertDeviceControlPolicy(policy))
|
||||
case .onLocalMicrophoneClosedByAdmin:
|
||||
callback("onLocalMicrophoneClosedByAdmin", "")
|
||||
}
|
||||
}.store(in: &liveSeatEventCancellables)
|
||||
}
|
||||
|
||||
private func convertDeviceControlPolicy(_ reason: DeviceControlPolicy) -> String {
|
||||
if reason == DeviceControlPolicy.unlockOnly {
|
||||
return "UNLOCK_ONLY"
|
||||
}
|
||||
return "FORCE_OPEN"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class LiveSummaryStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
public static let shared = LiveSummaryStoreObserver()
|
||||
|
||||
public func liveSummaryStoreChanged(
|
||||
_ liveID: String, _ callback: @escaping (_ name: String, _ data: String) -> Void
|
||||
) {
|
||||
cancellables.removeAll()
|
||||
|
||||
LiveSummaryStore.create(liveID: liveID)
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LiveSummaryState.summaryData))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { data in
|
||||
let dict = TypeConvert.convertLiveSummaryDataToDic(summaryData: data)
|
||||
if let json = JsonUtil.toJson(dict) {
|
||||
callback("summaryData", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import AtomicXCore
|
||||
import Combine
|
||||
import DCloudUTSFoundation
|
||||
import RTCRoomEngine
|
||||
|
||||
public class LoginStoreObserver {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
public static let shared = LoginStoreObserver()
|
||||
|
||||
public func loginStoreChanged(_ callback: @escaping (_ name: String, _ data: String) -> Void) {
|
||||
cancellables.removeAll()
|
||||
|
||||
LoginStore.shared
|
||||
.state.subscribe(StatePublisherSelector(keyPath: \LoginState.loginUserInfo))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] userInfo in
|
||||
guard let self = self else { return }
|
||||
guard let userInfo = userInfo else { return }
|
||||
if let jsonString = JsonUtil.toJson(
|
||||
self.converUserProfileToDic(userProfile: userInfo))
|
||||
{
|
||||
callback("loginUserInfo", jsonString)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
|
||||
LoginStore.shared.state.subscribe(StatePublisherSelector(keyPath: \LoginState.loginStatus))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { value in
|
||||
var loginStatus = "UNLOGIN"
|
||||
if value == .logined {
|
||||
loginStatus = "LOGINED"
|
||||
}
|
||||
if let json = JsonUtil.toJson(loginStatus) {
|
||||
callback("loginStatus", json)
|
||||
}
|
||||
}).store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func converUserProfileToDic(userProfile: UserProfile) -> [String: Any] {
|
||||
return [
|
||||
"userID": userProfile.userID,
|
||||
"nickname": userProfile.nickname,
|
||||
"avatarURL": userProfile.avatarURL,
|
||||
"selfSignature": userProfile.selfSignature,
|
||||
"gender": convertGender(gender: userProfile.gender),
|
||||
"role": userProfile.role,
|
||||
"level": userProfile.level,
|
||||
"allowType": convertAllowType(type: userProfile.allowType),
|
||||
// "customInfo": userProfile.customInfo, //TODO:暂不支持
|
||||
]
|
||||
}
|
||||
private func convertGender(gender: Gender?) -> String {
|
||||
var genderStr = "UNKNOWN"
|
||||
if( gender == .male) {
|
||||
genderStr = "MALE"
|
||||
} else if( gender == .female) {
|
||||
genderStr = "FEMALE"
|
||||
}
|
||||
return genderStr
|
||||
}
|
||||
private func convertAllowType(type: AllowType?) -> String {
|
||||
var allowType = "ALLOW_ANY"
|
||||
if(type == .needConfirm) {
|
||||
allowType = "NEED_CONFIRM"
|
||||
} else if(type == .denyAny) {
|
||||
allowType = "DENY_ANY"
|
||||
}
|
||||
return allowType
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import AtomicXCore
|
||||
import RTCRoomEngine
|
||||
|
||||
struct TypeConvert {
|
||||
|
||||
static func convertLiveUserInfoToDic(liveUserInfo: LiveUserInfo) -> [String: String] {
|
||||
var dict: [String: String] = [
|
||||
"userID": liveUserInfo.userID ?? "",
|
||||
"userName": liveUserInfo.userName ?? "",
|
||||
"avatarURL": liveUserInfo.avatarURL ?? "",
|
||||
]
|
||||
return dict
|
||||
}
|
||||
|
||||
static func convertUserRole(_ role: Role?) -> String {
|
||||
switch role {
|
||||
case .admin:
|
||||
return "ADMIN"
|
||||
case .generalUser:
|
||||
return "GENERAL_USER"
|
||||
default:
|
||||
return "OWNER"
|
||||
}
|
||||
}
|
||||
|
||||
static func convertSeatUserInfoToDic(seatUserInfo: SeatUserInfo) -> [String: Any] {
|
||||
var dict: [String: Any] = [
|
||||
"userID": seatUserInfo.userID,
|
||||
"userName": seatUserInfo.userName ?? "",
|
||||
"avatarURL": seatUserInfo.avatarURL ?? "",
|
||||
"role": convertUserRole(seatUserInfo.role),
|
||||
"liveID": seatUserInfo.liveID,
|
||||
"microphoneStatus": convertDeviceStatus(seatUserInfo.microphoneStatus),
|
||||
"allowOpenMicrophone": seatUserInfo.allowOpenMicrophone,
|
||||
"cameraStatus": convertDeviceStatus(seatUserInfo.cameraStatus),
|
||||
"allowOpenCamera": seatUserInfo.allowOpenCamera,
|
||||
]
|
||||
return dict
|
||||
}
|
||||
|
||||
static func convertDeviceStatus(_ status: DeviceStatus) -> String {
|
||||
switch status {
|
||||
case .on:
|
||||
return "ON"
|
||||
case .off:
|
||||
return "OFF"
|
||||
}
|
||||
}
|
||||
|
||||
static func convertLiveInfoToDic(liveInfo: LiveInfo) -> [String: Any] {
|
||||
var dict: [String: Any] = [
|
||||
"liveID": liveInfo.liveID,
|
||||
"liveName": liveInfo.liveName,
|
||||
"notice": liveInfo.notice,
|
||||
"isMessageDisable": liveInfo.isMessageDisable,
|
||||
"isPublicVisible": liveInfo.isPublicVisible,
|
||||
"isSeatEnabled": liveInfo.isSeatEnabled,
|
||||
"keepOwnerOnSeat": liveInfo.keepOwnerOnSeat,
|
||||
"maxSeatCount": liveInfo.maxSeatCount,
|
||||
"seatMode": TypeConvert.convertTakeSeatMode(liveInfo.seatMode),
|
||||
"seatLayoutTemplateID": liveInfo.seatLayoutTemplateID,
|
||||
"coverURL": liveInfo.coverURL,
|
||||
"backgroundURL": liveInfo.backgroundURL,
|
||||
"activityStatus": liveInfo.activityStatus,
|
||||
"liveOwner": TypeConvert.convertLiveUserInfoToDic(liveUserInfo: liveInfo.liveOwner),
|
||||
"createTime" : liveInfo.createTime,
|
||||
"categoryList": liveInfo.categoryList,
|
||||
"totalViewerCount": liveInfo.totalViewerCount,
|
||||
"isGiftEnabled": liveInfo.isGiftEnabled,
|
||||
"metaData": liveInfo.metaData,
|
||||
]
|
||||
return dict
|
||||
}
|
||||
|
||||
static func convertTakeSeatMode(_ mode: TakeSeatMode) -> String {
|
||||
switch mode {
|
||||
case .free:
|
||||
return "FREE"
|
||||
case .apply:
|
||||
return "APPLY"
|
||||
}
|
||||
}
|
||||
|
||||
static func convertLiveSummaryDataToDic(summaryData: LiveSummaryData) -> [String: Any] {
|
||||
var dict: [String: Any] = [
|
||||
"totalDuration": summaryData.totalDuration,
|
||||
"totalViewers": summaryData.totalViewers,
|
||||
"totalGiftsSent": summaryData.totalGiftsSent,
|
||||
"totalGiftUniqueSenders": summaryData.totalGiftUniqueSenders,
|
||||
"totalGiftCoins": summaryData.totalGiftCoins,
|
||||
"totalLikesReceived": summaryData.totalLikesReceived,
|
||||
"totalMessageSent": summaryData.totalMessageSent,
|
||||
]
|
||||
return dict
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user