diff --git a/ui/src/App.tsx b/ui/src/App.tsx
index c2706cd2..00b8d5cd 100644
--- a/ui/src/App.tsx
+++ b/ui/src/App.tsx
@@ -1,17 +1,13 @@
-import React, {useEffect} from 'react';
+import React from 'react';
import {createHashRouter, RouterProvider} from 'react-router-dom';
import Applications from './application/Applications.tsx';
import Clients from './client/Clients.tsx';
import {checkAuthLoader} from './common/Auth.ts';
import Messages from './message/Messages.tsx';
-import {WebSocketStore} from './message/WebSocketStore.ts';
import PluginsRootLayout from './pages/plugins.tsx';
import RootLayout from './pages/root';
import PluginDetailView from './plugin/PluginDetailView.tsx';
import Plugins from './plugin/Plugins.tsx';
-import * as Notifications from './snack/browserNotification.ts';
-import {useAppDispatch, useAppSelector} from './store';
-import {messageActions} from './message/message-slice.ts';
import Login from './user/Login.tsx';
import Users from './user/Users.tsx';
@@ -71,46 +67,6 @@ const router = createHashRouter([
},
]);
-const ws = new WebSocketStore();
-
-const App = () => {
- const dispatch = useAppDispatch();
- const loggedIn = useAppSelector((state) => state.auth.loggedIn);
- const reloadRequired = useAppSelector((state) => state.ui.reloadRequired);
-
- useEffect(() => {
- if (loggedIn) {
- ws.listen((message) => {
- dispatch(messageActions.loading(true));
- dispatch(messageActions.add(message));
- Notifications.notifyNewMessage(message);
- if (message.priority >= 4) {
- const src = 'static/notification.ogg';
- const audio = new Audio(src);
- audio.play();
- }
- });
- window.onbeforeunload = () => {
- ws.close();
- };
- } else {
- ws.close();
- }
- }, [dispatch, loggedIn, reloadRequired]);
-
-
- return (
-
- );
-};
+const App = () => ();
export default App;
-
-/*
-
- {authenticating ? (} />) : null}
- } />
- } />
-
-
-*/
diff --git a/ui/src/message/WebSocketStore.ts b/ui/src/message/WebSocketStore.ts
index 8633874c..9b7dbce9 100644
--- a/ui/src/message/WebSocketStore.ts
+++ b/ui/src/message/WebSocketStore.ts
@@ -1,10 +1,13 @@
+import {Middleware} from '@reduxjs/toolkit';
import {AxiosError} from 'axios';
import {getAuthToken} from '../common/Auth.ts';
import * as config from '../config';
+import * as Notifications from '../snack/browserNotification.ts';
import {tryAuthenticate} from '../user/auth-actions.ts';
import {uiActions} from '../store/ui-slice.ts';
import {IMessage} from '../types';
-import state from '../store/index.ts';
+import state, {RootState} from '../store/index.ts';
+import {messageActions} from './message-slice.ts';
export class WebSocketStore {
private wsActive = false;
@@ -57,3 +60,38 @@ export class WebSocketStore {
public close = () => this.ws?.close(1000, 'WebSocketStore#close');
}
+
+const ws = new WebSocketStore();
+
+export const handleWebsocketMiddleware: Middleware<{}, RootState> =
+ (store) => (next) => (action) => {
+ const prevLoginStatus = store.getState().auth.loggedIn;
+ const prevReloadRequired = store.getState().ui.reloadRequired;
+ const result = next(action);
+ const nextLoginStatus = store.getState().auth.loggedIn;
+ const nextReloadRequired = store.getState().ui.reloadRequired;
+
+ // Open websocket connection on login and if a reload is required
+ if ((action.type.startsWith('auth/login') && prevLoginStatus !== nextLoginStatus)
+ || (action.type.startsWith('ui/setReloadRequired') && prevReloadRequired !== nextReloadRequired && nextReloadRequired)
+ ) {
+ ws.listen((message) => {
+ store.dispatch(messageActions.loading(true));
+ store.dispatch(messageActions.add(message));
+ Notifications.notifyNewMessage(message);
+ if (message.priority >= 4) {
+ const src = 'static/notification.ogg';
+ const audio = new Audio(src);
+ audio.play();
+ }
+ });
+ window.onbeforeunload = () => {
+ ws.close();
+ };
+ }
+ // Close websocket if the user logs out
+ if (action.type.startsWith('auth/logout') && prevLoginStatus !== nextLoginStatus && !nextLoginStatus) {
+ ws.close();
+ }
+ return result;
+ };
diff --git a/ui/src/store/index.ts b/ui/src/store/index.ts
index 5ce295d6..8ab8f41b 100644
--- a/ui/src/store/index.ts
+++ b/ui/src/store/index.ts
@@ -1,5 +1,6 @@
import {configureStore} from '@reduxjs/toolkit';
import {useDispatch, useSelector} from 'react-redux';
+import {handleWebsocketMiddleware} from '../message/WebSocketStore.ts';
import uiReducer from './ui-slice';
import authReducer from '../user/auth-slice';
@@ -21,7 +22,7 @@ const store = configureStore({
message: messageReducer,
},
middleware: (getDefaultMiddleware) =>
- getDefaultMiddleware().concat(connectionErrorMiddleware),
+ getDefaultMiddleware().concat(handleWebsocketMiddleware, connectionErrorMiddleware),
});
// Infer the `RootState` and `AppDispatch` types from the store itself