-
Notifications
You must be signed in to change notification settings - Fork 0
/
useSCWebSocket.ts
116 lines (109 loc) · 4.5 KB
/
useSCWebSocket.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import {useEffect, useState} from 'react';
import {SCContextType, SCUserContextType} from '../types';
import {SCNotificationTopicType, SCNotificationTypologyType} from '@selfcommunity/types';
import {useSCContext} from '../components/provider/SCContextProvider';
import {useSCUser} from '../components/provider/SCUserProvider';
import {WSClientType} from '@selfcommunity/utils';
import {WSClient} from '@selfcommunity/utils';
import {SCNotificationMapping, SCNotificationTopics} from '../constants/Notification';
import {WS_FACILITY_NOTIFY, WS_PROTOCOL_PREFIX, WS_HEARTBEAT_MESSAGE} from '../constants/WebSocket';
import PubSub from 'pubsub-js';
/**
:::info
This custom hook is used to to init web socket.
:::
*/
export default function useSCWebSocket() {
const scContext: SCContextType = useSCContext();
const scUserContext: SCUserContextType = useSCUser();
const [wsInstance, setWsInstance] = useState<WSClientType>(null);
// Websocket uri and protocols
const _wsUri = `wss://${new URL(scContext.settings.portal).hostname}/ws/${WS_FACILITY_NOTIFY}?subscribe-user`;
const _wsProtocol =
scContext.settings.session.authToken && scContext.settings.session.authToken.accessToken
? `${WS_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 && _wsProtocol) {
setWsInstance(
WSClient.getInstance({
uri: _wsUri,
heartbeatMsg: WS_HEARTBEAT_MESSAGE,
protocols: [_wsProtocol],
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};
}