+
{
roomStore.updateUserStreamVisible(streamUserIdList);
};
+// 处理顶部布局水平滑动
+function handleWheel(event: WheelEvent) {
+ streamListRef.value.scrollLeft += event.deltaY;
+}
+
const handleStreamContainerScrollDebounce = debounce(handleStreamContainerScroll, 300);
onMounted(() => {
diff --git a/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/index.vue b/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/index.vue
index 94b7f6036..a0b3bc425 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/index.vue
+++ b/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/index.vue
@@ -35,8 +35,19 @@
{{ t('Currently no member has applied to go on stage') }}
- {{ t('Agree All') }}
-
+
+ {{ t('Agree All') }}
+
+
{{ t('Reject All') }}
@@ -46,7 +57,7 @@
diff --git a/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/useMasterApplyControlHooks.ts b/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/useMasterApplyControlHooks.ts
deleted file mode 100644
index e2d2925df..000000000
--- a/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/useMasterApplyControlHooks.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { storeToRefs } from 'pinia';
-import { computed, watch } from 'vue';
-import { useBasicStore } from '../../../../stores/basic';
-import { useRoomStore } from '../../../../stores/room';
-import useMasterApplyControl from '../../../../hooks/useMasterApplyControl';
-import { useI18n } from '../../../../locales';
-import TUINotification from '../../../common/base/Notification/index';
-import { isMobile } from '../../../../utils/environment';
-
-export default function useMasterApplyControlHooks() {
- const { t } = useI18n();
- const basicStore = useBasicStore();
- const roomStore = useRoomStore();
- const { handleUserApply, handleAllUserApply } = useMasterApplyControl();
- const { showApplyUserList } = storeToRefs(basicStore);
- const { applyToAnchorList } = storeToRefs(roomStore);
-
- const applyToAnchorUserCount = computed(() => applyToAnchorList.value.length);
- const noUserApply = computed(() => applyToAnchorUserCount.value === 0);
-
- const handleConfirm = async (onlyOneUserTakeStage: boolean, userId: string) => {
- if (isMobile) {
- basicStore.setSidebarOpenStatus(true);
- basicStore.setSidebarName('apply');
- } else {
- if (onlyOneUserTakeStage) {
- handleUserApply(userId, true);
- } else {
- basicStore.setShowApplyUserList(true);
- }
- }
- };
-
- const handleCancel = async (onlyOneUserTakeStage: boolean, userId: string) => {
- if (!isMobile && onlyOneUserTakeStage) {
- handleUserApply(userId, false);
- }
- };
-
- watch(applyToAnchorUserCount, (newVal, oldVal) => {
- if (newVal <= oldVal) return;
- const onlyOneUserTakeStage = newVal === 1;
- const firstUser = applyToAnchorList.value[0];
- const userName = firstUser?.userName || firstUser?.userId;
- const message = onlyOneUserTakeStage
- ? `${userName} ${t('Applying for the stage')}`
- : `${userName} ${t('and so on number people applying to stage', { number: applyToAnchorList.value.length })}`;
- TUINotification({
- message,
- appendToRoomContainer: true,
- confirmButtonText: isMobile ? t('Check') : (onlyOneUserTakeStage ? t('Agree to the stage') : t('Check')),
- cancelButtonText: isMobile ? undefined : (onlyOneUserTakeStage ? t('Reject') : t('Neglect')),
- confirm: () => handleConfirm(onlyOneUserTakeStage, firstUser?.userId),
- cancel: () => handleCancel(onlyOneUserTakeStage, firstUser?.userId),
- });
- });
-
- function hideApplyList() {
- basicStore.setShowApplyUserList(false);
- }
-
- return {
- t,
- roomStore,
- showApplyUserList,
- hideApplyList,
- applyToAnchorUserCount,
- applyToAnchorList,
- handleAllUserApply,
- handleUserApply,
- noUserApply,
- };
-}
diff --git a/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MemberApplyControl.vue b/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MemberApplyControl.vue
index c96715636..bee8281f6 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MemberApplyControl.vue
+++ b/Electron/vue2/src/TUIRoom/components/RoomFooter/ApplyControl/MemberApplyControl.vue
@@ -199,6 +199,12 @@ function handleStepDownDialogVisible() {
async function leaveSeat() {
await roomEngine.instance?.leaveSeat();
showDialog.value = false;
+ if (roomStore.isCameraDisableForAllUser && isGeneralUser.value) {
+ roomStore.setCanControlSelfVideo(false);
+ }
+ if (roomStore.isMicrophoneDisableForAllUser && isGeneralUser.value) {
+ roomStore.setCanControlSelfAudio(false);
+ }
}
function hideApplyAttention() {
@@ -318,7 +324,6 @@ onBeforeUnmount(() => {
}
.mobile-info {
min-width: 50vw;
- white-space: normal;
}
.close {
cursor: pointer;
diff --git a/Electron/vue2/src/TUIRoom/components/RoomFooter/AudioControl.vue b/Electron/vue2/src/TUIRoom/components/RoomFooter/AudioControl.vue
index eddd5c62a..54e157e74 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomFooter/AudioControl.vue
+++ b/Electron/vue2/src/TUIRoom/components/RoomFooter/AudioControl.vue
@@ -118,7 +118,6 @@ async function toggleMuteAudio() {
TUIMessageBox({
title: t('Note'),
message: t('Microphone not detected on current device'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
});
return;
diff --git a/Electron/vue2/src/TUIRoom/components/RoomFooter/EndControl/index.vue b/Electron/vue2/src/TUIRoom/components/RoomFooter/EndControl/index.vue
index 7d4018601..0bbc289f8 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomFooter/EndControl/index.vue
+++ b/Electron/vue2/src/TUIRoom/components/RoomFooter/EndControl/index.vue
@@ -175,7 +175,6 @@ const onRoomDismissed = async (eventInfo: { roomId: string }) => {
TUIMessageBox({
title: t('Note'),
message: t('The host closed the room.'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
callback: async () => {
resetState();
diff --git a/Electron/vue2/src/TUIRoom/components/RoomFooter/EndControl/useEndControlHooks.ts b/Electron/vue2/src/TUIRoom/components/RoomFooter/EndControl/useEndControlHooks.ts
index f72a1031e..033d4add8 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomFooter/EndControl/useEndControlHooks.ts
+++ b/Electron/vue2/src/TUIRoom/components/RoomFooter/EndControl/useEndControlHooks.ts
@@ -1,6 +1,6 @@
import { ref, Ref, computed, onUnmounted } from 'vue';
import { useBasicStore } from '../../../stores/basic';
-import { useRoomStore } from '../../../stores/room';
+import { useRoomStore, UserInfo } from '../../../stores/room';
import { useChatStore } from '../../../stores/chat';
import { storeToRefs } from 'pinia';
import { useI18n } from '../../../locales';
@@ -25,7 +25,7 @@ export default function useEndControl() {
logger.log(`${logPrefix} basicStore:`, basicStore);
const roomStore = useRoomStore();
- const { localUser, remoteUserList } = storeToRefs(roomStore);
+ const { localUser, remoteUserList, applyToAnchorList } = storeToRefs(roomStore);
const title = computed(() => (currentDialogType.value === DialogType.BasicDialog ? t('Leave room?') : t('Select a new host')));
const isShowLeaveRoomDialog = computed(() => (
roomStore.isMaster && remoteUserList.value.length > 0)
@@ -87,6 +87,24 @@ export default function useEndControl() {
}
}
+ async function handleUpdateSeatApplicationList() {
+ if (!roomStore.isSpeakAfterTakingSeatMode) {
+ return;
+ }
+ if (applyToAnchorList.value.length > 0) {
+ applyToAnchorList.value.forEach((user: UserInfo) => {
+ user.applyToAnchorRequestId && roomStore.removeApplyToAnchorUser(user.applyToAnchorRequestId);
+ });
+ }
+ const applicationList = await roomEngine.instance?.getSeatApplicationList();
+ if (applicationList && applicationList.length > 0) {
+ for (const applicationInfo of applicationList) {
+ const { userId, requestId, timestamp } = applicationInfo;
+ roomStore.addApplyToAnchorUser({ userId, requestId, timestamp });
+ }
+ }
+ }
+
const onUserRoleChanged = async (eventInfo: { userId: string, userRole: TUIRole }) => {
const { userId, userRole } = eventInfo;
const isLocal = roomStore.localUser.userId === userId;
@@ -108,6 +126,12 @@ export default function useEndControl() {
if (oldUserRole === TUIRole.kAdministrator) {
TUIMessage({ type: 'warning', message: t('Your administrator status has been revoked') });
}
+ if (roomStore.localStream.hasAudioStream) {
+ roomStore.setCanControlSelfAudio(true);
+ }
+ if (roomStore.localStream.hasVideoStream) {
+ roomStore.setCanControlSelfVideo(true);
+ }
}
break;
case TUIRole.kAdministrator:
@@ -115,6 +139,9 @@ export default function useEndControl() {
TUIMessage({ type: 'success', message: t('You have become a administrator') });
roomStore.setCanControlSelfAudio(true);
roomStore.setCanControlSelfVideo(true);
+ if (roomStore.isSpeakAfterTakingSeatMode) {
+ handleUpdateSeatApplicationList();
+ }
}
break;
case TUIRole.kRoomOwner: {
@@ -125,13 +152,7 @@ export default function useEndControl() {
if (!roomStore.isAnchor) {
await roomEngine.instance?.takeSeat({ seatIndex: -1, timeout: 0 });
}
- const applicationList = await roomEngine.instance?.getSeatApplicationList();
- if (applicationList) {
- for (const applicationInfo of applicationList) {
- const { userId, requestId, timestamp } = applicationInfo;
- roomStore.addApplyToAnchorUser({ userId, requestId, timestamp });
- }
- }
+ handleUpdateSeatApplicationList();
}
if (chatStore.isMessageDisableByAdmin) {
roomEngine.instance?.disableSendingMessageByAdmin({
diff --git a/Electron/vue2/src/TUIRoom/components/RoomFooter/ManageStageControl.vue b/Electron/vue2/src/TUIRoom/components/RoomFooter/ManageStageControl.vue
index 528a3d980..b7fda321b 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomFooter/ManageStageControl.vue
+++ b/Electron/vue2/src/TUIRoom/components/RoomFooter/ManageStageControl.vue
@@ -27,11 +27,13 @@ import { useI18n } from '../../locales';
import TuiBadge from '../common/base/Badge.vue';
import { isMobile } from '../../utils/environment';
import MasterApplyControl from './ApplyControl/MasterApplyControl/index.vue';
+import useMasterApplyControl from '../../hooks/useMasterApplyControl';
const { t } = useI18n();
const basicStore = useBasicStore();
const roomStore = useRoomStore();
+const { handleShowNotification } = useMasterApplyControl();
const { sidebarName, showApplyUserList } = storeToRefs(basicStore);
const { applyToAnchorList } = storeToRefs(roomStore);
@@ -48,4 +50,7 @@ function toggleManageStage() {
basicStore.setSidebarName('apply');
}
}
+
+handleShowNotification();
+
diff --git a/Electron/vue2/src/TUIRoom/components/RoomFooter/VideoControl.vue b/Electron/vue2/src/TUIRoom/components/RoomFooter/VideoControl.vue
index 2793405a4..10286657f 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomFooter/VideoControl.vue
+++ b/Electron/vue2/src/TUIRoom/components/RoomFooter/VideoControl.vue
@@ -118,7 +118,6 @@ async function toggleMuteVideo() {
TUIMessageBox({
title: t('Note'),
message: t('Camera not detected on current device'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
});
return;
diff --git a/Electron/vue2/src/TUIRoom/components/RoomHome/RoomControl/index.vue b/Electron/vue2/src/TUIRoom/components/RoomHome/RoomControl/index.vue
index 7013d02f4..7c2d0b0cd 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomHome/RoomControl/index.vue
+++ b/Electron/vue2/src/TUIRoom/components/RoomHome/RoomControl/index.vue
@@ -83,9 +83,8 @@ import { useBasicStore } from '../../../stores/basic';
import { useRoomStore } from '../../../stores/room';
import AudioMediaControl from '../../common/AudioMediaControl.vue';
import VideoMediaControl from '../../common/VideoMediaControl.vue';
-import TUIRoomEngine, { TUIRoomEvents, TRTCVideoMirrorType, TRTCVideoRotation, TRTCVideoFillMode, TUIRoomDeviceMangerEvents } from '@tencentcloud/tuiroom-engine-electron';
+import TUIRoomEngine, { TRTCVideoMirrorType, TRTCVideoRotation, TRTCVideoFillMode, TUIRoomDeviceMangerEvents } from '@tencentcloud/tuiroom-engine-electron';
import '../../../directives/vClickOutside';
-import { isElectron } from '../../../utils/environment';
import { isEnumerateDevicesSupported, isGetUserMediaSupported } from '../../../utils/mediaAbility';
import useDeviceManager from '../../../hooks/useDeviceManager';
@@ -134,38 +133,21 @@ async function openCamera() {
rotation: TRTCVideoRotation.TRTCVideoRotation0,
fillMode: TRTCVideoFillMode.TRTCVideoFillMode_Fill,
});
- if (isElectron) {
- roomEngine.instance?.setLocalVideoView({ view: 'stream-preview' });
- await roomEngine.instance?.openLocalCamera();
- } else {
- await roomEngine.instance?.startCameraDeviceTest({
- view: 'stream-preview',
- });
- }
+ await roomEngine.instance?.startCameraDeviceTest({
+ view: 'stream-preview',
+ });
}
async function closeCamera() {
- if (isElectron) {
- await roomEngine.instance?.closeLocalCamera();
- } else {
- await roomEngine.instance?.stopCameraDeviceTest();
- }
+ await roomEngine.instance?.stopCameraDeviceTest();
}
async function openAudio() {
- if (isElectron) {
- await roomEngine.instance?.openLocalMicrophone();
- } else {
- await roomEngine.instance?.startMicDeviceTest({ interval: 200 });
- }
+ await roomEngine.instance?.startMicDeviceTest({ interval: 200 });
}
async function closeAudio() {
- if (isElectron) {
- await roomEngine.instance?.closeLocalMicrophone();
- } else {
- await roomEngine.instance?.stopMicDeviceTest();
- }
+ await roomEngine.instance?.stopMicDeviceTest();
}
async function toggleMuteAudio() {
@@ -259,22 +241,13 @@ function enterRoom() {
TUIRoomEngine.once('ready', () => {
startStreamPreview();
- if (isElectron) {
- roomEngine.instance?.on(TUIRoomEvents.onUserVoiceVolumeChanged, onUserVoiceVolume);
- } else {
- deviceManager.instance?.on(TUIRoomDeviceMangerEvents.onTestMicVolume, onUserVoiceVolume);
- }
+ deviceManager.instance?.on(TUIRoomDeviceMangerEvents.onTestMicVolume, onUserVoiceVolume);
});
onBeforeUnmount(async () => {
await closeAudio();
await closeCamera();
-
- if (isElectron) {
- roomEngine.instance?.off(TUIRoomEvents.onUserVoiceVolumeChanged, onUserVoiceVolume);
- } else {
- deviceManager.instance?.off(TUIRoomDeviceMangerEvents.onTestMicVolume, onUserVoiceVolume);
- }
+ deviceManager.instance?.off(TUIRoomDeviceMangerEvents.onTestMicVolume, onUserVoiceVolume);
});
diff --git a/Electron/vue2/src/TUIRoom/components/RoomSidebar/useSideBarHooks.ts b/Electron/vue2/src/TUIRoom/components/RoomSidebar/useSideBarHooks.ts
index c8a485e6c..4cf21c784 100644
--- a/Electron/vue2/src/TUIRoom/components/RoomSidebar/useSideBarHooks.ts
+++ b/Electron/vue2/src/TUIRoom/components/RoomSidebar/useSideBarHooks.ts
@@ -64,13 +64,15 @@ export default function useSideBar() {
};
let tim = roomEngine.instance?.getTIM();
+ tim?.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onReceiveMessage);
+
watch(sdkAppId, () => {
- if (!tim) {
+ if (!tim && sdkAppId.value) {
tim = TencentCloudChat.create({ SDKAppID: basicStore.sdkAppId });
+ tim?.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onReceiveMessage);
}
- tim?.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onReceiveMessage);
- }, { immediate: true });
+ });
onUnmounted(() => {
tim?.off(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onReceiveMessage);
diff --git a/Electron/vue2/src/TUIRoom/components/common/AudioMediaControl.vue b/Electron/vue2/src/TUIRoom/components/common/AudioMediaControl.vue
index de3e926a5..67e7ed708 100644
--- a/Electron/vue2/src/TUIRoom/components/common/AudioMediaControl.vue
+++ b/Electron/vue2/src/TUIRoom/components/common/AudioMediaControl.vue
@@ -73,7 +73,6 @@ async function handleClickIcon() {
TUIMessageBox({
title: t('Note'),
message: t('The current browser does not support capturing audio'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
});
return;
diff --git a/Electron/vue2/src/TUIRoom/components/common/RoomTime.vue b/Electron/vue2/src/TUIRoom/components/common/RoomTime.vue
index 5504a80b9..30b167c45 100644
--- a/Electron/vue2/src/TUIRoom/components/common/RoomTime.vue
+++ b/Electron/vue2/src/TUIRoom/components/common/RoomTime.vue
@@ -35,7 +35,5 @@ onUnmounted(() => {
font-size: 14px;
font-weight: 500;
line-height: 20px;
- width: 38px;
- letter-spacing: -0.24px;
}
diff --git a/Electron/vue2/src/TUIRoom/components/common/VideoMediaControl.vue b/Electron/vue2/src/TUIRoom/components/common/VideoMediaControl.vue
index 9a27acf13..da8c03a29 100644
--- a/Electron/vue2/src/TUIRoom/components/common/VideoMediaControl.vue
+++ b/Electron/vue2/src/TUIRoom/components/common/VideoMediaControl.vue
@@ -73,7 +73,6 @@ async function handleClickIcon() {
TUIMessageBox({
title: t('Note'),
message: t('The current browser does not support capturing video'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
});
return;
diff --git a/Electron/vue2/src/TUIRoom/components/common/base/MessageBox/index.ts b/Electron/vue2/src/TUIRoom/components/common/base/MessageBox/index.ts
index e4ee127d5..de4d9e868 100644
--- a/Electron/vue2/src/TUIRoom/components/common/base/MessageBox/index.ts
+++ b/Electron/vue2/src/TUIRoom/components/common/base/MessageBox/index.ts
@@ -4,17 +4,20 @@ export type MessageProps = {
title: string,
message: string,
callback?: () => Promise
,
- appendToRoomContainer?: boolean,
confirmButtonText?: string,
}
-const MessageBox = ({ title, message, callback, appendToRoomContainer, confirmButtonText }: MessageProps) => {
+
+const MessageBox = ({ title, message, callback, confirmButtonText }: MessageProps) => {
const container = document.createElement('div');
- document.body.appendChild(container);
+ const fullscreenElement = document.fullscreenElement || document.getElementById('roomContainer') || document.body;
+ fullscreenElement.appendChild(container);
+
+
const onRemove = () => {
vm.$destroy();
- document.body.removeChild(container);
+ fullscreenElement.removeChild(container);
};
- const messageBoxConstruct = Vue.extend({
+ const MessageBoxConstruct = Vue.extend({
render: (h: any) => h(TUIMessageBox, {
props: {
title,
@@ -22,14 +25,10 @@ const MessageBox = ({ title, message, callback, appendToRoomContainer, confirmBu
callback,
confirmButtonText,
remove: onRemove,
- appendToRoomContainer,
- },
- on: {
- remove: onRemove,
},
}),
});
- const vm = new messageBoxConstruct({el: document.createElement('div')}).$mount()
- container.appendChild(vm.$el)
+ const vm = new MessageBoxConstruct({ el: document.createElement('div') }).$mount();
+ container.appendChild(vm.$el);
};
export default MessageBox;
diff --git a/Electron/vue2/src/TUIRoom/components/common/base/MessageBox/index.vue b/Electron/vue2/src/TUIRoom/components/common/base/MessageBox/index.vue
index 7f5c44d5a..e39af9b21 100644
--- a/Electron/vue2/src/TUIRoom/components/common/base/MessageBox/index.vue
+++ b/Electron/vue2/src/TUIRoom/components/common/base/MessageBox/index.vue
@@ -1,8 +1,7 @@
-
+
+ */
+
import { getLanguage } from '../utils/common';
import ZH from './zh-CN';
import EN from './en-US';
+import { ref } from 'vue';
+
+const locale = ref('');
+class TUIKitI18n {
+ messages: Record
;
+ global: Record;
+
+ constructor(options: { messages: Record, locale: string }) {
+ this.messages = options.messages;
+ locale.value = options.locale;
+ this.global = {};
+ this.global.locale = locale;
+ this.global.t = this.t.bind(this);
+ }
+
+ private getNamed(option: Record) {
+ return (key: string) => option[key] || key;
+ }
+
+ private t(key: any, option?: Record) {
+ const message = this.messages[locale.value];
+ if (!message[key]) {
+ return key;
+ }
+ if (typeof message[key] === 'function') {
+ const named = this.getNamed(option || {});
+ return message[key]({ named });
+ }
+ return message[key];
+ }
-// 参考文档:https://vue-i18n.intlify.dev/guide/migration/vue2.html#vue-i18n-bridge
-Vue.use(VueI18n, { bridge: true });
+ // 兼容 App.use 不报错
+ public install() {
+ }
+}
-export default createI18n({
- legacy: false,
+const i18n = new TUIKitI18n({
locale: getLanguage() || 'zh-CN',
messages: {
'zh-CN': ZH,
'en-US': EN,
},
-}, VueI18n);
+});
-export { useI18n };
+export default i18n;
+export function useI18n() {
+ return {
+ t: i18n.global.t.bind(i18n),
+ };
+}
diff --git a/Electron/vue2/src/TUIRoom/locales/zh-CN.ts b/Electron/vue2/src/TUIRoom/locales/zh-CN.ts
index b0f511a8a..0a637c010 100644
--- a/Electron/vue2/src/TUIRoom/locales/zh-CN.ts
+++ b/Electron/vue2/src/TUIRoom/locales/zh-CN.ts
@@ -243,9 +243,9 @@ export default {
'kicked out of the room by other device': '相同账号在其他客户端进入房间',
'kicked out of the room by serve': '被服务端踢出房间',
// @ts-ignore
- 'Reject on Stage failed, please retry': ({ named }) => `拒绝 ${named('name')} 上台失败, 请重试`,
+ 'Reject sb stage failed, please retry': ({ named }) => `拒绝 ${named('name')} 上台失败, 请重试`,
// @ts-ignore
- 'Agree on Stage failed, please retry': ({ named }) => `同意 ${named('name')} 上台失败, 请重试`,
+ 'Agree sb stage failed, please retry': ({ named }) => `同意 ${named('name')} 上台失败, 请重试`,
'Has been fully muted and cannot open the microphone': '已被全员静音,无法打开麦克风',
'Has been muted by the host and cannot open the microphone': '已被主持人静音,无法打开麦克风',
'To apply to speak in the room, please raise your hand first to apply for the microphone': '申请发言房间,请先举手申请上麦',
diff --git a/Electron/vue2/src/TUIRoom/services/roomService.ts b/Electron/vue2/src/TUIRoom/services/roomService.ts
index cdabe428f..e8b901eb5 100644
--- a/Electron/vue2/src/TUIRoom/services/roomService.ts
+++ b/Electron/vue2/src/TUIRoom/services/roomService.ts
@@ -189,7 +189,6 @@ export class RoomService {
title: t('Note'),
message: notice,
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: async () => {
this.emit(EventType.ROOM_KICKED_OUT, { roomId, reason, message });
this.resetStore();
@@ -220,7 +219,6 @@ export class RoomService {
title: t('Note'),
message: t('userSig 已过期'),
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: () => {
this.emit(EventType.ROOM_USER_SIG_EXPIRED, {});
},
@@ -233,7 +231,6 @@ export class RoomService {
title: t('Note'),
message: t('系统检测到您的账号被踢下线'),
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: async () => {
this.emit(EventType.ROOM_KICKED_OFFLINE, { message });
},
@@ -338,13 +335,15 @@ export class RoomService {
await TUIRoomEngine.setSelfInfo({ userName, avatarUrl });
}
- private async doEnterRoom(roomId: string) {
+ private async doEnterRoom(options: { roomId: string; roomType: TUIRoomType}) {
+ const { roomId, roomType } = options;
const isH5 = isMobile && !isWeChat;
const trtcCloud = roomEngine.instance?.getTRTCCloud();
trtcCloud?.setDefaultStreamRecvMode(true, false);
trtcCloud?.enableSmallVideoStream(!isH5, smallParam);
const roomInfo = (await roomEngine.instance?.enterRoom({
roomId,
+ roomType,
})) as TUIRoomInfo;
roomEngine.instance?.muteLocalAudio();
if (!roomInfo.isSeatEnabled) {
@@ -453,7 +452,11 @@ export class RoomService {
}
this.basicStore.setRoomId(roomId);
logger.debug(`${logPrefix}enterRoom:`, roomId, roomParam);
- const roomInfo = await this.doEnterRoom(roomId);
+ const roomParams = {
+ roomId,
+ roomType: TUIRoomType.kConference,
+ };
+ const roomInfo = await this.doEnterRoom(roomParams);
this.roomStore.setRoomInfo(roomInfo);
await this.getUserList();
if (roomInfo.isSeatEnabled) {
diff --git a/Electron/vue2/src/main.ts b/Electron/vue2/src/main.ts
index febe0d49b..9d7e14226 100644
--- a/Electron/vue2/src/main.ts
+++ b/Electron/vue2/src/main.ts
@@ -2,7 +2,6 @@ import Vue from 'vue';
import App from './App.vue';
import router from './router';
import { createPinia, PiniaVuePlugin } from 'pinia';
-import i18n from './TUIRoom/locales/';
import { ipcRenderer } from 'electron';
if (window.isHasScreen === undefined) {
window.isHasScreen = false;
@@ -17,8 +16,6 @@ ipcRenderer.on('main-process-message', (_event, ...args) => {
Vue.use(PiniaVuePlugin);
const pinia = createPinia();
-Vue.use(i18n);
-
Vue.config.productionTip = false;
new Vue({
diff --git a/Electron/vue2/src/views/home.vue b/Electron/vue2/src/views/home.vue
index 49307d62a..c51788b64 100644
--- a/Electron/vue2/src/views/home.vue
+++ b/Electron/vue2/src/views/home.vue
@@ -88,7 +88,7 @@ export default {
let isRoomExist = false;
const tim = roomEngine.instance?.getTIM();
try {
- await tim.searchGroupByID(roomId);
+ await tim?.searchGroupByID(roomId);
isRoomExist = true;
} catch (error) {
// 房间不存在
diff --git a/Electron/vue2/src/views/room.vue b/Electron/vue2/src/views/room.vue
index dc1974770..8592e921d 100644
--- a/Electron/vue2/src/views/room.vue
+++ b/Electron/vue2/src/views/room.vue
@@ -62,7 +62,6 @@ export default {
TUIMessageBox({
title: this.$t('Note'),
message,
- appendToRoomContainer: true,
confirmButtonText: this.$t('Sure'),
callback: () => {
this.$router.push({ path: 'home' });
@@ -77,7 +76,6 @@ export default {
TUIMessageBox({
title: this.$t('Note'),
message,
- appendToRoomContainer: true,
confirmButtonText: this.$t('Sure'),
callback: () => {
this.$router.push({ path: 'home' });
@@ -90,7 +88,6 @@ export default {
TUIMessageBox({
title: this.$t('Note'),
message,
- appendToRoomContainer: true,
confirmButtonText: this.$t('Sure'),
callback: () => {
sessionStorage.removeItem('tuiRoom-currentUserInfo');
diff --git a/Electron/vue3/CHANGELOG.md b/Electron/vue3/CHANGELOG.md
index 78e32d670..caf4cddde 100644
--- a/Electron/vue3/CHANGELOG.md
+++ b/Electron/vue3/CHANGELOG.md
@@ -1,3 +1,17 @@
+## 2024.04.29@2.3.1
+
+**Feature**
+
+- 升级 [@tencentcloud/tuiroom-engine-electron](https://www.npmjs.com/package/@tencentcloud/tuiroom-engine-electron) 到 v2.3.1 版本,详情请查看 [发布日志](https://cloud.tencent.com/document/product/1690/89361);
+
+**Bug Fixed**
+- 修复 Electron 下拔出外接摄像头摄像头列表默认设备未更新的问题;
+- 修复成员操作面板距顶部距离不够,展示不完全问题;
+- 修复 Notification 组件收到其他成员处理事件时显隐展示的问题;
+- 修复获取主持人和管理员身份后没有更新申请上麦列表的问题;
+- 修复聊天消息未读数不准确的问题;
+- 修复转交房主或管理员状态下多次点击麦克风和摄像头按钮 disable 状态错误的问题。
+
## 2024.04.08@2.2.2
**Feature**
diff --git a/Electron/vue3/package-lock.json b/Electron/vue3/package-lock.json
index 7cabd5ea6..7ec06700d 100644
--- a/Electron/vue3/package-lock.json
+++ b/Electron/vue3/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "electron-vue-vite",
- "version": "2.2.2",
+ "version": "2.3.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
diff --git a/Electron/vue3/package.json b/Electron/vue3/package.json
index 2331eb80c..598c7aa5e 100644
--- a/Electron/vue3/package.json
+++ b/Electron/vue3/package.json
@@ -1,6 +1,6 @@
{
"name": "room-uikit-electron-vue3",
- "version": "2.2.2",
+ "version": "2.3.1",
"description": "This is an interactive multimedia room solution that published by Tencent Cloud RTC team for PC base on Electron, vue and so on.",
"main": "dist/main/index.cjs",
"author": "",
@@ -50,17 +50,15 @@
"dependencies": {
"@tencentcloud/chat": "latest",
"@tencentcloud/tui-core": "latest",
- "@tencentcloud/tuiroom-engine-electron": "^2.2.2",
+ "@tencentcloud/tuiroom-engine-electron": "^2.3.1",
"@tencentcloud/universal-api": "^2.0.9",
- "interactjs": "^1.10.26",
"axios": "^0.27.2",
+ "interactjs": "^1.10.26",
"js-cookie": "^3.0.1",
"lodash.isequal": "^4.5.0",
"mitt": "^3.0.0",
"pinia": "^2.0.24",
"sass": "^1.56.1",
- "trtc-electron-sdk": "11.6.602-beta.0",
- "vue-i18n": "^9.2.2",
"vue-router": "^4.0.14",
"yuv-buffer": "^1.0.0",
"yuv-canvas": "^1.2.11"
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/Chat/ChatEditor/useChatEditor.ts b/Electron/vue3/packages/renderer/src/TUIRoom/components/Chat/ChatEditor/useChatEditor.ts
index 5e80f0ba3..8c0b91346 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/Chat/ChatEditor/useChatEditor.ts
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/Chat/ChatEditor/useChatEditor.ts
@@ -44,6 +44,9 @@ export default function useChatEditor() {
isEmojiToolbarVisible.value = false;
try {
const tim = roomEngine.instance?.getTIM();
+ if (!tim) {
+ throw new Error('tim is null');
+ }
const message = tim.createTextMessage({
to: roomId.value,
conversationType: TencentCloudChat.TYPES.CONV_GROUP,
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/Chat/MessageList/useMessageListHook.ts b/Electron/vue3/packages/renderer/src/TUIRoom/components/Chat/MessageList/useMessageListHook.ts
index b657dc3f0..f8d5ec184 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/Chat/MessageList/useMessageListHook.ts
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/Chat/MessageList/useMessageListHook.ts
@@ -21,7 +21,7 @@ export default function useMessageList() {
async function handleGetHistoryMessageList() {
const tim = roomEngine.instance?.getTIM();
- const imResponse = await tim.getMessageList({
+ const imResponse = await tim?.getMessageList({
conversationID: `GROUP${roomId.value}`,
nextReqMessageID: nextReqMessageId.value,
});
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/MemberControl/index.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/MemberControl/index.vue
index 00f6c2784..2a3e00c10 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/MemberControl/index.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/MemberControl/index.vue
@@ -98,14 +98,14 @@ function toggleClickMoreBtn() {
}
}
-// 根据页面位置确定下拉框的定位
function handleDropDownPosition() {
const { top, bottom } = moreBtnRef.value?.getBoundingClientRect();
- const containerBottom = document.getElementById('memberListContainer')?.getBoundingClientRect()?.bottom;
- if (!containerBottom) {
+ const { top: containerTop, bottom: containerBottom } = document.getElementById('memberListContainer')?.getBoundingClientRect() as DOMRect;
+ if (!containerBottom || !containerTop) {
return;
}
const bottomSize = containerBottom - bottom;
+ const topSize = top - containerTop;
let dropDownContainerHeight = 0;
if (!showMoreControl.value) {
operateListRef.value.style = 'display:block;position:absolute;z-index:-1000';
@@ -114,7 +114,10 @@ function handleDropDownPosition() {
} else {
dropDownContainerHeight = operateListRef.value?.offsetHeight;
}
- if (bottomSize < top && bottomSize < dropDownContainerHeight) {
+ if (topSize < dropDownContainerHeight) {
+ return;
+ }
+ if (bottomSize < dropDownContainerHeight) {
dropdownClass.value = 'up';
}
}
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/MemberItemCommon/MemberInfo.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/MemberItemCommon/MemberInfo.vue
index 0d1161140..f57bf6478 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/MemberItemCommon/MemberInfo.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/MemberItemCommon/MemberInfo.vue
@@ -13,6 +13,7 @@
{{ extraInfo }}
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/index.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/index.vue
index 9dcd78ec9..ff7ca283a 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/index.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/ManageMember/index.vue
@@ -224,7 +224,6 @@ const {
}
}
.member-list-container {
- overflow-y: scroll;
flex: 1;
margin-top: 10px;
overflow-y: scroll;
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomContent/StreamContainer/index.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomContent/StreamContainer/index.vue
index 1635f311f..c14f9440d 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomContent/StreamContainer/index.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomContent/StreamContainer/index.vue
@@ -9,7 +9,13 @@
>
-
+
{
roomStore.updateUserStreamVisible(streamUserIdList);
};
+// 处理顶部布局水平滑动
+function handleWheel(event: WheelEvent) {
+ streamListRef.value.scrollLeft += event.deltaY;
+}
+
const handleStreamContainerScrollDebounce = debounce(handleStreamContainerScroll, 300);
onMounted(() => {
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/index.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/index.vue
index 94b7f6036..a0b3bc425 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/index.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/index.vue
@@ -35,8 +35,19 @@
{{ t('Currently no member has applied to go on stage') }}
- {{ t('Agree All') }}
-
+
+ {{ t('Agree All') }}
+
+
{{ t('Reject All') }}
@@ -46,7 +57,7 @@
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/useMasterApplyControlHooks.ts b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/useMasterApplyControlHooks.ts
deleted file mode 100644
index e2d2925df..000000000
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MasterApplyControl/useMasterApplyControlHooks.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { storeToRefs } from 'pinia';
-import { computed, watch } from 'vue';
-import { useBasicStore } from '../../../../stores/basic';
-import { useRoomStore } from '../../../../stores/room';
-import useMasterApplyControl from '../../../../hooks/useMasterApplyControl';
-import { useI18n } from '../../../../locales';
-import TUINotification from '../../../common/base/Notification/index';
-import { isMobile } from '../../../../utils/environment';
-
-export default function useMasterApplyControlHooks() {
- const { t } = useI18n();
- const basicStore = useBasicStore();
- const roomStore = useRoomStore();
- const { handleUserApply, handleAllUserApply } = useMasterApplyControl();
- const { showApplyUserList } = storeToRefs(basicStore);
- const { applyToAnchorList } = storeToRefs(roomStore);
-
- const applyToAnchorUserCount = computed(() => applyToAnchorList.value.length);
- const noUserApply = computed(() => applyToAnchorUserCount.value === 0);
-
- const handleConfirm = async (onlyOneUserTakeStage: boolean, userId: string) => {
- if (isMobile) {
- basicStore.setSidebarOpenStatus(true);
- basicStore.setSidebarName('apply');
- } else {
- if (onlyOneUserTakeStage) {
- handleUserApply(userId, true);
- } else {
- basicStore.setShowApplyUserList(true);
- }
- }
- };
-
- const handleCancel = async (onlyOneUserTakeStage: boolean, userId: string) => {
- if (!isMobile && onlyOneUserTakeStage) {
- handleUserApply(userId, false);
- }
- };
-
- watch(applyToAnchorUserCount, (newVal, oldVal) => {
- if (newVal <= oldVal) return;
- const onlyOneUserTakeStage = newVal === 1;
- const firstUser = applyToAnchorList.value[0];
- const userName = firstUser?.userName || firstUser?.userId;
- const message = onlyOneUserTakeStage
- ? `${userName} ${t('Applying for the stage')}`
- : `${userName} ${t('and so on number people applying to stage', { number: applyToAnchorList.value.length })}`;
- TUINotification({
- message,
- appendToRoomContainer: true,
- confirmButtonText: isMobile ? t('Check') : (onlyOneUserTakeStage ? t('Agree to the stage') : t('Check')),
- cancelButtonText: isMobile ? undefined : (onlyOneUserTakeStage ? t('Reject') : t('Neglect')),
- confirm: () => handleConfirm(onlyOneUserTakeStage, firstUser?.userId),
- cancel: () => handleCancel(onlyOneUserTakeStage, firstUser?.userId),
- });
- });
-
- function hideApplyList() {
- basicStore.setShowApplyUserList(false);
- }
-
- return {
- t,
- roomStore,
- showApplyUserList,
- hideApplyList,
- applyToAnchorUserCount,
- applyToAnchorList,
- handleAllUserApply,
- handleUserApply,
- noUserApply,
- };
-}
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MemberApplyControl.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MemberApplyControl.vue
index c96715636..bee8281f6 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MemberApplyControl.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ApplyControl/MemberApplyControl.vue
@@ -199,6 +199,12 @@ function handleStepDownDialogVisible() {
async function leaveSeat() {
await roomEngine.instance?.leaveSeat();
showDialog.value = false;
+ if (roomStore.isCameraDisableForAllUser && isGeneralUser.value) {
+ roomStore.setCanControlSelfVideo(false);
+ }
+ if (roomStore.isMicrophoneDisableForAllUser && isGeneralUser.value) {
+ roomStore.setCanControlSelfAudio(false);
+ }
}
function hideApplyAttention() {
@@ -318,7 +324,6 @@ onBeforeUnmount(() => {
}
.mobile-info {
min-width: 50vw;
- white-space: normal;
}
.close {
cursor: pointer;
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/AudioControl.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/AudioControl.vue
index eddd5c62a..54e157e74 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/AudioControl.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/AudioControl.vue
@@ -118,7 +118,6 @@ async function toggleMuteAudio() {
TUIMessageBox({
title: t('Note'),
message: t('Microphone not detected on current device'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
});
return;
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/EndControl/index.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/EndControl/index.vue
index 7d4018601..0bbc289f8 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/EndControl/index.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/EndControl/index.vue
@@ -175,7 +175,6 @@ const onRoomDismissed = async (eventInfo: { roomId: string }) => {
TUIMessageBox({
title: t('Note'),
message: t('The host closed the room.'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
callback: async () => {
resetState();
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/EndControl/useEndControlHooks.ts b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/EndControl/useEndControlHooks.ts
index f72a1031e..033d4add8 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/EndControl/useEndControlHooks.ts
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/EndControl/useEndControlHooks.ts
@@ -1,6 +1,6 @@
import { ref, Ref, computed, onUnmounted } from 'vue';
import { useBasicStore } from '../../../stores/basic';
-import { useRoomStore } from '../../../stores/room';
+import { useRoomStore, UserInfo } from '../../../stores/room';
import { useChatStore } from '../../../stores/chat';
import { storeToRefs } from 'pinia';
import { useI18n } from '../../../locales';
@@ -25,7 +25,7 @@ export default function useEndControl() {
logger.log(`${logPrefix} basicStore:`, basicStore);
const roomStore = useRoomStore();
- const { localUser, remoteUserList } = storeToRefs(roomStore);
+ const { localUser, remoteUserList, applyToAnchorList } = storeToRefs(roomStore);
const title = computed(() => (currentDialogType.value === DialogType.BasicDialog ? t('Leave room?') : t('Select a new host')));
const isShowLeaveRoomDialog = computed(() => (
roomStore.isMaster && remoteUserList.value.length > 0)
@@ -87,6 +87,24 @@ export default function useEndControl() {
}
}
+ async function handleUpdateSeatApplicationList() {
+ if (!roomStore.isSpeakAfterTakingSeatMode) {
+ return;
+ }
+ if (applyToAnchorList.value.length > 0) {
+ applyToAnchorList.value.forEach((user: UserInfo) => {
+ user.applyToAnchorRequestId && roomStore.removeApplyToAnchorUser(user.applyToAnchorRequestId);
+ });
+ }
+ const applicationList = await roomEngine.instance?.getSeatApplicationList();
+ if (applicationList && applicationList.length > 0) {
+ for (const applicationInfo of applicationList) {
+ const { userId, requestId, timestamp } = applicationInfo;
+ roomStore.addApplyToAnchorUser({ userId, requestId, timestamp });
+ }
+ }
+ }
+
const onUserRoleChanged = async (eventInfo: { userId: string, userRole: TUIRole }) => {
const { userId, userRole } = eventInfo;
const isLocal = roomStore.localUser.userId === userId;
@@ -108,6 +126,12 @@ export default function useEndControl() {
if (oldUserRole === TUIRole.kAdministrator) {
TUIMessage({ type: 'warning', message: t('Your administrator status has been revoked') });
}
+ if (roomStore.localStream.hasAudioStream) {
+ roomStore.setCanControlSelfAudio(true);
+ }
+ if (roomStore.localStream.hasVideoStream) {
+ roomStore.setCanControlSelfVideo(true);
+ }
}
break;
case TUIRole.kAdministrator:
@@ -115,6 +139,9 @@ export default function useEndControl() {
TUIMessage({ type: 'success', message: t('You have become a administrator') });
roomStore.setCanControlSelfAudio(true);
roomStore.setCanControlSelfVideo(true);
+ if (roomStore.isSpeakAfterTakingSeatMode) {
+ handleUpdateSeatApplicationList();
+ }
}
break;
case TUIRole.kRoomOwner: {
@@ -125,13 +152,7 @@ export default function useEndControl() {
if (!roomStore.isAnchor) {
await roomEngine.instance?.takeSeat({ seatIndex: -1, timeout: 0 });
}
- const applicationList = await roomEngine.instance?.getSeatApplicationList();
- if (applicationList) {
- for (const applicationInfo of applicationList) {
- const { userId, requestId, timestamp } = applicationInfo;
- roomStore.addApplyToAnchorUser({ userId, requestId, timestamp });
- }
- }
+ handleUpdateSeatApplicationList();
}
if (chatStore.isMessageDisableByAdmin) {
roomEngine.instance?.disableSendingMessageByAdmin({
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ManageStageControl.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ManageStageControl.vue
index 528a3d980..b7fda321b 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ManageStageControl.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/ManageStageControl.vue
@@ -27,11 +27,13 @@ import { useI18n } from '../../locales';
import TuiBadge from '../common/base/Badge.vue';
import { isMobile } from '../../utils/environment';
import MasterApplyControl from './ApplyControl/MasterApplyControl/index.vue';
+import useMasterApplyControl from '../../hooks/useMasterApplyControl';
const { t } = useI18n();
const basicStore = useBasicStore();
const roomStore = useRoomStore();
+const { handleShowNotification } = useMasterApplyControl();
const { sidebarName, showApplyUserList } = storeToRefs(basicStore);
const { applyToAnchorList } = storeToRefs(roomStore);
@@ -48,4 +50,7 @@ function toggleManageStage() {
basicStore.setSidebarName('apply');
}
}
+
+handleShowNotification();
+
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/VideoControl.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/VideoControl.vue
index 2793405a4..10286657f 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/VideoControl.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomFooter/VideoControl.vue
@@ -118,7 +118,6 @@ async function toggleMuteVideo() {
TUIMessageBox({
title: t('Note'),
message: t('Camera not detected on current device'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
});
return;
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomHome/RoomControl/index.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomHome/RoomControl/index.vue
index e98d340a9..54d39f783 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomHome/RoomControl/index.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomHome/RoomControl/index.vue
@@ -83,9 +83,8 @@ import { useBasicStore } from '../../../stores/basic';
import { useRoomStore } from '../../../stores/room';
import AudioMediaControl from '../../common/AudioMediaControl.vue';
import VideoMediaControl from '../../common/VideoMediaControl.vue';
-import TUIRoomEngine, { TUIRoomEvents, TRTCVideoMirrorType, TRTCVideoRotation, TRTCVideoFillMode, TUIRoomDeviceMangerEvents } from '@tencentcloud/tuiroom-engine-electron';
+import TUIRoomEngine, { TRTCVideoMirrorType, TRTCVideoRotation, TRTCVideoFillMode, TUIRoomDeviceMangerEvents } from '@tencentcloud/tuiroom-engine-electron';
import vClickOutside from '../../../directives/vClickOutside';
-import { isElectron } from '../../../utils/environment';
import { isEnumerateDevicesSupported, isGetUserMediaSupported } from '../../../utils/mediaAbility';
import useDeviceManager from '../../../hooks/useDeviceManager';
@@ -134,38 +133,21 @@ async function openCamera() {
rotation: TRTCVideoRotation.TRTCVideoRotation0,
fillMode: TRTCVideoFillMode.TRTCVideoFillMode_Fill,
});
- if (isElectron) {
- roomEngine.instance?.setLocalVideoView({ view: 'stream-preview' });
- await roomEngine.instance?.openLocalCamera();
- } else {
- await roomEngine.instance?.startCameraDeviceTest({
- view: 'stream-preview',
- });
- }
+ await roomEngine.instance?.startCameraDeviceTest({
+ view: 'stream-preview',
+ });
}
async function closeCamera() {
- if (isElectron) {
- await roomEngine.instance?.closeLocalCamera();
- } else {
- await roomEngine.instance?.stopCameraDeviceTest();
- }
+ await roomEngine.instance?.stopCameraDeviceTest();
}
async function openAudio() {
- if (isElectron) {
- await roomEngine.instance?.openLocalMicrophone();
- } else {
- await roomEngine.instance?.startMicDeviceTest({ interval: 200 });
- }
+ await roomEngine.instance?.startMicDeviceTest({ interval: 200 });
}
async function closeAudio() {
- if (isElectron) {
- await roomEngine.instance?.closeLocalMicrophone();
- } else {
- await roomEngine.instance?.stopMicDeviceTest();
- }
+ await roomEngine.instance?.stopMicDeviceTest();
}
async function toggleMuteAudio() {
@@ -259,22 +241,13 @@ function enterRoom() {
TUIRoomEngine.once('ready', () => {
startStreamPreview();
- if (isElectron) {
- roomEngine.instance?.on(TUIRoomEvents.onUserVoiceVolumeChanged, onUserVoiceVolume);
- } else {
- deviceManager.instance?.on(TUIRoomDeviceMangerEvents.onTestMicVolume, onUserVoiceVolume);
- }
+ deviceManager.instance?.on(TUIRoomDeviceMangerEvents.onTestMicVolume, onUserVoiceVolume);
});
onBeforeUnmount(async () => {
await closeAudio();
await closeCamera();
-
- if (isElectron) {
- roomEngine.instance?.off(TUIRoomEvents.onUserVoiceVolumeChanged, onUserVoiceVolume);
- } else {
- deviceManager.instance?.off(TUIRoomDeviceMangerEvents.onTestMicVolume, onUserVoiceVolume);
- }
+ deviceManager.instance?.off(TUIRoomDeviceMangerEvents.onTestMicVolume, onUserVoiceVolume);
});
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomSidebar/useSideBarHooks.ts b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomSidebar/useSideBarHooks.ts
index c8a485e6c..4cf21c784 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomSidebar/useSideBarHooks.ts
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/RoomSidebar/useSideBarHooks.ts
@@ -64,13 +64,15 @@ export default function useSideBar() {
};
let tim = roomEngine.instance?.getTIM();
+ tim?.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onReceiveMessage);
+
watch(sdkAppId, () => {
- if (!tim) {
+ if (!tim && sdkAppId.value) {
tim = TencentCloudChat.create({ SDKAppID: basicStore.sdkAppId });
+ tim?.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onReceiveMessage);
}
- tim?.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onReceiveMessage);
- }, { immediate: true });
+ });
onUnmounted(() => {
tim?.off(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onReceiveMessage);
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/AudioMediaControl.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/AudioMediaControl.vue
index 0bf832657..7640bbd3a 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/AudioMediaControl.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/AudioMediaControl.vue
@@ -73,7 +73,6 @@ async function handleClickIcon() {
TUIMessageBox({
title: t('Note'),
message: t('The current browser does not support capturing audio'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
});
return;
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/RoomTime.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/RoomTime.vue
index 5504a80b9..30b167c45 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/RoomTime.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/RoomTime.vue
@@ -35,7 +35,5 @@ onUnmounted(() => {
font-size: 14px;
font-weight: 500;
line-height: 20px;
- width: 38px;
- letter-spacing: -0.24px;
}
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/VideoMediaControl.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/VideoMediaControl.vue
index f67f3c6ea..062d0b951 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/VideoMediaControl.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/VideoMediaControl.vue
@@ -73,7 +73,6 @@ async function handleClickIcon() {
TUIMessageBox({
title: t('Note'),
message: t('The current browser does not support capturing video'),
- appendToRoomContainer: true,
confirmButtonText: t('Sure'),
});
return;
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/base/MessageBox/index.ts b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/base/MessageBox/index.ts
index 8df1d8e52..eaac840a6 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/base/MessageBox/index.ts
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/base/MessageBox/index.ts
@@ -6,16 +6,16 @@ export type MessageProps = {
title: string,
message: string,
callback?: () => Promise
,
- appendToRoomContainer?: boolean,
confirmButtonText?: string,
}
-const MessageBox = ({ title, message, callback, appendToRoomContainer, confirmButtonText }: MessageProps) => {
+const MessageBox = ({ title, message, callback, confirmButtonText }: MessageProps) => {
const container = document.createElement('div');
- document.body.appendChild(container);
+ const fullscreenElement = document.fullscreenElement || document.getElementById('roomContainer') || document.body;
+ fullscreenElement.appendChild(container);
const onRemove = () => {
render(null, container);
- document.body.removeChild(container);
+ fullscreenElement.removeChild(container);
};
const vnode = createVNode(TUIMessageBox, {
@@ -24,7 +24,6 @@ const MessageBox = ({ title, message, callback, appendToRoomContainer, confirmBu
callback,
confirmButtonText,
remove: onRemove,
- appendToRoomContainer,
});
render(vnode, container);
};
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/base/MessageBox/index.vue b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/base/MessageBox/index.vue
index 7f5c44d5a..e39af9b21 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/components/common/base/MessageBox/index.vue
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/components/common/base/MessageBox/index.vue
@@ -1,8 +1,7 @@
-
+
+ */
+
import { getLanguage } from '../utils/common';
import ZH from './zh-CN';
import EN from './en-US';
+import { ref } from 'vue';
+
+const locale = ref('');
+class TUIKitI18n {
+ messages: Record;
+ global: Record;
+
+ constructor(options: { messages: Record, locale: string }) {
+ this.messages = options.messages;
+ locale.value = options.locale;
+ this.global = {};
+ this.global.locale = locale;
+ this.global.t = this.t.bind(this);
+ }
+
+ private getNamed(option: Record) {
+ return (key: string) => option[key] || key;
+ }
+
+ private t(key: any, option?: Record) {
+ const message = this.messages[locale.value];
+ if (!message[key]) {
+ return key;
+ }
+ if (typeof message[key] === 'function') {
+ const named = this.getNamed(option || {});
+ return message[key]({ named });
+ }
+ return message[key];
+ }
+
+ // 兼容 App.use 不报错
+ public install() {
+ }
+}
-// 注册i8n实例并引入语言文件
-const i18n = createI18n({
- legacy: false,
+const i18n = new TUIKitI18n({
locale: getLanguage() || 'zh-CN',
messages: {
'zh-CN': ZH,
@@ -15,4 +73,8 @@ const i18n = createI18n({
export default i18n;
-export { useI18n };
+export function useI18n() {
+ return {
+ t: i18n.global.t.bind(i18n),
+ };
+}
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/locales/zh-CN.ts b/Electron/vue3/packages/renderer/src/TUIRoom/locales/zh-CN.ts
index b0f511a8a..0a637c010 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/locales/zh-CN.ts
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/locales/zh-CN.ts
@@ -243,9 +243,9 @@ export default {
'kicked out of the room by other device': '相同账号在其他客户端进入房间',
'kicked out of the room by serve': '被服务端踢出房间',
// @ts-ignore
- 'Reject on Stage failed, please retry': ({ named }) => `拒绝 ${named('name')} 上台失败, 请重试`,
+ 'Reject sb stage failed, please retry': ({ named }) => `拒绝 ${named('name')} 上台失败, 请重试`,
// @ts-ignore
- 'Agree on Stage failed, please retry': ({ named }) => `同意 ${named('name')} 上台失败, 请重试`,
+ 'Agree sb stage failed, please retry': ({ named }) => `同意 ${named('name')} 上台失败, 请重试`,
'Has been fully muted and cannot open the microphone': '已被全员静音,无法打开麦克风',
'Has been muted by the host and cannot open the microphone': '已被主持人静音,无法打开麦克风',
'To apply to speak in the room, please raise your hand first to apply for the microphone': '申请发言房间,请先举手申请上麦',
diff --git a/Electron/vue3/packages/renderer/src/TUIRoom/services/roomService.ts b/Electron/vue3/packages/renderer/src/TUIRoom/services/roomService.ts
index cdabe428f..e8b901eb5 100644
--- a/Electron/vue3/packages/renderer/src/TUIRoom/services/roomService.ts
+++ b/Electron/vue3/packages/renderer/src/TUIRoom/services/roomService.ts
@@ -189,7 +189,6 @@ export class RoomService {
title: t('Note'),
message: notice,
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: async () => {
this.emit(EventType.ROOM_KICKED_OUT, { roomId, reason, message });
this.resetStore();
@@ -220,7 +219,6 @@ export class RoomService {
title: t('Note'),
message: t('userSig 已过期'),
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: () => {
this.emit(EventType.ROOM_USER_SIG_EXPIRED, {});
},
@@ -233,7 +231,6 @@ export class RoomService {
title: t('Note'),
message: t('系统检测到您的账号被踢下线'),
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: async () => {
this.emit(EventType.ROOM_KICKED_OFFLINE, { message });
},
@@ -338,13 +335,15 @@ export class RoomService {
await TUIRoomEngine.setSelfInfo({ userName, avatarUrl });
}
- private async doEnterRoom(roomId: string) {
+ private async doEnterRoom(options: { roomId: string; roomType: TUIRoomType}) {
+ const { roomId, roomType } = options;
const isH5 = isMobile && !isWeChat;
const trtcCloud = roomEngine.instance?.getTRTCCloud();
trtcCloud?.setDefaultStreamRecvMode(true, false);
trtcCloud?.enableSmallVideoStream(!isH5, smallParam);
const roomInfo = (await roomEngine.instance?.enterRoom({
roomId,
+ roomType,
})) as TUIRoomInfo;
roomEngine.instance?.muteLocalAudio();
if (!roomInfo.isSeatEnabled) {
@@ -453,7 +452,11 @@ export class RoomService {
}
this.basicStore.setRoomId(roomId);
logger.debug(`${logPrefix}enterRoom:`, roomId, roomParam);
- const roomInfo = await this.doEnterRoom(roomId);
+ const roomParams = {
+ roomId,
+ roomType: TUIRoomType.kConference,
+ };
+ const roomInfo = await this.doEnterRoom(roomParams);
this.roomStore.setRoomInfo(roomInfo);
await this.getUserList();
if (roomInfo.isSeatEnabled) {
diff --git a/Electron/vue3/packages/renderer/src/main.ts b/Electron/vue3/packages/renderer/src/main.ts
index c3f512f28..507d03a04 100644
--- a/Electron/vue3/packages/renderer/src/main.ts
+++ b/Electron/vue3/packages/renderer/src/main.ts
@@ -2,7 +2,6 @@ import { createApp } from 'vue';
import App from '@/App.vue';
import { createPinia } from 'pinia';
import router from './router/index';
-import VueI18n from './TUIRoom/locales/index';
import { ipcRenderer } from 'electron';
if (window.isHasScreen === undefined) {
window.isHasScreen = false;
@@ -18,5 +17,4 @@ ipcRenderer.on('main-process-message', (_event, ...args) => {
const app = createApp(App);
app.use(router);
app.use(createPinia());
-app.use(VueI18n);
app.mount('#app').$nextTick(window.removeLoading);
diff --git a/Electron/vue3/packages/renderer/src/views/home.vue b/Electron/vue3/packages/renderer/src/views/home.vue
index b29f8236e..b6d50e8db 100644
--- a/Electron/vue3/packages/renderer/src/views/home.vue
+++ b/Electron/vue3/packages/renderer/src/views/home.vue
@@ -65,7 +65,7 @@ async function checkRoomExistWhenCreateRoom(roomId: string) {
let isRoomExist = false;
const tim = roomEngine.instance?.getTIM();
try {
- await tim.searchGroupByID(roomId);
+ await tim?.searchGroupByID(roomId);
isRoomExist = true;
} catch (error: any) {
// 房间不存在
diff --git a/Electron/vue3/packages/renderer/src/views/room.vue b/Electron/vue3/packages/renderer/src/views/room.vue
index ef887f32a..37b75214e 100644
--- a/Electron/vue3/packages/renderer/src/views/room.vue
+++ b/Electron/vue3/packages/renderer/src/views/room.vue
@@ -18,7 +18,7 @@ import Room from '@/TUIRoom/index.vue';
import { useRoute } from 'vue-router';
import router from '@/router';
import { checkNumber } from '@/TUIRoom/utils/common';
-import { useI18n } from 'vue-i18n';
+import { useI18n } from '@/TUIRoom/locales';
import TUIMessageBox from '@/TUIRoom/components/common/base/MessageBox';
import {
TUIKickedOutOfRoomReason,
@@ -64,7 +64,6 @@ onMounted(async () => {
title: t('Note'),
message,
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: async () => {
router.replace({ path: 'home' });
},
@@ -79,7 +78,6 @@ onMounted(async () => {
title: t('Note'),
message,
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: async () => {
router.replace({ path: 'home' });
},
@@ -92,7 +90,6 @@ onMounted(async () => {
title: t('Note'),
message,
confirmButtonText: t('Sure'),
- appendToRoomContainer: true,
callback: async () => {
sessionStorage.removeItem('tuiRoom-currentUserInfo');
router.replace({ path: 'home' });