From 10e36d23555661cc16f0c9e83231f78be2933c18 Mon Sep 17 00:00:00 2001 From: hjlarry Date: Fri, 19 Sep 2025 10:43:28 +0800 Subject: [PATCH] add avatar on canvas node --- .../components/workflow/nodes/_base/node.tsx | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/web/app/components/workflow/nodes/_base/node.tsx b/web/app/components/workflow/nodes/_base/node.tsx index 9fd9c3ce72..f09126fd37 100644 --- a/web/app/components/workflow/nodes/_base/node.tsx +++ b/web/app/components/workflow/nodes/_base/node.tsx @@ -47,6 +47,10 @@ import BlockIcon from '@/app/components/workflow/block-icon' import Tooltip from '@/app/components/base/tooltip' import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud' import { ToolTypeEnum } from '../../block-selector/types' +import { UserAvatarList } from '@/app/components/base/user-avatar-list' +import { useAppContext } from '@/context/app-context' +import { useStore } from '@/app/components/workflow/store' +import { useCollaboration } from '@/app/components/workflow/collaboration/hooks/use-collaboration' type BaseNodeProps = { children: ReactElement @@ -65,6 +69,35 @@ const BaseNode: FC = ({ const { handleNodeIterationChildSizeChange } = useNodeIterationInteractions() const { handleNodeLoopChildSizeChange } = useNodeLoopInteractions() const toolIcon = useToolIcon(data) + const { userProfile } = useAppContext() + const appId = useStore(s => s.appId) + const { nodePanelPresence } = useCollaboration(appId as string) + + const currentUserPresence = useMemo(() => { + const userId = userProfile?.id || '' + const username = userProfile?.name || userProfile?.email || 'User' + const avatar = userProfile?.avatar_url || userProfile?.avatar || null + + return { + userId, + username, + avatar, + } + }, [userProfile?.avatar, userProfile?.avatar_url, userProfile?.email, userProfile?.id, userProfile?.name]) + + const viewingUsers = useMemo(() => { + const presence = nodePanelPresence?.[id] + if (!presence) + return [] + + return Object.values(presence) + .filter(viewer => viewer.userId && viewer.userId !== currentUserPresence.userId) + .map(viewer => ({ + id: viewer.clientId, + name: viewer.username, + avatar_url: viewer.avatar || null, + })) + }, [currentUserPresence.userId, id, nodePanelPresence]) useEffect(() => { if (nodeRef.current && data.selected && data.isInIteration) { @@ -237,7 +270,7 @@ const BaseNode: FC = ({ />
{data.title} @@ -258,6 +291,15 @@ const BaseNode: FC = ({ ) } + {viewingUsers.length > 0 && ( +
+ +
+ )}
{ data._iterationLength && data._iterationIndex && data._runningStatus === NodeRunningStatus.Running && (