Skip to content

Commit c8d89e0

Browse files
committed
Correctly handle socket state in the app and make it possible to listen for events
1 parent f0ca8bc commit c8d89e0

File tree

6 files changed

+89
-16
lines changed

6 files changed

+89
-16
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"classnames": "^2.2.6",
1111
"date-fns": "^1.29.0",
1212
"easy-peasy": "^2.5.0",
13+
"events": "^3.0.0",
1314
"feather-icons": "^4.10.0",
1415
"formik": "^1.5.7",
1516
"jquery": "^3.3.1",
@@ -35,6 +36,7 @@
3536
"@babel/preset-env": "^7.3.1",
3637
"@babel/preset-react": "^7.0.0",
3738
"@types/classnames": "^2.2.8",
39+
"@types/events": "^3.0.0",
3840
"@types/feather-icons": "^4.7.0",
3941
"@types/lodash": "^4.14.119",
4042
"@types/query-string": "^6.3.0",
Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import React, { useEffect } from 'react';
22
import { Actions, State, useStoreActions, useStoreState } from 'easy-peasy';
33
import { ApplicationState } from '@/state/types';
4-
import Sockette from 'sockette';
4+
import { Websocket } from '@/plugins/Websocket';
55

66
export default () => {
77
const server = useStoreState((state: State<ApplicationState>) => state.server.data);
88
const instance = useStoreState((state: State<ApplicationState>) => state.server.socket.instance);
9-
const setInstance = useStoreActions((actions: Actions<ApplicationState>) => actions.server.socket.setInstance);
10-
const setConnectionState = useStoreActions((actions: Actions<ApplicationState>) => actions.server.socket.setConnectionState);
9+
const setServerStatus = useStoreActions((actions: Actions<ApplicationState>) => actions.server.setServerStatus);
10+
const { setInstance, setConnectionState } = useStoreActions((actions: Actions<ApplicationState>) => actions.server.socket);
1111

1212
useEffect(() => {
1313
// If there is already an instance or there is no server, just exit out of this process
@@ -16,19 +16,20 @@ export default () => {
1616
return;
1717
}
1818

19-
console.log('need to connect to instance');
20-
const socket = new Sockette(`wss://wings.pterodactyl.test:8080/api/servers/${server.uuid}/ws`, {
21-
protocols: 'CC8kHCuMkXPosgzGO6d37wvhNcksWxG6kTrA',
22-
// onmessage: (ev) => console.log(ev),
23-
onopen: () => setConnectionState(true),
24-
onclose: () => setConnectionState(false),
25-
onerror: () => setConnectionState(false),
26-
});
19+
console.log('Connecting!');
2720

28-
console.log('Setting instance!');
21+
const socket = new Websocket(
22+
`wss://wings.pterodactyl.test:8080/api/servers/${server.uuid}/ws`,
23+
'CC8kHCuMkXPosgzGO6d37wvhNcksWxG6kTrA'
24+
);
25+
26+
socket.on('SOCKET_OPEN', () => setConnectionState(true));
27+
socket.on('SOCKET_CLOSE', () => setConnectionState(false));
28+
socket.on('SOCKET_ERROR', () => setConnectionState(false));
29+
socket.on('status', (status) => setServerStatus(status));
2930

3031
setInstance(socket);
31-
}, [server]);
32+
}, [ server ]);
3233

3334
return null;
3435
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Sockette from 'sockette';
2+
import { EventEmitter } from 'events';
3+
4+
export const SOCKET_EVENTS = [
5+
'SOCKET_OPEN',
6+
'SOCKET_RECONNECT',
7+
'SOCKET_CLOSE',
8+
'SOCKET_ERROR',
9+
];
10+
11+
export class Websocket extends EventEmitter {
12+
socket: Sockette;
13+
14+
constructor (url: string, protocol: string) {
15+
super();
16+
17+
this.socket = new Sockette(url, {
18+
protocols: protocol,
19+
onmessage: e => {
20+
try {
21+
let { event, args } = JSON.parse(e.data);
22+
this.emit(event, ...args);
23+
} catch (ex) {
24+
console.warn('Failed to parse incoming websocket message.', ex);
25+
}
26+
},
27+
onopen: () => this.emit('SOCKET_OPEN'),
28+
onreconnect: () => this.emit('SOCKET_RECONNECT'),
29+
onclose: () => this.emit('SOCKET_CLOSE'),
30+
onerror: () => this.emit('SOCKET_ERROR'),
31+
});
32+
}
33+
34+
close (code?: number, reason?: string) {
35+
this.socket.close(code, reason);
36+
}
37+
38+
open () {
39+
this.socket.open();
40+
}
41+
42+
json (data: any) {
43+
this.socket.json(data);
44+
}
45+
46+
reconnect () {
47+
this.socket.reconnect();
48+
}
49+
50+
send (data: any) {
51+
this.socket.send(data);
52+
}
53+
}

resources/scripts/state/models/server.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,36 @@ import getServer, { Server } from '@/api/server/getServer';
22
import { action, Action, thunk, Thunk } from 'easy-peasy';
33
import socket, { SocketState } from './socket';
44

5+
export type ServerStatus = 'offline' | 'starting' | 'stopping' | 'online';
6+
57
export interface ServerState {
68
data?: Server;
9+
status: ServerStatus;
710
socket: SocketState;
811
getServer: Thunk<ServerState, string, {}, any, Promise<void>>;
912
setServer: Action<ServerState, Server>;
13+
setServerStatus: Action<ServerState, ServerStatus>;
1014
clearServerState: Action<ServerState>;
1115
}
1216

1317
const server: ServerState = {
1418
socket,
19+
status: 'offline',
1520
getServer: thunk(async (actions, payload) => {
1621
const server = await getServer(payload);
1722
actions.setServer(server);
1823
}),
1924
setServer: action((state, payload) => {
2025
state.data = payload;
2126
}),
27+
setServerStatus: action((state, payload) => {
28+
state.status = payload;
29+
}),
2230
clearServerState: action(state => {
2331
state.data = undefined;
2432

2533
if (state.socket.instance) {
34+
state.socket.instance.removeAllListeners();
2635
state.socket.instance.close();
2736
}
2837

resources/scripts/state/models/socket.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Action, action } from 'easy-peasy';
2-
import Sockette from 'sockette';
2+
import { Websocket } from '@/plugins/Websocket';
33

44
export interface SocketState {
5-
instance: Sockette | null;
5+
instance: Websocket | null;
66
connected: boolean;
7-
setInstance: Action<SocketState, Sockette | null>;
7+
setInstance: Action<SocketState, Websocket | null>;
88
setConnectionState: Action<SocketState, boolean>;
99
}
1010

yarn.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,10 @@
766766
version "1.0.0"
767767
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
768768

769+
"@types/events@^3.0.0":
770+
version "3.0.0"
771+
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
772+
769773
"@types/feather-icons@^4.7.0":
770774
version "4.7.0"
771775
resolved "https://registry.yarnpkg.com/@types/feather-icons/-/feather-icons-4.7.0.tgz#ec66bc046bcd1513835f87541ecef54b50c57ec9"
@@ -3059,6 +3063,10 @@ events@^1.0.0:
30593063
version "1.1.1"
30603064
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
30613065

3066+
events@^3.0.0:
3067+
version "3.0.0"
3068+
resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
3069+
30623070
eventsource@^1.0.7:
30633071
version "1.0.7"
30643072
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0"

0 commit comments

Comments
 (0)