aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/settingsWS/store.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/settingsWS/store.js')
-rwxr-xr-xsrc/features/settingsWS/store.js130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/features/settingsWS/store.js b/src/features/settingsWS/store.js
new file mode 100755
index 000000000..167a70d10
--- /dev/null
+++ b/src/features/settingsWS/store.js
@@ -0,0 +1,130 @@
1import { observable } from 'mobx';
2import WebSocket from 'ws';
3import ms from 'ms';
4
5import { FeatureStore } from '../utils/FeatureStore';
6import { createReactions } from '../../stores/lib/Reaction';
7import { WS_API } from '../../environment';
8
9const debug = require('debug')('Franz:feature:settingsWS:store');
10
11export class SettingsWSStore extends FeatureStore {
12 stores = null;
13
14 actions = null;
15
16 ws = null;
17
18 pingTimeout = null;
19
20 reconnectTimeout = null;
21
22 @observable connected = false;
23
24 start(stores, actions) {
25 this.stores = stores;
26 this.actions = actions;
27
28 this._registerReactions(createReactions([
29 this._initialize.bind(this),
30 this._reconnect.bind(this),
31 this._close.bind(this),
32 ]));
33 }
34
35 connect() {
36 try {
37 const wsURL = `${WS_API}/ws/${this.stores.user.data.id}`;
38 debug('Setting up WebSocket to', wsURL);
39
40 this.ws = new WebSocket(wsURL);
41
42 this.ws.on('open', () => {
43 debug('Opened WebSocket');
44 this.send({
45 action: 'authorize',
46 token: this.stores.user.authToken,
47 });
48
49 this.connected = true;
50
51 this.heartbeat();
52 });
53
54 this.ws.on('message', (data) => {
55 const resp = JSON.parse(data);
56 debug('Received message', resp);
57
58 if (resp.id) {
59 this.stores.user.getUserInfoRequest.patch((result) => {
60 if (!result) return;
61
62 debug('Patching user object with new values');
63 Object.assign(result, resp);
64 });
65 }
66 });
67
68 this.ws.on('ping', this.heartbeat.bind(this));
69 } catch (err) {
70 console.err(err);
71 }
72 }
73
74 heartbeat() {
75 debug('Heartbeat');
76 clearTimeout(this.pingTimeout);
77
78 this.pingTimeout = setTimeout(() => {
79 debug('Terminating connection, reconnecting in 35');
80 this.ws.terminate();
81
82 this.connected = false;
83 }, ms('35s'));
84 }
85
86 send(data) {
87 if (this.ws && this.ws.readyState === 1) {
88 this.ws.send(JSON.stringify(data));
89 debug('Sending data', data);
90 } else {
91 debug('WebSocket is not initialized');
92 }
93 }
94
95 // Reactions
96
97 _initialize() {
98 if (this.stores.user.data.id && !this.ws) {
99 this.connect();
100 }
101 }
102
103 _reconnect() {
104 if (!this.connected) {
105 debug('Trying to reconnect in 30s');
106 this.reconnectTimeout = setInterval(() => {
107 debug('Trying to reconnect');
108 this.connect();
109 }, ms('30s'));
110 } else {
111 debug('Clearing reconnect interval');
112 clearInterval(this.reconnectTimeout);
113 }
114 }
115
116 _close() {
117 if (!this.stores.user.isLoggedIn) {
118 debug('Stopping reactions');
119 this._stopReactions();
120
121 if (this.ws) {
122 debug('Terminating connection');
123 this.ws.terminate();
124 this.ws = null;
125 }
126 }
127 }
128}
129
130export default SettingsWSStore;