@flashphoner/sfusdk-examples 2.0.56

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.
Files changed (40) hide show
  1. package/README.md +43 -0
  2. package/package.json +32 -0
  3. package/src/client/chat.js +67 -0
  4. package/src/client/config.json +26 -0
  5. package/src/client/controls.js +314 -0
  6. package/src/client/display.js +502 -0
  7. package/src/client/main.css +45 -0
  8. package/src/client/main.html +220 -0
  9. package/src/client/main.js +157 -0
  10. package/src/client/resources/details_close.png +0 -0
  11. package/src/client/resources/details_open.png +0 -0
  12. package/src/client/util.js +67 -0
  13. package/src/commons/js/config.js +81 -0
  14. package/src/commons/js/display.js +484 -0
  15. package/src/commons/js/util.js +202 -0
  16. package/src/commons/media/silence.mp3 +0 -0
  17. package/src/controller/dependencies/sigma/sigma.renderers.edgeLabels.min.js +1 -0
  18. package/src/controller/dependencies/sigma/sigma.renderers.parallelEdges.min.js +1 -0
  19. package/src/controller/dependencies/sigma/sigma.require.js +12076 -0
  20. package/src/controller/graph-view.js +32 -0
  21. package/src/controller/main.css +45 -0
  22. package/src/controller/main.html +79 -0
  23. package/src/controller/main.js +65 -0
  24. package/src/controller/parser.js +202 -0
  25. package/src/controller/resources/details_close.png +0 -0
  26. package/src/controller/resources/details_open.png +0 -0
  27. package/src/controller/rest.js +56 -0
  28. package/src/controller/table-view.js +64 -0
  29. package/src/controller/test-data.js +382 -0
  30. package/src/player/config.json +8 -0
  31. package/src/player/player.css +19 -0
  32. package/src/player/player.html +54 -0
  33. package/src/player/player.js +209 -0
  34. package/src/sfu.ts +28 -0
  35. package/src/two-way-streaming/config.json +34 -0
  36. package/src/two-way-streaming/two-way-streaming.css +26 -0
  37. package/src/two-way-streaming/two-way-streaming.html +72 -0
  38. package/src/two-way-streaming/two-way-streaming.js +375 -0
  39. package/tsconfig.json +15 -0
  40. package/webpack.config.js +40 -0
@@ -0,0 +1,484 @@
1
+ const initLocalDisplay = function(localDisplayElement){
2
+ const localDisplayDiv = localDisplayElement;
3
+ const localDisplays = {};
4
+
5
+ const removeLocalDisplay = function(id) {
6
+ let localDisplay = document.getElementById(localDisplays[id].id);
7
+ let video = localDisplay.getElementsByTagName("video");
8
+ if (video && video[0]) {
9
+ for (const [key, vTrack] of Object.entries(video[0].srcObject.getTracks())) {
10
+ vTrack.stop();
11
+ }
12
+ }
13
+ delete localDisplays[id];
14
+ localDisplay.remove();
15
+ }
16
+
17
+ const getAudioContainer = function() {
18
+ for (const [key, value] of Object.entries(localDisplays)) {
19
+ let video = value.getElementsByTagName("video");
20
+ if (video && video[0]) {
21
+ let audioStateButton = value.getElementsByTagName("button");
22
+ let audioTracks = video[0].srcObject.getAudioTracks();
23
+ if (!audioTracks || audioTracks.length === 0) {
24
+ return {
25
+ id: value.id,
26
+ video: video[0],
27
+ audioStateDisplay: audioStateButton[0]
28
+ }
29
+ }
30
+ }
31
+ }
32
+ };
33
+
34
+ const add = function(id, name, stream) {
35
+ if (stream.getAudioTracks().length > 0) {
36
+ let videoElement = getAudioContainer();
37
+ if (videoElement) {
38
+ let track = stream.getAudioTracks()[0];
39
+ videoElement.video.srcObject.addTrack(track);
40
+ videoElement.audioStateDisplay.innerHTML = audioStateText(stream);
41
+ track.addEventListener("ended", function() {
42
+ videoElement.video.srcObject.removeTrack(track);
43
+ videoElement.audioStateDisplay.innerHTML = "No audio";
44
+ //check video element has no tracks left
45
+ for (const [key, vTrack] of Object.entries(videoElement.video.srcObject.getTracks())) {
46
+ if (vTrack.readyState !== "ended") {
47
+ return;
48
+ }
49
+ }
50
+ removeLocalDisplay(videoElement.id);
51
+ });
52
+ return;
53
+ }
54
+ }
55
+
56
+ const coreDisplay = document.createElement('div');
57
+ coreDisplay.setAttribute("class","text-center");
58
+ coreDisplay.setAttribute("style","width: auto; height: auto;");
59
+ coreDisplay.id = stream.id;
60
+ const streamNameDisplay = document.createElement("div");
61
+ streamNameDisplay.innerHTML = "Name: " + name;
62
+ streamNameDisplay.setAttribute("class","text-center");
63
+ streamNameDisplay.setAttribute("style","width: auto; height: auto;");
64
+ coreDisplay.appendChild(streamNameDisplay);
65
+
66
+ const audioStateDisplay = document.createElement("button");
67
+ audioStateDisplay.innerHTML = audioStateText(stream);
68
+ audioStateDisplay.addEventListener('click', function(){
69
+ if (stream.getAudioTracks().length > 0) {
70
+ stream.getAudioTracks()[0].enabled = !(stream.getAudioTracks()[0].enabled);
71
+ audioStateDisplay.innerHTML = audioStateText(stream);
72
+ }
73
+ });
74
+ coreDisplay.appendChild(audioStateDisplay);
75
+
76
+ const streamDisplay = document.createElement('div');
77
+ streamDisplay.id = "stream-" + id;
78
+ streamDisplay.setAttribute("class","text-center");
79
+ streamDisplay.setAttribute("style","width: auto; height: auto;");
80
+ coreDisplay.appendChild(streamDisplay);
81
+ const video = document.createElement("video");
82
+ video.muted = true;
83
+ if(Browser().isSafariWebRTC()) {
84
+ video.setAttribute("playsinline", "");
85
+ video.setAttribute("webkit-playsinline", "");
86
+ }
87
+ streamDisplay.appendChild(video);
88
+ video.srcObject = stream;
89
+ video.onloadedmetadata = function (e) {
90
+ video.play();
91
+ };
92
+ stream.getTracks().forEach(function(track){
93
+ track.addEventListener("ended", function() {
94
+ video.srcObject.removeTrack(track);
95
+ //check video element has no tracks left
96
+ for (const [key, vTrack] of Object.entries(video.srcObject.getTracks())) {
97
+ if (vTrack.readyState !== "ended") {
98
+ return;
99
+ }
100
+ }
101
+ removeLocalDisplay(id);
102
+ });
103
+ });
104
+ video.addEventListener('resize', function (event) {
105
+ streamNameDisplay.innerHTML = "Name: " + name + "<br/>Max.resolution: " + video.videoWidth + "x" + video.videoHeight;
106
+ resizeVideo(event.target);
107
+ });
108
+ localDisplays[id] = coreDisplay;
109
+ localDisplayDiv.appendChild(coreDisplay);
110
+ return coreDisplay;
111
+ }
112
+
113
+ const stop = function () {
114
+ for (const [key, value] of Object.entries(localDisplays)) {
115
+ removeLocalDisplay(value.id);
116
+ }
117
+ }
118
+
119
+ const audioStateText = function (stream) {
120
+ if (stream.getAudioTracks().length > 0) {
121
+ if (stream.getAudioTracks()[0].enabled) {
122
+ return "Mute";
123
+ } else {
124
+ return "Unmute";
125
+ }
126
+ }
127
+ return "No audio";
128
+ }
129
+
130
+ return {
131
+ add: add,
132
+ stop: stop
133
+ }
134
+ }
135
+
136
+ const initRemoteDisplay = function(mainDiv, room, peerConnection) {
137
+ const constants = SFU.constants;
138
+ const remoteParticipants = {};
139
+ room.on(constants.SFU_ROOM_EVENT.ADD_TRACKS, function(e) {
140
+ console.log("Received ADD_TRACKS");
141
+ let participant = remoteParticipants[e.info.nickName];
142
+ if (!participant) {
143
+ participant = {};
144
+ participant.nickName = e.info.nickName;
145
+ participant.tracks = [];
146
+ participant.displays = [];
147
+ remoteParticipants[participant.nickName] = participant;
148
+ }
149
+ participant.tracks.push.apply(participant.tracks, e.info.info);
150
+ for (const pTrack of e.info.info) {
151
+ let createDisplay = true;
152
+ for (let i = 0; i < participant.displays.length; i++) {
153
+ let display = participant.displays[i];
154
+ if (pTrack.type === "VIDEO") {
155
+ if (display.hasVideo()) {
156
+ continue;
157
+ }
158
+ display.videoMid = pTrack.mid;
159
+ display.setTrackInfo(pTrack);
160
+ createDisplay = false;
161
+ break;
162
+ } else if (pTrack.type === "AUDIO") {
163
+ if (display.hasAudio()) {
164
+ continue;
165
+ }
166
+ display.audioMid = pTrack.mid;
167
+ createDisplay = false;
168
+ break;
169
+ }
170
+ }
171
+ if (!createDisplay) {
172
+ continue;
173
+ }
174
+ let display = createRemoteDisplay(participant.nickName, participant.nickName, mainDiv);
175
+ participant.displays.push(display);
176
+ if (pTrack.type === "VIDEO") {
177
+ display.videoMid = pTrack.mid;
178
+ display.setTrackInfo(pTrack);
179
+ } else if (pTrack.type === "AUDIO") {
180
+ display.audioMid = pTrack.mid;
181
+ }
182
+ }
183
+ }).on(constants.SFU_ROOM_EVENT.REMOVE_TRACKS, function(e) {
184
+ console.log("Received REMOVE_TRACKS");
185
+ const participant = remoteParticipants[e.info.nickName];
186
+ if (!participant) {
187
+ return;
188
+ }
189
+ for (const rTrack of e.info.info) {
190
+ for (let i = 0; i < participant.tracks.length; i++) {
191
+ if (rTrack.mid === participant.tracks[i].mid) {
192
+ participant.tracks.splice(i, 1);
193
+ break;
194
+ }
195
+ }
196
+ for (let i = 0; i < participant.displays.length; i++) {
197
+ let found = false;
198
+ const display = participant.displays[i];
199
+ if (display.audioMid === rTrack.mid) {
200
+ display.setAudio(null);
201
+ found = true;
202
+ } else if (display.videoMid === rTrack.mid) {
203
+ display.setVideo(null);
204
+ found = true;
205
+ }
206
+ if (found) {
207
+ if (!display.hasAudio() && !display.hasVideo()) {
208
+ display.dispose();
209
+ participant.displays.splice(i, 1);
210
+ }
211
+ break;
212
+ }
213
+ }
214
+ }
215
+ }).on(constants.SFU_ROOM_EVENT.LEFT, function(e) {
216
+ console.log("Received LEFT");
217
+ let participant = remoteParticipants[e.name];
218
+ if (!participant) {
219
+ return;
220
+ }
221
+ participant.displays.forEach(function(display){
222
+ display.dispose();
223
+ })
224
+ delete remoteParticipants[e.name];
225
+ }).on(constants.SFU_ROOM_EVENT.TRACK_QUALITY_STATE, function(e){
226
+ console.log("Received track quality state");
227
+ const participant = remoteParticipants[e.info.nickName];
228
+ if (!participant) {
229
+ return;
230
+ }
231
+
232
+ for (const rTrack of e.info.tracks) {
233
+ const mid = rTrack.mid;
234
+ for (let i = 0; i < participant.displays.length; i++) {
235
+ const display = participant.displays[i];
236
+ if (display.videoMid === mid) {
237
+ display.updateQualityInfo(rTrack.quality);
238
+ break;
239
+ }
240
+ }
241
+ }
242
+ });
243
+
244
+ const createRemoteDisplay = function(id, name, mainDiv) {
245
+ const cell = document.createElement("div");
246
+ cell.setAttribute("class", "text-center");
247
+ cell.id = id;
248
+ mainDiv.appendChild(cell);
249
+ const streamNameDisplay = document.createElement("div");
250
+ streamNameDisplay.innerHTML = "Published by: " + name;
251
+ streamNameDisplay.setAttribute("style","width:auto; height:auto;");
252
+ streamNameDisplay.setAttribute("class","text-center");
253
+ cell.appendChild(streamNameDisplay);
254
+ const qualityDisplay = document.createElement("div");
255
+ qualityDisplay.setAttribute("style","width:auto; height:auto;");
256
+ qualityDisplay.setAttribute("class","text-center");
257
+ cell.appendChild(qualityDisplay);
258
+
259
+ let qualityDivs = [];
260
+
261
+ const rootDisplay = document.createElement("div");
262
+ rootDisplay.setAttribute("style","width:auto; height:auto;");
263
+ rootDisplay.setAttribute("class","text-center");
264
+ cell.appendChild(rootDisplay);
265
+ const streamDisplay = document.createElement("div");
266
+ streamDisplay.setAttribute("style","width:auto; height:auto;");
267
+ streamDisplay.setAttribute("class","text-center");
268
+ rootDisplay.appendChild(streamDisplay);
269
+
270
+ let audio = null;
271
+ let video = null;
272
+ return {
273
+ dispose: function() {
274
+ cell.remove();
275
+ },
276
+ hide: function(value) {
277
+ if (value) {
278
+ cell.style.display = "none";
279
+ } else {
280
+ cell.style.display = "block";
281
+ }
282
+ },
283
+ setAudio: function(stream) {
284
+ if (audio) {
285
+ audio.remove();
286
+ }
287
+ if (!stream) {
288
+ audio = null;
289
+ this.audioMid = undefined;
290
+ return;
291
+ }
292
+ audio = document.createElement("audio");
293
+ audio.controls = "controls";
294
+ audio.muted = true;
295
+ audio.autoplay = true;
296
+ cell.appendChild(audio);
297
+ audio.srcObject = stream;
298
+ audio.onloadedmetadata = function (e) {
299
+ audio.play().then(function() {
300
+ audio.muted = false;
301
+ });
302
+ };
303
+ },
304
+ hasAudio: function() {
305
+ return audio !== null || this.audioMid !== undefined;
306
+ },
307
+ setVideo: function(stream) {
308
+ if (video) {
309
+ video.remove();
310
+ }
311
+
312
+ if (stream == null) {
313
+ video = null;
314
+ this.videoMid = undefined;
315
+ qualityDivs.forEach(function(div) {
316
+ div.remove();
317
+ });
318
+ qualityDivs = [];
319
+ return;
320
+ }
321
+ video = document.createElement("video");
322
+ video.muted = true;
323
+ if(Browser().isSafariWebRTC()) {
324
+ video.setAttribute("playsinline", "");
325
+ video.setAttribute("webkit-playsinline", "");
326
+ }
327
+ streamDisplay.appendChild(video);
328
+ video.srcObject = stream;
329
+ video.onloadedmetadata = function (e) {
330
+ video.play().then(function() {
331
+ video.muted = false;
332
+ });
333
+ };
334
+ video.addEventListener("resize", function (event) {
335
+ streamNameDisplay.innerHTML = "Published by: " + name + "<br/>Current resolution: " + video.videoWidth + "x" + video.videoHeight;
336
+ resizeVideo(event.target);
337
+ });
338
+ },
339
+ setTrackInfo: function(trackInfo) {
340
+ if (trackInfo && trackInfo.quality) {
341
+ for (let i = 0; i < trackInfo.quality.length; i++) {
342
+ const qualityDiv = document.createElement("button");
343
+ qualityDivs.push(qualityDiv);
344
+ qualityDiv.innerText = trackInfo.quality[i];
345
+ qualityDiv.setAttribute("style", "display:inline-block; border: solid; border-width: 1px");
346
+ qualityDiv.style.color = "red";
347
+ qualityDiv.addEventListener('click', function(){
348
+ console.log("Clicked on quality " + trackInfo.quality[i] + " trackId " + trackInfo.id);
349
+ if (qualityDiv.style.color === "red") {
350
+ return;
351
+ }
352
+ for (let c = 0; c < qualityDivs.length; c++) {
353
+ if (qualityDivs[c].style.color !== "red") {
354
+ qualityDivs[c].style.color = "gray";
355
+ }
356
+ }
357
+ qualityDiv.style.color = "blue";
358
+ room.changeQuality(trackInfo.id, trackInfo.quality[i]);
359
+ });
360
+ qualityDisplay.appendChild(qualityDiv);
361
+ }
362
+ }
363
+ },
364
+ updateQualityInfo: function(videoQuality) {
365
+ for (const qualityInfo of videoQuality) {
366
+ for (const qualityDiv of qualityDivs) {
367
+ if (qualityDiv.innerText === qualityInfo.quality){
368
+ if (qualityInfo.available === true) {
369
+ qualityDiv.style.color = "gray";
370
+ } else {
371
+ qualityDiv.style.color = "red";
372
+ }
373
+ break;
374
+ }
375
+ }
376
+ }
377
+ },
378
+ hasVideo: function() {
379
+ return video !== null || this.videoMid !== undefined;
380
+ },
381
+ audioMid: undefined,
382
+ videoMid: undefined
383
+ };
384
+ }
385
+
386
+ const stop = function() {
387
+ for (const [nickName, participant] of Object.entries(remoteParticipants)) {
388
+ participant.displays.forEach(function(display){
389
+ display.dispose();
390
+ });
391
+ delete remoteParticipants[nickName];
392
+ }
393
+ }
394
+
395
+ peerConnection.ontrack = ({transceiver}) => {
396
+ let rParticipant;
397
+ console.log("Attach remote track " + transceiver.receiver.track.id + " kind " + transceiver.receiver.track.kind + " mid " + transceiver.mid);
398
+ for (const [nickName, participant] of Object.entries(remoteParticipants)) {
399
+ for (const pTrack of participant.tracks) {
400
+ console.log("Participant " + participant.nickName + " track " + pTrack.id + " mid " + pTrack.mid);
401
+ if (pTrack.mid === transceiver.mid) {
402
+ rParticipant = participant;
403
+ break;
404
+ }
405
+ }
406
+ if (rParticipant) {
407
+ break;
408
+ }
409
+ }
410
+ if (rParticipant) {
411
+ for (const display of rParticipant.displays) {
412
+ if (transceiver.receiver.track.kind === "video") {
413
+ if (display.videoMid === transceiver.mid) {
414
+ let stream = new MediaStream();
415
+ stream.addTrack(transceiver.receiver.track);
416
+ display.setVideo(stream);
417
+ break;
418
+ }
419
+ } else if (transceiver.receiver.track.kind === "audio") {
420
+ if (display.audioMid === transceiver.mid) {
421
+ let stream = new MediaStream();
422
+ stream.addTrack(transceiver.receiver.track);
423
+ display.setAudio(stream);
424
+ break;
425
+ }
426
+ }
427
+ }
428
+ } else {
429
+ console.warn("Failed to find participant for track " + transceiver.receiver.track.id);
430
+ }
431
+ }
432
+
433
+ return {
434
+ stop: stop
435
+ }
436
+ }
437
+
438
+ const resizeVideo = function(video, width, height) {
439
+ if (!video.parentNode) {
440
+ return;
441
+ }
442
+ if (video instanceof HTMLCanvasElement) {
443
+ video.videoWidth = video.width;
444
+ video.videoHeight = video.height;
445
+ }
446
+ var display = video.parentNode;
447
+ var parentSize = {
448
+ w: display.parentNode.clientWidth,
449
+ h: display.parentNode.clientHeight
450
+ };
451
+ var newSize;
452
+ if (width && height) {
453
+ newSize = downScaleToFitSize(width, height, parentSize.w, parentSize.h);
454
+ } else {
455
+ newSize = downScaleToFitSize(video.videoWidth, video.videoHeight, parentSize.w, parentSize.h);
456
+ }
457
+ display.style.width = newSize.w + "px";
458
+ display.style.height = newSize.h + "px";
459
+
460
+ //vertical align
461
+ var margin = 0;
462
+ if (parentSize.h - newSize.h > 1) {
463
+ margin = Math.floor((parentSize.h - newSize.h) / 2);
464
+ }
465
+ display.style.margin = margin + "px auto";
466
+ console.log("Resize from " + video.videoWidth + "x" + video.videoHeight + " to " + display.offsetWidth + "x" + display.offsetHeight);
467
+ }
468
+
469
+ const downScaleToFitSize = function(videoWidth, videoHeight, dstWidth, dstHeight) {
470
+ var newWidth, newHeight;
471
+ var videoRatio = videoWidth / videoHeight;
472
+ var dstRatio = dstWidth / dstHeight;
473
+ if (dstRatio > videoRatio) {
474
+ newHeight = dstHeight;
475
+ newWidth = Math.floor(videoRatio * dstHeight);
476
+ } else {
477
+ newWidth = dstWidth;
478
+ newHeight = Math.floor(dstWidth / videoRatio);
479
+ }
480
+ return {
481
+ w: newWidth,
482
+ h: newHeight
483
+ };
484
+ }
@@ -0,0 +1,202 @@
1
+ const stripCodecs = function(sdp, codecs) {
2
+ if (!codecs.length) return sdp;
3
+ var sdpArray = sdp.split("\n");
4
+ var codecsArray = codecs.split(",");
5
+
6
+ //search and delete codecs line
7
+ var pt = [];
8
+ var i;
9
+ for (var p = 0; p < codecsArray.length; p++) {
10
+ console.log("Searching for codec " + codecsArray[p]);
11
+ for (i = 0; i < sdpArray.length; i++) {
12
+ if (sdpArray[i].search(new RegExp(codecsArray[p],'i')) !== -1 && sdpArray[i].indexOf("a=rtpmap") === 0) {
13
+ console.log(codecsArray[p] + " detected");
14
+ pt.push(sdpArray[i].match(/[0-9]+/)[0]);
15
+ sdpArray[i] = "";
16
+ }
17
+ }
18
+ }
19
+ if (pt.length) {
20
+ //searching for fmtp
21
+ for (p = 0; p < pt.length; p++) {
22
+ for (i = 0; i < sdpArray.length; i++) {
23
+ if (sdpArray[i].search("a=fmtp:" + pt[p]) !== -1 || sdpArray[i].search("a=rtcp-fb:" + pt[p]) !== -1) {
24
+ sdpArray[i] = "";
25
+ }
26
+ }
27
+ }
28
+
29
+ //delete entries from m= line
30
+ for (i = 0; i < sdpArray.length; i++) {
31
+ if (sdpArray[i].search("m=audio") !== -1 || sdpArray[i].search("m=video") !== -1) {
32
+ var mLineSplitted = sdpArray[i].split(" ");
33
+ var newMLine = "";
34
+ for (var m = 0; m < mLineSplitted.length; m++) {
35
+ if (pt.indexOf(mLineSplitted[m].trim()) === -1 || m <= 2) {
36
+ newMLine += mLineSplitted[m];
37
+ if (m < mLineSplitted.length - 1) {
38
+ newMLine = newMLine + " ";
39
+ }
40
+ }
41
+ }
42
+ sdpArray[i] = newMLine;
43
+ }
44
+ }
45
+ }
46
+
47
+ //normalize sdp after modifications
48
+ var result = "";
49
+ for (i = 0; i < sdpArray.length; i++) {
50
+ if (sdpArray[i] !== "") {
51
+ result += sdpArray[i] + "\n";
52
+ }
53
+ }
54
+ return result;
55
+ }
56
+
57
+ const stripVideoCodecsExcept = function (sdp, codec) {
58
+ let actualStripCodec = "rtx";
59
+ if (codec === "VP8") {
60
+ actualStripCodec += ",H264";
61
+ } else if (codec === "H264") {
62
+ actualStripCodec += ",VP8";
63
+ } else {
64
+ return sdp;
65
+ }
66
+ return stripCodecs(sdp, actualStripCodec);
67
+ }
68
+
69
+ //Set WCS URL
70
+ const setURL = function () {
71
+ var proto;
72
+ var url;
73
+ var port;
74
+ if (window.location.protocol == "http:") {
75
+ proto = "ws://";
76
+ port = "8080";
77
+ } else {
78
+ proto = "wss://";
79
+ port = "8443";
80
+ }
81
+
82
+ url = proto + window.location.hostname + ":" + port;
83
+ return url;
84
+ }
85
+
86
+ // Get URL parameter
87
+ const getUrlParam = function (name) {
88
+ var url = window.location.href;
89
+ name = name.replace(/[\[\]]/g, "\\$&");
90
+ var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
91
+ results = regex.exec(url);
92
+ if (!results) return null;
93
+ if (!results[2]) return '';
94
+ return decodeURIComponent(results[2].replace(/\+/g, " "));
95
+ }
96
+
97
+ // Generate simple uuid
98
+ const createUUID = function (length) {
99
+ var s = [];
100
+ var hexDigits = "0123456789abcdef";
101
+ for (var i = 0; i < 36; i++) {
102
+ s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
103
+ }
104
+ s[14] = "4";
105
+ s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
106
+ s[8] = s[13] = s[18] = s[23] = "-";
107
+
108
+ var uuid = s.join("");
109
+
110
+ return uuid.substring(0, length);
111
+ }
112
+
113
+ const Browser = function() {
114
+ const isIE = function () {
115
+ return /*@cc_on!@*/false || !!document.documentMode;
116
+ }
117
+
118
+ const isFirefox = function () {
119
+ return typeof InstallTrigger !== 'undefined';
120
+ }
121
+
122
+ const isChrome = function () {
123
+ return !!window.chrome && /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor) && !/OPR/.test(navigator.userAgent);
124
+ }
125
+
126
+ const isEdge = function () {
127
+ return !this.isIE() && !!window.StyleMedia;
128
+ }
129
+
130
+ const isOpera = function () {
131
+ return (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
132
+ }
133
+
134
+ const isiOS = function () {
135
+ return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
136
+ }
137
+
138
+ const isSafari = function () {
139
+ let userAgent = navigator.userAgent.toLowerCase();
140
+ return /(safari|applewebkit)/i.test(userAgent) && !userAgent.includes("chrome") && !userAgent.includes("android");
141
+ }
142
+
143
+ const isAndroid = function () {
144
+ return navigator.userAgent.toLowerCase().indexOf("android") > -1;
145
+ }
146
+
147
+ const isSafariWebRTC = function () {
148
+ return navigator.mediaDevices && this.isSafari();
149
+ }
150
+
151
+ const isSamsungBrowser = function () {
152
+ return /SamsungBrowser/i.test(navigator.userAgent);
153
+ }
154
+
155
+ const isAndroidFirefox = function () {
156
+ return this.isAndroid() && /Firefox/i.test(navigator.userAgent);
157
+ }
158
+
159
+ const isMobile = function () {
160
+ return this.isAndroid() || this.isiOS();
161
+ }
162
+
163
+ return {
164
+ isIE: isIE,
165
+ isFirefox: isFirefox,
166
+ isChrome: isChrome,
167
+ isEdge: isEdge,
168
+ isOpera: isOpera,
169
+ isSafari: isSafari,
170
+ isSafariWebRTC: isSafariWebRTC,
171
+ isSamsungBrowser: isSamsungBrowser,
172
+ isAndroid: isAndroid,
173
+ isiOS: isiOS,
174
+ isAndroidFirefox: isAndroidFirefox,
175
+ isMobile: isMobile
176
+ }
177
+ }
178
+
179
+
180
+ const playFirstSound = function (parent, preloader) {
181
+ return new Promise(function (resolve, reject) {
182
+ let audio = document.createElement("audio");
183
+ audio.controls = "controls";
184
+ audio.muted = true;
185
+ audio.hidden = true;
186
+ audio.preload = "auto";
187
+ audio.type="audio/mpeg";
188
+ if (preloader) {
189
+ audio.src = preloader;
190
+ parent.appendChild(audio);
191
+ audio.play().then(function() {
192
+ audio.remove();
193
+ resolve();
194
+ }).catch(function (e) {
195
+ console.error("Can't play preloader: " + e);
196
+ reject();
197
+ });
198
+ return;
199
+ }
200
+ resolve();
201
+ });
202
+ }
Binary file
@@ -0,0 +1 @@
1
+ (function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.settings");var b={defaultEdgeLabelColor:"#000",defaultEdgeLabelActiveColor:"#000",defaultEdgeLabelSize:10,edgeLabelSize:"fixed",edgeLabelSizePowRatio:1,edgeLabelThreshold:1};sigma.settings=sigma.utils.extend(sigma.settings||{},b),sigma.settings.drawEdgeLabels=!0}).call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.edges.labels"),sigma.canvas.edges.labels.curve=function(a,b,c,d,e){if("string"==typeof a.label){var f=e("prefix")||"",g=a[f+"size"]||1;if(!(g<e("edgeLabelThreshold"))){var h,i,j,k=b[f+"size"],l=b[f+"x"],m=b[f+"y"],n=c[f+"x"],o=c[f+"y"],p=n-l,q=o-m,r=l<n?1:-1,s={},t=.5;b.id===c.id?(s=sigma.utils.getSelfLoopControlPoints(l,m,k),i=sigma.utils.getPointOnBezierCurve(t,l,m,n,o,s.x1,s.y1,s.x2,s.y2),j=Math.atan2(1,1)):(s=sigma.utils.getQuadraticControlPoint(l,m,n,o),i=sigma.utils.getPointOnQuadraticCurve(t,l,m,n,o,s.x,s.y),j=Math.atan2(q*r,p*r)),h="fixed"===e("edgeLabelSize")?e("defaultEdgeLabelSize"):e("defaultEdgeLabelSize")*g*Math.pow(g,-1/e("edgeLabelSizePowRatio")),d.save(),a.active?(d.font=[e("activeFontStyle"),h+"px",e("activeFont")||e("font")].join(" "),d.fillStyle="edge"===e("edgeActiveColor")?a.active_color||e("defaultEdgeActiveColor"):e("defaultEdgeLabelActiveColor")):(d.font=[e("fontStyle"),h+"px",e("font")].join(" "),d.fillStyle="edge"===e("edgeLabelColor")?a.color||e("defaultEdgeColor"):e("defaultEdgeLabelColor")),d.textAlign="center",d.textBaseline="alphabetic",d.translate(i.x,i.y),d.rotate(j),d.fillText(a.label,0,-g/2-3),d.restore()}}}}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.edges.labels"),sigma.canvas.edges.labels.curvedArrow=function(a,b,c,d,e){sigma.canvas.edges.labels.curve(a,b,c,d,e)}}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.edges.labels"),sigma.canvas.edges.labels.def=function(a,b,c,d,e){if("string"==typeof a.label&&b!=c){var f=e("prefix")||"",g=a[f+"size"]||1;if(!(g<e("edgeLabelThreshold"))){if(0===e("edgeLabelSizePowRatio"))throw'"edgeLabelSizePowRatio" must not be 0.';var h,i=(b[f+"x"]+c[f+"x"])/2,j=(b[f+"y"]+c[f+"y"])/2,k=c[f+"x"]-b[f+"x"],l=c[f+"y"]-b[f+"y"],m=b[f+"x"]<c[f+"x"]?1:-1,n=Math.atan2(l*m,k*m);h="fixed"===e("edgeLabelSize")?e("defaultEdgeLabelSize"):e("defaultEdgeLabelSize")*g*Math.pow(g,-1/e("edgeLabelSizePowRatio")),d.save(),a.active?(d.font=[e("activeFontStyle"),h+"px",e("activeFont")||e("font")].join(" "),d.fillStyle="edge"===e("edgeActiveColor")?a.active_color||e("defaultEdgeActiveColor"):e("defaultEdgeLabelActiveColor")):(d.font=[e("fontStyle"),h+"px",e("font")].join(" "),d.fillStyle="edge"===e("edgeLabelColor")?a.color||e("defaultEdgeColor"):e("defaultEdgeLabelColor")),d.textAlign="center",d.textBaseline="alphabetic",d.translate(i,j),d.rotate(n),d.fillText(a.label,0,-g/2-3),d.restore()}}}}.call(this);