@webex/media-helpers 3.0.0-next.4 → 3.0.0-next.6

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,136 +1,136 @@
1
- /* eslint-disable @typescript-eslint/no-misused-new */
2
- /* eslint-disable valid-jsdoc */
3
- /* eslint-disable require-jsdoc */
4
- import {
5
- AudioDeviceConstraints,
6
- createCameraStream as wcmeCreateCameraStream,
7
- createDisplayStream as wcmeCreateDisplayStream,
8
- createDisplayStreamWithAudio as wcmeCreateDisplayStreamWithAudio,
9
- createMicrophoneStream as wcmeCreateMicrophoneStream,
10
- LocalDisplayStream,
11
- LocalSystemAudioStream,
12
- LocalMicrophoneStream as WcmeLocalMicrophoneStream,
13
- LocalCameraStream as WcmeLocalCameraStream,
14
- VideoDeviceConstraints,
15
- } from '@webex/internal-media-core';
16
- import {TypedEvent} from '@webex/ts-events';
17
-
18
- export {
19
- getDevices,
20
- LocalStream,
21
- LocalDisplayStream,
22
- LocalSystemAudioStream,
23
- LocalStreamEventNames,
24
- StreamEventNames,
25
- RemoteStream,
26
- } from '@webex/internal-media-core';
27
-
28
- export type ServerMuteReason =
29
- | 'remotelyMuted' // other user has remotely muted us
30
- | 'clientRequestFailed' // client called setMuted() but server request failed
31
- | 'localUnmuteRequired'; // server forced the client to be unmuted
32
-
33
- // these events are in addition to WCME events. This will be properly typed once webrtc-core event types inheritance is fixed
34
- export enum LocalMicrophoneStreamEventNames {
35
- ServerMuted = 'muted:byServer',
36
- }
37
-
38
- // these events are in addition to WCME events. This will be properly typed once webrtc-core event types inheritance is fixed
39
- export enum LocalCameraStreamEventNames {
40
- ServerMuted = 'muted:byServer',
41
- }
42
-
43
- export class LocalMicrophoneStream extends WcmeLocalMicrophoneStream {
44
- private unmuteAllowed = true;
45
-
46
- [LocalMicrophoneStreamEventNames.ServerMuted] = new TypedEvent<
47
- (muted: boolean, reason: ServerMuteReason) => void
48
- >();
49
-
50
- /**
51
- * @internal
52
- */
53
- setUnmuteAllowed(allowed) {
54
- this.unmuteAllowed = allowed;
55
- }
56
-
57
- /**
58
- * @returns true if user is allowed to unmute the Stream, false otherwise
59
- */
60
- isUnmuteAllowed() {
61
- return this.unmuteAllowed;
62
- }
63
-
64
- setMuted(muted: boolean): void {
65
- if (!muted) {
66
- if (!this.isUnmuteAllowed()) {
67
- throw new Error('Unmute is not allowed');
68
- }
69
- }
70
-
71
- return super.setMuted(muted);
72
- }
73
-
74
- /**
75
- * @internal
76
- */
77
- setServerMuted(muted: boolean, reason: ServerMuteReason) {
78
- if (muted !== this.muted) {
79
- this.setMuted(muted);
80
- this[LocalMicrophoneStreamEventNames.ServerMuted].emit(muted, reason);
81
- }
82
- }
83
- }
84
-
85
- export class LocalCameraStream extends WcmeLocalCameraStream {
86
- private unmuteAllowed = true;
87
-
88
- [LocalCameraStreamEventNames.ServerMuted] = new TypedEvent<
89
- (muted: boolean, reason: ServerMuteReason) => void
90
- >();
91
-
92
- /**
93
- * @internal
94
- */
95
- setUnmuteAllowed(allowed) {
96
- this.unmuteAllowed = allowed;
97
- }
98
-
99
- /**
100
- * @returns true if user is allowed to unmute the Stream, false otherwise
101
- */
102
- isUnmuteAllowed() {
103
- return this.unmuteAllowed;
104
- }
105
-
106
- setMuted(muted: boolean): void {
107
- if (!muted) {
108
- if (!this.isUnmuteAllowed()) {
109
- throw new Error('Unmute is not allowed');
110
- }
111
- }
112
-
113
- return super.setMuted(muted);
114
- }
115
-
116
- /**
117
- * @internal
118
- */
119
- setServerMuted(muted: boolean, reason: ServerMuteReason) {
120
- if (muted !== this.muted) {
121
- this.setMuted(muted);
122
- this[LocalCameraStreamEventNames.ServerMuted].emit(muted, reason);
123
- }
124
- }
125
- }
126
-
127
- export const createMicrophoneStream = (constraints?: AudioDeviceConstraints) =>
128
- wcmeCreateMicrophoneStream(LocalMicrophoneStream, constraints);
129
-
130
- export const createCameraStream = (constraints?: VideoDeviceConstraints) =>
131
- wcmeCreateCameraStream(LocalCameraStream, constraints);
132
-
133
- export const createDisplayStream = () => wcmeCreateDisplayStream(LocalDisplayStream);
134
-
135
- export const createDisplayStreamWithAudio = () =>
136
- wcmeCreateDisplayStreamWithAudio(LocalDisplayStream, LocalSystemAudioStream);
1
+ /* eslint-disable @typescript-eslint/no-misused-new */
2
+ /* eslint-disable valid-jsdoc */
3
+ /* eslint-disable require-jsdoc */
4
+ import {
5
+ AudioDeviceConstraints,
6
+ createCameraStream as wcmeCreateCameraStream,
7
+ createDisplayStream as wcmeCreateDisplayStream,
8
+ createDisplayStreamWithAudio as wcmeCreateDisplayStreamWithAudio,
9
+ createMicrophoneStream as wcmeCreateMicrophoneStream,
10
+ LocalDisplayStream,
11
+ LocalSystemAudioStream,
12
+ LocalMicrophoneStream as WcmeLocalMicrophoneStream,
13
+ LocalCameraStream as WcmeLocalCameraStream,
14
+ VideoDeviceConstraints,
15
+ } from '@webex/internal-media-core';
16
+ import {TypedEvent} from '@webex/ts-events';
17
+
18
+ export {
19
+ getDevices,
20
+ LocalStream,
21
+ LocalDisplayStream,
22
+ LocalSystemAudioStream,
23
+ LocalStreamEventNames,
24
+ StreamEventNames,
25
+ RemoteStream,
26
+ } from '@webex/internal-media-core';
27
+
28
+ export type ServerMuteReason =
29
+ | 'remotelyMuted' // other user has remotely muted us
30
+ | 'clientRequestFailed' // client called setMuted() but server request failed
31
+ | 'localUnmuteRequired'; // server forced the client to be unmuted
32
+
33
+ // these events are in addition to WCME events. This will be properly typed once webrtc-core event types inheritance is fixed
34
+ export enum LocalMicrophoneStreamEventNames {
35
+ ServerMuted = 'muted:byServer',
36
+ }
37
+
38
+ // these events are in addition to WCME events. This will be properly typed once webrtc-core event types inheritance is fixed
39
+ export enum LocalCameraStreamEventNames {
40
+ ServerMuted = 'muted:byServer',
41
+ }
42
+
43
+ export class LocalMicrophoneStream extends WcmeLocalMicrophoneStream {
44
+ private unmuteAllowed = true;
45
+
46
+ [LocalMicrophoneStreamEventNames.ServerMuted] = new TypedEvent<
47
+ (muted: boolean, reason: ServerMuteReason) => void
48
+ >();
49
+
50
+ /**
51
+ * @internal
52
+ */
53
+ setUnmuteAllowed(allowed) {
54
+ this.unmuteAllowed = allowed;
55
+ }
56
+
57
+ /**
58
+ * @returns true if user is allowed to unmute the Stream, false otherwise
59
+ */
60
+ isUnmuteAllowed() {
61
+ return this.unmuteAllowed;
62
+ }
63
+
64
+ setMuted(muted: boolean): void {
65
+ if (!muted) {
66
+ if (!this.isUnmuteAllowed()) {
67
+ throw new Error('Unmute is not allowed');
68
+ }
69
+ }
70
+
71
+ return super.setMuted(muted);
72
+ }
73
+
74
+ /**
75
+ * @internal
76
+ */
77
+ setServerMuted(muted: boolean, reason: ServerMuteReason) {
78
+ if (muted !== this.muted) {
79
+ this.setMuted(muted);
80
+ this[LocalMicrophoneStreamEventNames.ServerMuted].emit(muted, reason);
81
+ }
82
+ }
83
+ }
84
+
85
+ export class LocalCameraStream extends WcmeLocalCameraStream {
86
+ private unmuteAllowed = true;
87
+
88
+ [LocalCameraStreamEventNames.ServerMuted] = new TypedEvent<
89
+ (muted: boolean, reason: ServerMuteReason) => void
90
+ >();
91
+
92
+ /**
93
+ * @internal
94
+ */
95
+ setUnmuteAllowed(allowed) {
96
+ this.unmuteAllowed = allowed;
97
+ }
98
+
99
+ /**
100
+ * @returns true if user is allowed to unmute the Stream, false otherwise
101
+ */
102
+ isUnmuteAllowed() {
103
+ return this.unmuteAllowed;
104
+ }
105
+
106
+ setMuted(muted: boolean): void {
107
+ if (!muted) {
108
+ if (!this.isUnmuteAllowed()) {
109
+ throw new Error('Unmute is not allowed');
110
+ }
111
+ }
112
+
113
+ return super.setMuted(muted);
114
+ }
115
+
116
+ /**
117
+ * @internal
118
+ */
119
+ setServerMuted(muted: boolean, reason: ServerMuteReason) {
120
+ if (muted !== this.muted) {
121
+ this.setMuted(muted);
122
+ this[LocalCameraStreamEventNames.ServerMuted].emit(muted, reason);
123
+ }
124
+ }
125
+ }
126
+
127
+ export const createMicrophoneStream = (constraints?: AudioDeviceConstraints) =>
128
+ wcmeCreateMicrophoneStream(LocalMicrophoneStream, constraints);
129
+
130
+ export const createCameraStream = (constraints?: VideoDeviceConstraints) =>
131
+ wcmeCreateCameraStream(LocalCameraStream, constraints);
132
+
133
+ export const createDisplayStream = () => wcmeCreateDisplayStream(LocalDisplayStream);
134
+
135
+ export const createDisplayStreamWithAudio = () =>
136
+ wcmeCreateDisplayStreamWithAudio(LocalDisplayStream, LocalSystemAudioStream);
@@ -1,145 +1,145 @@
1
- import {assert, expect} from '@webex/test-helper-chai';
2
- import sinon from 'sinon';
3
- import {
4
- LocalCameraStream,
5
- LocalMicrophoneStream,
6
- LocalMicrophoneStreamEventNames,
7
- LocalCameraStreamEventNames,
8
- LocalDisplayStream,
9
- LocalSystemAudioStream,
10
- createCameraStream,
11
- createMicrophoneStream,
12
- createDisplayStream,
13
- createDisplayStreamWithAudio,
14
- } from '../../../src/webrtc-core';
15
- import * as wcmeStreams from '@webex/internal-media-core';
16
-
17
- describe('media-helpers', () => {
18
- describe('webrtc-core', () => {
19
- const classesToTest = [
20
- {
21
- className: LocalCameraStream,
22
- title: 'LocalCameraStream',
23
- event: LocalCameraStreamEventNames,
24
- createFn: createCameraStream,
25
- spyFn: 'createCameraStream',
26
- },
27
- {
28
- className: LocalMicrophoneStream,
29
- title: 'LocalMicrophoneStream',
30
- event: LocalMicrophoneStreamEventNames,
31
- createFn: createMicrophoneStream,
32
- spyFn: 'createMicrophoneStream',
33
- },
34
- ];
35
-
36
- classesToTest.forEach(({className, title, event, createFn, spyFn}) =>
37
- describe(title, () => {
38
- const fakeStream = {
39
- getStreams: sinon.stub().returns([
40
- {
41
- label: 'fake Stream',
42
- id: 'fake Stream id',
43
- enabled: true,
44
- },
45
- ]),
46
- };
47
- const stream = new className(fakeStream);
48
-
49
- afterEach(() => {
50
- sinon.restore();
51
- });
52
-
53
- it('by default allows unmuting', async () => {
54
- assert.equal(stream.isUnmuteAllowed(), true);
55
- await stream.setMuted(false);
56
- });
57
-
58
- it('rejects setMute(false) if unmute is not allowed', async () => {
59
- stream.setUnmuteAllowed(false);
60
-
61
- assert.equal(stream.isUnmuteAllowed(), false);
62
- const fn = () => stream.setMuted(false);
63
- expect(fn).to.throw(/Unmute is not allowed/);
64
- });
65
-
66
- it('resolves setMute(false) if unmute is allowed', async () => {
67
- stream.setUnmuteAllowed(true);
68
-
69
- assert.equal(stream.isUnmuteAllowed(), true);
70
- await stream.setMuted(false);
71
- });
72
-
73
- describe('#setServerMuted', () => {
74
- afterEach(() => {
75
- sinon.restore();
76
- });
77
-
78
- const checkSetServerMuted = async (startMute, setMute, expectedCalled) => {
79
- await stream.setMuted(startMute);
80
-
81
- assert.equal(stream.muted, startMute);
82
-
83
- const handler = sinon.fake();
84
- stream.on(event.ServerMuted, handler);
85
-
86
- await stream.setServerMuted(setMute, 'remotelyMuted');
87
-
88
- assert.equal(stream.muted, setMute);
89
- if (expectedCalled) {
90
- assert.calledOnceWithExactly(handler, {muted: setMute, reason: 'remotelyMuted'});
91
- } else {
92
- assert.notCalled(handler);
93
- }
94
- };
95
-
96
- it('tests true to false', async () => {
97
- await checkSetServerMuted(true, false, true);
98
- });
99
-
100
- it('tests false to true', async () => {
101
- await checkSetServerMuted(false, true, true);
102
- });
103
-
104
- it('tests true to true', async () => {
105
- await checkSetServerMuted(true, true, false);
106
- });
107
-
108
- it('tests false to false', async () => {
109
- await checkSetServerMuted(false, false, false);
110
- });
111
- });
112
-
113
- describe('#wcmeCreateMicrophoneStream, #wcmeCreateCameraStream', () => {
114
- it('checks creating Streams', async () => {
115
- const constraints = {devideId: 'abc'};
116
-
117
- const spy = sinon.stub(wcmeStreams, spyFn).returns('something');
118
- const result = createFn(constraints);
119
-
120
- assert.equal(result, 'something');
121
- assert.calledOnceWithExactly(spy, className, constraints);
122
- });
123
- });
124
- })
125
- );
126
-
127
- describe('createDisplayStream', () => {
128
- it('checks createDisplayStream', async () => {
129
- const spy = sinon.stub(wcmeStreams, 'createDisplayStream').returns('something');
130
- const result = createDisplayStream();
131
- assert.equal(result, 'something');
132
- assert.calledOnceWithExactly(spy, LocalDisplayStream);
133
- });
134
- });
135
-
136
- describe('createDisplayStreamWithAudio', () => {
137
- it('checks createDisplayStreamWithAudio', async () => {
138
- const spy = sinon.stub(wcmeStreams, 'createDisplayStreamWithAudio').returns('something');
139
- const result = createDisplayStreamWithAudio();
140
- assert.equal(result, 'something');
141
- assert.calledOnceWithExactly(spy, LocalDisplayStream, LocalSystemAudioStream);
142
- });
143
- });
144
- });
145
- });
1
+ import {assert, expect} from '@webex/test-helper-chai';
2
+ import sinon from 'sinon';
3
+ import {
4
+ LocalCameraStream,
5
+ LocalMicrophoneStream,
6
+ LocalMicrophoneStreamEventNames,
7
+ LocalCameraStreamEventNames,
8
+ LocalDisplayStream,
9
+ LocalSystemAudioStream,
10
+ createCameraStream,
11
+ createMicrophoneStream,
12
+ createDisplayStream,
13
+ createDisplayStreamWithAudio,
14
+ } from '../../../src/webrtc-core';
15
+ import * as wcmeStreams from '@webex/internal-media-core';
16
+
17
+ describe('media-helpers', () => {
18
+ describe('webrtc-core', () => {
19
+ const classesToTest = [
20
+ {
21
+ className: LocalCameraStream,
22
+ title: 'LocalCameraStream',
23
+ event: LocalCameraStreamEventNames,
24
+ createFn: createCameraStream,
25
+ spyFn: 'createCameraStream',
26
+ },
27
+ {
28
+ className: LocalMicrophoneStream,
29
+ title: 'LocalMicrophoneStream',
30
+ event: LocalMicrophoneStreamEventNames,
31
+ createFn: createMicrophoneStream,
32
+ spyFn: 'createMicrophoneStream',
33
+ },
34
+ ];
35
+
36
+ classesToTest.forEach(({className, title, event, createFn, spyFn}) =>
37
+ describe(title, () => {
38
+ const fakeStream = {
39
+ getStreams: sinon.stub().returns([
40
+ {
41
+ label: 'fake Stream',
42
+ id: 'fake Stream id',
43
+ enabled: true,
44
+ },
45
+ ]),
46
+ };
47
+ const stream = new className(fakeStream);
48
+
49
+ afterEach(() => {
50
+ sinon.restore();
51
+ });
52
+
53
+ it('by default allows unmuting', async () => {
54
+ assert.equal(stream.isUnmuteAllowed(), true);
55
+ await stream.setMuted(false);
56
+ });
57
+
58
+ it('rejects setMute(false) if unmute is not allowed', async () => {
59
+ stream.setUnmuteAllowed(false);
60
+
61
+ assert.equal(stream.isUnmuteAllowed(), false);
62
+ const fn = () => stream.setMuted(false);
63
+ expect(fn).to.throw(/Unmute is not allowed/);
64
+ });
65
+
66
+ it('resolves setMute(false) if unmute is allowed', async () => {
67
+ stream.setUnmuteAllowed(true);
68
+
69
+ assert.equal(stream.isUnmuteAllowed(), true);
70
+ await stream.setMuted(false);
71
+ });
72
+
73
+ describe('#setServerMuted', () => {
74
+ afterEach(() => {
75
+ sinon.restore();
76
+ });
77
+
78
+ const checkSetServerMuted = async (startMute, setMute, expectedCalled) => {
79
+ await stream.setMuted(startMute);
80
+
81
+ assert.equal(stream.muted, startMute);
82
+
83
+ const handler = sinon.fake();
84
+ stream.on(event.ServerMuted, handler);
85
+
86
+ await stream.setServerMuted(setMute, 'remotelyMuted');
87
+
88
+ assert.equal(stream.muted, setMute);
89
+ if (expectedCalled) {
90
+ assert.calledOnceWithExactly(handler, {muted: setMute, reason: 'remotelyMuted'});
91
+ } else {
92
+ assert.notCalled(handler);
93
+ }
94
+ };
95
+
96
+ it('tests true to false', async () => {
97
+ await checkSetServerMuted(true, false, true);
98
+ });
99
+
100
+ it('tests false to true', async () => {
101
+ await checkSetServerMuted(false, true, true);
102
+ });
103
+
104
+ it('tests true to true', async () => {
105
+ await checkSetServerMuted(true, true, false);
106
+ });
107
+
108
+ it('tests false to false', async () => {
109
+ await checkSetServerMuted(false, false, false);
110
+ });
111
+ });
112
+
113
+ describe('#wcmeCreateMicrophoneStream, #wcmeCreateCameraStream', () => {
114
+ it('checks creating Streams', async () => {
115
+ const constraints = {devideId: 'abc'};
116
+
117
+ const spy = sinon.stub(wcmeStreams, spyFn).returns('something');
118
+ const result = createFn(constraints);
119
+
120
+ assert.equal(result, 'something');
121
+ assert.calledOnceWithExactly(spy, className, constraints);
122
+ });
123
+ });
124
+ })
125
+ );
126
+
127
+ describe('createDisplayStream', () => {
128
+ it('checks createDisplayStream', async () => {
129
+ const spy = sinon.stub(wcmeStreams, 'createDisplayStream').returns('something');
130
+ const result = createDisplayStream();
131
+ assert.equal(result, 'something');
132
+ assert.calledOnceWithExactly(spy, LocalDisplayStream);
133
+ });
134
+ });
135
+
136
+ describe('createDisplayStreamWithAudio', () => {
137
+ it('checks createDisplayStreamWithAudio', async () => {
138
+ const spy = sinon.stub(wcmeStreams, 'createDisplayStreamWithAudio').returns('something');
139
+ const result = createDisplayStreamWithAudio();
140
+ assert.equal(result, 'something');
141
+ assert.calledOnceWithExactly(spy, LocalDisplayStream, LocalSystemAudioStream);
142
+ });
143
+ });
144
+ });
145
+ });
package/tsconfig.json CHANGED
@@ -1,6 +1,6 @@
1
- {
2
- "extends": "../../../tsconfig.json",
3
- "include": [
4
- "src"
5
- ],
1
+ {
2
+ "extends": "../../../tsconfig.json",
3
+ "include": [
4
+ "src"
5
+ ],
6
6
  }
package/dist/constants.js DELETED
@@ -1,59 +0,0 @@
1
- "use strict";
2
-
3
- var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
- _Object$defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.PresetCameraConstraints = exports.FacingMode = exports.DisplaySurface = void 0;
8
- var FacingMode; // can be used later on when we add constraints in create display track
9
- exports.FacingMode = FacingMode;
10
- (function (FacingMode) {
11
- FacingMode["user"] = "user";
12
- FacingMode["environment"] = "environment";
13
- })(FacingMode || (exports.FacingMode = FacingMode = {}));
14
- var DisplaySurface;
15
- exports.DisplaySurface = DisplaySurface;
16
- (function (DisplaySurface) {
17
- DisplaySurface["browser"] = "browser";
18
- DisplaySurface["monitor"] = "monitor";
19
- DisplaySurface["window"] = "window";
20
- })(DisplaySurface || (exports.DisplaySurface = DisplaySurface = {}));
21
- var PresetCameraConstraints = {
22
- '1080p': {
23
- frameRate: 30,
24
- width: 1920,
25
- height: 1080
26
- },
27
- '720p': {
28
- frameRate: 30,
29
- width: 1280,
30
- height: 720
31
- },
32
- '480p': {
33
- frameRate: 30,
34
- width: 640,
35
- height: 480
36
- },
37
- '360p': {
38
- frameRate: 30,
39
- width: 640,
40
- height: 360
41
- },
42
- '240p': {
43
- frameRate: 30,
44
- width: 320,
45
- height: 240
46
- },
47
- '180p': {
48
- frameRate: 30,
49
- width: 320,
50
- height: 180
51
- },
52
- '120p': {
53
- frameRate: 30,
54
- width: 160,
55
- height: 120
56
- }
57
- };
58
- exports.PresetCameraConstraints = PresetCameraConstraints;
59
- //# sourceMappingURL=constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["FacingMode","exports","DisplaySurface","PresetCameraConstraints","frameRate","width","height"],"sources":["constants.ts"],"sourcesContent":["import {VideoDeviceConstraints} from '@webex/internal-media-core';\r\n\r\nexport enum FacingMode {\r\n user = 'user',\r\n environment = 'environment',\r\n}\r\n\r\n// can be used later on when we add constraints in create display track\r\nexport enum DisplaySurface {\r\n browser = 'browser',\r\n monitor = 'monitor',\r\n window = 'window',\r\n}\r\n\r\nexport const PresetCameraConstraints: {[key: string]: VideoDeviceConstraints} = {\r\n '1080p': {frameRate: 30, width: 1920, height: 1080},\r\n\r\n '720p': {frameRate: 30, width: 1280, height: 720},\r\n\r\n '480p': {frameRate: 30, width: 640, height: 480},\r\n\r\n '360p': {frameRate: 30, width: 640, height: 360},\r\n\r\n '240p': {frameRate: 30, width: 320, height: 240},\r\n\r\n '180p': {frameRate: 30, width: 320, height: 180},\r\n\r\n '120p': {frameRate: 30, width: 160, height: 120},\r\n};\r\n"],"mappings":";;;;;;;IAEYA,UAAU,EAKtB;AAAAC,OAAA,CAAAD,UAAA,GAAAA,UAAA;AAAA,WALYA,UAAU;EAAVA,UAAU;EAAVA,UAAU;AAAA,GAAVA,UAAU,KAAAC,OAAA,CAAAD,UAAA,GAAVA,UAAU;AAAA,IAMVE,cAAc;AAAAD,OAAA,CAAAC,cAAA,GAAAA,cAAA;AAAA,WAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;AAAA,GAAdA,cAAc,KAAAD,OAAA,CAAAC,cAAA,GAAdA,cAAc;AAMnB,IAAMC,uBAAgE,GAAG;EAC9E,OAAO,EAAE;IAACC,SAAS,EAAE,EAAE;IAAEC,KAAK,EAAE,IAAI;IAAEC,MAAM,EAAE;EAAI,CAAC;EAEnD,MAAM,EAAE;IAACF,SAAS,EAAE,EAAE;IAAEC,KAAK,EAAE,IAAI;IAAEC,MAAM,EAAE;EAAG,CAAC;EAEjD,MAAM,EAAE;IAACF,SAAS,EAAE,EAAE;IAAEC,KAAK,EAAE,GAAG;IAAEC,MAAM,EAAE;EAAG,CAAC;EAEhD,MAAM,EAAE;IAACF,SAAS,EAAE,EAAE;IAAEC,KAAK,EAAE,GAAG;IAAEC,MAAM,EAAE;EAAG,CAAC;EAEhD,MAAM,EAAE;IAACF,SAAS,EAAE,EAAE;IAAEC,KAAK,EAAE,GAAG;IAAEC,MAAM,EAAE;EAAG,CAAC;EAEhD,MAAM,EAAE;IAACF,SAAS,EAAE,EAAE;IAAEC,KAAK,EAAE,GAAG;IAAEC,MAAM,EAAE;EAAG,CAAC;EAEhD,MAAM,EAAE;IAACF,SAAS,EAAE,EAAE;IAAEC,KAAK,EAAE,GAAG;IAAEC,MAAM,EAAE;EAAG;AACjD,CAAC;AAACL,OAAA,CAAAE,uBAAA,GAAAA,uBAAA"}