@webex/plugin-meetings 2.35.4 → 2.36.1
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/dist/media/index.js +6 -2
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/index.js +55 -14
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +28 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/reactions/reactions.js +111 -0
- package/dist/reactions/reactions.js.map +1 -0
- package/dist/reactions/reactions.type.js +40 -0
- package/dist/reactions/reactions.type.js.map +1 -0
- package/package.json +17 -17
- package/src/media/index.ts +6 -2
- package/src/meeting/index.ts +47 -15
- package/src/meeting/request.ts +23 -0
- package/src/reactions/reactions.ts +104 -0
- package/src/reactions/reactions.type.ts +36 -0
- package/test/unit/spec/meeting/index.js +120 -14
- package/test/unit/spec/meeting/request.js +25 -1
package/src/meeting/request.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
SEND_DTMF_ENDPOINT,
|
|
26
26
|
_SLIDES_
|
|
27
27
|
} from '../constants';
|
|
28
|
+
import {Reaction} from '../reactions/reactions.type';
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* @class MeetingRequest
|
|
@@ -768,4 +769,26 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
768
769
|
uri: keepAliveUrl
|
|
769
770
|
});
|
|
770
771
|
}
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Make a network request to send a reaction.
|
|
775
|
+
* @param {Object} options
|
|
776
|
+
* @param {Url} options.reactionChannelUrl
|
|
777
|
+
* @param {Reaction} options.reaction
|
|
778
|
+
* @param {string} options.senderID
|
|
779
|
+
* @returns {Promise}
|
|
780
|
+
*/
|
|
781
|
+
sendReaction({ reactionChannelUrl, reaction, participantId }: { reactionChannelUrl: string, reaction: Reaction, participantId: string }) {
|
|
782
|
+
const uri = reactionChannelUrl;
|
|
783
|
+
|
|
784
|
+
// @ts-ignore
|
|
785
|
+
return this.request({
|
|
786
|
+
method: HTTP_VERBS.POST,
|
|
787
|
+
uri,
|
|
788
|
+
body: {
|
|
789
|
+
sender: {participantId},
|
|
790
|
+
reaction,
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
}
|
|
771
794
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {Reaction, ReactionType, SkinTone, SkinToneType} from './reactions.type';
|
|
2
|
+
|
|
3
|
+
const Reactions: Record<ReactionType, Reaction> = {
|
|
4
|
+
smile: {
|
|
5
|
+
type: 'smile',
|
|
6
|
+
codepoints: '1F642',
|
|
7
|
+
shortcodes: ':slightly_smiling_face:'
|
|
8
|
+
},
|
|
9
|
+
sad: {
|
|
10
|
+
type: 'sad',
|
|
11
|
+
codepoints: '1F625',
|
|
12
|
+
shortcodes: ':sad_but_relieved_face:',
|
|
13
|
+
},
|
|
14
|
+
wow: {
|
|
15
|
+
type: 'wow',
|
|
16
|
+
codepoints: '1F62E',
|
|
17
|
+
shortcodes: ':open_mouth:',
|
|
18
|
+
},
|
|
19
|
+
haha: {
|
|
20
|
+
type: 'haha',
|
|
21
|
+
codepoints: '1F603',
|
|
22
|
+
shortcodes: ':smiley:'
|
|
23
|
+
},
|
|
24
|
+
celebrate: {
|
|
25
|
+
type: 'celebrate',
|
|
26
|
+
codepoints: '1F389',
|
|
27
|
+
shortcodes: ':party_popper:',
|
|
28
|
+
},
|
|
29
|
+
clap: {
|
|
30
|
+
type: 'clap',
|
|
31
|
+
codepoints: '1F44F',
|
|
32
|
+
shortcodes: ':clap:',
|
|
33
|
+
},
|
|
34
|
+
thumbs_up: {
|
|
35
|
+
type: 'thumb_up',
|
|
36
|
+
codepoints: '1F44D',
|
|
37
|
+
shortcodes: ':thumbsup:',
|
|
38
|
+
},
|
|
39
|
+
thumbs_down: {
|
|
40
|
+
type: 'thumb_down',
|
|
41
|
+
codepoints: '1F44E',
|
|
42
|
+
shortcodes: ':thumbsdown:',
|
|
43
|
+
},
|
|
44
|
+
heart: {
|
|
45
|
+
type: 'heart',
|
|
46
|
+
codepoints: '2764',
|
|
47
|
+
shortcodes: ':heart:',
|
|
48
|
+
},
|
|
49
|
+
fire: {
|
|
50
|
+
type: 'fire',
|
|
51
|
+
codepoints: '1F525',
|
|
52
|
+
shortcodes: ':fire:',
|
|
53
|
+
},
|
|
54
|
+
prayer: {
|
|
55
|
+
type: 'prayer',
|
|
56
|
+
codepoints: '1F64F',
|
|
57
|
+
shortcodes: ':pray:',
|
|
58
|
+
},
|
|
59
|
+
speed_up: {
|
|
60
|
+
type: 'speed_up',
|
|
61
|
+
codepoints: '1F407',
|
|
62
|
+
shortcodes: ':rabbit:',
|
|
63
|
+
},
|
|
64
|
+
slow_down: {
|
|
65
|
+
type: 'slow_down',
|
|
66
|
+
codepoints: '1F422',
|
|
67
|
+
shortcodes: ':turtle:',
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const SkinTones: Record<SkinToneType, SkinTone> = {
|
|
72
|
+
normal: {
|
|
73
|
+
type: 'normal_skin_tone',
|
|
74
|
+
codepoints: '',
|
|
75
|
+
shortcodes: '',
|
|
76
|
+
},
|
|
77
|
+
light: {
|
|
78
|
+
type: 'light_skin_tone',
|
|
79
|
+
codepoints: '1F3FB',
|
|
80
|
+
shortcodes: ':skin-tone-2:',
|
|
81
|
+
},
|
|
82
|
+
medium_light: {
|
|
83
|
+
type: 'medium_light_skin_tone',
|
|
84
|
+
codepoints: '1F3FC',
|
|
85
|
+
shortcodes: ':skin-tone-3:',
|
|
86
|
+
},
|
|
87
|
+
medium: {
|
|
88
|
+
type: 'medium_skin_tone',
|
|
89
|
+
codepoints: '1F3FD',
|
|
90
|
+
shortcodes: ':skin-tone-4:',
|
|
91
|
+
},
|
|
92
|
+
medium_dark: {
|
|
93
|
+
type: 'medium_dark_skin_tone',
|
|
94
|
+
codepoints: '1F3FE',
|
|
95
|
+
shortcodes: ':skin-tone-5:',
|
|
96
|
+
},
|
|
97
|
+
dark: {
|
|
98
|
+
type: 'dark_skin_tone',
|
|
99
|
+
codepoints: '1F3FF',
|
|
100
|
+
shortcodes: ':skin-tone-6:',
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export {Reactions, SkinTones};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
export type EmoticonData = {
|
|
3
|
+
type: string;
|
|
4
|
+
codepoints?: string;
|
|
5
|
+
shortcodes?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type SkinTone = EmoticonData;
|
|
9
|
+
export type Reaction = ReactionData & {
|
|
10
|
+
tone?: SkinTone;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export enum ReactionType {
|
|
14
|
+
smile = 'smile',
|
|
15
|
+
sad = 'sad',
|
|
16
|
+
wow = 'wow',
|
|
17
|
+
haha = 'haha',
|
|
18
|
+
celebrate = 'celebrate',
|
|
19
|
+
clap = 'clap',
|
|
20
|
+
thumbs_up = 'thumbs_up',
|
|
21
|
+
thumbs_down = 'thumbs_down',
|
|
22
|
+
heart = 'heart',
|
|
23
|
+
fire = 'fire',
|
|
24
|
+
prayer = 'prayer',
|
|
25
|
+
speed_up = 'speed_up',
|
|
26
|
+
slow_down = 'slow_down',
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export enum SkinToneType {
|
|
30
|
+
normal = 'normal',
|
|
31
|
+
light = 'light',
|
|
32
|
+
medium_light = 'medium_light',
|
|
33
|
+
medium = 'medium',
|
|
34
|
+
medium_dark = 'medium_dark',
|
|
35
|
+
dark = 'dark',
|
|
36
|
+
}
|
|
@@ -715,6 +715,13 @@ describe('plugin-meetings', () => {
|
|
|
715
715
|
height: {
|
|
716
716
|
max: 200,
|
|
717
717
|
ideal: 200
|
|
718
|
+
},
|
|
719
|
+
frameRate: {
|
|
720
|
+
ideal: 15,
|
|
721
|
+
max: 30
|
|
722
|
+
},
|
|
723
|
+
facingMode: {
|
|
724
|
+
ideal: 'user'
|
|
718
725
|
}
|
|
719
726
|
}
|
|
720
727
|
};
|
|
@@ -1420,9 +1427,9 @@ describe('plugin-meetings', () => {
|
|
|
1420
1427
|
});
|
|
1421
1428
|
});
|
|
1422
1429
|
});
|
|
1423
|
-
describe('#
|
|
1424
|
-
it('should have #
|
|
1425
|
-
assert.exists(meeting.
|
|
1430
|
+
describe('#requestScreenShareFloor', () => {
|
|
1431
|
+
it('should have #requestScreenShareFloor', () => {
|
|
1432
|
+
assert.exists(meeting.requestScreenShareFloor);
|
|
1426
1433
|
});
|
|
1427
1434
|
beforeEach(() => {
|
|
1428
1435
|
meeting.locusInfo.mediaShares = [{name: 'content', url: url1}];
|
|
@@ -1430,7 +1437,7 @@ describe('plugin-meetings', () => {
|
|
|
1430
1437
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
|
1431
1438
|
});
|
|
1432
1439
|
it('should send the share', async () => {
|
|
1433
|
-
const share = meeting.
|
|
1440
|
+
const share = meeting.requestScreenShareFloor();
|
|
1434
1441
|
|
|
1435
1442
|
assert.exists(share.then);
|
|
1436
1443
|
await share;
|
|
@@ -3457,22 +3464,34 @@ describe('plugin-meetings', () => {
|
|
|
3457
3464
|
sandbox = null;
|
|
3458
3465
|
});
|
|
3459
3466
|
|
|
3460
|
-
describe('#
|
|
3461
|
-
it('should have #
|
|
3462
|
-
assert.exists(meeting.
|
|
3467
|
+
describe('#releaseScreenShareFloor', () => {
|
|
3468
|
+
it('should have #releaseScreenShareFloor', () => {
|
|
3469
|
+
assert.exists(meeting.releaseScreenShareFloor);
|
|
3463
3470
|
});
|
|
3464
3471
|
beforeEach(() => {
|
|
3465
|
-
meeting.
|
|
3472
|
+
meeting.selfId = 'some self id';
|
|
3473
|
+
meeting.locusInfo.mediaShares = [{name: 'content', url: url1, floor: {beneficiary: {id: meeting.selfId}}}];
|
|
3466
3474
|
meeting.locusInfo.self = {url: url2};
|
|
3475
|
+
meeting.mediaProperties = {mediaDirection: {sendShare: true}};
|
|
3467
3476
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
|
3468
3477
|
});
|
|
3469
|
-
it('should call
|
|
3470
|
-
const share = meeting.
|
|
3478
|
+
it('should call changeMeetingFloor()', async () => {
|
|
3479
|
+
const share = meeting.releaseScreenShareFloor();
|
|
3471
3480
|
|
|
3472
3481
|
assert.exists(share.then);
|
|
3473
3482
|
await share;
|
|
3474
3483
|
assert.calledOnce(meeting.meetingRequest.changeMeetingFloor);
|
|
3475
3484
|
});
|
|
3485
|
+
it('should not call changeMeetingFloor() if someone else already has the floor', async () => {
|
|
3486
|
+
// change selfId so that it doesn't match the beneficiary id from meeting.locusInfo.mediaShares
|
|
3487
|
+
meeting.selfId = 'new self id';
|
|
3488
|
+
|
|
3489
|
+
const share = meeting.releaseScreenShareFloor();
|
|
3490
|
+
|
|
3491
|
+
assert.exists(share.then);
|
|
3492
|
+
await share;
|
|
3493
|
+
assert.notCalled(meeting.meetingRequest.changeMeetingFloor);
|
|
3494
|
+
});
|
|
3476
3495
|
});
|
|
3477
3496
|
|
|
3478
3497
|
describe('#setSipUri', () => {
|
|
@@ -4003,7 +4022,7 @@ describe('plugin-meetings', () => {
|
|
|
4003
4022
|
if (newPayload.previous.content.beneficiaryId === USER_IDS.ME) {
|
|
4004
4023
|
eventTrigger.share.push({
|
|
4005
4024
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4006
|
-
functionName: '
|
|
4025
|
+
functionName: 'localShare'
|
|
4007
4026
|
});
|
|
4008
4027
|
}
|
|
4009
4028
|
else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
@@ -4054,7 +4073,7 @@ describe('plugin-meetings', () => {
|
|
|
4054
4073
|
if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
4055
4074
|
eventTrigger.share.push({
|
|
4056
4075
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4057
|
-
functionName: '
|
|
4076
|
+
functionName: 'localShare'
|
|
4058
4077
|
});
|
|
4059
4078
|
}
|
|
4060
4079
|
else {
|
|
@@ -4073,7 +4092,7 @@ describe('plugin-meetings', () => {
|
|
|
4073
4092
|
if (newPayload.previous.content.beneficiaryId === USER_IDS.ME) {
|
|
4074
4093
|
eventTrigger.share.push({
|
|
4075
4094
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4076
|
-
functionName: '
|
|
4095
|
+
functionName: 'localShare'
|
|
4077
4096
|
});
|
|
4078
4097
|
}
|
|
4079
4098
|
else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
@@ -4116,7 +4135,7 @@ describe('plugin-meetings', () => {
|
|
|
4116
4135
|
if (beneficiaryId === USER_IDS.ME) {
|
|
4117
4136
|
eventTrigger.share.push({
|
|
4118
4137
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4119
|
-
functionName: '
|
|
4138
|
+
functionName: 'localShare'
|
|
4120
4139
|
});
|
|
4121
4140
|
}
|
|
4122
4141
|
else {
|
|
@@ -4582,6 +4601,93 @@ describe('plugin-meetings', () => {
|
|
|
4582
4601
|
meeting.stopKeepAlive();
|
|
4583
4602
|
});
|
|
4584
4603
|
});
|
|
4604
|
+
|
|
4605
|
+
describe('#sendReaction', () => {
|
|
4606
|
+
it('should have #sendReaction', () => {
|
|
4607
|
+
assert.exists(meeting.sendReaction);
|
|
4608
|
+
});
|
|
4609
|
+
|
|
4610
|
+
beforeEach(() => {
|
|
4611
|
+
meeting.meetingRequest.sendReaction = sinon.stub().returns(Promise.resolve());
|
|
4612
|
+
});
|
|
4613
|
+
|
|
4614
|
+
it('should send reaction with the right data and return a promise', async () => {
|
|
4615
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
4616
|
+
|
|
4617
|
+
const reactionPromise = meeting.sendReaction('thumbs_down', 'light');
|
|
4618
|
+
|
|
4619
|
+
assert.exists(reactionPromise.then);
|
|
4620
|
+
await reactionPromise;
|
|
4621
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
4622
|
+
reactionChannelUrl: 'Fake URL',
|
|
4623
|
+
reaction: {
|
|
4624
|
+
type: 'thumb_down',
|
|
4625
|
+
codepoints: '1F44E',
|
|
4626
|
+
shortcodes: ':thumbsdown:',
|
|
4627
|
+
tone: {
|
|
4628
|
+
type: 'light_skin_tone',
|
|
4629
|
+
codepoints: '1F3FB',
|
|
4630
|
+
shortcodes: ':skin-tone-2:'
|
|
4631
|
+
}
|
|
4632
|
+
},
|
|
4633
|
+
participantId: meeting.members.selfId,
|
|
4634
|
+
});
|
|
4635
|
+
});
|
|
4636
|
+
|
|
4637
|
+
it('should fail sending a reaction if data channel is undefined', async () => {
|
|
4638
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: undefined}};
|
|
4639
|
+
|
|
4640
|
+
await assert.isRejected(meeting.sendReaction('thumbs_down', 'light'), Error, 'Error sending reaction, service url not found.');
|
|
4641
|
+
|
|
4642
|
+
assert.notCalled(meeting.meetingRequest.sendReaction);
|
|
4643
|
+
});
|
|
4644
|
+
|
|
4645
|
+
it('should fail sending a reaction if reactionType is invalid ', async () => {
|
|
4646
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
4647
|
+
|
|
4648
|
+
await assert.isRejected(meeting.sendReaction('invalid_reaction', 'light'), Error, 'invalid_reaction is not a valid reaction.');
|
|
4649
|
+
|
|
4650
|
+
assert.notCalled(meeting.meetingRequest.sendReaction);
|
|
4651
|
+
});
|
|
4652
|
+
|
|
4653
|
+
it('should send a reaction with default skin tone if provided skinToneType is invalid ', async () => {
|
|
4654
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
4655
|
+
|
|
4656
|
+
const reactionPromise = meeting.sendReaction('thumbs_down', 'invalid_skin_tone');
|
|
4657
|
+
|
|
4658
|
+
assert.exists(reactionPromise.then);
|
|
4659
|
+
await reactionPromise;
|
|
4660
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
4661
|
+
reactionChannelUrl: 'Fake URL',
|
|
4662
|
+
reaction: {
|
|
4663
|
+
type: 'thumb_down',
|
|
4664
|
+
codepoints: '1F44E',
|
|
4665
|
+
shortcodes: ':thumbsdown:',
|
|
4666
|
+
tone: {type: 'normal_skin_tone', codepoints: '', shortcodes: ''}
|
|
4667
|
+
},
|
|
4668
|
+
participantId: meeting.members.selfId,
|
|
4669
|
+
});
|
|
4670
|
+
});
|
|
4671
|
+
|
|
4672
|
+
it('should send a reaction with default skin tone if none provided', async () => {
|
|
4673
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
4674
|
+
|
|
4675
|
+
const reactionPromise = meeting.sendReaction('thumbs_down');
|
|
4676
|
+
|
|
4677
|
+
assert.exists(reactionPromise.then);
|
|
4678
|
+
await reactionPromise;
|
|
4679
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
4680
|
+
reactionChannelUrl: 'Fake URL',
|
|
4681
|
+
reaction: {
|
|
4682
|
+
type: 'thumb_down',
|
|
4683
|
+
codepoints: '1F44E',
|
|
4684
|
+
shortcodes: ':thumbsdown:',
|
|
4685
|
+
tone: {type: 'normal_skin_tone', codepoints: '', shortcodes: ''}
|
|
4686
|
+
},
|
|
4687
|
+
participantId: meeting.members.selfId,
|
|
4688
|
+
});
|
|
4689
|
+
});
|
|
4690
|
+
});
|
|
4585
4691
|
});
|
|
4586
4692
|
});
|
|
4587
4693
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import sinon from 'sinon';
|
|
2
2
|
import {assert} from '@webex/test-helper-chai';
|
|
3
3
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
4
|
-
|
|
5
4
|
import Meetings from '@webex/plugin-meetings';
|
|
6
5
|
import MeetingRequest from '@webex/plugin-meetings/src/meeting/request';
|
|
7
6
|
|
|
@@ -278,5 +277,30 @@ describe('plugin-meetings', () => {
|
|
|
278
277
|
assert.equal(requestParams.uri, keepAliveUrl);
|
|
279
278
|
});
|
|
280
279
|
});
|
|
280
|
+
|
|
281
|
+
describe('#sendReaction', () => {
|
|
282
|
+
it('sends request to sendReaction', async () => {
|
|
283
|
+
const reactionChannelUrl = 'reactionChannelUrl';
|
|
284
|
+
const participantId = 'participantId';
|
|
285
|
+
const reaction = {
|
|
286
|
+
type: 'thumb_down',
|
|
287
|
+
codepoints: '1F44E',
|
|
288
|
+
shortcodes: ':thumbsdown:',
|
|
289
|
+
tone: {type: 'normal_skin_tone', codepoints: '', shortcodes: ''}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
await meetingsRequest.sendReaction({
|
|
293
|
+
reactionChannelUrl,
|
|
294
|
+
reaction,
|
|
295
|
+
participantId
|
|
296
|
+
});
|
|
297
|
+
const requestParams = meetingsRequest.request.getCall(0).args[0];
|
|
298
|
+
|
|
299
|
+
assert.equal(requestParams.method, 'POST');
|
|
300
|
+
assert.equal(requestParams.uri, reactionChannelUrl);
|
|
301
|
+
assert.equal(requestParams.body.sender.participantId, participantId);
|
|
302
|
+
assert.equal(requestParams.body.reaction, reaction);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
281
305
|
});
|
|
282
306
|
});
|