import { updateFullTime, updateFullYear, } from '@ringcentral-integration/commons/helpers/meetingHelper'; import type { RcvDelegator, RcvItemType, RcvWaitingRoomModeProps, } from '@ringcentral-integration/commons/modules/RcVideo'; import { ASSISTED_USERS_MYSELF, AUTH_USER_TYPE, RCV_ITEM_NAME, RCV_WAITING_ROOM_MODE, } from '@ringcentral-integration/commons/modules/RcVideo'; import { RcCheckbox, RcDatePicker, RcIcon, RcLink, RcMenuItem, RcSelect, RcText, RcTextField, RcTimePicker, spacing, styled, } from '@ringcentral/juno'; import { InfoBorder } from '@ringcentral/juno-icon'; import clsx from 'clsx'; import type { FunctionComponent } from 'react'; import React, { useEffect, useMemo, useRef, useState, useCallback, } from 'react'; import { formatMeetingId } from '../../lib/MeetingCalendarHelper'; import { getHoursList, getMinutesList, HOUR_SCALE, MINUTE_SCALE, } from '../../lib/MeetingHelper'; import { VideoPanelProps } from '../GenericMeetingPanel/interface'; import { MigrateToPluginAlert, RemoveMeetingWarn } from '../MeetingAlert'; import { ExtendedTooltip } from '../MeetingConfigsV2/ExtendedTooltip'; import { SpinnerOverlay } from '../SpinnerOverlay'; import { SettingGroup } from './SettingGroup'; import { VideoSecuritySettingItem } from './VideoSecuritySettingItem'; import { RCV_SCHEDULE_ON_BEHALF_GUIDANCE_LINK } from './constants'; import i18n, { type I18nKey } from './i18n'; import styles from './styles.scss'; import { getHelperTextForPasswordField } from './utils'; const PanelRoot = styled.div` ${RcCheckbox} { padding: ${spacing(2)}; } `; export const VideoConfig: FunctionComponent = (props) => { const { disabled, currentLocale, meeting, updateMeetingSettings, recipientsSection, init, children, showWhen, showDuration, showRcvAdminLock, showPmiConfirm, showAllowAnyoneRecord, showAllowAnyoneTranscribe, showWaitingRoom, showE2EE, isE2EEDisabled, enablePersonalMeeting, isPmiChangeConfirmed, isPersonalMeetingDisabled, personalMeetingId, personalMeetingName, switchUsePersonalMeetingId, trackSettingChanges, e2eeInteractFunc, onPmiChangeClick, onCloseMigrationAlert, datePickerSize, timePickerSize, checkboxSize, labelPlacement, delegators, showScheduleOnBehalf, updateScheduleFor, showSpinnerInConfigPanel, joinBeforeHostLabel, authUserTypeValue, isJoinBeforeHostDisabled, isPasswordFieldDisabled, isAllowToRecordDisabled, isAllowAnyoneTranscribeDisabled, isMuteAudioDisabled, isTurnOffCameraDisabled, isAllowScreenSharingDisabled, isAuthenticatedCanJoinDisabled, isAuthUserTypeDisabled, isWaitingRoomTypeDisabled, isWaitingRoomDisabled, isRequirePasswordDisabled, isWaitingRoomNotCoworkerDisabled, isWaitingRoomGuestDisabled, showRemoveMeetingWarning, brandConfig, showMigrationAlert, } = props; const hoursList = getHoursList(HOUR_SCALE, currentLocale); const minutesList = getMinutesList(MINUTE_SCALE, currentLocale); useEffect(() => { if (init) { init(); } }, []); const update = (options: any, itemName?: RcvItemType) => { updateMeetingSettings({ ...meeting, ...options, }); trackSettingChanges && itemName && trackSettingChanges(itemName); }; /* Password validate interaction */ const [isPasswordFocus, setPasswordFocus] = useState(false); const startTime = useMemo(() => { return new Date(meeting.startTime!); }, [meeting.startTime!]); /* Scrollbar */ const configRef = useRef(); const [hasScrollBar, setHasScrollBar] = useState(false); useEffect(() => { setHasScrollBar( // @ts-expect-error TS(2532): Object is possibly 'undefined'. configRef.current.scrollHeight > configRef.current.clientHeight, ); }, []); const showPMI = useMemo( () => enablePersonalMeeting && (personalMeetingId || personalMeetingName), [enablePersonalMeeting, personalMeetingId, personalMeetingName], ); const getPMILabel = useCallback(() => { if (personalMeetingName) { return (
{i18n.getString('usePersonalMeetingName', currentLocale)}   {personalMeetingName}
); } const pmiId = formatMeetingId(personalMeetingId!, '-'); return (
{i18n.getString('usePersonalMeetingId', currentLocale)}   {pmiId}
); }, [personalMeetingId, personalMeetingName, currentLocale]); return ( // @ts-expect-error TS(2322): Type '{ children: Element; ref: MutableRefObject
{showSpinnerInConfigPanel ? : null} {showRemoveMeetingWarning && ( )} {showMigrationAlert && brandConfig.substituteName && ( )}
{children}
{recipientsSection ? (
{recipientsSection}
) : null} {showWhen ? (
{ update({ // @ts-expect-error TS(2345): Argument of type 'Date | null' is not assignable t... Remove this comment to see the full error message startTime: updateFullYear(startTime, value), }); }} />
{ update({ // @ts-expect-error TS(2345): Argument of type 'Date | null' is not assignable t... Remove this comment to see the full error message startTime: updateFullTime(startTime, value), }); }} />
) : null} {showDuration ? (
{ // @ts-expect-error TS(2571): Object is of type 'unknown'. const value = +e.target.value; const restMinutes = Math.floor(meeting.duration! % 60); const durationInMinutes = value * 60 + restMinutes; update({ duration: durationInMinutes, }); }} className={styles.select} label={i18n.getString('duration', currentLocale)} > {hoursList.map((item, i) => ( {/* @ts-expect-error TS(2339): Property 'text' does not exist on type 'never'. */} {item !== null ? item.text : 'defaultValue'} ))}
{ // @ts-expect-error TS(2571): Object is of type 'unknown'. const value = +e.target.value; const restHours = Math.floor(meeting.duration! / 60); // @ts-expect-error TS(2339): Property 'value' does not exist on type 'never'. const isMax = restHours === hoursList.slice(-1)[0].value; const minutes = isMax ? 0 : value; const durationInMinutes = restHours * 60 + minutes; update({ duration: durationInMinutes, }); }} > {minutesList.map((item, i) => ( {/* @ts-expect-error TS(2339): Property 'text' does not exist on type 'never'. */} {item !== null ? item.text : 'defaultValue'} ))}
) : null} {showScheduleOnBehalf ? ( {i18n.getString('scheduleFor', currentLocale)} { e.stopPropagation(); }} >
{i18n.getString('scheduleForGuidance', currentLocale)}

{i18n.getString( 'scheduleForGuidanceMore', currentLocale, )}
} > { e.stopPropagation(); }} /> } >
{ updateScheduleFor(e.target.value as string); // @ts-expect-error TS(2722): Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message trackSettingChanges(RCV_ITEM_NAME.scheduleFor); }} value={meeting.extensionId} > {/* @ts-expect-error TS(2532): Object is possibly 'undefined'. */} {delegators.map((item: RcvDelegator, index: number) => { const userName = item.name === ASSISTED_USERS_MYSELF ? i18n.getString(item.name, currentLocale) : item.name; return ( {userName} ); })}
) : null} {showPMI && ( <> { switchUsePersonalMeetingId(checked); }} /> {meeting.usePersonalMeetingId && showPmiConfirm && !isPmiChangeConfirmed ? (
{i18n.getString('changePmiSettings', currentLocale)}
) : null} )} { update( { muteAudio: !meeting.muteAudio, }, RCV_ITEM_NAME.muteAudio, ); }} /> { update( { muteVideo: !meeting.muteVideo, }, RCV_ITEM_NAME.muteVideo, ); }} />
{showE2EE ? ( {i18n.getString('useE2ee', currentLocale)} } > { e2eeInteractFunc(value); // @ts-expect-error TS(2722): Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message trackSettingChanges(RCV_ITEM_NAME.e2ee); }} /> ) : null} { const next = !meeting.isMeetingSecret; update( { isMeetingSecret: next, }, RCV_ITEM_NAME.isMeetingSecret, ); }} /> {meeting.isMeetingSecret ? (
{ update({ meetingPassword: e.target.value, }); }} onFocus={() => { setPasswordFocus(true); }} onBlur={() => { setPasswordFocus(false); // @ts-expect-error TS(2722): Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message trackSettingChanges(RCV_ITEM_NAME.meetingPassword); }} />
) : null} { update( { allowJoinBeforeHost: !meeting.allowJoinBeforeHost, }, RCV_ITEM_NAME.allowJoinBeforeHost, ); }} /> {showWaitingRoom ? ( <> { update( { waitingRoomMode: checked ? RCV_WAITING_ROOM_MODE.notcoworker : RCV_WAITING_ROOM_MODE.off, }, RCV_ITEM_NAME.waitingRoomMode, ); }} /> {meeting.waitingRoomMode ? (
{ update( { waitingRoomMode: e.target .value as RcvWaitingRoomModeProps, }, RCV_ITEM_NAME.waitingRoomType, ); }} value={meeting.waitingRoomMode} > {i18n.getString('waitingRoomAll', currentLocale)} {i18n.getString('waitingRoomNotCoworker', currentLocale)} {i18n.getString('waitingRoomGuest', currentLocale)}
) : null} ) : null} { update( { isOnlyAuthUserJoin: checked, isOnlyCoworkersJoin: checked ? meeting.isOnlyCoworkersJoin : false, }, RCV_ITEM_NAME.isOnlyAuthUserJoin, ); }} /> {meeting.isOnlyAuthUserJoin ? (
{ update( { isOnlyCoworkersJoin: e.target.value === AUTH_USER_TYPE.SIGNED_IN_CO_WORKERS, }, RCV_ITEM_NAME.isOnlyCoworkersJoin, ); }} value={authUserTypeValue} > {i18n.getString('signedInUsers', currentLocale)} {i18n.getString('signedInCoWorkers', currentLocale)}
) : null} { update( { allowScreenSharing: !meeting.allowScreenSharing, }, RCV_ITEM_NAME.allowScreenSharing, ); }} /> {showAllowAnyoneRecord && ( { update( { allowAnyoneRecord: e.target.value === 'true', }, RCV_ITEM_NAME.allowAnyoneRecord, ); }} value={meeting.allowAnyoneRecord?.toString()} > {i18n.getString('everyone', currentLocale)} {i18n.getString('onlyHostModerators', currentLocale)} )} {showAllowAnyoneTranscribe && ( { update( { allowAnyoneTranscribe: e.target.value === 'true', }, RCV_ITEM_NAME.allowAnyoneTranscribe, ); }} value={meeting.allowAnyoneTranscribe?.toString()} > {i18n.getString('everyone', currentLocale)} {i18n.getString('onlyHostModerators', currentLocale)} )}
); }; VideoConfig.defaultProps = { recipientsSection: undefined, showWhen: true, showDuration: true, showRcvAdminLock: false, enablePersonalMeeting: false, isPmiChangeConfirmed: false, showPmiConfirm: false, showWaitingRoom: false, showE2EE: false, isE2EEDisabled: false, datePickerSize: 'medium', timePickerSize: 'medium', labelPlacement: 'start', checkboxSize: 'medium', };