qortal-mobile/src/components/Group/WebsocketActive.tsx
2024-09-12 05:01:36 +03:00

121 lines
4.3 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
import { getBaseApiReactSocket, pauseAllQueues, resumeAllQueues } from '../../App';
export const WebSocketActive = ({ myAddress, setIsLoadingGroups }) => {
const socketRef = useRef(null); // WebSocket reference
const timeoutIdRef = useRef(null); // Timeout ID reference
const groupSocketTimeoutRef = useRef(null); // Group Socket Timeout reference
const initiateRef = useRef(null)
const forceCloseWebSocket = () => {
if (socketRef.current) {
console.log('Force closing the WebSocket');
clearTimeout(timeoutIdRef.current);
clearTimeout(groupSocketTimeoutRef.current);
socketRef.current.close(1000, 'forced');
socketRef.current = null;
}
};
useEffect(() => {
if (!myAddress) return; // Only proceed if myAddress is set
if (!window?.location?.href?.includes("?main=true")) return;
const pingHeads = () => {
try {
if (socketRef.current?.readyState === WebSocket.OPEN) {
socketRef.current.send('ping');
timeoutIdRef.current = setTimeout(() => {
if (socketRef.current) {
socketRef.current.close();
clearTimeout(groupSocketTimeoutRef.current);
}
}, 5000); // Close if no pong in 5 seconds
}
} catch (error) {
console.error('Error during ping:', error);
}
};
const initWebsocketMessageGroup = async () => {
forceCloseWebSocket(); // Ensure we close any existing connection
const currentAddress = myAddress;
try {
if(!initiateRef.current) {
setIsLoadingGroups(true)
pauseAllQueues()
}
const socketLink = `${getBaseApiReactSocket()}/websockets/chat/active/${currentAddress}?encoding=BASE64`;
socketRef.current = new WebSocket(socketLink);
socketRef.current.onopen = () => {
console.log('WebSocket connection opened');
setTimeout(pingHeads, 50); // Initial ping
};
socketRef.current.onmessage = (e) => {
try {
if (e.data === 'pong') {
clearTimeout(timeoutIdRef.current);
groupSocketTimeoutRef.current = setTimeout(pingHeads, 45000); // Ping every 45 seconds
} else {
if(!initiateRef.current) {
setIsLoadingGroups(false)
initiateRef.current = true
resumeAllQueues()
}
const data = JSON.parse(e.data);
const filteredGroups = data.groups?.filter(item => item?.groupId !== 0) || [];
const sortedGroups = filteredGroups.sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));
const sortedDirects = (data?.direct || []).filter(item =>
item?.name !== 'extension-proxy' && item?.address !== 'QSMMGSgysEuqDCuLw3S4cHrQkBrh3vP3VH'
).sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));
chrome?.runtime?.sendMessage({
action: 'handleActiveGroupDataFromSocket',
payload: {
groups: sortedGroups,
directs: sortedDirects,
},
});
}
} catch (error) {
console.error('Error parsing onmessage data:', error);
}
};
socketRef.current.onclose = (event) => {
clearTimeout(groupSocketTimeoutRef.current);
clearTimeout(timeoutIdRef.current);
console.warn(`WebSocket closed: ${event.reason || 'unknown reason'}`);
if (event.reason !== 'forced' && event.code !== 1000) {
setTimeout(() => initWebsocketMessageGroup(), 10000); // Retry after 10 seconds
}
};
socketRef.current.onerror = (error) => {
console.error('WebSocket error:', error);
clearTimeout(groupSocketTimeoutRef.current);
clearTimeout(timeoutIdRef.current);
if (socketRef.current) {
socketRef.current.close();
}
};
} catch (error) {
console.error('Error initializing WebSocket:', error);
}
};
initWebsocketMessageGroup(); // Initialize WebSocket on component mount
return () => {
forceCloseWebSocket(); // Clean up WebSocket on component unmount
};
}, [myAddress]);
return null;
};