Skip to content

Commit 6e72fda

Browse files
committed
Added WS to slides
1 parent 45388ec commit 6e72fda

File tree

8 files changed

+184
-3
lines changed

8 files changed

+184
-3
lines changed

packages/slides/index.html

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,16 @@
4444
<h1>Present Controls</h1>
4545
</header>
4646
<div>
47-
<ul>
48-
<li><button class="share buttonlink">Share Screen</button></li><!-- Share Screen / Stop Sharing -->
47+
<div class="connected-container">
48+
<span class="indicator"></span><span class="message"></span>
49+
</div>
50+
<ul class="menu-options">
51+
<li><button class="share buttonlink">Share Screen</button></li>
52+
<li><button class="stopSharing buttonlink">Stop Sharing</button></li>
4953
<li><button class="snapshot buttonlink">Take Snapshot</button></li>
5054
<li><button class="openPreview buttonlink">Open Preview</button></li>
55+
<li><button class="connect buttonlink">Connect</button></li>
56+
<li><button class="disconnect buttonlink">Disconnect</button></li>
5157
</ul>
5258
</div>
5359
</div>

packages/slides/resources/present.styl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,58 @@
77
max-width: 100%;
88
max-height: 85vh;
99
}
10+
11+
.indicator {
12+
height: 0.9em;
13+
width: 0.9em;
14+
border-radius: 50%;
15+
display: inline-block;
16+
margin-right: 1em;
17+
background-color: red;
18+
}
19+
20+
body.connected {
21+
.indicator {
22+
background-color: green;
23+
}
24+
25+
.menu-options {
26+
.connect {
27+
display: none;
28+
}
29+
30+
.disconnect {
31+
display: block;
32+
}
33+
}
34+
}
35+
36+
body.sharing {
37+
.menu-options {
38+
.stopSharing {
39+
display: block;
40+
}
41+
42+
.snapshot {
43+
display: block;
44+
}
45+
46+
.share {
47+
display: none;
48+
}
49+
}
50+
}
51+
52+
.menu-options {
53+
.stopSharing {
54+
display: none;
55+
}
56+
57+
.snapshot {
58+
display: none;
59+
}
60+
61+
.disconnect {
62+
display: none;
63+
}
64+
}

packages/slides/src/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export function getWebSocketServer() {
2+
const url = new URL((window as any)?.location);
3+
return `ws://${url.host}`;
4+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { getWebSocketServer } from "../config";
2+
import { wait } from "./websocket";
3+
4+
let socket: WebSocket | undefined;
5+
6+
/**
7+
* Handles incoming message
8+
*/
9+
function messageHandler(event: any) {
10+
console.log('message', event);
11+
}
12+
13+
export function connect(url = getWebSocketServer()) {
14+
if (socket && socket.url.indexOf(url) === -1) {
15+
throw new Error(`Socket currently connected to ${ socket.url }. Cannot connect to ${ url } unless disconnected.`)
16+
}
17+
if (!socket) {
18+
socket = new WebSocket(url);
19+
socket.addEventListener('close', function () {
20+
this.removeEventListener('message', messageHandler);
21+
socket = undefined;
22+
});
23+
socket.addEventListener('error', (event) => {
24+
console.warn('websocket error', event);
25+
});
26+
socket.addEventListener('message', messageHandler);
27+
}
28+
29+
return wait(socket);
30+
}
31+
32+
export function disconnect() {
33+
if (socket) {
34+
socket.close();
35+
socket = undefined;
36+
}
37+
}
38+
39+
export function isConnected() {
40+
return socket && socket.readyState <= 1;
41+
}
42+
43+
export async function send(data: string | ArrayBuffer | Blob | ArrayBufferView) {
44+
if (!socket) {
45+
throw new Error('No connection');
46+
}
47+
const ws = await wait(socket);
48+
ws.send(data);
49+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
export const enum WebSocketState {
2+
Connecting = 0,
3+
Open = 1,
4+
Closing = 2,
5+
Closed = 3
6+
}
7+
8+
export function wait(socket?: WebSocket): Promise<WebSocket> {
9+
if (!socket) {
10+
return Promise.reject(new Error('not connected'));
11+
}
12+
switch (socket.readyState) {
13+
case WebSocketState.Connecting:
14+
return new Promise((resolve, reject) => {
15+
const onOpen = () => {
16+
resolve(socket);
17+
socket.removeEventListener('open', onOpen);
18+
socket.removeEventListener('error', reject);
19+
socket.removeEventListener('close', reject);
20+
}
21+
socket.addEventListener('open', onOpen);
22+
socket.addEventListener('error', reject);
23+
socket.addEventListener('close', reject);
24+
});
25+
case WebSocketState.Open:
26+
return Promise.resolve(socket);
27+
default:
28+
return Promise.reject(new Error('socket is closed'));
29+
}
30+
}
31+
32+
export function is(socket: WebSocket, state: WebSocketState) {
33+
return socket.readyState === state;
34+
}

packages/slides/src/elements.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,11 @@ export function getPreview() {
2929
export function getOpenPreviewButton() {
3030
return document.querySelector('.openPreview');
3131
}
32+
33+
export function getConnectButton() {
34+
return document.querySelector('.menu-options .connect');
35+
}
36+
37+
export function getDisconnectButton() {
38+
return document.querySelector('.menu-options .disconnect');
39+
}

packages/slides/src/menu.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getScreenMedia, getScreenshot } from "./screen";
2-
import { getMenuContainer, getPreviewContainer, getPreview, getMenuCloseButton, getShareButton, getSnapshotButton, getPreviewCloseButton, getOpenPreviewButton } from "./elements";
2+
import { getMenuContainer, getPreviewContainer, getPreview, getMenuCloseButton, getShareButton, getSnapshotButton, getPreviewCloseButton, getOpenPreviewButton, getConnectButton, getDisconnectButton } from "./elements";
3+
import { connect, disconnect } from "./connection/connection";
34

45
export function openMenu() {
56
getMenuContainer()?.classList.add('opened');
@@ -36,6 +37,10 @@ getMenuCloseButton()?.addEventListener('click', closeMenu);
3637

3738
getShareButton()?.addEventListener('click', async () => {
3839
const media = await getScreenMedia();
40+
document.body.classList.add('sharing');
41+
media.getVideoTracks()[0]?.addEventListener('ended', () => {
42+
document.body.classList.remove('sharing');
43+
});
3944
});
4045

4146
getSnapshotButton()?.addEventListener('click', async () => {
@@ -52,3 +57,15 @@ getOpenPreviewButton()?.addEventListener('click', () => {
5257
closeMenu();
5358
openPreview();
5459
});
60+
61+
getConnectButton()?.addEventListener('click', async () => {
62+
const socket = await connect();
63+
document.body.classList.add('connected');
64+
socket.addEventListener('close', () => {
65+
document.body.classList.remove('connected');
66+
});
67+
});
68+
69+
getDisconnectButton()?.addEventListener('click', () => {
70+
disconnect();
71+
});

packages/slides/src/screen.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ export function getScreenMedia() {
1010
return media;
1111
}
1212

13+
export async function stopSharing() {
14+
if (media) {
15+
const m = media;
16+
media = undefined;
17+
(await m).getTracks().forEach(track => track.stop());
18+
}
19+
}
20+
1321
export async function getScreenshot() {
1422
const canvas = document.createElement('canvas');
1523
const video = document.createElement('video');

0 commit comments

Comments
 (0)