@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
200 lines • 9.04 kB
JavaScript
;
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