UNPKG

@tencentcloud/roomkit-electron-vue3

Version:

<h1 align="center"> TUIRoomKit</h1> Conference (TUIRoomKit) is a product suitable for multi-person audio and video conversation scenarios such as business meetings, webinars, and online education. By integrating this product, you can add room management,

511 lines (510 loc) 18 kB
import { ref, reactive, computed } from "vue"; import { useI18n } from "../../../locales/index.mjs"; import { useRoomStore } from "../../../stores/room.mjs"; import useGetRoomEngine from "../../../hooks/useRoomEngine.mjs"; import { useBasicStore } from "../../../stores/basic.mjs"; import useMasterApplyControl from "../../../hooks/useMasterApplyControl.mjs"; import { TUIRole, TUIMediaDevice, TUIRequestCallbackType, TUIErrorCode } from "@tencentcloud/tuiroom-engine-electron"; import AudioOpenIcon from "../../common/icons/AudioOpenIcon.vue.mjs"; import VideoOpenIcon from "../../common/icons/VideoOpenIcon.vue.mjs"; import ChatForbiddenIcon from "../../common/icons/ChatForbiddenIcon.vue.mjs"; import KickOutIcon from "../../common/icons/KickOutIcon.vue.mjs"; import InviteOnStageIcon from "../../common/icons/InviteOnStageIcon.vue.mjs"; import DenyOnStageIcon from "../../common/icons/DenyOnStageIcon.vue.mjs"; import OnStageIcon from "../../common/icons/OnStageIcon.vue.mjs"; import OffStageIcon from "../../common/icons/OffStageIcon.vue.mjs"; import TransferOwnerIcon from "../../common/icons/TransferOwnerIcon.vue.mjs"; import SetAdminIcon from "../../common/icons/SetAdminIcon.vue.mjs"; import RevokeAdminIcon from "../../common/icons/RevokeAdminIcon.vue.mjs"; import EditNameCardIcon from "../../common/icons/EditNameCardIcon.vue.mjs"; import { storeToRefs } from "pinia"; import renderMsg from "../../common/base/Message/Message.mjs"; import { MESSAGE_DURATION } from "../../../constants/message.mjs"; import bus from "../../../hooks/useMitt.mjs"; import useMemberItem from "../MemberItem/useMemberItemHooks.mjs"; import "../../../services/main.mjs"; import { roomService } from "../../../services/roomService.mjs"; import { isMobile } from "../../../utils/environment.mjs"; import { calculateByteLength } from "../../../utils/utils.mjs"; import "mitt"; import "../../../services/manager/roomActionManager.mjs"; import "@tencentcloud/tui-core"; function useMemberControl(props) { const roomEngine = useGetRoomEngine(); const { t } = useI18n(); const basicStore = useBasicStore(); const roomStore = useRoomStore(); const isDialogVisible = ref(false); const isShowInput = ref(false); const editorInputEle = ref(); const editorInputEleContainer = ref(); const tempUserName = ref(""); const dialogData = reactive({ title: "", content: "", confirmText: "", actionType: "", showInput: false, isConfirmButtonDisable: false }); const kickOffDialogContent = computed( () => t("whether to kick sb off the room", { name: roomService.getDisplayName(props.userInfo) }) ); const transferOwnerTitle = computed( () => t("Transfer the roomOwner to sb", { name: roomService.getDisplayName(props.userInfo) }) ); const { isFreeSpeakMode, isSpeakAfterTakingSeatMode, localUser, isGeneralUser, anchorUserList, maxSeatCount } = storeToRefs(roomStore); const { agreeUserOnStage, denyUserOnStage, inviteUserOnStage, cancelInviteUserOnStage, kickUserOffStage } = useMasterApplyControl(); const { isCanOperateMySelf } = useMemberItem(props.userInfo); const isMe = computed(() => basicStore.userId === props.userInfo.userId); const isTargetUserAnchor = computed(() => props.userInfo.onSeat === true); const isTargetUserAudience = computed(() => props.userInfo.onSeat !== true); const controlList = computed(() => { if (isCanOperateMySelf.value) { return [changeUserNameCard.value]; } const agreeOrDenyStageList = props.userInfo.isUserApplyingToAnchor ? [agreeOnStage.value, denyOnStage.value] : []; const inviteStageList = isTargetUserAudience.value && !props.userInfo.isUserApplyingToAnchor ? [inviteOnStage.value] : []; const onStageControlList = isTargetUserAnchor.value ? [audioControl.value, videoControl.value, makeOffStage.value] : []; const controlListObj = { freeSpeak: { [TUIRole.kRoomOwner]: [ audioControl.value, videoControl.value, chatControl.value, setOrRevokeAdmin.value, transferOwner.value, kickUser.value, changeUserNameCard.value ], [TUIRole.kAdministrator]: [ audioControl.value, videoControl.value, chatControl.value, changeUserNameCard.value ] }, speakAfterTakeSeat: { [TUIRole.kRoomOwner]: [ ...inviteStageList, ...onStageControlList, ...agreeOrDenyStageList, setOrRevokeAdmin.value, transferOwner.value, chatControl.value, kickUser.value, changeUserNameCard.value ], [TUIRole.kAdministrator]: [ ...inviteStageList, ...onStageControlList, ...agreeOrDenyStageList, chatControl.value, changeUserNameCard.value ] } }; if (isFreeSpeakMode.value) { return controlListObj.freeSpeak[localUser.value.userRole] || []; } if (isSpeakAfterTakingSeatMode.value) { return controlListObj.speakAfterTakeSeat[localUser.value.userRole] || []; } return []; }); const audioControl = computed(() => ({ key: "audioControl", icon: AudioOpenIcon, title: props.userInfo.hasAudioStream ? t("Mute") : t("Unmute"), func: muteUserAudio })); const videoControl = computed(() => { const videoControlTitle = props.userInfo.hasVideoStream ? t("Disable video") : t("Enable video"); return { key: "videoControl", icon: VideoOpenIcon, title: videoControlTitle, func: muteUserVideo }; }); const chatControl = computed(() => ({ key: "chatControl", icon: ChatForbiddenIcon, title: props.userInfo.isMessageDisabled ? t("Enable chat") : t("Disable chat"), func: disableUserChat })); const transferOwner = computed(() => ({ key: "transferOwner", icon: TransferOwnerIcon, title: t("Make host"), func: () => handleOpenDialog("transferOwner") })); const setOrRevokeAdmin = computed(() => ({ key: "setOrRevokeAdmin", icon: props.userInfo.userRole === TUIRole.kAdministrator ? RevokeAdminIcon : SetAdminIcon, title: props.userInfo.userRole === TUIRole.kAdministrator ? t("Remove administrator") : t("Set as administrator"), func: handleSetOrRevokeAdmin })); const kickUser = computed(() => ({ key: "kickUser", icon: KickOutIcon, title: t("Kick out"), func: () => handleOpenDialog("kickUser") })); const inviteOnStage = computed(() => ({ key: "inviteOnStage", icon: props.userInfo.isInvitingUserToAnchor ? DenyOnStageIcon : InviteOnStageIcon, title: props.userInfo.isInvitingUserToAnchor ? t("Cancel stage") : t("Invite stage"), func: toggleInviteUserOnStage })); const agreeOnStage = computed(() => ({ key: "agreeOnStage", icon: OnStageIcon, title: t("Agree to the stage"), func: agreeUserOnStage })); const denyOnStage = computed(() => ({ key: "denyOnStage", icon: DenyOnStageIcon, title: t("Refuse stage"), func: denyUserOnStage })); const makeOffStage = computed(() => ({ key: "makeOffStage", icon: OffStageIcon, title: t("Step down"), func: kickUserOffStage })); const changeUserNameCard = computed(() => ({ key: "changeUserNameCard", icon: EditNameCardIcon, title: t("change name"), func: () => handleOpenDialog("changeUserNameCard") })); async function toggleInviteUserOnStage(userInfo) { const { isInvitingUserToAnchor } = userInfo; if (isInvitingUserToAnchor) { cancelInviteUserOnStage(userInfo); } else { if (anchorUserList.value.length === maxSeatCount.value) { renderMsg({ type: "warning", message: `${t("The stage is full")}`, duration: MESSAGE_DURATION.NORMAL }); return; } inviteUserOnStage(userInfo); } } async function muteUserAudio(userInfo) { var _a, _b; if (userInfo.hasAudioStream) { await ((_a = roomEngine.instance) == null ? void 0 : _a.closeRemoteDeviceByAdmin({ userId: userInfo.userId, device: TUIMediaDevice.kMicrophone })); } else { if (userInfo.isRequestingUserOpenMic) { renderMsg({ type: "info", message: `${t("An invitation to open the microphone has been sent to sb.", { name: roomService.getDisplayName(userInfo) })}`, duration: MESSAGE_DURATION.NORMAL }); return; } const request = await ((_b = roomEngine.instance) == null ? void 0 : _b.openRemoteDeviceByAdmin({ userId: userInfo.userId, device: TUIMediaDevice.kMicrophone, timeout: 0, requestCallback: (callbackInfo) => { roomStore.setRequestUserOpenMic({ userId: userInfo.userId, isRequesting: false }); const { requestCallbackType, code } = callbackInfo; switch (requestCallbackType) { case TUIRequestCallbackType.kRequestError: if (code === TUIErrorCode.ERR_REQUEST_ID_REPEAT) { renderMsg({ type: "warning", message: t( "This member has already received the same request, please try again later" ), duration: MESSAGE_DURATION.NORMAL }); } break; } } })); renderMsg({ type: "info", message: `${t("An invitation to open the microphone has been sent to sb.", { name: roomService.getDisplayName(userInfo) })}`, duration: MESSAGE_DURATION.NORMAL }); if (request && request.requestId) { roomStore.setRequestUserOpenMic({ userId: userInfo.userId, isRequesting: true, requestId: request.requestId }); } } } async function muteUserVideo(userInfo) { var _a, _b; if (userInfo.hasVideoStream) { await ((_a = roomEngine.instance) == null ? void 0 : _a.closeRemoteDeviceByAdmin({ userId: userInfo.userId, device: TUIMediaDevice.kCamera })); } else { if (userInfo.isRequestingUserOpenCamera) { renderMsg({ type: "info", message: `${t("An invitation to open the camera has been sent to sb.", { name: roomService.getDisplayName(userInfo) })}`, duration: MESSAGE_DURATION.NORMAL }); return; } const request = await ((_b = roomEngine.instance) == null ? void 0 : _b.openRemoteDeviceByAdmin({ userId: userInfo.userId, device: TUIMediaDevice.kCamera, timeout: 0, requestCallback: (callbackInfo) => { roomStore.setRequestUserOpenCamera({ userId: userInfo.userId, isRequesting: false }); const { requestCallbackType, code } = callbackInfo; switch (requestCallbackType) { case TUIRequestCallbackType.kRequestError: if (code === TUIErrorCode.ERR_REQUEST_ID_REPEAT) { renderMsg({ type: "warning", message: t( "This member has already received the same request, please try again later" ), duration: MESSAGE_DURATION.NORMAL }); } break; } } })); renderMsg({ type: "info", message: `${t("An invitation to open the camera has been sent to sb.", { name: roomService.getDisplayName(userInfo) })}`, duration: MESSAGE_DURATION.NORMAL }); if (request && request.requestId) { roomStore.setRequestUserOpenCamera({ userId: userInfo.userId, isRequesting: true, requestId: request.requestId }); } } } async function disableUserChat(userInfo) { var _a; const { isMessageDisabled } = userInfo; try { await ((_a = roomEngine.instance) == null ? void 0 : _a.disableSendingMessageByAdmin({ userId: userInfo.userId, isDisable: !isMessageDisabled })); roomStore.setMuteUserChat(userInfo.userId, !isMessageDisabled); } catch (error) { renderMsg({ type: "error", message: t("Failed to disable chat"), duration: MESSAGE_DURATION.NORMAL }); } } async function kickOffUser(userInfo) { var _a; await ((_a = roomEngine.instance) == null ? void 0 : _a.kickRemoteUserOutOfRoom({ userId: userInfo.userId })); roomStore.removeUserInfo(userInfo.userId); } async function handleTransferOwner(userInfo) { var _a, _b; const roomInfo = await ((_a = roomEngine.instance) == null ? void 0 : _a.fetchRoomInfo()); if ((roomInfo == null ? void 0 : roomInfo.roomOwner) === roomStore.localUser.userId) { try { if (roomStore.localUser.hasScreenStream && roomStore.isScreenShareDisableForAllUser) { bus.emit("ScreenShare:stopScreenShare"); } await ((_b = roomEngine.instance) == null ? void 0 : _b.changeUserRole({ userId: userInfo.userId, userRole: TUIRole.kRoomOwner })); roomStore.setMasterUserId(userInfo.userId); renderMsg({ type: "success", message: t("The room owner has been transferred to sb", { name: roomService.getDisplayName(userInfo) }), duration: MESSAGE_DURATION.NORMAL }); } catch (error) { renderMsg({ type: "error", message: t("Make host failed, please try again."), duration: MESSAGE_DURATION.NORMAL }); } } } async function handleSetOrRevokeAdmin(userInfo) { var _a, _b; const newRole = userInfo.userRole === TUIRole.kGeneralUser ? TUIRole.kAdministrator : TUIRole.kGeneralUser; await ((_a = roomEngine.instance) == null ? void 0 : _a.changeUserRole({ userId: userInfo.userId, userRole: newRole })); const updatedUserName = roomStore.getUserName(userInfo.userId); const tipMessage = newRole === TUIRole.kAdministrator ? `${t("sb has been set as administrator", { name: updatedUserName })}` : `${t("The administrator status of sb has been withdrawn", { name: updatedUserName })}`; renderMsg({ type: "success", message: tipMessage }); roomStore.setRemoteUserRole(userInfo.userId, newRole); if (newRole === TUIRole.kGeneralUser && userInfo.hasScreenStream) { await ((_b = roomEngine.instance) == null ? void 0 : _b.closeRemoteDeviceByAdmin({ userId: userInfo.userId, device: TUIMediaDevice.kScreen })); } } function handleOpenDialog(action) { var _a; switch (action) { case "kickUser": isDialogVisible.value = true; Object.assign(dialogData, { title: t("Note"), content: kickOffDialogContent.value, confirmText: t("Confirm"), actionType: action, showInput: false, isConfirmButtonDisable: false }); break; case "transferOwner": isDialogVisible.value = true; Object.assign(dialogData, { title: transferOwnerTitle.value, content: t( "After transfer the room owner, you will become a general user" ), confirmText: t("Confirm transfer"), actionType: action, showInput: false, isConfirmButtonDisable: false }); break; case "changeUserNameCard": tempUserName.value = props.userInfo.nameCard || props.userInfo.userName; if (isMobile) { isShowInput.value = true; (_a = document == null ? void 0 : document.body) == null ? void 0 : _a.appendChild(editorInputEleContainer.value); } else { isDialogVisible.value = true; } Object.assign(dialogData, { title: t("change name"), content: "", confirmText: t("Confirm"), actionType: action, showInput: true, isConfirmButtonDisable: computed(() => tempUserName.value === "") }); break; } } const nameCardCheck = () => { const result = calculateByteLength(tempUserName.value) <= 32; !result && renderMsg({ type: "warning", message: t("The user name cannot exceed 32 characters"), duration: MESSAGE_DURATION.NORMAL }); return result; }; async function handleChangeUserNameCard(userInfo) { var _a; if (!nameCardCheck()) return; try { await ((_a = roomEngine.instance) == null ? void 0 : _a.changeUserNameCard({ userId: userInfo.userId, nameCard: tempUserName.value })); renderMsg({ type: "success", message: t("Name changed successfully"), duration: MESSAGE_DURATION.NORMAL }); } catch (error) { renderMsg({ type: "error", message: t("change name failed, please try again."), duration: MESSAGE_DURATION.NORMAL }); } } function handleAction(userInfo) { switch (dialogData.actionType) { case "kickUser": kickOffUser(userInfo); break; case "transferOwner": handleTransferOwner(userInfo); break; case "changeUserNameCard": handleChangeUserNameCard(userInfo); isShowInput.value = false; } isDialogVisible.value = false; } function handleCancelDialog() { tempUserName.value = props.userInfo.nameCard || props.userInfo.userName; isDialogVisible.value = false; } return { props, isMe, isGeneralUser, controlList, kickOffDialogContent, handleCancelDialog, handleAction, isDialogVisible, dialogData, tempUserName, isShowInput, editorInputEle, editorInputEleContainer }; } export { useMemberControl as default };