easyproctor 0.0.19 → 0.0.20
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/README.md +16 -16
- package/errors/errors.d.ts +10 -0
- package/esm/index.js +221 -49
- package/index.d.ts +16 -6
- package/index.js +221 -49
- package/interfaces/ProctoringRecord.d.ts +7 -0
- package/modules/checkPermissions.d.ts +2 -1
- package/modules/database.d.ts +4 -3
- package/modules/startScreenCapture.d.ts +4 -1
- package/package.json +2 -1
- package/unpkg/easyproctor.min.js +8 -8
package/README.md
CHANGED
|
@@ -35,14 +35,7 @@ Em um bundler
|
|
|
35
35
|
```javascript
|
|
36
36
|
import { useProctoring } from "easyproctor";
|
|
37
37
|
|
|
38
|
-
const {
|
|
39
|
-
start,
|
|
40
|
-
finish,
|
|
41
|
-
onFocus,
|
|
42
|
-
onLostFocus,
|
|
43
|
-
enumarateDevices,
|
|
44
|
-
checkPermissions,
|
|
45
|
-
} = useProctoring({
|
|
38
|
+
const { start, finish, pause, resume, onFocus, onLostFocus, enumarateDevices, checkPermissions, checkIfhasMultipleMonitors, onStopSharingScreen } = useProctoring({
|
|
46
39
|
examId: "00001",
|
|
47
40
|
clientId: "000001",
|
|
48
41
|
token: "...",
|
|
@@ -54,14 +47,7 @@ Via CDN: A função "useProctoring" é injetada para ser utilizada globalmente
|
|
|
54
47
|
```html
|
|
55
48
|
<script src="https://cdn.jsdelivr.net/npm/easyproctor/unpkg/easyproctor.min.js"></script>
|
|
56
49
|
<script>
|
|
57
|
-
const {
|
|
58
|
-
start,
|
|
59
|
-
finish,
|
|
60
|
-
onFocus,
|
|
61
|
-
onLostFocus,
|
|
62
|
-
enumarateDevices,
|
|
63
|
-
checkPermissions,
|
|
64
|
-
} = useProctoring({
|
|
50
|
+
const { start, finish, pause, resume, onFocus, onLostFocus, enumarateDevices, checkPermissions, checkIfhasMultipleMonitors, onStopSharingScreen } = useProctoring({
|
|
65
51
|
examId: "00001",
|
|
66
52
|
clientId: "000001",
|
|
67
53
|
token: "...",
|
|
@@ -198,6 +184,12 @@ const {
|
|
|
198
184
|
// Inicia a gravação da prova
|
|
199
185
|
start,
|
|
200
186
|
|
|
187
|
+
// Pausa a gravação
|
|
188
|
+
pause,
|
|
189
|
+
|
|
190
|
+
// Reinicia a gravação
|
|
191
|
+
resume,
|
|
192
|
+
|
|
201
193
|
// Finaliza a gravação da prova retornando os arquivos gerados
|
|
202
194
|
finish,
|
|
203
195
|
|
|
@@ -207,11 +199,19 @@ const {
|
|
|
207
199
|
// Adiciona uma função callback para ser executada quando o usuário perde o foco da tela
|
|
208
200
|
onLostFocus,
|
|
209
201
|
|
|
202
|
+
// Adiciona uma função callback para ser executada quando o usuário cancela o compartilhamento de tela
|
|
203
|
+
onStopSharingScreen
|
|
204
|
+
|
|
210
205
|
// Enumera os dispositivos de camera e microfone
|
|
211
206
|
enumarateDevices,
|
|
212
207
|
|
|
213
208
|
// Checa as permissões de camera e microfone
|
|
214
209
|
checkPermissions,
|
|
210
|
+
|
|
211
|
+
// Checa se existe mais de um monitor
|
|
212
|
+
checkIfhasMultipleMonitors
|
|
213
|
+
|
|
214
|
+
|
|
215
215
|
} = useProctoring({
|
|
216
216
|
examId: "00001",
|
|
217
217
|
clientId: "000001",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const SCRIPT_NOT_CALLED_INSIDE_BODY = "script_not_called_inside_body";
|
|
2
|
+
export declare const INCOMPATIBLE_NAVIGATOR = "incompatible_navigator";
|
|
3
|
+
export declare const REQUIRED_FIELD_NOT_PROVIDED = "required_field_not_provided";
|
|
4
|
+
export declare const NOT_SHARED_FIRST_SCREEN = "not_shared_first_screen";
|
|
5
|
+
export declare const MULTIPLE_MONITORS_DETECTED = "multiple_monitors_detected";
|
|
6
|
+
export declare const PROCTORING_ALREADY_STARTED = "proctoring_already_started";
|
|
7
|
+
export declare const PROCTORING_NOT_STARTED = "proctoring_not_started";
|
|
8
|
+
export declare const PROCTORING_RUNNING = "proctoring_running";
|
|
9
|
+
export declare const NO_VIDEOS_RECORDED = "no_videos_recorded";
|
|
10
|
+
export declare const PERMISSIONS_NOT_GRANTED = "permissions_not_granted";
|
package/esm/index.js
CHANGED
|
@@ -16,11 +16,15 @@ function recorder(stream, buffer) {
|
|
|
16
16
|
mediaRecorder.start();
|
|
17
17
|
function stopRecording() {
|
|
18
18
|
return new Promise((resolve) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
if (mediaRecorder.state == "recording") {
|
|
20
|
+
resolvePromise = resolve;
|
|
21
|
+
mediaRecorder.stop();
|
|
22
|
+
stream.getTracks().forEach((el) => {
|
|
23
|
+
el.stop();
|
|
24
|
+
});
|
|
25
|
+
} else {
|
|
26
|
+
resolve();
|
|
27
|
+
}
|
|
24
28
|
});
|
|
25
29
|
}
|
|
26
30
|
return stopRecording;
|
|
@@ -43,8 +47,20 @@ async function startCameraCapture(buffer, options = { cameraId: void 0, micropho
|
|
|
43
47
|
return { cameraStream, stopCameraRecording };
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
// src/errors/errors.ts
|
|
51
|
+
var SCRIPT_NOT_CALLED_INSIDE_BODY = "script_not_called_inside_body";
|
|
52
|
+
var INCOMPATIBLE_NAVIGATOR = "incompatible_navigator";
|
|
53
|
+
var REQUIRED_FIELD_NOT_PROVIDED = "required_field_not_provided";
|
|
54
|
+
var NOT_SHARED_FIRST_SCREEN = "not_shared_first_screen";
|
|
55
|
+
var MULTIPLE_MONITORS_DETECTED = "multiple_monitors_detected";
|
|
56
|
+
var PROCTORING_ALREADY_STARTED = "proctoring_already_started";
|
|
57
|
+
var PROCTORING_NOT_STARTED = "proctoring_not_started";
|
|
58
|
+
var PROCTORING_RUNNING = "proctoring_running";
|
|
59
|
+
var NO_VIDEOS_RECORDED = "no_videos_recorded";
|
|
60
|
+
|
|
46
61
|
// src/modules/startScreenCapture.ts
|
|
47
|
-
async function startScreenCapture(buffer) {
|
|
62
|
+
async function startScreenCapture(buffer, options) {
|
|
63
|
+
const { allowOnlyFirstMonitor, onStopSharingScreenCallback } = options;
|
|
48
64
|
const displayMediaStreamConstraints = {
|
|
49
65
|
video: {
|
|
50
66
|
cursor: "always"
|
|
@@ -52,6 +68,15 @@ async function startScreenCapture(buffer) {
|
|
|
52
68
|
audio: false
|
|
53
69
|
};
|
|
54
70
|
const screenStream = await navigator.mediaDevices.getDisplayMedia(displayMediaStreamConstraints);
|
|
71
|
+
const tracks = screenStream.getVideoTracks();
|
|
72
|
+
tracks[0].onended = onStopSharingScreenCallback;
|
|
73
|
+
const sharedFirstScreen = tracks.find((el) => el.getSettings().deviceId == "screen:0:0") != null;
|
|
74
|
+
if (!sharedFirstScreen && allowOnlyFirstMonitor) {
|
|
75
|
+
tracks.forEach((el) => {
|
|
76
|
+
el.stop();
|
|
77
|
+
});
|
|
78
|
+
throw NOT_SHARED_FIRST_SCREEN;
|
|
79
|
+
}
|
|
55
80
|
const stopScreenRecorder = recorder(screenStream, buffer);
|
|
56
81
|
return { screenStream, stopScreenRecorder };
|
|
57
82
|
}
|
|
@@ -125,21 +150,87 @@ async function checkPermissions() {
|
|
|
125
150
|
return false;
|
|
126
151
|
}
|
|
127
152
|
}
|
|
153
|
+
async function checkIfhasMultipleMonitors() {
|
|
154
|
+
return new Promise((resolve, reject) => {
|
|
155
|
+
const presentationRequest = new PresentationRequest("receiver.html");
|
|
156
|
+
presentationRequest.getAvailability().then((availability) => {
|
|
157
|
+
let hasMultipleMonitors = availability.value;
|
|
158
|
+
availability.addEventListener("change", function() {
|
|
159
|
+
hasMultipleMonitors = availability.value;
|
|
160
|
+
});
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
resolve(hasMultipleMonitors);
|
|
163
|
+
}, 1e3);
|
|
164
|
+
}).catch((error) => reject(error));
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// src/modules/database.ts
|
|
169
|
+
var databaseName = "EasyProctorPlugin";
|
|
170
|
+
var databaseVersion = 2;
|
|
171
|
+
function initializeDatabase(table) {
|
|
172
|
+
return new Promise((resolve, reject) => {
|
|
173
|
+
const request = indexedDB.open(databaseName, databaseVersion);
|
|
174
|
+
request.onupgradeneeded = () => {
|
|
175
|
+
request.result.createObjectStore("exams", { keyPath: "id" });
|
|
176
|
+
};
|
|
177
|
+
request.onerror = (e) => {
|
|
178
|
+
console.log(e);
|
|
179
|
+
reject("N\xE3o foi poss\xEDvel inicializar a biblioteca, por favor, entre em contato com o suporte e informe o erro acima");
|
|
180
|
+
};
|
|
181
|
+
request.onsuccess = () => {
|
|
182
|
+
const db = request.result;
|
|
183
|
+
const tableRef = db.transaction(table, "readwrite");
|
|
184
|
+
const store = tableRef.objectStore(table);
|
|
185
|
+
resolve(store);
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
async function insertRecord(table, data) {
|
|
190
|
+
const store = await initializeDatabase(table);
|
|
191
|
+
return new Promise((resolve, reject) => {
|
|
192
|
+
const request = store.put(data);
|
|
193
|
+
request.onsuccess = () => resolve();
|
|
194
|
+
request.onerror = (e) => reject(e);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
async function getRecord(table) {
|
|
198
|
+
const store = await initializeDatabase(table);
|
|
199
|
+
return new Promise((resolve, reject) => {
|
|
200
|
+
const request = store.getAll();
|
|
201
|
+
request.onsuccess = () => {
|
|
202
|
+
const data = request.result[0];
|
|
203
|
+
resolve(data);
|
|
204
|
+
};
|
|
205
|
+
request.onerror = (e) => reject(e);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
async function clearBuffers(table) {
|
|
209
|
+
const store = await initializeDatabase(table);
|
|
210
|
+
return new Promise((resolve, reject) => {
|
|
211
|
+
const request = store.clear();
|
|
212
|
+
request.onsuccess = () => resolve();
|
|
213
|
+
request.onerror = (e) => reject(e);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
128
216
|
|
|
129
217
|
// src/index.ts
|
|
218
|
+
var defaultProctoringOptions = {
|
|
219
|
+
cameraId: void 0,
|
|
220
|
+
microphoneId: void 0,
|
|
221
|
+
allowMulipleMonitors: false,
|
|
222
|
+
allowOnlyFirstMonitor: true
|
|
223
|
+
};
|
|
130
224
|
var azureBlobUrl = "https://iarisprod.blob.core.windows.net/iaris";
|
|
131
225
|
function useProctoring(proctoringOptions) {
|
|
132
226
|
["examId", "clientId", "token"].forEach((el) => {
|
|
133
227
|
const key = el;
|
|
134
228
|
if (!proctoringOptions[key]) {
|
|
135
|
-
throw
|
|
229
|
+
throw REQUIRED_FIELD_NOT_PROVIDED + ": " + key;
|
|
136
230
|
}
|
|
137
231
|
});
|
|
138
|
-
if (!navigator.mediaDevices.getDisplayMedia) {
|
|
139
|
-
throw
|
|
140
|
-
}
|
|
141
|
-
if (!window.indexedDB) {
|
|
142
|
-
throw "Voc\xEA est\xE1 usando uma vers\xE3o muito antiga do navegador, n\xE3o \xE9 poss\xEDvel relizar a requisi\xE7\xE3o";
|
|
232
|
+
if (!navigator.mediaDevices.getDisplayMedia || !window.indexedDB || typeof PresentationRequest === "undefined") {
|
|
233
|
+
throw INCOMPATIBLE_NAVIGATOR;
|
|
143
234
|
}
|
|
144
235
|
function download(file) {
|
|
145
236
|
const url = URL.createObjectURL(file);
|
|
@@ -158,25 +249,36 @@ function useProctoring(proctoringOptions) {
|
|
|
158
249
|
let alerts = [];
|
|
159
250
|
let onLostFocusCallback;
|
|
160
251
|
let onFocusCallback;
|
|
252
|
+
let onStopSharingScreenCallback = void 0;
|
|
161
253
|
let cancelCallback = null;
|
|
254
|
+
function _clear() {
|
|
255
|
+
cameraBuffer = [];
|
|
256
|
+
screenBuffer = [];
|
|
257
|
+
proctoringId = "";
|
|
258
|
+
startTime = 0;
|
|
259
|
+
alerts = [];
|
|
260
|
+
}
|
|
162
261
|
async function _startCapture(options) {
|
|
163
|
-
console.log(cancelCallback);
|
|
164
262
|
if (!document.body) {
|
|
165
|
-
throw
|
|
263
|
+
throw SCRIPT_NOT_CALLED_INSIDE_BODY;
|
|
166
264
|
}
|
|
167
265
|
if (cancelCallback != null) {
|
|
168
|
-
throw
|
|
266
|
+
throw PROCTORING_ALREADY_STARTED;
|
|
169
267
|
}
|
|
170
268
|
let cancelCameraCapture = null;
|
|
171
269
|
let cancelScreenCapture = null;
|
|
270
|
+
const { cameraId, microphoneId, allowOnlyFirstMonitor } = options;
|
|
172
271
|
try {
|
|
173
|
-
const { screenStream, stopScreenRecorder } = await startScreenCapture(screenBuffer
|
|
174
|
-
|
|
272
|
+
const { screenStream, stopScreenRecorder } = await startScreenCapture(screenBuffer, {
|
|
273
|
+
allowOnlyFirstMonitor,
|
|
274
|
+
onStopSharingScreenCallback: () => onStopSharingScreenCallback && onStopSharingScreenCallback()
|
|
275
|
+
});
|
|
175
276
|
const { cameraStream, stopCameraRecording } = await startCameraCapture(cameraBuffer, { cameraId, microphoneId });
|
|
176
277
|
cancelScreenCapture = stopScreenRecorder;
|
|
177
278
|
cancelCameraCapture = stopCameraRecording;
|
|
178
279
|
cancelCallback = async function() {
|
|
179
280
|
await Promise.all([cancelCameraCapture(), cancelScreenCapture()]);
|
|
281
|
+
cancelCallback = null;
|
|
180
282
|
};
|
|
181
283
|
return { screenStream, cameraStream };
|
|
182
284
|
} catch (error) {
|
|
@@ -185,7 +287,7 @@ function useProctoring(proctoringOptions) {
|
|
|
185
287
|
cancelCameraCapture && await cancelCameraCapture();
|
|
186
288
|
cameraBuffer = [];
|
|
187
289
|
screenBuffer = [];
|
|
188
|
-
throw
|
|
290
|
+
throw error;
|
|
189
291
|
}
|
|
190
292
|
}
|
|
191
293
|
const _onLostFocus = () => {
|
|
@@ -211,11 +313,33 @@ function useProctoring(proctoringOptions) {
|
|
|
211
313
|
window.removeEventListener("blur", _onLostFocus);
|
|
212
314
|
window.removeEventListener("focus", _onReturnFocus);
|
|
213
315
|
};
|
|
214
|
-
|
|
215
|
-
const
|
|
216
|
-
const
|
|
217
|
-
|
|
316
|
+
const _generateFiles = (index) => {
|
|
317
|
+
const finalCameraBuffer = cameraBuffer;
|
|
318
|
+
const finalScreenBuffer = screenBuffer;
|
|
319
|
+
if (finalCameraBuffer.length == 0 || finalScreenBuffer.length == 0) {
|
|
320
|
+
throw PROCTORING_NOT_STARTED;
|
|
321
|
+
}
|
|
322
|
+
const cameraFileName = `EP_${proctoringId}_camera_${index}.webm`;
|
|
323
|
+
const screenFIleName = `EP_${proctoringId}_screen_${index}.webm`;
|
|
324
|
+
const cameraFile = new File(finalCameraBuffer, cameraFileName, { type: "video/webm" });
|
|
325
|
+
const screenFile = new File(finalScreenBuffer, screenFIleName, { type: "video/webm" });
|
|
326
|
+
return { cameraFile, screenFile };
|
|
327
|
+
};
|
|
328
|
+
async function start(options = defaultProctoringOptions) {
|
|
329
|
+
const { cameraId, microphoneId, allowOnlyFirstMonitor = true, allowMulipleMonitors = false } = options;
|
|
330
|
+
if (!allowMulipleMonitors) {
|
|
331
|
+
const hasMultipleMonitors = await checkIfhasMultipleMonitors();
|
|
332
|
+
if (hasMultipleMonitors) {
|
|
333
|
+
throw MULTIPLE_MONITORS_DETECTED;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const hasExam = await getRecord("exams");
|
|
337
|
+
if (hasExam != null) {
|
|
338
|
+
throw PROCTORING_ALREADY_STARTED;
|
|
339
|
+
}
|
|
218
340
|
try {
|
|
341
|
+
const { cameraStream, screenStream } = await _startCapture({ cameraId, microphoneId, allowOnlyFirstMonitor });
|
|
342
|
+
startTime = Date.now();
|
|
219
343
|
const resp = await makeRequest({
|
|
220
344
|
url: `/proctoring/start/${proctoringOptions.examId}`,
|
|
221
345
|
method: "POST",
|
|
@@ -224,6 +348,12 @@ function useProctoring(proctoringOptions) {
|
|
|
224
348
|
});
|
|
225
349
|
resp.cameraStream = cameraStream;
|
|
226
350
|
resp.screenStream = screenStream;
|
|
351
|
+
await insertRecord("exams", {
|
|
352
|
+
id: resp.id,
|
|
353
|
+
cameraBuffers: [],
|
|
354
|
+
screenBuffers: [],
|
|
355
|
+
alerts: []
|
|
356
|
+
});
|
|
227
357
|
proctoringId = resp.id;
|
|
228
358
|
_addListeners();
|
|
229
359
|
return resp;
|
|
@@ -232,36 +362,74 @@ function useProctoring(proctoringOptions) {
|
|
|
232
362
|
throw error;
|
|
233
363
|
}
|
|
234
364
|
}
|
|
365
|
+
async function pause() {
|
|
366
|
+
const record = await getRecord("exams");
|
|
367
|
+
if (!cancelCallback || !record) {
|
|
368
|
+
throw PROCTORING_NOT_STARTED;
|
|
369
|
+
}
|
|
370
|
+
onStopSharingScreenCallback = void 0;
|
|
371
|
+
await cancelCallback();
|
|
372
|
+
const { cameraFile, screenFile } = _generateFiles(record.cameraBuffers.length);
|
|
373
|
+
record.cameraBuffers.push(cameraFile);
|
|
374
|
+
record.screenBuffers.push(screenFile);
|
|
375
|
+
record.alerts.push(...alerts);
|
|
376
|
+
await insertRecord("exams", record);
|
|
377
|
+
_clear();
|
|
378
|
+
}
|
|
379
|
+
async function resume(options = defaultProctoringOptions) {
|
|
380
|
+
_clear();
|
|
381
|
+
const { cameraId, microphoneId, allowOnlyFirstMonitor = true, allowMulipleMonitors = false } = options;
|
|
382
|
+
if (!allowMulipleMonitors) {
|
|
383
|
+
const hasMultipleMonitors = await checkIfhasMultipleMonitors();
|
|
384
|
+
if (hasMultipleMonitors) {
|
|
385
|
+
throw MULTIPLE_MONITORS_DETECTED;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (cancelCallback) {
|
|
389
|
+
throw PROCTORING_RUNNING;
|
|
390
|
+
}
|
|
391
|
+
const record = await getRecord("exams");
|
|
392
|
+
if (!record) {
|
|
393
|
+
throw PROCTORING_NOT_STARTED;
|
|
394
|
+
}
|
|
395
|
+
const { cameraStream, screenStream } = await _startCapture({ cameraId, microphoneId, allowOnlyFirstMonitor });
|
|
396
|
+
proctoringId = record.id;
|
|
397
|
+
startTime = Date.now();
|
|
398
|
+
return { cameraStream, screenStream };
|
|
399
|
+
}
|
|
235
400
|
async function finish(options = {}) {
|
|
236
401
|
const { onProgress } = options;
|
|
402
|
+
const record = await getRecord("exams");
|
|
403
|
+
if (!record) {
|
|
404
|
+
throw PROCTORING_NOT_STARTED;
|
|
405
|
+
}
|
|
406
|
+
onStopSharingScreenCallback = void 0;
|
|
237
407
|
if (cancelCallback) {
|
|
238
408
|
await cancelCallback();
|
|
409
|
+
const { cameraFile, screenFile } = _generateFiles(record.cameraBuffers.length);
|
|
410
|
+
record.cameraBuffers.push(cameraFile);
|
|
411
|
+
record.screenBuffers.push(screenFile);
|
|
239
412
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const finalScreenBuffer = screenBuffer;
|
|
243
|
-
if (finalCameraBuffer.length == 0 || finalScreenBuffer.length == 0) {
|
|
244
|
-
throw "N\xE3o existe nenhuma grava\xE7\xE3o iniciada";
|
|
413
|
+
if (record.cameraBuffers.length == 0 || record.screenBuffers.length == 0) {
|
|
414
|
+
throw NO_VIDEOS_RECORDED;
|
|
245
415
|
}
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
const screenFile = new File(finalScreenBuffer, screenFIleName, { type: "video/webm" });
|
|
250
|
-
let cameraProgress = 0;
|
|
251
|
-
let screenProgress = 0;
|
|
416
|
+
const time = new Date().toISOString();
|
|
417
|
+
const totalFiles = record.cameraBuffers.length + record.screenBuffers.length;
|
|
418
|
+
const uploadProgress = Array(totalFiles).fill(0);
|
|
252
419
|
const handleOnProgress = () => {
|
|
253
|
-
onProgress && onProgress((
|
|
420
|
+
onProgress && onProgress(uploadProgress.reduce((acc, el) => acc += el, 0) / totalFiles);
|
|
254
421
|
};
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
|
|
422
|
+
const allFiles = [...record.cameraBuffers, ...record.screenBuffers];
|
|
423
|
+
const uploadPromises = allFiles.map((c, i) => {
|
|
424
|
+
return upload_default({
|
|
425
|
+
file: c,
|
|
426
|
+
onProgress: (progress) => {
|
|
427
|
+
uploadProgress[i] = progress;
|
|
428
|
+
handleOnProgress();
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
await Promise.all(uploadPromises);
|
|
265
433
|
_removeListeners();
|
|
266
434
|
await makeRequest({
|
|
267
435
|
url: "/proctoring/save-screen",
|
|
@@ -269,19 +437,20 @@ function useProctoring(proctoringOptions) {
|
|
|
269
437
|
jwt: proctoringOptions.token,
|
|
270
438
|
body: {
|
|
271
439
|
proctoringId,
|
|
272
|
-
alerts: [...alerts]
|
|
440
|
+
alerts: [...record.alerts, ...alerts]
|
|
273
441
|
}
|
|
274
442
|
});
|
|
275
443
|
await makeRequest({
|
|
276
|
-
url: `/proctoring/finish/${
|
|
444
|
+
url: `/proctoring/finish/${record.id}`,
|
|
277
445
|
method: "POST",
|
|
278
446
|
body: {
|
|
279
447
|
endDate: time,
|
|
280
|
-
videoCameraUrl: `${azureBlobUrl}/${
|
|
281
|
-
videoScreenUrl: `${azureBlobUrl}/${
|
|
448
|
+
videoCameraUrl: `${azureBlobUrl}/${proctoringId}/cameraFiles`,
|
|
449
|
+
videoScreenUrl: `${azureBlobUrl}/${proctoringId}/screenFiles`
|
|
282
450
|
},
|
|
283
451
|
jwt: proctoringOptions.token
|
|
284
452
|
});
|
|
453
|
+
await clearBuffers("exams");
|
|
285
454
|
cameraBuffer = [];
|
|
286
455
|
screenBuffer = [];
|
|
287
456
|
alerts = [];
|
|
@@ -290,10 +459,13 @@ function useProctoring(proctoringOptions) {
|
|
|
290
459
|
function onFocus(cb) {
|
|
291
460
|
onFocusCallback = cb;
|
|
292
461
|
}
|
|
462
|
+
function onStopSharingScreen(cb) {
|
|
463
|
+
onStopSharingScreenCallback = cb;
|
|
464
|
+
}
|
|
293
465
|
function onLostFocus(cb) {
|
|
294
466
|
onLostFocusCallback = cb;
|
|
295
467
|
}
|
|
296
|
-
return { start, finish,
|
|
468
|
+
return { start, finish, pause, resume, onFocus, onLostFocus, enumarateDevices, checkPermissions, checkIfhasMultipleMonitors, onStopSharingScreen };
|
|
297
469
|
}
|
|
298
470
|
if (typeof window !== "undefined") {
|
|
299
471
|
window.useProctoring = useProctoring;
|
package/index.d.ts
CHANGED
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
import enumarateDevices from "./modules/enumarateDevices";
|
|
2
|
-
import checkPermissions from "./modules/checkPermissions";
|
|
2
|
+
import { checkPermissions, checkIfhasMultipleMonitors } from "./modules/checkPermissions";
|
|
3
3
|
import StartProctoringResponse from "./dtos/StartProctoringResponse";
|
|
4
|
+
interface ProctoringOptions {
|
|
5
|
+
cameraId?: string;
|
|
6
|
+
microphoneId?: string;
|
|
7
|
+
allowMulipleMonitors?: boolean;
|
|
8
|
+
allowOnlyFirstMonitor?: boolean;
|
|
9
|
+
}
|
|
4
10
|
export declare function useProctoring(proctoringOptions: {
|
|
5
11
|
examId: string;
|
|
6
12
|
clientId: string;
|
|
7
13
|
token: string;
|
|
8
14
|
}): {
|
|
9
|
-
start: (options?:
|
|
10
|
-
cameraId?: string;
|
|
11
|
-
microphoneId?: string;
|
|
12
|
-
}) => Promise<StartProctoringResponse>;
|
|
15
|
+
start: (options?: ProctoringOptions) => Promise<StartProctoringResponse>;
|
|
13
16
|
finish: (options?: {
|
|
14
17
|
onProgress?: ((percentage: number) => void) | undefined;
|
|
15
18
|
}) => Promise<void>;
|
|
16
|
-
|
|
19
|
+
pause: () => Promise<void>;
|
|
20
|
+
resume: (options?: ProctoringOptions) => Promise<{
|
|
21
|
+
cameraStream: MediaStream;
|
|
22
|
+
screenStream: MediaStream;
|
|
23
|
+
}>;
|
|
17
24
|
onFocus: (cb: () => void) => void;
|
|
18
25
|
onLostFocus: (cb: () => void) => void;
|
|
19
26
|
enumarateDevices: typeof enumarateDevices;
|
|
20
27
|
checkPermissions: typeof checkPermissions;
|
|
28
|
+
checkIfhasMultipleMonitors: typeof checkIfhasMultipleMonitors;
|
|
29
|
+
onStopSharingScreen: (cb: () => void) => void;
|
|
21
30
|
};
|
|
31
|
+
export {};
|