-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMuppetProvider.jsx
More file actions
99 lines (88 loc) · 3.48 KB
/
MuppetProvider.jsx
File metadata and controls
99 lines (88 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
/* --------------------------------------------------------------------------------
* Created on Tues Nov 5 2024
*
* Copyright (c) 2024 Colorado State University. All rights reserved. (1)
*
* Contributors:
* Mackenzie Grimes (1)
*
* --------------------------------------------------------------------------------
*/
import { createContext, useEffect, useState } from 'react';
import MuppetChannel from './MuppetChannel';
import { getAndSaveSessionId } from './session';
const MuppetContext = createContext(null);
/**
*
* @param {Object} props
* @param {string} props.clientName This web app, the source/originator to declare when creating
* any WebRTC connections. This is how other apps will address MUPPET messages directly to this app.
* @param {string} props.serverUrl The URL/address of the WebRTC signaling server to connect to
* so other apps in the suite can find our app and negotiate a direct websocket to us.
* @param {string} props.serverPath The path argument to append to the WebRTC server URL (defaults to "/")
* @param {string[]} props.channels List of MUPPET channel "rooms" to which to connect
*/
function MuppetProvider({
clientName = '',
serverUrl = '',
serverPath = '/',
channels = [],
children = null,
}) {
const [currentChannels, setCurrentChannels] = useState({});
const [sessionId, setSessionId] = useState(null);
useEffect(() => {
// same sessionId will be used for all MUPPET channel rooms/connections
const fetchSessionId = async () => {
setSessionId(await getAndSaveSessionId(clientName));
};
if (!sessionId) {
fetchSessionId();
}
}, [sessionId, clientName]);
useEffect(() => {
if (!sessionId) {
console.debug(`[${clientName}] [MuppetProvider] sessionId null, not creating channels yet`);
return () => {}; // nothing to do
}
// TODO: not sure if this is needed, never seen it log
// Object.values(currentChannels).forEach((channel) => {
// console.debug(
// `[${clientName}] [MuppetProvider] now throwing away pre-existing channel: ${JSON.stringify(channel)}`,
// );
// if (channel?.isOpen()) {
// console.debug(`[${clientName}] [MuppetProvider] closing channel: ${channel.room}}`);
// channel.close();
// }
// });
const channelMap = {};
channels.forEach((channelName) => {
// for each channelName, map its room name to a new MuppetChannel and initiate a connection
try {
channelMap[channelName] = new MuppetChannel({
clientName,
room: `${sessionId}:${channelName}`,
serverUrl,
serverPath,
});
channelMap[channelName].connect();
} catch (err) {
console.error('Failed to connect to MuppetChannel', channelName, err);
channelMap[channelName] = null;
}
});
setCurrentChannels(channelMap);
// when this Hook is unmounted (usually re-rendered), terminate all WebRTC channels
// TODO: haven't seen this actually run in logs, not sure when Provider gets cleaned up
return () =>
Object.entries(channelMap).forEach(([channelName, channel]) => {
console.debug(
`[${clientName}] [MuppetProvider] [unmount] Attempting to close channel ${channelName}`,
channel,
);
channel?.close();
});
}, [channels, clientName, serverPath, serverUrl, sessionId]);
return <MuppetContext.Provider value={currentChannels}>{children}</MuppetContext.Provider>;
}
export { MuppetContext, MuppetProvider };