@es-joy/jsoe 0.8.1 → 0.10.0

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.
@@ -1,5 +1,6 @@
1
1
  import {jml} from '../vendor-imports.js';
2
2
  import {$e} from '../utils/templateUtils.js';
3
+ import {visualize, getUserMedia, startScreenCapture} from '../utils/media.js';
3
4
  import dialogs from '../utils/dialogs.js';
4
5
 
5
6
  /**
@@ -13,107 +14,6 @@ import dialogs from '../utils/dialogs.js';
13
14
  * @typedef {(file: FileInfo) => void} SetValue
14
15
  */
15
16
 
16
- /** @type {AudioContext} */
17
- let audioCtx;
18
- /**
19
- * @param {MediaStream} stream
20
- * @param {HTMLCanvasElement} canvas
21
- * @see Adapted from {@link https://mdn.github.io/dom-examples/media/web-dictaphone/}
22
- * @returns {void}
23
- */
24
- function visualize (stream, canvas) {
25
- if (!audioCtx) {
26
- audioCtx = new AudioContext();
27
- }
28
- const canvasCtx = /** @type {CanvasRenderingContext2D} */ (
29
- canvas.getContext('2d')
30
- );
31
-
32
- const source = audioCtx.createMediaStreamSource(stream);
33
-
34
- const analyser = audioCtx.createAnalyser();
35
- analyser.fftSize = 2048;
36
- const bufferLength = analyser.frequencyBinCount;
37
- const dataArray = new Uint8Array(bufferLength);
38
-
39
- source.connect(analyser);
40
- // analyser.connect(audioCtx.destination);
41
-
42
- draw();
43
-
44
- /**
45
- * @returns {void}
46
- */
47
- function draw () {
48
- const WIDTH = canvas.width;
49
- const HEIGHT = canvas.height;
50
-
51
- requestAnimationFrame(draw);
52
-
53
- analyser.getByteTimeDomainData(dataArray);
54
-
55
- canvasCtx.fillStyle = 'rgb(200, 200, 200)';
56
- canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
57
-
58
- canvasCtx.lineWidth = 2;
59
- canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
60
-
61
- canvasCtx.beginPath();
62
-
63
- const sliceWidth = WIDTH * 1 / bufferLength;
64
- let x = 0;
65
-
66
- for (let i = 0; i < bufferLength; i++) {
67
- const v = dataArray[i] / 128;
68
- const y = v * HEIGHT / 2;
69
-
70
- if (i === 0) {
71
- canvasCtx.moveTo(x, y);
72
- } else {
73
- canvasCtx.lineTo(x, y);
74
- }
75
-
76
- x += sliceWidth;
77
- }
78
-
79
- canvasCtx.lineTo(canvas.width, canvas.height / 2);
80
- canvasCtx.stroke();
81
- }
82
- }
83
-
84
- /**
85
- * @param {MediaStreamConstraints} constraints
86
- * @returns {Promise<MediaStream|null>}
87
- */
88
- async function getUserMedia (constraints) {
89
- let stream = null;
90
- try {
91
- stream = await navigator.mediaDevices.getUserMedia(constraints);
92
- /* c8 ignore next 4 */
93
- } catch (err) {
94
- console.error('err', err);
95
- return null;
96
- }
97
- return stream;
98
- }
99
-
100
- /**
101
- * @param {DisplayMediaStreamOptions|undefined} displayMediaOptions
102
- * @returns {Promise<MediaStream|null>}
103
- */
104
- async function startScreenCapture (displayMediaOptions) {
105
- let captureStream = null;
106
-
107
- try {
108
- captureStream =
109
- await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
110
- /* c8 ignore next 3 */
111
- } catch (err) {
112
- console.error(`Error: ${err}`);
113
- }
114
- return captureStream;
115
- }
116
-
117
17
  /**
118
18
  * @param {number} timestamp
119
19
  * @returns {string}
@@ -0,0 +1,35 @@
1
+ import arrayType from './arrayType.js';
2
+
3
+ /**
4
+ * @type {import('../types.js').TypeObject}
5
+ */
6
+ const filelistType = {
7
+ option: ['FileList'],
8
+ array: true,
9
+ filelist: true,
10
+ regexEndings: [',', ')'],
11
+ stringRegexBegin: /^FileList\(/u,
12
+ stringRegexEnd: /^\)/u,
13
+
14
+ toValue (...args) {
15
+ return arrayType.toValue.apply(this, args);
16
+ },
17
+ getValue (...args) {
18
+ return arrayType.getValue.apply(this, args);
19
+ },
20
+ getInput (...args) {
21
+ return arrayType.getInput.apply(this, args);
22
+ },
23
+ viewUI ({...args}) {
24
+ return arrayType.viewUI.call(this, {
25
+ ...args, type: 'filelist'
26
+ });
27
+ },
28
+ editUI ({...args}) {
29
+ return arrayType.editUI.call(this, {
30
+ ...args, type: 'filelist'
31
+ });
32
+ }
33
+ };
34
+
35
+ export default filelistType;
package/src/jsoe.css CHANGED
@@ -97,6 +97,14 @@ video.recordedMedia {
97
97
  background-color: beige;
98
98
  }
99
99
 
100
+ [data-type="filelist"] {
101
+ background-color: bisque;
102
+ }
103
+
104
+ [data-type="blob"] {
105
+ background-color: lightgray;
106
+ }
107
+
100
108
  [class^="propertyName-"] {
101
109
  background-color: yellow;
102
110
  }
package/src/types.js CHANGED
@@ -35,6 +35,8 @@ import SpecialNumberSuperType from './superTypes/SpecialNumberType.js';
35
35
  import errorType from './fundamentalTypes/errorType.js';
36
36
  import errorsSpecialType from './superTypes/errorsSpecialType.js';
37
37
  import fileType from './fundamentalTypes/fileType.js';
38
+ import filelistType from './fundamentalTypes/filelistType.js';
39
+ import blobType from './fundamentalTypes/blobType.js';
38
40
 
39
41
  /**
40
42
  * Utility to retrieve the property value given a legend element.
@@ -269,9 +271,11 @@ const Types = {};
269
271
  * @property {boolean} [array] Private context variable. Whether or not
270
272
  * it is an array. Do not use in other types.
271
273
  * @property {boolean} [map] Private context variable. Whether or not
272
- * it is a Map. Do not use in other types.
274
+ * it is a `Map`. Do not use in other types.
273
275
  * @property {boolean} [set] Private context variable. Whether or not
274
- * it is a set. Do not use in other types.
276
+ * it is a `Set`. Do not use in other types.
277
+ * @property {boolean} [filelist] Private context variable. Whether or not
278
+ * it is a `FileList` type. Do not use in other types.
275
279
  * @property {boolean} [sparse] Private context variable. Whether or not
276
280
  * it is a sparse array. Do not use in other types.
277
281
  * @property {boolean} [valid] Private context variable. Whether or not
@@ -385,9 +389,8 @@ Types.availableTypes = {
385
389
  set: setType,
386
390
 
387
391
  file: fileType,
388
- filelist: {
389
- option: ['FileList']
390
- },
392
+ filelist: filelistType,
393
+ blob: blobType,
391
394
  blobHTML: blobHTMLType,
392
395
  arraybuffer: {
393
396
  option: ['ArrayBuffer']
@@ -470,7 +473,7 @@ Types.availableTypes = {
470
473
  * "int8array"|"uint8array"|"uint8clampedarray"|"int16array"|"uint16array"|
471
474
  * "int32array"|"uint32array"|"float32array"|"float64array"|"IntlCollator"|
472
475
  * "IntlDateTimeFormat"|"IntlNumberFormat"|"ValidDate"|
473
- * "arrayNonindexKeys"|"error"|"errors"} AvailableType
476
+ * "arrayNonindexKeys"|"error"|"errors"|"blob"} AvailableType
474
477
  */
475
478
 
476
479
  /**
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @typedef {number} Integer
3
+ */
4
+ /**
5
+ * `FileList` polyfill.
6
+ */
7
+ class FileList {
8
+ /**
9
+ * Set private properties and length.
10
+ */
11
+ constructor () {
12
+ // eslint-disable-next-line prefer-rest-params
13
+ this._files = arguments[0];
14
+ this.length = this._files.length;
15
+ }
16
+ /**
17
+ * @param {Integer} index
18
+ * @returns {File}
19
+ */
20
+ item (index) {
21
+ return this._files[index];
22
+ }
23
+ /* eslint-disable class-methods-use-this */
24
+ /**
25
+ * @returns {"FileList"}
26
+ */
27
+ get [Symbol.toStringTag] () {
28
+ /* eslint-enable class-methods-use-this */
29
+ return 'FileList';
30
+ }
31
+ }
32
+ export default FileList;
@@ -0,0 +1,103 @@
1
+ /** @type {AudioContext} */
2
+ let audioCtx;
3
+ /**
4
+ * @param {MediaStream} stream
5
+ * @param {HTMLCanvasElement} canvas
6
+ * @see Adapted from {@link https://mdn.github.io/dom-examples/media/web-dictaphone/}
7
+ * @returns {void}
8
+ */
9
+ function visualize (stream, canvas) {
10
+ if (!audioCtx) {
11
+ audioCtx = new AudioContext();
12
+ }
13
+ const canvasCtx = /** @type {CanvasRenderingContext2D} */ (
14
+ canvas.getContext('2d')
15
+ );
16
+
17
+ const source = audioCtx.createMediaStreamSource(stream);
18
+
19
+ const analyser = audioCtx.createAnalyser();
20
+ analyser.fftSize = 2048;
21
+ const bufferLength = analyser.frequencyBinCount;
22
+ const dataArray = new Uint8Array(bufferLength);
23
+
24
+ source.connect(analyser);
25
+ // analyser.connect(audioCtx.destination);
26
+
27
+ draw();
28
+
29
+ /**
30
+ * @returns {void}
31
+ */
32
+ function draw () {
33
+ const WIDTH = canvas.width;
34
+ const HEIGHT = canvas.height;
35
+
36
+ requestAnimationFrame(draw);
37
+
38
+ analyser.getByteTimeDomainData(dataArray);
39
+
40
+ canvasCtx.fillStyle = 'rgb(200, 200, 200)';
41
+ canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
42
+
43
+ canvasCtx.lineWidth = 2;
44
+ canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
45
+
46
+ canvasCtx.beginPath();
47
+
48
+ const sliceWidth = WIDTH * 1 / bufferLength;
49
+ let x = 0;
50
+
51
+ for (let i = 0; i < bufferLength; i++) {
52
+ const v = dataArray[i] / 128;
53
+ const y = v * HEIGHT / 2;
54
+
55
+ if (i === 0) {
56
+ canvasCtx.moveTo(x, y);
57
+ } else {
58
+ canvasCtx.lineTo(x, y);
59
+ }
60
+
61
+ x += sliceWidth;
62
+ }
63
+
64
+ canvasCtx.lineTo(canvas.width, canvas.height / 2);
65
+ canvasCtx.stroke();
66
+ }
67
+ }
68
+
69
+
70
+ /**
71
+ * @param {MediaStreamConstraints} constraints
72
+ * @returns {Promise<MediaStream|null>}
73
+ */
74
+ async function getUserMedia (constraints) {
75
+ let stream = null;
76
+ try {
77
+ stream = await navigator.mediaDevices.getUserMedia(constraints);
78
+ /* c8 ignore next 4 */
79
+ } catch (err) {
80
+ console.error('err', err);
81
+ return null;
82
+ }
83
+ return stream;
84
+ }
85
+
86
+ /**
87
+ * @param {DisplayMediaStreamOptions|undefined} displayMediaOptions
88
+ * @returns {Promise<MediaStream|null>}
89
+ */
90
+ async function startScreenCapture (displayMediaOptions) {
91
+ let captureStream = null;
92
+
93
+ try {
94
+ captureStream =
95
+ await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
96
+ /* c8 ignore next 3 */
97
+ } catch (err) {
98
+ console.error(`Error: ${err}`);
99
+ }
100
+ return captureStream;
101
+ }
102
+
103
+ export {visualize, getUserMedia, startScreenCapture};