| 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>; | |