Skip to content

Commit 9b89d72

Browse files
committed
Working chatrooms !
Refactor websocket integration: replace WebsocketProvider with useChatWebsocket and usePostWebsocket hooks, update chatSlice to handle chat room messages, and enhance websocket initialization logic
1 parent 446d5df commit 9b89d72

5 files changed

Lines changed: 90 additions & 39 deletions

File tree

frontend/src/pages/main.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,24 @@ import { getAllChats } from "@/statemanagement/chats/chatSlice";
44
import { getAllPosts } from "@/statemanagement/posting/postSlice";
55
import { useAppDispatch } from "@/statemanagement/store";
66
import { getAllUsers, getOwnUser } from "@/statemanagement/users/usersSlice";
7-
import { WebsocketProvider } from "@/websocket/websocketProvider";
7+
import { useChatWebsocket } from "@/websocket/chatWebsocket";
8+
import { usePostWebsocket } from "@/websocket/postWebsocket";
89
import { useEffect } from "react";
910
import { Route, Routes } from "react-router-dom";
1011
import { ChatsPage } from "./subpages/Chats";
1112

1213
export const Main = () => {
1314
const dispatch = useAppDispatch();
15+
usePostWebsocket();
16+
useChatWebsocket();
1417
useEffect(() => {
1518
dispatch(getAllPosts());
1619
dispatch(getAllChats());
1720
dispatch(getOwnUser());
1821
dispatch(getAllUsers());
1922
}, []);
2023
return (
21-
<WebsocketProvider>
24+
<>
2225
<Header />
2326
<main className="flex-1 flex">
2427
<div className="container mx-auto shadow-lg rounded-lg p-6 flex flex-col">
@@ -28,6 +31,6 @@ export const Main = () => {
2831
</Routes>
2932
</div>
3033
</main>
31-
</WebsocketProvider>
34+
</>
3235
);
3336
};

frontend/src/statemanagement/chats/chatSlice.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,20 @@ export const chatSlice = createSlice({
101101
name: "chats",
102102
initialState,
103103
reducers: {
104-
addChatSync: (state, action) => {
105-
state.chats.unshift(action.payload);
106-
},
107104
setActiveChatId: (state, action: { payload: string }) => {
108105
state.activeChatId = action.payload;
109106
},
107+
updateChatRoomMessagesSync: (state, action: { payload: ChatRoom }) => {
108+
const chatRoom = state.chats.find((x) => x.id == action.payload.id);
109+
if (chatRoom != null) {
110+
chatRoom.messages = unique(
111+
[...(chatRoom.messages ?? []), ...(action.payload.messages ?? [])],
112+
(x) => x.id
113+
);
114+
} else {
115+
state.chats.push(action.payload);
116+
}
117+
},
110118
},
111119
extraReducers: (builder) => {
112120
builder.addCase(getAllChats.pending, (state) => {
@@ -155,6 +163,7 @@ export const chatSlice = createSlice({
155163
},
156164
});
157165

158-
export const { addChatSync, setActiveChatId } = chatSlice.actions;
166+
export const { updateChatRoomMessagesSync, setActiveChatId } =
167+
chatSlice.actions;
159168

160169
export default chatSlice.reducer;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { updateChatRoomMessagesSync } from "@/statemanagement/chats/chatSlice";
2+
import { useAppDispatch } from "@/statemanagement/store";
3+
import { ChatRoom } from "@/types/chatroom.type";
4+
import { useCallback } from "react";
5+
import { useWebsocket } from "./websocketProvider";
6+
7+
export const useChatWebsocket = () => {
8+
const dispatch = useAppDispatch();
9+
const onChat = useCallback(
10+
(data: unknown) => {
11+
dispatch(updateChatRoomMessagesSync(data as ChatRoom));
12+
},
13+
[dispatch]
14+
);
15+
const url = `ws://${window.envUrl}/api/v1/chats/query/ws`;
16+
useWebsocket(url, [{ eventName: "default", onEvent: onChat }]);
17+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { addPostSync } from "@/statemanagement/posting/postSlice";
2+
import { useAppDispatch } from "@/statemanagement/store";
3+
import { useCallback } from "react";
4+
import { useWebsocket } from "./websocketProvider";
5+
6+
export const usePostWebsocket = () => {
7+
const dispatch = useAppDispatch();
8+
const onPost = useCallback(
9+
(data: any) => {
10+
console.log(data);
11+
dispatch(addPostSync(data));
12+
},
13+
[dispatch]
14+
);
15+
const url = `ws://${window.envUrl}/api/v1/posting/query/ws`;
16+
useWebsocket(url, [{ eventName: "default", onEvent: onPost }]);
17+
};
Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,50 @@
1-
import { addPostSync } from "@/statemanagement/posting/postSlice";
2-
import { useAppDispatch, useAppSelector } from "@/statemanagement/store";
3-
import { useCallback, useEffect, useMemo, useState } from "react";
1+
import { useAppSelector } from "@/statemanagement/store";
2+
import { useEffect } from "react";
43

5-
interface WebsocketProviderProps {
6-
children: React.ReactNode;
7-
}
4+
export const useWebsocket = (
5+
url: string,
6+
listenToEvents: { eventName: string; onEvent: (data: unknown) => void }[]
7+
) => {
8+
const token = useAppSelector((state) => state.authentication.token) || "";
89

9-
export const WebsocketProvider = ({ children }: WebsocketProviderProps) => {
10-
const url = `ws://${window.envUrl}/api/v1/posting/query/ws`;
11-
const token = useAppSelector((state) => state.authentication.token);
12-
const dispatch = useAppDispatch();
13-
const [newWebSocket, setNewWebSocket] = useState(0);
14-
const ws = useMemo(() => {
15-
return new WebSocket(url);
16-
}, [newWebSocket]);
17-
18-
const onPost = useCallback(
19-
(data: any) => {
20-
console.log(data);
21-
dispatch(addPostSync(data));
22-
},
23-
[ws, dispatch]
24-
);
2510
useEffect(() => {
11+
websocketInitializer(url, token, listenToEvents);
12+
}, [url, token]);
13+
};
14+
15+
const websocketInitializer = (
16+
url: string,
17+
token: string,
18+
listenToEvents: { eventName: string; onEvent: (data: unknown) => void }[]
19+
) => {
20+
const initWebsocket = () => {
21+
const ws = new WebSocket(url);
22+
let isReconnecting = false;
2623
ws.onmessage = (event) => {
27-
onPost(JSON.parse(event.data));
24+
listenToEvents.forEach((listenDef) => {
25+
if (listenDef.eventName === "default") {
26+
//todo add event name to the event
27+
listenDef.onEvent(JSON.parse(event.data));
28+
}
29+
});
2830
};
2931
ws.onopen = () => {
3032
ws.send(JSON.stringify({ token: token, data: "" }));
3133
};
34+
const reconnect = () => {
35+
if (!isReconnecting) {
36+
isReconnecting = true;
37+
setTimeout(() => {
38+
initWebsocket();
39+
}, 500);
40+
}
41+
};
3242
ws.onclose = () => {
33-
setTimeout(() => {
34-
setNewWebSocket(newWebSocket + 1);
35-
}, 500);
43+
reconnect();
3644
};
3745
ws.onerror = () => {
38-
setTimeout(() => {
39-
setNewWebSocket(newWebSocket + 1);
40-
}, 500);
46+
reconnect();
4147
};
42-
}, [ws, newWebSocket, onPost]);
43-
44-
return <>{children}</>;
48+
};
49+
initWebsocket();
4550
};

0 commit comments

Comments
 (0)