124 lines
2.5 KiB
JavaScript
124 lines
2.5 KiB
JavaScript
let _instance;
|
|
|
|
class Store {
|
|
constructor() {
|
|
if (_instance) return _instance;
|
|
|
|
this.data = {};
|
|
|
|
this.listeners = {};
|
|
|
|
_instance = this;
|
|
|
|
return _instance;
|
|
}
|
|
|
|
onUpdate(key, cb) {
|
|
if (!this.listeners[key]) this.listeners[key] = [];
|
|
|
|
this.listeners[key].push(cb);
|
|
}
|
|
|
|
set(key, obj) {
|
|
this.data[key] = obj;
|
|
|
|
if (this.listeners[key]) this.listeners[key].forEach(cb => cb(this.data[key]));
|
|
}
|
|
|
|
get(key) {
|
|
return this.data[key];
|
|
}
|
|
|
|
addComment(comment) {
|
|
const newComment = { comment };
|
|
|
|
if (comment.pid) {
|
|
this.pasteReply(newComment);
|
|
} else {
|
|
this.pasteComment(newComment);
|
|
}
|
|
}
|
|
|
|
pasteReply(newReply) {
|
|
let again = true;
|
|
|
|
const concatReply = (root, reply) => {
|
|
root.replies = root.replies || [];
|
|
root.replies = [reply].concat(root.replies);
|
|
|
|
again = false;
|
|
|
|
return root;
|
|
};
|
|
|
|
const paste = (root, commentObj) => {
|
|
if (!again) return root;
|
|
|
|
if (root.comment.id === commentObj.comment.pid) {
|
|
return concatReply(root, commentObj);
|
|
}
|
|
|
|
if (root.replies) {
|
|
root.replies = root.replies.map(reply => {
|
|
if (reply.comment.id === commentObj.comment.pid) {
|
|
return concatReply(reply, commentObj);
|
|
}
|
|
return paste(reply, commentObj);
|
|
});
|
|
}
|
|
|
|
return root;
|
|
};
|
|
|
|
this.set('comments', this.data.comments.map(thread => paste(thread, newReply)));
|
|
}
|
|
|
|
pasteComment(newComment) {
|
|
this.set('comments', [newComment].concat(this.data.comments));
|
|
}
|
|
|
|
replaceComment(newComment) {
|
|
let again = true;
|
|
|
|
const replace = (thread, comment) => {
|
|
if (!again) return thread;
|
|
|
|
if (thread.comment.id === comment.id) {
|
|
thread.comment = comment;
|
|
again = false;
|
|
return thread;
|
|
}
|
|
|
|
if (thread.replies) {
|
|
thread.replies = thread.replies.map(reply => replace(reply, comment));
|
|
}
|
|
|
|
return thread;
|
|
};
|
|
|
|
this.set('comments', this.data.comments.map(thread => replace(thread, newComment)));
|
|
}
|
|
|
|
getPinnedComments() {
|
|
const comments = this.data.comments || [];
|
|
|
|
return comments.reduce((acc, thread) => acc.concat(findPinnedComments(thread)), []);
|
|
}
|
|
}
|
|
|
|
function findPinnedComments(thread) {
|
|
let result = [];
|
|
|
|
if (thread.comment.pin) {
|
|
result = result.concat(thread.comment);
|
|
}
|
|
|
|
if (thread.replies) {
|
|
result = result.concat(thread.replies.reduce((acc, thread) => acc.concat(findPinnedComments(thread)), []));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export default new Store();
|