@newtonschool/react_proctoring_library 0.0.125 → 0.0.126-beta.1

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.
@@ -26,6 +26,7 @@ var _permission = require("../../utils/permission");
26
26
  var _openHeimdall = require("../openHeimdall");
27
27
  var _ElectronContext = require("../../contexts/ElectronContext");
28
28
  var _disableExtendedDisplay = require("../disable-extended-display");
29
+ var _secondaryDevice = require("../secondaryDevice");
29
30
  var _jsxRuntime = require("react/jsx-runtime");
30
31
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
31
32
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -46,7 +47,9 @@ const ProctorApp = _ref => {
46
47
  getWebcamSnapshot = () => {},
47
48
  getScreengrab = () => {},
48
49
  logger = () => {},
49
- onProctoredViewChange = () => {}
50
+ onProctoredViewChange = () => {},
51
+ isSecondaryDevice,
52
+ firebaseClient
50
53
  } = _ref;
51
54
  const context = (0, _react.useContext)(proctoredContext);
52
55
  const isElectronApp = (0, _react.useContext)(_ElectronContext.ElectronContext);
@@ -124,6 +127,13 @@ const ProctorApp = _ref => {
124
127
  permissions: permissions,
125
128
  proctorParams: proctorParams,
126
129
  askPermission: askPermission
130
+ }), proctorParams.secondaryDevice && /*#__PURE__*/(0, _jsxRuntime.jsx)(_secondaryDevice.SecondaryDevice, {
131
+ proctorParams: proctorParams,
132
+ permissions: permissions,
133
+ proctoredContext: proctoredContext,
134
+ isSecondaryDevice: isSecondaryDevice,
135
+ firebaseClient: firebaseClient,
136
+ allPermissionGranted: allPermissionGrantedOnce.current
127
137
  }), proctorParams.webcamSnapshots && /*#__PURE__*/(0, _jsxRuntime.jsx)(_webcamActivityTracker.default, {
128
138
  logger: logger,
129
139
  config: config,
@@ -131,7 +141,9 @@ const ProctorApp = _ref => {
131
141
  proctoredContext: proctoredContext,
132
142
  getWebcamSnapshot: getWebcamSnapshot,
133
143
  proctoringIdentifier: proctoringIdentifier,
134
- setAskPermissionAction: setAskPermissionAction
144
+ setAskPermissionAction: setAskPermissionAction,
145
+ firebaseClient: firebaseClient,
146
+ isSecondaryDevice: isSecondaryDevice
135
147
  }), proctorParams.screenshareSnapshots && /*#__PURE__*/(0, _jsxRuntime.jsx)(_screenshareActivityTracker.default, {
136
148
  config: config,
137
149
  getScreengrab: getScreengrab,
@@ -52,6 +52,7 @@ const ProctoredContextApp = _ref => {
52
52
  openHeimdall: null
53
53
  });
54
54
  const [screenshareStream, setScreenshareStream] = (0, _react.useState)(null);
55
+ const [secondaryDevicePermission, setSecondaryDevicePermission] = (0, _react.useState)(null);
55
56
  const downloadHeimdallUrl = (0, _react.useRef)(null);
56
57
  const allPermissionGrantedOnce = (0, _react.useRef)(false);
57
58
  const webcamReference = (0, _react.useRef)(null);
@@ -67,8 +68,9 @@ const ProctoredContextApp = _ref => {
67
68
  fullscreen: isFullscreen,
68
69
  screenshare: screensharePermission,
69
70
  openHeimdall: openHeimdallAppPermission,
70
- singleScreen: !extendedDisplayConnected
71
- }), [videoPermission, audioPermission, isFullscreen, screensharePermission, openHeimdallAppPermission, extendedDisplayConnected]);
71
+ singleScreen: !extendedDisplayConnected,
72
+ secondaryDevice: secondaryDevicePermission
73
+ }), [videoPermission, audioPermission, isFullscreen, screensharePermission, openHeimdallAppPermission, extendedDisplayConnected, secondaryDevicePermission]);
72
74
  const proctorParams = (0, _react.useMemo)(() => _objectSpread(_objectSpread({}, _defaults.defaultConfig), config.proctorParams), [config.proctorParams]);
73
75
  const Context = contextProvider;
74
76
  const forceUpdate = () => {
@@ -87,7 +89,8 @@ const ProctoredContextApp = _ref => {
87
89
  audio: setAudioPermission,
88
90
  video: setVideoPermission,
89
91
  screenshare: setScreensharePermission,
90
- openHeimdall: setOpenHeimdallAppPermission
92
+ openHeimdall: setOpenHeimdallAppPermission,
93
+ secondaryDevice: setSecondaryDevicePermission
91
94
  },
92
95
  streamSetter: {
93
96
  screenshare: setScreenshareStream
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SecondaryDevice = void 0;
7
+ require("core-js/modules/web.dom-collections.iterator.js");
8
+ var _react = require("react");
9
+ var _proctoringStatusUtils = require("../../utils/proctoringStatusUtils");
10
+ var _permission = require("../../utils/permission");
11
+ var _breachUtils = require("../../utils/breachUtils");
12
+ const SecondaryDevice = _ref => {
13
+ let {
14
+ proctoredContext,
15
+ isSecondaryDevice,
16
+ firebaseClient,
17
+ proctorParams,
18
+ permissions
19
+ } = _ref;
20
+ const {
21
+ permissionSetter
22
+ } = (0, _react.useContext)(proctoredContext);
23
+ const setSecondaryDevicePermission = permissionSetter.secondaryDevice;
24
+ const [primaryDeviceOnline, setPrimaryDeviceOnline] = (0, _react.useState)(false);
25
+ const [secondaryDeviceOnline, setSecondaryDeviceOnline] = (0, _react.useState)(false);
26
+ const [secondaryDeviceAllPermissionGranted, setSecondaryDeviceAllPermissionGranted] = (0, _react.useState)(false);
27
+ const allPermissionGranted = (0, _permission.hasAllPermissions)((0, _breachUtils.getRequiredPermissionsFromProctorParams)(proctorParams), permissions);
28
+ (0, _react.useEffect)(() => {
29
+ const cleanup = (0, _proctoringStatusUtils.setupDeviceStatusListeners)({
30
+ firebaseClient,
31
+ isSecondaryDevice,
32
+ onPrimaryDeviceStatusChange: connectionStatus => {
33
+ setPrimaryDeviceOnline(connectionStatus);
34
+ },
35
+ onSecondaryDeviceStatusChange: (connectionStatus, allPermissionGranted) => {
36
+ setSecondaryDeviceOnline(connectionStatus);
37
+ setSecondaryDeviceAllPermissionGranted(allPermissionGranted);
38
+ },
39
+ allPermissionGranted
40
+ });
41
+ return cleanup;
42
+ }, [firebaseClient, isSecondaryDevice, allPermissionGranted]);
43
+ (0, _react.useEffect)(() => {
44
+ if (isSecondaryDevice) {
45
+ setSecondaryDevicePermission(primaryDeviceOnline && secondaryDeviceOnline);
46
+ } else {
47
+ setSecondaryDevicePermission(primaryDeviceOnline && secondaryDeviceOnline && secondaryDeviceAllPermissionGranted);
48
+ }
49
+ }, [isSecondaryDevice, primaryDeviceOnline, secondaryDeviceOnline, secondaryDeviceAllPermissionGranted, setSecondaryDevicePermission]);
50
+ return null;
51
+ };
52
+ exports.SecondaryDevice = SecondaryDevice;
@@ -21,7 +21,9 @@ const WebCam = _ref => {
21
21
  logger,
22
22
  config,
23
23
  getWebcamSnapshot,
24
- proctoringIdentifier
24
+ proctoringIdentifier,
25
+ firebaseClient,
26
+ isSecondaryDevice
25
27
  } = _ref;
26
28
  const isElectronApp = (0, _react.useContext)(_ElectronContext.ElectronContext);
27
29
  if (isElectronApp) {
@@ -39,7 +41,9 @@ const WebCam = _ref => {
39
41
  logger: logger,
40
42
  config: config,
41
43
  getWebcamSnapshot: getWebcamSnapshot,
42
- proctoringIdentifier: proctoringIdentifier
44
+ proctoringIdentifier: proctoringIdentifier,
45
+ firebaseClient: firebaseClient,
46
+ isSecondaryDevice: isSecondaryDevice
43
47
  });
44
48
  };
45
49
  var _default = exports.default = WebCam;
@@ -19,6 +19,7 @@ var _browserUtils = require("../../utils/browserUtils");
19
19
  var _webcamMicrophoneUtils = require("../../utils/webcamMicrophoneUtils");
20
20
  var _dom = require("../../constants/dom");
21
21
  var _useBreachData = require("../../hooks/useBreachData");
22
+ var _proctoringStatusUtils = require("../../utils/proctoringStatusUtils");
22
23
  var _jsxRuntime = require("react/jsx-runtime");
23
24
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
24
25
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -36,7 +37,9 @@ const WebWebCam = _ref => {
36
37
  proctoredContext,
37
38
  getWebcamSnapshot,
38
39
  proctoringIdentifier,
39
- config
40
+ config,
41
+ firebaseClient,
42
+ isSecondaryDevice
40
43
  } = _ref;
41
44
  const {
42
45
  permissionSetter,
@@ -106,6 +109,13 @@ const WebWebCam = _ref => {
106
109
  ref: webcamReference,
107
110
  onUserMedia: () => {
108
111
  setVideoPermission(true);
112
+ if (firebaseClient) {
113
+ if (isSecondaryDevice) {
114
+ (0, _proctoringStatusUtils.setSecondaryDeviceConnected)(firebaseClient);
115
+ } else {
116
+ (0, _proctoringStatusUtils.setPrimaryDeviceConnected)(firebaseClient);
117
+ }
118
+ }
109
119
  },
110
120
  onUserMediaError: err => {
111
121
  logger("Retry Count = ".concat(retryCount, " | Webcam error, onUserMediaError | ").concat(err.toString()));
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.proctorParamsToPermission = exports.initialValues = exports.gpuTypes = exports.evaluateVideoIntervalInSeconds = exports.defaultConfig = exports.URL_VIDEO_PERMISSION_HIGHLIGHT = exports.STATS_PARAMS = exports.INITIAL_STATISTICS = void 0;
6
+ exports.proctorParamsToPermission = exports.initialValues = exports.gpuTypes = exports.evaluateVideoIntervalInSeconds = exports.defaultConfig = exports.URL_VIDEO_PERMISSION_HIGHLIGHT = exports.STATS_PARAMS = exports.PROCTORING_STATUS_PATH = exports.INITIAL_STATISTICS = void 0;
7
7
  const defaultConfig = exports.defaultConfig = {
8
8
  tabSwitch: true,
9
9
  fullscreenExit: true,
@@ -47,8 +47,10 @@ const proctorParamsToPermission = exports.proctorParamsToPermission = {
47
47
  audio: 'audio',
48
48
  openHeimdall: 'openHeimdall',
49
49
  downloadHeimdall: 'downloadHeimdall',
50
- disableExtendedDisplay: 'singleScreen'
50
+ disableExtendedDisplay: 'singleScreen',
51
+ secondaryDevice: 'secondaryDevice'
51
52
  };
52
53
  const evaluateVideoIntervalInSeconds = exports.evaluateVideoIntervalInSeconds = 5;
53
54
  const gpuTypes = exports.gpuTypes = ['intel', 'apple', 'amd', 'radeon', 'nvidia', 'geforce'];
54
- const URL_VIDEO_PERMISSION_HIGHLIGHT = exports.URL_VIDEO_PERMISSION_HIGHLIGHT = 'https://d3dyfaf3iutrxo.cloudfront.net/general/upload/2bbf06308d7549de81502005bfa1365f.png';
55
+ const URL_VIDEO_PERMISSION_HIGHLIGHT = exports.URL_VIDEO_PERMISSION_HIGHLIGHT = 'https://d3dyfaf3iutrxo.cloudfront.net/general/upload/2bbf06308d7549de81502005bfa1365f.png';
56
+ const PROCTORING_STATUS_PATH = exports.PROCTORING_STATUS_PATH = 'proctoringStatus';
@@ -75,6 +75,18 @@ Object.defineProperty(exports, "isWebcamVideoValid", {
75
75
  return _webcamMicrophoneUtils.isWebcamVideoValid;
76
76
  }
77
77
  });
78
+ Object.defineProperty(exports, "setPrimaryDeviceConnected", {
79
+ enumerable: true,
80
+ get: function get() {
81
+ return _proctoringStatusUtils.setPrimaryDeviceConnected;
82
+ }
83
+ });
84
+ Object.defineProperty(exports, "setupDeviceStatusListeners", {
85
+ enumerable: true,
86
+ get: function get() {
87
+ return _proctoringStatusUtils.setupDeviceStatusListeners;
88
+ }
89
+ });
78
90
  Object.defineProperty(exports, "updateStatistics", {
79
91
  enumerable: true,
80
92
  get: function get() {
@@ -84,4 +96,5 @@ Object.defineProperty(exports, "updateStatistics", {
84
96
  var _webcamMicrophoneUtils = require("./webcamMicrophoneUtils");
85
97
  var _browserUtils = require("./browserUtils");
86
98
  var _arrayUtils = require("./arrayUtils");
87
- var _gpuUtils = require("./gpuUtils");
99
+ var _gpuUtils = require("./gpuUtils");
100
+ var _proctoringStatusUtils = require("./proctoringStatusUtils");
@@ -8,13 +8,17 @@ require("core-js/modules/esnext.iterator.constructor.js");
8
8
  require("core-js/modules/esnext.iterator.for-each.js");
9
9
  const hasAllPermissions = (requiredPermissions, permissions) => {
10
10
  let hasPermission = true;
11
+ const status = {};
11
12
  requiredPermissions.forEach(element => {
13
+ const granted = permissions ? Boolean(permissions[element]) : false;
14
+ status[element] = granted;
12
15
  if (!permissions) {
13
16
  hasPermission = false;
14
17
  } else if (!permissions[element]) {
15
18
  hasPermission = hasPermission && false;
16
19
  }
17
20
  });
21
+ console.log('::[hasAllPermissions]', status, 'allGranted:', hasPermission);
18
22
  return hasPermission;
19
23
  };
20
24
  exports.hasAllPermissions = hasAllPermissions;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setupDeviceStatusListeners = exports.setSecondaryDeviceConnected = exports.setPrimaryDeviceConnected = void 0;
7
+ var _defaults = require("../constants/defaults");
8
+ /**
9
+ * Marks the primary device as connected in Firebase. Call when desktop webcam
10
+ * connects successfully. No-op if firebaseClient is missing required fields.
11
+ *
12
+ * @param {Object} firebaseClient
13
+ * @returns {Promise<void>|undefined} Resolves when set completes, or undefined if skipped
14
+ */
15
+ const setPrimaryDeviceConnected = firebaseClient => {
16
+ if (!(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.userUuid) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.myFirebaseDB) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.setValue) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.getRef)) {
17
+ return undefined;
18
+ }
19
+ const {
20
+ updateValue: update,
21
+ getRef: ref
22
+ } = firebaseClient;
23
+ const primaryDeviceRef = ref(firebaseClient.myFirebaseDB, "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(firebaseClient.userUuid, "/primaryDevice"));
24
+ const payload = {
25
+ connected: true
26
+ };
27
+ return update(primaryDeviceRef, payload).catch(error => {
28
+ console.error('::[proctoringStatusUtils] Failed to set primary device status online:', error);
29
+ });
30
+ };
31
+
32
+ /**
33
+ * Marks the secondary device as connected in Firebase. Call when secondary
34
+ * device webcam connects successfully. No-op if firebaseClient is missing required fields.
35
+ *
36
+ * @param {Object} firebaseClient - { userUuid, myFirebaseDB, setValue, getRef }
37
+ * @returns {Promise<void>|undefined} Resolves when set completes, or undefined if skipped
38
+ */
39
+ exports.setPrimaryDeviceConnected = setPrimaryDeviceConnected;
40
+ const setSecondaryDeviceConnected = firebaseClient => {
41
+ if (!(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.userUuid) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.myFirebaseDB) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.setValue) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.getRef)) {
42
+ return undefined;
43
+ }
44
+ const {
45
+ updateValue: update,
46
+ getRef: ref
47
+ } = firebaseClient;
48
+ const secondaryDeviceRef = ref(firebaseClient.myFirebaseDB, "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(firebaseClient.userUuid, "/secondaryDevice"));
49
+ const payload = {
50
+ connected: true
51
+ };
52
+ return update(secondaryDeviceRef, payload).catch(error => {
53
+ console.error('::[proctoringStatusUtils] Failed to set secondary device status online:', error);
54
+ });
55
+ };
56
+
57
+ /**
58
+ * Sets up Firebase device status: marks current device (primary/secondary) as connected,
59
+ * registers onDisconnect, and subscribes to primary and secondary status.
60
+ * Returns a cleanup function to unsubscribe listeners.
61
+ *
62
+ * @param {Object} params
63
+ * @param {Object} params.firebaseClient
64
+ * @param {boolean} params.isSecondaryDevice
65
+ * @param {(connected: boolean) => void} params.onPrimaryDeviceStatusChange
66
+ * @param {(connected: boolean) => void} params.onSecondaryDeviceStatusChange
67
+ * @param {boolean} params.allPermissionGranted
68
+ * @returns {() => void} Cleanup function to unsubscribe, or no-op if setup skipped
69
+ */
70
+ exports.setSecondaryDeviceConnected = setSecondaryDeviceConnected;
71
+ const setupDeviceStatusListeners = _ref => {
72
+ let {
73
+ firebaseClient,
74
+ isSecondaryDevice,
75
+ onPrimaryDeviceStatusChange,
76
+ onSecondaryDeviceStatusChange,
77
+ allPermissionGranted
78
+ } = _ref;
79
+ const {
80
+ userUuid,
81
+ firestoreAuthStatus,
82
+ myFirebaseDB,
83
+ setValue: set,
84
+ getRef: ref,
85
+ updateValue: update,
86
+ onDisconnect,
87
+ getValue: onValue
88
+ } = firebaseClient || {};
89
+ if (!userUuid || !firestoreAuthStatus || !ref || !set || !onDisconnect || !onValue) {
90
+ return () => {};
91
+ }
92
+ const primaryDeviceStatusRef = ref(myFirebaseDB, "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(userUuid, "/primaryDevice"));
93
+ const secondaryDeviceStatusRef = ref(myFirebaseDB, "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(userUuid, "/secondaryDevice"));
94
+ const currentDeviceStatusRef = isSecondaryDevice ? secondaryDeviceStatusRef : primaryDeviceStatusRef;
95
+ update(currentDeviceStatusRef, {
96
+ allPermissionGranted
97
+ });
98
+ onDisconnect(currentDeviceStatusRef).update({
99
+ connected: false
100
+ });
101
+ const unsubscribePrimary = onValue(primaryDeviceStatusRef, snapshot => {
102
+ const val = snapshot.val();
103
+ onPrimaryDeviceStatusChange(Boolean(val === null || val === void 0 ? void 0 : val.connected));
104
+ });
105
+ const unsubscribeSecondary = onValue(secondaryDeviceStatusRef, snapshot => {
106
+ const val = snapshot.val();
107
+ onSecondaryDeviceStatusChange(Boolean(val === null || val === void 0 ? void 0 : val.connected), val === null || val === void 0 ? void 0 : val.allPermissionGranted);
108
+ });
109
+ return () => {
110
+ unsubscribePrimary();
111
+ unsubscribeSecondary();
112
+ };
113
+ };
114
+ exports.setupDeviceStatusListeners = setupDeviceStatusListeners;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newtonschool/react_proctoring_library",
3
- "version": "0.0.125",
3
+ "version": "0.0.126-beta.1",
4
4
  "description": "Used to proctor online tests",
5
5
  "author": "ayushkagrawal,shreyachandra,weastel",
6
6
  "main": "dist/index.js",