mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-01-08 21:41:55 -05:00
207 lines
6.3 KiB
JavaScript
207 lines
6.3 KiB
JavaScript
const keyMirror = require('keymirror');
|
|
const mergeWith = require('lodash.mergewith');
|
|
const uniqBy = require('lodash.uniqby');
|
|
|
|
// Number of replies to fetch at a time.
|
|
// The way this code is currently structured, it expects
|
|
// this number to be the same for project comment reply threads
|
|
// as well as studio comment reply threads.
|
|
// These could be decoupled in the future.
|
|
const REPLY_FETCH_LIMIT = 25;
|
|
|
|
|
|
module.exports.Status = keyMirror({
|
|
FETCHED: null,
|
|
NOT_FETCHED: null,
|
|
FETCHING: null,
|
|
ERROR: null
|
|
});
|
|
|
|
module.exports.getInitialState = () => ({
|
|
status: {
|
|
comments: module.exports.Status.NOT_FETCHED
|
|
},
|
|
comments: [],
|
|
replies: {},
|
|
moreCommentsToLoad: false
|
|
});
|
|
|
|
module.exports.commentsReducer = (state, action) => {
|
|
if (typeof state === 'undefined') {
|
|
state = module.exports.getInitialState();
|
|
}
|
|
|
|
switch (action.type) {
|
|
case 'RESET_TO_INTIAL_STATE':
|
|
return module.exports.getInitialState();
|
|
case 'RESET_COMMENTS':
|
|
return Object.assign({}, state, {
|
|
comments: [],
|
|
replies: {}
|
|
});
|
|
case 'SET_COMMENT_FETCH_STATUS':
|
|
return Object.assign({}, state, {
|
|
status: Object.assign({}, state.status, {
|
|
[action.infoType]: action.status
|
|
})
|
|
});
|
|
case 'SET_COMMENTS':
|
|
return Object.assign({}, state, {
|
|
comments: uniqBy(state.comments.concat(action.items), 'id')
|
|
});
|
|
case 'UPDATE_COMMENT':
|
|
if (action.topLevelCommentId) {
|
|
return Object.assign({}, state, {
|
|
replies: Object.assign({}, state.replies, {
|
|
[action.topLevelCommentId]: state.replies[action.topLevelCommentId].map(comment => {
|
|
if (comment.id === action.commentId) {
|
|
return Object.assign({}, comment, action.comment);
|
|
}
|
|
return comment;
|
|
})
|
|
})
|
|
});
|
|
}
|
|
|
|
return Object.assign({}, state, {
|
|
comments: state.comments.map(comment => {
|
|
if (comment.id === action.commentId) {
|
|
return Object.assign({}, comment, action.comment);
|
|
}
|
|
return comment;
|
|
})
|
|
});
|
|
case 'ADD_NEW_COMMENT':
|
|
if (action.topLevelCommentId) {
|
|
return Object.assign({}, state, {
|
|
replies: Object.assign({}, state.replies, {
|
|
// Replies to comments go at the end of the thread
|
|
[action.topLevelCommentId]:
|
|
(state.replies[action.topLevelCommentId] || [])
|
|
.concat(action.comment)
|
|
}),
|
|
comments: state.comments.map(comment => {
|
|
if (comment.id === action.topLevelCommentId) {
|
|
return Object.assign({}, comment, {
|
|
reply_count: comment.reply_count + 1
|
|
});
|
|
}
|
|
return comment;
|
|
})
|
|
});
|
|
}
|
|
|
|
// Reply to the top level project, put the reply at the beginning
|
|
return Object.assign({}, state, {
|
|
comments: [action.comment, ...state.comments],
|
|
replies: Object.assign({}, state.replies, {[action.comment.id]: []})
|
|
});
|
|
case 'UPDATE_ALL_REPLIES':
|
|
return Object.assign({}, state, {
|
|
replies: Object.assign({}, state.replies, {
|
|
[action.commentId]: state.replies[action.commentId].map(reply =>
|
|
Object.assign({}, reply, action.comment)
|
|
)
|
|
})
|
|
});
|
|
case 'SET_REPLIES':
|
|
return Object.assign({}, state, {
|
|
// Append new replies to the state.replies structure
|
|
replies: mergeWith({}, state.replies, action.replies, (replies, newReplies) => (
|
|
uniqBy((replies || []).concat(newReplies || []), 'id')
|
|
)),
|
|
// Also set the `moreRepliesToLoad` property on the top-level comments
|
|
comments: state.comments.map(comment => {
|
|
if (action.replies[comment.id]) {
|
|
return Object.assign({}, comment, {
|
|
moreRepliesToLoad: action.replies[comment.id].length === REPLY_FETCH_LIMIT
|
|
});
|
|
}
|
|
return comment;
|
|
})
|
|
});
|
|
case 'SET_MORE_COMMENTS_TO_LOAD':
|
|
return Object.assign({}, state, {
|
|
moreCommentsToLoad: action.moreCommentsToLoad
|
|
});
|
|
default:
|
|
return state;
|
|
}
|
|
};
|
|
|
|
module.exports.setFetchStatus = (type, status) => ({
|
|
type: 'SET_COMMENT_FETCH_STATUS',
|
|
infoType: type,
|
|
status: status
|
|
});
|
|
|
|
module.exports.setComments = items => ({
|
|
type: 'SET_COMMENTS',
|
|
items: items
|
|
});
|
|
|
|
module.exports.setReplies = replies => ({
|
|
type: 'SET_REPLIES',
|
|
replies: replies
|
|
});
|
|
|
|
module.exports.setCommentDeleted = (commentId, topLevelCommentId) => ({
|
|
type: 'UPDATE_COMMENT',
|
|
commentId: commentId,
|
|
topLevelCommentId: topLevelCommentId,
|
|
comment: {
|
|
visibility: 'deleted'
|
|
}
|
|
});
|
|
|
|
module.exports.setRepliesDeleted = commentId => ({
|
|
type: 'UPDATE_ALL_REPLIES',
|
|
commentId: commentId,
|
|
comment: {
|
|
visibility: 'deleted'
|
|
}
|
|
});
|
|
|
|
module.exports.setCommentReported = (commentId, topLevelCommentId) => ({
|
|
type: 'UPDATE_COMMENT',
|
|
commentId: commentId,
|
|
topLevelCommentId: topLevelCommentId,
|
|
comment: {
|
|
visibility: 'reported'
|
|
}
|
|
});
|
|
|
|
module.exports.setCommentRestored = (commentId, topLevelCommentId) => ({
|
|
type: 'UPDATE_COMMENT',
|
|
commentId: commentId,
|
|
topLevelCommentId: topLevelCommentId,
|
|
comment: {
|
|
visibility: 'visible'
|
|
}
|
|
});
|
|
|
|
module.exports.setRepliesRestored = commentId => ({
|
|
type: 'UPDATE_ALL_REPLIES',
|
|
commentId: commentId,
|
|
comment: {
|
|
visibility: 'visible'
|
|
}
|
|
});
|
|
|
|
module.exports.addNewComment = (comment, topLevelCommentId) => ({
|
|
type: 'ADD_NEW_COMMENT',
|
|
comment: comment,
|
|
topLevelCommentId: topLevelCommentId
|
|
});
|
|
|
|
module.exports.setMoreCommentsToLoad = moreCommentsToLoad => ({
|
|
type: 'SET_MORE_COMMENTS_TO_LOAD',
|
|
moreCommentsToLoad: moreCommentsToLoad
|
|
});
|
|
|
|
module.exports.resetComments = () => ({
|
|
type: 'RESET_COMMENTS'
|
|
});
|
|
|
|
// Selectors
|
|
module.exports.selectCommentCount = state => state.comments.comments.length;
|