videomail-client 8.3.1 → 8.3.2

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 +12 -14
  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,149 +0,0 @@
1
- import numberIsInteger from "number-is-integer";
2
-
3
- import VideomailError from "./../util/videomailError";
4
-
5
- function getOuterWidth(element) {
6
- let outerWidth = 0;
7
- let rect = element.getBoundingClientRect();
8
-
9
- if (rect) {
10
- outerWidth = rect.right - rect.left;
11
- }
12
-
13
- if (outerWidth < 1) {
14
- // last effort, can happen when replaying only
15
- rect = document.body.getBoundingClientRect();
16
- outerWidth = rect.right - rect.left;
17
- }
18
-
19
- return outerWidth;
20
- }
21
-
22
- function figureMinHeight(height, options) {
23
- if (options.hasDefinedHeight()) {
24
- if (!height) {
25
- height = options.video.height;
26
- } else {
27
- height = Math.min(options.video.height, height);
28
- }
29
- }
30
-
31
- if (numberIsInteger(height) && height < 1) {
32
- throw VideomailError.create(
33
- `Got a video height less than 1 (${height}) while figuring out the minimum!`,
34
- options,
35
- );
36
- }
37
-
38
- // just return it, can be "auto"
39
- return height;
40
- }
41
-
42
- export default {
43
- limitWidth(element, width, options) {
44
- let limitedWidth;
45
-
46
- const outerWidth = getOuterWidth(element);
47
-
48
- if (width) {
49
- // only when that element has a defined width, apply this logic
50
- limitedWidth = outerWidth > 0 && outerWidth < width ? outerWidth : width;
51
- } else {
52
- // else apply the outer width when the element has no defined width yet
53
- limitedWidth = outerWidth;
54
- }
55
-
56
- if (numberIsInteger(limitedWidth) && limitedWidth < 1) {
57
- throw VideomailError.create("Limited width cannot be less than 1!", options);
58
- } else {
59
- return limitedWidth;
60
- }
61
- },
62
-
63
- /*
64
- * this is difficult to compute and is not entirely correct.
65
- * but good enough for now to ensure some stability.
66
- */
67
- limitHeight(height, options) {
68
- if (numberIsInteger(height) && height < 1) {
69
- throw VideomailError.create(
70
- "Passed limit-height argument cannot be less than 1!",
71
- options,
72
- );
73
- } else {
74
- const limitedHeight = Math.min(
75
- height,
76
- // document.body.scrollHeight,
77
- document.documentElement.clientHeight,
78
- );
79
-
80
- if (limitedHeight < 1) {
81
- throw VideomailError.create("Limited height cannot be less than 1!", options);
82
- } else {
83
- return limitedHeight;
84
- }
85
- }
86
- },
87
-
88
- calculateWidth(options) {
89
- let height = options.videoHeight || null;
90
- const ratio = options.ratio || options.getRatio();
91
-
92
- height = figureMinHeight(height, options);
93
-
94
- if (options.responsive) {
95
- height = this.limitHeight(height, options);
96
- }
97
-
98
- if (numberIsInteger(height) && height < 1) {
99
- throw VideomailError.create(
100
- "Height cannot be smaller than 1 when calculating width.",
101
- options,
102
- );
103
- } else {
104
- const calculatedWidth = parseInt(height / ratio);
105
-
106
- if (calculatedWidth < 1) {
107
- throw VideomailError.create(
108
- "Calculated width cannot be smaller than 1!",
109
- options,
110
- );
111
- } else {
112
- return calculatedWidth;
113
- }
114
- }
115
- },
116
-
117
- calculateHeight(element, options) {
118
- let width = options.videoWidth || null;
119
- let height;
120
-
121
- const ratio = options.ratio || options.getRatio();
122
-
123
- if (options.hasDefinedWidth()) {
124
- width = options.video.width;
125
- }
126
-
127
- if (numberIsInteger(width) && width < 1) {
128
- throw VideomailError.create(
129
- "Unable to calculate height when width is less than 1.",
130
- options,
131
- );
132
- } else if (options.responsive) {
133
- width = this.limitWidth(element, width, options);
134
- }
135
-
136
- if (width) {
137
- height = parseInt(width * ratio);
138
- }
139
-
140
- if (numberIsInteger(height) && height < 1) {
141
- throw VideomailError.create(
142
- "Just calculated a height less than 1 which is wrong.",
143
- options,
144
- );
145
- } else {
146
- return figureMinHeight(height, options);
147
- }
148
- },
149
- };
@@ -1,319 +0,0 @@
1
- import getFormData from "get-form-data";
2
- import hidden from "hidden";
3
- import h from "hyperscript";
4
- import inherits from "inherits";
5
-
6
- import Events from "../events";
7
- import EventEmitter from "../util/eventEmitter";
8
- import VideomailError from "../util/videomailError";
9
-
10
- // fixes https://github.com/binarykitchen/videomail-client/issues/71
11
- function trimEmail(email) {
12
- return email.replace(/(^[,\s]+)|([,\s]+$)/g, "");
13
- }
14
-
15
- const Form = function (container, formElement, options) {
16
- EventEmitter.call(this, options, "Form");
17
-
18
- const self = this;
19
-
20
- let keyInput;
21
-
22
- function getData() {
23
- return getFormData(formElement, { includeDisabled: true });
24
- }
25
-
26
- this.transformFormData = function (formData) {
27
- const FORM_FIELDS = {
28
- subject: options.selectors.subjectInputName,
29
- from: options.selectors.fromInputName,
30
- to: options.selectors.toInputName,
31
- cc: options.selectors.ccInputName,
32
- bcc: options.selectors.bccInputName,
33
- body: options.selectors.bodyInputName,
34
- key: options.selectors.keyInputName,
35
- parentKey: options.selectors.parentKeyInputName,
36
- sendCopy: options.selectors.sendCopyInputName,
37
- };
38
-
39
- const transformedFormData = {};
40
-
41
- Object.keys(FORM_FIELDS).forEach(function (key) {
42
- const formFieldValue = FORM_FIELDS[key];
43
-
44
- if (formFieldValue in formData) {
45
- transformedFormData[key] = formData[formFieldValue];
46
- }
47
- });
48
-
49
- if (transformedFormData.from) {
50
- transformedFormData.from = trimEmail(transformedFormData.from);
51
- }
52
-
53
- if (transformedFormData.to) {
54
- transformedFormData.to = trimEmail(transformedFormData.to);
55
- }
56
-
57
- if (transformedFormData.cc) {
58
- transformedFormData.cc = trimEmail(transformedFormData.cc);
59
- }
60
-
61
- if (transformedFormData.bcc) {
62
- transformedFormData.bcc = trimEmail(transformedFormData.bcc);
63
- }
64
-
65
- return transformedFormData;
66
- };
67
-
68
- this.getRecipients = function () {
69
- const videomailFormData = this.transformFormData(getData());
70
-
71
- const recipients = {};
72
-
73
- if ("to" in videomailFormData) {
74
- recipients.to = videomailFormData.to;
75
- }
76
-
77
- if ("cc" in videomailFormData) {
78
- recipients.cc = videomailFormData.cc;
79
- }
80
-
81
- if ("bcc" in videomailFormData) {
82
- recipients.bcc = videomailFormData.bcc;
83
- }
84
-
85
- return recipients;
86
- };
87
-
88
- this.loadVideomail = function (videomail) {
89
- const limit = formElement.elements.length;
90
-
91
- let input;
92
- let name;
93
-
94
- for (let i = 0; i < limit; i++) {
95
- input = formElement.elements[i];
96
- name = input.name;
97
-
98
- if (videomail[name]) {
99
- input.value = videomail[name];
100
- }
101
-
102
- if (
103
- name === options.selectors.subjectInputName ||
104
- name === options.selectors.bodyInputName
105
- ) {
106
- input.disabled = true;
107
- }
108
- }
109
-
110
- formElement.setAttribute("method", "put");
111
- };
112
-
113
- function isNotButton(element) {
114
- return element.tagName !== "BUTTON" && element.type !== "submit";
115
- }
116
-
117
- function setDisabled(disabled, buttonsToo) {
118
- const limit = formElement.elements.length;
119
-
120
- for (let i = 0; i < limit; i++) {
121
- if (buttonsToo || (!buttonsToo && isNotButton(formElement.elements[i]))) {
122
- formElement.elements[i].disabled = disabled;
123
- }
124
- }
125
- }
126
-
127
- function hideAll() {
128
- const limit = formElement.elements.length;
129
-
130
- for (let i = 0; i < limit; i++) {
131
- hidden(formElement.elements[i], true);
132
- }
133
-
134
- hidden(formElement, true);
135
- }
136
-
137
- function getInputElements() {
138
- return formElement.querySelectorAll("input, textarea");
139
- }
140
-
141
- function getSelectElements() {
142
- return formElement.querySelectorAll("select");
143
- }
144
-
145
- this.disable = function (buttonsToo) {
146
- setDisabled(true, buttonsToo);
147
- };
148
-
149
- this.enable = function (buttonsToo) {
150
- setDisabled(false, buttonsToo);
151
- };
152
-
153
- this.build = function () {
154
- if (options.enableAutoValidation) {
155
- const inputElements = getInputElements();
156
- let inputElement;
157
-
158
- for (let i = 0, len = inputElements.length; i < len; i++) {
159
- inputElement = inputElements[i];
160
-
161
- if (inputElement.type === "radio") {
162
- inputElement.addEventListener("change", function () {
163
- container.validate();
164
- });
165
- } else {
166
- inputElement.addEventListener("input", function () {
167
- // let angular validate first, e.g. remove the custom error
168
- setTimeout(function () {
169
- container.validate();
170
- }, 0);
171
- });
172
- }
173
- }
174
-
175
- const selectElements = getSelectElements();
176
-
177
- for (let j = 0, len2 = selectElements.length; j < len2; j++) {
178
- selectElements[j].addEventListener("change", function () {
179
- container.validate();
180
- });
181
- }
182
- }
183
-
184
- keyInput = formElement.querySelector(
185
- `input[name="${options.selectors.keyInputName}"]`,
186
- );
187
-
188
- if (!keyInput) {
189
- keyInput = h("input", {
190
- name: options.selectors.keyInputName,
191
- type: "hidden",
192
- });
193
-
194
- formElement.appendChild(keyInput);
195
- }
196
-
197
- this.on(Events.PREVIEW, function (videomailKey) {
198
- /*
199
- * beware that preview doesn't always come with a key, i.E.
200
- * container.show() can emit PREVIEW without a key when a replay already exists
201
- * (can happen when showing - hiding - showing videomail over again)
202
- */
203
-
204
- // only emit error if key is missing AND the input has no key (value) yet
205
- if (!videomailKey && !keyInput.value) {
206
- self.emit(
207
- Events.ERROR,
208
- VideomailError.create("Videomail key for preview is missing!", options),
209
- );
210
- } else if (videomailKey) {
211
- keyInput.value = videomailKey;
212
- }
213
- /*
214
- * else
215
- * leave as it and use existing keyInput.value
216
- */
217
- });
218
-
219
- // fixes https://github.com/binarykitchen/videomail-client/issues/91
220
- this.on(Events.GOING_BACK, () => {
221
- keyInput.value = null;
222
- });
223
-
224
- this.on(Events.ERROR, function (err) {
225
- /*
226
- * since https://github.com/binarykitchen/videomail-client/issues/60
227
- * we hide areas to make it easier for the user to process an error
228
- * (= less distractions)
229
- */
230
- if (err.hideForm && err.hideForm() && options.adjustFormOnBrowserError) {
231
- hideAll();
232
- } else if (
233
- err.hideButtons &&
234
- err.hideButtons() &&
235
- options.adjustFormOnBrowserError
236
- ) {
237
- hideSubmitButton();
238
- }
239
- });
240
-
241
- this.on(Events.BUILT, function () {
242
- startListeningToSubmitEvents();
243
- });
244
- };
245
-
246
- function hideSubmitButton() {
247
- const submitButton = self.findSubmitButton();
248
- hidden(submitButton, true);
249
- }
250
-
251
- function startListeningToSubmitEvents() {
252
- const submitButton = container.getSubmitButton();
253
- submitButton.addEventListener("click", self.doTheSubmit.bind(self));
254
- }
255
-
256
- this.doTheSubmit = (e) => {
257
- if (e) {
258
- e.preventDefault();
259
- }
260
-
261
- /*
262
- * only submit when there is a container,
263
- * otherwise do nothing and leave as it
264
- */
265
- if (container.hasElement()) {
266
- container.submitAll(
267
- getData(),
268
- formElement.getAttribute("method"),
269
- formElement.getAttribute("action"),
270
- );
271
- }
272
-
273
- return false; // important to stop submission
274
- };
275
-
276
- this.getInvalidElement = () => {
277
- const inputElements = getInputElements();
278
- let i = 0;
279
-
280
- for (const len = inputElements.length; i < len; i++) {
281
- if (!inputElements[i].validity.valid) {
282
- return inputElements[i];
283
- }
284
- }
285
-
286
- const selectElements = getSelectElements();
287
- let j = 0;
288
-
289
- for (const len2 = selectElements.length; j < len2; j++) {
290
- if (!selectElements[j].validity.valid) {
291
- return selectElements[j];
292
- }
293
- }
294
-
295
- return null;
296
- };
297
-
298
- this.validate = function () {
299
- const formIsValid = formElement.checkValidity();
300
-
301
- return formIsValid;
302
- };
303
-
304
- this.findSubmitButton = function () {
305
- return formElement.querySelector("[type='submit']");
306
- };
307
-
308
- this.hide = function () {
309
- formElement && hidden(formElement, true);
310
- };
311
-
312
- this.show = function () {
313
- formElement && hidden(formElement, false);
314
- };
315
- };
316
-
317
- inherits(Form, EventEmitter);
318
-
319
- export default Form;
@@ -1,81 +0,0 @@
1
- // enhances options with useful functions we can reuse everywhere
2
- import deepmerge from "deepmerge";
3
-
4
- export default {
5
- addFunctions(options) {
6
- let audioEnabled = options.audio && options.audio.enabled;
7
-
8
- options.hasDefinedHeight = function () {
9
- return this.video.height && this.video.height !== "auto";
10
- };
11
-
12
- options.hasDefinedWidth = function () {
13
- return this.video.width && this.video.width !== "auto";
14
- };
15
-
16
- options.hasDefinedDimension = function () {
17
- return this.hasDefinedWidth() || this.hasDefinedHeight();
18
- };
19
-
20
- options.hasDefinedDimensions = function () {
21
- return this.hasDefinedWidth() && this.hasDefinedHeight();
22
- };
23
-
24
- options.getRatio = function () {
25
- let ratio = 1; // just a default one when no computations are possible
26
-
27
- // todo fix this, it's not really an option
28
- const hasVideoDimensions = this.videoHeight && this.videoWidth;
29
-
30
- if (this.hasDefinedDimensions()) {
31
- if (hasVideoDimensions) {
32
- // figure out first which one to pick
33
- if (
34
- this.videoHeight < this.video.height ||
35
- this.videoWidth < this.video.width
36
- ) {
37
- ratio = this.videoHeight / this.videoWidth;
38
- } else {
39
- ratio = this.video.height / this.video.width;
40
- }
41
- } else {
42
- ratio = this.video.height / this.video.width;
43
- }
44
- } else if (hasVideoDimensions) {
45
- ratio = this.videoHeight / this.videoWidth;
46
- }
47
-
48
- return ratio;
49
- };
50
-
51
- options.isAudioEnabled = function () {
52
- return audioEnabled;
53
- };
54
-
55
- options.setAudioEnabled = function (enabled) {
56
- audioEnabled = enabled;
57
- };
58
-
59
- options.isAutoPauseEnabled = function () {
60
- return this.enableAutoPause && this.enablePause;
61
- };
62
- },
63
-
64
- /*
65
- * not very elegant but works! and if you here are reading this, and
66
- * start to doubt, rest assured, it's solid and run thousand times over
67
- * and over again each day. and other large sites out there have their own
68
- * tech debts. hope i have shattered your illusion on perfection?
69
- */
70
- merge(defaultOptions, newOptions) {
71
- const options = deepmerge(defaultOptions, newOptions, {
72
- arrayMerge(destination, source) {
73
- return source;
74
- },
75
- });
76
-
77
- this.addFunctions(options);
78
-
79
- return options;
80
- },
81
- };
@@ -1,83 +0,0 @@
1
- import h from "hyperscript";
2
- import hidden from "hidden";
3
-
4
- export default function (visuals, options) {
5
- const self = this;
6
-
7
- let countdownElement;
8
- let intervalId;
9
- let countdown;
10
- let paused;
11
-
12
- function fire(cb) {
13
- self.unload();
14
- self.hide();
15
-
16
- // keep all callbacks async
17
- setTimeout(function () {
18
- cb();
19
- }, 0);
20
- }
21
-
22
- function countBackward(cb) {
23
- if (!paused) {
24
- options.debug("Countdown", countdown);
25
- countdown--;
26
-
27
- if (countdown < 1) {
28
- fire(cb);
29
- } else {
30
- countdownElement.innerHTML = countdown;
31
- }
32
- }
33
- }
34
-
35
- this.start = function (cb) {
36
- countdownElement.innerHTML = countdown = options.video.countdown;
37
-
38
- this.show();
39
-
40
- intervalId = setInterval(countBackward.bind(this, cb), 950);
41
- };
42
-
43
- this.pause = function () {
44
- paused = true;
45
- };
46
-
47
- this.resume = function () {
48
- paused = false;
49
- };
50
-
51
- this.build = function () {
52
- countdownElement = visuals.querySelector(".countdown");
53
-
54
- if (!countdownElement) {
55
- countdownElement = h("p.countdown");
56
-
57
- this.hide();
58
-
59
- visuals.appendChild(countdownElement);
60
- } else {
61
- this.hide();
62
- }
63
- };
64
-
65
- this.show = function () {
66
- hidden(countdownElement, false);
67
- };
68
-
69
- this.isCountingDown = function () {
70
- return Boolean(intervalId);
71
- };
72
-
73
- this.unload = function () {
74
- clearInterval(intervalId);
75
- paused = false;
76
- intervalId = null;
77
- };
78
-
79
- this.hide = function () {
80
- hidden(countdownElement, true);
81
- this.unload();
82
- };
83
- }
@@ -1,53 +0,0 @@
1
- import h from "hyperscript";
2
- import hidden from "hidden";
3
-
4
- import Events from "./../../../../events";
5
- import EventEmitter from "./../../../../util/eventEmitter";
6
-
7
- export default function (visuals, options) {
8
- EventEmitter.call(this, options, "Facing Mode");
9
-
10
- const self = this;
11
- let facingModeElement;
12
-
13
- function initEvents() {
14
- self.on(Events.ERROR, function () {
15
- self.hide();
16
- });
17
- }
18
-
19
- this.build = function () {
20
- facingModeElement = visuals.querySelector(".facingMode");
21
-
22
- if (!facingModeElement) {
23
- facingModeElement = h("button.facingMode");
24
- facingModeElement.innerHTML = "⤾";
25
-
26
- facingModeElement.onclick = (e) => {
27
- e && e.preventDefault();
28
-
29
- try {
30
- self.emit(Events.SWITCH_FACING_MODE);
31
- } catch (exc) {
32
- self.emit(Events.ERROR, exc);
33
- }
34
- };
35
-
36
- this.hide();
37
-
38
- visuals.appendChild(facingModeElement);
39
- } else {
40
- this.hide();
41
- }
42
-
43
- initEvents();
44
- };
45
-
46
- this.hide = function () {
47
- hidden(facingModeElement, true);
48
- };
49
-
50
- this.show = function () {
51
- hidden(facingModeElement, false);
52
- };
53
- }