|
|
@@ -4,7 +4,7 @@ import { UserInfo, useRoomStore } from '../../../stores/room';
|
|
|
import useGetRoomEngine from '../../../hooks/useRoomEngine';
|
|
|
import { useBasicStore } from '../../../stores/basic';
|
|
|
import useMasterApplyControl from '../../../hooks/useMasterApplyControl';
|
|
|
-import { TUIMediaDevice, TUIRole, TUIRequestCallbackType, TUIErrorCode } from '@tencentcloud/tuiroom-engine-wx';
|
|
|
+import { TUIMediaDevice, TUIRole, TUIRequestCallbackType, TUIErrorCode } from '@tencentcloud/tuiroom-engine-wx';
|
|
|
import AudioOpenIcon from '../../../assets/icons/AudioOpenIcon.svg';
|
|
|
import VideoOpenIcon from '../../../assets/icons/VideoOpenIcon.svg';
|
|
|
import ChatForbiddenIcon from '../../../assets/icons/ChatForbiddenIcon.svg';
|
|
|
@@ -16,15 +16,20 @@ import OffStageIcon from '../../../assets/icons/OffStageIcon.svg';
|
|
|
import TransferOwnerIcon from '../../../assets/icons/TransferOwnerIcon.svg';
|
|
|
import SetAdminIcon from '../../../assets/icons/SetAdminIcon.svg';
|
|
|
import RevokeAdminIcon from '../../../assets/icons/RevokeAdminIcon.svg';
|
|
|
+import EditNameCardIcon from '../../../assets/icons/EditNameCardIcon.svg';
|
|
|
import { storeToRefs } from 'pinia';
|
|
|
import TUIMessage from '../../common/base/Message';
|
|
|
import { MESSAGE_DURATION } from '../../../constants/message';
|
|
|
-
|
|
|
+import eventBus from '../../../hooks/useMitt';
|
|
|
+import useMemberItemHooks from '../MemberItem/useMemberItemHooks';
|
|
|
+import { roomService } from '../../../services';
|
|
|
+import { isMobile } from '../../../utils/environment';
|
|
|
+import { calculateByteLength } from '../../../utils/utils';
|
|
|
interface ObjectType {
|
|
|
[key: string]: any;
|
|
|
}
|
|
|
|
|
|
-type ActionType = 'transferOwner' | 'kickUser' | '';
|
|
|
+type ActionType = 'transferOwner' | 'kickUser' | 'changeUserNameCard' | '';
|
|
|
export default function useMemberControl(props?: any) {
|
|
|
const roomEngine = useGetRoomEngine();
|
|
|
const { t } = useI18n();
|
|
|
@@ -32,14 +37,19 @@ export default function useMemberControl(props?: any) {
|
|
|
const basicStore = useBasicStore();
|
|
|
const roomStore = useRoomStore();
|
|
|
const isDialogVisible: Ref<boolean> = ref(false);
|
|
|
- const dialogData: Ref<{ title: string; content: string; confirmText: string; actionType: ActionType }> = ref({
|
|
|
+ const isShowInput: Ref<boolean> = ref(false);
|
|
|
+ const editorInputEle = ref();
|
|
|
+ const editorInputEleContainer = ref();
|
|
|
+ const tempUserName = ref(props.userInfo.nameCard || props.userInfo.userName);
|
|
|
+ const dialogData: Ref<{ title: string; content: string; confirmText: string; actionType: ActionType, showInput: boolean }> = ref({
|
|
|
title: '',
|
|
|
content: '',
|
|
|
confirmText: '',
|
|
|
actionType: '' as ActionType,
|
|
|
+ showInput: false,
|
|
|
});
|
|
|
- const kickOffDialogContent = computed(() => t('whether to kick sb off the room', { name: props.userInfo.userName || props.userInfo.userId }));
|
|
|
- const transferOwnerTitle = computed(() => t('Transfer the roomOwner to sb', { name: props.userInfo.userName || props.userInfo.userId }));
|
|
|
+ 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,
|
|
|
@@ -50,8 +60,6 @@ export default function useMemberControl(props?: any) {
|
|
|
} = storeToRefs(roomStore);
|
|
|
/**
|
|
|
* Functions related to the Raise Your Hand function
|
|
|
- *
|
|
|
- * 举手发言功能相关函数
|
|
|
**/
|
|
|
const {
|
|
|
agreeUserOnStage,
|
|
|
@@ -61,11 +69,16 @@ export default function useMemberControl(props?: any) {
|
|
|
kickUserOffStage,
|
|
|
} = useMasterApplyControl();
|
|
|
|
|
|
+ const { isCanOperateMySelf } = useMemberItemHooks(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] : [];
|
|
|
@@ -77,20 +90,22 @@ export default function useMemberControl(props?: any) {
|
|
|
[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,
|
|
|
+ kickUser.value, changeUserNameCard.value,
|
|
|
],
|
|
|
[TUIRole.kAdministrator]: [
|
|
|
...inviteStageList, ...onStageControlList, ...agreeOrDenyStageList,
|
|
|
- chatControl.value,
|
|
|
+ chatControl.value, changeUserNameCard.value,
|
|
|
],
|
|
|
},
|
|
|
};
|
|
|
@@ -119,7 +134,7 @@ export default function useMemberControl(props?: any) {
|
|
|
const chatControl = computed(() => ({
|
|
|
key: 'chatControl',
|
|
|
icon: ChatForbiddenIcon,
|
|
|
- title: props.userInfo.isChatMutedByMasterOrAdmin ? t('Enable chat') : t('Disable chat'),
|
|
|
+ title: props.userInfo.isMessageDisabled ? t('Enable chat') : t('Disable chat'),
|
|
|
func: disableUserChat,
|
|
|
}));
|
|
|
|
|
|
@@ -160,10 +175,15 @@ export default function useMemberControl(props?: any) {
|
|
|
|
|
|
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'),
|
|
|
+ }));
|
|
|
/**
|
|
|
* Invitation to the stage/uninvitation to the stage
|
|
|
- *
|
|
|
- * 邀请上台/取消邀请上台
|
|
|
**/
|
|
|
async function toggleInviteUserOnStage(userInfo: UserInfo) {
|
|
|
const { isInvitingUserToAnchor } = userInfo;
|
|
|
@@ -184,8 +204,6 @@ export default function useMemberControl(props?: any) {
|
|
|
|
|
|
/**
|
|
|
* Banning/Unbanning
|
|
|
- *
|
|
|
- * 禁麦/邀请打开麦克风
|
|
|
**/
|
|
|
async function muteUserAudio(userInfo: UserInfo) {
|
|
|
if (userInfo.hasAudioStream) {
|
|
|
@@ -197,7 +215,7 @@ export default function useMemberControl(props?: any) {
|
|
|
if (userInfo.isRequestingUserOpenMic) {
|
|
|
TUIMessage({
|
|
|
type: 'info',
|
|
|
- message: `${t('An invitation to open the microphone has been sent to sb.', { name: userInfo.userName || userInfo.userId })}`,
|
|
|
+ message: `${t('An invitation to open the microphone has been sent to sb.', { name: roomService.getDisplayName(userInfo) })}`,
|
|
|
duration: MESSAGE_DURATION.NORMAL,
|
|
|
});
|
|
|
return;
|
|
|
@@ -224,7 +242,7 @@ export default function useMemberControl(props?: any) {
|
|
|
});
|
|
|
TUIMessage({
|
|
|
type: 'info',
|
|
|
- message: `${t('An invitation to open the microphone has been sent to sb.', { name: userInfo.userName || userInfo.userId })}`,
|
|
|
+ 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) {
|
|
|
@@ -235,8 +253,6 @@ export default function useMemberControl(props?: any) {
|
|
|
|
|
|
/**
|
|
|
* Banned painting/unbanned painting
|
|
|
- *
|
|
|
- * 禁画/取消禁画
|
|
|
**/
|
|
|
async function muteUserVideo(userInfo: UserInfo) {
|
|
|
if (userInfo.hasVideoStream) {
|
|
|
@@ -248,7 +264,7 @@ export default function useMemberControl(props?: any) {
|
|
|
if (userInfo.isRequestingUserOpenCamera) {
|
|
|
TUIMessage({
|
|
|
type: 'info',
|
|
|
- message: `${t('An invitation to open the camera has been sent to sb.', { name: userInfo.userName || userInfo.userId })}`,
|
|
|
+ message: `${t('An invitation to open the camera has been sent to sb.', { name: roomService.getDisplayName(userInfo) })}`,
|
|
|
duration: MESSAGE_DURATION.NORMAL,
|
|
|
});
|
|
|
return;
|
|
|
@@ -275,7 +291,7 @@ export default function useMemberControl(props?: any) {
|
|
|
});
|
|
|
TUIMessage({
|
|
|
type: 'info',
|
|
|
- message: `${t('An invitation to open the camera has been sent to sb.', { name: userInfo.userName || userInfo.userId })}`,
|
|
|
+ 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) {
|
|
|
@@ -285,36 +301,44 @@ export default function useMemberControl(props?: any) {
|
|
|
}
|
|
|
/**
|
|
|
* Allow text chat / Cancel text chat
|
|
|
- *
|
|
|
- * 允许文字聊天/取消文字聊天
|
|
|
**/
|
|
|
- function disableUserChat(userInfo: UserInfo) {
|
|
|
- const currentState = userInfo.isChatMutedByMasterOrAdmin;
|
|
|
- roomStore.setMuteUserChat(userInfo.userId, !currentState);
|
|
|
- roomEngine.instance?.disableSendingMessageByAdmin({
|
|
|
- userId: userInfo.userId,
|
|
|
- isDisable: !currentState,
|
|
|
- });
|
|
|
+ async function disableUserChat(userInfo: UserInfo) {
|
|
|
+ const { isMessageDisabled } = userInfo;
|
|
|
+ try {
|
|
|
+ await roomEngine.instance?.disableSendingMessageByAdmin({
|
|
|
+ userId: userInfo.userId,
|
|
|
+ isDisable: !isMessageDisabled,
|
|
|
+ });
|
|
|
+ roomStore.setMuteUserChat(userInfo.userId, !isMessageDisabled);
|
|
|
+ } catch (error) {
|
|
|
+ TUIMessage({
|
|
|
+ type: 'error',
|
|
|
+ message: t('Failed to disable chat'),
|
|
|
+ duration: MESSAGE_DURATION.NORMAL,
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Kick the user out of the room
|
|
|
- *
|
|
|
- * 将用户踢出房间
|
|
|
**/
|
|
|
async function kickOffUser(userInfo: UserInfo) {
|
|
|
await roomEngine.instance?.kickRemoteUserOutOfRoom({
|
|
|
userId: userInfo.userId,
|
|
|
});
|
|
|
+ roomStore.removeRemoteUser(userInfo.userId);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 转移房主给用户
|
|
|
+ * Transfer host to user
|
|
|
*/
|
|
|
async function handleTransferOwner(userInfo: UserInfo) {
|
|
|
const roomInfo = await roomEngine.instance?.fetchRoomInfo();
|
|
|
if (roomInfo?.roomOwner === roomStore.localUser.userId) {
|
|
|
try {
|
|
|
+ if (roomStore.localUser.hasScreenStream) {
|
|
|
+ eventBus.emit('ScreenShare:stopScreenShare');
|
|
|
+ }
|
|
|
await roomEngine.instance?.changeUserRole({
|
|
|
userId: userInfo.userId,
|
|
|
userRole: TUIRole.kRoomOwner,
|
|
|
@@ -322,7 +346,7 @@ export default function useMemberControl(props?: any) {
|
|
|
roomStore.setMasterUserId(userInfo.userId);
|
|
|
TUIMessage({
|
|
|
type: 'success',
|
|
|
- message: t('The room owner has been transferred to sb', { name: userInfo.userName || userInfo.userId }),
|
|
|
+ message: t('The room owner has been transferred to sb', { name: roomService.getDisplayName(userInfo) }),
|
|
|
duration: MESSAGE_DURATION.NORMAL,
|
|
|
});
|
|
|
} catch (error) {
|
|
|
@@ -336,7 +360,7 @@ export default function useMemberControl(props?: any) {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 设置/撤销管理员权限
|
|
|
+ * Set/Remove administrator permissions
|
|
|
*/
|
|
|
async function handleSetOrRevokeAdmin(userInfo: UserInfo) {
|
|
|
const newRole = userInfo.userRole === TUIRole.kGeneralUser ? TUIRole.kAdministrator : TUIRole.kGeneralUser;
|
|
|
@@ -350,30 +374,89 @@ export default function useMemberControl(props?: any) {
|
|
|
: `${t('The administrator status of sb has been withdrawn', { name: updatedUserName })}`;
|
|
|
TUIMessage({ type: 'success', message: tipMessage });
|
|
|
roomStore.setRemoteUserRole(userInfo.userId, newRole);
|
|
|
+ if (newRole === TUIRole.kGeneralUser && userInfo.hasScreenStream) {
|
|
|
+ await roomEngine.instance?.closeRemoteDeviceByAdmin({
|
|
|
+ userId: userInfo.userId,
|
|
|
+ device: TUIMediaDevice.kScreen,
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
function handleOpenDialog(action: string) {
|
|
|
- isDialogVisible.value = true;
|
|
|
switch (action) {
|
|
|
case 'kickUser':
|
|
|
+ isDialogVisible.value = true;
|
|
|
dialogData.value = {
|
|
|
title: t('Note'),
|
|
|
content: kickOffDialogContent.value,
|
|
|
confirmText: t('Confirm'),
|
|
|
actionType: action,
|
|
|
+ showInput: false,
|
|
|
};
|
|
|
break;
|
|
|
case 'transferOwner':
|
|
|
+ isDialogVisible.value = true;
|
|
|
dialogData.value = {
|
|
|
title: transferOwnerTitle.value,
|
|
|
content: t('After transfer the room owner, you will become a general user'),
|
|
|
confirmText: t('Confirm transfer'),
|
|
|
actionType: action,
|
|
|
+ showInput: false,
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ case 'changeUserNameCard':
|
|
|
+ if (isMobile) {
|
|
|
+ isShowInput.value = true;
|
|
|
+ document?.body?.appendChild(editorInputEleContainer.value);
|
|
|
+ } else {
|
|
|
+ isDialogVisible.value = true;
|
|
|
+ }
|
|
|
+ dialogData.value = {
|
|
|
+ title: t('change name'),
|
|
|
+ content: '',
|
|
|
+ confirmText: t('Confirm'),
|
|
|
+ actionType: action,
|
|
|
+ showInput: true,
|
|
|
};
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ const nameCardCheck = () => {
|
|
|
+ const result = calculateByteLength(tempUserName.value) <= 32;
|
|
|
+ !result && TUIMessage({
|
|
|
+ type: 'warning',
|
|
|
+ message: t('The user name cannot exceed 32 characters'),
|
|
|
+ duration: MESSAGE_DURATION.NORMAL,
|
|
|
+ });
|
|
|
+ return result;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * change UserNameCard
|
|
|
+ */
|
|
|
+ async function handleChangeUserNameCard(userInfo: UserInfo) {
|
|
|
+ if (!nameCardCheck()) return;
|
|
|
+ try {
|
|
|
+ await roomEngine.instance?.changeUserNameCard({
|
|
|
+ userId: userInfo.userId,
|
|
|
+ nameCard: tempUserName.value,
|
|
|
+ });
|
|
|
+ TUIMessage({
|
|
|
+ type: 'success',
|
|
|
+ message: t('Name changed successfully'),
|
|
|
+ duration: MESSAGE_DURATION.NORMAL,
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ TUIMessage({
|
|
|
+ type: 'error',
|
|
|
+ message: t('change name failed, please try again.'),
|
|
|
+ duration: MESSAGE_DURATION.NORMAL,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
function handleAction(userInfo: UserInfo) {
|
|
|
switch (dialogData.value.actionType) {
|
|
|
case 'kickUser':
|
|
|
@@ -382,13 +465,18 @@ export default function useMemberControl(props?: any) {
|
|
|
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,
|
|
|
@@ -399,5 +487,9 @@ export default function useMemberControl(props?: any) {
|
|
|
handleAction,
|
|
|
isDialogVisible,
|
|
|
dialogData,
|
|
|
+ tempUserName,
|
|
|
+ isShowInput,
|
|
|
+ editorInputEle,
|
|
|
+ editorInputEleContainer,
|
|
|
};
|
|
|
};
|