tfrere's picture
tfrere HF Staff
feat(frontend): editor refresh (embed studio, comment popover, shiki, top bar, hooks, styles)
76fc93a
import * as Y from "yjs";
export interface ReplyData {
id: string;
author: string;
authorColor: string;
text: string;
createdAt: number;
}
export interface CommentData {
id: string;
author: string;
authorColor: string;
text: string;
createdAt: number;
resolved: boolean;
resolvedBy?: string;
resolvedAt?: number;
replies: ReplyData[];
}
export function createCommentStore(ydoc: Y.Doc) {
const ymap = ydoc.getMap<CommentData>("comments");
return {
add(comment: Omit<CommentData, "replies">) {
ymap.set(comment.id, { ...comment, replies: [] });
},
addReply(commentId: string, reply: ReplyData) {
const comment = ymap.get(commentId);
if (!comment) return;
ymap.set(commentId, {
...comment,
replies: [...comment.replies, reply],
});
},
resolve(id: string, resolvedBy: string) {
const comment = ymap.get(id);
if (!comment) return;
ymap.set(id, {
...comment,
resolved: true,
resolvedBy,
resolvedAt: Date.now(),
});
},
unresolve(id: string) {
const comment = ymap.get(id);
if (!comment) return;
ymap.set(id, {
...comment,
resolved: false,
resolvedBy: undefined,
resolvedAt: undefined,
});
},
remove(id: string) {
ymap.delete(id);
},
get(id: string): CommentData | undefined {
return ymap.get(id);
},
getAll(): CommentData[] {
const comments: CommentData[] = [];
ymap.forEach((value) => comments.push(value));
return comments.sort((a, b) => a.createdAt - b.createdAt);
},
observe(callback: () => void) {
ymap.observe(callback);
return () => ymap.unobserve(callback);
},
};
}
export type CommentStore = ReturnType<typeof createCommentStore>;