videomail-client 8.3.1 → 8.3.3

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.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/prototype/js/videomail-client.js +8 -9
  3. package/prototype/js/videomail-client.min.js +1 -1
  4. package/prototype/js/videomail-client.min.js.map +1 -1
  5. package/src/js/client.js +0 -210
  6. package/src/js/constants.js +0 -11
  7. package/src/js/events.js +0 -46
  8. package/src/js/index.js +0 -15
  9. package/src/js/options.js +0 -180
  10. package/src/js/resource.js +0 -206
  11. package/src/js/util/audioRecorder.js +0 -152
  12. package/src/js/util/browser.js +0 -319
  13. package/src/js/util/collectLogger.js +0 -72
  14. package/src/js/util/eventEmitter.js +0 -72
  15. package/src/js/util/humanize.js +0 -16
  16. package/src/js/util/mediaEvents.js +0 -148
  17. package/src/js/util/pretty.js +0 -70
  18. package/src/js/util/standardize.js +0 -71
  19. package/src/js/util/videomailError.js +0 -431
  20. package/src/js/wrappers/buttons.js +0 -670
  21. package/src/js/wrappers/container.js +0 -797
  22. package/src/js/wrappers/dimension.js +0 -149
  23. package/src/js/wrappers/form.js +0 -319
  24. package/src/js/wrappers/optionsWrapper.js +0 -81
  25. package/src/js/wrappers/visuals/inside/recorder/countdown.js +0 -83
  26. package/src/js/wrappers/visuals/inside/recorder/facingMode.js +0 -53
  27. package/src/js/wrappers/visuals/inside/recorder/pausedNote.js +0 -59
  28. package/src/js/wrappers/visuals/inside/recorder/recordNote.js +0 -42
  29. package/src/js/wrappers/visuals/inside/recorder/recordTimer.js +0 -149
  30. package/src/js/wrappers/visuals/inside/recorderInsides.js +0 -144
  31. package/src/js/wrappers/visuals/notifier.js +0 -341
  32. package/src/js/wrappers/visuals/recorder.js +0 -1492
  33. package/src/js/wrappers/visuals/replay.js +0 -355
  34. package/src/js/wrappers/visuals/userMedia.js +0 -541
  35. package/src/js/wrappers/visuals.js +0 -410
  36. package/src/styles/css/main.min.css.js +0 -1
  37. package/src/styles/styl/keyframes/blink.styl +0 -16
  38. package/src/styles/styl/main.styl +0 -126
@@ -1,152 +0,0 @@
1
- import AudioSample from "audio-sample";
2
- import Browser from "./browser";
3
- import VideomailError from "./videomailError";
4
- import isPOT from "is-power-of-two";
5
-
6
- const CHANNELS = 1;
7
-
8
- /*
9
- * for inspiration see
10
- * https://github.com/saebekassebil/microphone-stream
11
- */
12
-
13
- // todo code needs rewrite
14
-
15
- export default function (userMedia, options) {
16
- let scriptProcessor;
17
- let audioInput;
18
- let vcAudioContext;
19
-
20
- const browser = new Browser(options);
21
-
22
- function getAudioContextClass() {
23
- return window.AudioContext || window.webkitAudioContext;
24
- }
25
-
26
- function hasAudioContext() {
27
- return Boolean(getAudioContextClass()) && Boolean(getAudioContext());
28
- }
29
-
30
- function getAudioContext() {
31
- // instantiate only once
32
- if (!vcAudioContext) {
33
- const AudioContext = getAudioContextClass();
34
- vcAudioContext = new AudioContext();
35
- }
36
-
37
- return vcAudioContext;
38
- }
39
-
40
- function onAudioProcess(e, cb) {
41
- if (!userMedia.isRecording() || userMedia.isPaused()) {
42
- return;
43
- }
44
-
45
- /*
46
- * Returns a Float32Array containing the PCM data associated with the channel,
47
- * defined by the channel parameter (with 0 representing the first channel)
48
- */
49
- const float32Array = e.inputBuffer.getChannelData(0);
50
-
51
- cb(new AudioSample(float32Array));
52
- }
53
-
54
- this.init = function (localMediaStream) {
55
- options.debug("AudioRecorder: init()");
56
-
57
- // creates an audio node from the microphone incoming stream
58
- const volume = getAudioContext().createGain();
59
-
60
- try {
61
- audioInput = getAudioContext().createMediaStreamSource(localMediaStream);
62
- } catch (exc) {
63
- throw VideomailError.create("Webcam has no audio", exc.toString(), options);
64
- }
65
-
66
- let { bufferSize } = options.audio;
67
-
68
- // see https://github.com/binarykitchen/videomail-client/issues/184
69
- if (bufferSize === "auto") {
70
- if (browser.isFirefox()) {
71
- bufferSize = 512;
72
- } else {
73
- bufferSize = 2048;
74
- }
75
- }
76
-
77
- if (!isPOT(bufferSize)) {
78
- throw VideomailError.create("Audio buffer size must be a power of two.", options);
79
- }
80
-
81
- if (!options.audio.volume || options.audio.volume > 1) {
82
- throw VideomailError.create("Audio volume must be between zero and one.", options);
83
- }
84
-
85
- volume.gain.value = options.audio.volume;
86
-
87
- /*
88
- * Create a ScriptProcessorNode with the given bufferSize and
89
- * a single input and output channel
90
- */
91
- scriptProcessor = getAudioContext().createScriptProcessor(
92
- bufferSize,
93
- CHANNELS,
94
- CHANNELS,
95
- );
96
-
97
- // connect stream to our scriptProcessor
98
- audioInput.connect(scriptProcessor);
99
-
100
- // connect our scriptProcessor to the previous destination
101
- scriptProcessor.connect(getAudioContext().destination);
102
-
103
- // connect volume
104
- audioInput.connect(volume);
105
- volume.connect(scriptProcessor);
106
- };
107
-
108
- this.record = function (cb) {
109
- options.debug("AudioRecorder: record()");
110
-
111
- scriptProcessor.onaudioprocess = function (e) {
112
- onAudioProcess(e, cb);
113
- };
114
- };
115
-
116
- this.stop = function () {
117
- options.debug("AudioRecorder: stop()");
118
-
119
- if (scriptProcessor) {
120
- scriptProcessor.onaudioprocess = undefined;
121
- }
122
-
123
- if (audioInput) {
124
- audioInput.disconnect();
125
- }
126
-
127
- // https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/close
128
- if (hasAudioContext()) {
129
- if (getAudioContext().close) {
130
- getAudioContext()
131
- .close()
132
- .then(function () {
133
- options.debug("AudioRecorder: audio context is closed");
134
- vcAudioContext = null;
135
- })
136
- .catch(function (err) {
137
- throw VideomailError.create(err, options);
138
- });
139
- } else {
140
- vcAudioContext = null;
141
- }
142
- }
143
- };
144
-
145
- this.getSampleRate = function () {
146
- if (hasAudioContext()) {
147
- return getAudioContext().sampleRate;
148
- }
149
-
150
- return -1;
151
- };
152
- }
@@ -1,319 +0,0 @@
1
- import defined from "defined";
2
- import UAParser from "ua-parser-js";
3
-
4
- import VideomailError from "./videomailError";
5
-
6
- const FALLBACK_VIDEO_TYPE = "mp4";
7
-
8
- const Browser = function (options) {
9
- options ||= {};
10
-
11
- const firefoxDownload = "http://www.mozilla.org/firefox/update/";
12
- const edgeDownload = "https://www.microsoft.com/en-us/download/details.aspx?id=48126";
13
- const chromeDownload = "http://www.google.com/chrome/";
14
- const chromiumDownload = "http://www.chromium.org/getting-involved/download-chromium";
15
- const ua = defined(
16
- options.fakeUaString,
17
- typeof window !== "undefined" && window.navigator && window.navigator.userAgent,
18
- "",
19
- );
20
-
21
- const uaParser = new UAParser(ua).getResult();
22
-
23
- const isIOS = uaParser.os.name === "iOS";
24
- const browserVersion = parseFloat(uaParser.browser.version);
25
- const isChrome = uaParser.browser.name === "Chrome";
26
- const isBrave = uaParser.browser.name === "Brave";
27
- const isChromium = uaParser.browser.name === "Chromium";
28
- const firefox = uaParser.browser.name === "Firefox";
29
- const osVersion = parseFloat(uaParser.os.version);
30
- const isWindows = uaParser.os.name === "Windows";
31
- const isEdge = uaParser.browser.name === "Edge" || (isWindows && osVersion >= 10);
32
- const isIE = /IE/.test(uaParser.browser.name);
33
- const isSafari = /Safari/.test(uaParser.browser.name);
34
- const isOpera = /Opera/.test(uaParser.browser.name);
35
- const isAndroid = /Android/.test(uaParser.os.name);
36
- const chromeBased = isChrome || isChromium;
37
- const isFacebook = uaParser.browser.name === "Facebook"; // Facebook App for iOS & Android
38
-
39
- const isMobile = isIOS || isAndroid;
40
- const isOkSafari = isSafari && browserVersion >= 11;
41
- const isOkIOS = isIOS && osVersion >= 11;
42
- const isBadIOS = isIOS && osVersion < 11;
43
- // unfortunately need to be able to fake https because tape-run can't run on https
44
- const isHTTPS = options.fakeHttps || window.location.protocol === "https:";
45
-
46
- const okBrowser =
47
- chromeBased ||
48
- firefox ||
49
- isAndroid ||
50
- isOpera ||
51
- isEdge ||
52
- isOkSafari ||
53
- isOkIOS ||
54
- isBrave;
55
-
56
- const self = this;
57
-
58
- let videoType;
59
-
60
- function getRecommendation() {
61
- let warning;
62
-
63
- if (firefox) {
64
- if (isIOS) {
65
- warning =
66
- "Firefox on iOS is not ready for cameras yet. Hopefully in near future ...";
67
- } else {
68
- warning =
69
- `Probably you need to <a href="${firefoxDownload}" target="_blank">` +
70
- `upgrade Firefox</a> to fix this.`;
71
- }
72
- } else if (isChrome) {
73
- if (isIOS) {
74
- warning =
75
- "Use Safari instead. Apple doesn't give Chrome access to iPhone cameras (booo).";
76
- } else {
77
- warning =
78
- `Probably you need to <a href="${chromeDownload}" target="_blank">` +
79
- `upgrade Chrome</a> to fix this.`;
80
- }
81
- } else if (isChromium) {
82
- warning =
83
- `Probably you need to <a href="${chromiumDownload}" target="_blank">` +
84
- `upgrade Chromium</a> to fix this.`;
85
- } else if (isIE) {
86
- warning =
87
- `Instead of Internet Explorer you need to upgrade to` +
88
- ` <a href="${edgeDownload}" target="_blank">Edge</a>.`;
89
- } else if (isOkSafari) {
90
- warning =
91
- "Probably you need to shut down Safari and restart it, this for correct webcam access.";
92
- } else if (isSafari) {
93
- warning =
94
- `Safari below version 11 has no webcam support.<br/>Better upgrade Safari or pick` +
95
- ` <a href="${chromeDownload}" target="_blank">Chrome</a>,` +
96
- ` <a href="${firefoxDownload}" target="_blank">Firefox</a> or Android.`;
97
- }
98
-
99
- return warning;
100
- }
101
-
102
- function getUserMediaWarning() {
103
- let warning;
104
-
105
- if (isBadIOS) {
106
- warning =
107
- "On iPads or iPhones below iOS v11 this camera feature is missing.<br/><br/>" +
108
- "For now, we recommend you to upgrade iOS or to use an Android device.";
109
- } else {
110
- warning = getRecommendation();
111
- }
112
-
113
- if (!warning) {
114
- if (self.isChromeBased() || self.isFirefox() || isSafari) {
115
- warning = "For the webcam feature, your browser needs an upgrade.";
116
- } else if (isFacebook) {
117
- warning =
118
- `Hence we recommend you to use a real browser like ` +
119
- `<a href="${chromeDownload}" target="_blank">Chrome</a>, ` +
120
- `<a href="${firefoxDownload}" target="_blank">Firefox</a> or ` +
121
- `<a href="${edgeDownload}" target="_blank">Edge</a>.`;
122
- } else {
123
- warning =
124
- `Hence we recommend you to use either ` +
125
- `<a href="${chromeDownload}" target="_blank">Chrome</a>, ` +
126
- `<a href="${firefoxDownload}" target="_blank">Firefox</a>, ` +
127
- `<a href="${edgeDownload}" target="_blank">Edge</a> or Android.`;
128
- }
129
- }
130
-
131
- return warning;
132
- }
133
-
134
- this.canRecord = function () {
135
- const hasNavigator = typeof navigator !== "undefined";
136
- let canRecord = false;
137
-
138
- if (hasNavigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
139
- canRecord = true;
140
- } else {
141
- const getUserMediaType = hasNavigator && typeof navigator.getUserMedia_;
142
-
143
- canRecord = getUserMediaType === "function";
144
- }
145
-
146
- return canRecord;
147
- };
148
-
149
- this.checkRecordingCapabilities = function () {
150
- let err;
151
-
152
- if (!isHTTPS) {
153
- err = VideomailError.create(
154
- {
155
- message: "Sorry, your page is insecure",
156
- },
157
- "Please switch to HTTPS to ensure all is encrypted.",
158
- options,
159
- {
160
- classList: [VideomailError.BROWSER_PROBLEM],
161
- },
162
- );
163
- } else if (!okBrowser || !this.canRecord()) {
164
- const classList = [];
165
-
166
- if (isBadIOS) {
167
- classList.push(VideomailError.IOS_PROBLEM);
168
- } else {
169
- classList.push(VideomailError.BROWSER_PROBLEM);
170
- }
171
-
172
- let message;
173
-
174
- // good to be able to distinguish between two reasons why and what sort of camera it is
175
- if (!okBrowser) {
176
- if (isMobile) {
177
- message = "Sorry, your browser is unable to use your mobile camera";
178
- } else {
179
- message = "Sorry, your browser is unable to use webcams";
180
- }
181
- } else if (isMobile) {
182
- if (isFacebook) {
183
- message = "Sorry, the Facebook app cannot record from your mobile camera";
184
- } else {
185
- message = "Sorry, your browser cannot record from your mobile camera";
186
- }
187
- } else {
188
- message = "Sorry, your browser cannot record from webcams";
189
- }
190
-
191
- if (isBadIOS) {
192
- /*
193
- * on older iPhones length of JSON is limited and breaking
194
- * so just don't report and ignore
195
- */
196
- options.reportErrors = false;
197
- }
198
-
199
- err = VideomailError.create(
200
- {
201
- message,
202
- },
203
- getUserMediaWarning(),
204
- options,
205
- {
206
- classList,
207
- },
208
- );
209
- }
210
-
211
- return err;
212
- };
213
-
214
- this.checkBufferTypes = function () {
215
- let err;
216
-
217
- if (typeof window === "undefined" || typeof window.atob === "undefined") {
218
- err = VideomailError.create("atob is not supported", options);
219
- } else if (typeof window.ArrayBuffer === "undefined") {
220
- err = VideomailError.create("ArrayBuffers are not supported", options);
221
- } else if (typeof window.Uint8Array === "undefined") {
222
- err = VideomailError.create("Uint8Arrays are not supported", options);
223
- }
224
-
225
- return err;
226
- };
227
-
228
- function canPlayType(video, type) {
229
- let canPlayType;
230
-
231
- if (video && video.canPlayType) {
232
- canPlayType = video.canPlayType(`video/${type}`);
233
- }
234
-
235
- // definitely cannot be played here
236
- if (canPlayType === "") {
237
- return false;
238
- }
239
-
240
- return canPlayType;
241
- }
242
-
243
- this.getVideoType = function (video) {
244
- if (!videoType && video) {
245
- if (canPlayType(video, "mp4")) {
246
- videoType = "mp4";
247
- } else if (canPlayType(video, "webm")) {
248
- videoType = "webm";
249
- }
250
- }
251
-
252
- if (videoType !== "webm" && videoType !== "mp4") {
253
- // we only support these two. anything else defaults to the fallback.
254
- videoType = FALLBACK_VIDEO_TYPE;
255
- }
256
-
257
- if (!videoType || videoType === "") {
258
- // just as a fallback
259
- videoType = FALLBACK_VIDEO_TYPE;
260
- }
261
-
262
- return videoType;
263
- };
264
-
265
- this.getNoAccessIssue = function () {
266
- const message = "Unable to access webcam";
267
- let explanation;
268
-
269
- if (this.isChromeBased()) {
270
- explanation = "Click on the allow button to grant access to your webcam.";
271
- } else if (this.isFirefox()) {
272
- explanation = "Please grant Firefox access to your webcam.";
273
- } else {
274
- explanation = "Your system does not let your browser access your webcam.";
275
- }
276
-
277
- return VideomailError.create(message, explanation, options);
278
- };
279
-
280
- this.isChromeBased = function () {
281
- return chromeBased;
282
- };
283
-
284
- this.isFirefox = function () {
285
- return firefox;
286
- };
287
-
288
- this.isEdge = function () {
289
- return isEdge;
290
- };
291
-
292
- this.isAndroid = function () {
293
- return isAndroid;
294
- };
295
-
296
- this.isMobile = function () {
297
- return uaParser.device.type === "mobile";
298
- };
299
-
300
- this.isOkSafari = function () {
301
- return isOkSafari;
302
- };
303
-
304
- this.isIOS = function () {
305
- return isIOS;
306
- };
307
-
308
- this.getUsefulData = function () {
309
- return {
310
- browser: uaParser.browser,
311
- device: uaParser.device,
312
- os: uaParser.os,
313
- engine: uaParser.engine,
314
- userAgent: ua,
315
- };
316
- };
317
- };
318
-
319
- export default Browser;
@@ -1,72 +0,0 @@
1
- import Browser from "./browser";
2
- import formatUtil from "format-util";
3
-
4
- export default function (localOptions = {}) {
5
- const browser = new Browser(localOptions);
6
- const logger = localOptions.logger || console;
7
- const containerId =
8
- (localOptions.selectors && localOptions.selectors.containerId) ||
9
- "undefined container id";
10
- const stack = [];
11
-
12
- function lifo(level, parameters) {
13
- const line = formatUtil(...parameters);
14
-
15
- if (stack.length > localOptions.logStackSize) {
16
- stack.pop();
17
- }
18
-
19
- stack.push(`[${level}] ${line}`);
20
-
21
- return line;
22
- }
23
-
24
- function addContainerId(firstArgument) {
25
- return `#${containerId} [${new Date().toLocaleTimeString()}] > ${firstArgument}`;
26
- }
27
-
28
- /*
29
- * workaround: since we cannot overwrite console.log without having the correct file and line number
30
- * we'll use groupCollapsed() and trace() instead to get these.
31
- */
32
- this.debug = function () {
33
- // always add it for better client error reports
34
- const args = [].slice.call(arguments, 0);
35
- args[0] = addContainerId(args[0]);
36
-
37
- const output = lifo("debug", args);
38
-
39
- if (localOptions.verbose) {
40
- if (browser.isFirefox()) {
41
- logger.debug(output);
42
- } else if (logger.groupCollapsed) {
43
- logger.groupCollapsed(output);
44
- logger.trace("Trace");
45
- logger.groupEnd();
46
- } else if (logger.debug) {
47
- logger.debug(output);
48
- } else {
49
- // last resort if everything else fails for any weird reasons
50
- console.log(output);
51
- }
52
- }
53
- };
54
-
55
- this.error = function () {
56
- const args = [].slice.call(arguments, 0);
57
- args[0] = addContainerId(args[0]);
58
-
59
- logger.error(lifo("error", args));
60
- };
61
-
62
- this.warn = function () {
63
- const args = [].slice.call(arguments, 0);
64
- args[0] = addContainerId(args[0]);
65
-
66
- logger.warn(lifo("warn", args));
67
- };
68
-
69
- this.getLines = function () {
70
- return stack;
71
- };
72
- }
@@ -1,72 +0,0 @@
1
- import despot from "despot";
2
- import stringify from "safe-json-stringify";
3
-
4
- import VideomailError from "./videomailError";
5
- import Events from "./../events";
6
-
7
- // TODO: MAKE EVENT EMITTING IN DESPOT NOT GLOBAL BUT BY CONTAINER ID INSTEAD
8
-
9
- export default function (options, name) {
10
- this.emit = function (event) {
11
- const args = Array.prototype.slice.call(arguments, 0);
12
-
13
- if (!event) {
14
- throw VideomailError.create("You cannot emit without an event.", options);
15
- }
16
-
17
- // Automatically convert errors to videomail errors
18
- if (event === Events.ERROR) {
19
- let err = args[1];
20
-
21
- err = VideomailError.create(err, options);
22
-
23
- args[1] = err;
24
- }
25
-
26
- if (options.debug) {
27
- if (event !== "removeListener" && event !== "newListener") {
28
- let moreArguments;
29
-
30
- if (args[1]) {
31
- moreArguments = args.slice(1);
32
- }
33
-
34
- if (moreArguments) {
35
- options.debug("%s emits: %s", name, event, stringify(moreArguments));
36
- } else {
37
- options.debug("%s emits: %s", name, event);
38
- }
39
- }
40
- }
41
-
42
- const result = despot.emit.apply(despot, args);
43
-
44
- /*
45
- * Todo: have this emitted through a configuration because it is pretty noisy
46
- * if (event !== Events.EVENT_EMITTED)
47
- * this.emit(Events.EVENT_EMITTED, event)
48
- */
49
-
50
- return result;
51
- };
52
-
53
- this.on = function (eventName, cb) {
54
- return despot.on(eventName, cb);
55
- };
56
-
57
- this.once = function (eventName, cb) {
58
- return despot.once(eventName, cb);
59
- };
60
-
61
- this.listeners = function (eventName) {
62
- return despot.listeners(eventName);
63
- };
64
-
65
- this.removeListener = function (eventName, cb) {
66
- return despot.removeListener(eventName, cb);
67
- };
68
-
69
- this.removeAllListeners = function () {
70
- despot.removeAllListeners();
71
- };
72
- }
@@ -1,16 +0,0 @@
1
- import { filesize } from "filesize";
2
- import humanizeDuration from "humanize-duration";
3
-
4
- // todo get rid of this class and use those imports directly
5
-
6
- export default {
7
- filesize(bytes, round) {
8
- return filesize(bytes, {
9
- round,
10
- });
11
- },
12
-
13
- toTime(t) {
14
- return humanizeDuration(t);
15
- },
16
- };