UNPKG

@selfcommunity/react-core

Version:

React Core Components useful for integrating UI Community components (react-ui).

111 lines (110 loc) 5.3 kB
import { useEffect, useState } from 'react'; import { SCNotificationTopicType, SCNotificationTypologyType } from '@selfcommunity/types'; import { useSCContext } from '../components/provider/SCContextProvider'; import { useSCUser } from '../components/provider/SCUserProvider'; import { WSClient } from '@selfcommunity/utils'; import { SCNotificationMapping, SCNotificationTopics } from '../constants/Notification'; import { WS_FACILITY_NOTIFY, WS_SUB_PROTOCOL_PREFIX, WS_HEARTBEAT_MESSAGE, WS_PROTOCOL_SECURE, WS_PROTOCOL_INSECURE, WS_PREFIX_PATH, } from '../constants/WebSocket'; import PubSub from 'pubsub-js'; /** :::info This custom hook is used to init web socket. ::: */ export default function useSCWebSocket() { const scContext = useSCContext(); const scUserContext = useSCUser(); const [wsInstance, setWsInstance] = useState(null); // Websocket uri, prefixPath, protocols and sub-protocols const _wsProtocol = scContext.settings.notifications.webSocket.secure || !('secure' in scContext.settings.notifications.webSocket) ? WS_PROTOCOL_SECURE : WS_PROTOCOL_INSECURE; const _wsPrefixPath = scContext.settings.notifications.webSocket.prefixPath || WS_PREFIX_PATH; const _wsUri = `${_wsProtocol}://${new URL(scContext.settings.portal).hostname}/${_wsPrefixPath}/${WS_FACILITY_NOTIFY}?subscribe-user`; const _wsSubProtocol = scContext.settings.session.authToken && scContext.settings.session.authToken.accessToken ? `${WS_SUB_PROTOCOL_PREFIX}${scContext.settings.session.authToken.accessToken}` : null; /** * Before document unload handler * Close webSocket */ const handleBeforeUnload = () => { wsInstance && wsInstance.close(); }; /** * Check if there is a currently active session and a * wsInstance connection when the provider is mounted for the first time. * If there is an error, it means there is no session. */ useEffect(() => { if (scUserContext.user && !wsInstance && _wsUri && _wsSubProtocol) { setWsInstance(WSClient.getInstance({ uri: _wsUri, heartbeatMsg: WS_HEARTBEAT_MESSAGE, protocols: [_wsSubProtocol], receiveMessage: receiveMessage, })); // Close the socket channel before window unload window.addEventListener('beforeunload', handleBeforeUnload); } if (!scUserContext.user && wsInstance) { // Disconnect the socket window.removeEventListener('beforeunload', handleBeforeUnload); wsInstance && wsInstance.close(); } }, [scUserContext.user]); /** * Receive a message from wsInstance. */ const receiveMessage = (data) => { // receive a message though the websocket from the server let _data = JSON.parse(data); if (_data && _data.type && SCNotificationTopics.includes(_data.type)) { if (_data.type === SCNotificationTopicType.INTERACTION) { /** * With topic interaction there are two types of notifications group: * - notification_banner * - comment, nested_comment, follow, etc.. */ if (_data.data.activity_type === SCNotificationTypologyType.NOTIFICATION_BANNER) { /** * Notification of type 'notification_banner' * It is a special case of notifications with topic 'interaction' */ PubSub.publish(`${_data.type}.${SCNotificationTypologyType.NOTIFICATION_BANNER}`, _data); } else if (SCNotificationMapping[_data.data.activity_type]) { /** * Notification of type 'comment', 'nested_comment', etc... */ PubSub.publish(`${_data.type}.${SCNotificationMapping[_data.data.activity_type]}`, _data); } setNotificationCounters(_data.data); } else { PubSub.publish(`${_data.type}`, _data); } } }; /** * Update user context counters * @param payload */ const setNotificationCounters = (payload) => { /** * The counter count_interactions includes pure interactions and notification banners, * so unseen_interactions_counter = payload.count_interactions - payload.count_notification_banners * if payload.count_notification_banners exists (was added later in the payload of the message ws) */ let unseen_interactions_counter = 0; if (payload.count_interactions !== undefined) { unseen_interactions_counter = payload.count_interactions; } if (payload.count_notification_banners !== undefined) { unseen_interactions_counter = Math.max(unseen_interactions_counter - payload.count_notification_banners, 0); scUserContext.setUnseenInteractionsCounter(payload.count_notification_banners); } payload.count_interactions !== undefined && scUserContext.setUnseenInteractionsCounter(unseen_interactions_counter); }; return { wsInstance, setWsInstance }; }