UNPKG

@selfcommunity/react-core

Version:

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

100 lines (98 loc) 4.22 kB
import { useEffect, useMemo, useRef } from 'react'; import { http, Endpoints } from '@selfcommunity/api-services'; import { SCNotificationTopicType, SCNotificationTypologyType } from '@selfcommunity/types'; import { useSCPreferences } from '../components/provider/SCPreferencesProvider'; import { CONFIGURATIONS_FOLLOW_ENABLED } from '../constants/Preferences'; import useSCCachingManager from './useSCCachingManager'; import PubSub from 'pubsub-js'; import { SCNotificationMapping } from '../constants/Notification'; /** :::info This custom hook is used to manage followers users. ::: :::tip How to use it: Follow these steps: ```jsx 1. const scUserContext: SCUserContextType = useSCUser(); 2. const scFollowersManager: SCFollowersManagerType = scUserContext.manager.followers; 3. scFollowersManager.isFollowers(user) ``` ::: */ export default function useSCFollowersManager(user) { const { cache, updateCache, emptyCache, data, setData, loading, setLoading, setUnLoading, isLoading } = useSCCachingManager(); const scPreferencesContext = useSCPreferences(); const followEnabled = CONFIGURATIONS_FOLLOW_ENABLED in scPreferencesContext.preferences && scPreferencesContext.preferences[CONFIGURATIONS_FOLLOW_ENABLED].value; const notificationFollowSubscription = useRef(null); const notificationUnFollowSubscription = useRef(null); /** * Notification subscriber only for FOLLOW * @param msg * @param data */ const notificationSubscriber = (msg, d) => { if (SCNotificationMapping[d.data.activity_type] === SCNotificationTypologyType.USER_FOLLOW) { updateCache([d.data.follower.id]); if (!data.includes(d.data.follower.id)) { setData((prev) => [...[d.data.follower.id], ...prev]); } } else if (SCNotificationMapping[d.data.activity_type] === SCNotificationTypologyType.USER_UNFOLLOW) { updateCache([d.data.unfollower.id]); if (data.includes(d.data.unfollower.id)) { setData((prev) => prev.filter((id) => id !== d.data.unfollower.id)); } } }; /** * Subscribe to notification types user_follow, user_unfollow */ useEffect(() => { notificationFollowSubscription.current = PubSub.subscribe(`${SCNotificationTopicType.INTERACTION}.${SCNotificationTypologyType.USER_FOLLOW}`, notificationSubscriber); notificationUnFollowSubscription.current = PubSub.subscribe(`${SCNotificationTopicType.INTERACTION}.${SCNotificationTypologyType.USER_UNFOLLOW}`, notificationSubscriber); return () => { PubSub.unsubscribe(notificationFollowSubscription.current); PubSub.unsubscribe(notificationUnFollowSubscription.current); }; }, [data.length, cache.length]); /** * Check if the user is a followers of the authenticated user * Update the followers cached * @param user */ const checkIsUserFollowers = (user) => { setLoading(user.id); http .request({ url: Endpoints.CheckUserFollower.url({ id: user.id }), method: Endpoints.CheckUserFollower.method, }) .then((res) => { if (res.status >= 300) { return Promise.reject(res); } updateCache([user.id]); setData((prev) => (res.data.is_follower ? [...prev, ...[user.id]] : prev.filter((id) => id !== user.id))); setUnLoading(user.id); return Promise.resolve(res.data); }); }; /** * Memoized isFollower * If user is already in cache -> check if the user is in followers, * otherwise, check if user is a followers of the authenticated user */ const isFollower = useMemo(() => (user) => { if (cache.includes(user.id)) { return Boolean(data.includes(user.id)); } if (!isLoading(user)) { checkIsUserFollowers(user); } return false; }, [data, loading, cache]); if (!followEnabled || !user) { return { followers: data, loading, isLoading }; } return { followers: data, loading, isLoading, isFollower, emptyCache }; }