@oxyhq/services
Version:
Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀
161 lines (152 loc) • 6.98 kB
JavaScript
;
import { useCallback, useMemo, useEffect } from 'react';
import { useFollowStore } from '../stores/followStore';
import { useOxy } from '../context/OxyContext';
export const useFollow = userId => {
const {
oxyServices
} = useOxy();
const userIds = useMemo(() => Array.isArray(userId) ? userId : userId ? [userId] : [], [userId]);
const isSingleUser = typeof userId === 'string';
// Zustand selectors
const followState = useFollowStore();
// Single user helpers
const isFollowing = isSingleUser && userId ? followState.followingUsers[userId] ?? false : false;
const isLoading = isSingleUser && userId ? followState.loadingUsers[userId] ?? false : false;
const error = isSingleUser && userId ? followState.errors[userId] ?? null : null;
// Follower count helpers
const followerCount = isSingleUser && userId ? followState.followerCounts[userId] ?? null : null;
const followingCount = isSingleUser && userId ? followState.followingCounts[userId] ?? null : null;
const isLoadingCounts = isSingleUser && userId ? followState.loadingCounts[userId] ?? false : false;
const toggleFollow = useCallback(async () => {
if (!isSingleUser || !userId) throw new Error('toggleFollow is only available for single user mode');
await followState.toggleFollowUser(userId, oxyServices, isFollowing);
}, [isSingleUser, userId, followState, oxyServices, isFollowing]);
const setFollowStatus = useCallback(following => {
if (!isSingleUser || !userId) throw new Error('setFollowStatus is only available for single user mode');
followState.setFollowingStatus(userId, following);
}, [isSingleUser, userId, followState]);
const fetchStatus = useCallback(async () => {
if (!isSingleUser || !userId) throw new Error('fetchStatus is only available for single user mode');
await followState.fetchFollowStatus(userId, oxyServices);
}, [isSingleUser, userId, followState, oxyServices]);
const clearError = useCallback(() => {
if (!isSingleUser || !userId) throw new Error('clearError is only available for single user mode');
followState.clearFollowError(userId);
}, [isSingleUser, userId, followState]);
const fetchUserCounts = useCallback(async () => {
if (!isSingleUser || !userId) throw new Error('fetchUserCounts is only available for single user mode');
await followState.fetchUserCounts(userId, oxyServices);
}, [isSingleUser, userId, followState, oxyServices]);
const setFollowerCount = useCallback(count => {
if (!isSingleUser || !userId) throw new Error('setFollowerCount is only available for single user mode');
followState.setFollowerCount(userId, count);
}, [isSingleUser, userId, followState]);
const setFollowingCount = useCallback(count => {
if (!isSingleUser || !userId) throw new Error('setFollowingCount is only available for single user mode');
followState.setFollowingCount(userId, count);
}, [isSingleUser, userId, followState]);
// Auto-fetch counts when hook is used for a single user and counts are missing.
useEffect(() => {
if (!isSingleUser || !userId) return;
// If either count is not set and we're not already loading counts, trigger a fetch.
if ((followerCount === null || followingCount === null) && !isLoadingCounts) {
fetchUserCounts().catch(err => console.warn('useFollow: fetchUserCounts failed', err));
}
}, [isSingleUser, userId, followerCount, followingCount, isLoadingCounts, fetchUserCounts]);
// Multiple user helpers
const followData = useMemo(() => {
const data = {};
userIds.forEach(uid => {
data[uid] = {
isFollowing: followState.followingUsers[uid] ?? false,
isLoading: followState.loadingUsers[uid] ?? false,
error: followState.errors[uid] ?? null
};
});
return data;
}, [userIds, followState.followingUsers, followState.loadingUsers, followState.errors]);
const toggleFollowForUser = useCallback(async targetUserId => {
const currentState = followState.followingUsers[targetUserId] ?? false;
await followState.toggleFollowUser(targetUserId, oxyServices, currentState);
}, [followState, oxyServices]);
const setFollowStatusForUser = useCallback((targetUserId, following) => {
followState.setFollowingStatus(targetUserId, following);
}, [followState]);
const fetchStatusForUser = useCallback(async targetUserId => {
await followState.fetchFollowStatus(targetUserId, oxyServices);
}, [followState, oxyServices]);
const fetchAllStatuses = useCallback(async () => {
await Promise.all(userIds.map(uid => followState.fetchFollowStatus(uid, oxyServices)));
}, [userIds, followState, oxyServices]);
const clearErrorForUser = useCallback(targetUserId => {
followState.clearFollowError(targetUserId);
}, [followState]);
const updateCountsFromFollowAction = useCallback((targetUserId, action, counts) => {
const currentUserId = oxyServices.getCurrentUserId() || undefined;
followState.updateCountsFromFollowAction(targetUserId, action, counts, currentUserId);
}, [followState, oxyServices]);
// Aggregate helpers for multiple users
const isAnyLoading = userIds.some(uid => followState.loadingUsers[uid]);
const hasAnyError = userIds.some(uid => !!followState.errors[uid]);
const allFollowing = userIds.every(uid => followState.followingUsers[uid]);
const allNotFollowing = userIds.every(uid => !followState.followingUsers[uid]);
if (isSingleUser && userId) {
return {
isFollowing,
isLoading,
error,
toggleFollow,
setFollowStatus,
fetchStatus,
clearError,
// Follower count methods
followerCount,
followingCount,
isLoadingCounts,
fetchUserCounts,
setFollowerCount,
setFollowingCount
};
}
return {
followData,
toggleFollowForUser,
setFollowStatusForUser,
fetchStatusForUser,
fetchAllStatuses,
clearErrorForUser,
isAnyLoading,
hasAnyError,
allFollowing,
allNotFollowing
};
};
// Convenience hook for just follower counts
export const useFollowerCounts = userId => {
const {
oxyServices
} = useOxy();
const followState = useFollowStore();
const followerCount = followState.followerCounts[userId] ?? null;
const followingCount = followState.followingCounts[userId] ?? null;
const isLoadingCounts = followState.loadingCounts[userId] ?? false;
const fetchUserCounts = useCallback(async () => {
await followState.fetchUserCounts(userId, oxyServices);
}, [userId, followState, oxyServices]);
const setFollowerCount = useCallback(count => {
followState.setFollowerCount(userId, count);
}, [userId, followState]);
const setFollowingCount = useCallback(count => {
followState.setFollowingCount(userId, count);
}, [userId, followState]);
return {
followerCount,
followingCount,
isLoadingCounts,
fetchUserCounts,
setFollowerCount,
setFollowingCount
};
};
//# sourceMappingURL=useFollow.js.map