UNPKG

@tencentcloud/roomkit-web-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,

685 lines (684 loc) 29.1 kB
import { defineComponent, ref, computed, watch, nextTick, createElementBlock, openBlock, createVNode, unref, withCtx, createElementVNode, createCommentVNode, toDisplayString, Fragment, renderList, normalizeClass, createBlock, createTextVNode } from "vue"; import { useI18n } from "../../../locales/index.mjs"; import Input from "../../common/base/Input/index.mjs"; import Select from "../../common/base/Select/index.mjs"; import OPtion from "../../common/base/Option/index.mjs"; import { IconScheduleAttendees, IconClose, TUIButton } from "@tencentcloud/uikit-base-component-vue3"; import TuiAvatar from "../../common/Avatar.vue2.mjs"; import Datepicker from "../../common/base/Datepicker/index.mjs"; import Timepicker from "../../common/base/Timepicker/index.mjs"; import TuiSwitch from "../../common/base/TuiSwitch.vue.mjs"; import _sfc_main$1 from "../DurationTimePicker.vue.mjs"; import _sfc_main$2 from "../TimezonePicker.vue.mjs"; import Contacts from "../Contacts.vue.mjs"; import PanelContainer from "../PanelContainer.vue.mjs"; import InvitePanel from "../InvitePanel.vue.mjs"; import ActionSheep from "../../common/base/ActionSheep.vue2.mjs"; import { PASSWORD_MAX_LENGTH_LIMIT } from "../../../constants/room.mjs"; import "../../../services/main.mjs"; import { roomService } from "../../../services/roomService.mjs"; import { EventType } from "../../../services/types.mjs"; import { TUISeatMode, TUIConferenceStatus } from "@tencentcloud/tuiroom-engine-js"; import { isWeChat } from "../../../utils/environment.mjs"; import { deepClone, calculateByteLength } from "../../../utils/utils.mjs"; import "mitt"; import "../../../services/manager/roomActionManager.mjs"; import "@tencentcloud/tui-core"; import { invalidDigitalPasswordRegex } from "../../../utils/common.mjs"; import { getDateAndTime, convertToTimestamp, calculateEndTime } from "../scheduleUtils.mjs"; const _hoisted_1 = { class: "schedule-conference-form" }; const _hoisted_2 = { class: "form-items-container" }; const _hoisted_3 = { class: "form-item" }; const _hoisted_4 = { class: "form-label" }; const _hoisted_5 = { key: 0, class: "form-item" }; const _hoisted_6 = { class: "form-label" }; const _hoisted_7 = { class: "form-value" }; const _hoisted_8 = { class: "form-item" }; const _hoisted_9 = { class: "form-label" }; const _hoisted_10 = { class: "form-value" }; const _hoisted_11 = { class: "form-item" }; const _hoisted_12 = { class: "form-label" }; const _hoisted_13 = { class: "form-value" }; const _hoisted_14 = { key: 1, class: "form-item" }; const _hoisted_15 = { class: "form-label" }; const _hoisted_16 = { class: "form-value" }; const _hoisted_17 = { class: "form-item column" }; const _hoisted_18 = { class: "form-label" }; const _hoisted_19 = { class: "form-value" }; const _hoisted_20 = { class: "form-attendees-item-container" }; const _hoisted_21 = ["title"]; const _hoisted_22 = { class: "form-attendees" }; const _hoisted_23 = ["title"]; const _hoisted_24 = { key: 0, class: "form-attendees-item", style: { "flex-basis": "content" } }; const _hoisted_25 = { key: 0, class: "form-items-container" }; const _hoisted_26 = { class: "form-item" }; const _hoisted_27 = { class: "form-label" }; const _hoisted_28 = { class: "form-value flex-end" }; const _hoisted_29 = { key: 0, class: "form-item" }; const _hoisted_30 = { class: "form-label" }; const _hoisted_31 = { key: 1, class: "form-items-container" }; const _hoisted_32 = { class: "form-item" }; const _hoisted_33 = { class: "form-label" }; const _hoisted_34 = { class: "form-value flex-end" }; const _hoisted_35 = { class: "form-item" }; const _hoisted_36 = { class: "form-label" }; const _hoisted_37 = { class: "form-value flex-end" }; const _hoisted_38 = { class: "schedule-conference-footer" }; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "ScheduleConferencePanelH5", props: { userName: {}, visible: { type: Boolean }, conferenceInfo: {} }, emits: ["input"], setup(__props, { emit: __emit }) { const { t } = useI18n(); const shareLinkData = ref(); const props = __props; const emit = __emit; const isDialogVisible = ref(false); const contactsVisible = ref(false); const showRoomInvite = ref(false); const isShowPasswordInput = ref(false); const needCheck = ref(false); const isEditMode = computed(() => !!props.conferenceInfo); const roomId = ref(""); const contacts = ref([]); const { date: startDate, laterTime: startTime } = getDateAndTime(/* @__PURE__ */ new Date()); const defaultFormData = ref({ roomName: t("sb temporary room", { name: props.userName || roomService.basicStore.userId }), roomMode: "FreeToSpeak", startDate, startTime, duration: 1800, timezone: isWeChat ? "Asia/Shanghai" : Intl.DateTimeFormat().resolvedOptions().timeZone, searchUser: "", scheduleAttendees: [], isMicrophoneDisableForAllUser: false, isScreenShareDisableForAllUser: false, isCameraDisableForAllUser: false, password: "" }); const form = ref(deepClone(defaultFormData.value)); const resetData = () => { defaultFormData.value.startDate = form.value.startDate; defaultFormData.value.startTime = form.value.startTime; form.value = Object.assign({}, deepClone(defaultFormData.value)); }; watch( () => props.visible, async (val) => { isDialogVisible.value = val; if (val) { form.value.roomName = t("sb temporary room", { name: props.userName || roomService.basicStore.userId }); const { date, laterTime } = getDateAndTime(/* @__PURE__ */ new Date()); form.value.startDate = date; form.value.startTime = laterTime; contacts.value = await roomService.scheduleConferenceManager.fetchFriendList(); isEditMode.value && (form.value = Object.assign({}, deepClone(editParams.value))); } }, { immediate: true } ); const updateDialogVisible = (val) => { needCheck.value = val; emit("input", val); if (!val) { isShowPasswordInput.value = false; resetData(); } }; watch( isDialogVisible, (val) => { updateDialogVisible(val); }, { immediate: true } ); const editParams = computed(() => { if (!props.conferenceInfo) return {}; const { basicRoomInfo, scheduleAttendees, scheduleStartTime, scheduleEndTime } = props.conferenceInfo; const { date, time } = getDateAndTime(new Date(scheduleStartTime * 1e3)); const { roomName, isSeatEnabled, isMicrophoneDisableForAllUser, isScreenShareDisableForAllUser, isCameraDisableForAllUser, password } = basicRoomInfo; return { roomName, roomMode: isSeatEnabled ? "SpeakAfterTakingSeat" : "FreeToSpeak", startDate: date, startTime: time, duration: scheduleEndTime - scheduleStartTime, timezone: isWeChat ? "Asia/Shanghai" : Intl.DateTimeFormat().resolvedOptions().timeZone, searchUser: "", scheduleAttendees, isMicrophoneDisableForAllUser, isScreenShareDisableForAllUser, isCameraDisableForAllUser, password }; }); const scheduleParams = computed(() => { const { startDate: startDate2, startTime: startTime2, timezone, duration, scheduleAttendees } = form.value; const scheduleStartTime = convertToTimestamp(startDate2, startTime2, timezone); const scheduleEndTime = calculateEndTime(scheduleStartTime, duration); return { roomId: roomId.value, scheduleStartTime: scheduleStartTime / 1e3, scheduleEndTime: scheduleEndTime / 1e3, scheduleAttendees, roomName: form.value.roomName, isSeatEnabled: form.value.roomMode !== "FreeToSpeak", seatMode: form.value.roomMode === "SpeakAfterTakingSeat" ? TUISeatMode.kApplyToTake : void 0, isMicrophoneDisableForAllUser: form.value.isMicrophoneDisableForAllUser, isScreenShareDisableForAllUser: form.value.isScreenShareDisableForAllUser, isCameraDisableForAllUser: form.value.isCameraDisableForAllUser, password: form.value.password }; }); const timeCheck = () => { if (!needCheck.value) return true; const { timezone, startDate: startDate2, startTime: startTime2 } = form.value; const scheduleStartTime = convertToTimestamp(startDate2, startTime2, timezone); const currentDate = /* @__PURE__ */ new Date(); currentDate.setMilliseconds(0); currentDate.setSeconds(0); const currentTime = currentDate.getTime(); const result = scheduleStartTime >= currentTime; !result && roomService.emit(EventType.ROOM_NOTICE_MESSAGE, { type: "warning", message: t("The start time cannot be earlier than the current time") }); return result; }; const roomNameCheck = () => { if (!needCheck.value) return true; if (form.value.roomName === "") { roomService.emit(EventType.ROOM_NOTICE_MESSAGE, { type: "warning", message: t("The room name cannot be empty") }); return false; } const result = calculateByteLength(form.value.roomName) <= 100; !result && roomService.emit(EventType.ROOM_NOTICE_MESSAGE, { type: "warning", message: t("The room name cannot exceed 100 characters") }); return result; }; const roomStatusCheck = () => { var _a; if (!needCheck.value) return true; const isNotStarted = ((_a = props.conferenceInfo) == null ? void 0 : _a.status) === TUIConferenceStatus.kConferenceStatusNotStarted; !isNotStarted && roomService.emit(EventType.ROOM_NOTICE_MESSAGE, { type: "warning", message: t( "The meeting is in progress and any meeting information cannot be modified" ) }); return isNotStarted; }; const roomPasswordCheck = () => { if (!isShowPasswordInput.value) { form.value.password = ""; return true; } const { password } = form.value; if (calculateByteLength(password) !== PASSWORD_MAX_LENGTH_LIMIT) { roomService.emit(EventType.ROOM_NOTICE_MESSAGE, { type: "warning", message: t("Your room password format is incorrect, please check it") }); return false; } return true; }; watch( () => form.value.startTime, async (newValue, oldValue) => { if (!timeCheck()) { await nextTick(); form.value.startTime = oldValue; } } ); watch( () => form.value.startDate, async (newValue, oldValue) => { if (!timeCheck()) { await nextTick(); form.value.startDate = oldValue; } } ); watch( () => form.value.timezone, async (newValue, oldValue) => { const { startDate: startDate2, startTime: startTime2 } = form.value; const currentDate = new Date( convertToTimestamp(startDate2, startTime2, newValue, -1, oldValue) ); const { date, laterTime } = getDateAndTime(currentDate); form.value.startDate = date; form.value.startTime = laterTime; } ); watch( () => isShowPasswordInput.value, (val) => { if (val) { form.value.password = `${Math.floor(Math.random() * 9e5) + 1e5}`; } } ); watch( () => form.value.password, async (val) => { if (val && invalidDigitalPasswordRegex.test(val)) { await nextTick(); form.value.password = val.replace(invalidDigitalPasswordRegex, ""); } } ); const roomTypeList = [ { label: "Free Speech Room", value: "FreeToSpeak" }, { label: "On-stage Speaking Room", value: "SpeakAfterTakingSeat" } ]; const selectScheduleAttends = () => { contactsVisible.value = true; }; const searchScheduleAttend = (v) => { if (!v) return []; return contacts.value.filter( (user) => (user == null ? void 0 : user.profile.nick.includes(v)) || (user == null ? void 0 : user.userID.includes(v)) ); }; const addSelectUser = (user) => { var _a, _b; form.value.searchUser = ""; if (form.value.scheduleAttendees.findIndex( (item) => item.userId === user.userID ) !== -1) return; form.value.scheduleAttendees.push({ userId: user.userID, userName: (_a = user.profile) == null ? void 0 : _a.nick, avatarUrl: (_b = user.profile) == null ? void 0 : _b.avatar }); }; const removeSelectUser = (user) => { form.value.scheduleAttendees = form.value.scheduleAttendees.filter( (item) => item.userId !== user.userId ); }; const contactsConfirm = (contacts2) => { form.value.scheduleAttendees = contacts2; }; let scheduleConferenceInProgress = false; const scheduleConference = async () => { if (scheduleConferenceInProgress) return; if (!timeCheck()) return; if (!roomNameCheck()) return; if (!roomPasswordCheck()) return; scheduleConferenceInProgress = true; try { roomId.value = await roomService.scheduleConferenceManager.generateRoomId(); await roomService.scheduleConferenceManager.scheduleConference({ ...scheduleParams.value, roomId: roomId.value }); const userIdList = scheduleParams.value.scheduleAttendees.map( (item) => item.userId ); if (userIdList && userIdList.length > 0) { await roomService.scheduleConferenceManager.addAttendeesByAdmin({ roomId: roomId.value, userIdList }); } shareLinkData.value = deepClone(scheduleParams.value); updateDialogVisible(false); showRoomInvite.value = true; } catch (err) { roomService.emit(EventType.ROOM_NOTICE_MESSAGE, { type: "error", message: err.message }); } scheduleConferenceInProgress = false; }; const compareArrays = (oldArray, newArray, key) => { const added = []; const removed = []; const newKeySet = new Set(newArray.map((item) => item[key])); const oldKeySet = new Set(oldArray.map((item) => item[key])); newArray.forEach((item) => { if (!oldKeySet.has(item[key])) { added.push(item); } }); oldArray.forEach((item) => { if (!newKeySet.has(item[key])) { removed.push(item); } }); return { added, removed }; }; const updateConferenceInfo = async () => { var _a; if (!roomStatusCheck()) return; if (!timeCheck()) return; if (!roomNameCheck()) return; try { const roomId2 = (_a = props.conferenceInfo) == null ? void 0 : _a.basicRoomInfo.roomId; if (!roomId2) return; const { roomName, scheduleStartTime, scheduleEndTime, scheduleAttendees } = scheduleParams.value; await roomService.scheduleConferenceManager.updateConferenceInfo({ roomId: roomId2, roomName, scheduleStartTime, scheduleEndTime }); const compareResult = compareArrays( props.conferenceInfo.scheduleAttendees, scheduleAttendees, "userId" ); await Promise.all([ compareResult.added.length > 0 && roomService.scheduleConferenceManager.addAttendeesByAdmin({ roomId: roomId2, userIdList: compareResult.added.map((item) => item.userId) }), compareResult.removed.length > 0 && roomService.scheduleConferenceManager.removeAttendeesByAdmin({ roomId: roomId2, userIdList: compareResult.removed.map((item) => item.userId) }) ]); updateDialogVisible(false); } catch (err) { roomService.emit(EventType.ROOM_NOTICE_MESSAGE, { type: "error", message: err.message }); } }; return (_ctx, _cache) => { return openBlock(), createElementBlock("div", null, [ createVNode(PanelContainer, { visible: isDialogVisible.value, title: unref(t)(!isEditMode.value ? unref(t)("Schedule") : unref(t)("Modify Room")), onInput: _cache[11] || (_cache[11] = ($event) => isDialogVisible.value = $event) }, { default: withCtx(() => { var _a; return [ createElementVNode("div", _hoisted_1, [ createElementVNode("div", _hoisted_2, [ createElementVNode("div", _hoisted_3, [ createElementVNode("span", _hoisted_4, toDisplayString(unref(t)("Room Name")), 1), createVNode(unref(Input), { modelValue: form.value.roomName, "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => form.value.roomName = $event), class: "form-value", placeholder: unref(t)("please enter the room name"), maxlength: "", border: false }, null, 8, ["modelValue", "placeholder"]) ]), !isEditMode.value ? (openBlock(), createElementBlock("div", _hoisted_5, [ createElementVNode("span", _hoisted_6, toDisplayString(unref(t)("Room type")), 1), createElementVNode("div", _hoisted_7, [ createVNode(unref(Select), { value: form.value.roomMode, onInput: _cache[1] || (_cache[1] = ($event) => form.value.roomMode = $event) }, { default: withCtx(() => [ (openBlock(), createElementBlock(Fragment, null, renderList(roomTypeList, (item) => { return createVNode(unref(OPtion), { key: item.value, value: item.value, label: unref(t)(item.label) }, null, 8, ["value", "label"]); }), 64)) ]), _: 1 }, 8, ["value"]) ]) ])) : createCommentVNode("", true), createElementVNode("div", _hoisted_8, [ createElementVNode("span", _hoisted_9, toDisplayString(unref(t)("Starting time")), 1), createElementVNode("div", _hoisted_10, [ createVNode(unref(Datepicker), { class: "date-picker", value: form.value.startDate, onInput: _cache[2] || (_cache[2] = ($event) => form.value.startDate = $event) }, null, 8, ["value"]), createVNode(unref(Timepicker), { value: form.value.startTime, class: "time-picker", onInput: _cache[3] || (_cache[3] = ($event) => form.value.startTime = $event) }, null, 8, ["value"]) ]) ]), createElementVNode("div", _hoisted_11, [ createElementVNode("span", _hoisted_12, toDisplayString(unref(t)("Room duration")), 1), createElementVNode("div", _hoisted_13, [ createVNode(_sfc_main$1, { "model-value": form.value.duration, class: "select", onInput: _cache[4] || (_cache[4] = ($event) => form.value.duration = $event) }, null, 8, ["model-value"]) ]) ]), !unref(isWeChat) ? (openBlock(), createElementBlock("div", _hoisted_14, [ createElementVNode("span", _hoisted_15, toDisplayString(unref(t)("Time zone")), 1), createElementVNode("div", _hoisted_16, [ createVNode(_sfc_main$2, { "model-value": form.value.timezone, class: "select", onInput: _cache[5] || (_cache[5] = ($event) => form.value.timezone = $event) }, null, 8, ["model-value"]) ]) ])) : createCommentVNode("", true), createElementVNode("div", _hoisted_17, [ createElementVNode("span", _hoisted_18, toDisplayString(unref(t)("Attendees")), 1), createElementVNode("div", _hoisted_19, [ createVNode(unref(Input), { modelValue: form.value.searchUser, "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => form.value.searchUser = $event), class: "form-input search-user", search: searchScheduleAttend, select: addSelectUser, placeholder: unref(t)("Please enter the member name"), border: false }, { suffixIcon: withCtx(() => [ createVNode(unref(IconScheduleAttendees), { onClick: selectScheduleAttends, class: normalizeClass(["select-attendees"]) }) ]), searchResultItem: withCtx(({ data }) => [ createElementVNode("div", _hoisted_20, [ createVNode(TuiAvatar, { class: "form-attendees-item-avatar", "img-src": data.profile.avatar }, null, 8, ["img-src"]), createElementVNode("p", { class: "form-attendees-item-name", title: data.profile.nick }, toDisplayString(data.profile.nick), 9, _hoisted_21) ]) ]), _: 1 }, 8, ["modelValue", "placeholder"]), createElementVNode("div", _hoisted_22, [ (openBlock(true), createElementBlock(Fragment, null, renderList(form.value.scheduleAttendees, (user) => { return openBlock(), createElementBlock("span", { key: user.userId, class: "form-attendees-item" }, [ createVNode(TuiAvatar, { class: "form-attendees-item-avatar", "img-src": user.avatarUrl }, null, 8, ["img-src"]), createElementVNode("p", { class: "form-attendees-item-name", title: user.userName }, toDisplayString(user.userName), 9, _hoisted_23), createVNode(unref(IconClose), { class: "form-attendees-item-remove", onClick: ($event) => removeSelectUser(user) }, null, 8, ["onClick"]) ]); }), 128)), ((_a = form.value.scheduleAttendees) == null ? void 0 : _a.length) > 0 ? (openBlock(), createElementBlock("span", _hoisted_24, toDisplayString(`${form.value.scheduleAttendees.length} ${unref(t)("people")}`), 1)) : createCommentVNode("", true) ]) ]) ]) ]), !isEditMode.value ? (openBlock(), createElementBlock("div", _hoisted_25, [ createElementVNode("div", _hoisted_26, [ createElementVNode("span", _hoisted_27, toDisplayString(unref(t)("Encryption")), 1), createElementVNode("div", _hoisted_28, [ createVNode(TuiSwitch, { modelValue: isShowPasswordInput.value, "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => isShowPasswordInput.value = $event) }, null, 8, ["modelValue"]) ]) ]), isShowPasswordInput.value ? (openBlock(), createElementBlock("div", _hoisted_29, [ createElementVNode("span", _hoisted_30, toDisplayString(unref(t)("Room Password")), 1), createVNode(unref(Input), { "model-value": form.value.password, onInput: _cache[8] || (_cache[8] = ($event) => form.value.password = $event), class: "form-value", placeholder: unref(t)("Enter 6-digit password"), maxlength: "6", border: false, align: "right" }, null, 8, ["model-value", "placeholder"]) ])) : createCommentVNode("", true) ])) : createCommentVNode("", true), !isEditMode.value ? (openBlock(), createElementBlock("div", _hoisted_31, [ createElementVNode("div", _hoisted_32, [ createElementVNode("span", _hoisted_33, toDisplayString(unref(t)("Disable all audios")), 1), createElementVNode("div", _hoisted_34, [ createVNode(TuiSwitch, { modelValue: form.value.isMicrophoneDisableForAllUser, "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => form.value.isMicrophoneDisableForAllUser = $event) }, null, 8, ["modelValue"]) ]) ]), createElementVNode("div", _hoisted_35, [ createElementVNode("span", _hoisted_36, toDisplayString(unref(t)("Disable all videos")), 1), createElementVNode("div", _hoisted_37, [ createVNode(TuiSwitch, { modelValue: form.value.isCameraDisableForAllUser, "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => form.value.isCameraDisableForAllUser = $event) }, null, 8, ["modelValue"]) ]) ]) ])) : createCommentVNode("", true) ]), createElementVNode("div", _hoisted_38, [ !isEditMode.value ? (openBlock(), createBlock(unref(TUIButton), { key: 0, "custom-style": { width: "100%", padding: "10px", fontSize: "16px", borderRadius: "6px" }, onClick: scheduleConference, type: "primary" }, { default: withCtx(() => [ createTextVNode(toDisplayString(unref(t)("Schedule")), 1) ]), _: 1 })) : (openBlock(), createBlock(unref(TUIButton), { key: 1, type: "primary", onClick: updateConferenceInfo, "custom-style": { width: "100%", padding: "10px", fontSize: "16px", borderRadius: "6px" } }, { default: withCtx(() => [ createTextVNode(toDisplayString(unref(t)("Save")), 1) ]), _: 1 })) ]) ]; }), _: 1 }, 8, ["visible", "title"]), createVNode(Contacts, { visible: contactsVisible.value, contacts: contacts.value, "selected-list": scheduleParams.value.scheduleAttendees, onInput: _cache[12] || (_cache[12] = ($event) => contactsVisible.value = $event), onConfirm: contactsConfirm, isMobile: true }, null, 8, ["visible", "contacts", "selected-list"]), createVNode(ActionSheep, { visible: showRoomInvite.value, onInput: _cache[13] || (_cache[13] = ($event) => showRoomInvite.value = $event), title: unref(t)("Schedule successful, invite members to join") }, { default: withCtx(() => [ createVNode(InvitePanel, { shareLinkData: shareLinkData.value }, null, 8, ["shareLinkData"]) ]), _: 1 }, 8, ["visible", "title"]) ]); }; } }); export { _sfc_main as default };