UNPKG

@replyke/core

Version:

Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.

243 lines 9.53 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = require("react"); const useFetchSpace_1 = __importDefault(require("./useFetchSpace")); const useFetchSpaceByShortId_1 = __importDefault(require("./useFetchSpaceByShortId")); const useFetchSpaceBySlug_1 = __importDefault(require("./useFetchSpaceBySlug")); const useFetchSpaceBreadcrumb_1 = __importDefault(require("./useFetchSpaceBreadcrumb")); const useUpdateSpace_1 = __importDefault(require("./useUpdateSpace")); const useDeleteSpace_1 = __importDefault(require("./useDeleteSpace")); const useJoinSpace_1 = __importDefault(require("./useJoinSpace")); const useLeaveSpace_1 = __importDefault(require("./useLeaveSpace")); const useSpacePermissions_1 = __importDefault(require("./useSpacePermissions")); const handleError_1 = require("../../utils/handleError"); function useSpaceData({ spaceId, shortId, slug, space: spaceProp, include, }) { const [space, setSpace] = (0, react_1.useState)(spaceProp); const [loading, setLoading] = (0, react_1.useState)(false); const [error, setError] = (0, react_1.useState)(null); const [breadcrumb, setBreadcrumb] = (0, react_1.useState)([]); // Cache to store fetched spaces keyed by unique identifier const spaceCache = (0, react_1.useRef)({}); // Fetch hooks const fetchSpace = (0, useFetchSpace_1.default)(); const fetchSpaceByShortId = (0, useFetchSpaceByShortId_1.default)(); const fetchSpaceBySlug = (0, useFetchSpaceBySlug_1.default)(); const fetchSpaceBreadcrumb = (0, useFetchSpaceBreadcrumb_1.default)(); // Operation hooks const updateSpaceHook = (0, useUpdateSpace_1.default)(); const deleteSpaceHook = (0, useDeleteSpace_1.default)(); const joinSpaceHook = (0, useJoinSpace_1.default)(); const leaveSpaceHook = (0, useLeaveSpace_1.default)(); // Stabilize include param to prevent infinite loops when passed as inline array const stableInclude = (0, react_1.useMemo)(() => include, // eslint-disable-next-line react-hooks/exhaustive-deps [JSON.stringify(include)]); // Compute permissions const permissions = (0, useSpacePermissions_1.default)({ memberPermissions: space?.memberPermissions, postingPermission: space?.postingPermission || "members", readingPermission: space?.readingPermission || "anyone", }); // Handle space update const handleUpdateSpace = (0, react_1.useCallback)(async ({ update }) => { if (!space) return; try { const newSpace = await updateSpaceHook({ spaceId: space.id, update, }); if (newSpace) setSpace(newSpace); return newSpace; } catch (err) { (0, handleError_1.handleError)(err, "Failed to update space"); setError("Failed to update space"); } }, [space, updateSpaceHook]); // Handle space delete const handleDeleteSpace = (0, react_1.useCallback)(async () => { if (!space) return; try { await deleteSpaceHook({ spaceId: space.id }); setSpace(undefined); } catch (err) { (0, handleError_1.handleError)(err, "Failed to delete space"); setError("Failed to delete space"); } }, [space, deleteSpaceHook]); // Handle join space const handleJoinSpace = (0, react_1.useCallback)(async () => { if (!space) return; try { const response = await joinSpaceHook({ spaceId: space.id }); const member = response.membership; // Update space with new memberPermissions and member count // Note: When joining, role is always "member", status is "pending" or "active" setSpace((prev) => { if (!prev) return prev; return { ...prev, membersCount: prev.membersCount + 1, memberPermissions: { isAdmin: false, isModerator: false, isMember: member.status === "active", status: member.status, canPost: member.status === "active", canModerate: false, canRead: true, }, }; }); } catch (err) { (0, handleError_1.handleError)(err, "Failed to join space"); setError("Failed to join space"); } }, [space, joinSpaceHook]); // Handle leave space const handleLeaveSpace = (0, react_1.useCallback)(async () => { if (!space) return; try { await leaveSpaceHook({ spaceId: space.id }); // Update space to remove memberPermissions and decrement member count setSpace((prev) => { if (!prev) return prev; return { ...prev, membersCount: Math.max(0, prev.membersCount - 1), memberPermissions: null, }; }); } catch (err) { (0, handleError_1.handleError)(err, "Failed to leave space"); setError("Failed to leave space"); } }, [space, leaveSpaceHook]); // Fetch space effect (0, react_1.useEffect)(() => { const handleFetchSpace = async () => { if (!spaceId && !shortId && !slug) return; // If space is already loaded with matching ID, skip fetch if (space && spaceId && space.id === spaceId) return; if (space && shortId && space.shortId === shortId) return; if (space && slug && space.slug === slug) return; const uniqueKey = `${spaceId ?? ""}-${shortId ?? ""}-${slug ?? ""}`; // If we have a cached space, update the state and exit if (spaceCache.current[uniqueKey]) { setSpace(spaceCache.current[uniqueKey]); return; } setLoading(true); setError(null); try { let fetchedSpace = null; if (spaceId) { fetchedSpace = await fetchSpace({ spaceId, include: stableInclude }); } else if (shortId) { fetchedSpace = await fetchSpaceByShortId({ shortId, include: stableInclude }); } else if (slug) { fetchedSpace = await fetchSpaceBySlug({ slug, include: stableInclude }); } if (fetchedSpace) { // Store the fetched space in cache spaceCache.current[uniqueKey] = fetchedSpace; setSpace(fetchedSpace); } else { setSpace(null); } } catch (err) { (0, handleError_1.handleError)(err, "Failed to fetch space"); setError("Failed to fetch space"); setSpace(null); } finally { setLoading(false); } }; handleFetchSpace(); }, [ fetchSpace, fetchSpaceByShortId, fetchSpaceBySlug, spaceId, shortId, slug, space, stableInclude, ]); // Fetch breadcrumb effect (0, react_1.useEffect)(() => { const handleFetchBreadcrumb = async () => { if (!space?.id) { setBreadcrumb([]); return; } try { const breadcrumbData = await fetchSpaceBreadcrumb({ spaceId: space.id, }); setBreadcrumb(breadcrumbData.breadcrumb); } catch (err) { // Breadcrumb is not critical, just log the error (0, handleError_1.handleError)(err, "Failed to fetch space breadcrumb"); setBreadcrumb([]); } }; handleFetchBreadcrumb(); }, [space?.id, fetchSpaceBreadcrumb]); // Update space when prop changes (0, react_1.useEffect)(() => { if (spaceProp) setSpace(spaceProp); }, [spaceProp]); return { space, setSpace, // Permissions isMember: permissions.isMember, isAdmin: permissions.isAdmin, isModerator: permissions.isModerator, canPost: permissions.canPost, canModerate: permissions.canModerate, canRead: permissions.canRead, membershipStatus: space?.memberPermissions?.status || null, isPending: permissions.isPending, isBanned: permissions.isBanned, // Hierarchy breadcrumb, parentSpace: space?.parentSpace || null, childSpaces: space?.childSpaces || [], // Operations updateSpace: handleUpdateSpace, deleteSpace: handleDeleteSpace, joinSpace: handleJoinSpace, leaveSpace: handleLeaveSpace, // State loading, error, }; } exports.default = useSpaceData; //# sourceMappingURL=useSpaceData.js.map