@digitalsamba/embedded-sdk 0.0.13 → 0.0.18
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/README.md +2 -0
- package/dist/cjs/index.d.ts +16 -3
- package/dist/cjs/index.js +129 -17
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +83 -15
- package/dist/cjs/types.js +0 -6
- package/dist/cjs/utils/PermissionManager/index.d.ts +13 -0
- package/dist/cjs/utils/PermissionManager/index.js +74 -0
- package/dist/cjs/utils/PermissionManager/types.d.ts +23 -0
- package/dist/cjs/utils/PermissionManager/types.js +2 -0
- package/dist/cjs/utils/proxy.d.ts +1 -0
- package/dist/cjs/utils/proxy.js +21 -0
- package/dist/cjs/utils/vars.d.ts +23 -0
- package/dist/cjs/utils/vars.js +48 -0
- package/dist/esm/index.d.ts +16 -3
- package/dist/esm/index.js +127 -15
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +83 -15
- package/dist/esm/types.js +1 -5
- package/dist/esm/utils/PermissionManager/index.d.ts +13 -0
- package/dist/esm/utils/PermissionManager/index.js +70 -0
- package/dist/esm/utils/PermissionManager/types.d.ts +23 -0
- package/dist/esm/utils/PermissionManager/types.js +1 -0
- package/dist/esm/utils/proxy.d.ts +1 -0
- package/dist/esm/utils/proxy.js +17 -0
- package/dist/esm/utils/vars.d.ts +23 -0
- package/dist/esm/utils/vars.js +45 -0
- package/dist/index.html +98 -3
- package/dist/initial-config-demo.html +303 -0
- package/dist/permissions-demo.html +289 -0
- package/dist/types/index.d.ts +16 -3
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/types/types.d.ts +83 -15
- package/dist/types/utils/PermissionManager/index.d.ts +13 -0
- package/dist/types/utils/PermissionManager/types.d.ts +23 -0
- package/dist/types/utils/proxy.d.ts +1 -0
- package/dist/types/utils/vars.d.ts +23 -0
- package/dist/umd/index.js +1 -1
- package/package.json +1 -1
package/dist/index.html
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
<style>
|
11
11
|
.user-list-row {
|
12
12
|
display: flex;
|
13
|
-
margin
|
13
|
+
margin: 12px 0 8px;
|
14
14
|
align-items: center;
|
15
15
|
}
|
16
16
|
|
@@ -22,6 +22,22 @@
|
|
22
22
|
margin-right: 8px;
|
23
23
|
}
|
24
24
|
|
25
|
+
.speaker-indicator {
|
26
|
+
width: 8px;
|
27
|
+
height: 8px;
|
28
|
+
display: block;
|
29
|
+
border-radius: 50%;
|
30
|
+
margin-right: 8px;
|
31
|
+
background: #4cd964;
|
32
|
+
opacity: 0;
|
33
|
+
margin-left: 8px;
|
34
|
+
}
|
35
|
+
|
36
|
+
.speaker-indicator.show {
|
37
|
+
opacity: 1
|
38
|
+
}
|
39
|
+
|
40
|
+
|
25
41
|
.log p {
|
26
42
|
font-size: 14px;
|
27
43
|
line-height: 1;
|
@@ -42,6 +58,10 @@
|
|
42
58
|
<h3>Room users:</h3>
|
43
59
|
<div class="participants">
|
44
60
|
|
61
|
+
</div>
|
62
|
+
<h3>Room state</h3>
|
63
|
+
<div class="state">
|
64
|
+
|
45
65
|
</div>
|
46
66
|
</div>
|
47
67
|
</div>
|
@@ -85,7 +105,8 @@
|
|
85
105
|
// const api = new DigitalSambaEmbedded({ frame});
|
86
106
|
//const api = new DigitalSambaEmbedded({ url: ROOM_URL}, {reportErrors: true});
|
87
107
|
|
88
|
-
|
108
|
+
|
109
|
+
var api = DigitalSambaEmbedded.createControl({ url: ROOM_URL, root: parent });
|
89
110
|
|
90
111
|
const log = document.querySelector('.log');
|
91
112
|
|
@@ -103,6 +124,7 @@
|
|
103
124
|
{command: 'disableAudio', label: 'disable audio' },
|
104
125
|
{command: 'startScreenshare', label: 'start screenshare' },
|
105
126
|
{command: 'stopScreenshare', label: 'stop screenshare' },
|
127
|
+
{command: 'raiseHand', label: 'raise hand' },
|
106
128
|
{command: 'startRecording', label: 'start recording' },
|
107
129
|
{command: 'stopRecording', label: 'stop recording' },
|
108
130
|
{command: 'showToolbar', label: 'show toolbar' },
|
@@ -172,14 +194,38 @@
|
|
172
194
|
}
|
173
195
|
});
|
174
196
|
|
197
|
+
api.on('handRaised', ({data}) => {
|
198
|
+
const control = document.querySelector('#lower-hand-'+data.userId);
|
199
|
+
|
200
|
+
if(control) {
|
201
|
+
control.style.display = 'inline'
|
202
|
+
}
|
203
|
+
})
|
204
|
+
|
205
|
+
api.on('handLowered', ({data}) => {
|
206
|
+
const id = data.user;
|
207
|
+
|
208
|
+
const control = document.querySelector('#lower-hand-'+ id );
|
209
|
+
|
210
|
+
if(control) {
|
211
|
+
control.style.display = 'none'
|
212
|
+
}
|
213
|
+
})
|
214
|
+
|
215
|
+
const stateBlock = document.querySelector('.state');
|
216
|
+
|
217
|
+
api.on('roomStateUpdated', ({data}) => {
|
218
|
+
stateBlock.innerHTML = JSON.stringify(data);
|
219
|
+
})
|
175
220
|
|
176
221
|
api.on('usersUpdated', ({data: {users}}) => {
|
177
222
|
participantList.innerHTML = '';
|
178
223
|
|
179
|
-
|
180
224
|
users.forEach(user => {
|
181
225
|
const row = document.createElement('div');
|
182
226
|
row.className = 'user-list-row';
|
227
|
+
const subButtons = document.createElement('div')
|
228
|
+
row.appendChild(subButtons);
|
183
229
|
|
184
230
|
const avatar = document.createElement('span');
|
185
231
|
avatar.className = 'user-list-avatar';
|
@@ -192,6 +238,11 @@
|
|
192
238
|
name.innerText = user.name;
|
193
239
|
row.appendChild(name);
|
194
240
|
|
241
|
+
const speakerIndicator = document.createElement('span')
|
242
|
+
speakerIndicator.className = `speaker-indicator speaker-indicator-${user.id}`;
|
243
|
+
row.appendChild(speakerIndicator);
|
244
|
+
|
245
|
+
|
195
246
|
if(user.kind === 'local') {
|
196
247
|
const label = document.createElement('span');
|
197
248
|
label.className = 'user-list-label';
|
@@ -210,13 +261,57 @@
|
|
210
261
|
kickControl.style.margin = '0 4px';
|
211
262
|
kickControl.onclick = () => {api.removeUser(user.id)}
|
212
263
|
row.appendChild(kickControl);
|
264
|
+
|
265
|
+
const allowBroadcastControl = document.createElement('button');
|
266
|
+
allowBroadcastControl.innerHTML = 'allow broadcast'
|
267
|
+
allowBroadcastControl.style.margin = '0 4px';
|
268
|
+
allowBroadcastControl.onclick = () => {api.allowBroadcast(user.id)}
|
269
|
+
subButtons.appendChild(allowBroadcastControl);
|
270
|
+
|
271
|
+
const disallowBroadcastControl = document.createElement('button');
|
272
|
+
disallowBroadcastControl.innerHTML = 'disallow broadcast'
|
273
|
+
disallowBroadcastControl.style.margin = '0 4px';
|
274
|
+
disallowBroadcastControl.onclick = () => {api.disallowBroadcast(user.id)}
|
275
|
+
subButtons.appendChild(disallowBroadcastControl);
|
276
|
+
|
277
|
+
const allowScreenshareControl = document.createElement('button');
|
278
|
+
allowScreenshareControl.innerHTML = 'allow screenshare'
|
279
|
+
allowScreenshareControl.style.margin = '0 4px';
|
280
|
+
allowScreenshareControl.onclick = () => {api.allowScreenshare(user.id)}
|
281
|
+
subButtons.appendChild(allowScreenshareControl);
|
282
|
+
|
283
|
+
const disallowScreenshareControl = document.createElement('button');
|
284
|
+
disallowScreenshareControl.innerHTML = 'disallow screenshare'
|
285
|
+
disallowScreenshareControl.style.margin = '0 4px';
|
286
|
+
disallowScreenshareControl.onclick = () => {api.disallowScreenshare(user.id)}
|
287
|
+
subButtons.appendChild(disallowScreenshareControl);
|
213
288
|
}
|
214
289
|
|
290
|
+
const raisedHandControl = document.createElement('button');
|
291
|
+
raisedHandControl.id = 'lower-hand-'+user.id;
|
292
|
+
raisedHandControl.innerHTML = 'lower hand'
|
293
|
+
raisedHandControl.style.margin = '0 4px';
|
294
|
+
raisedHandControl.style.display = 'none';
|
295
|
+
raisedHandControl.onclick = () => {api.lowerHand(user.id)}
|
296
|
+
row.appendChild(raisedHandControl);
|
297
|
+
|
215
298
|
participantList.appendChild(row);
|
299
|
+
participantList.appendChild(subButtons);
|
216
300
|
|
217
301
|
})
|
218
302
|
})
|
219
303
|
|
304
|
+
api.on('activeSpeakerChanged', ({data}) => {
|
305
|
+
const currentIndicator = document.querySelector('.speaker-indicator.show')
|
306
|
+
if(currentIndicator) {
|
307
|
+
currentIndicator.className = currentIndicator.className.replace(' show', '');
|
308
|
+
|
309
|
+
}
|
310
|
+
|
311
|
+
const newIndicator = document.querySelector(`.speaker-indicator-${data.user.id}`);
|
312
|
+
newIndicator.className = newIndicator.className + ' show'
|
313
|
+
})
|
314
|
+
|
220
315
|
</script>
|
221
316
|
|
222
317
|
</body>
|
@@ -0,0 +1,303 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
7
|
+
<title>Document</title>
|
8
|
+
<!-- <script src="https://unpkg.com/@digitalsamba/embedded-sdk"></script>-->
|
9
|
+
<script src="./umd/index.js"></script>
|
10
|
+
<style>
|
11
|
+
.user-list-row {
|
12
|
+
display: flex;
|
13
|
+
margin-bottom: 8px;
|
14
|
+
align-items: center;
|
15
|
+
}
|
16
|
+
|
17
|
+
.user-list-avatar {
|
18
|
+
width: 24px;
|
19
|
+
height: 24px;
|
20
|
+
display: block;
|
21
|
+
border-radius: 50%;
|
22
|
+
margin-right: 8px;
|
23
|
+
}
|
24
|
+
|
25
|
+
.log p {
|
26
|
+
font-size: 14px;
|
27
|
+
line-height: 1;
|
28
|
+
margin: 0 0 4px
|
29
|
+
}
|
30
|
+
|
31
|
+
.buttons button, .captions-buttons button {
|
32
|
+
margin: 2px;
|
33
|
+
}
|
34
|
+
</style>
|
35
|
+
<script>
|
36
|
+
const initialRoomState = {
|
37
|
+
username: "",
|
38
|
+
micEnabled: false,
|
39
|
+
cameraEnabled: false,
|
40
|
+
showToolbar: false,
|
41
|
+
showCaptions: false,
|
42
|
+
layoutMode: 'auto'
|
43
|
+
}
|
44
|
+
</script>
|
45
|
+
</head>
|
46
|
+
<body>
|
47
|
+
<div class="sdk-prep">
|
48
|
+
<h3>Initial settings</h3>
|
49
|
+
|
50
|
+
<label for="prep-username-input">
|
51
|
+
<p>Username:</p>
|
52
|
+
<input type="text" id="prep-username-input">
|
53
|
+
</label>
|
54
|
+
<div class="prep-checkboxes"></div>
|
55
|
+
<fieldset>
|
56
|
+
<legend>Layout mode:</legend>
|
57
|
+
<div>
|
58
|
+
<input type="radio" id="prep-layout-mode1" checked name="contact" value="auto" onchange="initialRoomState.layoutMode = 'auto'" />
|
59
|
+
<label for="prep-layout-mode1">Auto</label>
|
60
|
+
|
61
|
+
<input type="radio" id="contactChoice2" name="contact" value="tiled" onchange="initialRoomState.layoutMode = 'tiled'"/>
|
62
|
+
<label for="contactChoice2">Tiled</label>
|
63
|
+
</div>
|
64
|
+
</fieldset>
|
65
|
+
<div style="margin-top: 20px">
|
66
|
+
<button type="button" class="sdk-prep-submit">load</button>
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
<div class="sdk-ready" style="display: none">
|
70
|
+
<div style="display: flex">
|
71
|
+
<div class="ifp">
|
72
|
+
|
73
|
+
</div>
|
74
|
+
<div style="min-width: 300px ; padding: 0 16px">
|
75
|
+
<h3>Room users:</h3>
|
76
|
+
<div class="participants">
|
77
|
+
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
</div>
|
81
|
+
<div class="div buttons" style=" border: 1px solid yellow">
|
82
|
+
<button class="c0" style="margin-right: 15px; border: 2px solid blue">LOAD</button>
|
83
|
+
|
84
|
+
</div>
|
85
|
+
<div class="div captions-buttons" style=" border: 1px solid yellow">
|
86
|
+
<p>captions controls</p>
|
87
|
+
|
88
|
+
</div>
|
89
|
+
|
90
|
+
<div class="log">
|
91
|
+
|
92
|
+
</div>
|
93
|
+
</div>
|
94
|
+
|
95
|
+
<script async defer>
|
96
|
+
const parent = document.querySelector('.ifp');
|
97
|
+
const frame = document.querySelector('.if');
|
98
|
+
const buttonsParent = document.querySelector('.buttons');
|
99
|
+
const captionsButtonsParent = document.querySelector('.captions-buttons');
|
100
|
+
const participantList = document.querySelector('.participants');
|
101
|
+
const btn0 = document.querySelector('.c0');
|
102
|
+
const prepButton = document.querySelector('.sdk-prep-submit');
|
103
|
+
const prepBlock = document.querySelector('.sdk-prep')
|
104
|
+
const controlsBlock = document.querySelector('.sdk-ready')
|
105
|
+
const prepUsernameInput = document.getElementById('prep-username-input')
|
106
|
+
const prepCheckboxesParent = document.querySelector('.prep-checkboxes')
|
107
|
+
|
108
|
+
// change these values to connect to your room
|
109
|
+
const TEAM = 'some-team';
|
110
|
+
const ROOM = 'some-room';
|
111
|
+
let ROOM_URL = 'https://localhost:3000/Public'
|
112
|
+
|
113
|
+
if(window.location.search) {
|
114
|
+
const params = new URLSearchParams(window.location.search);
|
115
|
+
const dynamicRoomUrl = params.get('roomUrl');
|
116
|
+
if(dynamicRoomUrl) {
|
117
|
+
ROOM_URL = dynamicRoomUrl
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
//const api = new DigitalSambaEmbedded({ root: parent, team: TEAM, room: ROOM});
|
122
|
+
// const api = new DigitalSambaEmbedded({ frame});
|
123
|
+
//const api = new DigitalSambaEmbedded({ url: ROOM_URL}, {reportErrors: true});
|
124
|
+
|
125
|
+
const prepCheckboxes = [
|
126
|
+
{control: 'micEnabled', label: 'Microphone enabled by default'},
|
127
|
+
{control: 'cameraEnabled', label: 'Camera enabled by default'},
|
128
|
+
{control: 'showToolbar', label: 'Show toolbar'},
|
129
|
+
{control: 'showCaptions', label: 'Show captions'},
|
130
|
+
];
|
131
|
+
|
132
|
+
prepCheckboxes.forEach(control => {
|
133
|
+
const label = document.createElement('label');
|
134
|
+
label.style.display = 'block'
|
135
|
+
label.htmlFor = 'prep-' + control.control;
|
136
|
+
label.innerHTML = '<span>' + control.label + '</span>'
|
137
|
+
|
138
|
+
|
139
|
+
const field = document.createElement('input');
|
140
|
+
field.type = 'checkbox';
|
141
|
+
field.id = 'prep-' + control.control;
|
142
|
+
|
143
|
+
field.onchange = (e) => {
|
144
|
+
initialRoomState[control.control] = e.target.checked
|
145
|
+
}
|
146
|
+
|
147
|
+
label.appendChild(field);
|
148
|
+
prepCheckboxesParent.appendChild(label)
|
149
|
+
|
150
|
+
})
|
151
|
+
|
152
|
+
prepButton.onclick = () => {
|
153
|
+
prepBlock.style.display = 'none'
|
154
|
+
controlsBlock.style.display = 'block'
|
155
|
+
|
156
|
+
createControl()
|
157
|
+
}
|
158
|
+
|
159
|
+
prepUsernameInput.onchange = (e) => {
|
160
|
+
initialRoomState.username = e.target.value
|
161
|
+
|
162
|
+
console.warn(initialRoomState, '.,s')
|
163
|
+
}
|
164
|
+
|
165
|
+
|
166
|
+
const createControl = () => {
|
167
|
+
const api = DigitalSambaEmbedded.createControl({ url: ROOM_URL, root: parent, roomSettings: initialRoomState });
|
168
|
+
|
169
|
+
const log = document.querySelector('.log');
|
170
|
+
|
171
|
+
api.frame.width = 900;
|
172
|
+
api.frame.height = 700;
|
173
|
+
|
174
|
+
btn0.onclick = () => {api.load({ frameAttributes: {style: "border: 5px solid red"}, reportErrors: true })}
|
175
|
+
|
176
|
+
const baseControls = [
|
177
|
+
{command: 'toggleVideo', label: 'toggle video' },
|
178
|
+
{command: 'enableVideo', label: 'enable video' },
|
179
|
+
{command: 'disableVideo', label: 'disable video' },
|
180
|
+
{command: 'toggleAudio', label: 'toggle audio' },
|
181
|
+
{command: 'enableAudio', label: 'enable audio' },
|
182
|
+
{command: 'disableAudio', label: 'disable audio' },
|
183
|
+
{command: 'startScreenshare', label: 'start screenshare' },
|
184
|
+
{command: 'stopScreenshare', label: 'stop screenshare' },
|
185
|
+
{command: 'startRecording', label: 'start recording' },
|
186
|
+
{command: 'stopRecording', label: 'stop recording' },
|
187
|
+
{command: 'showToolbar', label: 'show toolbar' },
|
188
|
+
{command: 'hideToolbar', label: 'hide toolbar' },
|
189
|
+
{command: 'toggleToolbar', label: 'toggle toolbar' },
|
190
|
+
{command: 'changeLayoutMode', label: 'auto layout', args: ['auto'] },
|
191
|
+
{command: 'changeLayoutMode', label: 'tiled layout', args: ['tiled'] },
|
192
|
+
{command: 'showCaptions', label: 'show captions'},
|
193
|
+
{command: 'hideCaptions', label: 'hide captions'},
|
194
|
+
{command: 'toggleCaptions', label: 'toggle captions'},
|
195
|
+
{command: 'leaveSession', label: 'leave session' },
|
196
|
+
{command: 'endSession', label: 'end session' },
|
197
|
+
]
|
198
|
+
|
199
|
+
baseControls.forEach(control => {
|
200
|
+
const button = document.createElement("button");
|
201
|
+
button.innerHTML = control.label;
|
202
|
+
button.onclick = () => api[control.command](...(control.args || []))
|
203
|
+
|
204
|
+
buttonsParent.appendChild(button);
|
205
|
+
})
|
206
|
+
|
207
|
+
const captionsControls = [
|
208
|
+
{command: 'configureCaptions', label: 'set font size - small', args: [{fontSize: 'small'}] },
|
209
|
+
{command: 'configureCaptions', label: 'set font size - medium', args: [{fontSize: 'medium'}] },
|
210
|
+
{command: 'configureCaptions', label: 'set font size - large', args: [{fontSize: 'large'}] },
|
211
|
+
{command: 'configureCaptions', label: 'set spoken language - english', args: [{spokenLanguage: 'en'}] },
|
212
|
+
{command: 'configureCaptions', label: 'set spoken language - french', args: [{spokenLanguage: 'fr'}] },
|
213
|
+
{command: 'configureCaptions', label: 'set spoken language - spanish', args: [{spokenLanguage: 'es'}] },
|
214
|
+
]
|
215
|
+
|
216
|
+
captionsControls.forEach(control => {
|
217
|
+
const button = document.createElement("button");
|
218
|
+
button.innerHTML = control.label;
|
219
|
+
button.onclick = () => api[control.command](...(control.args || []))
|
220
|
+
|
221
|
+
captionsButtonsParent.appendChild(button);
|
222
|
+
})
|
223
|
+
|
224
|
+
api.on('*', (data) => {
|
225
|
+
log.innerHTML += `<p>${Number(new Date)}: ev(${data?.type}): ${JSON.stringify(data)}</p>`
|
226
|
+
});
|
227
|
+
|
228
|
+
api.on('userJoined', (data) => {
|
229
|
+
log.innerHTML += `<p>${Number(new Date)}: USER JOINED: ${JSON.stringify(data)}</p>`
|
230
|
+
});
|
231
|
+
|
232
|
+
api.on('userLeft', (data) => {
|
233
|
+
log.innerHTML += `<p>${Number(new Date)}: USER LEFT: ${JSON.stringify(data)}</p>`
|
234
|
+
});
|
235
|
+
|
236
|
+
api.on('permissionsChanged', ({ data }) => {
|
237
|
+
if(data.broadcast !== undefined){
|
238
|
+
if(data.broadcast) {
|
239
|
+
alert('You were granted broadcast permission')
|
240
|
+
} else {
|
241
|
+
alert('Your permission to broadcast was rejected')
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
if(data.screenshare !== undefined){
|
246
|
+
if(data.screenshare) {
|
247
|
+
alert('You were granted screenshare permission')
|
248
|
+
} else {
|
249
|
+
alert('Your permission to screenshare was rejected')
|
250
|
+
}
|
251
|
+
}
|
252
|
+
});
|
253
|
+
|
254
|
+
|
255
|
+
api.on('usersUpdated', ({data: {users}}) => {
|
256
|
+
participantList.innerHTML = '';
|
257
|
+
|
258
|
+
|
259
|
+
users.forEach(user => {
|
260
|
+
const row = document.createElement('div');
|
261
|
+
row.className = 'user-list-row';
|
262
|
+
|
263
|
+
const avatar = document.createElement('span');
|
264
|
+
avatar.className = 'user-list-avatar';
|
265
|
+
avatar.style.background = user.avatarColor;
|
266
|
+
row.appendChild(avatar);
|
267
|
+
|
268
|
+
|
269
|
+
const name = document.createElement('span');
|
270
|
+
name.className = 'user-list-name';
|
271
|
+
name.innerText = user.name;
|
272
|
+
row.appendChild(name);
|
273
|
+
|
274
|
+
if(user.kind === 'local') {
|
275
|
+
const label = document.createElement('span');
|
276
|
+
label.className = 'user-list-label';
|
277
|
+
label.innerText = '(you)'
|
278
|
+
label.style.color = '#777';
|
279
|
+
row.appendChild(label);
|
280
|
+
} else {
|
281
|
+
const micControl = document.createElement('button');
|
282
|
+
micControl.innerHTML = 'toggle mic'
|
283
|
+
micControl.style.margin = '0 4px';
|
284
|
+
micControl.onclick = () => {api.requestToggleAudio(user.id)}
|
285
|
+
row.appendChild(micControl);
|
286
|
+
|
287
|
+
const kickControl = document.createElement('button');
|
288
|
+
kickControl.innerHTML = 'kick'
|
289
|
+
kickControl.style.margin = '0 4px';
|
290
|
+
kickControl.onclick = () => {api.removeUser(user.id)}
|
291
|
+
row.appendChild(kickControl);
|
292
|
+
}
|
293
|
+
|
294
|
+
participantList.appendChild(row);
|
295
|
+
|
296
|
+
})
|
297
|
+
})
|
298
|
+
}
|
299
|
+
|
300
|
+
</script>
|
301
|
+
|
302
|
+
</body>
|
303
|
+
</html>
|