From dcd8469f4da3727e624f290f0e008cca2ee673c9 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Sun, 21 Oct 2018 14:00:00 +0200 Subject: [PATCH] Add WebSocketStore for handling the web socket --- ui/src/index.tsx | 22 +++++++++++++++-- ui/src/stores/WebSocketStore.ts | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 ui/src/stores/WebSocketStore.ts diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 83d4104..8ee5315 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -2,11 +2,16 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import 'typeface-roboto'; import 'typeface-roboto-mono'; -import * as UserAction from './actions/UserAction'; +import './actions/defaultAxios'; import * as config from './config'; import Layout from './Layout'; import registerServiceWorker from './registerServiceWorker'; import * as Notifications from './stores/Notifications'; +import {currentUser} from './stores/CurrentUser'; +import AppStore from './stores/AppStore'; +import {reaction} from 'mobx'; +import {WebSocketStore} from './stores/WebSocketStore'; +import SnackManager from './stores/SnackManager'; const defaultDevConfig = { url: 'http://localhost:80/', @@ -35,7 +40,20 @@ declare global { } else { config.set(window.config || defaultDevConfig); } - UserAction.checkIfAlreadyLoggedIn(); + const ws = new WebSocketStore(SnackManager.snack); + reaction( + () => currentUser.loggedIn, + (loggedIn) => { + if (loggedIn) { + ws.listen(); + } else { + ws.close(); + } + AppStore.refresh(); + } + ); + + currentUser.tryAuthenticate(); ReactDOM.render(, document.getElementById('root')); registerServiceWorker(); })(); diff --git a/ui/src/stores/WebSocketStore.ts b/ui/src/stores/WebSocketStore.ts new file mode 100644 index 0000000..24b517a --- /dev/null +++ b/ui/src/stores/WebSocketStore.ts @@ -0,0 +1,43 @@ +import {SnackReporter} from './SnackManager'; +import {currentUser} from './CurrentUser'; +import * as config from '../config'; +import NewMessagesStore from './MessagesStore'; + +export class WebSocketStore { + private wsActive = false; + private ws: WebSocket | null = null; + + public constructor(private readonly snack: SnackReporter) {} + + public listen = () => { + if (!currentUser.token() || this.wsActive) { + return; + } + this.wsActive = true; + + const wsUrl = config + .get('url') + .replace('http', 'ws') + .replace('https', 'wss'); + const ws = new WebSocket(wsUrl + 'stream?token=' + currentUser.token()); + + ws.onerror = (e) => { + this.wsActive = false; + console.log('WebSocket connection errored', e); + }; + + ws.onmessage = (data) => NewMessagesStore.publishSingleMessage(JSON.parse(data.data)); + + ws.onclose = () => { + this.wsActive = false; + currentUser.tryAuthenticate().then(() => { + this.snack('WebSocket connection closed, trying again in 30 seconds.'); + setTimeout(this.listen, 30000); + }); + }; + + this.ws = ws; + }; + + public close = () => this.ws && this.ws.close(); +}