@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.
- package/dist/components/ProctorApp.js +78 -57
- package/dist/components/activity-tracker/index.js +34 -37
- package/dist/components/permissions/index.js +15 -8
- package/dist/components/permissions/permission-body.js +4 -2
- package/dist/constants/defaults.js +26 -22
- package/dist/constants/text.js +6 -4
- package/dist/hooks/index.js +0 -8
- package/dist/hooks/useFullScreenData.js +8 -14
- package/dist/hooks/usePageVisibility.js +2 -2
- package/dist/hooks/useWebcamData.js +26 -34
- package/dist/utils/breachUtils.js +64 -24
- package/dist/utils/browserUtils.js +11 -2
- package/dist/utils/index.js +0 -14
- package/dist/utils/webcamMicrophoneUtils.js +61 -17
- package/package.json +3 -2
|
@@ -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
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
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
|
-
|
|
74
|
-
|
|
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
|
-
}, [
|
|
111
|
+
}, [recurring, recurringFetchInterval, sendProctoredParamValues, sendWebcamSnapshot, sendScreengrab]);
|
|
86
112
|
(0, _react.useEffect)(() => {
|
|
87
113
|
const currentStats = {
|
|
88
114
|
userCount,
|
|
89
|
-
|
|
90
|
-
|
|
115
|
+
isTabSwitched,
|
|
116
|
+
isFullscreen,
|
|
91
117
|
lookedAwayCount,
|
|
92
118
|
isWebcamDataReliable: isWebcamProcessingReliable
|
|
93
119
|
};
|
|
94
|
-
const breachData = (0, _breachUtils.getDataOnBreach)(statistics, currentStats,
|
|
120
|
+
const breachData = (0, _breachUtils.getDataOnBreach)(statistics, currentStats, proctorParams);
|
|
121
|
+
(0, _utils.updateStatistics)(statistics, currentStats, proctorParams);
|
|
95
122
|
|
|
96
123
|
if (breachData) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
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
|
-
|
|
130
|
-
|
|
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
|
-
|
|
39
|
-
setScreensharePermission
|
|
37
|
+
screenshareReference
|
|
40
38
|
} = _ref;
|
|
41
|
-
const videoReference = (0, _react.useRef)(null);
|
|
42
39
|
(0, _react.useEffect)(() => {
|
|
43
|
-
if (isChrome) {
|
|
44
|
-
(0,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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,
|
|
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
|
-
|
|
150
|
-
|
|
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
|
-
|
|
35
|
-
setFullscreen
|
|
38
|
+
updateScreensharePermission
|
|
36
39
|
} = _ref;
|
|
37
|
-
const showPermissionModal =
|
|
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(
|
|
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 &&
|
|
65
|
-
}))
|
|
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
|
-
}, "
|
|
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.
|
|
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
|
-
|
|
17
|
+
isTabSwitched: false,
|
|
9
18
|
userCount: 0,
|
|
10
19
|
isWebcamDataReliable: true,
|
|
11
20
|
isWatching: true,
|
|
12
21
|
canOpenFullScreen: false,
|
|
13
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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;
|
package/dist/constants/text.js
CHANGED
|
@@ -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;
|
package/dist/hooks/index.js
CHANGED
|
@@ -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 (
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
27
|
-
const getUsers = async (network, video) => {
|
|
26
|
+
const getUserCount = async (model, image) => {
|
|
28
27
|
try {
|
|
29
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
46
|
+
if ((0, _utils.isGPUAvailable)() && proctorParams.people && proctorParams.lookedAwayCount) {
|
|
47
|
+
const loadCocoSSDModel = async () => {
|
|
52
48
|
try {
|
|
53
|
-
const
|
|
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
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
18
|
-
|
|
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
|
|
62
|
+
if (isWebcamRequired(proctorParams) && data[isWebCamReliableParam] !== isWebcamDataReliable) {
|
|
26
63
|
return {
|
|
27
|
-
|
|
28
|
-
breachedParam: "IS_WEBCAM_DATA_RELIABLE",
|
|
64
|
+
breachedParam: isWebCamReliableParam,
|
|
29
65
|
timestamp,
|
|
30
66
|
data: _objectSpread(_objectSpread({}, data), {}, {
|
|
31
|
-
|
|
67
|
+
[isWebCamReliableParam]: isWebcamDataReliable
|
|
32
68
|
})
|
|
33
69
|
};
|
|
34
70
|
}
|
|
35
71
|
|
|
36
|
-
|
|
72
|
+
const userCountMaxParam = _defaults.STATS_PARAMS.userCountMax;
|
|
73
|
+
|
|
74
|
+
if (proctorParams.people && data[userCountMaxParam] < userCount) {
|
|
37
75
|
return {
|
|
38
|
-
|
|
39
|
-
breachedParam: "USER_COUNT_MAX",
|
|
76
|
+
breachedParam: userCountMaxParam,
|
|
40
77
|
timestamp,
|
|
41
78
|
data: _objectSpread(_objectSpread({}, data), {}, {
|
|
42
|
-
|
|
79
|
+
[userCountMaxParam]: userCount
|
|
43
80
|
})
|
|
44
81
|
};
|
|
45
82
|
}
|
|
46
83
|
|
|
47
|
-
|
|
84
|
+
const isTabSwitchedParam = _defaults.STATS_PARAMS.isTabSwitched;
|
|
85
|
+
|
|
86
|
+
if (proctorParams.tabSwitch && isTabSwitched && !data[isTabSwitchedParam]) {
|
|
48
87
|
return {
|
|
49
|
-
|
|
50
|
-
breachedParam: "TAB_SWITCH_COUNT",
|
|
88
|
+
breachedParam: isTabSwitchedParam,
|
|
51
89
|
timestamp,
|
|
52
90
|
data: _objectSpread(_objectSpread({}, data), {}, {
|
|
53
|
-
|
|
91
|
+
[isTabSwitchedParam]: isTabSwitched
|
|
54
92
|
})
|
|
55
93
|
};
|
|
56
94
|
}
|
|
57
95
|
|
|
58
|
-
|
|
96
|
+
const fullscreenExitParam = _defaults.STATS_PARAMS.isFullscreen;
|
|
97
|
+
|
|
98
|
+
if (proctorParams.fullscreenExit && !isFullscreen && data[fullscreenExitParam]) {
|
|
59
99
|
return {
|
|
60
|
-
|
|
61
|
-
breachedParam: "FULLSCREEN_EXIT_COUNT",
|
|
100
|
+
breachedParam: fullscreenExitParam,
|
|
62
101
|
timestamp,
|
|
63
102
|
data: _objectSpread(_objectSpread({}, data), {}, {
|
|
64
|
-
|
|
103
|
+
[fullscreenExitParam]: isFullscreen
|
|
65
104
|
})
|
|
66
105
|
};
|
|
67
106
|
}
|
|
68
107
|
|
|
69
|
-
|
|
108
|
+
const lookedAwayParam = _defaults.STATS_PARAMS.lookedAwayCount;
|
|
109
|
+
|
|
110
|
+
if (proctorParams.lookedAway && data[lookedAwayParam] !== lookedAwayCount) {
|
|
70
111
|
return {
|
|
71
|
-
|
|
72
|
-
breachedParam: "LOOKED_AWAY_COUNT",
|
|
112
|
+
breachedParam: lookedAwayParam,
|
|
73
113
|
timestamp,
|
|
74
114
|
data: _objectSpread(_objectSpread({}, data), {}, {
|
|
75
|
-
|
|
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;
|
package/dist/utils/index.js
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
31
|
-
|
|
38
|
+
isTabSwitched,
|
|
39
|
+
isFullscreen,
|
|
32
40
|
lookedAwayCount,
|
|
33
41
|
userCount,
|
|
34
42
|
isWebcamDataReliable
|
|
35
43
|
} = currentStats;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
128
|
-
video: true
|
|
129
|
-
audio: true
|
|
148
|
+
const setupScreensharePermission = (setScreensharePermission, screenshareReference) => navigator.mediaDevices.getDisplayMedia({
|
|
149
|
+
video: true
|
|
130
150
|
}).then(stream => {
|
|
131
|
-
|
|
132
|
-
|
|
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.
|
|
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 (
|
|
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.
|
|
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.
|
|
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/
|
|
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
|
},
|