@digitalsamba/embedded-sdk 0.0.12 → 0.0.17
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 +9 -0
- package/dist/cjs/index.d.ts +26 -2
- package/dist/cjs/index.js +185 -9
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +104 -9
- 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 +26 -2
- package/dist/esm/index.js +184 -8
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +104 -9
- 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 +264 -59
- package/dist/initial-config-demo.html +303 -0
- package/dist/permissions-demo.html +289 -0
- package/dist/types/index.d.ts +26 -2
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/types/types.d.ts +104 -9
- 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
@@ -0,0 +1,70 @@
|
|
1
|
+
export class PermissionManager {
|
2
|
+
constructor(parent) {
|
3
|
+
this.permissionsMap = {};
|
4
|
+
this.lookupDynamicPermission = (permission, dynamicPermissions) => {
|
5
|
+
if (!dynamicPermissions) {
|
6
|
+
return false;
|
7
|
+
}
|
8
|
+
return dynamicPermissions.includes(permission);
|
9
|
+
};
|
10
|
+
this.lookupPermission = (options) => {
|
11
|
+
const { permissionsMap, permission, targetRole, role, dynamicPermissions } = options;
|
12
|
+
if (dynamicPermissions) {
|
13
|
+
const granted = this.lookupDynamicPermission(permission, dynamicPermissions);
|
14
|
+
if (granted) {
|
15
|
+
return true;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
if (permissionsMap[role][permission]) {
|
19
|
+
return true;
|
20
|
+
}
|
21
|
+
return Boolean(permissionsMap[role][`${permission}_${targetRole}`]);
|
22
|
+
};
|
23
|
+
this.checkPermissions = ({ permissions, targetRole, permissionsMap, role, dynamicPermissions, }) => {
|
24
|
+
if (Array.isArray(permissions)) {
|
25
|
+
return permissions.some((permission) => this.lookupPermission({ permission, targetRole, role, permissionsMap, dynamicPermissions }));
|
26
|
+
}
|
27
|
+
return this.lookupPermission({
|
28
|
+
permission: permissions,
|
29
|
+
targetRole,
|
30
|
+
role,
|
31
|
+
permissionsMap,
|
32
|
+
dynamicPermissions,
|
33
|
+
});
|
34
|
+
};
|
35
|
+
this.refinePermissions = (permissions, { targetRole, role, userId, users, permissionsMap, localUser }) => {
|
36
|
+
const options = {
|
37
|
+
permissionsMap,
|
38
|
+
permissions,
|
39
|
+
targetRole,
|
40
|
+
role: localUser.role,
|
41
|
+
dynamicPermissions: localUser.dynamicPermissions,
|
42
|
+
};
|
43
|
+
if (role) {
|
44
|
+
options.role = role;
|
45
|
+
options.dynamicPermissions = undefined;
|
46
|
+
}
|
47
|
+
if (userId && users) {
|
48
|
+
options.role = users[userId].role;
|
49
|
+
options.dynamicPermissions = users[userId].dynamicPermissions;
|
50
|
+
}
|
51
|
+
return this.checkPermissions(options);
|
52
|
+
};
|
53
|
+
this.hasPermissions = (permissions, { targetRole, role, userId } = {}) => {
|
54
|
+
const users = this.parent.stored.users;
|
55
|
+
const localUser = this.parent.localUser;
|
56
|
+
if (!localUser) {
|
57
|
+
return false;
|
58
|
+
}
|
59
|
+
return this.refinePermissions(permissions, {
|
60
|
+
permissionsMap: this.permissionsMap,
|
61
|
+
role,
|
62
|
+
targetRole,
|
63
|
+
users,
|
64
|
+
userId,
|
65
|
+
localUser,
|
66
|
+
});
|
67
|
+
};
|
68
|
+
this.parent = parent;
|
69
|
+
}
|
70
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { User, UserId } from '../../types';
|
2
|
+
import { PermissionTypes } from '../vars';
|
3
|
+
export type PermissionsMap = Record<string, Record<string, boolean>>;
|
4
|
+
export interface HasPermissionsOptions {
|
5
|
+
targetRole?: string;
|
6
|
+
role?: string;
|
7
|
+
userId?: UserId;
|
8
|
+
}
|
9
|
+
export interface RefinePermissionsOptions extends HasPermissionsOptions {
|
10
|
+
permissionsMap: PermissionsMap;
|
11
|
+
localUser: User;
|
12
|
+
users?: Record<UserId, User>;
|
13
|
+
}
|
14
|
+
export interface LookupPermissionOptions {
|
15
|
+
permissionsMap: PermissionsMap;
|
16
|
+
permission: PermissionTypes;
|
17
|
+
role: string;
|
18
|
+
targetRole?: string;
|
19
|
+
dynamicPermissions?: PermissionTypes[];
|
20
|
+
}
|
21
|
+
export interface CheckPermissionsOptions extends Omit<LookupPermissionOptions, 'permission'> {
|
22
|
+
permissions: PermissionTypes | PermissionTypes[];
|
23
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare const createWatchedProxy: <G>(initialState: G, onChange: (newState: G) => void) => any;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
const createHandler = (onChange) => {
|
2
|
+
const handler = {
|
3
|
+
get(target, key) {
|
4
|
+
if (typeof target[key] === 'object' && target[key] !== null) {
|
5
|
+
return new Proxy(target[key], handler);
|
6
|
+
}
|
7
|
+
return target[key];
|
8
|
+
},
|
9
|
+
set(target, prop, value) {
|
10
|
+
target[prop] = value;
|
11
|
+
onChange(target);
|
12
|
+
return target;
|
13
|
+
},
|
14
|
+
};
|
15
|
+
return handler;
|
16
|
+
};
|
17
|
+
export const createWatchedProxy = (initialState, onChange) => new Proxy(initialState, createHandler(onChange));
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { Stored } from '../types';
|
2
|
+
export declare const CONNECT_TIMEOUT = 10000;
|
3
|
+
export declare const internalEvents: Record<string, boolean>;
|
4
|
+
export declare enum LayoutMode {
|
5
|
+
tiled = "tiled",
|
6
|
+
auto = "auto"
|
7
|
+
}
|
8
|
+
export declare enum PermissionTypes {
|
9
|
+
broadcast = "broadcast",
|
10
|
+
manageBroadcast = "manage_broadcast",
|
11
|
+
endSession = "end_session",
|
12
|
+
startSession = "start_session",
|
13
|
+
removeParticipant = "remove_participant",
|
14
|
+
screenshare = "screenshare",
|
15
|
+
manageScreenshare = "manage_screenshare",
|
16
|
+
recording = "recording",
|
17
|
+
generalChat = "general_chat",
|
18
|
+
remoteMuting = "remote_muting",
|
19
|
+
askRemoteUnmute = "ask_remote_unmute",
|
20
|
+
raiseHand = "raise_hand",
|
21
|
+
manageRoles = "manage_roles"
|
22
|
+
}
|
23
|
+
export declare const defaultStoredState: Stored;
|
@@ -0,0 +1,45 @@
|
|
1
|
+
export const CONNECT_TIMEOUT = 10000;
|
2
|
+
export const internalEvents = {
|
3
|
+
roomJoined: true,
|
4
|
+
};
|
5
|
+
export var LayoutMode;
|
6
|
+
(function (LayoutMode) {
|
7
|
+
LayoutMode["tiled"] = "tiled";
|
8
|
+
LayoutMode["auto"] = "auto";
|
9
|
+
})(LayoutMode || (LayoutMode = {}));
|
10
|
+
export var PermissionTypes;
|
11
|
+
(function (PermissionTypes) {
|
12
|
+
PermissionTypes["broadcast"] = "broadcast";
|
13
|
+
PermissionTypes["manageBroadcast"] = "manage_broadcast";
|
14
|
+
PermissionTypes["endSession"] = "end_session";
|
15
|
+
PermissionTypes["startSession"] = "start_session";
|
16
|
+
PermissionTypes["removeParticipant"] = "remove_participant";
|
17
|
+
PermissionTypes["screenshare"] = "screenshare";
|
18
|
+
PermissionTypes["manageScreenshare"] = "manage_screenshare";
|
19
|
+
PermissionTypes["recording"] = "recording";
|
20
|
+
PermissionTypes["generalChat"] = "general_chat";
|
21
|
+
PermissionTypes["remoteMuting"] = "remote_muting";
|
22
|
+
PermissionTypes["askRemoteUnmute"] = "ask_remote_unmute";
|
23
|
+
PermissionTypes["raiseHand"] = "raise_hand";
|
24
|
+
PermissionTypes["manageRoles"] = "manage_roles";
|
25
|
+
})(PermissionTypes || (PermissionTypes = {}));
|
26
|
+
export const defaultStoredState = {
|
27
|
+
userId: '',
|
28
|
+
roomState: {
|
29
|
+
media: {
|
30
|
+
micEnabled: false,
|
31
|
+
cameraEnabled: false,
|
32
|
+
},
|
33
|
+
layout: {
|
34
|
+
mode: LayoutMode.tiled,
|
35
|
+
showToolbar: true,
|
36
|
+
toolbarPosition: 'left',
|
37
|
+
},
|
38
|
+
captionsState: {
|
39
|
+
showCaptions: false,
|
40
|
+
spokenLanguage: 'en',
|
41
|
+
fontSize: 'medium',
|
42
|
+
},
|
43
|
+
},
|
44
|
+
users: {},
|
45
|
+
};
|
package/dist/index.html
CHANGED
@@ -7,68 +7,106 @@
|
|
7
7
|
<title>Document</title>
|
8
8
|
<!-- <script src="https://unpkg.com/@digitalsamba/embedded-sdk"></script>-->
|
9
9
|
<script src="./umd/index.js"></script>
|
10
|
+
<style>
|
11
|
+
.user-list-row {
|
12
|
+
display: flex;
|
13
|
+
margin: 12px 0 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
|
+
.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
|
+
|
41
|
+
.log p {
|
42
|
+
font-size: 14px;
|
43
|
+
line-height: 1;
|
44
|
+
margin: 0 0 4px
|
45
|
+
}
|
46
|
+
|
47
|
+
.buttons button, .captions-buttons button {
|
48
|
+
margin: 2px;
|
49
|
+
}
|
50
|
+
</style>
|
10
51
|
</head>
|
11
52
|
<body>
|
12
|
-
<div
|
13
|
-
|
14
|
-
<div class="log">
|
53
|
+
<div style="display: flex">
|
54
|
+
<div class="ifp">
|
15
55
|
|
16
56
|
</div>
|
57
|
+
<div style="min-width: 300px ; padding: 0 16px">
|
58
|
+
<h3>Room users:</h3>
|
59
|
+
<div class="participants">
|
17
60
|
|
61
|
+
</div>
|
62
|
+
<h3>Room state</h3>
|
63
|
+
<div class="state">
|
64
|
+
|
65
|
+
</div>
|
66
|
+
</div>
|
18
67
|
</div>
|
19
|
-
<div class="div" style=" border: 1px solid yellow">
|
68
|
+
<div class="div buttons" style=" border: 1px solid yellow">
|
20
69
|
<button class="c0" style="margin-right: 15px; border: 2px solid blue">LOAD</button>
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
<
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
<button class="c10">stopRecording</button>
|
31
|
-
<button class="c11">showToolbar</button>
|
32
|
-
<button class="c12">hideToolbar</button>
|
33
|
-
<button class="c13">toggleToolbar</button>
|
34
|
-
<button class="c14">auto layout</button>
|
35
|
-
<button class="c15">tiled layout</button>
|
36
|
-
<button class="c16">leave session</button>
|
37
|
-
<button class="c17">end session</button>
|
70
|
+
|
71
|
+
</div>
|
72
|
+
<div class="div captions-buttons" style=" border: 1px solid yellow">
|
73
|
+
<p>captions controls</p>
|
74
|
+
|
75
|
+
</div>
|
76
|
+
|
77
|
+
<div class="log">
|
78
|
+
|
38
79
|
</div>
|
39
80
|
|
40
81
|
<script async defer>
|
41
82
|
const parent = document.querySelector('.ifp');
|
42
83
|
const frame = document.querySelector('.if');
|
84
|
+
const buttonsParent = document.querySelector('.buttons');
|
85
|
+
const captionsButtonsParent = document.querySelector('.captions-buttons');
|
86
|
+
const participantList = document.querySelector('.participants');
|
87
|
+
|
43
88
|
const btn0 = document.querySelector('.c0');
|
44
|
-
|
45
|
-
const btn2 = document.querySelector('.c2');
|
46
|
-
const btn3 = document.querySelector('.c3');
|
47
|
-
const btn4 = document.querySelector('.c4');
|
48
|
-
const btn5 = document.querySelector('.c5');
|
49
|
-
const btn6 = document.querySelector('.c6');
|
50
|
-
const btn7 = document.querySelector('.c7');
|
51
|
-
const btn8 = document.querySelector('.c8');
|
52
|
-
const btn9 = document.querySelector('.c9');
|
53
|
-
const btn10 = document.querySelector('.c10');
|
54
|
-
const btn11 = document.querySelector('.c11');
|
55
|
-
const btn12 = document.querySelector('.c12');
|
56
|
-
const btn13 = document.querySelector('.c13');
|
57
|
-
const btn14 = document.querySelector('.c14');
|
58
|
-
const btn15 = document.querySelector('.c15');
|
59
|
-
const btn16 = document.querySelector('.c16');
|
60
|
-
const btn17 = document.querySelector('.c17');
|
89
|
+
|
61
90
|
|
62
91
|
// change these values to connect to your room
|
63
92
|
const TEAM = 'some-team';
|
64
93
|
const ROOM = 'some-room';
|
65
|
-
|
94
|
+
let ROOM_URL = 'https://localhost:3000/Public'
|
95
|
+
|
96
|
+
if(window.location.search) {
|
97
|
+
const params = new URLSearchParams(window.location.search);
|
98
|
+
const dynamicRoomUrl = params.get('roomUrl');
|
99
|
+
if(dynamicRoomUrl) {
|
100
|
+
ROOM_URL = dynamicRoomUrl
|
101
|
+
}
|
102
|
+
}
|
66
103
|
|
67
104
|
//const api = new DigitalSambaEmbedded({ root: parent, team: TEAM, room: ROOM});
|
68
105
|
// const api = new DigitalSambaEmbedded({ frame});
|
69
106
|
//const api = new DigitalSambaEmbedded({ url: ROOM_URL}, {reportErrors: true});
|
70
107
|
|
71
|
-
|
108
|
+
|
109
|
+
var api = DigitalSambaEmbedded.createControl({ url: ROOM_URL, root: parent });
|
72
110
|
|
73
111
|
const log = document.querySelector('.log');
|
74
112
|
|
@@ -76,29 +114,60 @@
|
|
76
114
|
api.frame.height = 700;
|
77
115
|
|
78
116
|
btn0.onclick = () => {api.load({ frameAttributes: {style: "border: 5px solid red"}, reportErrors: true })}
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
117
|
+
|
118
|
+
const baseControls = [
|
119
|
+
{command: 'toggleVideo', label: 'toggle video' },
|
120
|
+
{command: 'enableVideo', label: 'enable video' },
|
121
|
+
{command: 'disableVideo', label: 'disable video' },
|
122
|
+
{command: 'toggleAudio', label: 'toggle audio' },
|
123
|
+
{command: 'enableAudio', label: 'enable audio' },
|
124
|
+
{command: 'disableAudio', label: 'disable audio' },
|
125
|
+
{command: 'startScreenshare', label: 'start screenshare' },
|
126
|
+
{command: 'stopScreenshare', label: 'stop screenshare' },
|
127
|
+
{command: 'raiseHand', label: 'raise hand' },
|
128
|
+
{command: 'startRecording', label: 'start recording' },
|
129
|
+
{command: 'stopRecording', label: 'stop recording' },
|
130
|
+
{command: 'showToolbar', label: 'show toolbar' },
|
131
|
+
{command: 'hideToolbar', label: 'hide toolbar' },
|
132
|
+
{command: 'toggleToolbar', label: 'toggle toolbar' },
|
133
|
+
{command: 'changeLayoutMode', label: 'auto layout', args: ['auto'] },
|
134
|
+
{command: 'changeLayoutMode', label: 'tiled layout', args: ['tiled'] },
|
135
|
+
{command: 'showCaptions', label: 'show captions'},
|
136
|
+
{command: 'hideCaptions', label: 'hide captions'},
|
137
|
+
{command: 'toggleCaptions', label: 'toggle captions'},
|
138
|
+
{command: 'leaveSession', label: 'leave session' },
|
139
|
+
{command: 'endSession', label: 'end session' },
|
140
|
+
]
|
141
|
+
|
142
|
+
baseControls.forEach(control => {
|
143
|
+
const button = document.createElement("button");
|
144
|
+
button.innerHTML = control.label;
|
145
|
+
button.onclick = () => api[control.command](...(control.args || []))
|
146
|
+
|
147
|
+
buttonsParent.appendChild(button);
|
148
|
+
})
|
149
|
+
|
150
|
+
const captionsControls = [
|
151
|
+
{command: 'configureCaptions', label: 'set font size - small', args: [{fontSize: 'small'}] },
|
152
|
+
{command: 'configureCaptions', label: 'set font size - medium', args: [{fontSize: 'medium'}] },
|
153
|
+
{command: 'configureCaptions', label: 'set font size - large', args: [{fontSize: 'large'}] },
|
154
|
+
{command: 'configureCaptions', label: 'set spoken language - english', args: [{spokenLanguage: 'en'}] },
|
155
|
+
{command: 'configureCaptions', label: 'set spoken language - french', args: [{spokenLanguage: 'fr'}] },
|
156
|
+
{command: 'configureCaptions', label: 'set spoken language - spanish', args: [{spokenLanguage: 'es'}] },
|
157
|
+
]
|
158
|
+
|
159
|
+
captionsControls.forEach(control => {
|
160
|
+
const button = document.createElement("button");
|
161
|
+
button.innerHTML = control.label;
|
162
|
+
button.onclick = () => api[control.command](...(control.args || []))
|
163
|
+
|
164
|
+
captionsButtonsParent.appendChild(button);
|
165
|
+
})
|
96
166
|
|
97
167
|
api.on('*', (data) => {
|
98
|
-
log.innerHTML += `<p>${Number(new Date)}: ev(${data
|
168
|
+
log.innerHTML += `<p>${Number(new Date)}: ev(${data?.type}): ${JSON.stringify(data)}</p>`
|
99
169
|
});
|
100
170
|
|
101
|
-
|
102
171
|
api.on('userJoined', (data) => {
|
103
172
|
log.innerHTML += `<p>${Number(new Date)}: USER JOINED: ${JSON.stringify(data)}</p>`
|
104
173
|
});
|
@@ -107,6 +176,142 @@
|
|
107
176
|
log.innerHTML += `<p>${Number(new Date)}: USER LEFT: ${JSON.stringify(data)}</p>`
|
108
177
|
});
|
109
178
|
|
179
|
+
api.on('permissionsChanged', ({ data }) => {
|
180
|
+
if(data.broadcast !== undefined){
|
181
|
+
if(data.broadcast) {
|
182
|
+
alert('You were granted broadcast permission')
|
183
|
+
} else {
|
184
|
+
alert('Your permission to broadcast was rejected')
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
if(data.screenshare !== undefined){
|
189
|
+
if(data.screenshare) {
|
190
|
+
alert('You were granted screenshare permission')
|
191
|
+
} else {
|
192
|
+
alert('Your permission to screenshare was rejected')
|
193
|
+
}
|
194
|
+
}
|
195
|
+
});
|
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
|
+
})
|
220
|
+
|
221
|
+
api.on('usersUpdated', ({data: {users}}) => {
|
222
|
+
participantList.innerHTML = '';
|
223
|
+
|
224
|
+
users.forEach(user => {
|
225
|
+
const row = document.createElement('div');
|
226
|
+
row.className = 'user-list-row';
|
227
|
+
const subButtons = document.createElement('div')
|
228
|
+
row.appendChild(subButtons);
|
229
|
+
|
230
|
+
const avatar = document.createElement('span');
|
231
|
+
avatar.className = 'user-list-avatar';
|
232
|
+
avatar.style.background = user.avatarColor;
|
233
|
+
row.appendChild(avatar);
|
234
|
+
|
235
|
+
|
236
|
+
const name = document.createElement('span');
|
237
|
+
name.className = 'user-list-name';
|
238
|
+
name.innerText = user.name;
|
239
|
+
row.appendChild(name);
|
240
|
+
|
241
|
+
const speakerIndicator = document.createElement('span')
|
242
|
+
speakerIndicator.className = `speaker-indicator speaker-indicator-${user.id}`;
|
243
|
+
row.appendChild(speakerIndicator);
|
244
|
+
|
245
|
+
|
246
|
+
if(user.kind === 'local') {
|
247
|
+
const label = document.createElement('span');
|
248
|
+
label.className = 'user-list-label';
|
249
|
+
label.innerText = '(you)'
|
250
|
+
label.style.color = '#777';
|
251
|
+
row.appendChild(label);
|
252
|
+
} else {
|
253
|
+
const micControl = document.createElement('button');
|
254
|
+
micControl.innerHTML = 'toggle mic'
|
255
|
+
micControl.style.margin = '0 4px';
|
256
|
+
micControl.onclick = () => {api.requestToggleAudio(user.id)}
|
257
|
+
row.appendChild(micControl);
|
258
|
+
|
259
|
+
const kickControl = document.createElement('button');
|
260
|
+
kickControl.innerHTML = 'kick'
|
261
|
+
kickControl.style.margin = '0 4px';
|
262
|
+
kickControl.onclick = () => {api.removeUser(user.id)}
|
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);
|
288
|
+
}
|
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
|
+
|
298
|
+
participantList.appendChild(row);
|
299
|
+
participantList.appendChild(subButtons);
|
300
|
+
|
301
|
+
})
|
302
|
+
})
|
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
|
+
|
110
315
|
</script>
|
111
316
|
|
112
317
|
</body>
|