@newtonschool/react_proctoring_library 0.0.14 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,8 @@ exports.default = exports.ProctorApp = void 0;
7
7
 
8
8
  require("core-js/modules/web.dom-collections.iterator.js");
9
9
 
10
+ require("core-js/modules/es.promise.js");
11
+
10
12
  var _react = _interopRequireWildcard(require("react"));
11
13
 
12
14
  var _ = require(".");
@@ -15,20 +17,28 @@ var _utils = require("../utils");
15
17
 
16
18
  var _hooks = require("../hooks");
17
19
 
18
- var _defaults = require("../constants/defaults");
19
-
20
20
  var _permissions = require("./permissions");
21
21
 
22
22
  var _useWebcamData = _interopRequireDefault(require("../hooks/useWebcamData"));
23
23
 
24
24
  var _breachUtils = require("../utils/breachUtils");
25
25
 
26
+ var _webcamMicrophoneUtils = require("../utils/webcamMicrophoneUtils");
27
+
28
+ var _defaults = require("../constants/defaults");
29
+
26
30
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
31
 
28
32
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
29
33
 
30
34
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
31
35
 
36
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
37
+
38
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
39
+
40
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
41
+
32
42
  const isWebcamProcessingReliable = (0, _utils.isGPUAvailable)();
33
43
 
34
44
  const ProctorApp = _ref => {
@@ -42,93 +52,104 @@ const ProctorApp = _ref => {
42
52
  } = _ref;
43
53
  const webcamReference = (0, _react.useRef)(null);
44
54
  const canvasReference = (0, _react.useRef)(null);
45
- const statistics = (0, _react.useRef)(_defaults.INITIAL_STATISTICS);
55
+ const screenshareReference = (0, _react.useRef)(null);
56
+ const proctorParams = (0, _react.useMemo)(() => _objectSpread(_objectSpread({}, _defaults.defaultConfig), config.proctorParams), [config.proctorParams]);
57
+ const statistics = (0, _react.useRef)((0, _breachUtils.getInitialStats)(proctorParams));
46
58
  const {
47
- proctorParams,
48
59
  recurring = false,
49
- recurringFetchInterval = 0,
50
- trackScreenshare = false
51
- } = config; // const {
52
- // userCount = true,
53
- // tabSwitch = true,
54
- // fullscreenExit = true,
55
- // lookedAway = true,
56
- // } = proctorParams;
57
-
58
- const [audioPermission, setAudioPermission] = (0, _react.useState)(false);
59
- const [videoPermission, setVideoPermission] = (0, _react.useState)(false);
60
- const [screensharePermission, setScreensharePermission] = (0, _react.useState)(!trackScreenshare);
60
+ recurringFetchInterval = 0
61
+ } = config;
62
+ const [audioPermission, setAudioPermission] = (0, _react.useState)();
63
+ const [videoPermission, setVideoPermission] = (0, _react.useState)();
64
+ const [screensharePermission, setScreensharePermission] = (0, _react.useState)(!proctorParams.screenshareSnapshots);
61
65
  const firstFullScreenDone = (0, _react.useRef)(false);
66
+ const recurringFetchIntervalRef = (0, _react.useRef)(null);
67
+ const sendScreengrab = (0, _react.useCallback)(async function () {
68
+ let isBreach = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
69
+ let breachedParam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
70
+
71
+ if (proctorParams.screenshareSnapshots) {
72
+ const screenshot = await (0, _webcamMicrophoneUtils.captureScreenshot)();
73
+ getScreengrab(proctoringIdentifier, screenshot, isBreach, breachedParam);
74
+ }
75
+ }, [getScreengrab, proctoringIdentifier, proctorParams.screenshareSnapshots]);
76
+ const sendWebcamSnapshot = (0, _react.useCallback)(function () {
77
+ let isBreach = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
78
+ let breachedParam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
79
+
80
+ if (proctorParams.webcamSnapshots) {
81
+ const webcamSnapshot = (0, _utils.captureWebcamSnapshot)(webcamReference);
82
+
83
+ if (webcamReference) {
84
+ getWebcamSnapshot(proctoringIdentifier, webcamSnapshot, isBreach, breachedParam);
85
+ }
86
+ }
87
+ }, [proctoringIdentifier, getWebcamSnapshot, proctorParams.webcamSnapshots]);
88
+ const sendProctoredParamValues = (0, _react.useCallback)(function () {
89
+ let isBreach = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
90
+ let breachParam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
91
+ getProctorParamValues(proctoringIdentifier, statistics.current, isBreach, breachParam);
92
+ }, [proctoringIdentifier, getProctorParamValues]);
62
93
  const {
63
94
  isFullscreen,
64
- setFullscreen,
65
- fullScreenExitCount
66
- } = (0, _hooks.useFullscreenData)(firstFullScreenDone);
67
- const [userCount, lookedAwayCount, isWebcamDataReliable] = (0, _useWebcamData.default)(webcamReference, canvasReference);
68
- const tabSwitchCount = (0, _hooks.useTabSwitchCount)(firstFullScreenDone);
69
- let recurringFetchIntervalRef = (0, _react.useRef)(null);
95
+ setFullscreen
96
+ } = (0, _hooks.useFullscreenData)(firstFullScreenDone, proctorParams.fullscreenExit);
97
+ const [userCount, lookedAwayCount] = (0, _useWebcamData.default)(webcamReference, canvasReference, proctorParams);
98
+ const isTabSwitched = !(0, _hooks.usePageVisibility)(proctorParams.tabSwitch) && firstFullScreenDone.current;
70
99
  (0, _react.useEffect)(() => {
71
100
  if (recurring) {
72
101
  recurringFetchIntervalRef.current = setInterval(() => {
73
- getProctorParamValues(proctoringIdentifier, statistics.current, false);
74
- const webcamSnapshot = (0, _utils.captureWebcamSnapshot)(webcamReference);
75
-
76
- if (webcamReference) {
77
- getWebcamSnapshot(proctoringIdentifier, webcamSnapshot, false);
78
- }
102
+ sendProctoredParamValues();
103
+ sendWebcamSnapshot();
104
+ sendScreengrab();
79
105
  }, recurringFetchInterval);
80
106
  }
81
107
 
82
108
  return () => {
83
109
  clearInterval(recurringFetchIntervalRef.current);
84
110
  };
85
- }, [proctoringIdentifier, recurring, recurringFetchInterval, getWebcamSnapshot, getProctorParamValues]);
111
+ }, [recurring, recurringFetchInterval, sendProctoredParamValues, sendWebcamSnapshot, sendScreengrab]);
86
112
  (0, _react.useEffect)(() => {
87
113
  const currentStats = {
88
114
  userCount,
89
- tabSwitchCount,
90
- fullScreenExitCount,
115
+ isTabSwitched,
116
+ isFullscreen,
91
117
  lookedAwayCount,
92
118
  isWebcamDataReliable: isWebcamProcessingReliable
93
119
  };
94
- const breachData = (0, _breachUtils.getDataOnBreach)(statistics, currentStats, proctoringIdentifier);
120
+ const breachData = (0, _breachUtils.getDataOnBreach)(statistics, currentStats, proctorParams);
121
+ (0, _utils.updateStatistics)(statistics, currentStats, proctorParams);
95
122
 
96
123
  if (breachData) {
97
- getProctorParamValues(breachData.proctoringIdentifier, breachData.data, true, breachData.breachedParam);
98
-
99
- if (breachData.breachedParam === "LOOKED_AWAY_COUNT" || breachData.breachedParam === "USER_COUNT_MAX") {
100
- const webcamSnapshot = (0, _utils.captureWebcamSnapshot)(webcamReference);
101
-
102
- if (webcamSnapshot) {
103
- getWebcamSnapshot(breachData.proctoringIdentifier, webcamSnapshot, true, breachData.breachedParam);
104
- }
105
- } else {// getScreengrab();
106
- }
107
-
108
- (0, _utils.updateStatistics)(statistics, currentStats);
124
+ sendProctoredParamValues(true, breachData.breachedParam);
125
+ sendWebcamSnapshot(true, breachData.breachedParam);
126
+ sendScreengrab(true, breachData.breachedParam);
109
127
  }
110
- }, [userCount, tabSwitchCount, fullScreenExitCount, lookedAwayCount, isWebcamDataReliable, proctoringIdentifier, getProctorParamValues, getWebcamSnapshot]);
111
-
112
- if (proctoringIdentifier === undefined) {
113
- // todo
114
- return;
115
- }
116
-
117
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_permissions.Permission, {
128
+ }, [userCount, isTabSwitched, isFullscreen, lookedAwayCount, sendProctoredParamValues, sendWebcamSnapshot, sendScreengrab, proctorParams]);
129
+ const updateScreensharePermission = (0, _react.useCallback)(() => {
130
+ (0, _webcamMicrophoneUtils.setupScreensharePermission)(setScreensharePermission, screenshareReference);
131
+ }, []);
132
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _breachUtils.showProctoredComponent)(proctorParams, {
133
+ isFullscreen,
134
+ audioPermission,
135
+ videoPermission,
136
+ screensharePermission
137
+ }) && children, /*#__PURE__*/_react.default.createElement(_permissions.Permission, {
138
+ proctorParams: proctorParams,
118
139
  isFullscreen: isFullscreen,
119
140
  audioPermisison: audioPermission,
120
141
  videoPermission: videoPermission,
142
+ setFullscreen: setFullscreen,
121
143
  screensharePermission: screensharePermission,
122
- trackScreenshare: trackScreenshare,
123
- setFullscreen: setFullscreen
144
+ updateScreensharePermission: updateScreensharePermission
124
145
  }), /*#__PURE__*/_react.default.createElement(_.ActivityTracker, {
146
+ proctorParams: proctorParams,
125
147
  setAudioPermission: setAudioPermission,
126
148
  setVideoPermission: setVideoPermission,
127
149
  webcamReference: webcamReference,
128
150
  canvasReference: canvasReference,
129
- trackScreenshare: trackScreenshare,
130
- setScreensharePermission: setScreensharePermission
131
- }), isFullscreen && audioPermission && videoPermission && children);
151
+ screenshareReference: screenshareReference
152
+ }));
132
153
  };
133
154
 
134
155
  exports.ProctorApp = ProctorApp;
@@ -7,16 +7,16 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.default = void 0;
9
9
 
10
- require("core-js/modules/es.regexp.exec.js");
11
-
12
- require("core-js/modules/es.string.match.js");
13
-
14
10
  var _react = _interopRequireWildcard(require("react"));
15
11
 
16
12
  var _reactWebcam = _interopRequireDefault(require("react-webcam"));
17
13
 
18
14
  var _utils = require("../../utils");
19
15
 
16
+ var _breachUtils = require("../../utils/breachUtils");
17
+
18
+ var _browserUtils = require("../../utils/browserUtils");
19
+
20
20
  var _webcamMicrophoneUtils = require("../../utils/webcamMicrophoneUtils");
21
21
 
22
22
  require("./index.scss");
@@ -27,50 +27,44 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
27
27
 
28
28
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
29
29
 
30
- const isChrome = !!navigator.userAgent.match(/chrome|chromium/i);
31
-
32
30
  const ActivityTracker = _ref => {
33
31
  let {
32
+ proctorParams,
34
33
  webcamReference,
35
34
  canvasReference,
36
35
  setAudioPermission,
37
36
  setVideoPermission,
38
- trackScreenshare,
39
- setScreensharePermission
37
+ screenshareReference
40
38
  } = _ref;
41
- const videoReference = (0, _react.useRef)(null);
42
39
  (0, _react.useEffect)(() => {
43
- if (isChrome) {
44
- (0, _webcamMicrophoneUtils.updateVideoPermissions)(setVideoPermission);
45
- (0, _webcamMicrophoneUtils.updateAudioPermissions)(setAudioPermission);
46
-
47
- if (trackScreenshare) {
48
- (0, _webcamMicrophoneUtils.updateScreensharePermission)(setScreensharePermission, videoReference);
40
+ if ((0, _browserUtils.isChrome)()) {
41
+ if ((0, _breachUtils.isWebcamRequired)(proctorParams)) {
42
+ (0, _webcamMicrophoneUtils.updateVideoPermissions)(setVideoPermission);
43
+ (0, _webcamMicrophoneUtils.updateAudioPermissions)(setAudioPermission);
44
+ (0, _webcamMicrophoneUtils.getVideoPermissionQuery)().then(status => {
45
+ status.onchange = evt => {
46
+ (0, _webcamMicrophoneUtils.updateVideoPermissions)(setVideoPermission);
47
+ };
48
+ }).catch(err => {
49
+ console.log("Video Permission", err);
50
+ });
51
+ (0, _webcamMicrophoneUtils.getAudioPermissionQuery)().then(status => {
52
+ status.onchange = evt => {
53
+ (0, _webcamMicrophoneUtils.updateAudioPermissions)(setAudioPermission);
54
+ };
55
+ }).catch(err => {
56
+ (0, _webcamMicrophoneUtils.updateAudioPermissions)("Audio Permission", err);
57
+ });
49
58
  }
50
-
51
- (0, _webcamMicrophoneUtils.getVideoPermissionQuery)().then(status => {
52
- status.onchange = evt => {
53
- (0, _webcamMicrophoneUtils.updateVideoPermissions)(setVideoPermission);
54
- };
55
- }).catch(err => {
56
- console.log("Video Permission", err);
57
- });
58
- (0, _webcamMicrophoneUtils.getAudioPermissionQuery)().then(status => {
59
- status.onchange = evt => {
60
- (0, _webcamMicrophoneUtils.updateAudioPermissions)(setAudioPermission);
61
- };
62
- }).catch(err => {
63
- (0, _webcamMicrophoneUtils.updateAudioPermissions)("Audio Permission", err);
64
- });
65
59
  }
66
- }, [setVideoPermission, setAudioPermission, setScreensharePermission, trackScreenshare]);
67
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactWebcam.default, {
60
+ }, [setVideoPermission, setAudioPermission, proctorParams]);
61
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _breachUtils.isWebcamRequired)(proctorParams) && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactWebcam.default, {
68
62
  audio: true,
69
63
  muted: true,
70
64
  screenshotFormat: "image/jpeg",
71
65
  ref: webcamReference,
72
66
  onUserMedia: stream => {
73
- if (!isChrome) {
67
+ if (!(0, _browserUtils.isChrome)()) {
74
68
  const {
75
69
  audio,
76
70
  video
@@ -137,7 +131,7 @@ const ActivityTracker = _ref => {
137
131
  }
138
132
  },
139
133
  onUserMediaError: error => {
140
- if (!isChrome) {
134
+ if (!(0, _browserUtils.isChrome)()) {
141
135
  setVideoPermission(false);
142
136
  setAudioPermission(false);
143
137
  }
@@ -145,9 +139,12 @@ const ActivityTracker = _ref => {
145
139
  className: "captured-video-canvas"
146
140
  }), /*#__PURE__*/_react.default.createElement("canvas", {
147
141
  ref: canvasReference,
148
- className: "captured-video-canvas"
149
- }), /*#__PURE__*/_react.default.createElement("video", {
150
- src: videoReference.current
142
+ className: "captured-video-canvas",
143
+ id: "wc-ref"
144
+ })), proctorParams.screenshareSnapshots && /*#__PURE__*/_react.default.createElement("video", {
145
+ ref: screenshareReference,
146
+ className: "captured-video-canvas",
147
+ id: "ss-ref"
151
148
  }));
152
149
  };
153
150
 
@@ -19,6 +19,8 @@ var text = _interopRequireWildcard(require("../../constants/text"));
19
19
 
20
20
  var _permissionBody = require("./permission-body");
21
21
 
22
+ var _breachUtils = require("../../utils/breachUtils");
23
+
22
24
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
23
25
 
24
26
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -27,14 +29,15 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
27
29
 
28
30
  const Permission = _ref => {
29
31
  let {
32
+ proctorParams,
30
33
  isFullscreen,
31
34
  audioPermisison,
32
35
  videoPermission,
36
+ setFullscreen,
33
37
  screensharePermission,
34
- trackScreenshare,
35
- setFullscreen
38
+ updateScreensharePermission
36
39
  } = _ref;
37
- const showPermissionModal = !isFullscreen || !audioPermisison || !videoPermission;
40
+ const showPermissionModal = isFullscreen === false || (0, _breachUtils.isWebcamRequired)(proctorParams) && audioPermisison === false || (0, _breachUtils.isWebcamRequired)(proctorParams) && videoPermission === false || !screensharePermission;
38
41
  return /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal, {
39
42
  show: showPermissionModal,
40
43
  size: "lg",
@@ -43,7 +46,7 @@ const Permission = _ref => {
43
46
  centered: true
44
47
  }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Header, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Title, null, text.PERMISSION_TITLE)), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Body, {
45
48
  className: "font-medium"
46
- }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
49
+ }, /*#__PURE__*/_react.default.createElement("div", {
47
50
  style: {
48
51
  borderRadius: "20px"
49
52
  }
@@ -59,10 +62,14 @@ const Permission = _ref => {
59
62
  src: _askPermission.default
60
63
  }), text.VIDEO_UNSUPPORTED_IN_BROWSER)), /*#__PURE__*/_react.default.createElement(_permissionBody.PermissionBody, {
61
64
  showFullscreenText: !isFullscreen,
62
- showAudioPermissionText: !audioPermisison,
63
- showVideoPermissionText: !videoPermission,
64
- showScreensharePermission: !screensharePermission && trackScreenshare
65
- }))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Footer, null, !isFullscreen && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
65
+ showAudioPermissionText: !audioPermisison && (0, _breachUtils.isWebcamRequired)(proctorParams),
66
+ showVideoPermissionText: !videoPermission && (0, _breachUtils.isWebcamRequired)(proctorParams),
67
+ showScreensharePermission: !screensharePermission && proctorParams.screenshareSnapshots
68
+ })), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Footer, null, !screensharePermission && proctorParams.screenshareSnapshots && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
69
+ onClick: () => {
70
+ updateScreensharePermission();
71
+ }
72
+ }, text.ALLOW_SCREENSHARE), screensharePermission && !isFullscreen && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
66
73
  variant: "primary",
67
74
  onClick: () => {
68
75
  setFullscreen();
@@ -15,6 +15,8 @@ require("./index.scss");
15
15
 
16
16
  var text = _interopRequireWildcard(require("../../constants/text"));
17
17
 
18
+ var _browserUtils = require("../../utils/browserUtils");
19
+
18
20
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
21
 
20
22
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -32,9 +34,9 @@ const PermissionBody = _ref => {
32
34
  className: "mb-2"
33
35
  }, text.PERMISSION_GENERIC), showScreensharePermission && /*#__PURE__*/_react.default.createElement("div", {
34
36
  className: "mb-2"
35
- }, /*#__PURE__*/_react.default.createElement("span", {
37
+ }, (0, _browserUtils.isChrome)() && /*#__PURE__*/_react.default.createElement("strong", null, "Please switch to chrome"), /*#__PURE__*/_react.default.createElement("span", {
36
38
  className: "pr-2 font-weight-bold"
37
- }, "Screen Share:"), text.PERMISSION_SCREENSHARE), showAudioPermissionText && showVideoPermissionText ? /*#__PURE__*/_react.default.createElement("div", {
39
+ }, "Screenshare:"), text.PERMISSION_SCREENSHARE), showAudioPermissionText && showVideoPermissionText ? /*#__PURE__*/_react.default.createElement("div", {
38
40
  className: "mb-2"
39
41
  }, /*#__PURE__*/_react.default.createElement("span", {
40
42
  className: "pr-2 font-weight-bold"
@@ -3,40 +3,44 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.initialValues = exports.gpuTypes = exports.glancePercentageToPass = exports.evaluateVideoIntervalInSeconds = exports.bodyPixConfigs = exports.INITIAL_STATISTICS = void 0;
6
+ exports.initialValues = exports.gpuTypes = exports.evaluateVideoIntervalInSeconds = exports.defaultConfig = exports.STATS_PARAMS = exports.INITIAL_STATISTICS = void 0;
7
+ const defaultConfig = {
8
+ people: true,
9
+ tabSwitch: true,
10
+ fullscreenExit: true,
11
+ lookedAway: true,
12
+ webcamSnapshots: true,
13
+ screenshareSnapshots: true
14
+ };
15
+ exports.defaultConfig = defaultConfig;
7
16
  const initialValues = {
8
- tabSwitchCount: 0,
17
+ isTabSwitched: false,
9
18
  userCount: 0,
10
19
  isWebcamDataReliable: true,
11
20
  isWatching: true,
12
21
  canOpenFullScreen: false,
13
- fullScreenExitCount: 0,
22
+ isFullscreen: false,
14
23
  lookedAwayCount: 0,
15
24
  firstTimeFullScreen: true
16
25
  };
17
26
  exports.initialValues = initialValues;
27
+ const STATS_PARAMS = {
28
+ isTabSwitched: "IS_TAB_SWITCHED",
29
+ isFullscreen: "IS_FULLSCREEN",
30
+ lookedAwayCount: "LOOKED_AWAY_COUNT",
31
+ userCountMax: "USER_COUNT_MAX",
32
+ isWebcamReliable: "IS_WEBCAM_DATA_RELIABLE"
33
+ };
34
+ exports.STATS_PARAMS = STATS_PARAMS;
18
35
  const INITIAL_STATISTICS = {
19
- TAB_SWITCH_COUNT: initialValues.tabSwitchCount,
20
- FULLSCREEN_EXIT_COUNT: initialValues.fullScreenExitCount,
21
- LOOKED_AWAY_COUNT: initialValues.lookedAwayCount,
22
- USER_COUNT_MAX: initialValues.userCount,
23
- IS_WEBCAM_DATA_RELIABLE: initialValues.isWebcamDataReliable
36
+ [STATS_PARAMS.isTabSwitched]: initialValues.isTabSwitched,
37
+ [STATS_PARAMS.isFullscreen]: initialValues.isFullscreen,
38
+ [STATS_PARAMS.lookedAwayCount]: initialValues.lookedAwayCount,
39
+ [STATS_PARAMS.userCountMax]: initialValues.userCount,
40
+ [STATS_PARAMS.isWebcamReliable]: initialValues.isWebcamDataReliable
24
41
  };
25
42
  exports.INITIAL_STATISTICS = INITIAL_STATISTICS;
26
- const bodyPixConfigs = {
27
- flipHorizontal: false,
28
- internalResolution: "medium",
29
- segmentationThreshold: 0.4,
30
- maxDetections: 10,
31
- scoreThreshold: 0.2,
32
- nmsRadius: 20,
33
- minKeypointScore: 0.3,
34
- refineSteps: 10
35
- };
36
- exports.bodyPixConfigs = bodyPixConfigs;
37
- const glancePercentageToPass = 60;
38
- exports.glancePercentageToPass = glancePercentageToPass;
39
- const evaluateVideoIntervalInSeconds = 1;
43
+ const evaluateVideoIntervalInSeconds = 5;
40
44
  exports.evaluateVideoIntervalInSeconds = evaluateVideoIntervalInSeconds;
41
45
  const gpuTypes = ["intel", "apple", "amd", "radeon", "nvidia", "geforce"];
42
46
  exports.gpuTypes = gpuTypes;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.WATCHING_SCREEN = exports.VIDEO_UNSUPPORTED_IN_BROWSER = exports.USER_COUNT_LABEL = exports.REQUEST_VIDEO_AUDIO_PERMISSIONS_HEADING = exports.REQUEST_VIDEO_AUDIO_PERMISSIONS_DESC = exports.REQUEST_PERMISSION = exports.PERMISSION_VIDEO = exports.PERMISSION_TITLE = exports.PERMISSION_SCREENSHARE = exports.PERMISSION_GENERIC = exports.PERMISSION_FULLSCREEN = exports.PERMISSION_AUDIO_VIDEO = exports.PERMISSION_AUDIO = exports.NO_CAMERA_AVAILABLE = exports.NO_AUDIO_DEVICE_AVAILABLE = exports.NOT_WATCHING_SCREEN = exports.MESSAGE = exports.FULLSCREEN_ERROR_MESSAGE = exports.DENY_FULLSCREEN = exports.CAMERA_UNAVAILABLE_INSECURE_CONN = exports.BROWSER_BLOCKED_PERMISSION_RESOLVED_RECHECK = exports.BROWSER_BLOCKED_PERMISSION_NEXT_STEP = exports.BROWSER_BLOCKED_PERMISSION_DIRECTION = exports.BROWSER_BLOCKED_PERMISSION_DIALOG = exports.BROWSER_BLOCKED_PERMISSION = exports.ALLOW_FULLSCREEN = void 0;
6
+ exports.WATCHING_SCREEN = exports.VIDEO_UNSUPPORTED_IN_BROWSER = exports.USER_COUNT_LABEL = exports.REQUEST_VIDEO_AUDIO_PERMISSIONS_HEADING = exports.REQUEST_VIDEO_AUDIO_PERMISSIONS_DESC = exports.REQUEST_PERMISSION = exports.PERMISSION_VIDEO = exports.PERMISSION_TITLE = exports.PERMISSION_SCREENSHARE = exports.PERMISSION_GENERIC = exports.PERMISSION_FULLSCREEN = exports.PERMISSION_AUDIO_VIDEO = exports.PERMISSION_AUDIO = exports.NO_CAMERA_AVAILABLE = exports.NO_AUDIO_DEVICE_AVAILABLE = exports.NOT_WATCHING_SCREEN = exports.MESSAGE = exports.FULLSCREEN_ERROR_MESSAGE = exports.DENY_FULLSCREEN = exports.CAMERA_UNAVAILABLE_INSECURE_CONN = exports.BROWSER_BLOCKED_PERMISSION_RESOLVED_RECHECK = exports.BROWSER_BLOCKED_PERMISSION_NEXT_STEP = exports.BROWSER_BLOCKED_PERMISSION_DIRECTION = exports.BROWSER_BLOCKED_PERMISSION_DIALOG = exports.BROWSER_BLOCKED_PERMISSION = exports.ALLOW_SCREENSHARE = exports.ALLOW_FULLSCREEN = void 0;
7
7
  const WATCHING_SCREEN = "You are watching the screen";
8
8
  exports.WATCHING_SCREEN = WATCHING_SCREEN;
9
9
  const NOT_WATCHING_SCREEN = "You are not watching the screen";
@@ -20,6 +20,8 @@ const DENY_FULLSCREEN = "Deny";
20
20
  exports.DENY_FULLSCREEN = DENY_FULLSCREEN;
21
21
  const ALLOW_FULLSCREEN = "Switch to Fullscreen";
22
22
  exports.ALLOW_FULLSCREEN = ALLOW_FULLSCREEN;
23
+ const ALLOW_SCREENSHARE = "Share Screen";
24
+ exports.ALLOW_SCREENSHARE = ALLOW_SCREENSHARE;
23
25
  const NO_CAMERA_AVAILABLE = "No Camera available for use.";
24
26
  exports.NO_CAMERA_AVAILABLE = NO_CAMERA_AVAILABLE;
25
27
  const NO_AUDIO_DEVICE_AVAILABLE = "No audio device available for use";
@@ -48,11 +50,11 @@ const PERMISSION_GENERIC = "This screen requires following permissions for conti
48
50
  exports.PERMISSION_GENERIC = PERMISSION_GENERIC;
49
51
  const PERMISSION_FULLSCREEN = "Please allow us to switch your screen to fullscreen mode.";
50
52
  exports.PERMISSION_FULLSCREEN = PERMISSION_FULLSCREEN;
51
- const PERMISSION_SCREENSHARE = "Please choose to share the entire screen out of all the screen share options.";
52
- exports.PERMISSION_SCREENSHARE = PERMISSION_SCREENSHARE;
53
53
  const PERMISSION_AUDIO_VIDEO = "Your browser or system settings have disallowed Microphone and Camera permissions. Please permit this website to access microphone and camera. Refresh after you've given the permission to access the screen";
54
54
  exports.PERMISSION_AUDIO_VIDEO = PERMISSION_AUDIO_VIDEO;
55
55
  const PERMISSION_VIDEO = "Your browser or system settings have disallowed Camera permissions. Please permit this website to access the camera. Refresh after you've given the permission to access the screen";
56
56
  exports.PERMISSION_VIDEO = PERMISSION_VIDEO;
57
57
  const PERMISSION_AUDIO = "Your browser or system settings have disallowed Microphone permissions. Please permit this website to access the microphone. Refresh after you've given the permission to access the screen";
58
- exports.PERMISSION_AUDIO = PERMISSION_AUDIO;
58
+ exports.PERMISSION_AUDIO = PERMISSION_AUDIO;
59
+ const PERMISSION_SCREENSHARE = "Please share your entire screen";
60
+ exports.PERMISSION_SCREENSHARE = PERMISSION_SCREENSHARE;
@@ -15,17 +15,9 @@ Object.defineProperty(exports, "usePageVisibility", {
15
15
  return _usePageVisibility.default;
16
16
  }
17
17
  });
18
- Object.defineProperty(exports, "useTabSwitchCount", {
19
- enumerable: true,
20
- get: function get() {
21
- return _useTabSwitchCount.default;
22
- }
23
- });
24
18
 
25
19
  var _useFullScreenData = _interopRequireDefault(require("./useFullScreenData"));
26
20
 
27
21
  var _usePageVisibility = _interopRequireDefault(require("./usePageVisibility"));
28
22
 
29
- var _useTabSwitchCount = _interopRequireDefault(require("./useTabSwitchCount"));
30
-
31
23
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -9,25 +9,18 @@ require("core-js/modules/web.dom-collections.iterator.js");
9
9
 
10
10
  var _react = require("react");
11
11
 
12
- var _defaults = require("../constants/defaults");
13
-
14
12
  var _utils = require("../utils");
15
13
 
16
14
  const browserFullscreenElementProp = (0, _utils.getBrowserFullscreenElementProp)();
17
15
 
18
- function useFullscreenData(firstFullScreenDone) {
16
+ function useFullscreenData(firstFullScreenDone, isProctorParam) {
19
17
  const fullScreenElement = (0, _react.useRef)(document.documentElement);
20
18
  const [isFullscreen, setIsFullscreen] = (0, _react.useState)(document[browserFullscreenElementProp] != null);
21
- const [fullScreenExitCount, setFullScreenExitCount] = (0, _react.useState)(_defaults.initialValues.fullScreenExitCount);
22
19
  (0, _react.useEffect)(() => {
23
- if (!isFullscreen && firstFullScreenDone.current) {
24
- setFullScreenExitCount(fullScreenExitCount => fullScreenExitCount + 1);
25
- }
26
-
27
- if (isFullscreen && !firstFullScreenDone.current) {
20
+ if (isFullscreen && !firstFullScreenDone.current || !isProctorParam) {
28
21
  firstFullScreenDone.current = true;
29
22
  }
30
- }, [isFullscreen, firstFullScreenDone]);
23
+ }, [isFullscreen, firstFullScreenDone, isProctorParam]);
31
24
 
32
25
  const setFullscreen = () => {
33
26
  if (!fullScreenElement || !fullScreenElement.current) {
@@ -42,13 +35,14 @@ function useFullscreenData(firstFullScreenDone) {
42
35
  };
43
36
 
44
37
  (0, _react.useEffect)(() => {
45
- document.onfullscreenchange = () => setIsFullscreen(document[browserFullscreenElementProp] != null);
38
+ if (isProctorParam) {
39
+ document.onfullscreenchange = () => setIsFullscreen(document[browserFullscreenElementProp] != null);
40
+ }
46
41
 
47
42
  return () => document.onfullscreenchange = undefined;
48
- }, []);
43
+ }, [isProctorParam]);
49
44
  return {
50
45
  isFullscreen,
51
- setFullscreen,
52
- fullScreenExitCount
46
+ setFullscreen
53
47
  };
54
48
  }
@@ -13,7 +13,7 @@ var _utils = require("../utils");
13
13
 
14
14
  const visibilityChangeEvent = (0, _utils.getVisibilityChangeEventName)();
15
15
 
16
- function usePageVisibility() {
16
+ function usePageVisibility(isProctorParam) {
17
17
  const [isVisible, setIsVisible] = (0, _react.useState)((0, _utils.getIsDocumentVisible)());
18
18
 
19
19
  const updateVisibility = () => {
@@ -27,5 +27,5 @@ function usePageVisibility() {
27
27
  document.removeEventListener(visibilityChangeEvent, updateVisibility);
28
28
  };
29
29
  }, []);
30
- return isVisible;
30
+ return !isVisible && isProctorParam;
31
31
  }
@@ -11,7 +11,7 @@ require("core-js/modules/web.dom-collections.iterator.js");
11
11
 
12
12
  var _react = require("react");
13
13
 
14
- var bodyPix = _interopRequireWildcard(require("@tensorflow-models/body-pix"));
14
+ var cocoSsd = _interopRequireWildcard(require("@tensorflow-models/coco-ssd"));
15
15
 
16
16
  var tf = _interopRequireWildcard(require("@tensorflow/tfjs"));
17
17
 
@@ -23,56 +23,48 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
23
23
 
24
24
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25
25
 
26
- /* https://stackoverflow.com/questions/63441878/bodypix-error-no-backend-found-in-registry */
27
- const getUsers = async (network, video) => {
26
+ const getUserCount = async (model, image) => {
28
27
  try {
29
- return await network.segmentMultiPerson(video, _defaults.bodyPixConfigs);
28
+ let predictions = await model.detect(image);
29
+ let numOfUsers = 0;
30
+ predictions.forEach(prediction => {
31
+ if (prediction.class === "person") {
32
+ numOfUsers += 1;
33
+ }
34
+ });
35
+ return numOfUsers;
30
36
  } catch (err) {
31
37
  console.log("Error Trace:", err);
32
38
  }
33
39
  };
34
40
 
35
- const getIsWatching = async (network, video) => {
36
- try {
37
- const partSegmentation = await network.segmentPersonParts(video, _defaults.bodyPixConfigs);
38
- const currentPercentage = (0, _utils.getGlancePercentage)(partSegmentation);
39
- return currentPercentage >= _defaults.glancePercentageToPass;
40
- } catch (err) {
41
- console.log("Error Trace:", err);
42
- }
43
- };
44
-
45
- function useWebcamData(webcamReference, canvasReference) {
41
+ function useWebcamData(webcamReference, canvasReference, proctorParams) {
46
42
  const [userCount, setUserCount] = (0, _react.useState)(_defaults.initialValues.userCount);
47
- const [isWatching, setIsWatching] = (0, _react.useState)(_defaults.initialValues.isWatching);
43
+ const isWatching = (0, _react.useState)(_defaults.initialValues.isWatching);
48
44
  const [lookedAwayCount, setLookedAwayCount] = (0, _react.useState)(_defaults.initialValues.lookedAwayCount);
49
45
  (0, _react.useEffect)(() => {
50
- if ((0, _utils.isGPUAvailable)()) {
51
- const loadBodyPixModel = async () => {
46
+ if ((0, _utils.isGPUAvailable)() && proctorParams.people && proctorParams.lookedAwayCount) {
47
+ const loadCocoSSDModel = async () => {
52
48
  try {
53
- const network = await bodyPix.load();
49
+ const model = await cocoSsd.load();
54
50
  setInterval(async () => {
55
51
  if ((0, _utils.isWebcamVideoValid)(webcamReference)) {
56
- var _users$length;
57
-
58
52
  const video = webcamReference.current.video;
59
53
  const {
60
54
  videoWidth,
61
55
  videoHeight
62
56
  } = video;
63
- video.width = videoWidth;
64
- video.height = videoHeight;
57
+ const b64Snapshot = webcamReference.current.getScreenshot();
58
+ const webcamSnapShot = new Image(videoWidth, videoHeight);
59
+ webcamSnapShot.src = b64Snapshot;
60
+
61
+ webcamSnapShot.onload = async () => {
62
+ const count = await getUserCount(model, webcamSnapShot);
63
+ setUserCount(count);
64
+ };
65
+
65
66
  canvasReference.current.width = videoWidth;
66
67
  canvasReference.current.height = videoHeight;
67
- const users = await getUsers(network, video);
68
- const count = (_users$length = users === null || users === void 0 ? void 0 : users.length) !== null && _users$length !== void 0 ? _users$length : 0;
69
- setUserCount(count);
70
-
71
- if (count) {
72
- setIsWatching(getIsWatching(network, video));
73
- } else {
74
- setIsWatching(false);
75
- }
76
68
  }
77
69
  }, _defaults.evaluateVideoIntervalInSeconds * 1000);
78
70
  } catch (err) {
@@ -81,9 +73,9 @@ function useWebcamData(webcamReference, canvasReference) {
81
73
  }
82
74
  };
83
75
 
84
- loadBodyPixModel();
76
+ loadCocoSSDModel();
85
77
  }
86
- }, [webcamReference, canvasReference]);
78
+ }, [webcamReference, canvasReference, proctorParams.people, proctorParams.lookedAwayCount]);
87
79
  (0, _react.useEffect)(() => {
88
80
  if (!isWatching) {
89
81
  setLookedAwayCount(lookedAwayCount => lookedAwayCount + 1);
@@ -3,7 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getDataOnBreach = void 0;
6
+ exports.showProctoredComponent = exports.isWebcamRequired = exports.getInitialStats = exports.getDataOnBreach = void 0;
7
+
8
+ var _defaults = require("../constants/defaults");
7
9
 
8
10
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
9
11
 
@@ -11,68 +13,106 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
11
13
 
12
14
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
13
15
 
14
- const getDataOnBreach = (statistics, currentData, proctoringIdentifier) => {
16
+ const getInitialStats = proctorParams => {
17
+ const initialStats = {};
18
+
19
+ if (proctorParams.people) {
20
+ initialStats[_defaults.STATS_PARAMS.userCountMax] = _defaults.initialValues.userCount;
21
+ }
22
+
23
+ if (proctorParams.tabSwitch) {
24
+ initialStats[_defaults.STATS_PARAMS.isTabSwitched] = _defaults.initialValues.isTabSwitched;
25
+ }
26
+
27
+ if (proctorParams.fullscreenExit) {
28
+ initialStats[_defaults.STATS_PARAMS.isFullscreen] = _defaults.initialValues.isFullscreen;
29
+ }
30
+
31
+ if (proctorParams.lookedAway) {
32
+ initialStats[_defaults.STATS_PARAMS.lookedAwayCount] = _defaults.initialValues.lookedAwayCount;
33
+ }
34
+
35
+ return initialStats;
36
+ };
37
+
38
+ exports.getInitialStats = getInitialStats;
39
+
40
+ const isWebcamRequired = proctorParams => proctorParams.people || proctorParams.lookedAway || proctorParams.webcamSnapshots;
41
+
42
+ exports.isWebcamRequired = isWebcamRequired;
43
+
44
+ const showProctoredComponent = (proctorParams, permissions) => {
45
+ return (!proctorParams.fullscreenExit || permissions.isFullscreen) && (!isWebcamRequired(proctorParams) || permissions.audioPermission && permissions.videoPermission) && (!proctorParams.screenshareSnapshots || permissions.screensharePermission);
46
+ };
47
+
48
+ exports.showProctoredComponent = showProctoredComponent;
49
+
50
+ const getDataOnBreach = (statistics, currentData, proctorParams) => {
15
51
  const {
16
52
  userCount,
17
- tabSwitchCount,
18
- fullScreenExitCount,
53
+ isTabSwitched,
54
+ isFullscreen,
19
55
  lookedAwayCount,
20
56
  isWebcamDataReliable
21
57
  } = currentData;
22
58
  const timestamp = Date.now();
23
59
  const data = statistics.current;
60
+ const isWebCamReliableParam = _defaults.STATS_PARAMS.isWebcamReliable;
24
61
 
25
- if (data.IS_WEBCAM_DATA_RELIABLE !== isWebcamDataReliable) {
62
+ if (isWebcamRequired(proctorParams) && data[isWebCamReliableParam] !== isWebcamDataReliable) {
26
63
  return {
27
- proctoringIdentifier,
28
- breachedParam: "IS_WEBCAM_DATA_RELIABLE",
64
+ breachedParam: isWebCamReliableParam,
29
65
  timestamp,
30
66
  data: _objectSpread(_objectSpread({}, data), {}, {
31
- IS_WEBCAM_DATA_RELIABLE: isWebcamDataReliable
67
+ [isWebCamReliableParam]: isWebcamDataReliable
32
68
  })
33
69
  };
34
70
  }
35
71
 
36
- if (data.USER_COUNT_MAX < userCount) {
72
+ const userCountMaxParam = _defaults.STATS_PARAMS.userCountMax;
73
+
74
+ if (proctorParams.people && data[userCountMaxParam] < userCount) {
37
75
  return {
38
- proctoringIdentifier,
39
- breachedParam: "USER_COUNT_MAX",
76
+ breachedParam: userCountMaxParam,
40
77
  timestamp,
41
78
  data: _objectSpread(_objectSpread({}, data), {}, {
42
- USER_COUNT_MAX: userCount
79
+ [userCountMaxParam]: userCount
43
80
  })
44
81
  };
45
82
  }
46
83
 
47
- if (data.TAB_SWITCH_COUNT !== tabSwitchCount) {
84
+ const isTabSwitchedParam = _defaults.STATS_PARAMS.isTabSwitched;
85
+
86
+ if (proctorParams.tabSwitch && isTabSwitched && !data[isTabSwitchedParam]) {
48
87
  return {
49
- proctoringIdentifier,
50
- breachedParam: "TAB_SWITCH_COUNT",
88
+ breachedParam: isTabSwitchedParam,
51
89
  timestamp,
52
90
  data: _objectSpread(_objectSpread({}, data), {}, {
53
- TAB_SWITCH_COUNT: tabSwitchCount
91
+ [isTabSwitchedParam]: isTabSwitched
54
92
  })
55
93
  };
56
94
  }
57
95
 
58
- if (data.FULLSCREEN_EXIT_COUNT !== fullScreenExitCount) {
96
+ const fullscreenExitParam = _defaults.STATS_PARAMS.isFullscreen;
97
+
98
+ if (proctorParams.fullscreenExit && !isFullscreen && data[fullscreenExitParam]) {
59
99
  return {
60
- proctoringIdentifier,
61
- breachedParam: "FULLSCREEN_EXIT_COUNT",
100
+ breachedParam: fullscreenExitParam,
62
101
  timestamp,
63
102
  data: _objectSpread(_objectSpread({}, data), {}, {
64
- FULLSCREEN_EXIT_COUNT: fullScreenExitCount
103
+ [fullscreenExitParam]: isFullscreen
65
104
  })
66
105
  };
67
106
  }
68
107
 
69
- if (data.LOOKED_AWAY_COUNT !== lookedAwayCount) {
108
+ const lookedAwayParam = _defaults.STATS_PARAMS.lookedAwayCount;
109
+
110
+ if (proctorParams.lookedAway && data[lookedAwayParam] !== lookedAwayCount) {
70
111
  return {
71
- proctoringIdentifier,
72
- breachedParam: "LOOKED_AWAY_COUNT",
112
+ breachedParam: lookedAwayParam,
73
113
  timestamp,
74
114
  data: _objectSpread(_objectSpread({}, data), {}, {
75
- LOOKED_AWAY_COUNT: lookedAwayCount
115
+ [lookedAwayParam]: lookedAwayCount
76
116
  })
77
117
  };
78
118
  }
@@ -3,7 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getVisibilityChangeEventName = exports.getIsDocumentVisible = exports.getBrowserFullscreenElementProp = void 0;
6
+ exports.isChrome = exports.getVisibilityChangeEventName = exports.getIsDocumentVisible = exports.getBrowserFullscreenElementProp = void 0;
7
+
8
+ require("core-js/modules/es.regexp.exec.js");
9
+
10
+ require("core-js/modules/es.string.match.js");
11
+
7
12
  const PROPERTY_TYPES = {
8
13
  HIDDEN: "hidden",
9
14
  VISIBILITY_CHANGE: "visibilitychange"
@@ -60,4 +65,8 @@ const getBrowserFullscreenElementProp = () => {
60
65
  }
61
66
  };
62
67
 
63
- exports.getBrowserFullscreenElementProp = getBrowserFullscreenElementProp;
68
+ exports.getBrowserFullscreenElementProp = getBrowserFullscreenElementProp;
69
+
70
+ const isChrome = () => !!navigator.userAgent.match(/chrome|chromium/i);
71
+
72
+ exports.isChrome = isChrome;
@@ -27,12 +27,6 @@ Object.defineProperty(exports, "getBrowserFullscreenElementProp", {
27
27
  return _browserUtils.getBrowserFullscreenElementProp;
28
28
  }
29
29
  });
30
- Object.defineProperty(exports, "getGlancePercentage", {
31
- enumerable: true,
32
- get: function get() {
33
- return _webcamMicrophoneUtils.getGlancePercentage;
34
- }
35
- });
36
30
  Object.defineProperty(exports, "getIsDocumentVisible", {
37
31
  enumerable: true,
38
32
  get: function get() {
@@ -69,12 +63,6 @@ Object.defineProperty(exports, "isWebcamVideoValid", {
69
63
  return _webcamMicrophoneUtils.isWebcamVideoValid;
70
64
  }
71
65
  });
72
- Object.defineProperty(exports, "sendDataOnBreach", {
73
- enumerable: true,
74
- get: function get() {
75
- return _breachUtils.sendDataOnBreach;
76
- }
77
- });
78
66
  Object.defineProperty(exports, "updateStatistics", {
79
67
  enumerable: true,
80
68
  get: function get() {
@@ -86,8 +74,6 @@ var _webcamMicrophoneUtils = require("./webcamMicrophoneUtils");
86
74
 
87
75
  var _browserUtils = require("./browserUtils");
88
76
 
89
- var _breachUtils = require("./breachUtils");
90
-
91
77
  var _arrayUtils = require("./arrayUtils");
92
78
 
93
79
  var _gpuUtils = require("./gpuUtils");
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.updateVideoPermissions = exports.updateStatistics = exports.updateScreensharePermission = exports.updateAudioPermissions = exports.isWebcamVideoValid = exports.getVideoPermissionQuery = exports.getVideoPermission = exports.getGlancePercentage = exports.getAudioVideoPermission = exports.getAudioPermissionQuery = exports.getAudioPermission = exports.captureWebcamSnapshot = void 0;
6
+ exports.updateVideoPermissions = exports.updateStatistics = exports.updateAudioPermissions = exports.setupScreensharePermission = exports.isWebcamVideoValid = exports.getVideoPermissionQuery = exports.getVideoPermission = exports.getGlancePercentage = exports.getAudioVideoPermission = exports.getAudioPermissionQuery = exports.getAudioPermission = exports.captureWebcamSnapshot = exports.captureScreenshot = void 0;
7
7
 
8
8
  require("core-js/modules/es.regexp.exec.js");
9
9
 
@@ -19,24 +19,45 @@ require("core-js/modules/es.typed-array.sort.js");
19
19
 
20
20
  require("core-js/modules/es.typed-array.to-locale-string.js");
21
21
 
22
+ require("core-js/modules/es.promise.js");
23
+
22
24
  var _ = require(".");
23
25
 
26
+ var _html2canvas = _interopRequireDefault(require("html2canvas"));
27
+
28
+ var _defaults = require("../constants/defaults");
29
+
30
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
+
24
32
  const isWebcamVideoValid = webcamReference => webcamReference !== null && webcamReference !== undefined && typeof webcamReference.current !== "undefined" && webcamReference.current !== null && webcamReference.current.video.readyState === 4;
25
33
 
26
34
  exports.isWebcamVideoValid = isWebcamVideoValid;
27
35
 
28
- const updateStatistics = (statistics, currentStats) => {
36
+ const updateStatistics = (statistics, currentStats, proctorParams) => {
29
37
  const {
30
- tabSwitchCount,
31
- fullScreenExitCount,
38
+ isTabSwitched,
39
+ isFullscreen,
32
40
  lookedAwayCount,
33
41
  userCount,
34
42
  isWebcamDataReliable
35
43
  } = currentStats;
36
- statistics.current.TAB_SWITCH_COUNT = tabSwitchCount;
37
- statistics.current.FULLSCREEN_EXIT_COUNT = fullScreenExitCount;
38
- statistics.current.LOOKED_AWAY_COUNT = lookedAwayCount;
39
- statistics.current.USER_COUNT_MAX = Math.max(userCount, statistics.current.USER_COUNT_MAX);
44
+
45
+ if (proctorParams.tabSwitch) {
46
+ statistics.current[_defaults.STATS_PARAMS.isTabSwitched] = isTabSwitched;
47
+ }
48
+
49
+ if (proctorParams.fullscreenExit) {
50
+ statistics.current[_defaults.STATS_PARAMS.isFullscreen] = isFullscreen;
51
+ }
52
+
53
+ if (proctorParams.lookedAway) {
54
+ statistics.current[_defaults.STATS_PARAMS.lookedAwayCount] = lookedAwayCount;
55
+ }
56
+
57
+ if (proctorParams.people) {
58
+ statistics.current[_defaults.STATS_PARAMS.userCountMax] = Math.max(userCount, statistics.current[_defaults.STATS_PARAMS.userCountMax]);
59
+ }
60
+
40
61
  statistics.current.IS_WEBCAM_DATA_RELIABLE = isWebcamDataReliable;
41
62
  };
42
63
 
@@ -124,21 +145,33 @@ const updateVideoPermissions = setVideoPermission => {
124
145
 
125
146
  exports.updateVideoPermissions = updateVideoPermissions;
126
147
 
127
- const updateScreensharePermission = (setScreensharePermission, videoReference) => navigator.mediaDevices.getDisplayMedia({
128
- video: true,
129
- audio: true
148
+ const setupScreensharePermission = (setScreensharePermission, screenshareReference) => navigator.mediaDevices.getDisplayMedia({
149
+ video: true
130
150
  }).then(stream => {
131
- if (stream.getTracks()[0].getSettings().displaySurface === "monitor") {
132
- videoReference.current = stream;
151
+ const track = stream.getTracks()[0];
152
+
153
+ if (track.getSettings().displaySurface === "monitor") {
154
+ screenshareReference.current.srcObject = stream;
155
+
156
+ screenshareReference.current.onloadedmetadata = e => {
157
+ screenshareReference.current.play();
158
+ };
159
+
160
+ track.onended = e => {
161
+ setScreensharePermission(false);
162
+ };
163
+
133
164
  setScreensharePermission(true);
134
165
  } else {
166
+ screenshareReference.current = null;
135
167
  setScreensharePermission(false);
136
168
  }
137
- }).catch(() => {
169
+ }).catch(e => {
170
+ screenshareReference.current = null;
138
171
  setScreensharePermission(false);
139
172
  });
140
173
 
141
- exports.updateScreensharePermission = updateScreensharePermission;
174
+ exports.setupScreensharePermission = setupScreensharePermission;
142
175
 
143
176
  const getVideoPermissionQuery = () => navigator.permissions.query({
144
177
  name: "camera"
@@ -170,8 +203,19 @@ const captureWebcamSnapshot = webcamReference => {
170
203
  try {
171
204
  const b64Snapshot = webcamReference.current.getScreenshot();
172
205
  return b64DataURItoBlob(b64Snapshot);
173
- } catch (_unused) {// pass
206
+ } catch (e) {// pass
207
+ }
208
+ };
209
+
210
+ exports.captureWebcamSnapshot = captureWebcamSnapshot;
211
+
212
+ const captureScreenshot = async () => {
213
+ try {
214
+ const canvas = await (0, _html2canvas.default)(document.querySelector("#ss-ref"));
215
+ const b64Snapshot = canvas.toDataURL("image/jpeg");
216
+ return b64DataURItoBlob(b64Snapshot);
217
+ } catch (e) {// pass
174
218
  }
175
219
  };
176
220
 
177
- exports.captureWebcamSnapshot = captureWebcamSnapshot;
221
+ exports.captureScreenshot = captureScreenshot;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newtonschool/react_proctoring_library",
3
- "version": "0.0.14",
3
+ "version": "0.0.17",
4
4
  "description": "Used to proctor online tests",
5
5
  "author": "ayushkagrawal,shreyachandra",
6
6
  "main": "dist/index.js",
@@ -13,10 +13,11 @@
13
13
  ""
14
14
  ],
15
15
  "dependencies": {
16
- "@tensorflow-models/body-pix": "^2.2.0",
16
+ "@tensorflow-models/coco-ssd": "^2.2.2",
17
17
  "@tensorflow/tfjs": "^3.9.0",
18
18
  "bootstrap": "^5.1.3",
19
19
  "core-js": "^3.22.7",
20
+ "html2canvas": "^1.4.1",
20
21
  "react-bootstrap": "^2.0.4",
21
22
  "react-webcam": "^6.0.0"
22
23
  },