@reactoo/watchtogether-sdk-js 2.6.75 → 2.6.76
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.
|
@@ -2,733 +2,789 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
|
|
4
4
|
<head>
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>The Bulk Join 2</title>
|
|
7
7
|
<script src="../../dist/watchtogether-sdk.js"></script>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
<style>.--high-quality{display:none}</style>
|
|
8
|
+
<link rel="stylesheet" href="./bulk_join_room_2.css">
|
|
11
9
|
</head>
|
|
12
10
|
|
|
13
11
|
<body>
|
|
14
12
|
<div class="app-wrapper">
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
13
|
+
<div class="settings">
|
|
14
|
+
<div class="heading">Settings</div>
|
|
15
|
+
|
|
16
|
+
<div class="form-group">
|
|
17
|
+
<label for="participants-count">Participants count</label>
|
|
18
|
+
<input type="number" id="participants-count" onchange="applySettingsFromForm()">
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="form-group --advanced --high-quality">
|
|
22
|
+
<label for="participants-high-quality">High quality</label>
|
|
23
|
+
<input type="checkbox" id="participants-high-quality" onchange="applySettingsFromForm()">
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="form-group --advanced">
|
|
27
|
+
<label for="participants-order-randomization">Participants order randomization</label>
|
|
28
|
+
<input type="checkbox" id="participants-order-randomization" onchange="applySettingsFromForm()">
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div class="form-group">
|
|
33
|
+
<label for="room-id">Room ID</label>
|
|
34
|
+
<input type="text" id="room-id" onchange="applySettingsFromForm()">
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="form-group --advanced">
|
|
38
|
+
<label for="pin-hash">Pin hash</label>
|
|
39
|
+
<input type="text" id="pin-hash" placeholder="Not required" onchange="applySettingsFromForm()">
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div class="form-group --advanced">
|
|
43
|
+
<label for="room-id">Connection delay (seconds)</label>
|
|
44
|
+
<input type="number" id="connection-delay" min="0" step="0.25" onchange="applySettingsFromForm()">
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div class="form-group --advanced">
|
|
48
|
+
<label for="parallel-queues">Parallel connection queues</label>
|
|
49
|
+
<input type="number" id="parallel-queues" min="1" step="4" onchange="applySettingsFromForm()">
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div class="form-group --advanced">
|
|
53
|
+
<label for="instance-type">Instance type</label>
|
|
54
|
+
<input type="text" id="instance-type" onchange="applySettingsFromForm()">
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<div class="form-group --advanced">
|
|
58
|
+
<label for="swagger-url">Swagger URL</label>
|
|
59
|
+
<input type="text" id="swagger-url" onchange="applySettingsFromForm()">
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div class="form-group --advanced">
|
|
63
|
+
<label for="fetch-names">Fetch participants names</label>
|
|
64
|
+
<input type="checkbox" id="fetch-names" onchange="applySettingsFromForm()">
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div class="form-group">
|
|
68
|
+
<button type="button" class="--advanced" onclick="resetSettings()">Reset settings</button>
|
|
69
|
+
<button type="button" class="--high-quality" onclick="toggleAdvancedSettings()">Toggle advanced settings</button>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="participants-controls">
|
|
75
|
+
<div class="heading">Participants controls</div>
|
|
76
|
+
<div class="form-group">
|
|
77
|
+
<button type="button" onclick="createParticipants()">Create participants (without connect)</button>
|
|
78
|
+
<button type="button" onclick="destroyParticipants()">Destroy participants</button>
|
|
79
|
+
<br class="--advanced">
|
|
80
|
+
<button type="button" class="--advanced" onclick="createSingleParticipant()">Create single participant (without connect)</button>
|
|
81
|
+
<br>
|
|
82
|
+
<button type="button" onclick="joinParticipantsToRoom()">Join all participants to room</button>
|
|
83
|
+
<button type="button" onclick="disconnectParticipantsFromRoom()">Disconnect all participants from room</button>
|
|
84
|
+
<br class="--advanced">
|
|
85
|
+
<div class="form-group --advanced">
|
|
86
|
+
<label for="participants-names">Participants names (one name per line)</label>
|
|
87
|
+
<textarea id="participants-names" rows="5" onchange="applySettingsFromForm()"></textarea>
|
|
88
|
+
</div>
|
|
89
|
+
<button type="button" class="--advanced" onclick="setParticipantsNames()">Set Participants Names</button>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<div class="heading --advanced">Room controls</div>
|
|
93
|
+
<div class="form-group --advanced">
|
|
94
|
+
<button type="button" onclick="initiateFakeChat()">Initiate fake chat</button>
|
|
95
|
+
</div>
|
|
96
|
+
<div class="form-group --advanced">
|
|
97
|
+
<label for="emoji-sparking-interval">Emoji sparking interval (seconds)</label>
|
|
98
|
+
<input type="number" id="emoji-sparking-interval" min="5" step="1" onchange="applySettingsFromForm()">
|
|
99
|
+
|
|
100
|
+
<button type="button" onclick="enableEmojiSparking()">Enable Emoji Sparking</button>
|
|
101
|
+
<button type="button" onclick="disableEmojiSparking()">Disable Emoji Sparking</button>
|
|
102
|
+
<button type="button" onclick="burstEmojiSparking()">Burst Emoji Sparking</button>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<div class="participants-list-container">
|
|
107
|
+
<div class="heading">Participants</div>
|
|
108
|
+
<div id="participants-list"></div>
|
|
109
|
+
</div>
|
|
104
110
|
</div>
|
|
105
111
|
|
|
106
112
|
<script>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
113
|
+
// https://github.com/w3c/webcodecs/blob/f73dd2ccea32c0652ef94d48b87d728e4f709569/samples/image-decoder/animated-gif-renderer.html
|
|
114
|
+
|
|
115
|
+
// ====================== Configuration ===================================
|
|
116
|
+
|
|
117
|
+
const settingsUrlParameterName = 'settings';
|
|
118
|
+
|
|
119
|
+
const defaultSettings = {
|
|
120
|
+
advancedSettings: false,
|
|
121
|
+
participantsCount: 5,
|
|
122
|
+
participantsHighQuality: false,
|
|
123
|
+
participantsOrderRandomization: false,
|
|
124
|
+
minParticipantsCount: 1,
|
|
125
|
+
maxParticipantsCount: 41,
|
|
126
|
+
roomId: "",
|
|
127
|
+
pinHash: "",
|
|
128
|
+
connectionDelay: 1,
|
|
129
|
+
parallelQueues: 1, // number of parallel queues for joining participants - only applied when connectionDelay is 0
|
|
130
|
+
instanceType: "reactooDemo",
|
|
131
|
+
swaggerUrl: "https://api.reactoo.com/v3/swagger.json",
|
|
132
|
+
fetchNames: false,
|
|
133
|
+
participantsNames: [],
|
|
134
|
+
emojiSparkingInterval: 180,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const gifsCount_lq = 32; // Number of gifs in ./persons_gifs_lq folder
|
|
138
|
+
const gifsCount_hq = 17; // Number of gifs in ./persons_gifs_hq folder
|
|
139
|
+
let gifsCount = gifsCount_hq + gifsCount_lq;
|
|
140
|
+
const sparkingEmojis = ['laugh', 'love', 'wow', 'clap', 'thumbsup', 'thumbsdown', 'fire'];
|
|
141
|
+
|
|
142
|
+
// ====================== General Variables ===============================
|
|
143
|
+
|
|
144
|
+
let settings;
|
|
145
|
+
|
|
146
|
+
const elements = {
|
|
147
|
+
form: {
|
|
148
|
+
participantsCount: document.getElementById("participants-count"),
|
|
149
|
+
participantsHighQuality: document.getElementById("participants-high-quality"),
|
|
150
|
+
participantsOrderRandomization: document.getElementById("participants-order-randomization"),
|
|
151
|
+
roomId: document.getElementById("room-id"),
|
|
152
|
+
pinHash: document.getElementById("pin-hash"),
|
|
153
|
+
connectionDelay: document.getElementById("connection-delay"),
|
|
154
|
+
parallelQueues: document.getElementById("parallel-queues"),
|
|
155
|
+
instanceType: document.getElementById("instance-type"),
|
|
156
|
+
swaggerUrl: document.getElementById("swagger-url"),
|
|
157
|
+
fetchNames: document.getElementById("fetch-names"),
|
|
158
|
+
participantsNames: document.getElementById("participants-names"),
|
|
159
|
+
emojiSparkingInterval: document.getElementById("emoji-sparking-interval"),
|
|
160
|
+
},
|
|
161
|
+
participantsList: document.getElementById("participants-list"),
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const participants = new Array(gifsCount).fill(undefined);
|
|
165
|
+
|
|
166
|
+
let usedGifsIds = [];
|
|
167
|
+
|
|
168
|
+
let usedGifsTimes = 0;
|
|
169
|
+
|
|
170
|
+
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
171
|
+
|
|
172
|
+
// ====================== Helper Functions ================================
|
|
173
|
+
|
|
174
|
+
function getUrlParameter(varName){
|
|
175
|
+
const queryStr = decodeURI(window.location.search) + '&';
|
|
176
|
+
const regex = new RegExp('.*?[&\\?]' + varName + '=(.*?)&.*');
|
|
177
|
+
const val = queryStr.replace(regex, "$1");
|
|
178
|
+
return val === queryStr ? false : val;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ====================== Settings Functions ==============================
|
|
182
|
+
|
|
183
|
+
function applySettingsFromForm() {
|
|
184
|
+
settings = {
|
|
185
|
+
advancedSettings: !!settings.advancedSettings,
|
|
186
|
+
participantsCount: parseInt(elements.form.participantsCount.value) || defaultSettings.participantsCount,
|
|
187
|
+
participantsHighQuality: elements.form.participantsHighQuality.checked,
|
|
188
|
+
participantsOrderRandomization: elements.form.participantsOrderRandomization.checked,
|
|
189
|
+
minParticipantsCount: parseInt(settings.minParticipantsCount) || defaultSettings.minParticipantsCount,
|
|
190
|
+
maxParticipantsCount: parseInt(settings.maxParticipantsCount) || defaultSettings.maxParticipantsCount,
|
|
191
|
+
roomId: elements.form.roomId.value || defaultSettings.roomId,
|
|
192
|
+
pinHash: elements.form.pinHash.value || defaultSettings.pinHash,
|
|
193
|
+
connectionDelay: parseFloat(elements.form.connectionDelay.value) || defaultSettings.connectionDelay,
|
|
194
|
+
parallelQueues: parseInt(elements.form.parallelQueues.value) || defaultSettings.parallelQueues,
|
|
195
|
+
instanceType: elements.form.instanceType.value || defaultSettings.instanceType,
|
|
196
|
+
swaggerUrl: elements.form.swaggerUrl.value || defaultSettings.swaggerUrl,
|
|
197
|
+
fetchNames: elements.form.fetchNames.checked,
|
|
198
|
+
participantsNames: elements.form.participantsNames.value.split("\n") || "",
|
|
199
|
+
emojiSparkingInterval: parseFloat(elements.form.emojiSparkingInterval.value) || defaultSettings.emojiSparkingInterval,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
setSettingsToUrl(false);
|
|
203
|
+
fillSettingsForm();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function setSettingsToUrl(deleteInstead = false) {
|
|
207
|
+
const url = new URL(location.href);
|
|
208
|
+
if (deleteInstead) {
|
|
209
|
+
url.searchParams.delete(settingsUrlParameterName);
|
|
210
|
+
} else {
|
|
211
|
+
url.searchParams.set(settingsUrlParameterName, JSON.stringify(settings));
|
|
212
|
+
}
|
|
213
|
+
history.replaceState (null, '', url);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function getSettingsFromUrl() {
|
|
217
|
+
let settingsFromUrl = getUrlParameter(settingsUrlParameterName);
|
|
218
|
+
|
|
219
|
+
if (settingsFromUrl && typeof settingsFromUrl === 'string') {
|
|
220
|
+
settingsFromUrl = JSON.parse(decodeURIComponent(settingsFromUrl.replace(/\+/g, ' ')));
|
|
221
|
+
|
|
222
|
+
if (settingsFromUrl && typeof settingsFromUrl === 'object' && !Array.isArray(settingsFromUrl)) {
|
|
223
|
+
settings = {...settings, ...settingsFromUrl};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function initializeSettings() {
|
|
229
|
+
settings = {...defaultSettings};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function resetSettings() {
|
|
233
|
+
initializeSettings();
|
|
234
|
+
setSettingsToUrl(true);
|
|
235
|
+
fillSettingsForm();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function toggleAdvancedSettings() {
|
|
239
|
+
const advancedSettings = settings.advancedSettings;
|
|
240
|
+
const participantsCount = settings.participantsCount;
|
|
241
|
+
const roomId = settings.roomId;
|
|
242
|
+
|
|
243
|
+
resetSettings();
|
|
244
|
+
|
|
245
|
+
settings.advancedSettings = !advancedSettings;
|
|
246
|
+
settings.participantsCount = participantsCount;
|
|
247
|
+
settings.roomId = roomId;
|
|
248
|
+
|
|
249
|
+
setSettingsToUrl(false);
|
|
250
|
+
location.reload();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function fillSettingsForm() {
|
|
254
|
+
elements.form.participantsCount.value = settings.participantsCount;
|
|
255
|
+
elements.form.participantsHighQuality.checked = settings.participantsHighQuality;
|
|
256
|
+
elements.form.participantsOrderRandomization.checked = settings.participantsOrderRandomization;
|
|
257
|
+
elements.form.roomId.value = settings.roomId;
|
|
258
|
+
elements.form.pinHash.value = settings.pinHash;
|
|
259
|
+
elements.form.connectionDelay.value = settings.connectionDelay;
|
|
260
|
+
elements.form.parallelQueues.value = settings.parallelQueues;
|
|
261
|
+
elements.form.instanceType.value = settings.instanceType;
|
|
262
|
+
elements.form.swaggerUrl.value = settings.swaggerUrl;
|
|
263
|
+
elements.form.fetchNames.checked = settings.fetchNames;
|
|
264
|
+
elements.form.participantsNames.value = settings.participantsNames.join("\n");
|
|
265
|
+
elements.form.emojiSparkingInterval.value = settings.emojiSparkingInterval;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// ====================== Main Logic ==================================
|
|
269
|
+
|
|
270
|
+
function getRandomNotUsedGifId() {
|
|
271
|
+
|
|
272
|
+
if (settings.participantsHighQuality){
|
|
273
|
+
gifsCount = gifsCount_hq;
|
|
274
|
+
} else {
|
|
275
|
+
gifsCount = gifsCount_lq;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (usedGifsIds.length >= gifsCount) {
|
|
279
|
+
usedGifsIds = [];
|
|
280
|
+
usedGifsTimes++;
|
|
281
|
+
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const availableGifsIds = new Array(gifsCount).fill().map((_, index) => index+1).filter(e => !usedGifsIds.includes(e));
|
|
285
|
+
let randomNotUsedGifId;
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
if (settings.participantsOrderRandomization) {
|
|
289
|
+
randomNotUsedGifId = availableGifsIds[Math.floor(Math.random() * availableGifsIds.length)];
|
|
290
|
+
} else {
|
|
291
|
+
randomNotUsedGifId = Math.min(...availableGifsIds);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// console.log(randomNotUsedGifId);
|
|
295
|
+
|
|
296
|
+
if (randomNotUsedGifId) {
|
|
297
|
+
usedGifsIds.push(randomNotUsedGifId);
|
|
298
|
+
return randomNotUsedGifId;
|
|
299
|
+
} else {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function createParticipant(participantOrder) {
|
|
305
|
+
|
|
306
|
+
// const gifId = getRandomNotUsedGifId();
|
|
307
|
+
const gifId = getRandomNotUsedGifId() + usedGifsTimes * gifsCount;
|
|
308
|
+
|
|
309
|
+
if (gifId === null) {
|
|
310
|
+
return Promise.reject();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
let gifUrl;
|
|
314
|
+
|
|
315
|
+
if (settings.participantsHighQuality){
|
|
316
|
+
// console.log("hq");
|
|
317
|
+
gifUrl = `./persons_gifs_hq/${gifId - usedGifsTimes * gifsCount}.mp4`;
|
|
318
|
+
} else {
|
|
319
|
+
// console.log("lq");
|
|
320
|
+
gifUrl = `./persons_gifs_lq/${gifId - usedGifsTimes * gifsCount}.gif`;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const frameIndex = 0;
|
|
324
|
+
const sdkInstance = WatchTogetherSDK({debug: true, storagePrefix: `participant_${gifId}`, apiUrl: settings.swaggerUrl})({instanceType: settings.instanceType});
|
|
325
|
+
|
|
326
|
+
const containerElement = document.createElement('div');
|
|
327
|
+
containerElement.classList.add('participant-container');
|
|
328
|
+
containerElement.setAttribute('data-participant-id', gifId);
|
|
329
|
+
containerElement.style.order = participantOrder;
|
|
330
|
+
|
|
331
|
+
let canvasElement;
|
|
332
|
+
let canvasContext;
|
|
333
|
+
|
|
334
|
+
if (settings.participantsHighQuality){
|
|
335
|
+
canvasElement = document.createElement('video')
|
|
336
|
+
canvasElement.setAttribute('title', `Video ID - ` + gifId);
|
|
337
|
+
canvasElement.src = gifUrl;
|
|
338
|
+
canvasElement.muted = false;
|
|
339
|
+
canvasElement.height = 270;
|
|
340
|
+
canvasElement.width = 480;
|
|
341
|
+
canvasElement.autoplay = true;
|
|
342
|
+
canvasElement.loop = true;
|
|
343
|
+
containerElement.appendChild(canvasElement);
|
|
344
|
+
// console.log(canvasElement);
|
|
345
|
+
} else {
|
|
346
|
+
canvasElement = document.createElement('canvas');
|
|
347
|
+
canvasElement.setAttribute('title', `Gif ID - ` + gifId);
|
|
348
|
+
canvasContext = canvasElement.getContext('2d');
|
|
349
|
+
containerElement.appendChild(canvasElement);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// const canvasElement = document.createElement('canvas');
|
|
353
|
+
// canvasElement.setAttribute('title', `Gif ID - ` + gifId);
|
|
354
|
+
// const canvasContext = canvasElement.getContext('2d');
|
|
355
|
+
// containerElement.appendChild(canvasElement);
|
|
356
|
+
|
|
357
|
+
let spaceElement = document.createElement('div');
|
|
358
|
+
spaceElement.classList.add('space');
|
|
359
|
+
containerElement.appendChild(spaceElement);
|
|
360
|
+
|
|
361
|
+
let participantNameElement;
|
|
362
|
+
participantNameElement = document.createElement('input');
|
|
363
|
+
participantNameElement.setAttribute('type', 'text');
|
|
364
|
+
participantNameElement.setAttribute('placeholder', 'Name');
|
|
365
|
+
participantNameElement.classList.add('--advanced');
|
|
366
|
+
containerElement.appendChild(participantNameElement);
|
|
367
|
+
|
|
368
|
+
const getNameButtonElement = document.createElement('button');
|
|
369
|
+
getNameButtonElement.innerText = 'Get name';
|
|
370
|
+
getNameButtonElement.addEventListener('click', () => {
|
|
371
|
+
sdkInstance.user.getUserSelf()
|
|
372
|
+
.then(response => {
|
|
373
|
+
participants[gifId].displayname = response.data.displayname;
|
|
374
|
+
participantNameElement.value = response.data.displayname;
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
getNameButtonElement.classList.add('--advanced');
|
|
378
|
+
containerElement.appendChild(getNameButtonElement);
|
|
379
|
+
|
|
380
|
+
const setNameButtonElement = document.createElement('button');
|
|
381
|
+
setNameButtonElement.innerText = 'Save name';
|
|
382
|
+
setNameButtonElement.addEventListener('click', () => sdkInstance.user.updateUserSelf({lastRoomId: settings.roomId, displayname: participantNameElement.value}));
|
|
383
|
+
setNameButtonElement.classList.add('--advanced');
|
|
384
|
+
containerElement.appendChild(setNameButtonElement);
|
|
385
|
+
|
|
386
|
+
spaceElement = document.createElement('div');
|
|
387
|
+
spaceElement.classList.add('space', '--advanced');
|
|
388
|
+
containerElement.appendChild(spaceElement);
|
|
389
|
+
|
|
390
|
+
const destroyButtonElement = document.createElement('button');
|
|
391
|
+
destroyButtonElement.innerText = 'Destroy';
|
|
392
|
+
destroyButtonElement.addEventListener('click', () => destroyParticipant(participants[gifId]));
|
|
393
|
+
destroyButtonElement.classList.add('--advanced');
|
|
394
|
+
containerElement.appendChild(destroyButtonElement);
|
|
395
|
+
|
|
396
|
+
const joinButtonElement = document.createElement('button');
|
|
397
|
+
joinButtonElement.innerText = 'Join';
|
|
398
|
+
joinButtonElement.addEventListener('click', () => joinParticipantToRoom(participants[gifId]));
|
|
399
|
+
joinButtonElement.classList.add('--advanced');
|
|
400
|
+
containerElement.appendChild(joinButtonElement);
|
|
401
|
+
|
|
402
|
+
const leaveButtonElement = document.createElement('button');
|
|
403
|
+
leaveButtonElement.innerText = 'Leave';
|
|
404
|
+
leaveButtonElement.addEventListener('click', () => disconnectParticipantFromRoom(participants[gifId]));
|
|
405
|
+
containerElement.appendChild(leaveButtonElement);
|
|
406
|
+
|
|
407
|
+
spaceElement = document.createElement('div');
|
|
408
|
+
spaceElement.classList.add('space', '--advanced');
|
|
409
|
+
containerElement.appendChild(spaceElement);
|
|
410
|
+
|
|
411
|
+
const toggleCameraButtonElement = document.createElement('button');
|
|
412
|
+
toggleCameraButtonElement.innerText = 'Toggle camera';
|
|
413
|
+
toggleCameraButtonElement.addEventListener('click', () => participants[gifId].session.toggleVideo());
|
|
414
|
+
toggleCameraButtonElement.classList.add('--advanced');
|
|
415
|
+
containerElement.appendChild(toggleCameraButtonElement);
|
|
416
|
+
|
|
417
|
+
const toggleAudioButtonElement = document.createElement('button');
|
|
418
|
+
toggleAudioButtonElement.innerText = 'Toggle audio';
|
|
419
|
+
toggleAudioButtonElement.addEventListener('click', () => participants[gifId].session.toggleAudio());
|
|
420
|
+
toggleAudioButtonElement.classList.add('--advanced');
|
|
421
|
+
containerElement.appendChild(toggleAudioButtonElement);
|
|
422
|
+
|
|
423
|
+
const toggleRaiseHandButtonElement = document.createElement('button');
|
|
424
|
+
toggleRaiseHandButtonElement.innerText = 'Toggle raise hand';
|
|
425
|
+
toggleRaiseHandButtonElement.addEventListener('click', () => {
|
|
426
|
+
sdkInstance.room.setUser({roomId: settings.roomId, userId: participants[gifId].sdkInstance.userId, flag: participants[gifId].handRaised ? 'handLower' : 'handRaise'});
|
|
427
|
+
participants[gifId].handRaised = !participants[gifId].handRaised;
|
|
428
|
+
});
|
|
429
|
+
toggleRaiseHandButtonElement.classList.add('--advanced');
|
|
430
|
+
containerElement.appendChild(toggleRaiseHandButtonElement);
|
|
431
|
+
|
|
432
|
+
const sparkEmojiButtonElement = document.createElement('button');
|
|
433
|
+
sparkEmojiButtonElement.innerText = 'Spark Emoji';
|
|
434
|
+
sparkEmojiButtonElement.addEventListener('click', () => {
|
|
435
|
+
sparkEmoji(participants[gifId]);
|
|
436
|
+
});
|
|
437
|
+
sparkEmojiButtonElement.classList.add('--advanced');
|
|
438
|
+
containerElement.appendChild(sparkEmojiButtonElement);
|
|
439
|
+
|
|
440
|
+
let participant;
|
|
441
|
+
|
|
442
|
+
if (settings.participantsHighQuality){
|
|
443
|
+
participant = {
|
|
444
|
+
gifId,
|
|
445
|
+
gifUrl,
|
|
446
|
+
frameIndex,
|
|
447
|
+
reverseOrder: false, // boomerang animation
|
|
448
|
+
width: canvasElement.width, // Will be set after first frame is decoded
|
|
449
|
+
height: canvasElement.height, // Will be set after first frame is decoded
|
|
450
|
+
canvas: canvasElement,
|
|
451
|
+
sdkInstance,
|
|
452
|
+
loginPromise: sdkInstance.auth.deviceLogin(false, gifId),
|
|
453
|
+
session: null, // Will be set after room join
|
|
454
|
+
handRaised: false,
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
if (settings.fetchNames) {
|
|
458
|
+
participant.loginPromise.then(() => sdkInstance.user.getUserSelf())
|
|
459
|
+
.then(response => {
|
|
460
|
+
participant.displayname = response.data.displayname;
|
|
461
|
+
participantNameElement.value = response.data.displayname;
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
elements.participantsList.appendChild(containerElement);
|
|
467
|
+
return Promise.resolve(participant);
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
} else {
|
|
471
|
+
return fetch(gifUrl)
|
|
472
|
+
.then(response => {
|
|
473
|
+
const imageDecoder = new ImageDecoder({data: response.body, type: 'image/gif'});
|
|
474
|
+
|
|
475
|
+
// if(typeof canvasElement !== "object") {
|
|
476
|
+
// console.log(settings.participantsHighQuality, typeof settings.participantsHighQuality, typeof canvasElement);
|
|
477
|
+
// }
|
|
478
|
+
|
|
479
|
+
participant = {
|
|
480
|
+
gifId,
|
|
481
|
+
gifUrl,
|
|
482
|
+
imageDecoder,
|
|
483
|
+
frameIndex,
|
|
484
|
+
reverseOrder: false, // boomerang animation
|
|
485
|
+
width: null, // Will be set after first frame is decoded
|
|
486
|
+
height: null, // Will be set after first frame is decoded
|
|
487
|
+
canvas: canvasElement,
|
|
488
|
+
canvasContext,
|
|
489
|
+
sdkInstance,
|
|
490
|
+
loginPromise: sdkInstance.auth.deviceLogin(false, gifId),
|
|
491
|
+
session: null, // Will be set after room join
|
|
492
|
+
handRaised: false,
|
|
493
|
+
emojiSparkingTimeoutId: null,
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
if (settings.fetchNames) {
|
|
497
|
+
participant.loginPromise.then(() => sdkInstance.user.getUserSelf())
|
|
498
|
+
.then(response => {
|
|
499
|
+
participant.displayname = response.data.displayname;
|
|
500
|
+
participantNameElement.value = response.data.displayname;
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return imageDecoder
|
|
505
|
+
.decode({frameIndex})
|
|
506
|
+
.then(decodeResult => {
|
|
507
|
+
participant.width = decodeResult.image.displayWidth;
|
|
508
|
+
participant.canvas.width = decodeResult.image.displayWidth;
|
|
509
|
+
|
|
510
|
+
participant.height = decodeResult.image.displayHeight;
|
|
511
|
+
participant.canvas.height = decodeResult.image.displayHeight;
|
|
512
|
+
|
|
513
|
+
participant.canvas.id = `canvas-${participant.gifId}`;
|
|
514
|
+
|
|
515
|
+
// Start render loop
|
|
516
|
+
renderGif(decodeResult, participant);
|
|
517
|
+
|
|
518
|
+
elements.participantsList.appendChild(containerElement);
|
|
519
|
+
return participant;
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function createParticipants(participantsCount = settings.participantsCount) {
|
|
527
|
+
|
|
528
|
+
destroyParticipants()
|
|
529
|
+
.then(() => {
|
|
530
|
+
for (let i = 0; i < participantsCount; i++) {
|
|
531
|
+
createParticipant(i).then(participant => {
|
|
532
|
+
participants[participant.gifId] = participant;
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
})
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function initiateFakeChat() {
|
|
539
|
+
req = "https://api.reactoo.com/v3/wt/room?demo=true&id=" + elements.form.roomId.value;
|
|
540
|
+
|
|
541
|
+
const sdkInstance = WatchTogetherSDK({debug: true, storagePrefix: `participant_fakeChat`, apiUrl: settings.swaggerUrl})({instanceType: settings.instanceType});
|
|
542
|
+
|
|
543
|
+
sdkInstance.auth.deviceLogin(false, "participant_fakeChat").then(() => {
|
|
544
|
+
sdkInstance.room.getRoomById(elements.form.roomId.value, elements.form.pinHash.value, undefined, true)
|
|
545
|
+
.then(response => {
|
|
546
|
+
console.log(response);
|
|
547
|
+
})
|
|
548
|
+
.catch(error => {
|
|
549
|
+
console.log(error);
|
|
550
|
+
});
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function createSingleParticipant() {
|
|
555
|
+
const participantOrder = participants.filter(p => p).length;
|
|
556
|
+
|
|
557
|
+
console.log(participantOrder);
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
createParticipant(participantOrder)
|
|
561
|
+
.then(participant => participants[participant.gifId] = participant);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
function destroyParticipant(participant) {
|
|
565
|
+
disconnectParticipantFromRoom(participant)
|
|
566
|
+
.then(() => {
|
|
567
|
+
if (participant.imageDecoder) {
|
|
568
|
+
participant.imageDecoder.close();
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
participant.sdkInstance.auth.logout();
|
|
572
|
+
usedGifsIds.splice(usedGifsIds.indexOf(participant.gifId), 1);
|
|
573
|
+
document.querySelector('.participant-container[data-participant-id="' + participant.gifId + '"]').remove();
|
|
574
|
+
|
|
575
|
+
participants[participant.gifId] = undefined;
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
function destroyParticipants() {
|
|
580
|
+
return disconnectParticipantsFromRoom()
|
|
581
|
+
.then(() => {
|
|
582
|
+
participants.filter(p => p).forEach(participant => {
|
|
583
|
+
if (participant.imageDecoder) {
|
|
584
|
+
participant.imageDecoder.close();
|
|
585
|
+
}
|
|
586
|
+
participant.sdkInstance.auth.logout();
|
|
587
|
+
usedGifsIds.splice(usedGifsIds.indexOf(participant.gifId), 1);
|
|
588
|
+
document.querySelector('.participant-container[data-participant-id="' + participant.gifId + '"]').remove();
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
for (let i = 0 ; i < participants.length ; i++) {
|
|
592
|
+
if (participants[i]) {
|
|
593
|
+
participants[i] = undefined;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
usedGifsTimes = 0;
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
function joinParticipantToRoom(participant) {
|
|
601
|
+
return participant.loginPromise.then(() => {
|
|
602
|
+
participant.sdkInstance.room.createSession({roomId: settings.roomId, pinHash: settings.pinHash})
|
|
603
|
+
.then(session => {
|
|
604
|
+
participant.session = session;
|
|
605
|
+
return Promise.all([session, session.connect()])
|
|
606
|
+
})
|
|
607
|
+
.then(([session, _]) => {
|
|
608
|
+
return getAudioStream()
|
|
609
|
+
.then(audioStream => {
|
|
610
|
+
participant.stream = participant.canvas.captureStream();
|
|
611
|
+
if (participant.stream.getAudioTracks().length === 0) {
|
|
612
|
+
participant.stream.addTrack(audioStream.getAudioTracks()[0]);
|
|
613
|
+
}
|
|
614
|
+
return session.publishLocal(participant.stream, 'camera0')
|
|
615
|
+
// .then(() => participant.session.toggleAudio(false));
|
|
616
|
+
});
|
|
617
|
+
});
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function joinParticipantsToRoom () {
|
|
622
|
+
if (settings.connectionDelay === 0 && settings.parallelQueues > 0) {
|
|
623
|
+
// Parallel join
|
|
624
|
+
|
|
625
|
+
const parallelQueues = new Array(participants.filter(p => p).length).fill().map(() => Promise.resolve());
|
|
626
|
+
|
|
627
|
+
for (let i = 0 ; i < participants.filter(p => p).length ; i++) {
|
|
628
|
+
const parallelQueueIndex = i % settings.parallelQueues;
|
|
629
|
+
parallelQueues[parallelQueueIndex] = parallelQueues[parallelQueueIndex]
|
|
630
|
+
.then(() => joinParticipantToRoom(participants.filter(p => p)[i]))
|
|
631
|
+
.then(() => new Promise(resolve => setTimeout(resolve, settings.connectionDelay * 1000)));
|
|
632
|
+
}
|
|
633
|
+
} else {
|
|
634
|
+
// Serial join
|
|
635
|
+
|
|
636
|
+
return participants.filter(p => p).reduce((promiseChain, participant) => {
|
|
637
|
+
return promiseChain.then(() => joinParticipantToRoom(participant))
|
|
638
|
+
.then(() => new Promise(resolve => setTimeout(resolve, settings.connectionDelay * 1000)));
|
|
639
|
+
}, Promise.resolve());
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function disconnectParticipantFromRoom(participant) {
|
|
644
|
+
if (participant && participant.loginPromise) {
|
|
645
|
+
return participant.loginPromise
|
|
646
|
+
.then(() => {
|
|
647
|
+
if (participant.session && participant.session.disconnect) {
|
|
648
|
+
return participant.session.disconnect();
|
|
649
|
+
}
|
|
650
|
+
})
|
|
651
|
+
.then(() => participant.session = null);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
function disconnectParticipantsFromRoom() {
|
|
656
|
+
return Promise.all(participants.filter(p => p).map(participant => disconnectParticipantFromRoom(participant)));
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
function renderGif(decodeResult, participant) {
|
|
660
|
+
participant.canvasContext.drawImage(decodeResult.image, 0, 0);
|
|
661
|
+
|
|
662
|
+
const track = participant.imageDecoder.tracks.selectedTrack;
|
|
663
|
+
|
|
664
|
+
if (!track) {
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// We check complete here since `frameCount` won't be stable until all data
|
|
669
|
+
// has been received. This may cause us to receive a RangeError during the
|
|
670
|
+
// decode() call below which needs to be handled.
|
|
671
|
+
if (participant.imageDecoder.complete) {
|
|
672
|
+
if (track.frameCount == 1) {
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
if ((participant.reverseOrder && participant.frameIndex - 1 <= 0) || (!participant.reverseOrder && participant.frameIndex + 1 >= track.frameCount)) {
|
|
677
|
+
participant.reverseOrder = !participant.reverseOrder;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
if (participant.reverseOrder) {
|
|
682
|
+
--participant.frameIndex;
|
|
683
|
+
} else {
|
|
684
|
+
++participant.frameIndex;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// Decode the next frame ahead of display so it's ready in time.
|
|
688
|
+
participant.imageDecoder.decode({frameIndex: participant.frameIndex})
|
|
689
|
+
.then( nextDecodeResult => setTimeout(_ => {
|
|
690
|
+
renderGif(nextDecodeResult, participant);
|
|
691
|
+
}, decodeResult.image.duration / 1000.0))
|
|
692
|
+
.catch(e => {
|
|
693
|
+
// We can end up requesting an imageIndex past the end since we're using
|
|
694
|
+
// a ReadableStrem from fetch(), when this happens just wrap around.
|
|
695
|
+
if (e instanceof RangeError) {
|
|
696
|
+
participant.frameIndex = 0;
|
|
697
|
+
participant.imageDecoder.decode({frameIndex: imageIndex}).then(decodeResult => renderGif(decodeResult, participant));
|
|
698
|
+
} else {
|
|
699
|
+
throw e;
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function setParticipantsNames() {
|
|
705
|
+
participants.filter(p => p).forEach((participant, participantOrder) => {
|
|
706
|
+
if (settings.participantsNames[participantOrder]) {
|
|
707
|
+
participant.sdkInstance.user.updateUserSelf({lastRoomId: settings.roomId, displayname: settings.participantsNames[participantOrder]});
|
|
708
|
+
} else {
|
|
709
|
+
console.log('Not enough names');
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function getAudioStream() {
|
|
715
|
+
return new Promise(resolve => {
|
|
716
|
+
const request = new XMLHttpRequest();
|
|
717
|
+
// https://ttsmp3.com/
|
|
718
|
+
request.open('GET', './sound_empty.mp3', true);
|
|
719
|
+
request.responseType = 'arraybuffer';
|
|
720
|
+
request.onload = function() {
|
|
721
|
+
audioContext.decodeAudioData(request.response)
|
|
722
|
+
.then(buffer => {
|
|
723
|
+
const streamDestination = audioContext.createMediaStreamDestination();
|
|
724
|
+
const source = audioContext.createBufferSource();
|
|
725
|
+
source.buffer = buffer;
|
|
726
|
+
source.connect(streamDestination);
|
|
727
|
+
source.loop = true;
|
|
728
|
+
source.start();
|
|
729
|
+
|
|
730
|
+
new Audio().srcObject = streamDestination.stream;
|
|
731
|
+
|
|
732
|
+
resolve(streamDestination.stream);
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
request.send();
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function sparkEmoji(participant, emoji = null) {
|
|
740
|
+
if (emoji === null) {
|
|
741
|
+
emoji = sparkingEmojis[Math.floor(Math.random() * sparkingEmojis.length)];
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
participant.sdkInstance.room.sendChatMessage({
|
|
745
|
+
roomId: settings.roomId,
|
|
746
|
+
message: `:emoji${emoji}:emoji`,
|
|
747
|
+
senderUserId: participant.sdkInstance.userId,
|
|
748
|
+
options: [50],
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
function enableEmojiSparking(participant = null) {
|
|
753
|
+
(participant ? [participant] : participants.filter(p => p)).forEach(participant => {
|
|
754
|
+
participant.emojiSparkingTimeoutId = setTimeout(() => {
|
|
755
|
+
sparkEmoji(participant);
|
|
756
|
+
enableEmojiSparking(participant);
|
|
757
|
+
}, Math.round((Math.random() * (settings.emojiSparkingInterval - 5) + 5) * 1000));
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function disableEmojiSparking() {
|
|
762
|
+
participants.filter(p => p).forEach(participant => {
|
|
763
|
+
clearTimeout(participant.emojiSparkingTimeoutId);
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
function burstEmojiSparking(participant = null, emoji = null) {
|
|
768
|
+
(participant ? [participant] : participants.filter(p => p)).forEach(participant => {
|
|
769
|
+
setTimeout(() => {
|
|
770
|
+
sparkEmoji(participant, emoji);
|
|
771
|
+
}, Math.round(Math.random() * 3000));
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// ====================== Initialization ==============================
|
|
776
|
+
|
|
777
|
+
document.addEventListener("DOMContentLoaded", function() {
|
|
778
|
+
initializeSettings();
|
|
779
|
+
getSettingsFromUrl();
|
|
780
|
+
|
|
781
|
+
if (!settings.advancedSettings) {
|
|
782
|
+
settings.participantsHighQuality = true;
|
|
783
|
+
document.head.insertAdjacentHTML("beforeend", `<style>.--advanced{display:none}</style>`)
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
fillSettingsForm();
|
|
787
|
+
});
|
|
732
788
|
|
|
733
789
|
</script>
|
|
734
790
|
|