@selfcommunity/react-core
Version:
React Core Components useful for integrating UI Community components (react-ui).
161 lines (159 loc) • 6.18 kB
JavaScript
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 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"));
/**
* Used on refresh and in isFollowed method
* Check if the user status is 'followed'
* to update the cache and data
*/
const STATUS_FOLLOWED = 'followed';
/**
:::info
This custom hook is used to manage followed users.
:::
:::tip How to use it:
Follow these steps:
```jsx
1. const scUserContext: SCUserContextType = useSCUser();
2. const scFollowedManager: SCFollowedManagerType = scUserContext.manager.followed;
3. scFollowedManager.isFollowed(user)
```
:::
*/
function useSCFollowedManager(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 followEnabled = Preferences_1.CONFIGURATIONS_FOLLOW_ENABLED in scPreferencesContext.preferences && scPreferencesContext.preferences[Preferences_1.CONFIGURATIONS_FOLLOW_ENABLED].value;
/**
* Memoized refresh all followed
* It makes a single request to the server and retrieves
* all the users followed by the authenticated user in a single solution
* It might be useful for multi-tab sync
*/
const refresh = (0, react_1.useMemo)(() => () => {
emptyCache();
if (user && 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.entries(res.data.connection_statuses)
.filter(([, v]) => v === STATUS_FOLLOWED)
.map(([k]) => parseInt(k)));
return Promise.resolve(res.data);
})
.catch((e) => {
utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, 'Unable to refresh users followed by the authenticated user.');
utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, e);
});
}
}, [data, user, cache]);
/**
* Memoized follow/unfollow User
* Toggle action
*/
const follow = (0, react_1.useMemo)(() => (user) => {
setLoading(user.id);
return api_services_1.http
.request({
url: api_services_1.Endpoints.FollowUser.url({ id: user.id }),
method: api_services_1.Endpoints.FollowUser.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
updateCache([user.id]);
const isFollowed = data.includes(user.id);
setData((prev) => (isFollowed ? prev.filter((id) => id !== user.id) : [...[user.id], ...prev]));
setUnLoading(user.id);
return Promise.resolve(res);
})
.catch((e) => {
setUnLoading(user.id);
return Promise.reject(e);
});
}, [data, loading, cache]);
/**
* Check if the authenticated user follow the user
* Update the followed cached
* Update followed user
* @param user
*/
const checkIsUserFollowed = (user) => {
setLoading(user.id);
api_services_1.http
.request({
url: api_services_1.Endpoints.CheckUserFollowed.url({ id: user.id }),
method: api_services_1.Endpoints.CheckUserFollowed.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
updateCache([user.id]);
setData((prev) => (res.data.is_followed ? [...prev, ...[user.id]] : prev.filter((id) => id !== user.id)));
setUnLoading(user.id);
return Promise.resolve(res.data);
});
};
/**
* Bypass remote check if the user is followed
*/
const getConnectionStatus = (0, react_1.useMemo)(() => (user) => {
const isFollowed = user.connection_status === STATUS_FOLLOWED;
updateCache([user.id]);
setData((prev) => (isFollowed ? [...prev, ...[user.id]] : prev));
return isFollowed;
}, [data, cache]);
/**
* Memoized isFollowed
* If user is already in cache -> check if the user is in followed,
* otherwise, check if auth user follow the user
*/
const isFollowed = (0, react_1.useMemo)(() => {
return (user) => {
if (cache.includes(user.id)) {
return Boolean(data.includes(user.id));
}
if (authUserId) {
if ('connection_status' in user) {
return getConnectionStatus(user);
}
if (!isLoading(user)) {
checkIsUserFollowed(user);
}
}
return false;
};
}, [data, loading, cache, authUserId]);
/**
* Empty cache on logout
*/
(0, react_1.useEffect)(() => {
if (!authUserId) {
emptyCache();
}
}, [authUserId]);
if (!followEnabled || !user) {
return { followed: data, loading, isLoading };
}
return { followed: data, loading, isLoading, follow, isFollowed, refresh, emptyCache };
}
exports.default = useSCFollowedManager;
;