UNPKG

@selfcommunity/react-core

Version:

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

272 lines (269 loc) • 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const react_1 = require("react"); const api_services_1 = require("@selfcommunity/api-services"); const types_1 = require("@selfcommunity/types"); const utils_1 = require("@selfcommunity/utils"); const Errors_1 = require("../constants/Errors"); const SCPreferencesProvider_1 = require("../components/provider/SCPreferencesProvider"); const Preferences_1 = require("../constants/Preferences"); const useSCCachingManager_1 = tslib_1.__importDefault(require("./useSCCachingManager")); const pubsub_js_1 = tslib_1.__importDefault(require("pubsub-js")); const Notification_1 = require("../constants/Notification"); const types_2 = require("@selfcommunity/types"); const use_deep_compare_effect_1 = require("use-deep-compare-effect"); /** :::info This custom hook is used to manage to manage friends. ::: :::tip How to use it: Follow these steps: ```jsx 1. const scUserContext: SCUserContextType = useSCUser(); 2. const scConnectionsManager: SCConnectionsManagerType = scUserContext.manager.connections; 3. scConnectionsManager.status(user) ``` ::: */ function useSCConnectionsManager(user) { const { cache, updateCache, emptyCache, data, setData, loading, setLoading, setUnLoading, isLoading } = (0, useSCCachingManager_1.default)(); const scPreferencesContext = (0, SCPreferencesProvider_1.useSCPreferences)(); const authUserId = user ? user.id : null; const connectionsDisabled = Preferences_1.CONFIGURATIONS_FOLLOW_ENABLED in scPreferencesContext.preferences && scPreferencesContext.preferences[Preferences_1.CONFIGURATIONS_FOLLOW_ENABLED].value; const notificationConnAcceptSubscription = (0, react_1.useRef)(null); const notificationConnRequestSubscription = (0, react_1.useRef)(null); const notificationConnRemoveSubscription = (0, react_1.useRef)(null); const notificationConnRequestCancelSubscription = (0, react_1.useRef)(null); /** * Notification subscriber handler * @param msg * @param data */ const notificationSubscriber = (msg, dataMsg) => { if (dataMsg.data.connection !== undefined) { let _upd; switch (Notification_1.SCNotificationMapping[dataMsg.data.activity_type]) { case types_1.SCNotificationTypologyType.CONNECTION_REQUEST: _upd = { user: 'request_user', state: types_2.SCConnectionStatus.CONNECTION_REQUEST_RECEIVED }; break; case types_1.SCNotificationTypologyType.CONNECTION_CANCEL_REQUEST: _upd = { user: 'cancel_request_user', state: null }; break; case types_1.SCNotificationTypologyType.CONNECTION_ACCEPT: _upd = { user: 'accept_user', state: types_2.SCConnectionStatus.CONNECTED }; break; case types_1.SCNotificationTypologyType.CONNECTION_REMOVE: _upd = { user: 'remove_user', state: null }; break; } updateCache([dataMsg.data[_upd.user].id]); setData((prev) => getDataUpdated(prev, dataMsg.data[_upd.user].id, _upd.state)); } }; /** * Subscribe to notification types user_follow, user_unfollow */ (0, use_deep_compare_effect_1.useDeepCompareEffectNoCheck)(() => { notificationConnAcceptSubscription.current = pubsub_js_1.default.subscribe(`${types_1.SCNotificationTopicType.INTERACTION}.${types_1.SCNotificationTypologyType.CONNECTION_ACCEPT}`, notificationSubscriber); notificationConnRequestSubscription.current = pubsub_js_1.default.subscribe(`${types_1.SCNotificationTopicType.INTERACTION}.${types_1.SCNotificationTypologyType.CONNECTION_REQUEST}`, notificationSubscriber); notificationConnRequestCancelSubscription.current = pubsub_js_1.default.subscribe(`${types_1.SCNotificationTopicType.INTERACTION}.${types_1.SCNotificationTypologyType.CONNECTION_CANCEL_REQUEST}`, notificationSubscriber); notificationConnRemoveSubscription.current = pubsub_js_1.default.subscribe(`${types_1.SCNotificationTopicType.INTERACTION}.${types_1.SCNotificationTypologyType.CONNECTION_REMOVE}`, notificationSubscriber); return () => { pubsub_js_1.default.unsubscribe(notificationConnAcceptSubscription.current); pubsub_js_1.default.unsubscribe(notificationConnRequestSubscription.current); pubsub_js_1.default.unsubscribe(notificationConnRequestCancelSubscription.current); pubsub_js_1.default.unsubscribe(notificationConnRemoveSubscription.current); }; }, [data]); /** * Memoized refresh all connections * It makes a single request to the server and retrieves * all the users connected by the authenticated user in a single solution * It might be useful for multi-tab sync */ const refresh = (0, react_1.useMemo)(() => () => { emptyCache(); if (authUserId && cache.length > 0) { // Only if user is authenticated api_services_1.http .request({ url: api_services_1.Endpoints.UserConnectionStatuses.url({}), method: api_services_1.Endpoints.UserConnectionStatuses.method, data: { users: cache }, }) .then((res) => { if (res.status >= 300) { return Promise.reject(res); } updateCache(Object.keys(res.data.connection_statuses).map((id) => parseInt(id))); setData(Object.keys(res.data.connection_statuses).map((k) => ({ [k]: res.data.connection_statuses[k] }))); return Promise.resolve(res.data); }) .catch((e) => { utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, 'Unable to refresh users Connections by the authenticated user.'); utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, e); }); } }, [data, authUserId, cache]); /** * Memoized Request connection */ const handleRequest = (0, react_1.useMemo)(() => (user, endpoint) => { setLoading(user.id); return api_services_1.http .request({ url: endpoint.url({ id: user.id }), method: endpoint.method, }) .then((res) => { if (res.status >= 300) { return Promise.reject(res); } updateCache([user.id]); setData((prev) => getDataUpdated(prev, user.id, res.data.connection_status)); setUnLoading(user.id); return Promise.resolve(res.data); }) .catch((e) => { utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, e); if (e && e.response && e.response && e.response.status && e.response.status === 403) { setUnLoading(user.id); return Promise.reject(e); } return checkUserConnectionStatus(user); }); }, [data, loading, cache]); /** * Memoized Request connection */ const requestConnection = (0, react_1.useMemo)(() => (user) => { return handleRequest(user, api_services_1.Endpoints.UserRequestConnection); }, [handleRequest]); /** * Memoized cancel request connection */ const cancelRequestConnection = (0, react_1.useMemo)(() => (user) => { return handleRequest(user, api_services_1.Endpoints.UserCancelRequestConnection); }, [handleRequest]); /** * Memoized Remove connection */ const removeConnection = (0, react_1.useMemo)(() => (user) => { return handleRequest(user, api_services_1.Endpoints.UserRemoveConnection); }, [handleRequest]); /** * Memoized Accept Request connection */ const acceptConnection = (0, react_1.useMemo)(() => (user) => { return handleRequest(user, api_services_1.Endpoints.UserAcceptRequestConnection); }, [handleRequest]); /** * Return current user status if exists, * otherwise return null */ const getCurrentUserCacheStatus = (0, react_1.useMemo)(() => (user) => { const d = data.filter((k) => parseInt(Object.keys(k)[0]) === user.id); return d.length ? d[0][user.id] : null; }, [data]); /** * Check if the authenticated user is connected with the user * Update the users cached * Update user statuses * @param user */ const checkUserConnectionStatus = (user) => { setLoading(user.id); return api_services_1.http .request({ url: api_services_1.Endpoints.UserCheckConnectionStatus.url({ id: user.id }), method: api_services_1.Endpoints.UserCheckConnectionStatus.method, }) .then((res) => { if (res.status >= 300) { return Promise.reject(res); } setData((prev) => getDataUpdated(prev, user.id, res.data.connection_status)); updateCache([user.id]); setUnLoading(user.id); return Promise.resolve(res.data); }) .catch((e) => { setUnLoading(user.id); return Promise.reject(e); }); }; /** * Get updated data * @param data * @param userId * @param connectionStatus */ const getDataUpdated = (data, userId, connectionStatus) => { const _index = data.findIndex((k) => parseInt(Object.keys(k)[0]) === userId); let _data; if (_index < 0) { _data = [...data, ...[{ [userId]: connectionStatus }]]; } else { _data = data.map((k, i) => { if (parseInt(Object.keys(k)[0]) === userId) { return { [Object.keys(k)[0]]: connectionStatus }; } return { [Object.keys(k)[0]]: data[i][Object.keys(k)[0]] }; }); } return _data; }; /** * Bypass remote check if the user is followed */ const getConnectionStatus = (0, react_1.useMemo)(() => (user) => { updateCache([user.id]); setData((prev) => getDataUpdated(prev, user.id, user.connection_status)); return user.connection_status; }, [data, cache]); /** * Memoized status * If user is already in cache -> check data user statuses, * otherwise, check if auth user is connected with user */ const status = (user) => { if (cache.includes(user.id)) { return getCurrentUserCacheStatus(user); } if (authUserId) { if ('connection_status' in user) { return getConnectionStatus(user); } if (!isLoading(user)) { checkUserConnectionStatus(user); } } return null; }; /** * Empty cache on logout */ (0, react_1.useEffect)(() => { if (!authUserId) { emptyCache(); } }, [authUserId]); if (connectionsDisabled || !user) { return { connections: data, loading, isLoading }; } return { connections: data, loading, isLoading, status, requestConnection, cancelRequestConnection, acceptConnection, removeConnection, refresh, emptyCache, }; } exports.default = useSCConnectionsManager;