UNPKG

@replyke/core

Version:

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

200 lines 9.04 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 hooks_1 = require("../../store/hooks"); const spaceListsSlice_1 = require("../../store/slices/spaceListsSlice"); const useSpaceListActions_1 = __importDefault(require("./useSpaceListActions")); const handleError_1 = require("../../utils/handleError"); function useSpaceList({ listId }) { const dispatch = (0, hooks_1.useReplykeDispatch)(); // Get state from Redux (parameterized selectors) const spaceList = (0, hooks_1.useReplykeSelector)((state) => (0, spaceListsSlice_1.selectSpaceList)(state, listId)); const spaces = (0, hooks_1.useReplykeSelector)((state) => (0, spaceListsSlice_1.selectSpaceListSpaces)(state, listId)); const loading = (0, hooks_1.useReplykeSelector)((state) => (0, spaceListsSlice_1.selectSpaceListLoading)(state, listId)); const hasMore = (0, hooks_1.useReplykeSelector)((state) => (0, spaceListsSlice_1.selectSpaceListHasMore)(state, listId)); const filters = (0, hooks_1.useReplykeSelector)((state) => (0, spaceListsSlice_1.selectSpaceListFilters)(state, listId)); const config = (0, hooks_1.useReplykeSelector)((state) => (0, spaceListsSlice_1.selectSpaceListConfig)(state, listId)); // Get space actions hook const spaceActions = (0, useSpaceListActions_1.default)(); // Debounce timer for filter changes const debounceTimer = (0, react_1.useRef)(null); // Fetch spaces function (always triggers a fetch) const handleFetchSpaces = (0, react_1.useCallback)((newFilters, newConfig, options) => { // Apply config defaults if not provided const configWithDefaults = { limit: 20, ...newConfig, }; // Ensure Redux state is initialized and update filters/config dispatch((0, spaceListsSlice_1.initializeList)({ listId })); dispatch((0, spaceListsSlice_1.updateFilters)({ listId, filters: newFilters, config: configWithDefaults, options, })); // Clear spaces immediately if requested if (options?.clearImmediately) { dispatch((0, spaceListsSlice_1.setSpaceListSpaces)({ listId, spaces: [], append: false })); } // Define the fetch logic const performFetch = async () => { // Use the applied config (configWithDefaults is the source of truth for this fetch) const currentConfig = { limit: configWithDefaults.limit }; // Build final filters by taking current state and applying new filters const currentState = spaceList || { sortBy: "newest", searchSlug: null, searchName: null, searchDescription: null, searchAny: null, readingPermission: null, memberOf: false, parentSpaceId: null, }; const finalFilters = { ...currentState }; // Apply resetUnspecified logic (only reset filter properties) if (options?.resetUnspecified) { finalFilters.sortBy = "newest"; finalFilters.searchSlug = null; finalFilters.searchName = null; finalFilters.searchDescription = null; finalFilters.searchAny = null; finalFilters.readingPermission = null; finalFilters.memberOf = false; finalFilters.parentSpaceId = null; } // Apply new filters Object.keys(newFilters).forEach((key) => { if (newFilters[key] !== undefined) { finalFilters[key] = newFilters[key]; } }); if (!finalFilters.sortBy) return; // sortBy is required dispatch((0, spaceListsSlice_1.setSpaceListLoading)({ listId, loading: true })); try { await spaceActions.fetchSpaces(listId, { page: 1, // User-controlled filters from Redux state + new filters sortBy: finalFilters.sortBy, searchSlug: finalFilters.searchSlug, searchName: finalFilters.searchName, searchDescription: finalFilters.searchDescription, searchAny: finalFilters.searchAny, readingPermission: finalFilters.readingPermission, memberOf: finalFilters.memberOf, parentSpaceId: finalFilters.parentSpaceId, // Configuration parameters from current config limit: currentConfig.limit, }); } catch (err) { console.error(`[SpaceList] Failed to fetch spaces for listId: ${listId}`, err); } }; // Execute immediately if requested, otherwise debounce // For initial loads (empty filters object), make it immediate by default const shouldBeImmediate = options?.fetchImmediately || Object.keys(newFilters).length === 0; if (shouldBeImmediate) { performFetch(); } else { // Clear existing debounce timer if (debounceTimer.current) { clearTimeout(debounceTimer.current); } // Debounce the actual fetch debounceTimer.current = setTimeout(() => { performFetch(); }, 800); // 800ms debounce delay } }, [dispatch, listId, spaceList, config, spaceActions.fetchSpaces]); // Load more function const loadMore = (0, react_1.useCallback)(async () => { if (!spaceList || loading || !hasMore) return; // Check if fetchSpaces has been called before (safeguard) if (!config) { console.error(`[SpaceList] loadMore called before fetchSpaces for listId: ${listId}. ` + `fetchSpaces must be called first to initialize configuration.`); return; } const nextPage = spaceList.page + 1; dispatch((0, spaceListsSlice_1.incrementPage)(listId)); // Directly fetch the next page try { await spaceActions.fetchSpaces(listId, { page: nextPage, // User-controlled filters from Redux state sortBy: spaceList.sortBy, searchSlug: spaceList.searchSlug, searchName: spaceList.searchName, searchDescription: spaceList.searchDescription, searchAny: spaceList.searchAny, readingPermission: spaceList.readingPermission, memberOf: spaceList.memberOf, parentSpaceId: spaceList.parentSpaceId, // Configuration parameters from state (single source of truth) limit: config.limit, }); } catch (err) { console.error(`[SpaceList] Failed to load more spaces for listId: ${listId}`, err); } }, [dispatch, listId, config, spaceList, loading, hasMore, spaceActions.fetchSpaces]); // Create space function const createSpace = (0, react_1.useCallback)(async ({ insertPosition, ...restOfProps }) => { try { const newSpace = await spaceActions.createSpace(listId, { ...restOfProps, insertPosition, }); return newSpace; } catch (err) { (0, handleError_1.handleError)(err, "Failed to create space"); } }, [spaceActions.createSpace, dispatch, listId]); // Delete space function const deleteSpace = (0, react_1.useCallback)(async ({ spaceId }) => { try { await spaceActions.deleteSpace(listId, { spaceId }); } catch (err) { (0, handleError_1.handleError)(err, "Failed to delete space"); } }, [spaceActions.deleteSpace, dispatch, listId]); return (0, react_1.useMemo)(() => ({ spaces, loading, hasMore, sortBy: filters?.sortBy || null, searchSlug: filters?.searchSlug || null, searchName: filters?.searchName || null, searchDescription: filters?.searchDescription || null, searchAny: filters?.searchAny || null, readingPermission: filters?.readingPermission || null, memberOf: filters?.memberOf || false, parentSpaceId: filters?.parentSpaceId || null, fetchSpaces: handleFetchSpaces, loadMore, createSpace, deleteSpace, }), [ spaces, loading, hasMore, filters, handleFetchSpaces, loadMore, createSpace, deleteSpace, ]); } exports.default = useSpaceList; //# sourceMappingURL=useSpaceList.js.map