Skip to content

Commit ebbf581

Browse files
Merge pull request #2 from pexip/feat/add-support-for-breakout-rooms
feat: add support for breakout rooms
2 parents 90e011f + 1ee1507 commit ebbf581

8 files changed

Lines changed: 513 additions & 358 deletions

File tree

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Change Log
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this
6+
project adheres to [Semantic Versioning](http://semver.org/).
7+
8+
## [1.1.0] 2024-08-30
9+
10+
### Added
11+
12+
- Support for breakout rooms.
13+
14+
## [1.0.0] - 2024-06-03
15+
16+
### Added
17+
18+
- Change message overlay for the main room in a VMR (only Pexip Infinity v35 and
19+
later).

package-lock.json

Lines changed: 304 additions & 291 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
{
22
"name": "message-overlay",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "Plugin that allows the host to display messages embedded in the video stream.",
55
"main": "index.js",
66
"scripts": {
77
"start": "vite",
88
"build": "vite build",
9-
"test": "jest --detectOpenHandles --silent",
109
"lint": "eslint ."
1110
},
1211
"keywords": [],
1312
"author": "",
1413
"license": "ISC",
1514
"type": "module",
1615
"dependencies": {
17-
"@pexip/plugin-api": "19.3.2"
16+
"@pexip/plugin-api": "19.3.3"
1817
},
1918
"devDependencies": {
2019
"eslint": "^8.1.0",
2120
"eslint-config-love": "^47.0.0",
2221
"eslint-config-prettier": "^9.1.0",
23-
"prettier": "^3.3.0",
22+
"prettier": "^3.3.3",
2423
"typescript": "^5.4.5",
25-
"vite": "^5.2.12",
26-
"vite-plugin-mkcert": "^1.17.5"
24+
"vite": "^5.4.2",
25+
"vite-plugin-mkcert": "^1.17.6"
2726
}
2827
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { setMessageOverlay } from '../messageOverlay'
2+
import { plugin } from '../plugin'
3+
4+
export const createInputMessageForm = async (
5+
roomId: string,
6+
currentMessage: string,
7+
roomName?: string,
8+
breakoutRooms?: Map<string, string>
9+
): Promise<void> => {
10+
const messageName =
11+
roomName != null ? `"${roomName}" message` : 'Room message'
12+
13+
const form = await plugin.ui.addForm({
14+
title: 'Set message overlay',
15+
description:
16+
'Write your message overlay text below. If you would like to get a new line press enter or make a new line in the textarea',
17+
form: {
18+
elements: {
19+
message: {
20+
name: messageName,
21+
type: 'textarea',
22+
isOptional: true,
23+
placeholder: 'Enter your message',
24+
value: currentMessage
25+
}
26+
},
27+
submitBtnTitle: 'Submit'
28+
}
29+
})
30+
31+
form.onInput.add(async (result): Promise<void> => {
32+
await form.remove()
33+
34+
if (result.message == null) {
35+
return
36+
}
37+
38+
if (roomId === '') {
39+
setMessageOverlay('main', result.message).catch(console.error)
40+
breakoutRooms?.forEach((_breakoutName, breakoutUuid) => {
41+
setMessageOverlay(breakoutUuid, result.message).catch(console.error)
42+
})
43+
} else {
44+
setMessageOverlay(roomId, result.message).catch(console.error)
45+
}
46+
})
47+
}

src/forms/createSelectRoomForm.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { createInputMessageForm } from './createInputMessageForm'
2+
import { getMessageOverlay } from '../messageOverlay'
3+
import { plugin } from '../plugin'
4+
5+
export const createSelectRoomForm = async (
6+
breakoutRooms: Map<string, string>
7+
): Promise<void> => {
8+
const form = await plugin.ui.addForm({
9+
title: 'Set message overlay',
10+
description: 'Choose the room you want to set the message overlay for.',
11+
form: {
12+
elements: {
13+
room: {
14+
name: 'Select room',
15+
type: 'select',
16+
isOptional: true,
17+
options: [
18+
{
19+
id: '',
20+
label: 'All rooms'
21+
},
22+
{
23+
id: 'main',
24+
label: 'Main room'
25+
},
26+
...Array.from(breakoutRooms).map(([roomId, roomName]) => ({
27+
id: roomId,
28+
label: roomName
29+
}))
30+
]
31+
}
32+
},
33+
submitBtnTitle: 'Choose'
34+
}
35+
})
36+
37+
form.onInput.add(async (result): Promise<void> => {
38+
await form.remove()
39+
40+
if (result.room == null) {
41+
return
42+
}
43+
44+
const roomId = result.room
45+
let currentMessage = ''
46+
47+
if (roomId !== '') {
48+
try {
49+
currentMessage = await getMessageOverlay(result.room)
50+
} catch (e) {
51+
console.error(e)
52+
}
53+
}
54+
55+
const roomName =
56+
roomId === ''
57+
? 'All rooms'
58+
: roomId === 'main'
59+
? 'Main room'
60+
: breakoutRooms.get(roomId)
61+
62+
await createInputMessageForm(roomId, currentMessage, roomName)
63+
})
64+
}

src/index.ts

Lines changed: 36 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,46 @@
11
import { type Button, registerPlugin } from '@pexip/plugin-api'
2+
import { createSelectRoomForm } from './forms/createSelectRoomForm'
3+
import { getMessageOverlay } from './messageOverlay'
4+
import { createInputMessageForm } from './forms/createInputMessageForm'
5+
import { setPlugin } from './plugin'
26

37
const plugin = await registerPlugin({
48
id: 'message-overlay',
5-
version: 0
9+
version: 1
610
})
711

12+
setPlugin(plugin)
13+
814
let button: Button<'settingsMenu'> | null = null
915
let creatingButton = false
1016

17+
const breakoutRooms = new Map<string, string>()
18+
19+
plugin.events.authenticatedWithConference.add(async () => {
20+
breakoutRooms.clear()
21+
})
22+
23+
plugin.events.breakoutBegin.add(async (breakoutRoom) => {
24+
breakoutRooms.set(breakoutRoom.breakout_uuid, '')
25+
})
26+
27+
plugin.events.breakoutEnd.add(async (breakoutRoom) => {
28+
breakoutRooms.delete(breakoutRoom.breakout_uuid)
29+
})
30+
1131
plugin.events.conferenceStatus.add(async ({ id, status }) => {
12-
if (id === 'main' && !status.directMedia && status.started) {
32+
if (breakoutRooms.has(id) && status.breakoutName != null) {
33+
breakoutRooms.set(id, status.breakoutName)
34+
}
35+
36+
if (!status.directMedia && status.started) {
1337
await addButton()
1438
} else {
1539
await removeButton()
1640
}
1741
})
1842

1943
const addButton = async (): Promise<void> => {
20-
console.log('addButton')
2144
if (button != null || creatingButton) {
2245
return
2346
}
@@ -43,65 +66,17 @@ const removeButton = async (): Promise<void> => {
4366
}
4467

4568
const handleClickButton = async (): Promise<void> => {
46-
let currentMessage = ''
47-
try {
48-
currentMessage = await getMessageOverlay()
49-
console.log(currentMessage)
50-
} catch (e) {
51-
console.error(e)
52-
}
53-
await createForm(currentMessage)
54-
}
55-
56-
const createForm = async (currentMessage: string): Promise<void> => {
57-
const form = await plugin.ui.addForm({
58-
title: 'Set message overlay',
59-
description:
60-
'Write your message overlay text below. If you would like to get a new line press enter or make a new line in the textarea',
61-
form: {
62-
elements: {
63-
message: {
64-
name: 'Enter text',
65-
type: 'textarea',
66-
isOptional: true,
67-
placeholder: 'Enter your message',
68-
value: currentMessage
69-
}
70-
},
71-
submitBtnTitle: 'Submit'
72-
}
73-
})
69+
if (breakoutRooms.size > 0) {
70+
await createSelectRoomForm(breakoutRooms)
71+
} else {
72+
const roomId = 'main'
73+
let currentMessage = ''
7474

75-
form.onInput.add((result): void => {
76-
handleFormSubmit(form, result).catch((e) => {
75+
try {
76+
currentMessage = await getMessageOverlay(roomId)
77+
} catch (e) {
7778
console.error(e)
78-
})
79-
})
80-
}
81-
82-
const handleFormSubmit = async (
83-
form: any,
84-
result: {
85-
message: string
79+
}
80+
await createInputMessageForm(roomId, currentMessage)
8681
}
87-
): Promise<void> => {
88-
form?.remove()
89-
await setMessageOverlay(result.message)
90-
}
91-
92-
const getMessageOverlay = async (): Promise<string> => {
93-
const response = await (plugin.conference as any).sendRequest({
94-
method: 'GET',
95-
path: 'get_message_text'
96-
})
97-
console.log(response)
98-
return response.data.result.text ?? ''
99-
}
100-
101-
const setMessageOverlay = async (text: string): Promise<void> => {
102-
await (plugin.conference as any).sendRequest({
103-
method: 'POST',
104-
path: 'set_message_text',
105-
payload: { text }
106-
})
10782
}

src/messageOverlay.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { plugin } from './plugin'
2+
3+
export const getMessageOverlay = async (roomId: string): Promise<string> => {
4+
let path = 'get_message_text'
5+
if (roomId !== 'main') {
6+
path = `breakouts/${roomId}/${path}`
7+
}
8+
9+
const response = await (plugin.conference as any).sendRequest({
10+
method: 'GET',
11+
path
12+
})
13+
14+
return response.data.result.text ?? ''
15+
}
16+
17+
export const setMessageOverlay = async (
18+
roomId: string,
19+
text: string
20+
): Promise<void> => {
21+
let path = 'set_message_text'
22+
if (roomId !== 'main') {
23+
path = `breakouts/${roomId}/${path}`
24+
}
25+
26+
;(plugin.conference as any).sendRequest({
27+
method: 'POST',
28+
path,
29+
payload: { text }
30+
})
31+
}

src/plugin.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { type Plugin } from '@pexip/plugin-api'
2+
3+
export let plugin: Plugin
4+
5+
export const setPlugin = (p: Plugin): void => {
6+
plugin = p
7+
}

0 commit comments

Comments
 (0)