refactor websocket init

This commit is contained in:
hjlarry 2025-08-07 17:31:12 +08:00
parent dd64af728f
commit be74b76079
5 changed files with 38 additions and 28 deletions

View File

@ -26,7 +26,6 @@ import Loading from '@/app/components/base/loading'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import type { App } from '@/types/app'
import useDocumentTitle from '@/hooks/use-document-title'
import { webSocketClient } from '@/app/components/workflow/collaboration/core/websocket-manager'
export type IAppDetailLayoutProps = {
children: React.ReactNode
@ -115,9 +114,6 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
setIsLoadingAppDetail(true)
fetchAppDetail({ url: '/apps', id: appId }).then((res) => {
setAppDetailRes(res)
// Only connect for workflow/advanced-chat apps and if not already connected
if ((res.mode === 'workflow' || res.mode === 'advanced-chat') && !webSocketClient.isConnected(appId))
webSocketClient.connect(appId)
}).catch((e: any) => {
if (e.status === 404)
router.replace('/apps')
@ -152,7 +148,6 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
useUnmount(() => {
setAppDetail()
webSocketClient.disconnect(appId)
})
if (!appDetail) {

View File

@ -107,7 +107,7 @@ const WorkflowMain = ({
const response = await fetchWorkflowDraft(`/apps/${appId}/workflows/draft`)
handleWorkflowDataUpdate(response)
}
catch (error) {
catch (error) {
console.error('workflow vars and features update failed:', error)
}
})

View File

@ -1,5 +1,4 @@
import {
useEffect,
useMemo,
} from 'react'
import useSWR from 'swr'
@ -25,26 +24,15 @@ import {
import { createWorkflowSlice } from './store/workflow/workflow-slice'
import WorkflowAppMain from './components/workflow-main'
import { collaborationManager } from '@/app/components/workflow/collaboration/core/collaboration-manager'
import { useStore } from '@/app/components/workflow/store'
const WorkflowAppWithAdditionalContext = () => {
const {
data,
isLoading,
} = useWorkflowInit()
const appId = useStore(s => s.appId)
const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig)
useEffect(() => {
if (appId && data)
collaborationManager.init(appId, null)
return () => {
collaborationManager.destroy()
}
}, [appId, data])
const nodesData = useMemo(() => {
if (data) {
const processedNodes = initialNodes(data.graph.nodes, data.graph.edges)

View File

@ -14,8 +14,13 @@ export class CollaborationManager {
private eventEmitter = new EventEmitter()
private currentAppId: string | null = null
private reactFlowStore: any = null
private cursors: Record<string, CursorPosition> = {}
init = (appId: string, reactFlowStore: any): void => {
if (!reactFlowStore) {
console.warn('CollaborationManager.init called without reactFlowStore, deferring to connect()')
return
}
this.connect(appId, reactFlowStore)
}
@ -64,6 +69,7 @@ export class CollaborationManager {
this.edgesMap = null
this.currentAppId = null
this.reactFlowStore = null
this.cursors = {}
this.eventEmitter.removeAllListeners()
}
@ -125,7 +131,7 @@ export class CollaborationManager {
if (!oldNode) {
this.nodesMap.set(newNode.id, newNode)
}
else {
else {
const oldPersistentData = this.getPersistentNodeData(oldNode)
const newPersistentData = this.getPersistentNodeData(newNode)
if (!isEqual(oldPersistentData, newPersistentData))
@ -185,24 +191,42 @@ export class CollaborationManager {
}
private setupSocketEventListeners(socket: any): void {
console.log('Setting up socket event listeners for collaboration')
socket.on('collaboration_update', (update: any) => {
if (update.type === 'mouseMove') {
this.eventEmitter.emit('cursors', {
[update.userId]: {
x: update.data.x,
y: update.data.y,
userId: update.userId,
timestamp: update.timestamp,
},
})
console.log('Processing mouseMove event:', update)
// Update cursor state for this user
this.cursors[update.userId] = {
x: update.data.x,
y: update.data.y,
userId: update.userId,
timestamp: update.timestamp,
}
// Emit the complete cursor state
console.log('Emitting complete cursor state:', this.cursors)
this.eventEmitter.emit('cursors', { ...this.cursors })
}
else if (update.type === 'varsAndFeaturesUpdate') {
else if (update.type === 'varsAndFeaturesUpdate') {
console.log('Processing varsAndFeaturesUpdate event:', update)
this.eventEmitter.emit('varsAndFeaturesUpdate', update)
}
})
socket.on('online_users', (data: { users: OnlineUser[] }) => {
const onlineUserIds = new Set(data.users.map(user => user.user_id))
// Remove cursors for offline users
Object.keys(this.cursors).forEach((userId) => {
if (!onlineUserIds.has(userId))
delete this.cursors[userId]
})
console.log('Updated online users and cleaned offline cursors:', data.users)
this.eventEmitter.emit('onlineUsers', data.users)
this.eventEmitter.emit('cursors', { ...this.cursors })
})
socket.on('connect', () => {

View File

@ -30,14 +30,17 @@ export function useCollaboration(appId: string, reactFlowStore?: any) {
initCollaboration()
const unsubscribeStateChange = collaborationManager.onStateChange((newState: any) => {
console.log('Collaboration state change:', newState)
setState((prev: any) => ({ ...prev, ...newState }))
})
const unsubscribeCursors = collaborationManager.onCursorUpdate((cursors: any) => {
console.log('Cursor update received:', cursors)
setState((prev: any) => ({ ...prev, cursors }))
})
const unsubscribeUsers = collaborationManager.onOnlineUsersUpdate((users: any) => {
console.log('Online users update:', users)
setState((prev: any) => ({ ...prev, onlineUsers: users }))
})