Files
midi_ios/TUIKit/TUIRoomKit/Source/View/ViewModel/ConferenceMainViewModel.swift
2025-08-14 10:07:49 +08:00

654 lines
28 KiB
Swift

//
// ConferenceMainViewModel.swift
// TUIRoomKit
//
// Created by aby on 2022/12/27.
// Copyright © 2022 Tencent. All rights reserved.
//
import Foundation
import TUICore
import RTCRoomEngine
import Factory
protocol ConferenceMainViewResponder: AnyObject {
func makeToast(text: String)
func changeToolBarHiddenState()
func setToolBarDelayHidden(isDelay: Bool)
func showExitRoomView()
func showAlert(title: String?, message: String?, sureTitle:String?, declineTitle: String?, sureBlock: (() -> ())?, declineBlock: (() -> ())?)
func showAlertWithAutoConfirm(title: String?, message: String?, sureTitle:String?, declineTitle: String?, sureBlock: (() -> ())?, declineBlock: (() -> ())?, autoConfirmSeconds: Int?)
func showRaiseHandNoticeView()
func updateRoomInfo(roomInfo: TUIRoomInfo)
func showPasswordView(roomId: String)
func hidePasswordView()
func showRepeatJoinRoomAlert()
}
class ConferenceMainViewModel: NSObject {
weak var viewResponder: ConferenceMainViewResponder? = nil
var engineManager: EngineManager {
EngineManager.shared
}
var store: RoomStore {
engineManager.store
}
var roomInfo: TUIRoomInfo {
store.roomInfo
}
var currentUser: UserEntity {
store.currentUser
}
let roomRouter: RoomRouter = RoomRouter.shared
private var isShownOpenCameraInviteAlert = false
private var isShownOpenMicrophoneInviteAlert = false
private var isShownTakeSeatInviteAlert = false
private weak var localAudioViewModel: LocalAudioViewModel?
private var selfRole: TUIRole?
var joinConferenceParams: JoinConferenceParams?
var startConferenceParams: StartConferenceParams?
var isShownWaterMark: Bool = ConferenceSession.sharedInstance.implementation.isEnableWaterMark;
override init() {
super.init()
selfRole = currentUser.userRole
subscribeEngine()
subLogoutNotification()
}
private func subscribeEngine() {
EngineEventCenter.shared.subscribeEngine(event: .onRoomDismissed, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onKickedOutOfRoom, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onRequestReceived, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onAllUserMicrophoneDisableChanged, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onAllUserCameraDisableChanged, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onKickedOffSeat, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onKickedOffLine, observer: self)
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_CurrentUserRoleChanged, responder: self)
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_CurrentUserMuteMessage, responder: self)
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_SetToolBarDelayHidden, responder: self)
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_ChangeToolBarHiddenState, responder: self)
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_ShowExitRoomView, responder: self)
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, responder: self)
EngineEventCenter.shared.subscribeEngine(event: .onStartedRoom, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onJoinedRoom, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onGetUserListFinished, observer: self)
}
private func subLogoutNotification() {
NotificationCenter.default.addObserver(self,
selector: #selector(dismissConferenceViewForLogout),
name: NSNotification.Name.TUILogoutSuccess, object: nil)
}
private func unsubLogoutNotification() {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.TUILogoutSuccess, object: nil)
}
private func unsubscribeEngine() {
EngineEventCenter.shared.unsubscribeEngine(event: .onRoomDismissed, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onKickedOutOfRoom, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onRequestReceived, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onAllUserMicrophoneDisableChanged, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onAllUserCameraDisableChanged, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onKickedOffSeat, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onKickedOffLine, observer: self)
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_CurrentUserRoleChanged, responder: self)
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_CurrentUserMuteMessage, responder: self)
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_SetToolBarDelayHidden, responder: self)
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_ChangeToolBarHiddenState, responder: self)
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_ShowExitRoomView, responder: self)
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, responder: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onStartedRoom, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onJoinedRoom, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onGetUserListFinished, observer: self)
}
func hideLocalAudioView() {
localAudioViewModel?.hideLocalAudioView()
}
func showLocalAudioView() {
localAudioViewModel?.showLocalAudioView()
}
func onViewDidLoadAction() {
if store.isEnteredRoom {
let roomId = startConferenceParams?.roomId ?? joinConferenceParams?.roomId
if let roomId = roomId, store.roomInfo.roomId != roomId {
viewResponder?.showRepeatJoinRoomAlert()
}
return
}
if startConferenceParams != nil {
quickStartConference()
return
}
if joinConferenceParams != nil {
joinConference()
}
}
func quickStartConference() {
guard let startParams = startConferenceParams, !startParams.roomId.isEmpty else {
return
}
ConferenceOptions.quickStart(startConferenceParams: startParams) { [weak self] roomInfo in
guard let self = self else { return }
guard !self.viewStore.isInternalCreation else { return }
self.notifySuccess(roomInfo: roomInfo, event: .onStartedRoom)
} onError: { [weak self] code, message in
guard let self = self else { return }
self.handleOperateConferenceFailedResult(roomId: startParams.roomId, event: .onStartedRoom, error: code, message: message)
}
}
func joinConference() {
guard let joinParams = joinConferenceParams, !joinParams.roomId.isEmpty else {
return
}
ConferenceOptions.join(joinConferenParams: joinParams) { [weak self] roomInfo in
guard let self = self else { return }
self.viewResponder?.hidePasswordView()
self.notifySuccess(roomInfo: roomInfo, event: .onJoinedRoom)
} onError: { [weak self] code, message in
guard let self = self else { return }
if code == .needPassword {
self.viewResponder?.showPasswordView(roomId: joinParams.roomId)
} else if code == .wrongPassword {
self.viewResponder?.makeToast(text: .wrongPasswordText)
} else {
self.handleOperateConferenceFailedResult(roomId: joinParams.roomId, event: .onJoinedRoom, error: code, message: message)
}
}
}
func notifySuccess(roomInfo: TUIRoomInfo?,
event: EngineEventCenter.RoomEngineEvent) {
let param = [
"roomInfo" : roomInfo ?? TUIRoomInfo(),
"error" : TUIError.success,
"mesasge" : ""
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: event, param: param)
}
func notifyError(roomId: String,
event: EngineEventCenter.RoomEngineEvent,
error: TUIError,
message: String) {
let roomInfo = TUIRoomInfo()
roomInfo.roomId = roomId
let param = [
"roomInfo" : roomInfo,
"error" : error,
"mesasge" : message
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: event, param: param)
}
func setJoinConferenceParams(params: JoinConferenceParams) {
joinConferenceParams = params
store.setCameraOpened(params.isOpenCamera)
store.setSoundOnSpeaker(params.isOpenSpeaker)
}
func setStartConferenceParams(params: StartConferenceParams) {
startConferenceParams = params
store.setCameraOpened(params.isOpenCamera)
store.setSoundOnSpeaker(params.isOpenSpeaker)
}
@objc func dismissConferenceViewForLogout() {
viewResponder?.showAlertWithAutoConfirm(title: .logoutText, message: nil, sureTitle: .alertOkText, declineTitle: nil, sureBlock: {
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, param: [:])
}, declineBlock: nil, autoConfirmSeconds: 5)
}
func handleWrongPasswordFault(roomId: String) {
handleOperateConferenceFailedResult(roomId: roomId, event: .onJoinedRoom, error: .wrongPassword, message: "password is wrong")
}
private func handleOperateConferenceFailedResult(roomId: String, event: EngineEventCenter.RoomEngineEvent, error: TUIError, message: String) {
if viewStore.isInternalCreation {
roomRouter.pop()
let errorText = "Error: " + String(describing: error) + ", Message: " + message
conferenceStore.dispatch(action: ViewActions.showToast(payload: ToastInfo(message: errorText)))
} else {
notifyError(roomId: roomId, event: event, error: error, message: message)
}
}
deinit {
unsubscribeEngine()
unsubLogoutNotification()
debugPrint("deinit \(self)")
}
@Injected(\.conferenceStore) var conferenceStore: ConferenceStore
@Injected(\.conferenceMainViewStore) var viewStore: ConferenceMainViewStore
}
extension ConferenceMainViewModel: RoomEngineEventResponder {
func onEngineEvent(name: EngineEventCenter.RoomEngineEvent, param: [String : Any]?) {
switch name {
case .onRoomDismissed:
handleRoomDismissed()
case .onKickedOutOfRoom:
handleKickedOutOfRoom()
case .onAllUserMicrophoneDisableChanged:
guard let isDisable = param?["isDisable"] as? Bool else { return }
handleAllUserMicrophoneDisableChanged(isDisable: isDisable)
case .onAllUserCameraDisableChanged:
guard let isDisable = param?["isDisable"] as? Bool else { return }
handleAllUserCameraDisableChanged(isDisable: isDisable)
case .onKickedOffSeat:
viewResponder?.makeToast(text: .kickedOffSeat)
case .onRequestReceived:
guard let request = param?["request"] as? TUIRequest else { return }
handleReceivedRequest(request: request)
case .onKickedOffLine:
handleKickedOffLine()
case .onStartedRoom:
guard let roomInfo = param?["roomInfo"] as? TUIRoomInfo else { return }
guard let error = param?["error"] as? TUIError else { return }
if error == .success {
handleStartRoom(roomInfo: roomInfo)
conferenceStore.dispatch(action: RoomActions.updateRoomState(payload: RoomInfo(with: roomInfo)))
}
case .onJoinedRoom:
guard let roomInfo = param?["roomInfo"] as? TUIRoomInfo else { return }
guard let error = param?["error"] as? TUIError else { return }
if error == .success {
handleJoinRoom(roomInfo: roomInfo)
conferenceStore.dispatch(action: RoomActions.updateRoomState(payload: RoomInfo(with: roomInfo)))
}
case .onGetUserListFinished:
let allUsers = self.store.attendeeList.map{ UserInfo(userEntity: $0) }
conferenceStore.dispatch(action: UserActions.updateAllUsers(payload: allUsers))
conferenceStore.dispatch(action: ConferenceInvitationActions.getInvitationList(payload: (store.roomInfo.roomId, "", [])))
default: break
}
}
private func handleRoomDismissed() {
#if RTCube_APPSTORE
if currentUser.userRole == .roomOwner {
let selector = NSSelectorFromString("showAlertUserLiveTimeOut")
if UIViewController.responds(to: selector) {
UIViewController.perform(selector)
}
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, param: [:])
engineManager.destroyEngineManager()
return
}
#endif
engineManager.destroyEngineManager()
viewResponder?.showAlertWithAutoConfirm(title: .destroyAlertText, message: nil, sureTitle: .alertOkText, declineTitle: nil, sureBlock: {
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, param: [:])
}, declineBlock: nil, autoConfirmSeconds: 5)
}
private func handleKickedOutOfRoom() {
engineManager.destroyEngineManager()
viewResponder?.showAlertWithAutoConfirm(title: .kickOffTitleText, message: nil, sureTitle: .alertOkText, declineTitle: nil , sureBlock: {
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, param: [:])
}, declineBlock: nil, autoConfirmSeconds: 5)
}
private func handleAllUserMicrophoneDisableChanged(isDisable: Bool) {
if isDisable {
RoomRouter.makeToastInCenter(toast: .allMuteAudioText, duration: 1.5)
} else {
RoomRouter.makeToastInCenter(toast: .allUnMuteAudioText, duration: 1.5)
}
}
private func handleAllUserCameraDisableChanged(isDisable: Bool) {
if isDisable {
RoomRouter.makeToastInCenter(toast: .allMuteVideoText, duration: 1.5)
} else {
RoomRouter.makeToastInCenter(toast: .allUnMuteVideoText, duration: 1.5)
}
}
private func handleReceivedRequest(request: TUIRequest) {
switch request.requestAction {
case .openRemoteCamera:
handleOpenCameraRequest(request: request)
case .openRemoteMicrophone:
handleOpenMicrophoneRequest(request: request)
case .invalidAction:
break
case .remoteUserOnSeat:
handleOnSeatRequest(request: request)
default: break
}
}
private func handleOpenCameraRequest(request: TUIRequest) {
guard !isShownOpenCameraInviteAlert else { return }
guard let userInfo = store.attendeeList.first(where: { $0.userId == request.userId }) else { return }
let nameText: String = userInfo.userRole == .roomOwner ? .hostText : .administratorText
let title = localizedReplace(.inviteTurnOnVideoText, replace: nameText)
viewResponder?.showAlert(title: title, message: nil, sureTitle: .agreeText, declineTitle: .declineText, sureBlock: { [weak self] in
guard let self = self else { return }
self.isShownOpenCameraInviteAlert = false
self.agreeOpenLocalCamera(request: request)
}, declineBlock: { [weak self] in
guard let self = self else { return }
self.isShownOpenCameraInviteAlert = false
self.engineManager.responseRemoteRequest(request.requestId, agree: false)
})
isShownOpenCameraInviteAlert = true
}
private func agreeOpenLocalCamera(request: TUIRequest) {
engineManager.setLocalVideoView(streamType: .cameraStream, view: nil)
if RoomCommon.checkAuthorCamaraStatusIsDenied() {
engineManager.responseRemoteRequest(request.requestId, agree: true)
} else {
RoomCommon.cameraStateActionWithPopCompletion { [weak self] granted in
guard let self = self else { return }
self.engineManager.responseRemoteRequest(request.requestId, agree: granted)
}
}
}
private func handleOpenMicrophoneRequest(request: TUIRequest) {
guard !isShownOpenMicrophoneInviteAlert else { return }
guard let userInfo = store.attendeeList.first(where: { $0.userId == request.userId }) else { return }
let nameText: String = userInfo.userRole == .roomOwner ? .hostText : .administratorText
let title = localizedReplace(.inviteTurnOnAudioText, replace: nameText)
viewResponder?.showAlert(title: title, message: nil, sureTitle: .agreeText, declineTitle: .declineText, sureBlock: { [weak self] in
guard let self = self else { return }
self.isShownOpenMicrophoneInviteAlert = false
self.agreeOpenLocalMic(request: request)
}, declineBlock: { [weak self] in
guard let self = self else { return }
self.isShownOpenMicrophoneInviteAlert = false
self.engineManager.responseRemoteRequest(request.requestId, agree: false)
})
isShownOpenMicrophoneInviteAlert = true
}
private func agreeOpenLocalMic(request: TUIRequest) {
if RoomCommon.checkAuthorMicStatusIsDenied() {
self.engineManager.responseRemoteRequest(request.requestId, agree: true)
} else {
RoomCommon.micStateActionWithPopCompletion { [weak self] granted in
guard let self = self else { return }
self.engineManager.responseRemoteRequest(request.requestId, agree: granted)
}
}
}
private func handleOnSeatRequest(request: TUIRequest) {
guard roomInfo.isSeatEnabled && !isShownTakeSeatInviteAlert else { return }
guard let userInfo = store.attendeeList.first(where: { $0.userId == request.userId }) else { return }
let nameText: String = userInfo.userRole == .roomOwner ? .hostText : .administratorText
let title = localizedReplace(.inviteSpeakOnStageTitle, replace: nameText)
viewResponder?.showAlert(title: title, message: .inviteSpeakOnStageMessage, sureTitle: .agreeSeatText, declineTitle: .declineText, sureBlock: { [weak self] in
guard let self = self else { return }
self.isShownTakeSeatInviteAlert = false
self.agreeOnSeatRequest(requestId: request.requestId)
}, declineBlock: { [weak self] in
guard let self = self else { return }
self.isShownTakeSeatInviteAlert = false
self.disagreeOnSeatRequest(requestId: request.requestId)
})
isShownTakeSeatInviteAlert = true
}
private func agreeOnSeatRequest(requestId: String) {
engineManager.responseRemoteRequest(requestId, agree: true) {
} onError: { [weak self] code, message in
guard let self = self else { return }
switch code {
case .failed:
self.viewResponder?.makeToast(text: .goOnStageTimedOutText)
case .allSeatOccupied:
self.viewResponder?.makeToast(text: .onStageNumberReachedLimitText)
default: break
}
}
}
private func disagreeOnSeatRequest(requestId: String) {
engineManager.responseRemoteRequest(requestId, agree: false) {
} onError: { code, message in
debugPrint("responseRemoteRequest:code:\(code),message:\(message)")
}
}
private func handleKickedOffLine() {
viewResponder?.showAlertWithAutoConfirm(title: .kieckedOffLineText, message: nil, sureTitle: .alertOkText, declineTitle: nil, sureBlock: {
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, param: [:])
}, declineBlock: nil, autoConfirmSeconds: 5)
}
private func handleStartRoom(roomInfo: TUIRoomInfo) {
viewResponder?.updateRoomInfo(roomInfo: roomInfo)
}
private func handleJoinRoom(roomInfo: TUIRoomInfo) {
if roomInfo.isSeatEnabled, store.isShownRaiseHandNotice {
viewResponder?.showRaiseHandNoticeView()
}
viewResponder?.updateRoomInfo(roomInfo: roomInfo)
}
}
extension ConferenceMainViewModel: ConferenceMainViewFactory {
func makeConferencePasswordView() -> ConferencePasswordView {
let passwordView = ConferencePasswordView()
passwordView.isHidden = true
passwordView.viewModel = self
return passwordView
}
func makeTopView() -> TopView {
let viewModel = TopViewModel()
let topView = TopView(viewModel: viewModel)
topView.backgroundColor = UIColor(0x0F1014)
return topView
}
func makeBottomView() -> BottomView {
let viewModel = BottomViewModel()
let bottomView = BottomView(viewModel: viewModel)
return bottomView
}
func makeVideoSeatView() -> UIView {
let viewModel = TUIVideoSeatViewModel()
let videoSeatView = TUIVideoSeatView(viewModel: viewModel)
videoSeatView.backgroundColor = UIColor(0x0F1014)
return videoSeatView
}
func makeRaiseHandNoticeView() -> UIView {
let raiseHandNoticeView = RaiseHandNoticeView()
raiseHandNoticeView.isHidden = true
return raiseHandNoticeView
}
func makeLocalAudioView() -> UIView {
let localAudioViewModel = LocalAudioViewModel()
localAudioViewModel.hideLocalAudioView()
let view = LocalAudioView(viewModel: localAudioViewModel)
self.localAudioViewModel = localAudioViewModel
return view
}
func makeWaterMarkLayer() -> WaterMarkLayer {
let layer = WaterMarkLayer()
layer.backgroundColor = UIColor.clear.cgColor
layer.anchorPoint = CGPointZero
layer.text = getWaterMarkText()
layer.lineStyle = .multiLine
layer.cornerRadius = 16
return layer
}
func makeFloatChatButton() -> FloatChatButton {
let floatchatButton = FloatChatButton()
floatchatButton.isHidden = !store.shouldShowFloatChatView
if store.isEnteredRoom {
floatchatButton.updateRoomId(roomId: store.roomInfo.roomId)
}
return floatchatButton
}
func makeFloatChatDisplayView() -> FloatChatDisplayView {
let view = FloatChatDisplayView()
view.isHidden = !store.shouldShowFloatChatView
return view
}
func makeRaiseHandApplicationNotificationView() -> RaiseHandApplicationNotificationView {
let viewModel = RaiseHandApplicationNotificationViewModel()
let notificationView = RaiseHandApplicationNotificationView(viewModel: viewModel)
return notificationView
}
private func getWaterMarkText() -> String {
let customizeText = ConferenceSession.sharedInstance.implementation.waterMarkText
if !customizeText.isEmpty {
return customizeText
}
let userId = TUILogin.getUserID() ?? currentUser.userId
let userName = TUILogin.getNickName() ?? currentUser.userName
var defaultText = userId
if !userName.isEmpty {
defaultText = defaultText + "(\(userName))"
}
return defaultText
}
}
extension ConferenceMainViewModel: RoomKitUIEventResponder {
func onNotifyUIEvent(key: EngineEventCenter.RoomUIEvent, Object: Any?, info: [AnyHashable : Any]?) {
switch key{
case .TUIRoomKitService_CurrentUserRoleChanged:
guard let userRole = info?["userRole"] as? TUIRole else { return }
handleSelfRoleChanged(userRole: userRole)
case .TUIRoomKitService_CurrentUserMuteMessage:
guard let isMute = info?["isMute"] as? Bool else { return }
viewResponder?.makeToast(text: isMute ? .messageTurnedOffText : .messageTurnedOnText)
case .TUIRoomKitService_ChangeToolBarHiddenState:
viewResponder?.changeToolBarHiddenState()
case .TUIRoomKitService_SetToolBarDelayHidden:
guard let isDelay = info?["isDelay"] as? Bool else { return }
viewResponder?.setToolBarDelayHidden(isDelay: isDelay)
case .TUIRoomKitService_ShowExitRoomView:
viewResponder?.showExitRoomView()
case .TUIRoomKitService_DismissConferenceViewController:
conferenceStore.dispatch(action: ConferenceInvitationActions.clearInvitationList())
conferenceStore.dispatch(action: RoomActions.clearRoomState())
default: break
}
}
private func handleSelfRoleChanged(userRole: TUIRole) {
switch userRole {
case .roomOwner:
viewResponder?.makeToast(text: .haveBecomeMasterText)
case .administrator:
viewResponder?.makeToast(text: .haveBecomeAdministratorText)
case .generalUser:
if selfRole == .administrator {
viewResponder?.makeToast(text: .revokedAdministratorText)
}
default: break
}
selfRole = userRole
}
}
private extension String {
static var kickOffTitleText: String {
localized("You were removed by the host.")
}
static var destroyAlertText: String {
localized("The conference was closed.")
}
static var inviteTurnOnAudioText: String {
localized("xx invites you to turn on the microphone")
}
static var inviteTurnOnVideoText: String {
localized("xx invites you to turn on the camera")
}
static var inviteSpeakOnStageTitle: String {
localized("xx invites you to speak on stage")
}
static var inviteSpeakOnStageMessage: String {
localized("You can turn on the camera and unmute it once you are on stage")
}
static var messageTurnedOffText: String {
localized("You were muted message by the host.")
}
static var messageTurnedOnText: String {
localized("You were unmuted message by the host.")
}
static var haveBecomeMasterText: String {
localized("You are now a host")
}
static var haveBecomeAdministratorText: String {
localized("You have become a conference admin")
}
static var kickedOffLineText: String {
localized("You are already logged in elsewhere")
}
static var alertOkText: String {
localized("OK")
}
static var declineText: String {
localized("Decline")
}
static var agreeText: String {
localized("Agree")
}
static var agreeSeatText: String {
localized("Approve")
}
static var allMuteAudioText: String {
localized("All audios disabled")
}
static var allMuteVideoText: String {
localized("All videos disabled")
}
static var allUnMuteAudioText: String {
localized("All audios enabled")
}
static var allUnMuteVideoText: String {
localized("All videos enabled")
}
static var kickedOffSeat: String {
localized("You have been asked to leave stage")
}
static var hostText: String {
localized("Host")
}
static var administratorText: String {
localized("Administrator")
}
static var revokedAdministratorText: String {
localized("Your conference admin status has been revoked")
}
static var onStageNumberReachedLimitText: String {
localized("The stage is full, please contact the host")
}
static var goOnStageTimedOutText: String {
localized("Failed to go on stage, invitation has timed out")
}
static var kieckedOffLineText: String {
localized("You are already logged in elsewhere")
}
static var logoutText: String {
localized("You are logged out")
}
static let wrongPasswordText = localized("Wrong password, please re-enter")
}