Nexus / frontend /components /RelayAPI.js
ChandimaPrabath's picture
debug
02f98b1
// RelayAPI.js - Next.js Wrapper for the WebSocket Server
import { useEffect, useState, useCallback, useRef } from "react";
const useWebSocket = (userId) => {
const [socket, setSocket] = useState(null);
const [messages, setMessages] = useState([]);
const [connectedChannels, setConnectedChannels] = useState(new Set());
const reconnectInterval = useRef(null);
const connect = useCallback(() => {
const ws = new WebSocket(`${process.env.NEXT_PUBLIC_RELAY_URL}/ws?user_id=${userId}`);
ws.onopen = () => {
console.debug("WebSocket connected.");
clearInterval(reconnectInterval.current);
};
ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.debug("Received message:", data);
setMessages((prev) => [...prev, data]);
console.debug(messages);
} catch (error) {
console.debug("Failed to parse WebSocket message:", event.data);
}
};
ws.onclose = () => {
console.warn("WebSocket closed. Reconnecting...");
reconnectInterval.current = setInterval(() => connect(), 5000);
};
ws.onerror = (error) => {
console.debug("WebSocket error:", error);
ws.close();
};
setSocket(ws);
}, [userId]);
useEffect(() => {
if (!userId) return;
connect();
return () => {
clearInterval(reconnectInterval.current);
setConnectedChannels(new Set());
if (socket) socket.close();
};
}, [connect, userId]);
const sendMessage = useCallback(
(action, channel, message, targetUserId = null) => {
if (!socket || socket.readyState !== WebSocket.OPEN) {
console.warn("WebSocket is not connected.");
return;
}
const payload = { action, channel, message, sender: userId };
if (targetUserId) payload.target_user_id = targetUserId;
try {
socket.send(JSON.stringify(payload));
console.debug("Sent message:", payload);
} catch (error) {
console.debug("Failed to send WebSocket message:", error);
}
},
[socket, userId]
);
const joinChannel = useCallback(
(channel) => {
if (connectedChannels.has(channel)) return;
sendMessage("join", channel);
setConnectedChannels((prev) => new Set([...prev, channel]));
},
[sendMessage, connectedChannels]
);
const leaveChannel = useCallback(
(channel) => {
if (!connectedChannels.has(channel)) return;
sendMessage("leave", channel);
setConnectedChannels((prev) => {
const updated = new Set(prev);
updated.delete(channel);
return updated;
});
},
[sendMessage, connectedChannels]
);
const broadcast = useCallback(
(channel, message) => {
sendMessage("broadcast", channel, message);
},
[sendMessage]
);
const sendToUser = useCallback(
(targetUserId, message) => {
sendMessage("send_to_user", null, message, targetUserId);
},
[sendMessage]
);
return { messages, joinChannel, leaveChannel, broadcast, sendToUser };
};
export const RelayAPIProvider = ({ userId=null, children }) => {
if (userId === null) {
userId = localStorage.getItem("u_id");
console.log("inside context")
}
const contextValue = useWebSocket(userId);
return (
<RelayAPIContext.Provider value={contextValue}>{children}</RelayAPIContext.Provider>
);
};
import React, { useContext } from "react";
const RelayAPIContext = React.createContext(null);
export const useRelayAPI = () => {
const context = useContext(RelayAPIContext);
if (!context) {
throw new Error("useRelayAPI must be used within a RelayAPIProvider");
}
return context;
};