@newtonschool/react_proctoring_library 0.0.13 → 0.0.16

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(".");
@@ -21,44 +23,85 @@ var _permissions = require("./permissions");
21
23
 
22
24
  var _useWebcamData = _interopRequireDefault(require("../hooks/useWebcamData"));
23
25
 
26
+ var _breachUtils = require("../utils/breachUtils");
27
+
28
+ var _webcamMicrophoneUtils = require("../utils/webcamMicrophoneUtils");
29
+
24
30
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
31
 
26
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); }
27
33
 
28
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; }
29
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
+
30
42
  const isWebcamProcessingReliable = (0, _utils.isGPUAvailable)();
31
43
 
32
44
  const ProctorApp = _ref => {
33
45
  let {
34
46
  proctoringIdentifier,
35
47
  children,
36
- proctoringParams = {
37
- userCount: true,
38
- tabSwitch: true,
39
- fullscreenExit: true,
40
- lookedAway: true,
41
- isWebcamDataReliable: true
42
- },
43
- sendData = () => {},
44
- shouldSendDataOnBreach = false
48
+ config,
49
+ getProctorParamValues = () => {},
50
+ getWebcamSnapshot = () => {},
51
+ getScreengrab = () => {}
45
52
  } = _ref;
46
53
  const webcamReference = (0, _react.useRef)(null);
47
54
  const canvasReference = (0, _react.useRef)(null);
55
+ const screenshareReference = (0, _react.useRef)(null);
48
56
  const statistics = (0, _react.useRef)(_defaults.INITIAL_STATISTICS);
49
- const [audioPermission, setAudioPermission] = (0, _react.useState)(false);
50
- const [videoPermission, setVideoPermission] = (0, _react.useState)(false);
57
+
58
+ const proctorParams = _objectSpread(_objectSpread({}, {
59
+ people: true,
60
+ tabSwitch: true,
61
+ fullscreenExit: true,
62
+ lookedAway: true
63
+ }), config.proctorParams);
64
+
65
+ const {
66
+ recurring = false,
67
+ recurringFetchInterval = 0
68
+ } = config;
69
+ const [audioPermission, setAudioPermission] = (0, _react.useState)();
70
+ const [videoPermission, setVideoPermission] = (0, _react.useState)();
71
+ const [screensharePermission, setScreensharePermission] = (0, _react.useState)();
51
72
  const firstFullScreenDone = (0, _react.useRef)(false);
73
+ const recurringFetchIntervalRef = (0, _react.useRef)(null);
74
+ const sendScreengrab = (0, _react.useCallback)(async function () {
75
+ let isBreach = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
76
+ let breachData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
77
+ const screenshot = await (0, _webcamMicrophoneUtils.captureScreenshot)();
78
+ getScreengrab(proctoringIdentifier, screenshot, isBreach, breachData.breachedParam);
79
+ }, [getScreengrab, proctoringIdentifier]);
80
+ (0, _react.useEffect)(() => {
81
+ if (recurring) {
82
+ recurringFetchIntervalRef.current = setInterval(() => {
83
+ getProctorParamValues(proctoringIdentifier, statistics.current, false);
84
+ const webcamSnapshot = (0, _utils.captureWebcamSnapshot)(webcamReference);
85
+
86
+ if (webcamReference) {
87
+ getWebcamSnapshot(proctoringIdentifier, webcamSnapshot, false);
88
+ }
89
+
90
+ sendScreengrab();
91
+ }, recurringFetchInterval);
92
+ }
93
+
94
+ return () => {
95
+ clearInterval(recurringFetchIntervalRef.current);
96
+ };
97
+ }, [recurring, recurringFetchInterval, proctoringIdentifier, getWebcamSnapshot, getProctorParamValues, sendScreengrab]);
52
98
  const {
53
99
  isFullscreen,
54
100
  setFullscreen,
55
101
  fullScreenExitCount
56
102
  } = (0, _hooks.useFullscreenData)(firstFullScreenDone);
57
- const [userCount, lookedAwayCount, isWebcamDataReliable] = (0, _useWebcamData.default)(webcamReference, canvasReference);
103
+ const [userCount, lookedAwayCount] = (0, _useWebcamData.default)(webcamReference, canvasReference);
58
104
  const tabSwitchCount = (0, _hooks.useTabSwitchCount)(firstFullScreenDone);
59
- (0, _react.useEffect)(() => {
60
- (0, _utils.removeStatsFromLocalStorage)(proctoringIdentifier);
61
- }, [proctoringIdentifier]);
62
105
  (0, _react.useEffect)(() => {
63
106
  const currentStats = {
64
107
  userCount,
@@ -67,31 +110,47 @@ const ProctorApp = _ref => {
67
110
  lookedAwayCount,
68
111
  isWebcamDataReliable: isWebcamProcessingReliable
69
112
  };
113
+ const breachData = (0, _breachUtils.getDataOnBreach)(statistics, currentStats);
114
+
115
+ if (breachData) {
116
+ getProctorParamValues(breachData.proctoringIdentifier, breachData.data, true, breachData.breachedParam);
117
+
118
+ if (breachData.breachedParam === "LOOKED_AWAY_COUNT" || breachData.breachedParam === "USER_COUNT_MAX") {
119
+ const webcamSnapshot = (0, _utils.captureWebcamSnapshot)(webcamReference);
70
120
 
71
- if (shouldSendDataOnBreach) {
72
- (0, _utils.sendDataOnBreach)(statistics, currentStats, proctoringIdentifier, sendData, webcamReference);
121
+ if (webcamSnapshot) {
122
+ getWebcamSnapshot(proctoringIdentifier, webcamSnapshot, true, breachData.breachedParam);
123
+ }
124
+ } else {
125
+ sendScreengrab(true, breachData);
126
+ }
73
127
  }
74
128
 
75
129
  (0, _utils.updateStatistics)(statistics, currentStats);
76
- (0, _utils.addOrUpdateStatsToLocalStorage)(proctoringIdentifier, statistics.current);
77
- }, [userCount, tabSwitchCount, fullScreenExitCount, lookedAwayCount, isWebcamDataReliable, proctoringIdentifier, sendData, shouldSendDataOnBreach]);
130
+ }, [userCount, tabSwitchCount, fullScreenExitCount, lookedAwayCount, getProctorParamValues, getWebcamSnapshot, sendScreengrab, proctoringIdentifier]);
131
+ const updateScreensharePermission = (0, _react.useCallback)(() => {
132
+ (0, _webcamMicrophoneUtils.setupScreensharePermission)(setScreensharePermission, screenshareReference);
133
+ }, []);
78
134
 
79
135
  if (proctoringIdentifier === undefined) {
80
136
  // todo
81
137
  return;
82
138
  }
83
139
 
84
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_permissions.Permission, {
140
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isFullscreen && audioPermission && videoPermission && screensharePermission && children, /*#__PURE__*/_react.default.createElement(_permissions.Permission, {
85
141
  isFullscreen: isFullscreen,
86
142
  audioPermisison: audioPermission,
87
143
  videoPermission: videoPermission,
88
- setFullscreen: setFullscreen
144
+ setFullscreen: setFullscreen,
145
+ screensharePermission: screensharePermission,
146
+ updateScreensharePermission: updateScreensharePermission
89
147
  }), /*#__PURE__*/_react.default.createElement(_.ActivityTracker, {
90
148
  setAudioPermission: setAudioPermission,
91
149
  setVideoPermission: setVideoPermission,
92
150
  webcamReference: webcamReference,
93
- canvasReference: canvasReference
94
- }), isFullscreen && audioPermission && videoPermission && children);
151
+ canvasReference: canvasReference,
152
+ screenshareReference: screenshareReference
153
+ }));
95
154
  };
96
155
 
97
156
  exports.ProctorApp = ProctorApp;
@@ -34,7 +34,8 @@ const ActivityTracker = _ref => {
34
34
  webcamReference,
35
35
  canvasReference,
36
36
  setAudioPermission,
37
- setVideoPermission
37
+ setVideoPermission,
38
+ screenshareReference
38
39
  } = _ref;
39
40
  (0, _react.useEffect)(() => {
40
41
  if (isChrome) {
@@ -137,7 +138,12 @@ const ActivityTracker = _ref => {
137
138
  className: "captured-video-canvas"
138
139
  }), /*#__PURE__*/_react.default.createElement("canvas", {
139
140
  ref: canvasReference,
140
- className: "captured-video-canvas"
141
+ className: "captured-video-canvas",
142
+ id: "wc-ref"
143
+ }), /*#__PURE__*/_react.default.createElement("video", {
144
+ ref: screenshareReference,
145
+ className: "captured-video-canvas",
146
+ id: "ss-ref"
141
147
  }));
142
148
  };
143
149
 
@@ -30,9 +30,11 @@ const Permission = _ref => {
30
30
  isFullscreen,
31
31
  audioPermisison,
32
32
  videoPermission,
33
- setFullscreen
33
+ setFullscreen,
34
+ screensharePermission,
35
+ updateScreensharePermission
34
36
  } = _ref;
35
- const showPermissionModal = !isFullscreen || !audioPermisison || !videoPermission;
37
+ const showPermissionModal = isFullscreen === false || audioPermisison === false || videoPermission === false || !screensharePermission;
36
38
  return /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal, {
37
39
  show: showPermissionModal,
38
40
  size: "lg",
@@ -41,7 +43,7 @@ const Permission = _ref => {
41
43
  centered: true
42
44
  }, /*#__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, {
43
45
  className: "font-medium"
44
- }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
46
+ }, /*#__PURE__*/_react.default.createElement("div", {
45
47
  style: {
46
48
  borderRadius: "20px"
47
49
  }
@@ -58,8 +60,13 @@ const Permission = _ref => {
58
60
  }), text.VIDEO_UNSUPPORTED_IN_BROWSER)), /*#__PURE__*/_react.default.createElement(_permissionBody.PermissionBody, {
59
61
  showFullscreenText: !isFullscreen,
60
62
  showAudioPermissionText: !audioPermisison,
61
- showVideoPermissionText: !videoPermission
62
- }))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Footer, null, !isFullscreen && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
63
+ showVideoPermissionText: !videoPermission,
64
+ showScreensharePermission: !screensharePermission
65
+ })), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Footer, null, !screensharePermission && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
66
+ onClick: () => {
67
+ updateScreensharePermission();
68
+ }
69
+ }, text.ALLOW_SCREENSHARE), screensharePermission && !isFullscreen && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
63
70
  variant: "primary",
64
71
  onClick: () => {
65
72
  setFullscreen();
@@ -25,11 +25,16 @@ const PermissionBody = _ref => {
25
25
  let {
26
26
  showFullscreenText,
27
27
  showAudioPermissionText,
28
- showVideoPermissionText
28
+ showVideoPermissionText,
29
+ showScreensharePermission
29
30
  } = _ref;
30
31
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
31
32
  className: "mb-2"
32
- }, text.PERMISSION_GENERIC), showAudioPermissionText && showVideoPermissionText ? /*#__PURE__*/_react.default.createElement("div", {
33
+ }, text.PERMISSION_GENERIC), showScreensharePermission && /*#__PURE__*/_react.default.createElement("div", {
34
+ className: "mb-2"
35
+ }, /*#__PURE__*/_react.default.createElement("span", {
36
+ className: "pr-2 font-weight-bold"
37
+ }, "Screenshare:"), text.PERMISSION_SCREENSHARE), showAudioPermissionText && showVideoPermissionText ? /*#__PURE__*/_react.default.createElement("div", {
33
38
  className: "mb-2"
34
39
  }, /*#__PURE__*/_react.default.createElement("span", {
35
40
  className: "pr-2 font-weight-bold"
@@ -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_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";
@@ -53,4 +55,6 @@ exports.PERMISSION_AUDIO_VIDEO = PERMISSION_AUDIO_VIDEO;
53
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";
54
56
  exports.PERMISSION_VIDEO = PERMISSION_VIDEO;
55
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";
56
- 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;
package/dist/index.js CHANGED
@@ -9,13 +9,5 @@ Object.defineProperty(exports, "ProctorApp", {
9
9
  return _components.ProctorApp;
10
10
  }
11
11
  });
12
- Object.defineProperty(exports, "getStatistics", {
13
- enumerable: true,
14
- get: function get() {
15
- return _utils.getStatistics;
16
- }
17
- });
18
-
19
- var _components = require("./components");
20
12
 
21
- var _utils = require("./utils");
13
+ var _components = require("./components");
@@ -3,9 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.sendDataOnBreach = void 0;
7
-
8
- var _ = require(".");
6
+ exports.getDataOnBreach = void 0;
9
7
 
10
8
  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; }
11
9
 
@@ -13,7 +11,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
13
11
 
14
12
  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; }
15
13
 
16
- const sendDataOnBreach = (statistics, currentData, proctoringIdentifier, sendData, webcamReference) => {
14
+ const getDataOnBreach = (statistics, currentData) => {
17
15
  const {
18
16
  userCount,
19
17
  tabSwitchCount,
@@ -25,63 +23,54 @@ const sendDataOnBreach = (statistics, currentData, proctoringIdentifier, sendDat
25
23
  const data = statistics.current;
26
24
 
27
25
  if (data.IS_WEBCAM_DATA_RELIABLE !== isWebcamDataReliable) {
28
- sendData({
29
- proctoringIdentifier,
30
- breach: "IS_WEBCAM_DATA_RELIABLE",
26
+ return {
27
+ breachedParam: "IS_WEBCAM_DATA_RELIABLE",
31
28
  timestamp,
32
29
  data: _objectSpread(_objectSpread({}, data), {}, {
33
30
  IS_WEBCAM_DATA_RELIABLE: isWebcamDataReliable
34
31
  })
35
- });
32
+ };
36
33
  }
37
34
 
38
35
  if (data.USER_COUNT_MAX < userCount) {
39
- const webcamSnapshot = (0, _.captureWebcamSnapshot)(webcamReference);
40
- sendData({
41
- proctoringIdentifier,
42
- breach: "USER_COUNT_MAX",
36
+ return {
37
+ breachedParam: "USER_COUNT_MAX",
43
38
  timestamp,
44
39
  data: _objectSpread(_objectSpread({}, data), {}, {
45
40
  USER_COUNT_MAX: userCount
46
- }),
47
- webcamSnapshot
48
- });
41
+ })
42
+ };
49
43
  }
50
44
 
51
45
  if (data.TAB_SWITCH_COUNT !== tabSwitchCount) {
52
- sendData({
53
- proctoringIdentifier,
54
- breach: "TAB_SWITCH_COUNT",
46
+ return {
47
+ breachedParam: "TAB_SWITCH_COUNT",
55
48
  timestamp,
56
49
  data: _objectSpread(_objectSpread({}, data), {}, {
57
50
  TAB_SWITCH_COUNT: tabSwitchCount
58
51
  })
59
- });
52
+ };
60
53
  }
61
54
 
62
55
  if (data.FULLSCREEN_EXIT_COUNT !== fullScreenExitCount) {
63
- sendData({
64
- proctoringIdentifier,
65
- breach: "FULLSCREEN_EXIT_COUNT",
56
+ return {
57
+ breachedParam: "FULLSCREEN_EXIT_COUNT",
66
58
  timestamp,
67
59
  data: _objectSpread(_objectSpread({}, data), {}, {
68
60
  FULLSCREEN_EXIT_COUNT: fullScreenExitCount
69
61
  })
70
- });
62
+ };
71
63
  }
72
64
 
73
65
  if (data.LOOKED_AWAY_COUNT !== lookedAwayCount) {
74
- const webcamSnapshot = (0, _.captureWebcamSnapshot)(webcamReference);
75
- sendData({
76
- proctoringIdentifier,
77
- breach: "LOOKED_AWAY_COUNT",
66
+ return {
67
+ breachedParam: "LOOKED_AWAY_COUNT",
78
68
  timestamp,
79
69
  data: _objectSpread(_objectSpread({}, data), {}, {
80
70
  LOOKED_AWAY_COUNT: lookedAwayCount
81
- }),
82
- webcamSnapshot
83
- });
71
+ })
72
+ };
84
73
  }
85
74
  };
86
75
 
87
- exports.sendDataOnBreach = sendDataOnBreach;
76
+ exports.getDataOnBreach = getDataOnBreach;
@@ -3,10 +3,30 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.updateVideoPermissions = exports.updateStatistics = 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
+
8
+ require("core-js/modules/es.regexp.exec.js");
9
+
10
+ require("core-js/modules/es.string.split.js");
11
+
12
+ require("core-js/modules/es.array-buffer.slice.js");
13
+
14
+ require("core-js/modules/es.typed-array.uint8-array.js");
15
+
16
+ require("core-js/modules/es.typed-array.set.js");
17
+
18
+ require("core-js/modules/es.typed-array.sort.js");
19
+
20
+ require("core-js/modules/es.typed-array.to-locale-string.js");
21
+
22
+ require("core-js/modules/es.promise.js");
7
23
 
8
24
  var _ = require(".");
9
25
 
26
+ var _html2canvas = _interopRequireDefault(require("html2canvas"));
27
+
28
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
+
10
30
  const isWebcamVideoValid = webcamReference => webcamReference !== null && webcamReference !== undefined && typeof webcamReference.current !== "undefined" && webcamReference.current !== null && webcamReference.current.video.readyState === 4;
11
31
 
12
32
  exports.isWebcamVideoValid = isWebcamVideoValid;
@@ -110,6 +130,34 @@ const updateVideoPermissions = setVideoPermission => {
110
130
 
111
131
  exports.updateVideoPermissions = updateVideoPermissions;
112
132
 
133
+ const setupScreensharePermission = (setScreensharePermission, screenshareReference) => navigator.mediaDevices.getDisplayMedia({
134
+ video: true
135
+ }).then(stream => {
136
+ const track = stream.getTracks()[0];
137
+
138
+ if (track.getSettings().displaySurface === "monitor") {
139
+ screenshareReference.current.srcObject = stream;
140
+
141
+ screenshareReference.current.onloadedmetadata = e => {
142
+ screenshareReference.current.play();
143
+ };
144
+
145
+ track.onended = e => {
146
+ setScreensharePermission(false);
147
+ };
148
+
149
+ setScreensharePermission(true);
150
+ } else {
151
+ screenshareReference.current = null;
152
+ setScreensharePermission(false);
153
+ }
154
+ }).catch(e => {
155
+ screenshareReference.current = null;
156
+ setScreensharePermission(false);
157
+ });
158
+
159
+ exports.setupScreensharePermission = setupScreensharePermission;
160
+
113
161
  const getVideoPermissionQuery = () => navigator.permissions.query({
114
162
  name: "camera"
115
163
  });
@@ -122,8 +170,37 @@ const getAudioPermissionQuery = () => navigator.permissions.query({
122
170
 
123
171
  exports.getAudioPermissionQuery = getAudioPermissionQuery;
124
172
 
173
+ const b64DataURItoBlob = dataURI => {
174
+ const byteString = window.atob(dataURI.split(",")[1]);
175
+ const mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0];
176
+ const u8arr = new Uint8Array(byteString.length);
177
+
178
+ for (let i = 0; i < byteString.length; i += 1) {
179
+ u8arr[i] = byteString.charCodeAt(i);
180
+ }
181
+
182
+ return new Blob([u8arr], {
183
+ type: mimeString
184
+ });
185
+ };
186
+
125
187
  const captureWebcamSnapshot = webcamReference => {
126
- return webcamReference.current.getScreenshot();
188
+ try {
189
+ const b64Snapshot = webcamReference.current.getScreenshot();
190
+ return b64DataURItoBlob(b64Snapshot);
191
+ } catch (e) {// pass
192
+ }
193
+ };
194
+
195
+ exports.captureWebcamSnapshot = captureWebcamSnapshot;
196
+
197
+ const captureScreenshot = async () => {
198
+ try {
199
+ const canvas = await (0, _html2canvas.default)(document.querySelector("#ss-ref"));
200
+ const b64Snapshot = canvas.toDataURL("image/jpeg");
201
+ return b64DataURItoBlob(b64Snapshot);
202
+ } catch (e) {// pass
203
+ }
127
204
  };
128
205
 
129
- exports.captureWebcamSnapshot = captureWebcamSnapshot;
206
+ exports.captureScreenshot = captureScreenshot;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newtonschool/react_proctoring_library",
3
- "version": "0.0.13",
3
+ "version": "0.0.16",
4
4
  "description": "Used to proctor online tests",
5
5
  "author": "ayushkagrawal,shreyachandra",
6
6
  "main": "dist/index.js",
@@ -17,6 +17,7 @@
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
  },