comment sync

This commit is contained in:
hjlarry 2025-09-18 13:27:27 +08:00
parent 6432d98469
commit 687662cf1f
3 changed files with 72 additions and 14 deletions

View File

@ -276,6 +276,24 @@ export class CollaborationManager {
return this.eventEmitter.on('leaderChange', callback)
}
onCommentsUpdate(callback: (update: { appId: string; timestamp: number }) => void): () => void {
return this.eventEmitter.on('commentsUpdate', callback)
}
emitCommentsUpdate(appId: string): void {
if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId)) return
const socket = webSocketClient.getSocket(this.currentAppId)
if (socket) {
console.log('Emitting Comments update event')
socket.emit('collaboration_event', {
type: 'commentsUpdate',
data: { appId, timestamp: Date.now() },
timestamp: Date.now(),
})
}
}
onUndoRedoStateChange(callback: (state: { canUndo: boolean; canRedo: boolean }) => void): () => void {
return this.eventEmitter.on('undoRedoStateChange', callback)
}
@ -613,6 +631,10 @@ export class CollaborationManager {
console.log('Processing workflowUpdate event:', update)
this.eventEmitter.emit('workflowUpdate', update.data)
}
else if (update.type === 'commentsUpdate') {
console.log('Processing commentsUpdate event:', update)
this.eventEmitter.emit('commentsUpdate', update.data)
}
else if (update.type === 'syncRequest') {
console.log('Received sync request from another user')
// Only process if we are the leader

View File

@ -5,6 +5,7 @@ import { useStore } from '../store'
import { ControlMode } from '../types'
import type { WorkflowCommentDetail, WorkflowCommentList } from '@/service/workflow-comment'
import { createWorkflowComment, createWorkflowCommentReply, deleteWorkflowComment, deleteWorkflowCommentReply, fetchWorkflowComment, fetchWorkflowComments, resolveWorkflowComment, updateWorkflowCommentReply } from '@/service/workflow-comment'
import { collaborationManager } from '@/app/components/workflow/collaboration'
export const useWorkflowComment = () => {
const params = useParams()
@ -37,6 +38,20 @@ export const useWorkflowComment = () => {
commentDetailCacheRef.current = commentDetailCache
}, [commentDetailCache])
const refreshActiveComment = useCallback(async (commentId: string) => {
if (!appId) return
const detailResponse = await fetchWorkflowComment(appId, commentId)
const detail = (detailResponse as any)?.data ?? detailResponse
commentDetailCacheRef.current = {
...commentDetailCacheRef.current,
[commentId]: detail,
}
setCommentDetailCache(commentDetailCacheRef.current)
setActiveComment(detail)
}, [appId, setActiveComment, setCommentDetailCache])
const loadComments = useCallback(async () => {
if (!appId) return
@ -53,6 +68,19 @@ export const useWorkflowComment = () => {
}
}, [appId, setComments, setCommentsLoading])
// Setup collaboration
useEffect(() => {
if (!appId) return
const unsubscribe = collaborationManager.onCommentsUpdate(() => {
loadComments()
if (activeCommentIdRef.current)
refreshActiveComment(activeCommentIdRef.current)
})
return unsubscribe
}, [appId, loadComments, refreshActiveComment])
useEffect(() => {
loadComments()
}, [loadComments])
@ -80,6 +108,9 @@ export const useWorkflowComment = () => {
})
console.log('Comment created successfully:', newComment)
collaborationManager.emitCommentsUpdate(appId)
await loadComments()
setPendingComment(null)
setControlMode(ControlMode.Pointer)
@ -133,26 +164,15 @@ export const useWorkflowComment = () => {
}
}, [appId, reactflow, setActiveComment, setActiveCommentId, setActiveCommentLoading, setCommentDetailCache, setControlMode, setPendingComment])
const refreshActiveComment = useCallback(async (commentId: string) => {
if (!appId) return
const detailResponse = await fetchWorkflowComment(appId, commentId)
const detail = (detailResponse as any)?.data ?? detailResponse
commentDetailCacheRef.current = {
...commentDetailCacheRef.current,
[commentId]: detail,
}
setCommentDetailCache(commentDetailCacheRef.current)
setActiveComment(detail)
}, [appId, setActiveComment, setCommentDetailCache])
const handleCommentResolve = useCallback(async (commentId: string) => {
if (!appId) return
setActiveCommentLoading(true)
try {
await resolveWorkflowComment(appId, commentId)
collaborationManager.emitCommentsUpdate(appId)
await refreshActiveComment(commentId)
await loadComments()
}
@ -170,6 +190,9 @@ export const useWorkflowComment = () => {
setActiveCommentLoading(true)
try {
await deleteWorkflowComment(appId, commentId)
collaborationManager.emitCommentsUpdate(appId)
const updatedCache = { ...commentDetailCacheRef.current }
delete updatedCache[commentId]
commentDetailCacheRef.current = updatedCache
@ -210,6 +233,9 @@ export const useWorkflowComment = () => {
setActiveCommentLoading(true)
try {
await createWorkflowCommentReply(appId, commentId, { content: trimmed, mentioned_user_ids: mentionedUserIds })
collaborationManager.emitCommentsUpdate(appId)
await refreshActiveComment(commentId)
await loadComments()
}
@ -229,6 +255,9 @@ export const useWorkflowComment = () => {
setActiveCommentLoading(true)
try {
await updateWorkflowCommentReply(appId, commentId, replyId, { content: trimmed, mentioned_user_ids: mentionedUserIds })
collaborationManager.emitCommentsUpdate(appId)
await refreshActiveComment(commentId)
await loadComments()
}
@ -246,6 +275,9 @@ export const useWorkflowComment = () => {
setActiveCommentLoading(true)
try {
await deleteWorkflowCommentReply(appId, commentId, replyId)
collaborationManager.emitCommentsUpdate(appId)
await refreshActiveComment(commentId)
await loadComments()
}

View File

@ -10,6 +10,7 @@ import { resolveWorkflowComment } from '@/service/workflow-comment'
import { useParams } from 'next/navigation'
import { useFormatTimeFromNow } from '@/app/components/workflow/hooks'
import { useAppContext } from '@/context/app-context'
import { collaborationManager } from '@/app/components/workflow/collaboration'
const CommentsPanel = () => {
const activeCommentId = useStore(s => s.activeCommentId)
@ -43,6 +44,9 @@ const CommentsPanel = () => {
if (!appId) return
try {
await resolveWorkflowComment(appId, comment.id)
collaborationManager.emitCommentsUpdate(appId)
await loadComments()
setActiveCommentId(comment.id)
}