@newtonschool/react_proctoring_library 0.0.133-beta.1 → 0.0.134
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.
|
@@ -10,7 +10,6 @@ var _proctoringStatusUtils = require("../../utils/proctoringStatusUtils");
|
|
|
10
10
|
var _permission = require("../../utils/permission");
|
|
11
11
|
var _breachUtils = require("../../utils/breachUtils");
|
|
12
12
|
var _usePageActivity = _interopRequireDefault(require("../../hooks/usePageActivity"));
|
|
13
|
-
var _proctoringDebugUtils = require("../../utils/proctoringDebugUtils");
|
|
14
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
14
|
const SecondaryDevice = _ref => {
|
|
16
15
|
let {
|
|
@@ -28,36 +27,10 @@ const SecondaryDevice = _ref => {
|
|
|
28
27
|
const [secondaryDeviceOnline, setSecondaryDeviceOnline] = (0, _react.useState)(true);
|
|
29
28
|
const [secondaryDeviceAllPermissionGranted, setSecondaryDeviceAllPermissionGranted] = (0, _react.useState)(true);
|
|
30
29
|
const {
|
|
31
|
-
isActive: isCurrentDeviceActive
|
|
32
|
-
isVisible,
|
|
33
|
-
isFocused,
|
|
34
|
-
isLifecycleActive
|
|
30
|
+
isActive: isCurrentDeviceActive
|
|
35
31
|
} = (0, _usePageActivity.default)();
|
|
36
32
|
const allPermissionGranted = (0, _permission.hasAllPermissions)((0, _breachUtils.getRequiredPermissionsFromProctorParams)(proctorParams), permissions);
|
|
37
33
|
const effectiveAllPermissionGranted = allPermissionGranted && isCurrentDeviceActive;
|
|
38
|
-
(0, _react.useEffect)(() => {
|
|
39
|
-
if (!isSecondaryDevice) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_session_started', {
|
|
43
|
-
deviceType: 'secondary',
|
|
44
|
-
userUuid: (firebaseClient === null || firebaseClient === void 0 ? void 0 : firebaseClient.userUuid) || null,
|
|
45
|
-
requiredPermissions: (0, _breachUtils.getRequiredPermissionsFromProctorParams)(proctorParams),
|
|
46
|
-
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown'
|
|
47
|
-
}, firebaseClient);
|
|
48
|
-
}, [firebaseClient === null || firebaseClient === void 0 ? void 0 : firebaseClient.userUuid, isSecondaryDevice, proctorParams]);
|
|
49
|
-
(0, _react.useEffect)(() => {
|
|
50
|
-
if (!isSecondaryDevice) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_page_activity_state_changed', {
|
|
54
|
-
deviceType: 'secondary',
|
|
55
|
-
isVisible,
|
|
56
|
-
isFocused,
|
|
57
|
-
isLifecycleActive,
|
|
58
|
-
isActive: isCurrentDeviceActive
|
|
59
|
-
}, firebaseClient);
|
|
60
|
-
}, [firebaseClient, isCurrentDeviceActive, isFocused, isLifecycleActive, isSecondaryDevice, isVisible]);
|
|
61
34
|
(0, _react.useEffect)(() => {
|
|
62
35
|
const cleanup = (0, _proctoringStatusUtils.setupDeviceStatusListeners)({
|
|
63
36
|
firebaseClient,
|
|
@@ -20,7 +20,6 @@ var _webcamMicrophoneUtils = require("../../utils/webcamMicrophoneUtils");
|
|
|
20
20
|
var _dom = require("../../constants/dom");
|
|
21
21
|
var _useBreachData = require("../../hooks/useBreachData");
|
|
22
22
|
var _proctoringStatusUtils = require("../../utils/proctoringStatusUtils");
|
|
23
|
-
var _proctoringDebugUtils = require("../../utils/proctoringDebugUtils");
|
|
24
23
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
25
24
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
26
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); }
|
|
@@ -47,7 +46,6 @@ const WebWebCam = _ref => {
|
|
|
47
46
|
references,
|
|
48
47
|
permissions
|
|
49
48
|
} = (0, _react.useContext)(proctoredContext);
|
|
50
|
-
const deviceType = isSecondaryDevice ? 'secondary' : 'primary';
|
|
51
49
|
const recurringFetchIntervalRef = (0, _react.useRef)(null);
|
|
52
50
|
const {
|
|
53
51
|
recurring = false,
|
|
@@ -110,13 +108,6 @@ const WebWebCam = _ref => {
|
|
|
110
108
|
screenshotFormat: "image/jpeg",
|
|
111
109
|
ref: webcamReference,
|
|
112
110
|
onUserMedia: () => {
|
|
113
|
-
if (isSecondaryDevice) {
|
|
114
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_webcam_user_media_succeeded', {
|
|
115
|
-
deviceType,
|
|
116
|
-
retryCount,
|
|
117
|
-
userUuid: (firebaseClient === null || firebaseClient === void 0 ? void 0 : firebaseClient.userUuid) || null
|
|
118
|
-
}, firebaseClient);
|
|
119
|
-
}
|
|
120
111
|
setVideoPermission(true);
|
|
121
112
|
if (firebaseClient) {
|
|
122
113
|
if (isSecondaryDevice) {
|
|
@@ -127,17 +118,6 @@ const WebWebCam = _ref => {
|
|
|
127
118
|
}
|
|
128
119
|
},
|
|
129
120
|
onUserMediaError: err => {
|
|
130
|
-
if (isSecondaryDevice) {
|
|
131
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_webcam_user_media_failed', {
|
|
132
|
-
deviceType,
|
|
133
|
-
retryCount,
|
|
134
|
-
userUuid: (firebaseClient === null || firebaseClient === void 0 ? void 0 : firebaseClient.userUuid) || null,
|
|
135
|
-
error: {
|
|
136
|
-
name: (err === null || err === void 0 ? void 0 : err.name) || null,
|
|
137
|
-
message: (err === null || err === void 0 ? void 0 : err.message) || String(err)
|
|
138
|
-
}
|
|
139
|
-
}, firebaseClient);
|
|
140
|
-
}
|
|
141
121
|
logger("Retry Count = ".concat(retryCount, " | Webcam error, onUserMediaError | ").concat(err.toString()));
|
|
142
122
|
if (retryCount === 0) {
|
|
143
123
|
setVideoPermission(false);
|
|
@@ -5,27 +5,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.updateCurrentDeviceStatus = exports.setupDeviceStatusListeners = exports.setSecondaryDeviceConnected = exports.setPrimaryDeviceConnected = void 0;
|
|
7
7
|
var _defaults = require("../constants/defaults");
|
|
8
|
-
var _proctoringDebugUtils = require("./proctoringDebugUtils");
|
|
9
8
|
const HEARTBEAT_INTERVAL_MS = 5000;
|
|
10
|
-
const OTHER_DEVICE_HEARTBEAT_TIMEOUT_MS =
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
message: (error === null || error === void 0 ? void 0 : error.message) || String(error)
|
|
14
|
-
});
|
|
15
|
-
const getObservedStatusPayload = function getObservedStatusPayload(status) {
|
|
16
|
-
let now = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Date.now();
|
|
17
|
-
return {
|
|
18
|
-
connected: Boolean(status === null || status === void 0 ? void 0 : status.connected),
|
|
19
|
-
allPermissionGranted: typeof (status === null || status === void 0 ? void 0 : status.allPermissionGranted) === 'boolean' ? status.allPermissionGranted : null,
|
|
20
|
-
lastHeartbeatAt: typeof (status === null || status === void 0 ? void 0 : status.lastHeartbeatAt) === 'number' ? status.lastHeartbeatAt : null,
|
|
21
|
-
heartbeatAgeMs: typeof (status === null || status === void 0 ? void 0 : status.lastHeartbeatAt) === 'number' ? now - status.lastHeartbeatAt : null,
|
|
22
|
-
deviceId: (status === null || status === void 0 ? void 0 : status.deviceId) || null
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
const hasRelevantObservedChange = (previousStatus, nextStatus) => {
|
|
26
|
-
const previous = getObservedStatusPayload(previousStatus);
|
|
27
|
-
const next = getObservedStatusPayload(nextStatus);
|
|
28
|
-
return previous.connected !== next.connected || previous.allPermissionGranted !== next.allPermissionGranted || previous.deviceId !== next.deviceId;
|
|
9
|
+
const OTHER_DEVICE_HEARTBEAT_TIMEOUT_MS = 20000;
|
|
10
|
+
const SERVER_TIMESTAMP = {
|
|
11
|
+
'.sv': 'timestamp'
|
|
29
12
|
};
|
|
30
13
|
|
|
31
14
|
/**
|
|
@@ -73,12 +56,6 @@ const setSecondaryDeviceConnected = firebaseClient => {
|
|
|
73
56
|
connected: true
|
|
74
57
|
};
|
|
75
58
|
return update(secondaryDeviceRef, payload).then(() => {}).catch(error => {
|
|
76
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
77
|
-
deviceType: 'secondary',
|
|
78
|
-
userUuid: firebaseClient.userUuid,
|
|
79
|
-
payload,
|
|
80
|
-
error: getErrorPayload(error)
|
|
81
|
-
}, firebaseClient);
|
|
82
59
|
console.error('::[proctoringStatusUtils] Failed to set secondary device status online:', error);
|
|
83
60
|
});
|
|
84
61
|
};
|
|
@@ -116,12 +93,6 @@ const updateCurrentDeviceStatus = _ref => {
|
|
|
116
93
|
if (!isSecondaryDevice) {
|
|
117
94
|
return;
|
|
118
95
|
}
|
|
119
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
120
|
-
deviceType: 'secondary',
|
|
121
|
-
userUuid: firebaseClient.userUuid,
|
|
122
|
-
payload,
|
|
123
|
-
error: getErrorPayload(error)
|
|
124
|
-
}, firebaseClient);
|
|
125
96
|
console.error('::[proctoringStatusUtils] Failed to update current device status:', error);
|
|
126
97
|
});
|
|
127
98
|
};
|
|
@@ -158,7 +129,6 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
158
129
|
onDisconnect,
|
|
159
130
|
getValue: onValue
|
|
160
131
|
} = firebaseClient || {};
|
|
161
|
-
const deviceType = isSecondaryDevice ? 'secondary' : 'primary';
|
|
162
132
|
if (!userUuid || !firestoreAuthStatus || !ref || !set || !onDisconnect || !onValue) {
|
|
163
133
|
return () => {};
|
|
164
134
|
}
|
|
@@ -166,58 +136,42 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
166
136
|
const secondaryDeviceStatusRef = ref(myFirebaseDB, "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(userUuid, "/secondaryDevice"));
|
|
167
137
|
const currentDeviceStatusRef = isSecondaryDevice ? secondaryDeviceStatusRef : primaryDeviceStatusRef;
|
|
168
138
|
const otherDeviceStatusRef = isSecondaryDevice ? primaryDeviceStatusRef : secondaryDeviceStatusRef;
|
|
139
|
+
const serverTimeOffsetRef = ref(myFirebaseDB, '.info/serverTimeOffset');
|
|
169
140
|
let latestPrimaryDeviceStatus = null;
|
|
170
141
|
let latestSecondaryDeviceStatus = null;
|
|
142
|
+
let serverTimeOffsetMs = null;
|
|
143
|
+
const getComparableNow = () => {
|
|
144
|
+
if (typeof serverTimeOffsetMs !== 'number') {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return Date.now() + serverTimeOffsetMs;
|
|
148
|
+
};
|
|
171
149
|
|
|
172
150
|
// When this client disconnects (tab close, network loss)
|
|
173
151
|
onDisconnect(currentDeviceStatusRef).update({
|
|
174
152
|
connected: false
|
|
175
153
|
}).then(() => {}).catch(err => {
|
|
176
|
-
if (!isSecondaryDevice) {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
180
|
-
deviceType,
|
|
181
|
-
userUuid,
|
|
182
|
-
payload: {
|
|
183
|
-
connected: false,
|
|
184
|
-
source: 'onDisconnect'
|
|
185
|
-
},
|
|
186
|
-
error: getErrorPayload(err)
|
|
187
|
-
}, firebaseClient);
|
|
188
154
|
console.error('::[proctoringStatusUtils] Failed to mark current device disconnected:', err);
|
|
189
155
|
});
|
|
190
156
|
|
|
191
157
|
// Get initial values and update callbacks immediately
|
|
192
|
-
const applyPrimarySnapshot =
|
|
158
|
+
const applyPrimarySnapshot = snapshot => {
|
|
193
159
|
var _snapshot$val, _snapshot$val2;
|
|
194
|
-
let source = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'subscription';
|
|
195
|
-
const previousValue = latestPrimaryDeviceStatus;
|
|
196
160
|
const val = (_snapshot$val = snapshot === null || snapshot === void 0 ? void 0 : (_snapshot$val2 = snapshot.val) === null || _snapshot$val2 === void 0 ? void 0 : _snapshot$val2.call(snapshot)) !== null && _snapshot$val !== void 0 ? _snapshot$val : snapshot;
|
|
197
161
|
latestPrimaryDeviceStatus = val;
|
|
198
162
|
onPrimaryDeviceStatusChange(Boolean(val === null || val === void 0 ? void 0 : val.connected));
|
|
199
163
|
};
|
|
200
|
-
const applySecondarySnapshot =
|
|
164
|
+
const applySecondarySnapshot = snapshot => {
|
|
201
165
|
var _snapshot$val3, _snapshot$val4;
|
|
202
|
-
let source = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'subscription';
|
|
203
|
-
const previousValue = latestSecondaryDeviceStatus;
|
|
204
166
|
const val = (_snapshot$val3 = snapshot === null || snapshot === void 0 ? void 0 : (_snapshot$val4 = snapshot.val) === null || _snapshot$val4 === void 0 ? void 0 : _snapshot$val4.call(snapshot)) !== null && _snapshot$val3 !== void 0 ? _snapshot$val3 : snapshot;
|
|
205
167
|
latestSecondaryDeviceStatus = val;
|
|
206
|
-
if (isSecondaryDevice && (source === 'initial_get' || hasRelevantObservedChange(previousValue, val))) {
|
|
207
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_observed', {
|
|
208
|
-
deviceType,
|
|
209
|
-
observedDeviceType: 'secondary',
|
|
210
|
-
source,
|
|
211
|
-
observedStatus: getObservedStatusPayload(val)
|
|
212
|
-
}, firebaseClient);
|
|
213
|
-
}
|
|
214
168
|
onSecondaryDeviceStatusChange(Boolean(val === null || val === void 0 ? void 0 : val.connected), val === null || val === void 0 ? void 0 : val.allPermissionGranted);
|
|
215
169
|
};
|
|
216
170
|
if (typeof (primaryDeviceStatusRef === null || primaryDeviceStatusRef === void 0 ? void 0 : primaryDeviceStatusRef.get) === 'function') {
|
|
217
|
-
primaryDeviceStatusRef.get().then(snapshot => applyPrimarySnapshot(snapshot
|
|
171
|
+
primaryDeviceStatusRef.get().then(snapshot => applyPrimarySnapshot(snapshot)).catch(() => {});
|
|
218
172
|
}
|
|
219
173
|
if (typeof (secondaryDeviceStatusRef === null || secondaryDeviceStatusRef === void 0 ? void 0 : secondaryDeviceStatusRef.get) === 'function') {
|
|
220
|
-
secondaryDeviceStatusRef.get().then(snapshot => applySecondarySnapshot(snapshot
|
|
174
|
+
secondaryDeviceStatusRef.get().then(snapshot => applySecondarySnapshot(snapshot)).catch(() => {});
|
|
221
175
|
}
|
|
222
176
|
|
|
223
177
|
// Subscribe to updates
|
|
@@ -227,58 +181,29 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
227
181
|
const unsubscribeSecondary = onValue(secondaryDeviceStatusRef, snapshot => {
|
|
228
182
|
applySecondarySnapshot(snapshot);
|
|
229
183
|
});
|
|
184
|
+
const unsubscribeServerTimeOffset = onValue(serverTimeOffsetRef, snapshot => {
|
|
185
|
+
var _snapshot$val5, _snapshot$val6;
|
|
186
|
+
const offsetValue = (_snapshot$val5 = snapshot === null || snapshot === void 0 ? void 0 : (_snapshot$val6 = snapshot.val) === null || _snapshot$val6 === void 0 ? void 0 : _snapshot$val6.call(snapshot)) !== null && _snapshot$val5 !== void 0 ? _snapshot$val5 : snapshot;
|
|
187
|
+
serverTimeOffsetMs = typeof offsetValue === 'number' ? offsetValue : serverTimeOffsetMs;
|
|
188
|
+
});
|
|
230
189
|
|
|
231
190
|
// Start heartbeat interval
|
|
232
191
|
let heartbeatIntervalId = null;
|
|
233
192
|
if (typeof window !== 'undefined' && typeof setInterval === 'function') {
|
|
234
193
|
heartbeatIntervalId = setInterval(() => {
|
|
235
|
-
const
|
|
194
|
+
const comparableNow = getComparableNow();
|
|
236
195
|
if (isCurrentDeviceActive) {
|
|
237
196
|
update(currentDeviceStatusRef, {
|
|
238
197
|
connected: true,
|
|
239
|
-
lastHeartbeatAt:
|
|
198
|
+
lastHeartbeatAt: SERVER_TIMESTAMP
|
|
240
199
|
}).then(() => {}).catch(error => {
|
|
241
|
-
if (!isSecondaryDevice) {
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_heartbeat_write_failed', {
|
|
245
|
-
deviceType,
|
|
246
|
-
userUuid,
|
|
247
|
-
isCurrentDeviceActive,
|
|
248
|
-
now,
|
|
249
|
-
isSecondaryDevice,
|
|
250
|
-
error: getErrorPayload(error)
|
|
251
|
-
}, firebaseClient);
|
|
252
200
|
console.error('::[proctoringStatusUtils] Failed to send heartbeat for current device:', error);
|
|
253
201
|
});
|
|
254
202
|
}
|
|
255
203
|
if (!isCurrentDeviceActive) {
|
|
256
204
|
update(currentDeviceStatusRef, {
|
|
257
205
|
connected: false
|
|
258
|
-
}).then(() => {
|
|
259
|
-
if (!isSecondaryDevice) {
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_current_device_marked_inactive', {
|
|
263
|
-
deviceType,
|
|
264
|
-
userUuid,
|
|
265
|
-
now,
|
|
266
|
-
isSecondaryDevice
|
|
267
|
-
}, firebaseClient);
|
|
268
|
-
}).catch(error => {
|
|
269
|
-
if (!isSecondaryDevice) {
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
273
|
-
deviceType,
|
|
274
|
-
userUuid,
|
|
275
|
-
now,
|
|
276
|
-
payload: {
|
|
277
|
-
connected: false,
|
|
278
|
-
source: 'inactive_page_state'
|
|
279
|
-
},
|
|
280
|
-
error: getErrorPayload(error)
|
|
281
|
-
}, firebaseClient);
|
|
206
|
+
}).then(() => {}).catch(error => {
|
|
282
207
|
console.error('::[proctoringStatusUtils] Failed to mark current device inactive:', error);
|
|
283
208
|
});
|
|
284
209
|
}
|
|
@@ -287,44 +212,10 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
287
212
|
const otherDeviceStatus = isSecondaryDevice ? latestPrimaryDeviceStatus : latestSecondaryDeviceStatus;
|
|
288
213
|
const lastBeat = otherDeviceStatus === null || otherDeviceStatus === void 0 ? void 0 : otherDeviceStatus.lastHeartbeatAt;
|
|
289
214
|
const isConnected = Boolean(otherDeviceStatus === null || otherDeviceStatus === void 0 ? void 0 : otherDeviceStatus.connected);
|
|
290
|
-
if (isConnected && typeof lastBeat === 'number' &&
|
|
215
|
+
if (typeof comparableNow === 'number' && isConnected && typeof lastBeat === 'number' && comparableNow - lastBeat > OTHER_DEVICE_HEARTBEAT_TIMEOUT_MS) {
|
|
291
216
|
update(otherDeviceStatusRef, {
|
|
292
217
|
connected: false
|
|
293
|
-
}).then(() => {
|
|
294
|
-
const isMarkingSecondaryDeviceStale = !isSecondaryDevice;
|
|
295
|
-
if (!isMarkingSecondaryDeviceStale) {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('primary_marked_secondary_inactive_due_to_stale_heartbeat', {
|
|
299
|
-
deviceType: 'primary',
|
|
300
|
-
userUuid,
|
|
301
|
-
now,
|
|
302
|
-
timeoutMs: OTHER_DEVICE_HEARTBEAT_TIMEOUT_MS,
|
|
303
|
-
heartbeatDiffMs: now - lastBeat,
|
|
304
|
-
payload: {
|
|
305
|
-
connected: false,
|
|
306
|
-
source: 'stale_other_device',
|
|
307
|
-
otherDeviceType: 'secondary',
|
|
308
|
-
otherDeviceStatus: getObservedStatusPayload(otherDeviceStatus, now)
|
|
309
|
-
}
|
|
310
|
-
}, firebaseClient);
|
|
311
|
-
}).catch(otherErr => {
|
|
312
|
-
const isMarkingSecondaryDeviceStale = !isSecondaryDevice;
|
|
313
|
-
if (!isMarkingSecondaryDeviceStale) {
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
(0, _proctoringDebugUtils.emitProctoringDebugLog)('secondary_device_status_write_failed', {
|
|
317
|
-
deviceType: 'secondary',
|
|
318
|
-
userUuid,
|
|
319
|
-
now,
|
|
320
|
-
payload: {
|
|
321
|
-
connected: false,
|
|
322
|
-
source: 'stale_other_device',
|
|
323
|
-
otherDeviceType: 'secondary',
|
|
324
|
-
otherDeviceStatus: getObservedStatusPayload(otherDeviceStatus, now)
|
|
325
|
-
},
|
|
326
|
-
error: getErrorPayload(otherErr)
|
|
327
|
-
}, firebaseClient);
|
|
218
|
+
}).then(() => {}).catch(otherErr => {
|
|
328
219
|
console.error('::[proctoringStatusUtils] Failed to mark other device disconnected due to stale heartbeat:', otherErr);
|
|
329
220
|
});
|
|
330
221
|
}
|
|
@@ -333,6 +224,7 @@ const setupDeviceStatusListeners = _ref2 => {
|
|
|
333
224
|
return () => {
|
|
334
225
|
unsubscribePrimary();
|
|
335
226
|
unsubscribeSecondary();
|
|
227
|
+
unsubscribeServerTimeOffset();
|
|
336
228
|
if (heartbeatIntervalId) {
|
|
337
229
|
clearInterval(heartbeatIntervalId);
|
|
338
230
|
}
|
package/package.json
CHANGED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
require("core-js/modules/es.symbol.description.js");
|
|
4
|
-
require("core-js/modules/esnext.iterator.constructor.js");
|
|
5
|
-
require("core-js/modules/esnext.iterator.filter.js");
|
|
6
|
-
require("core-js/modules/esnext.iterator.for-each.js");
|
|
7
|
-
Object.defineProperty(exports, "__esModule", {
|
|
8
|
-
value: true
|
|
9
|
-
});
|
|
10
|
-
exports.emitProctoringDebugLog = void 0;
|
|
11
|
-
require("core-js/modules/es.json.stringify.js");
|
|
12
|
-
require("core-js/modules/es.promise.js");
|
|
13
|
-
var _defaults = require("../constants/defaults");
|
|
14
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
16
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
17
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
18
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
19
|
-
const DEBUG_LOG_PREFIX = '::[secondary-device-debug]';
|
|
20
|
-
const WEB_REPORT_LOG_ENDPOINT = '/api/v1/user/report/web/';
|
|
21
|
-
const safeJsonStringify = value => {
|
|
22
|
-
try {
|
|
23
|
-
return JSON.stringify(value);
|
|
24
|
-
} catch (error) {
|
|
25
|
-
return JSON.stringify({
|
|
26
|
-
ts: Date.now(),
|
|
27
|
-
serializationError: (error === null || error === void 0 ? void 0 : error.message) || String(error)
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
const postDebugMessage = message => {
|
|
32
|
-
if (typeof window === 'undefined') {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
try {
|
|
36
|
-
if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {
|
|
37
|
-
const body = new Blob([safeJsonStringify({
|
|
38
|
-
message
|
|
39
|
-
})], {
|
|
40
|
-
type: 'application/json'
|
|
41
|
-
});
|
|
42
|
-
navigator.sendBeacon(WEB_REPORT_LOG_ENDPOINT, body);
|
|
43
|
-
} else if (typeof fetch === 'function') {
|
|
44
|
-
fetch(WEB_REPORT_LOG_ENDPOINT, {
|
|
45
|
-
method: 'POST',
|
|
46
|
-
headers: {
|
|
47
|
-
'Content-Type': 'application/json'
|
|
48
|
-
},
|
|
49
|
-
body: safeJsonStringify({
|
|
50
|
-
message
|
|
51
|
-
}),
|
|
52
|
-
keepalive: true
|
|
53
|
-
}).catch(() => {});
|
|
54
|
-
}
|
|
55
|
-
} catch (_) {}
|
|
56
|
-
};
|
|
57
|
-
const isDebugLogEnabled = async firebaseClient => {
|
|
58
|
-
if (!(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.userUuid) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.myFirebaseDB) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.getRef) || !(firebaseClient !== null && firebaseClient !== void 0 && firebaseClient.getValue)) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
const {
|
|
62
|
-
getRef: ref,
|
|
63
|
-
getValue
|
|
64
|
-
} = firebaseClient;
|
|
65
|
-
const debugEnabledRef = ref(firebaseClient.myFirebaseDB, "".concat(_defaults.PROCTORING_STATUS_PATH, "/").concat(firebaseClient.userUuid, "/isDebugEnabled"));
|
|
66
|
-
try {
|
|
67
|
-
return await new Promise(resolve => {
|
|
68
|
-
getValue(debugEnabledRef, snapshot => {
|
|
69
|
-
var _snapshot$val, _snapshot$val2;
|
|
70
|
-
const value = (_snapshot$val = snapshot === null || snapshot === void 0 ? void 0 : (_snapshot$val2 = snapshot.val) === null || _snapshot$val2 === void 0 ? void 0 : _snapshot$val2.call(snapshot)) !== null && _snapshot$val !== void 0 ? _snapshot$val : snapshot;
|
|
71
|
-
resolve(Boolean(value));
|
|
72
|
-
}, () => resolve(false), {
|
|
73
|
-
onlyOnce: true
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
} catch (_) {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
const emitProctoringDebugLog = exports.emitProctoringDebugLog = function emitProctoringDebugLog(event) {
|
|
81
|
-
let payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
82
|
-
let firebaseClient = arguments.length > 2 ? arguments[2] : undefined;
|
|
83
|
-
const message = "".concat(DEBUG_LOG_PREFIX, " ").concat(event, " ").concat(safeJsonStringify(_objectSpread({
|
|
84
|
-
ts: Date.now()
|
|
85
|
-
}, payload)));
|
|
86
|
-
isDebugLogEnabled(firebaseClient).then(enabled => {
|
|
87
|
-
if (!enabled) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
postDebugMessage(message);
|
|
91
|
-
});
|
|
92
|
-
};
|