@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
290 lines • 13 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var _a;
import { createSlice, createSelector } from "@reduxjs/toolkit";
// Default state for a new entity list
var createDefaultEntityListState = function () { return ({
entities: [],
page: 1,
loading: true,
hasMore: true,
error: null,
lastFetched: null,
// Default configuration
sourceId: null,
limit: 10,
// Default filters (user-controlled only)
sortBy: "hot",
sortDir: null,
sortType: "auto",
timeFrame: null,
userId: null,
followedOnly: false,
keywordsFilters: null,
titleFilters: null,
contentFilters: null,
attachmentsFilters: null,
locationFilters: null,
metadataFilters: null,
}); };
// Initial state
var initialState = {
lists: {},
};
// Create the slice
export var entityListsSlice = createSlice({
name: "entityLists",
initialState: initialState,
reducers: {
// Initialize or get existing list
initializeList: function (state, action) {
var listId = action.payload.listId;
if (!state.lists[listId]) {
state.lists[listId] = createDefaultEntityListState();
}
},
// Update filters and sort (unified function)
updateFiltersAndSort: function (state, action) {
var _a = action.payload, listId = _a.listId, filters = _a.filters, options = _a.options;
// Ensure list exists
if (!state.lists[listId]) {
state.lists[listId] = createDefaultEntityListState();
}
var list = state.lists[listId];
// If resetUnspecified is true, reset to defaults first
if (options === null || options === void 0 ? void 0 : options.resetUnspecified) {
var defaultState = createDefaultEntityListState();
// Reset all filter properties to defaults
list.sortBy = defaultState.sortBy;
list.sortDir = defaultState.sortDir;
list.sortType = defaultState.sortType;
list.timeFrame = defaultState.timeFrame;
list.userId = defaultState.userId;
list.followedOnly = defaultState.followedOnly;
list.keywordsFilters = defaultState.keywordsFilters;
list.titleFilters = defaultState.titleFilters;
list.contentFilters = defaultState.contentFilters;
list.attachmentsFilters = defaultState.attachmentsFilters;
list.locationFilters = defaultState.locationFilters;
list.metadataFilters = defaultState.metadataFilters;
}
// Update specified filters
Object.keys(filters).forEach(function (key) {
if (filters[key] !== undefined) {
list[key] = filters[key];
}
});
// Update config if provided
if (action.payload.config) {
if (action.payload.config.sourceId !== undefined) {
list.sourceId = action.payload.config.sourceId;
}
if (action.payload.config.limit !== undefined) {
list.limit = action.payload.config.limit;
}
}
// Reset pagination when filters change
list.page = 1;
list.hasMore = true;
list.error = null;
},
// Set loading state for entity list
setEntityListLoading: function (state, action) {
var _a = action.payload, listId = _a.listId, loading = _a.loading;
if (state.lists[listId]) {
state.lists[listId].loading = loading;
}
},
// Set entities for entity list
setEntityListEntities: function (state, action) {
var _a = action.payload, listId = _a.listId, entities = _a.entities, _b = _a.append, append = _b === void 0 ? false : _b;
if (!state.lists[listId]) {
state.lists[listId] = createDefaultEntityListState();
}
var list = state.lists[listId];
if (append) {
// Filter out duplicates when appending
var existingIds_1 = new Set(list.entities.map(function (e) { return e.id; }));
var newEntities = entities.filter(function (e) { return !existingIds_1.has(e.id); });
list.entities = __spreadArray(__spreadArray([], list.entities, true), newEntities, true);
}
else {
list.entities = entities;
}
list.loading = false;
list.lastFetched = Date.now();
// Note: hasMore is set explicitly by the caller based on limit from hook props
},
// Increment page for load more
incrementPage: function (state, action) {
var listId = action.payload;
if (state.lists[listId]) {
state.lists[listId].page += 1;
}
},
// Set hasMore for entity list
setEntityListHasMore: function (state, action) {
var _a = action.payload, listId = _a.listId, hasMore = _a.hasMore;
if (state.lists[listId]) {
state.lists[listId].hasMore = hasMore;
}
},
// Set error for entity list
setEntityListError: function (state, action) {
var _a = action.payload, listId = _a.listId, error = _a.error;
if (state.lists[listId]) {
state.lists[listId].error = error;
state.lists[listId].loading = false;
}
},
// Add entity
addEntity: function (state, action) {
var _a = action.payload, listId = _a.listId, entity = _a.entity, _b = _a.insertPosition, insertPosition = _b === void 0 ? "first" : _b;
if (!state.lists[listId])
return;
var list = state.lists[listId];
if (insertPosition === "last") {
list.entities.push(entity);
}
else {
list.entities.unshift(entity);
}
},
// Remove entity
removeEntity: function (state, action) {
var _a = action.payload, listId = _a.listId, entityId = _a.entityId;
if (!state.lists[listId])
return;
var list = state.lists[listId];
list.entities = list.entities.filter(function (e) { return e.id !== entityId; });
},
// Update keywords filters (special case due to complexity)
updateKeywordsFilters: function (state, action) {
var _a, _b, _c, _d;
var _e = action.payload, listId = _e.listId, type = _e.type, key = _e.key, value = _e.value;
if (!state.lists[listId]) {
state.lists[listId] = createDefaultEntityListState();
}
var list = state.lists[listId];
var items = Array.isArray(value) ? value : value ? [value] : [];
var newFilters = list.keywordsFilters || {};
switch (type) {
case "add": {
if (key === "both")
break; // Invalid to add to both
newFilters = __assign(__assign({}, newFilters), (_a = {}, _a[key] = Array.from(new Set(__spreadArray(__spreadArray([], (newFilters[key] || []), true), items, true))), _a));
break;
}
case "remove": {
if (key === "both") {
newFilters = {
includes: (newFilters.includes || []).filter(function (item) { return !items.includes(item); }),
doesNotInclude: (newFilters.doesNotInclude || []).filter(function (item) { return !items.includes(item); }),
};
}
else {
newFilters = __assign(__assign({}, newFilters), (_b = {}, _b[key] = (newFilters[key] || []).filter(function (item) { return !items.includes(item); }), _b));
}
break;
}
case "reset": {
if (key === "both") {
newFilters = {};
}
else {
newFilters = __assign(__assign({}, newFilters), (_c = {}, _c[key] = undefined, _c));
}
break;
}
case "replace": {
if (key === "both")
break; // Replace does not apply to both
newFilters = __assign(__assign({}, newFilters), (_d = {}, _d[key] = items, _d));
break;
}
}
list.keywordsFilters =
Object.keys(newFilters).length > 0 ? newFilters : null;
// Reset pagination when filters change
list.page = 1;
list.hasMore = true;
list.error = null;
},
// Clean up unused lists (for memory management)
cleanupList: function (state, action) {
var listId = action.payload;
delete state.lists[listId];
},
// Clean up old lists (older than TTL)
cleanupOldLists: function (state, action) {
var ttl = action.payload; // TTL in milliseconds
var now = Date.now();
Object.keys(state.lists).forEach(function (listId) {
var list = state.lists[listId];
if (list.lastFetched && now - list.lastFetched > ttl) {
delete state.lists[listId];
}
});
},
},
});
// Export actions
export var initializeList = (_a = entityListsSlice.actions, _a.initializeList), updateFiltersAndSort = _a.updateFiltersAndSort, setEntityListLoading = _a.setEntityListLoading, setEntityListEntities = _a.setEntityListEntities, incrementPage = _a.incrementPage, setEntityListHasMore = _a.setEntityListHasMore, setEntityListError = _a.setEntityListError, addEntity = _a.addEntity, removeEntity = _a.removeEntity, updateKeywordsFilters = _a.updateKeywordsFilters, cleanupList = _a.cleanupList, cleanupOldLists = _a.cleanupOldLists;
// Base selectors
var selectEntityListsState = function (state) {
return state.entityLists;
};
var selectListId = function (_, listId) { return listId; };
// Memoized selectors using createSelector
export var selectEntityList = createSelector([selectEntityListsState, selectListId], function (entityListsState, listId) {
return entityListsState.lists[listId];
});
export var selectEntityListEntities = createSelector([selectEntityList], function (entityList) { return (entityList === null || entityList === void 0 ? void 0 : entityList.entities) || []; });
export var selectEntityListLoading = createSelector([selectEntityList], function (entityList) { return (entityList === null || entityList === void 0 ? void 0 : entityList.loading) || false; });
export var selectEntityListHasMore = createSelector([selectEntityList], function (entityList) { return (entityList === null || entityList === void 0 ? void 0 : entityList.hasMore) || false; });
export var selectEntityListFilters = createSelector([selectEntityList], function (entityList) {
if (!entityList)
return null;
return {
sortBy: entityList.sortBy,
sortDir: entityList.sortDir,
sortType: entityList.sortType,
timeFrame: entityList.timeFrame,
userId: entityList.userId,
followedOnly: entityList.followedOnly,
keywordsFilters: entityList.keywordsFilters,
titleFilters: entityList.titleFilters,
contentFilters: entityList.contentFilters,
attachmentsFilters: entityList.attachmentsFilters,
locationFilters: entityList.locationFilters,
metadataFilters: entityList.metadataFilters,
};
});
export var selectEntityListConfig = createSelector([selectEntityList], function (entityList) {
if (!entityList)
return null;
return {
sourceId: entityList.sourceId,
limit: entityList.limit,
};
});
export default entityListsSlice.reducer;
//# sourceMappingURL=entityListsSlice.js.map