@sprig-technologies/sprig-browser 2.14.4 → 2.14.7
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/controller/controller.d.ts.map +1 -1
- package/controller/encodedViewJs.d.ts +2 -1
- package/controller/encodedViewJs.d.ts.map +1 -1
- package/controller/encodedViewJs.js +1 -1
- package/controller/queue.d.ts +1 -17
- package/controller/queue.d.ts.map +1 -1
- package/package.json +1 -1
- package/shared/network.js +2 -2
- package/controller/recordingAPI/index.js +0 -202
- package/controller/recordingAPI/permissionStubs.json +0 -65
package/controller/queue.d.ts
CHANGED
|
@@ -1,18 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
new (ul: any, queue: any): {
|
|
3
|
-
ul: any;
|
|
4
|
-
paused: boolean;
|
|
5
|
-
queue: any[];
|
|
6
|
-
flush(queue: any): void;
|
|
7
|
-
isPaused(): boolean;
|
|
8
|
-
pause(): void;
|
|
9
|
-
unpause(): void;
|
|
10
|
-
push(action: any): void;
|
|
11
|
-
perform(func: any): any;
|
|
12
|
-
/**
|
|
13
|
-
* Removes all queued items
|
|
14
|
-
*/
|
|
15
|
-
empty(): void;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
1
|
+
export {};
|
|
18
2
|
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../sprig-browser/controller/queue.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../sprig-browser/controller/queue.js"],"names":[],"mappings":""}
|
package/package.json
CHANGED
package/shared/network.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import 'whatwg-fetch';
|
|
3
3
|
import { HEADERS, INSTALLATION_METHOD } from './constants';
|
|
4
4
|
import Deferred from './deferred';
|
|
5
|
-
|
|
5
|
+
import { delay, NETWORK_CONFIG } from './networkHelper';
|
|
6
6
|
|
|
7
7
|
let killswitch = false;
|
|
8
8
|
let killswitchReason = '';
|
|
@@ -25,7 +25,7 @@ export function getHttpHeaders(Sprig = {}) {
|
|
|
25
25
|
const headers = {
|
|
26
26
|
'Content-Type': 'application/json',
|
|
27
27
|
'userleap-platform': 'web',
|
|
28
|
-
'x-ul-sdk-version': '2.14.
|
|
28
|
+
'x-ul-sdk-version': '2.14.7', //version here doesn't matter. it is string-replaced when compiled
|
|
29
29
|
};
|
|
30
30
|
if (Sprig.envId) headers[HEADERS.ENVIRONMENT_ID] = Sprig.envId;
|
|
31
31
|
if (Sprig.token) headers['Authorization'] = 'Bearer ' + Sprig.token;
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
/* global navigator, MediaRecorder, UpChunk, File, Blob, fetch*/
|
|
2
|
-
/*
|
|
3
|
-
recording api requirements
|
|
4
|
-
- check for and request for permissions
|
|
5
|
-
- handle recording exceptions (premature closing)
|
|
6
|
-
- track start end times
|
|
7
|
-
- show splash for permissions
|
|
8
|
-
*/
|
|
9
|
-
import 'whatwg-fetch';
|
|
10
|
-
export const PERMISSION = {
|
|
11
|
-
CAMERA: 'camera',
|
|
12
|
-
MICROPHONE: 'microphone',
|
|
13
|
-
SCREEN: 'screen',
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const STREAM_TYPE = {
|
|
17
|
-
AV: 'av',
|
|
18
|
-
SCREEN_CAPTURE: 'screen_capture',
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Gets the local audio stream of the current caller
|
|
22
|
-
* @param callbacks - an object to set the success/error behavior
|
|
23
|
-
* @returns {void}
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
async function getAVStream(permissionDescriptor) {
|
|
27
|
-
try {
|
|
28
|
-
return navigator.mediaDevices.getUserMedia(permissionDescriptor);
|
|
29
|
-
} catch (err) {
|
|
30
|
-
console.log('oops got an error:' + err);
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const createUpload = async (body) => {
|
|
36
|
-
const response = await fetch(`https://api-staging.sprig.com/2/environments/integrations/upload`, {
|
|
37
|
-
method: 'POST',
|
|
38
|
-
cache: 'no-cache',
|
|
39
|
-
headers: { 'Content-Type': 'application/json' },
|
|
40
|
-
body: JSON.stringify(body),
|
|
41
|
-
});
|
|
42
|
-
if (response.ok) {
|
|
43
|
-
const uploadResponse = await response.json();
|
|
44
|
-
console.log(`create upload response ${response}`);
|
|
45
|
-
return uploadResponse.upload.url;
|
|
46
|
-
} else {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const recorder = {
|
|
52
|
-
grantedPermissions: [],
|
|
53
|
-
streams: [],
|
|
54
|
-
recorders: [],
|
|
55
|
-
startingTimeOnTask: undefined,
|
|
56
|
-
async uploadVideo(fileUrl) {
|
|
57
|
-
console.log('uploading task about to start for ${fileUrl}');
|
|
58
|
-
//doesn't necessarily stop when the next question also requires media
|
|
59
|
-
const body = {
|
|
60
|
-
surveyId: 5105,
|
|
61
|
-
updatedAt: new Date().toISOString(),
|
|
62
|
-
mediaType: 'video',
|
|
63
|
-
};
|
|
64
|
-
const url = await createUpload(body);
|
|
65
|
-
if (!url) return;
|
|
66
|
-
|
|
67
|
-
const blob = new Blob([atob(fileUrl)], {
|
|
68
|
-
type: 'video/webm',
|
|
69
|
-
});
|
|
70
|
-
const upload = UpChunk.createUpload({
|
|
71
|
-
// endpoint computed from backend separately and hacked together
|
|
72
|
-
endpoint: url,
|
|
73
|
-
file: new File([blob], `recording video ${Date.now()}`),
|
|
74
|
-
chunkSize: 5120, // Uploads the file in ~5mb chunks
|
|
75
|
-
});
|
|
76
|
-
upload.startTime = Date.now();
|
|
77
|
-
|
|
78
|
-
// subscribe to events
|
|
79
|
-
upload.on('error', (err) => {
|
|
80
|
-
console.log(`upload error ${err}`);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
upload.on('progress', (progress) => {
|
|
84
|
-
console.log(progress);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
upload.on('success', () => {
|
|
88
|
-
console.log('uploaded!');
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
|
-
configure(eventEmitter) {
|
|
92
|
-
eventEmitter.subscribe('permission', async (payload) => {
|
|
93
|
-
const stream = await this.requestPermissions(payload.permissionDescriptors);
|
|
94
|
-
payload.callback(stream);
|
|
95
|
-
});
|
|
96
|
-
eventEmitter.subscribe('taskComplete', (payload) => {
|
|
97
|
-
console.log('congrats you have ' + payload.completed ? 'completed' : 'given up' + ' the task');
|
|
98
|
-
//doesn't necessarily stop when the next question also requires media
|
|
99
|
-
const body = {
|
|
100
|
-
surveyId: 5105,
|
|
101
|
-
updatedAt: new Date().toISOString(),
|
|
102
|
-
mediaType: 'video',
|
|
103
|
-
};
|
|
104
|
-
this.recorders.map((recorder) => {
|
|
105
|
-
recorder.stop();
|
|
106
|
-
});
|
|
107
|
-
this.recorders.map(async (recorder) => {
|
|
108
|
-
recorder.stream.getTracks().map((track) => {
|
|
109
|
-
track.stop();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const url = await createUpload(body);
|
|
113
|
-
if (!url) return;
|
|
114
|
-
const blob = new Blob(recorder.chunks, { type: 'video/webm' });
|
|
115
|
-
const upload = UpChunk.createUpload({
|
|
116
|
-
// endpoint computed from backend separately and hacked together
|
|
117
|
-
endpoint: url,
|
|
118
|
-
file: new File([blob], `recording video ${Date.now()}`),
|
|
119
|
-
chunkSize: 5120, // Uploads the file in ~5mb chunks
|
|
120
|
-
});
|
|
121
|
-
upload.startTime = Date.now();
|
|
122
|
-
|
|
123
|
-
// subscribe to events
|
|
124
|
-
upload.on('error', (err) => {
|
|
125
|
-
console.log(`upload error ${err}`);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
upload.on('progress', (progress) => {
|
|
129
|
-
console.log(progress);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
upload.on('success', () => {
|
|
133
|
-
console.log('uploaded!');
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
eventEmitter.subscribe('trackTime', (payload) => {
|
|
138
|
-
if (payload.timetracker === 'start') {
|
|
139
|
-
this.startingTimeOnTask = new Date();
|
|
140
|
-
} else {
|
|
141
|
-
const currentTime = new Date();
|
|
142
|
-
console.log(`task duration ${currentTime.getTime() - this.startingTimeOnTask.getTime()} ms`);
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
// TODO clean up this logic and combine the permission request and exception handling
|
|
148
|
-
async requestPermissions(permissions) {
|
|
149
|
-
// unsupported permissions
|
|
150
|
-
if (!permissions.every((val) => Object.values(PERMISSION).includes(val))) return false;
|
|
151
|
-
const streamResults = {};
|
|
152
|
-
const recordingOptions = {
|
|
153
|
-
audioBitsPerSecond: 128000,
|
|
154
|
-
videoBitsPerSecond: 2500000,
|
|
155
|
-
// mimeType: 'video/webm',
|
|
156
|
-
};
|
|
157
|
-
if (permissions.includes(PERMISSION.CAMERA) || permissions.includes(PERMISSION.MICROPHONE)) {
|
|
158
|
-
const stream = await getAVStream({
|
|
159
|
-
video: permissions.includes(PERMISSION.CAMERA),
|
|
160
|
-
audio: permissions.includes(PERMISSION.MICROPHONE),
|
|
161
|
-
});
|
|
162
|
-
if (stream && this.grantedPermissions.length === 0) {
|
|
163
|
-
[PERMISSION.CAMERA, PERMISSION.MICROPHONE].every(
|
|
164
|
-
(val) => permissions.includes(val) && this.grantedPermissions.push(val)
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
console.log('avstream successful');
|
|
168
|
-
console.log(stream);
|
|
169
|
-
streamResults[STREAM_TYPE.AV] = stream;
|
|
170
|
-
const mediaRecorder = new MediaRecorder(stream, recordingOptions);
|
|
171
|
-
mediaRecorder.chunks = [];
|
|
172
|
-
mediaRecorder.ondataavailable = function(e) {
|
|
173
|
-
mediaRecorder.chunks.push(e.data);
|
|
174
|
-
};
|
|
175
|
-
mediaRecorder.start();
|
|
176
|
-
this.recorders.push(mediaRecorder);
|
|
177
|
-
this.streams.push(stream);
|
|
178
|
-
}
|
|
179
|
-
if (permissions.includes(PERMISSION.SCREEN)) {
|
|
180
|
-
const captureStream = await navigator.mediaDevices.getDisplayMedia({
|
|
181
|
-
video: {
|
|
182
|
-
cursor: 'always',
|
|
183
|
-
},
|
|
184
|
-
});
|
|
185
|
-
console.log(captureStream);
|
|
186
|
-
const audioTrack = this.streams[0].getAudioTracks()[0];
|
|
187
|
-
captureStream.addTrack(audioTrack);
|
|
188
|
-
streamResults[STREAM_TYPE.SCREEN_CAPTURE] = captureStream;
|
|
189
|
-
const mediaRecorder = new MediaRecorder(captureStream, recordingOptions);
|
|
190
|
-
mediaRecorder.chunks = [];
|
|
191
|
-
mediaRecorder.ondataavailable = function(e) {
|
|
192
|
-
mediaRecorder.chunks.push(e.data);
|
|
193
|
-
};
|
|
194
|
-
mediaRecorder.start();
|
|
195
|
-
this.recorders.push(mediaRecorder);
|
|
196
|
-
this.streams.push(captureStream);
|
|
197
|
-
}
|
|
198
|
-
return streamResults;
|
|
199
|
-
},
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
export default recorder;
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"questions": [
|
|
3
|
-
{
|
|
4
|
-
"name": 103850,
|
|
5
|
-
"props": {
|
|
6
|
-
"message": "get your video/audio permissions",
|
|
7
|
-
"options": [],
|
|
8
|
-
"routingOptions": [],
|
|
9
|
-
"properties": {
|
|
10
|
-
"captionText": "click this button",
|
|
11
|
-
"buttonText": "get permission",
|
|
12
|
-
"permissions": ["microphone", "camera"],
|
|
13
|
-
"showVideoPlayer": true
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"type": "av_permission",
|
|
17
|
-
"surveyId": 1234
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"name": 103851,
|
|
21
|
-
"props": {
|
|
22
|
-
"message": "get your screen permissions",
|
|
23
|
-
"options": [],
|
|
24
|
-
"routingOptions": [],
|
|
25
|
-
"properties": {
|
|
26
|
-
"captionText": "click this button",
|
|
27
|
-
"buttonText": "get permission",
|
|
28
|
-
"permissions": ["screen"]
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
"type": "screen_permission",
|
|
32
|
-
"surveyId": 1234
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"name": 103852,
|
|
36
|
-
"props": {
|
|
37
|
-
"message": "record task",
|
|
38
|
-
"options": [],
|
|
39
|
-
"routingOptions": [],
|
|
40
|
-
"properties": {
|
|
41
|
-
"captionText": "get started",
|
|
42
|
-
"buttonText": "get started",
|
|
43
|
-
"timetracker": "start"
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
"type": "record_task_start",
|
|
47
|
-
"surveyId": 1234
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"name": 103853,
|
|
51
|
-
"props": {
|
|
52
|
-
"message": "complete task",
|
|
53
|
-
"options": [],
|
|
54
|
-
"routingOptions": [],
|
|
55
|
-
"properties": {
|
|
56
|
-
"captionText": "get started",
|
|
57
|
-
"completeText": "complete task",
|
|
58
|
-
"buttonText": "I give up",
|
|
59
|
-
"timetracker": "end"
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
"type": "record_task_finish",
|
|
63
|
-
"surveyId": 1234
|
|
64
|
-
}
|
|
65
|
-
]}
|