diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ProctoringDataMapper.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ProctoringDataMapper.cs index 6e600349..c270a095 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ProctoringDataMapper.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ProctoringDataMapper.cs @@ -20,8 +20,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping case Keys.Proctoring.JitsiMeet.AllowChat: MapJitsiMeetAllowChat(settings, value); break; - case Keys.Proctoring.JitsiMeet.AllowCloseCaptions: - MapJitsiMeetAllowCloseCaptions(settings, value); + case Keys.Proctoring.JitsiMeet.AllowClosedCaptions: + MapJitsiMeetAllowClosedCaptions(settings, value); break; case Keys.Proctoring.JitsiMeet.AllowRaiseHand: MapJitsiMeetAllowRaiseHands(settings, value); @@ -77,18 +77,36 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping case Keys.Proctoring.WindowVisibility: MapWindowVisibility(settings, value); break; + case Keys.Proctoring.Zoom.AllowChat: + MapZoomAllowChat(settings, value); + break; + case Keys.Proctoring.Zoom.AllowClosedCaptions: + MapZoomAllowClosedCaptions(settings, value); + break; + case Keys.Proctoring.Zoom.AllowRaiseHand: + MapZoomAllowRaiseHands(settings, value); + break; case Keys.Proctoring.Zoom.ApiKey: MapZoomApiKey(settings, value); break; case Keys.Proctoring.Zoom.ApiSecret: MapZoomApiSecret(settings, value); break; + case Keys.Proctoring.Zoom.AudioMuted: + MapZoomAudioMuted(settings, value); + break; case Keys.Proctoring.Zoom.Enabled: MapZoomEnabled(settings, value); break; case Keys.Proctoring.Zoom.MeetingNumber: MapZoomMeetingNumber(settings, value); break; + case Keys.Proctoring.Zoom.SendAudio: + MapZoomSendAudio(settings, value); + break; + case Keys.Proctoring.Zoom.SendVideo: + MapZoomSendVideo(settings, value); + break; case Keys.Proctoring.Zoom.Signature: MapZoomSignature(settings, value); break; @@ -98,6 +116,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping case Keys.Proctoring.Zoom.UserName: MapZoomUserName(settings, value); break; + case Keys.Proctoring.Zoom.VideoMuted: + MapZoomVideoMuted(settings, value); + break; } } @@ -109,11 +130,11 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping } } - private void MapJitsiMeetAllowCloseCaptions(AppSettings settings, object value) + private void MapJitsiMeetAllowClosedCaptions(AppSettings settings, object value) { if (value is bool allow) { - settings.Proctoring.JitsiMeet.AllowCloseCaptions = allow; + settings.Proctoring.JitsiMeet.AllowClosedCaptions = allow; } } @@ -280,6 +301,30 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping } } + private void MapZoomAllowChat(AppSettings settings, object value) + { + if (value is bool allow) + { + settings.Proctoring.Zoom.AllowChat = allow; + } + } + + private void MapZoomAllowClosedCaptions(AppSettings settings, object value) + { + if (value is bool allow) + { + settings.Proctoring.Zoom.AllowClosedCaptions = allow; + } + } + + private void MapZoomAllowRaiseHands(AppSettings settings, object value) + { + if (value is bool allow) + { + settings.Proctoring.Zoom.AllowRaiseHand = allow; + } + } + private void MapZoomApiKey(AppSettings settings, object value) { if (value is string key) @@ -296,6 +341,14 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping } } + private void MapZoomAudioMuted(AppSettings settings, object value) + { + if (value is bool muted) + { + settings.Proctoring.Zoom.AudioMuted = muted; + } + } + private void MapZoomEnabled(AppSettings settings, object value) { if (value is bool enabled) @@ -312,6 +365,22 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping } } + private void MapZoomSendAudio(AppSettings settings, object value) + { + if (value is bool send) + { + settings.Proctoring.Zoom.SendAudio = send; + } + } + + private void MapZoomSendVideo(AppSettings settings, object value) + { + if (value is bool send) + { + settings.Proctoring.Zoom.SendVideo = send; + } + } + private void MapZoomSignature(AppSettings settings, object value) { if (value is string signature) @@ -335,5 +404,13 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping settings.Proctoring.Zoom.UserName = name; } } + + private void MapZoomVideoMuted(AppSettings settings, object value) + { + if (value is bool muted) + { + settings.Proctoring.Zoom.VideoMuted = muted; + } + } } } diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs index eaca90ce..0139eeeb 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs @@ -218,7 +218,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData settings.Proctoring.Enabled = false; settings.Proctoring.JitsiMeet.AllowChat = false; - settings.Proctoring.JitsiMeet.AllowCloseCaptions = false; + settings.Proctoring.JitsiMeet.AllowClosedCaptions = false; settings.Proctoring.JitsiMeet.AllowRaiseHand = false; settings.Proctoring.JitsiMeet.AllowRecording = false; settings.Proctoring.JitsiMeet.AllowTileView = false; @@ -234,9 +234,15 @@ namespace SafeExamBrowser.Configuration.ConfigurationData settings.Proctoring.ShowTaskbarNotification = true; settings.Proctoring.WindowVisibility = WindowVisibility.Hidden; settings.Proctoring.Zoom.AllowChat = false; + settings.Proctoring.Zoom.AllowClosedCaptions = false; + settings.Proctoring.Zoom.AllowRaiseHand = false; + settings.Proctoring.Zoom.AudioMuted = true; settings.Proctoring.Zoom.Enabled = false; settings.Proctoring.Zoom.ReceiveAudio = false; settings.Proctoring.Zoom.ReceiveVideo = false; + settings.Proctoring.Zoom.SendAudio = true; + settings.Proctoring.Zoom.SendVideo = true; + settings.Proctoring.Zoom.VideoMuted = false; settings.Security.AllowApplicationLogAccess = false; settings.Security.AllowTermination = true; diff --git a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs index e294e76d..642659f8 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs @@ -229,7 +229,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData internal static class JitsiMeet { internal const string AllowChat = "jitsiMeetFeatureFlagChat"; - internal const string AllowCloseCaptions = "jitsiMeetFeatureFlagCloseCaptions"; + internal const string AllowClosedCaptions = "jitsiMeetFeatureFlagCloseCaptions"; internal const string AllowRaiseHand = "jitsiMeetFeatureFlagRaiseHand"; internal const string AllowRecording = "jitsiMeetFeatureFlagRecording"; internal const string AllowTileView = "jitsiMeetFeatureFlagTileView"; @@ -250,13 +250,20 @@ namespace SafeExamBrowser.Configuration.ConfigurationData internal static class Zoom { + internal const string AllowChat = "zoomFeatureFlagChat"; + internal const string AllowClosedCaptions = "zoomFeatureFlagCloseCaptions"; + internal const string AllowRaiseHand = "zoomFeatureFlagRaiseHand"; internal const string ApiKey = "zoomApiKey"; internal const string ApiSecret = "zoomApiSecret"; + internal const string AudioMuted = "zoomAudioMuted"; internal const string Enabled = "zoomEnable"; internal const string MeetingNumber = "zoomRoom"; + internal const string SendAudio = "zoomSendAudio"; + internal const string SendVideo = "zoomSendVideo"; internal const string Signature = "zoomToken"; internal const string Subject = "zoomSubject"; internal const string UserName = "zoomUserInfoDisplayName"; + internal const string VideoMuted = "zoomVideoMuted"; } } diff --git a/SafeExamBrowser.Proctoring/ProctoringController.cs b/SafeExamBrowser.Proctoring/ProctoringController.cs index 86d331f2..8ab3c461 100644 --- a/SafeExamBrowser.Proctoring/ProctoringController.cs +++ b/SafeExamBrowser.Proctoring/ProctoringController.cs @@ -240,7 +240,7 @@ namespace SafeExamBrowser.Proctoring if (settings.JitsiMeet.Enabled) { html = html.Replace("%%_ALLOW_CHAT_%%", settings.JitsiMeet.AllowChat ? "chat" : ""); - html = html.Replace("%%_ALLOW_CLOSED_CAPTIONS_%%", settings.JitsiMeet.AllowCloseCaptions ? "closedcaptions" : ""); + html = html.Replace("%%_ALLOW_CLOSED_CAPTIONS_%%", settings.JitsiMeet.AllowClosedCaptions ? "closedcaptions" : ""); html = html.Replace("%%_ALLOW_RAISE_HAND_%%", settings.JitsiMeet.AllowRaiseHand ? "raisehand" : ""); html = html.Replace("%%_ALLOW_RECORDING_%%", settings.JitsiMeet.AllowRecording ? "recording" : ""); html = html.Replace("%%_ALLOW_TILE_VIEW", settings.JitsiMeet.AllowTileView ? "tileview" : ""); @@ -255,12 +255,16 @@ namespace SafeExamBrowser.Proctoring else if (settings.Zoom.Enabled) { html = html.Replace("'%_ALLOW_CHAT_%'", settings.Zoom.AllowChat ? "true" : "false"); + html = html.Replace("'%_ALLOW_CLOSED_CAPTIONS_%'", settings.Zoom.AllowClosedCaptions ? "true" : "false"); + html = html.Replace("'%_ALLOW_RAISE_HAND_%'", settings.Zoom.AllowRaiseHand ? "true" : "false"); html = html.Replace("%%_API_KEY_%%", settings.Zoom.ApiKey); html = html.Replace("%%_API_SECRET_%%", settings.Zoom.ApiSecret); + html = html.Replace("'%_AUDIO_MUTED_%'", settings.Zoom.AudioMuted && settings.WindowVisibility != WindowVisibility.Hidden ? "true" : "false"); html = html.Replace("%%_MEETING_NUMBER_%%", settings.Zoom.MeetingNumber); html = html.Replace("%%_PASSWORD_%%", settings.Zoom.Password); html = html.Replace("%%_SIGNATURE_%%", settings.Zoom.Signature); html = html.Replace("%%_USER_NAME_%%", settings.Zoom.UserName); + html = html.Replace("'%_VIDEO_MUTED_%'", settings.Zoom.VideoMuted && settings.WindowVisibility != WindowVisibility.Hidden ? "true" : "false"); } return html; diff --git a/SafeExamBrowser.Proctoring/Zoom/index.html b/SafeExamBrowser.Proctoring/Zoom/index.html index bb1ca135..f55cb6f5 100644 --- a/SafeExamBrowser.Proctoring/Zoom/index.html +++ b/SafeExamBrowser.Proctoring/Zoom/index.html @@ -34,33 +34,38 @@ var audioContainer = document.getElementsByClassName('join-audio-container')[0]; var leave = document.getElementsByClassName('footer__leave-btn-container')[0]; var more = document.getElementsByClassName('more-button')[0]; + var raiseHandContainer = document.getElementsByClassName('participants-section-container__participants-footer')[0]; var videoButton = document.getElementsByClassName('send-video-container__btn')[0]; var videoContainer = document.getElementsByClassName('send-video-container')[0]; - if (audioButton && audioJoin < 100) { + if (audioButton && !'%_AUDIO_MUTED_%' && audioJoin < 100) { audioButton.click(); audioJoin++; } - if (audioContainer) { - audioContainer.style.visibility = "hidden"; + if (audioContainer && !'%_AUDIO_MUTED_%') { + audioContainer.style.visibility = 'hidden'; } if (leave) { - leave.style.visibility = "hidden"; + leave.style.visibility = 'hidden'; } if (more) { - more.style.visibility = "hidden"; + more.style.visibility = 'hidden'; } - if (videoButton && videoJoin < 100) { + if (raiseHandContainer && !'%_ALLOW_RAISE_HAND_%') { + raiseHandContainer.style.visibility = 'hidden'; + } + + if (videoButton && !'%_VIDEO_MUTED_%' && videoJoin < 100) { videoButton.click(); videoJoin++; } - if (videoContainer) { - videoContainer.style.visibility = "hidden"; + if (videoContainer && !'%_VIDEO_MUTED_%') { + videoContainer.style.visibility = 'hidden'; } requestAnimationFrame(initializeUserInterface); @@ -100,7 +105,7 @@ isSupportAV: true, isSupportBreakout: false, isSupportChat: '%_ALLOW_CHAT_%', - isSupportCC: false, + isSupportCC: '%_ALLOW_CLOSED_CAPTIONS_%', isSupportPolling: false, isSupportQA: false, isSupportNonverbal: false, diff --git a/SafeExamBrowser.Settings/Proctoring/JitsiMeetSettings.cs b/SafeExamBrowser.Settings/Proctoring/JitsiMeetSettings.cs index ac438744..a9c77d53 100644 --- a/SafeExamBrowser.Settings/Proctoring/JitsiMeetSettings.cs +++ b/SafeExamBrowser.Settings/Proctoring/JitsiMeetSettings.cs @@ -24,7 +24,7 @@ namespace SafeExamBrowser.Settings.Proctoring /// /// Determines whether the user can use close captions. /// - public bool AllowCloseCaptions { get; set; } + public bool AllowClosedCaptions { get; set; } /// /// Determines whether the user can use the raise hand feature. diff --git a/SafeExamBrowser.Settings/Proctoring/ZoomSettings.cs b/SafeExamBrowser.Settings/Proctoring/ZoomSettings.cs index 70dae978..fdb75c27 100644 --- a/SafeExamBrowser.Settings/Proctoring/ZoomSettings.cs +++ b/SafeExamBrowser.Settings/Proctoring/ZoomSettings.cs @@ -21,6 +21,16 @@ namespace SafeExamBrowser.Settings.Proctoring /// public bool AllowChat { get; set; } + /// + /// Determines whether the user can use closed captions. + /// + public bool AllowClosedCaptions { get; set; } + + /// + /// Determines whether the user can use the raise hand feature. + /// + public bool AllowRaiseHand { get; set; } + /// /// The API key to be used for authentication. /// @@ -31,6 +41,11 @@ namespace SafeExamBrowser.Settings.Proctoring /// public string ApiSecret { get; set; } + /// + /// Determines whether the audio starts muted. + /// + public bool AudioMuted { get; set; } + /// /// Determines whether proctoring with Zoom is enabled. /// @@ -56,6 +71,16 @@ namespace SafeExamBrowser.Settings.Proctoring /// public bool ReceiveVideo { get; set; } + /// + /// Determines whether the audio stream of the user will be sent to the server. + /// + public bool SendAudio { get; set; } + + /// + /// Determines whether the video stream of the user will be sent to the server. + /// + public bool SendVideo { get; set; } + /// /// The signature to be used for authentication. /// @@ -70,5 +95,10 @@ namespace SafeExamBrowser.Settings.Proctoring /// The user name to be used for the meeting. /// public string UserName { get; set; } + + /// + /// Determines whether the video starts muted. + /// + public bool VideoMuted { get; set; } } }